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

Commit

Permalink
Annotate manifests outside of release NS
Browse files Browse the repository at this point in the history
  • Loading branch information
hiddeco committed Feb 28, 2019
1 parent 2901b78 commit 36f888c
Showing 1 changed file with 73 additions and 18 deletions.
91 changes: 73 additions & 18 deletions integrations/helm/release/release.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package release

import (
"bytes"
"context"
"fmt"
"os"
Expand All @@ -11,6 +10,7 @@ import (
"github.com/ghodss/yaml"
"github.com/go-kit/kit/log"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/kubernetes"
"k8s.io/helm/pkg/chartutil"
k8shelm "k8s.io/helm/pkg/helm"
Expand All @@ -19,6 +19,7 @@ import (
"github.com/weaveworks/flux"
fluxk8s "github.com/weaveworks/flux/cluster/kubernetes"
flux_v1beta1 "github.com/weaveworks/flux/integrations/apis/flux.weave.works/v1beta1"
helmutil "k8s.io/helm/pkg/releaseutil"
)

type Action string
Expand Down Expand Up @@ -197,7 +198,7 @@ func (r *Release) Install(chartPath, releaseName string, fhr flux_v1beta1.HelmRe
return nil, err
}
if !opts.DryRun {
err = r.annotateResources(res.Release, fhr)
r.annotateResources(res.Release, fhr)
}
return res.Release, err
case UpgradeAction:
Expand All @@ -215,7 +216,7 @@ func (r *Release) Install(chartPath, releaseName string, fhr flux_v1beta1.HelmRe
return nil, err
}
if !opts.DryRun {
err = r.annotateResources(res.Release, fhr)
r.annotateResources(res.Release, fhr)
}
return res.Release, err
default:
Expand Down Expand Up @@ -246,22 +247,23 @@ func (r *Release) Delete(name string) error {

// annotateResources annotates each of the resources created (or updated)
// by the release so that we can spot them.
func (r *Release) annotateResources(release *hapi_release.Release, fhr flux_v1beta1.HelmRelease) error {
args := []string{"annotate", "--overwrite"}
args = append(args, "--namespace", release.Namespace)
args = append(args, "-f", "-")
args = append(args, fluxk8s.AntecedentAnnotation+"="+fhrResourceID(fhr).String())

ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "kubectl", args...)
cmd.Stdin = bytes.NewBufferString(release.Manifest)

output, err := cmd.CombinedOutput()
if err != nil {
r.logger.Log("output", string(output), "err", err)
func (r *Release) annotateResources(release *hapi_release.Release, fhr flux_v1beta1.HelmRelease) {
objs := releaseManifestToUnstructured(release.Manifest, r.logger)
for namespace, res := range namespacedResourceMap(objs, release.Namespace) {
args := []string{"annotate", "--overwrite"}
args = append(args, "--namespace", namespace)
args = append(args, res...)
args = append(args, fluxk8s.AntecedentAnnotation+"="+fhrResourceID(fhr).String())

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

cmd := exec.CommandContext(ctx, "kubectl", args...)
output, err := cmd.CombinedOutput()
if err != nil {
r.logger.Log("output", string(output), "err", err)
}
}
return err
}

// fhrResourceID constructs a flux.ResourceID for a HelmRelease resource.
Expand Down Expand Up @@ -296,3 +298,56 @@ func mergeValues(dest, src chartutil.Values) chartutil.Values {
}
return dest
}

// releaseManifestToUnstructured turns a string containing YAML
// manifests into an array of Unstructured objects.
func releaseManifestToUnstructured(manifest string, logger log.Logger) []unstructured.Unstructured {
manifests := helmutil.SplitManifests(manifest)
var objs []unstructured.Unstructured
for _, manifest := range manifests {
bytes, err := yaml.YAMLToJSON([]byte(manifest))
if err != nil {
logger.Log("err", err)
continue
}

var u unstructured.Unstructured
if err := u.UnmarshalJSON(bytes); err != nil {
logger.Log("err", err)
continue
}

// Helm charts may include list kinds, we are only interested in
// the items on those lists.
if u.IsList() {
l, err := u.ToList()
if err != nil {
logger.Log("err", err)
continue
}
objs = append(objs, l.Items...)
continue
}

objs = append(objs, u)
}
return objs
}

// namespacedResourceMap iterates over the given objects and maps the
// resource identifier against the namespace from the object, if no
// namespace is present (either because the object kind has no namespace
// or it belongs to the release namespace) it gets mapped against the
// given release namespace.
func namespacedResourceMap(objs []unstructured.Unstructured, releaseNamespace string) map[string][]string {
resources := make(map[string][]string)
for _, obj := range objs {
namespace := obj.GetNamespace()
if namespace == "" {
namespace = releaseNamespace
}
resource := obj.GetKind() + "/" + obj.GetName()
resources[namespace] = append(resources[namespace], resource)
}
return resources
}

0 comments on commit 36f888c

Please sign in to comment.