Skip to content

Commit fe60c6a

Browse files
authored
Merge pull request #1339 from salasberryfin/gcpmanaged-improve-test-coverage
Increase test coverage for managed cluster webhooks
2 parents 154f324 + 3752077 commit fe60c6a

File tree

3 files changed

+532
-128
lines changed

3 files changed

+532
-128
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1beta1
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/gomega"
23+
infrav1 "sigs.k8s.io/cluster-api-provider-gcp/api/v1beta1"
24+
)
25+
26+
func TestGCPManagedClusterValidatingWebhookUpdate(t *testing.T) {
27+
tests := []struct {
28+
name string
29+
expectError bool
30+
spec GCPManagedClusterSpec
31+
}{
32+
{
33+
name: "request to change mutable field additional labels",
34+
expectError: false,
35+
spec: GCPManagedClusterSpec{
36+
Project: "old-project",
37+
Region: "us-west1",
38+
CredentialsRef: &infrav1.ObjectReference{
39+
Namespace: "default",
40+
Name: "credsref",
41+
},
42+
AdditionalLabels: map[string]string{
43+
"testKey": "testVal",
44+
},
45+
},
46+
},
47+
{
48+
name: "request to change immutable field project",
49+
expectError: true,
50+
spec: GCPManagedClusterSpec{
51+
Project: "new-project",
52+
Region: "us-west1",
53+
CredentialsRef: &infrav1.ObjectReference{
54+
Namespace: "default",
55+
Name: "credsref",
56+
},
57+
},
58+
},
59+
{
60+
name: "request to change immutable field region",
61+
expectError: true,
62+
spec: GCPManagedClusterSpec{
63+
Project: "old-project",
64+
Region: "us-central1",
65+
CredentialsRef: &infrav1.ObjectReference{
66+
Namespace: "default",
67+
Name: "credsref",
68+
},
69+
},
70+
},
71+
{
72+
name: "request to change immutable field credentials ref",
73+
expectError: true,
74+
spec: GCPManagedClusterSpec{
75+
Project: "old-project",
76+
Region: "us-central1",
77+
CredentialsRef: &infrav1.ObjectReference{
78+
Namespace: "new-ns",
79+
Name: "new-name",
80+
},
81+
},
82+
},
83+
}
84+
85+
for _, tc := range tests {
86+
t.Run(tc.name, func(t *testing.T) {
87+
g := NewWithT(t)
88+
89+
newMC := &GCPManagedCluster{
90+
Spec: tc.spec,
91+
}
92+
oldMC := &GCPManagedCluster{
93+
Spec: GCPManagedClusterSpec{
94+
Project: "old-project",
95+
Region: "us-west1",
96+
CredentialsRef: &infrav1.ObjectReference{
97+
Namespace: "default",
98+
Name: "credsref",
99+
},
100+
},
101+
}
102+
103+
warn, err := newMC.ValidateUpdate(oldMC)
104+
105+
if tc.expectError {
106+
g.Expect(err).To(HaveOccurred())
107+
} else {
108+
g.Expect(err).ToNot(HaveOccurred())
109+
}
110+
// Nothing emits warnings yet
111+
g.Expect(warn).To(BeEmpty())
112+
})
113+
}
114+
}
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1beta1
18+
19+
import (
20+
"strings"
21+
"testing"
22+
23+
. "github.com/onsi/gomega"
24+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
)
26+
27+
var (
28+
vV1_27_1 = "v1.27.1"
29+
releaseChannel = Rapid
30+
)
31+
32+
func TestGCPManagedControlPlaneDefaultingWebhook(t *testing.T) {
33+
tests := []struct {
34+
name string
35+
resourceName string
36+
resourceNS string
37+
spec GCPManagedControlPlaneSpec
38+
expectSpec GCPManagedControlPlaneSpec
39+
expetError bool
40+
expectHash bool
41+
}{
42+
{
43+
name: "valid cluster name",
44+
resourceName: "cluster1",
45+
resourceNS: "default",
46+
spec: GCPManagedControlPlaneSpec{
47+
ClusterName: "default_cluster1",
48+
},
49+
expectSpec: GCPManagedControlPlaneSpec{ClusterName: "default_cluster1"},
50+
},
51+
{
52+
name: "no cluster name should generate a valid one",
53+
resourceName: "cluster1",
54+
resourceNS: "default",
55+
spec: GCPManagedControlPlaneSpec{
56+
ClusterName: "",
57+
},
58+
expectSpec: GCPManagedControlPlaneSpec{ClusterName: "default-cluster1"},
59+
},
60+
{
61+
name: "invalid cluster name (too long)",
62+
resourceName: strings.Repeat("A", maxClusterNameLength+1),
63+
resourceNS: "default",
64+
spec: GCPManagedControlPlaneSpec{
65+
ClusterName: "",
66+
},
67+
expectSpec: GCPManagedControlPlaneSpec{ClusterName: "capg-"},
68+
expectHash: true,
69+
},
70+
{
71+
name: "with kubernetes version",
72+
resourceName: "cluster1",
73+
resourceNS: "default",
74+
spec: GCPManagedControlPlaneSpec{
75+
ClusterName: "cluster1_27_1",
76+
ControlPlaneVersion: &vV1_27_1,
77+
},
78+
expectSpec: GCPManagedControlPlaneSpec{ClusterName: "cluster1_27_1", ControlPlaneVersion: &vV1_27_1},
79+
},
80+
{
81+
name: "with autopilot enabled",
82+
resourceName: "cluster1",
83+
resourceNS: "default",
84+
spec: GCPManagedControlPlaneSpec{
85+
ClusterName: "cluster1_autopilot",
86+
ControlPlaneVersion: &vV1_27_1,
87+
EnableAutopilot: true,
88+
},
89+
expectSpec: GCPManagedControlPlaneSpec{ClusterName: "cluster1_autopilot", ControlPlaneVersion: &vV1_27_1, EnableAutopilot: true},
90+
},
91+
}
92+
93+
for _, tc := range tests {
94+
t.Run(tc.name, func(t *testing.T) {
95+
g := NewWithT(t)
96+
97+
mcp := &GCPManagedControlPlane{
98+
ObjectMeta: metav1.ObjectMeta{
99+
Name: tc.resourceName,
100+
Namespace: tc.resourceNS,
101+
},
102+
Spec: tc.spec,
103+
}
104+
mcp.Default()
105+
106+
g.Expect(mcp.Spec).ToNot(BeNil())
107+
g.Expect(mcp.Spec.ClusterName).ToNot(BeEmpty())
108+
109+
if tc.expectHash {
110+
g.Expect(strings.HasPrefix(mcp.Spec.ClusterName, "capg-")).To(BeTrue())
111+
// We don't care about the exact name
112+
tc.expectSpec.ClusterName = mcp.Spec.ClusterName
113+
}
114+
g.Expect(mcp.Spec).To(Equal(tc.expectSpec))
115+
})
116+
}
117+
}
118+
119+
func TestGCPManagedControlPlaneValidatingWebhookCreate(t *testing.T) {
120+
tests := []struct {
121+
name string
122+
expectError bool
123+
spec GCPManagedControlPlaneSpec
124+
}{
125+
{
126+
name: "cluster name too long should cause an error",
127+
expectError: true,
128+
spec: GCPManagedControlPlaneSpec{
129+
ClusterName: strings.Repeat("A", maxClusterNameLength+1),
130+
},
131+
},
132+
{
133+
name: "autopilot enabled without release channel should cause an error",
134+
expectError: true,
135+
spec: GCPManagedControlPlaneSpec{
136+
ClusterName: "",
137+
EnableAutopilot: true,
138+
ReleaseChannel: nil,
139+
},
140+
},
141+
{
142+
name: "autopilot enabled with release channel",
143+
expectError: false,
144+
spec: GCPManagedControlPlaneSpec{
145+
ClusterName: "",
146+
EnableAutopilot: true,
147+
ReleaseChannel: &releaseChannel,
148+
},
149+
},
150+
}
151+
152+
for _, tc := range tests {
153+
t.Run(tc.name, func(t *testing.T) {
154+
g := NewWithT(t)
155+
156+
mcp := &GCPManagedControlPlane{
157+
Spec: tc.spec,
158+
}
159+
warn, err := mcp.ValidateCreate()
160+
161+
if tc.expectError {
162+
g.Expect(err).To(HaveOccurred())
163+
} else {
164+
g.Expect(err).ToNot(HaveOccurred())
165+
}
166+
// Nothing emits warnings yet
167+
g.Expect(warn).To(BeEmpty())
168+
})
169+
}
170+
}
171+
172+
func TestGCPManagedControlPlaneValidatingWebhookUpdate(t *testing.T) {
173+
tests := []struct {
174+
name string
175+
expectError bool
176+
spec GCPManagedControlPlaneSpec
177+
}{
178+
{
179+
name: "request to change cluster name should cause an error",
180+
expectError: true,
181+
spec: GCPManagedControlPlaneSpec{
182+
ClusterName: "default_cluster2",
183+
},
184+
},
185+
{
186+
name: "request to change project should cause an error",
187+
expectError: true,
188+
spec: GCPManagedControlPlaneSpec{
189+
ClusterName: "default_cluster1",
190+
Project: "new-project",
191+
},
192+
},
193+
{
194+
name: "request to change location should cause an error",
195+
expectError: true,
196+
spec: GCPManagedControlPlaneSpec{
197+
ClusterName: "default_cluster1",
198+
Location: "us-west4",
199+
},
200+
},
201+
{
202+
name: "request to enable/disable autopilot should cause an error",
203+
expectError: true,
204+
spec: GCPManagedControlPlaneSpec{
205+
ClusterName: "default_cluster1",
206+
EnableAutopilot: true,
207+
},
208+
},
209+
{
210+
name: "request to change network should not cause an error",
211+
expectError: false,
212+
spec: GCPManagedControlPlaneSpec{
213+
ClusterName: "default_cluster1",
214+
ClusterNetwork: &ClusterNetwork{
215+
PrivateCluster: &PrivateCluster{
216+
EnablePrivateEndpoint: false,
217+
},
218+
},
219+
},
220+
},
221+
}
222+
223+
for _, tc := range tests {
224+
t.Run(tc.name, func(t *testing.T) {
225+
g := NewWithT(t)
226+
227+
newMCP := &GCPManagedControlPlane{
228+
Spec: tc.spec,
229+
}
230+
oldMCP := &GCPManagedControlPlane{
231+
Spec: GCPManagedControlPlaneSpec{
232+
ClusterName: "default_cluster1",
233+
ClusterNetwork: &ClusterNetwork{
234+
PrivateCluster: &PrivateCluster{
235+
EnablePrivateEndpoint: true,
236+
},
237+
},
238+
},
239+
}
240+
241+
warn, err := newMCP.ValidateUpdate(oldMCP)
242+
243+
if tc.expectError {
244+
g.Expect(err).To(HaveOccurred())
245+
} else {
246+
g.Expect(err).ToNot(HaveOccurred())
247+
}
248+
// Nothing emits warnings yet
249+
g.Expect(warn).To(BeEmpty())
250+
})
251+
}
252+
}

0 commit comments

Comments
 (0)