|
| 1 | +# Mapping GitOps Repo Git Commit \<-\> Snapshot |
| 2 | + |
| 3 | +### Written by |
| 4 | +- Jonathan West (@jgwest) |
| 5 | +- Originally written in May 27, 2022 |
| 6 | + |
| 7 | + |
| 8 | +I've been investigating the implementation details of the ApplicationPromotionRun CR, which is responsible for updating the ApplicationEnvironmentSnapshotBinding. |
| 9 | + |
| 10 | +I'm looking for a way to determine which Git commits correspond to which Snapshots (or vice versa): |
| 11 | +e.g. snapshot name+environment \-\> git commits that contain that snapshot id for a particular environment, or git commit \-\> list of snapshot+env combinations that that git commit contains. |
| 12 | + |
| 13 | +**TL;DR**: My hope is that after HAS generates the GitOps repo, HAS can add the generated commit id to a list in one of the Environment APIs (see examples below). That list would also include the environment/snapshots in that commit. This list would then be used by the ApplicationPromotionRun controller (part of the GitOps Service) |
| 14 | + |
| 15 | +## The problem |
| 16 | + |
| 17 | +The following YAML would tell the GitOps Service to do a manual promotion of 'snapshotA' to 'app1' for the 'staging' environment. |
| 18 | + |
| 19 | +```yaml |
| 20 | +kind: ApplicationPromotionRun |
| 21 | +spec: |
| 22 | + snapshot: snapshotA |
| 23 | + application: app1 |
| 24 | + manualPromotion: |
| 25 | + targetEnvironment: staging |
| 26 | +``` |
| 27 | +
|
| 28 | +Once the above is created, the Promotion controller of the GitOps service will then do the following: |
| 29 | +
|
| 30 | +1. Find the ApplicationSnapshotEnvironmentBinding that corresponds to Application 'app1' on Environment 'staging' |
| 31 | +2. Set the 'snapshot' field of that binding to 'snapshotA' |
| 32 | +3. HAS: HAS will see the updated snapshot field of the binding and regenerate the GitOps repository |
| 33 | +4. GitOps Service will deploy the updated changes from the GitOps repository. |
| 34 | +5. Once deployed, GitOps Service will update the \`status\` \`GitOpsDeployment\` field, indicating which commit was deployed by Argo CD: |
| 35 | +
|
| 36 | +```yaml |
| 37 | +kind: GitOpsDeployment |
| 38 | +spec: |
| 39 | + # (...) |
| 40 | +status: |
| 41 | + healthy: |
| 42 | + status: Healthy/Unhealthy |
| 43 | + sync: |
| 44 | + status: Synced/OutOfSync |
| 45 | + revision: abc # (the particular Git commit that was deployed) |
| 46 | +``` |
| 47 | +
|
| 48 | +**Now, here's the open problem:** |
| 49 | +
|
| 50 | +The ApplicationPromotionRun controller needs to know if a particular Git revision (commit) contains the updated Snapshot and Environment. |
| 51 | +
|
| 52 | +Now: |
| 53 | +
|
| 54 | +* The ApplicationPromotionRun controller needs to be able to look at the GitOpsDeployment 'revision' field and know if it contains 'snapshotA' for the 'staging' environment. |
| 55 | +
|
| 56 | +The promotion controller wants to make sure that the Application still works when deployed with the new snapshot, and so it needs to know if the GitOps repository resources that have been deployed actually contains the new snapshot. |
| 57 | +
|
| 58 | +## Possible Solutions |
| 59 | +
|
| 60 | +Fortunately, the HAS component has all the information we need: |
| 61 | +
|
| 62 | +* What snapshot (name) was used to generate what Git commit (revision) |
| 63 | +
|
| 64 | +So the question is, where to put that information so that it can be consumed by the GitOpsService (and specifically the ApplicationPromotionRun controller). |
| 65 | +
|
| 66 | +Here are some ideas from brainstorming. |
| 67 | +
|
| 68 | +### Option A: Embed the information in the status field of the Snapshot |
| 69 | +
|
| 70 | +This option is my preference. |
| 71 | +
|
| 72 | +After HAS generates and pushed a Git commit, it would update the \`.status.gitopsRepository\` field of the ApplicationSnapshot, by adding a new entry to the gitRevisions list: |
| 73 | +
|
| 74 | +```yaml |
| 75 | +kind: ApplicationSnapshot |
| 76 | +metadata: |
| 77 | + name: snapshotA |
| 78 | +spec: |
| 79 | + application: app1 |
| 80 | + # (snapshot details) |
| 81 | +status: |
| 82 | + gitOpsRepository: |
| 83 | + - environment: staging |
| 84 | + gitRevisions: |
| 85 | + - abc # in revision 'abc', snapshotA is targeted to the staging environment |
| 86 | + - def |
| 87 | + - environment: dev |
| 88 | + gitRevisions: |
| 89 | + - abc # a single commit can/will often reference multiple environments (if multiple environments were deploying the same snapshot) |
| 90 | + - ghi |
| 91 | + - jkl |
| 92 | +``` |
| 93 | +
|
| 94 | +Note: |
| 95 | +
|
| 96 | +* The gitRevisions field would be a historical list of all the last N git commits that contain the snapshot deployed to the particular environment (for some N) |
| 97 | + * It would NOT be only the last gitRevision. |
| 98 | +* For example, if the snapshot had been used to generate 100 git commits for a particular environment, so far, the gitRevisions field would contain 100 entries. |
| 99 | +
|
| 100 | +### Option B: Embed the information into the status field of the Binding |
| 101 | +
|
| 102 | +This is an alternative option. The snapshot information is stored in the Binding, rather than in the Snapshot. |
| 103 | +
|
| 104 | +Whenever a Git commit is pushed by HAS, HAS would also update the Binding's '.status.snapshots' field. |
| 105 | +
|
| 106 | +```yaml |
| 107 | +kind: ApplicationSnapshotEnvironmentBinding |
| 108 | +spec: |
| 109 | + application: app1 |
| 110 | + snapshot: snapshotA |
| 111 | + environment: staging |
| 112 | + # (...) |
| 113 | +status: |
| 114 | + |
| 115 | + # A historical list of all the snapshots that have been deployed to this binding and environment (for some N number of git revisions) |
| 116 | + snapshots: |
| 117 | + - snapshot: snapshotA |
| 118 | + gitRevisions: |
| 119 | + - revisions: |
| 120 | + - abc |
| 121 | + - def |
| 122 | + - snapshot: snapshotB |
| 123 | + gitRevisions: |
| 124 | + - revisions: |
| 125 | + - ghi |
| 126 | + - jkl |
| 127 | +``` |
| 128 | +
|
| 129 | + |
| 130 | +One of this disadvantages to this approach is that the '.status.snapshots' field might get very large (with a large number of snapshots/environments/revisions), and K8s resources have a maximum size of 1024KB (\<512KB if using apply). |
| 131 | +
|
| 132 | +### Option C: Another idea? |
| 133 | +
|
| 134 | +These are the two obvious places to put this information. Any other suggestions? (Application? Component? Environment?) Or other behaviour? |
| 135 | +
|
| 136 | +The general problem to solve is: how to tell if a particular commit includes a particular snapshot, for a particular environment. |
| 137 | +
|
0 commit comments