Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Determine ownership by antecedent annotation
Browse files Browse the repository at this point in the history
Due to Helm creating its own descriptions when the user does not supply
one, the previous approach got shot as we would be unable to determine
ownership after manual helm actions.

The new approach is to check if the resources created by the release
are patched with the correct antecedent annotation, which we create
ourselves and have full control over (and survives rollbacks).

To be able to migrate existing releases to a HelmRelease, empty
(missing) annotations are still handled as true / owned by.
  • Loading branch information
hiddeco committed Jun 4, 2019
1 parent 5adbf2a commit 5ee12bd
Showing 1 changed file with 33 additions and 8 deletions.
41 changes: 33 additions & 8 deletions integrations/helm/release/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,20 +270,43 @@ func (r *Release) Delete(name string) error {
}

// OwnedByHelmRelease validates the release is managed by the given
// HelmRelease, by looking for the resource ID in the release
// description. This validation is necessary because we can not
// HelmRelease, by looking for the resource ID in the antecedent
// annotation. This validation is necessary because we can not
// validate the uniqueness of a release name on the creation of a
// HelmRelease, which would result in the operator attempting to
// upgrade a release indefinitely when multiple HelmReleases with the
// same release name exist.
//
// For backwards compatibility, and to be able to migrate existing
// releases to a HelmRelease, we define empty descriptions as a
// positive.
// To be able to migrate existing releases to a HelmRelease, empty
// (missing) annotations are handled as true / owned by.
func (r *Release) OwnedByHelmRelease(release *hapi_release.Release, fhr flux_v1beta1.HelmRelease) bool {
description := release.Info.Description
objs := releaseManifestToUnstructured(release.Manifest, log.NewNopLogger())

return description == "" || description == fhrResourceID(fhr).String()
escapedAnnotation := strings.ReplaceAll(fluxk8s.AntecedentAnnotation, ".", `\.`)
args := []string{"-o", "jsonpath={.metadata.annotations."+escapedAnnotation+"}", "get"}

for ns, res := range namespacedResourceMap(objs, release.Namespace) {
for _, r := range res {
a := append(args, "--namespace", ns, r)

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

cmd := exec.CommandContext(ctx, "kubectl", a...)
out, err := cmd.Output()
if err != nil {
continue
}

v := strings.TrimSpace(string(out))
if v == "" {
return true
}
return v == fhr.ResourceID().String()
}
}

return false
}

// annotateResources annotates each of the resources created (or updated)
Expand All @@ -296,7 +319,9 @@ func (r *Release) annotateResources(release *hapi_release.Release, fhr flux_v1be
args = append(args, res...)
args = append(args, fluxk8s.AntecedentAnnotation+"="+fhrResourceID(fhr).String())

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// The timeout is set to a high value as it may take some time
// to annotate large umbrella charts.
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()

cmd := exec.CommandContext(ctx, "kubectl", args...)
Expand Down

0 comments on commit 5ee12bd

Please sign in to comment.