Merge pull request #2008 from fluxcd/expand-hr-in-tree-ks

Expand Helm releases in flux tree cmd
pull/1932/head
Stefan Prodan 3 years ago committed by GitHub
commit 1d1d4bbf4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -191,7 +191,14 @@ jobs:
/tmp/flux create kustomization flux-system \
--source=flux-system \
--path=./clusters/staging
kubectl -n flux-system wait kustomization/infrastructure --for=condition=ready --timeout=5m
kubectl -n flux-system wait kustomization/apps --for=condition=ready --timeout=5m
kubectl -n nginx wait helmrelease/nginx --for=condition=ready --timeout=5m
kubectl -n redis wait helmrelease/redis --for=condition=ready --timeout=5m
kubectl -n podinfo wait helmrelease/podinfo --for=condition=ready --timeout=5m
- name: flux tree
run: |
/tmp/flux tree kustomization flux-system | grep Service/podinfo
- name: flux check
run: |
/tmp/flux check

@ -65,8 +65,6 @@ status:
v: v1
- id: cert-manager_cert-manager_source.toolkit.fluxcd.io_HelmRepository
v: v1beta1
- id: cert-manager_cert-manager_helm.toolkit.fluxcd.io_HelmRelease
v: v2beta1
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
@ -87,3 +85,4 @@ status:
reason: ReconciliationSucceeded
status: "True"
type: Ready
---

@ -1,6 +1,5 @@
Kustomization/{{ .fluxns }}/flux-system
├── Kustomization/{{ .fluxns }}/infrastructure
│ ├── HelmRepository/cert-manager/cert-manager
│ └── HelmRelease/cert-manager/cert-manager
│ └── HelmRepository/cert-manager/cert-manager
└── GitRepository/{{ .fluxns }}/flux-system

@ -6,7 +6,6 @@ Kustomization/{{ .fluxns }}/flux-system
├── Deployment/{{ .fluxns }}/source-controller
├── Kustomization/{{ .fluxns }}/infrastructure
│ ├── Namespace/cert-manager
│ ├── HelmRepository/cert-manager/cert-manager
│ └── HelmRelease/cert-manager/cert-manager
│ └── HelmRepository/cert-manager/cert-manager
└── GitRepository/{{ .fluxns }}/flux-system

@ -17,15 +17,23 @@ limitations under the License.
package main
import (
"bytes"
"compress/gzip"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"strings"
"github.com/fluxcd/flux2/internal/tree"
"github.com/fluxcd/flux2/internal/utils"
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
"github.com/fluxcd/pkg/ssa"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/cli-utils/pkg/object"
"sigs.k8s.io/controller-runtime/pkg/client"
@ -119,13 +127,15 @@ func treeKustomization(ctx context.Context, tree tree.ObjMetadataTree, item *kus
return nil
}
compactGroup := "toolkit.fluxcd.io"
for _, entry := range item.Status.Inventory.Entries {
objMetadata, err := object.ParseObjMetadata(entry.ID)
if err != nil {
return err
}
if compact && !strings.Contains(objMetadata.GroupKind.Group, "toolkit.fluxcd.io") {
if compact && !strings.Contains(objMetadata.GroupKind.Group, compactGroup) {
continue
}
@ -137,6 +147,26 @@ func treeKustomization(ctx context.Context, tree tree.ObjMetadataTree, item *kus
}
ks := tree.Add(objMetadata)
if objMetadata.GroupKind.Group == helmv2.GroupVersion.Group &&
objMetadata.GroupKind.Kind == helmv2.HelmReleaseKind {
objects, err := getHelmReleaseInventory(
ctx, client.ObjectKey{
Namespace: objMetadata.Namespace,
Name: objMetadata.Name,
}, kubeClient)
if err != nil {
return err
}
for _, obj := range objects {
if compact && !strings.Contains(obj.GroupKind.Group, compactGroup) {
continue
}
ks.Add(obj)
}
}
if objMetadata.GroupKind.Group == kustomizev1.GroupVersion.Group &&
objMetadata.GroupKind.Kind == kustomizev1.KustomizationKind {
k := &kustomizev1.Kustomization{}
@ -156,3 +186,84 @@ func treeKustomization(ctx context.Context, tree tree.ObjMetadataTree, item *kus
return nil
}
type hrStorage struct {
Name string `json:"name,omitempty"`
Manifest string `json:"manifest,omitempty"`
}
func getHelmReleaseInventory(ctx context.Context, objectKey client.ObjectKey, kubeClient client.Client) ([]object.ObjMetadata, error) {
hr := &helmv2.HelmRelease{}
if err := kubeClient.Get(ctx, objectKey, hr); err != nil {
return nil, err
}
storageNamespace := hr.GetNamespace()
if hr.Spec.StorageNamespace != "" {
storageNamespace = hr.Spec.StorageNamespace
}
storageName := hr.GetName()
if hr.Spec.ReleaseName != "" {
storageName = hr.Spec.ReleaseName
} else if hr.Spec.TargetNamespace != "" {
storageName = strings.Join([]string{hr.Spec.TargetNamespace, hr.Name}, "-")
}
storageVersion := hr.Status.LastReleaseRevision
// skip release if it failed to install
if storageVersion < 1 {
return nil, nil
}
storageKey := client.ObjectKey{
Namespace: storageNamespace,
Name: fmt.Sprintf("sh.helm.release.v1.%s.v%v", storageName, storageVersion),
}
storageSecret := &corev1.Secret{}
if err := kubeClient.Get(ctx, storageKey, storageSecret); err != nil {
// skip release if it has no storage
if apierrors.IsNotFound(err) {
return nil, nil
}
return nil, fmt.Errorf("failed to find the Helm storage object for HelmRelease '%s': %w", objectKey.String(), err)
}
releaseData, releaseFound := storageSecret.Data["release"]
if !releaseFound {
return nil, fmt.Errorf("failed to decode the Helm storage object for HelmRelease '%s'", objectKey.String())
}
// adapted from https://github.com/helm/helm/blob/02685e94bd3862afcb44f6cd7716dbeb69743567/pkg/storage/driver/util.go
var b64 = base64.StdEncoding
b, err := b64.DecodeString(string(releaseData))
if err != nil {
return nil, err
}
var magicGzip = []byte{0x1f, 0x8b, 0x08}
if bytes.Equal(b[0:3], magicGzip) {
r, err := gzip.NewReader(bytes.NewReader(b))
if err != nil {
return nil, err
}
defer r.Close()
b2, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
b = b2
}
var rls hrStorage
if err := json.Unmarshal(b, &rls); err != nil {
return nil, fmt.Errorf("failed to decode the Helm storage object for HelmRelease '%s': %w", objectKey.String(), err)
}
objects, err := ssa.ReadObjects(strings.NewReader(rls.Manifest))
if err != nil {
return nil, fmt.Errorf("failed to read the Helm storage object for HelmRelease '%s': %w", objectKey.String(), err)
}
return object.UnstructuredsToObjMetas(objects)
}

Loading…
Cancel
Save