Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for OCIRepository as chartRef #905

Merged
merged 12 commits into from
Apr 18, 2024
44 changes: 44 additions & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ jobs:
kubectl -n install-create-target-ns get deployment install-create-target-ns-install-create-target-ns-podinfo

kubectl -n helm-system delete -f config/testdata/install-create-target-ns
- name: Run install from ocirepo test
run: |
kubectl -n helm-system apply -f config/testdata/install-from-ocirepo-source
kubectl -n helm-system wait helmreleases/podinfo-from-ocirepo --for=condition=ready --timeout=4m
kubectl -n helm-system delete -f config/testdata/install-from-ocirepo-source
- name: Run install fail test
run: |
test_name=install-fail
Expand Down Expand Up @@ -458,6 +463,45 @@ jobs:
fi

kubectl delete -n helm-system -f config/testdata/$test_name/install.yaml
- name: Run upgrade from ocirepo source
run: |
test_name=upgrade-from-ocirepo-source
kubectl -n helm-system apply -f config/testdata/$test_name/install.yaml
echo -n ">>> Waiting for expected conditions"
count=0
until [ 'true' == "$( kubectl -n helm-system get helmrelease/$test_name -o json | jq '.status.conditions | map( { (.type): .status } ) | add | .Released=="True" and .Ready=="True"' )" ]; do
echo -n '.'
sleep 5
count=$((count + 1))
if [[ ${count} -eq 24 ]]; then
echo ' No more retries left!'
exit 1
fi
done
echo ' done'

# Validate release was installed.
REVISION_COUNT=$(helm -n helm-system history -o json $test_name | jq 'length')
if [ "$REVISION_COUNT" != 1 ]; then
echo -e "Unexpected revision count: $REVISION_COUNT"
exit 1
fi

kubectl -n helm-system apply -f config/testdata/$test_name/upgrade.yaml
echo -n ">>> Waiting for expected conditions"
count=0
until [ 'true' == "$( kubectl -n helm-system get helmrelease/$test_name -o json | jq '.status.conditions | map( { (.type): .status } ) | add | .Released=="True" and .Ready=="True"' )" ]; do
echo -n '.'
sleep 5
count=$((count + 1))
if [[ ${count} -eq 24 ]]; then
echo ' No more retries left!'
exit 1
fi
done
echo ' done'

kubectl delete -n helm-system -f config/testdata/$test_name/install.yaml
- name: Run upgrade fail with uninstall remediation strategy test
run: |
test_name=upgrade-fail-remediate-uninstall
Expand Down
32 changes: 29 additions & 3 deletions api/v2beta2/helmrelease_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,17 @@ type PostRenderer struct {
}

// HelmReleaseSpec defines the desired state of a Helm release.
// +kubebuilder:validation:XValidation:rule="(has(self.chart) && !has(self.chartRef)) || (!has(self.chart) && has(self.chartRef))", message="either chart or chartRef must be set"
type HelmReleaseSpec struct {
// Chart defines the template of the v1beta2.HelmChart that should be created
// for this HelmRelease.
// +required
Chart HelmChartTemplate `json:"chart"`
// +optional
Chart HelmChartTemplate `json:"chart,omitempty"`

// ChartRef holds a reference to a source controller resource containing the
// Helm chart artifact.
// +optional
ChartRef *CrossNamespaceSourceReference `json:"chartRef,omitempty"`
souleb marked this conversation as resolved.
Show resolved Hide resolved

// Interval at which to reconcile the Helm release.
// +kubebuilder:validation:Type=string
Expand Down Expand Up @@ -996,10 +1002,16 @@ type HelmReleaseStatus struct {
LastAppliedRevision string `json:"lastAppliedRevision,omitempty"`

// LastAttemptedRevision is the Source revision of the last reconciliation
// attempt.
// attempt. For OCIRepository sources, the 12 first characters of the digest are
// appended to the chart version e.g. "1.2.3+1234567890ab".
// +optional
LastAttemptedRevision string `json:"lastAttemptedRevision,omitempty"`

// LastAttemptedRevisionDigest is the digest of the last reconciliation attempt.
// This is only set for OCIRepository sources.
// +optional
LastAttemptedRevisionDigest string `json:"lastAttemptedRevisionDigest,omitempty"`

// LastAttemptedValuesChecksum is the SHA1 checksum for the values of the last
// reconciliation attempt.
// Deprecated: Use LastAttemptedConfigDigest instead.
Expand Down Expand Up @@ -1052,6 +1064,10 @@ func (in HelmReleaseStatus) GetHelmChart() (string, string) {
return "", ""
}

func (in *HelmReleaseStatus) GetLastAttemptedRevision() string {
return in.LastAttemptedRevision
}

const (
// SourceIndexKey is the key used for indexing HelmReleases based on
// their sources.
Expand Down Expand Up @@ -1241,6 +1257,16 @@ func (in *HelmRelease) GetStatusConditions() *[]metav1.Condition {
return &in.Status.Conditions
}

// IsChartRefPresent returns true if the HelmRelease has a ChartRef.
func (in *HelmRelease) HasChartRef() bool {
return in.Spec.ChartRef != nil
}

// IsChartTemplatePresent returns true if the HelmRelease has a ChartTemplate.
func (in *HelmRelease) HasChartTemplate() bool {
return in.Spec.Chart.Spec.Chart != ""
darkowlzz marked this conversation as resolved.
Show resolved Hide resolved
}

// +kubebuilder:object:root=true

// HelmReleaseList contains a list of HelmRelease objects.
Expand Down
27 changes: 27 additions & 0 deletions api/v2beta2/reference_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,33 @@ type CrossNamespaceObjectReference struct {
Namespace string `json:"namespace,omitempty"`
}

// CrossNamespaceSourceReference contains enough information to let you locate
// the typed referenced object at cluster level.
type CrossNamespaceSourceReference struct {
// APIVersion of the referent.
// +optional
APIVersion string `json:"apiVersion,omitempty"`

// Kind of the referent.
// +kubebuilder:validation:Enum=OCIRepository
// +required
Kind string `json:"kind"`

// Name of the referent.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=253
// +required
Name string `json:"name"`

// Namespace of the referent, defaults to the namespace of the Kubernetes
// resource object that contains the reference.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=63
// +kubebuilder:validation:Optional
// +optional
Namespace string `json:"namespace,omitempty"`
}

// ValuesReference contains a reference to a resource containing Helm values,
// and optionally the key they can be found at.
type ValuesReference struct {
Expand Down
3 changes: 3 additions & 0 deletions api/v2beta2/snapshot_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ type Snapshot struct {
// run by the controller.
// +optional
TestHooks *map[string]*TestHookStatus `json:"testHooks,omitempty"`
// OCIDigest is the digest of the OCI artifact associated with the release.
// +optional
OCIDigest string `json:"ociDigest,omitempty"`
}

// FullReleaseName returns the full name of the release in the format
Expand Down
20 changes: 20 additions & 0 deletions api/v2beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 48 additions & 2 deletions config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,10 @@ spec:
description: Namespace is the namespace the release is deployed
to.
type: string
ociDigest:
description: OCIDigest is the digest of the OCI artifact associated
with the release.
type: string
status:
description: Status is the current state of the release.
type: string
Expand Down Expand Up @@ -1420,6 +1424,35 @@ spec:
required:
- spec
type: object
chartRef:
description: |-
ChartRef holds a reference to a source controller resource containing the
Helm chart artifact.
properties:
apiVersion:
description: APIVersion of the referent.
type: string
kind:
description: Kind of the referent.
enum:
- OCIRepository
type: string
name:
description: Name of the referent.
maxLength: 253
minLength: 1
type: string
namespace:
description: |-
Namespace of the referent, defaults to the namespace of the Kubernetes
resource object that contains the reference.
maxLength: 63
minLength: 1
type: string
required:
- kind
- name
type: object
dependsOn:
description: |-
DependsOn may contain a meta.NamespacedObjectReference slice with
Expand Down Expand Up @@ -2199,9 +2232,12 @@ spec:
type: object
type: array
required:
- chart
- interval
type: object
x-kubernetes-validations:
- message: either chart or chartRef must be set
rule: (has(self.chart) && !has(self.chartRef)) || (!has(self.chart)
&& has(self.chartRef))
status:
default:
observedGeneration: -1
Expand Down Expand Up @@ -2342,6 +2378,10 @@ spec:
description: Namespace is the namespace the release is deployed
to.
type: string
ociDigest:
description: OCIDigest is the digest of the OCI artifact associated
with the release.
type: string
status:
description: Status is the current state of the release.
type: string
Expand Down Expand Up @@ -2420,7 +2460,13 @@ spec:
lastAttemptedRevision:
description: |-
LastAttemptedRevision is the Source revision of the last reconciliation
attempt.
attempt. For OCIRepository sources, the 12 first characters of the digest are
appended to the chart version e.g. "1.2.3+1234567890ab".
type: string
lastAttemptedRevisionDigest:
description: |-
LastAttemptedRevisionDigest is the digest of the last reconciliation attempt.
This is only set for OCIRepository sources.
type: string
lastAttemptedValuesChecksum:
description: |-
Expand Down
14 changes: 14 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,17 @@ rules:
- helmcharts/status
verbs:
- get
- apiGroups:
- source.toolkit.fluxcd.io
resources:
- ocirepositories
verbs:
- get
- list
- watch
- apiGroups:
- source.toolkit.fluxcd.io
resources:
- ocirepositories/status
verbs:
- get
25 changes: 25 additions & 0 deletions config/testdata/install-from-ocirepo-source/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
name: podinfo-ocirepo
spec:
interval: 30s
url: oci://ghcr.io/stefanprodan/charts/podinfo
ref:
tag: 6.6.0
---
apiVersion: helm.toolkit.fluxcd.io/v2beta2
kind: HelmRelease
metadata:
name: podinfo-from-ocirepo
spec:
chartRef:
kind: OCIRepository
name: podinfo-ocirepo
interval: 30s
values:
resources:
requests:
cpu: 100m
memory: 64Mi
25 changes: 25 additions & 0 deletions config/testdata/upgrade-from-ocirepo-source/install.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
name: upgrade-from-ocirepo-source
spec:
interval: 30s
url: oci://ghcr.io/stefanprodan/charts/podinfo
ref:
digest: "sha256:cdd538a0167e4b51152b71a477e51eb6737553510ce8797dbcc537e1342311bb"
---
apiVersion: helm.toolkit.fluxcd.io/v2beta2
kind: HelmRelease
metadata:
name: upgrade-from-ocirepo-source
spec:
chartRef:
kind: OCIRepository
name: upgrade-from-ocirepo-source
interval: 30s
values:
resources:
requests:
cpu: 100m
memory: 64Mi
10 changes: 10 additions & 0 deletions config/testdata/upgrade-from-ocirepo-source/upgrade.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
name: upgrade-from-ocirepo-source
spec:
interval: 30s
url: oci://ghcr.io/stefanprodan/charts/podinfo
ref:
digest: "sha256:0cc9a8446c95009ef382f5eade883a67c257f77d50f84e78ecef2aac9428d1e5"
Loading