Skip to content

Commit d382eca

Browse files
authored
Merge pull request #308 from arbourd/ignore-version
Add reconcile strategy for HelmCharts
2 parents c4cc0a7 + 27c385b commit d382eca

File tree

6 files changed

+131
-3
lines changed

6 files changed

+131
-3
lines changed

api/v1beta1/helmchart_types.go

+17
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ type HelmChartSpec struct {
4545
// +required
4646
Interval metav1.Duration `json:"interval"`
4747

48+
// Determines what enables the creation of a new artifact. Valid values are
49+
// ('ChartVersion', 'Revision').
50+
// See the documentation of the values for an explanation on their behavior.
51+
// Defaults to ChartVersion when omitted.
52+
// +kubebuilder:validation:Enum=ChartVersion;Revision
53+
// +kubebuilder:default:=ChartVersion
54+
// +optional
55+
ReconcileStrategy string `json:"reconcileStrategy,omitempty"`
56+
4857
// Alternative list of values files to use as the chart values (values.yaml
4958
// is not included by default), expected to be a relative path in the SourceRef.
5059
// Values files are merged in the order of this list with the last file overriding
@@ -65,6 +74,14 @@ type HelmChartSpec struct {
6574
Suspend bool `json:"suspend,omitempty"`
6675
}
6776

77+
const (
78+
// ReconcileStrategyChartVersion reconciles when the version of the Helm chart is different.
79+
ReconcileStrategyChartVersion string = "ChartVersion"
80+
81+
// ReconcileStrategyRevision reconciles when the Revision of the source is different.
82+
ReconcileStrategyRevision string = "Revision"
83+
)
84+
6885
// LocalHelmChartSourceReference contains enough information to let you locate
6986
// the typed referenced object at namespace level.
7087
type LocalHelmChartSourceReference struct {

config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ spec:
6262
interval:
6363
description: The interval at which to check the Source for updates.
6464
type: string
65+
reconcileStrategy:
66+
default: ChartVersion
67+
description: Determines what enables the creation of a new artifact. Valid values are ('ChartVersion', 'Revision'). See the documentation of the values for an explanation on their behavior. Defaults to ChartVersion when omitted.
68+
enum:
69+
- ChartVersion
70+
- Revision
71+
type: string
6572
sourceRef:
6673
description: The reference to the Source the chart is available at.
6774
properties:

controllers/helmchart_controller.go

+23-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"strings"
2828
"time"
2929

30+
"github.com/Masterminds/semver/v3"
3031
securejoin "github.com/cyphar/filepath-securejoin"
3132
"github.com/go-logr/logr"
3233
helmchart "helm.sh/helm/v3/pkg/chart"
@@ -526,9 +527,29 @@ func (r *HelmChartReconciler) reconcileFromTarballArtifact(ctx context.Context,
526527
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
527528
}
528529

530+
v, err := semver.NewVersion(helmChart.Metadata.Version)
531+
if err != nil {
532+
err = fmt.Errorf("semver error: %w", err)
533+
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
534+
}
535+
536+
version := v.String()
537+
if chart.Spec.ReconcileStrategy == sourcev1.ReconcileStrategyRevision {
538+
// Isolate the commit SHA from GitRepository type artifacts by removing the branch/ prefix.
539+
splitRev := strings.Split(artifact.Revision, "/")
540+
v, err := v.SetMetadata(splitRev[len(splitRev)-1])
541+
if err != nil {
542+
err = fmt.Errorf("semver error: %w", err)
543+
return sourcev1.HelmChartNotReady(chart, sourcev1.StorageOperationFailedReason, err.Error()), err
544+
}
545+
546+
version = v.String()
547+
helmChart.Metadata.Version = v.String()
548+
}
549+
529550
// Return early if the revision is still the same as the current chart artifact
530-
newArtifact := r.Storage.NewArtifactFor(chart.Kind, chart.ObjectMeta.GetObjectMeta(), helmChart.Metadata.Version,
531-
fmt.Sprintf("%s-%s.tgz", helmChart.Metadata.Name, helmChart.Metadata.Version))
551+
newArtifact := r.Storage.NewArtifactFor(chart.Kind, chart.ObjectMeta.GetObjectMeta(), version,
552+
fmt.Sprintf("%s-%s.tgz", helmChart.Metadata.Name, version))
532553
if !force && apimeta.IsStatusConditionTrue(chart.Status.Conditions, meta.ReadyCondition) && chart.GetArtifact().HasRevision(newArtifact.Revision) {
533554
if newArtifact.URL != artifact.URL {
534555
r.Storage.SetArtifactURL(chart.GetArtifact())

controllers/helmchart_controller_test.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ var _ = Describe("HelmChartReconciler", func() {
709709
err = f.Close()
710710
Expect(err).NotTo(HaveOccurred())
711711

712-
_, err = wt.Commit("Chart version bump", &git.CommitOptions{
712+
commit, err := wt.Commit("Chart version bump", &git.CommitOptions{
713713
Author: &object.Signature{
714714
Name: "John Doe",
715715
Email: "john@example.com",
@@ -735,6 +735,21 @@ var _ = Describe("HelmChartReconciler", func() {
735735
Expect(helmChart.Values["testDefault"]).To(BeTrue())
736736
Expect(helmChart.Values["testOverride"]).To(BeFalse())
737737

738+
When("Setting reconcileStrategy to Revision", func() {
739+
updated := &sourcev1.HelmChart{}
740+
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())
741+
updated.Spec.ReconcileStrategy = sourcev1.ReconcileStrategyRevision
742+
Expect(k8sClient.Update(context.Background(), updated)).To(Succeed())
743+
got := &sourcev1.HelmChart{}
744+
Eventually(func() bool {
745+
_ = k8sClient.Get(context.Background(), key, got)
746+
return got.Status.Artifact.Revision != updated.Status.Artifact.Revision &&
747+
storage.ArtifactExist(*got.Status.Artifact)
748+
}, timeout, interval).Should(BeTrue())
749+
Expect(got.Status.Artifact.Revision).To(ContainSubstring(updated.Status.Artifact.Revision))
750+
Expect(got.Status.Artifact.Revision).To(ContainSubstring(commit.String()))
751+
})
752+
738753
When("Setting valid valuesFiles attribute", func() {
739754
updated := &sourcev1.HelmChart{}
740755
Expect(k8sClient.Get(context.Background(), key, updated)).To(Succeed())

docs/api/source.md

+30
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,21 @@ Kubernetes meta/v1.Duration
555555
</tr>
556556
<tr>
557557
<td>
558+
<code>reconcileStrategy</code><br>
559+
<em>
560+
string
561+
</em>
562+
</td>
563+
<td>
564+
<em>(Optional)</em>
565+
<p>Determines what enables reconciliation. Valid values are (&lsquo;ChartVersion&rsquo;,
566+
&lsquo;Revision&rsquo;). See the documentation of the values for an explanation on their
567+
behavior.
568+
Defaults to ChartVersion when omitted.</p>
569+
</td>
570+
</tr>
571+
<tr>
572+
<td>
558573
<code>valuesFiles</code><br>
559574
<em>
560575
[]string
@@ -1613,6 +1628,21 @@ Kubernetes meta/v1.Duration
16131628
</tr>
16141629
<tr>
16151630
<td>
1631+
<code>reconcileStrategy</code><br>
1632+
<em>
1633+
string
1634+
</em>
1635+
</td>
1636+
<td>
1637+
<em>(Optional)</em>
1638+
<p>Determines what enables reconciliation. Valid values are (&lsquo;ChartVersion&rsquo;,
1639+
&lsquo;Revision&rsquo;). See the documentation of the values for an explanation on their
1640+
behavior.
1641+
Defaults to ChartVersion when omitted.</p>
1642+
</td>
1643+
</tr>
1644+
<tr>
1645+
<td>
16161646
<code>valuesFiles</code><br>
16171647
<em>
16181648
[]string

docs/spec/v1beta1/helmcharts.md

+38
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ type HelmChartSpec struct {
2828
// +required
2929
Interval metav1.Duration `json:"interval"`
3030

31+
// Determines what enables the creation of a new artifact. Valid values are
32+
// ('ChartVersion', 'Revision').
33+
// See the documentation of the values for an explanation on their behavior.
34+
// Defaults to ChartVersion when omitted.
35+
// +kubebuilder:validation:Enum=ChartVersion;Revision
36+
// +kubebuilder:default:=ChartVersion
37+
// +optional
38+
ReconcileStrategy string `json:"reconcileStrategy,omitempty"`
39+
3140
// Alternative list of values files to use as the chart values (values.yaml
3241
// is not included by default), expected to be a relative path in the SourceRef.
3342
// Values files are merged in the order of this list with the last file overriding
@@ -49,6 +58,18 @@ type HelmChartSpec struct {
4958
}
5059
```
5160

61+
### Reconciliation strategies
62+
63+
```go
64+
const (
65+
// ReconcileStrategyChartVersion creates a new chart artifact when the version of the Helm chart is different.
66+
ReconcileStrategyChartVersion string = "ChartVersion"
67+
68+
// ReconcileStrategyRevision creates a new chart artifact when the Revision of the SourceRef is different.
69+
ReconcileStrategyRevision string = "Revision"
70+
)
71+
```
72+
5273
### Reference types
5374

5475
```go
@@ -230,6 +251,23 @@ spec:
230251
- ./charts/podinfo/values-production.yaml
231252
```
232253

254+
Reconcile with every change to the source revision:
255+
256+
```yaml
257+
apiVersion: source.toolkit.fluxcd.io/v1beta1
258+
kind: HelmChart
259+
metadata:
260+
name: podinfo
261+
namespace: default
262+
spec:
263+
chart: ./charts/podinfo
264+
sourceRef:
265+
name: podinfo
266+
kind: GitRepository
267+
interval: 10m
268+
reconcileStrategy: Revision
269+
```
270+
233271
## Status examples
234272

235273
Successful chart pull:

0 commit comments

Comments
 (0)