Skip to content

Commit 9a84379

Browse files
committed
Adding tests for consistency
1 parent a94403e commit 9a84379

File tree

6 files changed

+502
-279
lines changed

6 files changed

+502
-279
lines changed

cmd/kubeadm/app/util/config/common_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ import (
2929

3030
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3131
"k8s.io/apimachinery/pkg/runtime/schema"
32+
"k8s.io/apimachinery/pkg/util/json"
3233
"k8s.io/apimachinery/pkg/util/version"
3334
apimachineryversion "k8s.io/apimachinery/pkg/version"
35+
"sigs.k8s.io/yaml"
3436

3537
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
3638
kubeadmapiv1old "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
@@ -41,6 +43,14 @@ import (
4143

4244
const KubeadmGroupName = "kubeadm.k8s.io"
4345

46+
var formats = []struct {
47+
name string
48+
marshal func(interface{}) ([]byte, error)
49+
}{
50+
{name: "JSON", marshal: json.Marshal},
51+
{name: "YAML", marshal: yaml.Marshal},
52+
}
53+
4454
func TestValidateSupportedVersion(t *testing.T) {
4555
tests := []struct {
4656
gvk schema.GroupVersionKind

cmd/kubeadm/app/util/config/initconfiguration_test.go

Lines changed: 202 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -17,110 +17,76 @@ limitations under the License.
1717
package config
1818

1919
import (
20-
"bytes"
2120
"fmt"
2221
"os"
2322
"path/filepath"
2423
"testing"
2524

25+
"github.com/google/go-cmp/cmp"
26+
"github.com/google/go-cmp/cmp/cmpopts"
27+
"github.com/lithammer/dedent"
28+
2629
v1 "k8s.io/api/core/v1"
2730
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28-
"sigs.k8s.io/yaml"
31+
"k8s.io/utils/ptr"
2932

30-
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
33+
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
3134
kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4"
3235
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
3336
)
3437

3538
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
4439
tmpdir, err := os.MkdirTemp("", "")
4540
if err != nil {
4641
t.Fatalf("Couldn't create tmpdir: %v", err)
4742
}
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{}
4951

50-
// cfgFiles is in cluster_test.go
51-
var tests = []struct {
52+
tests := []struct {
5253
name string
53-
fileContents []byte
54-
expectErr bool
55-
validate func(*testing.T, *kubeadm.InitConfiguration)
54+
cfgPath string
55+
fileContents string
56+
wantErr bool
5657
}{
5758
{
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,
7262
},
7363
{
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,
9071
},
9172
}
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)
11277
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)
11979
}
80+
defer func() {
81+
if err := os.RemoveAll(filePath); err != nil {
82+
t.Fatalf("Couldn't remove filePath: %v", err)
83+
}
84+
}()
12085
}
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)
12490
}
12591
})
12692
}
@@ -184,20 +150,167 @@ func TestDefaultTaintsMarshaling(t *testing.T) {
184150
}
185151

186152
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+
}
192159

193-
cfg, err := BytesToInitConfiguration(b, true)
194-
if err != nil {
195-
t.Fatalf("unexpected error of BytesToInitConfiguration: %v\nconfig: %s", err, string(b))
196-
}
160+
cfg, err := BytesToInitConfiguration(b, true)
161+
if err != nil {
162+
t.Fatalf("unexpected error of BytesToInitConfiguration: %v\nconfig: %s", err, string(b))
163+
}
197164

198-
if tc.expectedTaintCnt != len(cfg.NodeRegistration.Taints) {
199-
t.Fatalf("unexpected taints count\nexpected: %d\ngot: %d\ntaints: %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\nexpected: %d\ngot: %d\ntaints: %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\nError: %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+
}
202315
}
203316
}

0 commit comments

Comments
 (0)