Skip to content

Commit 458e033

Browse files
authored
Merge pull request #931 from cappyzawa/deprecate-updated-template-field
Add deprecation handling for .Updated template field
2 parents 7bd947c + f1a92cb commit 458e033

15 files changed

+276
-237
lines changed

api/v1beta2/condition_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,7 @@ const (
3636

3737
// InvalidPolicySelectorReason represents an invalid policy selector.
3838
InvalidPolicySelectorReason string = "InvalidPolicySelector"
39+
40+
// RemovedTemplateFieldReason represents usage of removed template field.
41+
RemovedTemplateFieldReason string = "RemovedTemplateField"
3942
)

api/v1beta2/git.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ type CommitSpec struct {
6565
SigningKey *SigningKey `json:"signingKey,omitempty"`
6666
// MessageTemplate provides a template for the commit message,
6767
// into which will be interpolated the details of the change made.
68+
// Note: The `Updated` template field has been removed. Use `Changed` instead.
6869
// +optional
6970
MessageTemplate string `json:"messageTemplate,omitempty"`
7071

config/crd/bases/image.toolkit.fluxcd.io_imageupdateautomations.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ spec:
440440
description: |-
441441
MessageTemplate provides a template for the commit message,
442442
into which will be interpolated the details of the change made.
443+
Note: The `Updated` template field has been removed. Use `Changed` instead.
443444
type: string
444445
messageTemplateValues:
445446
additionalProperties:

docs/api/v1beta2/image-automation.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ string
6767
<td>
6868
<em>(Optional)</em>
6969
<p>MessageTemplate provides a template for the commit message,
70-
into which will be interpolated the details of the change made.</p>
70+
into which will be interpolated the details of the change made.
71+
Note: The <code>Updated</code> template field has been removed. Use <code>Changed</code> instead.</p>
7172
</td>
7273
</tr>
7374
<tr>

docs/spec/v1beta2/imageupdateautomations.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,12 @@ spec:
374374
Automated image update by Flux
375375
```
376376

377-
**Deprecation Note:** The `Updated` template data available in v1beta1 API is
378-
deprecated. `Changed` template data is recommended for template data, as it
379-
accommodates for all the updates, including partial updates to just the image
380-
name or the tag, not just full image with name and tag update. The old templates
381-
will continue to work in v1beta2 API as `Updated` has not been removed yet. In
382-
the next API version, `Updated` may be removed.
377+
**Removal Note:** The `Updated` template data has been removed from the API.
378+
Use `Changed` template data instead, as it accommodates for all the updates,
379+
including partial updates to just the image name or the tag, not just full image
380+
with name and tag update. Templates using `Updated` will result in an error and
381+
the ImageUpdateAutomation will be marked as Stalled.
382+
383383

384384
The message template also has access to the data related to the changes made by
385385
the automation. The template is a [Go text template][go-text-template]. The data
@@ -393,14 +393,14 @@ type TemplateData struct {
393393
AutomationObject struct {
394394
Name, Namespace string
395395
}
396-
Changed update.ResultV2
396+
Changed update.Result
397397
Values map[string]string
398398
}
399399
400-
// ResultV2 contains the file changes made during the update. It contains
400+
// Result contains the file changes made during the update. It contains
401401
// details about the exact changes made to the files and the objects in them. It
402402
// has a nested structure file->objects->changes.
403-
type ResultV2 struct {
403+
type Result struct {
404404
FileChanges map[string]ObjectChanges
405405
}
406406
@@ -427,10 +427,10 @@ over the changed objects and changes:
427427

428428
```go
429429
// Changes returns all the changes that were made in at least one update.
430-
func (r ResultV2) Changes() []Change
430+
func (r Result) Changes() []Change
431431
432432
// Objects returns ObjectChanges, regardless of which file they appear in.
433-
func (r ResultV2) Objects() ObjectChanges
433+
func (r Result) Objects() ObjectChanges
434434
```
435435

436436
Example of using the methods in a template:

internal/controller/imageupdateautomation_controller.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,14 @@ func (r *ImageUpdateAutomationReconciler) reconcile(ctx context.Context, sp *pat
481481

482482
pushResult, err = sm.CommitAndPush(ctx, obj, policyResult, pushCfg...)
483483
if err != nil {
484+
// Check if error is due to removed template field usage.
485+
// Set Stalled condition and return nil error to prevent requeue, allowing user to fix template.
486+
if errors.Is(err, source.ErrRemovedTemplateField) {
487+
conditions.MarkStalled(obj, imagev1.RemovedTemplateFieldReason, "%s", err)
488+
result, retErr = ctrl.Result{}, nil
489+
return
490+
}
491+
484492
e := fmt.Errorf("failed to update source: %w", err)
485493
conditions.MarkFalse(obj, meta.ReadyCondition, imagev1.GitOperationFailedReason, "%s", e)
486494
result, retErr = ctrl.Result{}, e

internal/controller/imageupdateautomation_controller_test.go

Lines changed: 137 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ const (
7171
Automation: {{ .AutomationObject }}
7272
7373
Files:
74-
{{ range $filename, $_ := .Updated.Files -}}
74+
{{ range $filename, $_ := .Changed.FileChanges -}}
7575
- {{ $filename }}
7676
{{ end -}}
7777
7878
Objects:
79-
{{ range $resource, $_ := .Updated.Objects -}}
79+
{{ range $resource, $_ := .Changed.Objects -}}
8080
{{ if eq $resource.Kind "Deployment" -}}
8181
- {{ $resource.Kind | lower }} {{ $resource.Name | lower }}
8282
{{ else -}}
@@ -85,8 +85,10 @@ Objects:
8585
{{ end -}}
8686
8787
Images:
88-
{{ range .Updated.Images -}}
89-
- {{.}} ({{.Policy.Name}})
88+
{{ range .Changed.Changes -}}
89+
{{ if .Setter -}}
90+
- {{.NewValue}} ({{.Setter}})
91+
{{ end -}}
9092
{{ end -}}
9193
`
9294
testCommitMessageFmt = `Commit summary
@@ -98,7 +100,7 @@ Files:
98100
Objects:
99101
- deployment test
100102
Images:
101-
- helloworld:v1.0.0 (%s)
103+
- helloworld:v1.0.0 (%s:%s)
102104
`
103105
)
104106

@@ -727,7 +729,7 @@ func TestImageUpdateAutomationReconciler_commitMessage(t *testing.T) {
727729
name: "template with update Result",
728730
template: testCommitTemplate,
729731
wantCommitMsg: func(policyName, policyNS string) string {
730-
return fmt.Sprintf(testCommitMessageFmt, policyNS, policyName)
732+
return fmt.Sprintf(testCommitMessageFmt, policyNS, policyNS, policyName)
731733
},
732734
},
733735
{
@@ -841,6 +843,134 @@ Automation: %s/update-test
841843
}
842844
}
843845

846+
// TestImageUpdateAutomationReconciler_removedTemplateField tests removed template field usage (.Updated and .Changed.ImageResult).
847+
func TestImageUpdateAutomationReconciler_removedTemplateField(t *testing.T) {
848+
policySpec := imagev1_reflect.ImagePolicySpec{
849+
ImageRepositoryRef: meta.NamespacedObjectReference{
850+
Name: "not-expected-to-exist",
851+
},
852+
Policy: imagev1_reflect.ImagePolicyChoice{
853+
SemVer: &imagev1_reflect.SemVerPolicy{
854+
Range: "1.x",
855+
},
856+
},
857+
}
858+
fixture := "testdata/appconfig"
859+
latest := "helloworld:v1.0.0"
860+
861+
testCases := []struct {
862+
name string
863+
template string
864+
expectedErrMsg string
865+
}{
866+
{
867+
name: ".Updated field",
868+
template: `Commit summary
869+
870+
Automation: {{ .AutomationObject }}
871+
872+
Files:
873+
{{ range $filename, $_ := .Updated.Files -}}
874+
- {{ $filename }}
875+
{{ end -}}
876+
877+
Objects:
878+
{{ range $resource, $_ := .Updated.Objects -}}
879+
{{ if eq $resource.Kind "Deployment" -}}
880+
- {{ $resource.Kind | lower }} {{ $resource.Name | lower }}
881+
{{ else -}}
882+
- {{ $resource.Kind }} {{ $resource.Name }}
883+
{{ end -}}
884+
{{ end -}}
885+
886+
Images:
887+
{{ range .Updated.Images -}}
888+
- {{.}} ({{.Policy.Name}})
889+
{{ end -}}
890+
`,
891+
expectedErrMsg: "template uses removed '.Updated' field",
892+
},
893+
{
894+
name: ".Changed.ImageResult field",
895+
template: `Commit summary
896+
897+
Automation: {{ .AutomationObject }}
898+
899+
Files:
900+
{{ range $filename, $_ := .Changed.ImageResult.Files -}}
901+
- {{ $filename }}
902+
{{ end -}}
903+
904+
Objects:
905+
{{ range $resource, $_ := .Changed.ImageResult.Objects -}}
906+
- {{ $resource.Kind }} {{ $resource.Name }}
907+
{{ end -}}
908+
909+
Images:
910+
{{ range .Changed.ImageResult.Images -}}
911+
- {{.}} ({{.Policy.Name}})
912+
{{ end -}}
913+
`,
914+
expectedErrMsg: "template uses removed '.Changed.ImageResult' field",
915+
},
916+
}
917+
918+
for _, tc := range testCases {
919+
t.Run(tc.name, func(t *testing.T) {
920+
g := NewWithT(t)
921+
ctx := context.TODO()
922+
923+
namespace, err := testEnv.CreateNamespace(ctx, "image-auto-test")
924+
g.Expect(err).ToNot(HaveOccurred())
925+
defer func() { g.Expect(testEnv.Delete(ctx, namespace)).To(Succeed()) }()
926+
927+
testWithRepoAndImagePolicy(
928+
ctx, g, testEnv, namespace.Name, fixture, policySpec, latest,
929+
func(g *WithT, s repoAndPolicyArgs, repoURL string, localRepo *extgogit.Repository) {
930+
policyKey := types.NamespacedName{
931+
Name: s.imagePolicyName,
932+
Namespace: s.namespace,
933+
}
934+
_ = testutil.CommitInRepo(ctx, g, repoURL, s.branch, originRemote, "Install setter marker", func(tmp string) {
935+
g.Expect(testutil.ReplaceMarker(filepath.Join(tmp, "deploy.yaml"), policyKey)).To(Succeed())
936+
})
937+
938+
preChangeCommitId := testutil.CommitIdFromBranch(localRepo, s.branch)
939+
waitForNewHead(g, localRepo, s.branch, preChangeCommitId)
940+
preChangeCommitId = testutil.CommitIdFromBranch(localRepo, s.branch)
941+
942+
updateStrategy := &imagev1.UpdateStrategy{
943+
Strategy: imagev1.UpdateStrategySetters,
944+
}
945+
err := createImageUpdateAutomation(ctx, testEnv, "update-test", s.namespace, s.gitRepoName, s.gitRepoNamespace, s.branch, s.branch, "", tc.template, "", updateStrategy)
946+
g.Expect(err).ToNot(HaveOccurred())
947+
defer func() {
948+
g.Expect(deleteImageUpdateAutomation(ctx, testEnv, "update-test", s.namespace)).To(Succeed())
949+
}()
950+
951+
imageUpdateKey := types.NamespacedName{
952+
Namespace: s.namespace,
953+
Name: "update-test",
954+
}
955+
956+
g.Eventually(func() bool {
957+
var imageUpdate imagev1.ImageUpdateAutomation
958+
_ = testEnv.Get(context.TODO(), imageUpdateKey, &imageUpdate)
959+
stalledCondition := apimeta.FindStatusCondition(imageUpdate.Status.Conditions, meta.StalledCondition)
960+
return stalledCondition != nil &&
961+
stalledCondition.Status == metav1.ConditionTrue &&
962+
stalledCondition.Reason == imagev1.RemovedTemplateFieldReason &&
963+
strings.Contains(stalledCondition.Message, tc.expectedErrMsg)
964+
}, timeout).Should(BeTrue())
965+
966+
head, _ := localRepo.Head()
967+
g.Expect(head.Hash().String()).To(Equal(preChangeCommitId))
968+
},
969+
)
970+
})
971+
}
972+
}
973+
844974
func TestImageUpdateAutomationReconciler_crossNamespaceRef(t *testing.T) {
845975
g := NewWithT(t)
846976
policySpec := imagev1_reflect.ImagePolicySpec{
@@ -875,7 +1005,7 @@ func TestImageUpdateAutomationReconciler_crossNamespaceRef(t *testing.T) {
8751005
testWithCustomRepoAndImagePolicy(
8761006
ctx, g, testEnv, fixture, policySpec, latest, args,
8771007
func(g *WithT, s repoAndPolicyArgs, repoURL string, localRepo *extgogit.Repository) {
878-
commitMessage := fmt.Sprintf(testCommitMessageFmt, s.namespace, s.imagePolicyName)
1008+
commitMessage := fmt.Sprintf(testCommitMessageFmt, s.namespace, s.namespace, s.imagePolicyName)
8791009

8801010
// Update the setter marker in the repo.
8811011
policyKey := types.NamespacedName{

internal/policy/applier.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ var (
4242

4343
// ApplyPolicies applies the given set of policies on the source present in the
4444
// workDir based on the provided ImageUpdateAutomation configuration.
45-
func ApplyPolicies(ctx context.Context, workDir string, obj *imagev1.ImageUpdateAutomation, policies []imagev1_reflect.ImagePolicy) (update.ResultV2, error) {
46-
var result update.ResultV2
45+
func ApplyPolicies(ctx context.Context, workDir string, obj *imagev1.ImageUpdateAutomation, policies []imagev1_reflect.ImagePolicy) (update.Result, error) {
46+
var result update.Result
4747
if obj.Spec.Update == nil {
4848
return result, ErrNoUpdateStrategy
4949
}
@@ -62,5 +62,5 @@ func ApplyPolicies(ctx context.Context, workDir string, obj *imagev1.ImageUpdate
6262
}
6363

6464
tracelog := log.FromContext(ctx).V(logger.TraceLevel)
65-
return update.UpdateV2WithSetters(tracelog, manifestPath, manifestPath, policies)
65+
return update.UpdateWithSetters(tracelog, manifestPath, manifestPath, policies)
6666
}

internal/policy/applier_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta2"
3232
"github.com/fluxcd/image-automation-controller/internal/testutil"
3333
"github.com/fluxcd/image-automation-controller/pkg/test"
34-
"github.com/fluxcd/image-automation-controller/pkg/update"
3534
)
3635

3736
func testdataPath(path string) string {
@@ -48,7 +47,6 @@ func Test_applyPolicies(t *testing.T) {
4847
inputPath string
4948
expectedPath string
5049
wantErr bool
51-
wantResult update.Result
5250
}{
5351
{
5452
name: "valid update strategy and one policy",

0 commit comments

Comments
 (0)