Skip to content

Commit

Permalink
Make flux trace work with OCIRepository
Browse files Browse the repository at this point in the history
* Added support for OCIRepositories to `flux trace`
* Changed indentation to compensate new, longer field name "Source
  Revision"
* Added unit tests for the new output

closes fluxcd#2970

Signed-off-by: Max Jonas Werner <max@e13.dev>
  • Loading branch information
makkes authored and souleb committed Jul 10, 2023
1 parent b5651a2 commit b62a70d
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 48 deletions.
21 changes: 21 additions & 0 deletions cmd/flux/testdata/trace/helmrelease-oci.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

Object: HelmRelease/podinfo
Namespace: {{ .ns }}
Status: Managed by Flux
---
Kustomization: infrastructure
Namespace: {{ .fluxns }}
Path: ./infrastructure
Revision: main/696f056df216eea4f9401adbee0ff744d4df390f
Status: Last reconciled at {{ .kustomizationLastReconcile }}
Message: Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f
---
OCIRepository: flux-system
Namespace: {{ .fluxns }}
URL: oci://ghcr.io/example/repo
Tag: 1.2.3
Revision: dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3
Origin Revision: 6.1.6/450796ddb2ab6724ee1cc32a4be56da032d1cca0
Origin Source: https://github.com/stefanprodan/podinfo.git
Status: Last reconciled at {{ .ociRepositoryLastReconcile }}
Message: stored artifact for digest 'dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3'
92 changes: 92 additions & 0 deletions cmd/flux/testdata/trace/helmrelease-oci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: {{ .fluxns }}
---
apiVersion: v1
kind: Namespace
metadata:
name: {{ .ns }}
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
labels:
kustomize.toolkit.fluxcd.io/name: infrastructure
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
name: podinfo
namespace: {{ .ns }}
spec:
chart:
spec:
chart: podinfo
sourceRef:
kind: HelmRepository
name: podinfo
namespace: {{ .fluxns }}
interval: 5m
status:
conditions:
- lastTransitionTime: "2021-07-16T15:42:20Z"
message: Release reconciliation succeeded
reason: ReconciliationSucceeded
status: "True"
type: Ready
helmChart: {{ .fluxns }}/podinfo-podinfo
lastAppliedRevision: 6.0.0
lastAttemptedRevision: 6.0.0
lastAttemptedValuesChecksum: c31db75d05b7515eba2eef47bd71038c74b2e531
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: infrastructure
namespace: {{ .fluxns }}
spec:
path: ./infrastructure
sourceRef:
kind: OCIRepository
name: flux-system
validation: client
interval: 5m
prune: false
status:
conditions:
- lastTransitionTime: "2021-08-01T04:52:56Z"
message: 'Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f'
reason: ReconciliationSucceeded
status: "True"
type: Ready
lastAppliedRevision: main/696f056df216eea4f9401adbee0ff744d4df390f
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
labels:
kustomize.toolkit.fluxcd.io/name: flux-system
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
name: flux-system
namespace: {{ .fluxns }}
spec:
interval: 10m0s
provider: generic
ref:
tag: 1.2.3
timeout: 60s
url: oci://ghcr.io/example/repo
status:
artifact:
lastUpdateTime: "2022-08-10T10:07:59Z"
metadata:
org.opencontainers.image.revision: 6.1.6/450796ddb2ab6724ee1cc32a4be56da032d1cca0
org.opencontainers.image.source: https://github.com/stefanprodan/podinfo.git
path: "example"
revision: dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3
url: "example"
conditions:
- lastTransitionTime: "2021-07-20T00:48:16Z"
message: "stored artifact for digest 'dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3'"
reason: Succeed
status: "True"
type: Ready
32 changes: 16 additions & 16 deletions cmd/flux/testdata/trace/helmrelease.golden
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@

Object: HelmRelease/podinfo
Namespace: {{ .ns }}
Status: Managed by Flux
Object: HelmRelease/podinfo
Namespace: {{ .ns }}
Status: Managed by Flux
---
Kustomization: infrastructure
Namespace: {{ .fluxns }}
Path: ./infrastructure
Revision: main/696f056df216eea4f9401adbee0ff744d4df390f
Status: Last reconciled at {{ .kustomizationLastReconcile }}
Message: Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f
Kustomization: infrastructure
Namespace: {{ .fluxns }}
Path: ./infrastructure
Revision: main/696f056df216eea4f9401adbee0ff744d4df390f
Status: Last reconciled at {{ .kustomizationLastReconcile }}
Message: Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f
---
GitRepository: flux-system
Namespace: {{ .fluxns }}
URL: ssh://git@github.com/example/repo
Branch: main
Revision: main/696f056df216eea4f9401adbee0ff744d4df390f
Status: Last reconciled at {{ .gitRepositoryLastReconcile }}
Message: Fetched revision: main/696f056df216eea4f9401adbee0ff744d4df390f
GitRepository: flux-system
Namespace: {{ .fluxns }}
URL: ssh://git@github.com/example/repo
Branch: main
Revision: main/696f056df216eea4f9401adbee0ff744d4df390f
Status: Last reconciled at {{ .gitRepositoryLastReconcile }}
Message: Fetched revision: main/696f056df216eea4f9401adbee0ff744d4df390f
119 changes: 87 additions & 32 deletions cmd/flux/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
fluxmeta "github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/oci"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
)

Expand Down Expand Up @@ -219,72 +220,122 @@ func traceKustomization(ctx context.Context, kubeClient client.Client, ksName ty
}
ksReady := meta.FindStatusCondition(ks.Status.Conditions, fluxmeta.ReadyCondition)

var ksRepository *sourcev1.GitRepository
var gitRepository *sourcev1.GitRepository
var ociRepository *sourcev1.OCIRepository
var ksRepositoryReady *metav1.Condition
if ks.Spec.SourceRef.Kind == sourcev1.GitRepositoryKind {
ksRepository = &sourcev1.GitRepository{}
switch ks.Spec.SourceRef.Kind {
case sourcev1.GitRepositoryKind:
gitRepository = &sourcev1.GitRepository{}
sourceNamespace := ks.Namespace
if ks.Spec.SourceRef.Namespace != "" {
sourceNamespace = ks.Spec.SourceRef.Namespace
}
err = kubeClient.Get(ctx, types.NamespacedName{
Namespace: sourceNamespace,
Name: ks.Spec.SourceRef.Name,
}, ksRepository)
}, gitRepository)
if err != nil {
return "", fmt.Errorf("failed to find GitRepository: %w", err)
}
ksRepositoryReady = meta.FindStatusCondition(ksRepository.Status.Conditions, fluxmeta.ReadyCondition)
ksRepositoryReady = meta.FindStatusCondition(gitRepository.Status.Conditions, fluxmeta.ReadyCondition)
case sourcev1.OCIRepositoryKind:
ociRepository = &sourcev1.OCIRepository{}
sourceNamespace := ks.Namespace
if ks.Spec.SourceRef.Namespace != "" {
sourceNamespace = ks.Spec.SourceRef.Namespace
}
err = kubeClient.Get(ctx, types.NamespacedName{
Namespace: sourceNamespace,
Name: ks.Spec.SourceRef.Name,
}, ociRepository)
if err != nil {
return "", fmt.Errorf("failed to find OCIRepository: %w", err)
}
ksRepositoryReady = meta.FindStatusCondition(ociRepository.Status.Conditions, fluxmeta.ReadyCondition)
}

var traceTmpl = `
Object: {{.ObjectName}}
Object: {{.ObjectName}}
{{- if .ObjectNamespace }}
Namespace: {{.ObjectNamespace}}
Namespace: {{.ObjectNamespace}}
{{- end }}
Status: Managed by Flux
Status: Managed by Flux
{{- if .Kustomization }}
---
Kustomization: {{.Kustomization.Name}}
Namespace: {{.Kustomization.Namespace}}
Kustomization: {{.Kustomization.Name}}
Namespace: {{.Kustomization.Namespace}}
{{- if .Kustomization.Spec.TargetNamespace }}
Target: {{.Kustomization.Spec.TargetNamespace}}
Target: {{.Kustomization.Spec.TargetNamespace}}
{{- end }}
Path: {{.Kustomization.Spec.Path}}
Revision: {{.Kustomization.Status.LastAppliedRevision}}
Path: {{.Kustomization.Spec.Path}}
Revision: {{.Kustomization.Status.LastAppliedRevision}}
{{- if .KustomizationReady }}
Status: Last reconciled at {{.KustomizationReady.LastTransitionTime}}
Message: {{.KustomizationReady.Message}}
Status: Last reconciled at {{.KustomizationReady.LastTransitionTime}}
Message: {{.KustomizationReady.Message}}
{{- else }}
Status: Unknown
Status: Unknown
{{- end }}
{{- end }}
{{- if .GitRepository }}
---
GitRepository: {{.GitRepository.Name}}
Namespace: {{.GitRepository.Namespace}}
URL: {{.GitRepository.Spec.URL}}
GitRepository: {{.GitRepository.Name}}
Namespace: {{.GitRepository.Namespace}}
URL: {{.GitRepository.Spec.URL}}
{{- if .GitRepository.Spec.Reference }}
{{- if .GitRepository.Spec.Reference.Tag }}
Tag: {{.GitRepository.Spec.Reference.Tag}}
Tag: {{.GitRepository.Spec.Reference.Tag}}
{{- else if .GitRepository.Spec.Reference.SemVer }}
Tag: {{.GitRepository.Spec.Reference.SemVer}}
Tag: {{.GitRepository.Spec.Reference.SemVer}}
{{- else if .GitRepository.Spec.Reference.Branch }}
Branch: {{.GitRepository.Spec.Reference.Branch}}
Branch: {{.GitRepository.Spec.Reference.Branch}}
{{- end }}
{{- end }}
{{- if .GitRepository.Status.Artifact }}
Revision: {{.GitRepository.Status.Artifact.Revision}}
Revision: {{.GitRepository.Status.Artifact.Revision}}
{{- end }}
{{- if .GitRepositoryReady }}
{{- if eq .GitRepositoryReady.Status "False" }}
Status: Last reconciliation failed at {{.GitRepositoryReady.LastTransitionTime}}
{{- if .RepositoryReady }}
{{- if eq .RepositoryReady.Status "False" }}
Status: Last reconciliation failed at {{.RepositoryReady.LastTransitionTime}}
{{- else }}
Status: Last reconciled at {{.GitRepositoryReady.LastTransitionTime}}
Status: Last reconciled at {{.RepositoryReady.LastTransitionTime}}
{{- end }}
Message: {{.GitRepositoryReady.Message}}
Message: {{.RepositoryReady.Message}}
{{- else }}
Status: Unknown
Status: Unknown
{{- end }}
{{- end }}
{{- if .OCIRepository }}
---
OCIRepository: {{.OCIRepository.Name}}
Namespace: {{.OCIRepository.Namespace}}
URL: {{.OCIRepository.Spec.URL}}
{{- if .OCIRepository.Spec.Reference }}
{{- if .OCIRepository.Spec.Reference.Tag }}
Tag: {{.OCIRepository.Spec.Reference.Tag}}
{{- else if .OCIRepository.Spec.Reference.SemVer }}
Tag: {{.OCIRepository.Spec.Reference.SemVer}}
{{- else if .OCIRepository.Spec.Reference.Digest }}
Digest: {{.OCIRepository.Spec.Reference.Digest}}
{{- end }}
{{- end }}
{{- if .OCIRepository.Status.Artifact }}
Revision: {{.OCIRepository.Status.Artifact.Revision}}
{{- if .OCIRepository.Status.Artifact.Metadata }}
{{- $metadata := .OCIRepository.Status.Artifact.Metadata }}
{{- range $k, $v := .Annotations }}
{{ with (index $metadata $v) }}{{ $k }}{{ . }}{{ end }}
{{- end }}
{{- end }}
{{- end }}
{{- if .RepositoryReady }}
{{- if eq .RepositoryReady.Status "False" }}
Status: Last reconciliation failed at {{.RepositoryReady.LastTransitionTime}}
{{- else }}
Status: Last reconciled at {{.RepositoryReady.LastTransitionTime}}
{{- end }}
Message: {{.RepositoryReady.Message}}
{{- else }}
Status: Unknown
{{- end }}
{{- end }}
`
Expand All @@ -295,14 +346,18 @@ Status: Unknown
Kustomization *kustomizev1.Kustomization
KustomizationReady *metav1.Condition
GitRepository *sourcev1.GitRepository
GitRepositoryReady *metav1.Condition
OCIRepository *sourcev1.OCIRepository
RepositoryReady *metav1.Condition
Annotations map[string]string
}{
ObjectName: obj.GetKind() + "/" + obj.GetName(),
ObjectNamespace: obj.GetNamespace(),
Kustomization: ks,
KustomizationReady: ksReady,
GitRepository: ksRepository,
GitRepositoryReady: ksRepositoryReady,
GitRepository: gitRepository,
OCIRepository: ociRepository,
RepositoryReady: ksRepositoryReady,
Annotations: map[string]string{"Origin Source: ": oci.SourceAnnotation, "Origin Revision: ": oci.RevisionAnnotation},
}

t, err := template.New("tmpl").Parse(traceTmpl)
Expand Down
12 changes: 12 additions & 0 deletions cmd/flux/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ func TestTrace(t *testing.T) {
"gitRepositoryLastReconcile": toLocalTime(t, "2021-07-20T00:48:16Z"),
},
},
{
"HelmRelease from OCI registry",
"trace podinfo --kind HelmRelease --api-version=helm.toolkit.fluxcd.io/v2beta1",
"testdata/trace/helmrelease-oci.yaml",
"testdata/trace/helmrelease-oci.golden",
map[string]string{
"ns": allocateNamespace("podinfo"),
"fluxns": allocateNamespace("flux-system"),
"kustomizationLastReconcile": toLocalTime(t, "2021-08-01T04:52:56Z"),
"ociRepositoryLastReconcile": toLocalTime(t, "2021-07-20T00:48:16Z"),
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
Expand Down

0 comments on commit b62a70d

Please sign in to comment.