Skip to content

Commit 1a099d6

Browse files
Add tests for clusterctl image overrides functionality
Signed-off-by: Danil-Grigorev <danil.grigorev@suse.com>
1 parent c40d35f commit 1a099d6

File tree

2 files changed

+172
-6
lines changed

2 files changed

+172
-6
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
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 controller
18+
19+
import (
20+
"fmt"
21+
"testing"
22+
23+
. "github.com/onsi/gomega"
24+
appsv1 "k8s.io/api/apps/v1"
25+
corev1 "k8s.io/api/core/v1"
26+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
27+
"k8s.io/client-go/kubernetes/scheme"
28+
)
29+
30+
// inspectImages identifies the container images required to install the objects defined in the objs.
31+
// NB. The implemented approach is specific for the provider components YAML & for the cert-manager manifest; it is not
32+
// intended to cover all the possible objects used to deploy containers existing in Kubernetes.
33+
func inspectImages(objs []unstructured.Unstructured) ([]string, error) {
34+
images := []string{}
35+
36+
for i := range objs {
37+
o := objs[i]
38+
39+
var podSpec corev1.PodSpec
40+
41+
switch o.GetKind() {
42+
case deploymentKind:
43+
d := &appsv1.Deployment{}
44+
if err := scheme.Scheme.Convert(&o, d, nil); err != nil {
45+
return nil, err
46+
}
47+
48+
podSpec = d.Spec.Template.Spec
49+
case daemonSetKind:
50+
d := &appsv1.DaemonSet{}
51+
if err := scheme.Scheme.Convert(&o, d, nil); err != nil {
52+
return nil, err
53+
}
54+
55+
podSpec = d.Spec.Template.Spec
56+
default:
57+
continue
58+
}
59+
60+
for _, c := range podSpec.Containers {
61+
images = append(images, c.Image)
62+
}
63+
64+
for _, c := range podSpec.InitContainers {
65+
images = append(images, c.Image)
66+
}
67+
}
68+
69+
return images, nil
70+
}
71+
72+
func TestFixImages(t *testing.T) {
73+
type args struct {
74+
objs []unstructured.Unstructured
75+
alterImageFunc func(image string) (string, error)
76+
}
77+
78+
tests := []struct {
79+
name string
80+
args args
81+
want []string
82+
wantErr bool
83+
}{
84+
{
85+
name: "fix deployment containers images",
86+
args: args{
87+
objs: []unstructured.Unstructured{
88+
{
89+
Object: map[string]interface{}{
90+
"apiVersion": "apps/v1",
91+
"kind": deploymentKind,
92+
"spec": map[string]interface{}{
93+
"template": map[string]interface{}{
94+
"spec": map[string]interface{}{
95+
"containers": []map[string]interface{}{
96+
{
97+
"image": "container-image",
98+
},
99+
},
100+
"initContainers": []map[string]interface{}{
101+
{
102+
"image": "init-container-image",
103+
},
104+
},
105+
},
106+
},
107+
},
108+
},
109+
},
110+
},
111+
alterImageFunc: func(image string) (string, error) {
112+
return fmt.Sprintf("foo-%s", image), nil
113+
},
114+
},
115+
want: []string{"foo-container-image", "foo-init-container-image"},
116+
wantErr: false,
117+
},
118+
{
119+
name: "fix daemonSet containers images",
120+
args: args{
121+
objs: []unstructured.Unstructured{
122+
{
123+
Object: map[string]interface{}{
124+
"apiVersion": "apps/v1",
125+
"kind": daemonSetKind,
126+
"spec": map[string]interface{}{
127+
"template": map[string]interface{}{
128+
"spec": map[string]interface{}{
129+
"containers": []map[string]interface{}{
130+
{
131+
"image": "container-image",
132+
},
133+
},
134+
"initContainers": []map[string]interface{}{
135+
{
136+
"image": "init-container-image",
137+
},
138+
},
139+
},
140+
},
141+
},
142+
},
143+
},
144+
},
145+
alterImageFunc: func(image string) (string, error) {
146+
return fmt.Sprintf("foo-%s", image), nil
147+
},
148+
},
149+
want: []string{"foo-container-image", "foo-init-container-image"},
150+
wantErr: false,
151+
},
152+
}
153+
154+
for _, tt := range tests {
155+
t.Run(tt.name, func(t *testing.T) {
156+
g := NewWithT(t)
157+
158+
got, err := fixImages(tt.args.objs, tt.args.alterImageFunc)
159+
if tt.wantErr {
160+
g.Expect(err).To(HaveOccurred())
161+
return
162+
}
163+
164+
g.Expect(err).ToNot(HaveOccurred())
165+
166+
gotImages, err := inspectImages(got)
167+
g.Expect(err).ToNot(HaveOccurred())
168+
g.Expect(gotImages).To(Equal(tt.want))
169+
})
170+
}
171+
}

internal/controller/manifests_downloader_test.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,6 @@ func TestProviderDownloadWithOverrides(t *testing.T) {
8282
overridesClient, err := configclient.New(ctx, "", configclient.InjectReader(reader))
8383
g.Expect(err).ToNot(HaveOccurred())
8484

85-
overridesClient.Variables().Set("images", `
86-
all:
87-
repository: "myorg.io/local-repo"
88-
`)
89-
9085
p := &phaseReconciler{
9186
ctrlClient: fakeclient,
9287
provider: &operatorv1.CoreProvider{
@@ -111,6 +106,6 @@ all:
111106
_, err = p.fetch(ctx)
112107
g.Expect(err).ToNot(HaveOccurred())
113108

114-
g.Expect(p.components.Images()).To(HaveExactElements([]string{"myorg.io/local-repo/cluster-api-controller:v1.4.3"}))
109+
g.Expect(p.components.Images()).To(HaveExactElements([]string{"registry.k8s.io/cluster-api/cluster-api-controller:v1.4.3"}))
115110
g.Expect(p.components.Version()).To(Equal("v1.4.3"))
116111
}

0 commit comments

Comments
 (0)