@@ -17,110 +17,76 @@ limitations under the License.
17
17
package config
18
18
19
19
import (
20
- "bytes"
21
20
"fmt"
22
21
"os"
23
22
"path/filepath"
24
23
"testing"
25
24
25
+ "github.com/google/go-cmp/cmp"
26
+ "github.com/google/go-cmp/cmp/cmpopts"
27
+ "github.com/lithammer/dedent"
28
+
26
29
v1 "k8s.io/api/core/v1"
27
30
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28
- "sigs. k8s.io/yaml "
31
+ "k8s.io/utils/ptr "
29
32
30
- "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
33
+ kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
31
34
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4"
32
35
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
33
36
)
34
37
35
38
func TestLoadInitConfigurationFromFile (t * testing.T ) {
36
- certDir := "/tmp/foo"
37
- clusterCfg := []byte (fmt .Sprintf (`
38
- apiVersion: %s
39
- kind: ClusterConfiguration
40
- certificatesDir: %s
41
- kubernetesVersion: %s` , kubeadmapiv1 .SchemeGroupVersion .String (), certDir , constants .MinimumControlPlaneVersion .String ()))
42
-
43
- // Create temp folder for the test case
44
39
tmpdir , err := os .MkdirTemp ("" , "" )
45
40
if err != nil {
46
41
t .Fatalf ("Couldn't create tmpdir: %v" , err )
47
42
}
48
- defer os .RemoveAll (tmpdir )
43
+ defer func () {
44
+ if err := os .RemoveAll (tmpdir ); err != nil {
45
+ t .Fatalf ("Couldn't remove tmpdir: %v" , err )
46
+ }
47
+ }()
48
+ filename := "kubeadmConfig"
49
+ filePath := filepath .Join (tmpdir , filename )
50
+ options := LoadOrDefaultConfigurationOptions {}
49
51
50
- // cfgFiles is in cluster_test.go
51
- var tests = []struct {
52
+ tests := []struct {
52
53
name string
53
- fileContents [] byte
54
- expectErr bool
55
- validate func ( * testing. T , * kubeadm. InitConfiguration )
54
+ cfgPath string
55
+ fileContents string
56
+ wantErr bool
56
57
}{
57
58
{
58
- name : "v1beta3.partial1" ,
59
- fileContents : cfgFiles ["InitConfiguration_v1beta3" ],
60
- },
61
- {
62
- name : "v1beta3.partial2" ,
63
- fileContents : bytes .Join ([][]byte {
64
- cfgFiles ["InitConfiguration_v1beta3" ],
65
- clusterCfg ,
66
- }, []byte (constants .YAMLDocumentSeparator )),
67
- validate : func (t * testing.T , cfg * kubeadm.InitConfiguration ) {
68
- if cfg .ClusterConfiguration .CertificatesDir != certDir {
69
- t .Errorf ("CertificatesDir from ClusterConfiguration holds the wrong value, Expected: %v. Actual: %v" , certDir , cfg .ClusterConfiguration .CertificatesDir )
70
- }
71
- },
59
+ name : "Config file does not exists" ,
60
+ cfgPath : "tmp" ,
61
+ wantErr : true ,
72
62
},
73
63
{
74
- name : "v1beta3.full" ,
75
- fileContents : bytes .Join ([][]byte {
76
- cfgFiles ["InitConfiguration_v1beta3" ],
77
- cfgFiles ["ClusterConfiguration_v1beta3" ],
78
- cfgFiles ["Kube-proxy_componentconfig" ],
79
- cfgFiles ["Kubelet_componentconfig" ],
80
- }, []byte (constants .YAMLDocumentSeparator )),
81
- },
82
- {
83
- name : "v1beta4.full" ,
84
- fileContents : bytes .Join ([][]byte {
85
- cfgFiles ["InitConfiguration_v1beta4" ],
86
- cfgFiles ["ClusterConfiguration_v1beta4" ],
87
- cfgFiles ["Kube-proxy_componentconfig" ],
88
- cfgFiles ["Kubelet_componentconfig" ],
89
- }, []byte (constants .YAMLDocumentSeparator )),
64
+ name : "Valid kubeadm config" ,
65
+ cfgPath : filePath ,
66
+ fileContents : dedent .Dedent (`
67
+ apiVersion: kubeadm.k8s.io/v1beta4
68
+ kind: InitConfiguration
69
+ ` ),
70
+ wantErr : false ,
90
71
},
91
72
}
92
-
93
- for _ , rt := range tests {
94
- t .Run (rt .name , func (t2 * testing.T ) {
95
- cfgPath := filepath .Join (tmpdir , rt .name )
96
- err := os .WriteFile (cfgPath , rt .fileContents , 0644 )
97
- if err != nil {
98
- t .Errorf ("Couldn't create file: %v" , err )
99
- return
100
- }
101
-
102
- opts := LoadOrDefaultConfigurationOptions {
103
- SkipCRIDetect : true ,
104
- }
105
-
106
- obj , err := LoadInitConfigurationFromFile (cfgPath , opts )
107
- if rt .expectErr {
108
- if err == nil {
109
- t .Error ("Unexpected success" )
110
- }
111
- } else {
73
+ for _ , tt := range tests {
74
+ t .Run (tt .name , func (t * testing.T ) {
75
+ if tt .cfgPath == filePath {
76
+ err = os .WriteFile (tt .cfgPath , []byte (tt .fileContents ), 0644 )
112
77
if err != nil {
113
- t .Errorf ("Error reading file: %v" , err )
114
- return
115
- }
116
-
117
- if obj == nil {
118
- t .Error ("Unexpected nil return value" )
78
+ t .Fatalf ("Couldn't write content to file: %v" , err )
119
79
}
80
+ defer func () {
81
+ if err := os .RemoveAll (filePath ); err != nil {
82
+ t .Fatalf ("Couldn't remove filePath: %v" , err )
83
+ }
84
+ }()
120
85
}
121
- // exec additional validation on the returned value
122
- if rt .validate != nil {
123
- rt .validate (t , obj )
86
+
87
+ _ , err = LoadInitConfigurationFromFile (tt .cfgPath , options )
88
+ if (err != nil ) != tt .wantErr {
89
+ t .Errorf ("LoadInitConfigurationFromFile() error = %v, wantErr %v" , err , tt .wantErr )
124
90
}
125
91
})
126
92
}
@@ -184,20 +150,167 @@ func TestDefaultTaintsMarshaling(t *testing.T) {
184
150
}
185
151
186
152
for _ , tc := range tests {
187
- t .Run (tc .desc , func (t * testing.T ) {
188
- b , err := yaml .Marshal (tc .cfg )
189
- if err != nil {
190
- t .Fatalf ("unexpected error while marshalling to YAML: %v" , err )
191
- }
153
+ for _ , format := range formats {
154
+ t .Run (fmt .Sprintf ("%s_%s" , tc .desc , format .name ), func (t * testing.T ) {
155
+ b , err := format .marshal (tc .cfg )
156
+ if err != nil {
157
+ t .Fatalf ("unexpected error while marshalling to %s: %v" , format .name , err )
158
+ }
192
159
193
- cfg , err := BytesToInitConfiguration (b , true )
194
- if err != nil {
195
- t .Fatalf ("unexpected error of BytesToInitConfiguration: %v\n config: %s" , err , string (b ))
196
- }
160
+ cfg , err := BytesToInitConfiguration (b , true )
161
+ if err != nil {
162
+ t .Fatalf ("unexpected error of BytesToInitConfiguration: %v\n config: %s" , err , string (b ))
163
+ }
197
164
198
- if tc .expectedTaintCnt != len (cfg .NodeRegistration .Taints ) {
199
- t .Fatalf ("unexpected taints count\n expected: %d\n got: %d\n taints: %v" , tc .expectedTaintCnt , len (cfg .NodeRegistration .Taints ), cfg .NodeRegistration .Taints )
200
- }
201
- })
165
+ if tc .expectedTaintCnt != len (cfg .NodeRegistration .Taints ) {
166
+ t .Fatalf ("unexpected taints count\n expected: %d\n got: %d\n taints: %v" , tc .expectedTaintCnt , len (cfg .NodeRegistration .Taints ), cfg .NodeRegistration .Taints )
167
+ }
168
+ })
169
+ }
170
+ }
171
+ }
172
+
173
+ func TestBytesToInitConfiguration (t * testing.T ) {
174
+ tests := []struct {
175
+ name string
176
+ cfg interface {}
177
+ expectedCfg kubeadmapi.InitConfiguration
178
+ expectedError bool
179
+ skipCRIDetect bool
180
+ }{
181
+ {
182
+ name : "default config is set correctly" ,
183
+ cfg : kubeadmapiv1.InitConfiguration {
184
+ TypeMeta : metav1.TypeMeta {
185
+ APIVersion : kubeadmapiv1 .SchemeGroupVersion .String (),
186
+ Kind : constants .InitConfigurationKind ,
187
+ },
188
+ },
189
+ expectedCfg : kubeadmapi.InitConfiguration {
190
+ LocalAPIEndpoint : kubeadmapi.APIEndpoint {
191
+ AdvertiseAddress : "" ,
192
+ BindPort : 0 ,
193
+ },
194
+ NodeRegistration : kubeadmapi.NodeRegistrationOptions {
195
+ CRISocket : "unix:///var/run/containerd/containerd.sock" ,
196
+ Name : "" ,
197
+ Taints : []v1.Taint {
198
+ {
199
+ Key : "node-role.kubernetes.io/control-plane" ,
200
+ Effect : "NoSchedule" ,
201
+ },
202
+ },
203
+ ImagePullPolicy : "IfNotPresent" ,
204
+ ImagePullSerial : ptr .To (true ),
205
+ },
206
+ ClusterConfiguration : kubeadmapi.ClusterConfiguration {
207
+ Etcd : kubeadmapi.Etcd {
208
+ Local : & kubeadmapi.LocalEtcd {
209
+ DataDir : "/var/lib/etcd" ,
210
+ },
211
+ },
212
+ KubernetesVersion : "stable-1" ,
213
+ ImageRepository : kubeadmapiv1 .DefaultImageRepository ,
214
+ ClusterName : kubeadmapiv1 .DefaultClusterName ,
215
+ EncryptionAlgorithm : kubeadmapi .EncryptionAlgorithmType (kubeadmapiv1 .DefaultEncryptionAlgorithm ),
216
+ Networking : kubeadmapi.Networking {
217
+ ServiceSubnet : "10.96.0.0/12" ,
218
+ DNSDomain : "cluster.local" ,
219
+ },
220
+ CertificatesDir : "/etc/kubernetes/pki" ,
221
+ },
222
+ },
223
+ skipCRIDetect : true ,
224
+ },
225
+ {
226
+ name : "partial config with custom values" ,
227
+ cfg : kubeadmapiv1.InitConfiguration {
228
+ TypeMeta : metav1.TypeMeta {
229
+ APIVersion : kubeadmapiv1 .SchemeGroupVersion .String (),
230
+ Kind : constants .InitConfigurationKind ,
231
+ },
232
+ NodeRegistration : kubeadmapiv1.NodeRegistrationOptions {
233
+ Name : "test-node" ,
234
+ CRISocket : "unix:///var/run/containerd/containerd.sock" ,
235
+ },
236
+ },
237
+ expectedCfg : kubeadmapi.InitConfiguration {
238
+ LocalAPIEndpoint : kubeadmapi.APIEndpoint {
239
+ AdvertiseAddress : "" ,
240
+ BindPort : 0 ,
241
+ },
242
+ NodeRegistration : kubeadmapi.NodeRegistrationOptions {
243
+ CRISocket : "unix:///var/run/containerd/containerd.sock" ,
244
+ Name : "test-node" ,
245
+ Taints : []v1.Taint {
246
+ {
247
+ Key : "node-role.kubernetes.io/control-plane" ,
248
+ Effect : "NoSchedule" ,
249
+ },
250
+ },
251
+ ImagePullPolicy : "IfNotPresent" ,
252
+ ImagePullSerial : ptr .To (true ),
253
+ },
254
+ ClusterConfiguration : kubeadmapi.ClusterConfiguration {
255
+ Etcd : kubeadmapi.Etcd {
256
+ Local : & kubeadmapi.LocalEtcd {
257
+ DataDir : "/var/lib/etcd" ,
258
+ },
259
+ },
260
+ KubernetesVersion : "stable-1" ,
261
+ ImageRepository : kubeadmapiv1 .DefaultImageRepository ,
262
+ ClusterName : kubeadmapiv1 .DefaultClusterName ,
263
+ EncryptionAlgorithm : kubeadmapi .EncryptionAlgorithmType (kubeadmapiv1 .DefaultEncryptionAlgorithm ),
264
+ Networking : kubeadmapi.Networking {
265
+ ServiceSubnet : "10.96.0.0/12" ,
266
+ DNSDomain : "cluster.local" ,
267
+ },
268
+ CertificatesDir : "/etc/kubernetes/pki" ,
269
+ },
270
+ },
271
+ skipCRIDetect : true ,
272
+ },
273
+ {
274
+ name : "invalid configuration type" ,
275
+ cfg : kubeadmapiv1.UpgradeConfiguration {
276
+ TypeMeta : metav1.TypeMeta {
277
+ APIVersion : kubeadmapiv1 .SchemeGroupVersion .String (),
278
+ Kind : constants .UpgradeConfigurationKind ,
279
+ },
280
+ },
281
+ expectedError : true ,
282
+ skipCRIDetect : true ,
283
+ },
284
+ }
285
+
286
+ for _ , tc := range tests {
287
+ for _ , format := range formats {
288
+ t .Run (fmt .Sprintf ("%s_%s" , tc .name , format .name ), func (t * testing.T ) {
289
+ b , err := format .marshal (tc .cfg )
290
+ if err != nil {
291
+ t .Fatalf ("unexpected error marshaling %s: %v" , format .name , err )
292
+ }
293
+
294
+ cfg , err := BytesToInitConfiguration (b , tc .skipCRIDetect )
295
+ if (err != nil ) != tc .expectedError {
296
+ t .Fatalf ("expected error: %v, got error: %v\n Error: %v" , tc .expectedError , err != nil , err )
297
+ }
298
+
299
+ if ! tc .expectedError {
300
+ // Ignore dynamic fields that may be set during defaulting
301
+ diffOpts := []cmp.Option {
302
+ cmpopts .IgnoreFields (kubeadmapi.NodeRegistrationOptions {}, "Name" ),
303
+ cmpopts .IgnoreFields (kubeadmapi.InitConfiguration {}, "Timeouts" , "BootstrapTokens" , "LocalAPIEndpoint" ),
304
+ cmpopts .IgnoreFields (kubeadmapi.APIServer {}, "TimeoutForControlPlane" ),
305
+ cmpopts .IgnoreFields (kubeadmapi.ClusterConfiguration {}, "ComponentConfigs" , "KubernetesVersion" ,
306
+ "CertificateValidityPeriod" , "CACertificateValidityPeriod" ),
307
+ }
308
+
309
+ if diff := cmp .Diff (* cfg , tc .expectedCfg , diffOpts ... ); diff != "" {
310
+ t .Fatalf ("unexpected configuration difference (-want +got):\n %s" , diff )
311
+ }
312
+ }
313
+ })
314
+ }
202
315
}
203
316
}
0 commit comments