Skip to content

Commit d1f5881

Browse files
authored
Merge pull request #787 from sophotechlabs/test/workload-identity-config
Add unit tests for ValidateAndApplyWorkloadIdentityConfig
2 parents b93fef8 + 1222ffd commit d1f5881

2 files changed

Lines changed: 240 additions & 0 deletions

File tree

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright 2025 Stefan Prodan.
2+
// SPDX-License-Identifier: AGPL-3.0
3+
4+
package builder
5+
6+
import (
7+
"testing"
8+
9+
. "github.com/onsi/gomega"
10+
)
11+
12+
func TestValidateAndPatchComponents(t *testing.T) {
13+
tests := []struct {
14+
name string
15+
version string
16+
components []string
17+
expectError bool
18+
expectErrorMsg string
19+
expectPatchContains string
20+
}{
21+
{
22+
name: "empty components returns error",
23+
version: "2.7.0",
24+
components: []string{},
25+
expectError: true,
26+
expectErrorMsg: "no components defined",
27+
},
28+
{
29+
name: "invalid component returns error",
30+
version: "2.7.0",
31+
components: []string{"invalid-controller"},
32+
expectError: true,
33+
expectErrorMsg: "invalid component: invalid-controller",
34+
},
35+
{
36+
name: "default components with notification-controller adds patch",
37+
version: "2.7.0",
38+
components: DefaultComponents,
39+
expectPatchContains: "notification.toolkit.fluxcd.io",
40+
},
41+
{
42+
name: "components without notification-controller omits patch",
43+
version: "2.7.0",
44+
components: []string{"source-controller", "kustomize-controller", "helm-controller"},
45+
},
46+
{
47+
name: "source-watcher with version < 2.7.0 returns error",
48+
version: "2.6.0",
49+
components: []string{"source-controller", "kustomize-controller", "source-watcher"},
50+
expectError: true,
51+
expectErrorMsg: "source-watcher is only supported in Flux versions >= 2.7.0",
52+
},
53+
{
54+
name: "source-watcher with version >= 2.7.0 adds feature gate",
55+
version: "2.7.0",
56+
components: []string{"source-controller", "kustomize-controller", "source-watcher"},
57+
expectPatchContains: "ExternalArtifact=true",
58+
},
59+
{
60+
name: "invalid version returns error",
61+
version: "not-a-version",
62+
components: DefaultComponents,
63+
expectError: true,
64+
expectErrorMsg: "failed to parse Flux version",
65+
},
66+
}
67+
68+
for _, tt := range tests {
69+
t.Run(tt.name, func(t *testing.T) {
70+
g := NewWithT(t)
71+
72+
opts := MakeDefaultOptions()
73+
opts.Version = tt.version
74+
opts.Components = tt.components
75+
76+
err := opts.ValidateAndPatchComponents()
77+
78+
if tt.expectError {
79+
g.Expect(err).To(HaveOccurred())
80+
if tt.expectErrorMsg != "" {
81+
g.Expect(err.Error()).To(ContainSubstring(tt.expectErrorMsg))
82+
}
83+
return
84+
}
85+
86+
g.Expect(err).NotTo(HaveOccurred())
87+
88+
if tt.expectPatchContains != "" {
89+
g.Expect(opts.Patches).To(ContainSubstring(tt.expectPatchContains))
90+
}
91+
})
92+
}
93+
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright 2025 Stefan Prodan.
2+
// SPDX-License-Identifier: AGPL-3.0
3+
4+
package builder
5+
6+
import (
7+
"testing"
8+
9+
. "github.com/onsi/gomega"
10+
11+
fluxcdv1 "github.com/controlplaneio-fluxcd/flux-operator/api/v1"
12+
)
13+
14+
func TestValidateAndApplyWorkloadIdentityConfig(t *testing.T) {
15+
tests := []struct {
16+
name string
17+
version string
18+
cluster fluxcdv1.Cluster
19+
expectError bool
20+
expectErrorMsg string
21+
expectRemovePermission bool
22+
expectPatchContains string
23+
expectPatchNotContains string
24+
expectMultitenantWorkloadIdentityPatchApplied bool
25+
}{
26+
// Invalid version.
27+
{
28+
name: "invalid version returns error",
29+
version: "not-a-version",
30+
expectError: true,
31+
},
32+
// Flux < 2.6.0 tests.
33+
{
34+
name: "pre-2.6.0 with defaults succeeds with no patches",
35+
version: "2.5.0",
36+
},
37+
{
38+
name: "pre-2.6.0 with objectLevelWorkloadIdentity returns error",
39+
version: "2.5.0",
40+
cluster: fluxcdv1.Cluster{ObjectLevelWorkloadIdentity: true},
41+
expectError: true,
42+
expectErrorMsg: "not supported in Flux versions < 2.6.0",
43+
},
44+
{
45+
name: "pre-2.6.0 with multitenantWorkloadIdentity returns error",
46+
version: "2.5.0",
47+
cluster: fluxcdv1.Cluster{MultitenantWorkloadIdentity: true},
48+
expectError: true,
49+
expectErrorMsg: "not supported in Flux versions < 2.6.0",
50+
},
51+
// Flux 2.6.x tests.
52+
{
53+
name: "2.6.x with defaults removes SA token permission",
54+
version: "2.6.0",
55+
expectRemovePermission: true,
56+
},
57+
{
58+
name: "2.6.x with objectLevelWorkloadIdentity adds feature gate patch",
59+
version: "2.6.5",
60+
cluster: fluxcdv1.Cluster{ObjectLevelWorkloadIdentity: true},
61+
expectPatchContains: "ObjectLevelWorkloadIdentity=true",
62+
},
63+
{
64+
name: "2.6.x with multitenantWorkloadIdentity returns error",
65+
version: "2.6.0",
66+
cluster: fluxcdv1.Cluster{MultitenantWorkloadIdentity: true},
67+
expectError: true,
68+
expectErrorMsg: "not supported in Flux versions 2.6.x",
69+
},
70+
// Flux >= 2.7.0 tests.
71+
{
72+
name: "2.7.0 with defaults disables feature gate and removes SA token permission",
73+
version: "2.7.0",
74+
expectPatchContains: "ObjectLevelWorkloadIdentity=false",
75+
expectRemovePermission: true,
76+
},
77+
{
78+
name: "2.7.0 objectLevel=false multitenant=true returns error",
79+
version: "2.7.0",
80+
cluster: fluxcdv1.Cluster{MultitenantWorkloadIdentity: true},
81+
expectError: true,
82+
expectErrorMsg: "objectLevelWorkloadIdentity must be set to true",
83+
},
84+
{
85+
name: "2.7.0 objectLevel=true adds feature gate for all controllers",
86+
version: "2.7.0",
87+
cluster: fluxcdv1.Cluster{ObjectLevelWorkloadIdentity: true},
88+
expectPatchContains: "helm-controller",
89+
},
90+
{
91+
name: "2.7.0 objectLevel=true multitenant=true adds multitenant patch",
92+
version: "2.7.0",
93+
cluster: fluxcdv1.Cluster{
94+
ObjectLevelWorkloadIdentity: true,
95+
MultitenantWorkloadIdentity: true,
96+
},
97+
expectMultitenantWorkloadIdentityPatchApplied: true,
98+
},
99+
{
100+
name: "2.7.0 multitenant with custom service accounts",
101+
version: "2.7.0",
102+
cluster: fluxcdv1.Cluster{
103+
ObjectLevelWorkloadIdentity: true,
104+
MultitenantWorkloadIdentity: true,
105+
TenantDefaultServiceAccount: "custom-sa",
106+
},
107+
expectPatchContains: "custom-sa",
108+
},
109+
}
110+
111+
for _, tt := range tests {
112+
t.Run(tt.name, func(t *testing.T) {
113+
g := NewWithT(t)
114+
115+
opts := MakeDefaultOptions()
116+
opts.Version = tt.version
117+
118+
err := opts.ValidateAndApplyWorkloadIdentityConfig(tt.cluster)
119+
120+
if tt.expectError {
121+
g.Expect(err).To(HaveOccurred())
122+
if tt.expectErrorMsg != "" {
123+
g.Expect(err.Error()).To(ContainSubstring(tt.expectErrorMsg))
124+
}
125+
return
126+
}
127+
128+
g.Expect(err).NotTo(HaveOccurred())
129+
130+
if tt.expectRemovePermission {
131+
g.Expect(opts.RemovePermissionForCreatingServiceAccountTokens).To(BeTrue())
132+
}
133+
134+
if tt.expectPatchContains != "" {
135+
g.Expect(opts.Patches).To(ContainSubstring(tt.expectPatchContains))
136+
}
137+
138+
if tt.expectPatchNotContains != "" {
139+
g.Expect(opts.Patches).NotTo(ContainSubstring(tt.expectPatchNotContains))
140+
}
141+
142+
if tt.expectMultitenantWorkloadIdentityPatchApplied {
143+
g.Expect(opts.Patches).To(ContainSubstring("default-service-account"))
144+
}
145+
})
146+
}
147+
}

0 commit comments

Comments
 (0)