diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta2/types.go b/cmd/kubeadm/app/apis/kubeadm/v1beta2/types.go index 2003851ac9c..327463430c6 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta2/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta2/types.go @@ -65,13 +65,13 @@ type ClusterConfiguration struct { metav1.TypeMeta `json:",inline"` // Etcd holds configuration for etcd. - Etcd Etcd `json:"etcd"` + Etcd Etcd `json:"etcd,omitempty"` // Networking holds configuration for the networking topology of the cluster. - Networking Networking `json:"networking"` + Networking Networking `json:"networking,omitempty"` // KubernetesVersion is the target version of the control plane. - KubernetesVersion string `json:"kubernetesVersion"` + KubernetesVersion string `json:"kubernetesVersion,omitempty"` // ControlPlaneEndpoint sets a stable IP address or DNS name for the control plane; it // can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port. @@ -84,7 +84,7 @@ type ClusterConfiguration struct { // control plane instances. // e.g. in environments with enforced node recycling, the ControlPlaneEndpoint // could be used for assigning a stable DNS to the control plane. - ControlPlaneEndpoint string `json:"controlPlaneEndpoint"` + ControlPlaneEndpoint string `json:"controlPlaneEndpoint,omitempty"` // APIServer contains extra settings for the API server control plane component APIServer APIServer `json:"apiServer,omitempty"` @@ -96,16 +96,16 @@ type ClusterConfiguration struct { Scheduler ControlPlaneComponent `json:"scheduler,omitempty"` // DNS defines the options for the DNS add-on installed in the cluster. - DNS DNS `json:"dns"` + DNS DNS `json:"dns,omitempty"` // CertificatesDir specifies where to store or look for all required certificates. - CertificatesDir string `json:"certificatesDir"` + CertificatesDir string `json:"certificatesDir,omitempty"` // ImageRepository sets the container registry to pull images from. // If empty, `k8s.gcr.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`) // `gcr.io/kubernetes-ci-images` will be used as a default for control plane components and for kube-proxy, while `k8s.gcr.io` // will be used for all the other images. - ImageRepository string `json:"imageRepository"` + ImageRepository string `json:"imageRepository,omitempty"` // UseHyperKubeImage controls if hyperkube should be used for Kubernetes components instead of their respective separate images UseHyperKubeImage bool `json:"useHyperKubeImage,omitempty"` @@ -188,11 +188,11 @@ type ClusterStatus struct { // APIEndpoint struct contains elements of API server instance deployed on a node. type APIEndpoint struct { // AdvertiseAddress sets the IP address for the API server to advertise. - AdvertiseAddress string `json:"advertiseAddress"` + AdvertiseAddress string `json:"advertiseAddress,omitempty"` // BindPort sets the secure port for the API Server to bind to. // Defaults to 6443. - BindPort int32 `json:"bindPort"` + BindPort int32 `json:"bindPort,omitempty"` } // NodeRegistrationOptions holds fields that relate to registering a new control-plane or node to the cluster, either via "kubeadm init" or "kubeadm join" @@ -209,7 +209,7 @@ type NodeRegistrationOptions struct { // Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process // it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your control-plane node, set this field to an // empty slice, i.e. `taints: {}` in the YAML file. This field is solely used for Node registration. - Taints []v1.Taint `json:"taints,omitempty"` + Taints []v1.Taint `json:"taints"` // KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file // kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap @@ -220,11 +220,11 @@ type NodeRegistrationOptions struct { // Networking contains elements describing cluster's networking configuration type Networking struct { // ServiceSubnet is the subnet used by k8s services. Defaults to "10.96.0.0/12". - ServiceSubnet string `json:"serviceSubnet"` + ServiceSubnet string `json:"serviceSubnet,omitempty"` // PodSubnet is the subnet used by pods. - PodSubnet string `json:"podSubnet"` + PodSubnet string `json:"podSubnet,omitempty"` // DNSDomain is the dns domain used by k8s services. Defaults to "cluster.local". - DNSDomain string `json:"dnsDomain"` + DNSDomain string `json:"dnsDomain,omitempty"` } // BootstrapToken describes one bootstrap token, stored as a Secret in the cluster @@ -306,12 +306,12 @@ type JoinConfiguration struct { metav1.TypeMeta `json:",inline"` // NodeRegistration holds fields that relate to registering the new control-plane node to the cluster - NodeRegistration NodeRegistrationOptions `json:"nodeRegistration"` + NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty"` // CACertPath is the path to the SSL certificate authority used to // secure comunications between node and control-plane. // Defaults to "/etc/kubernetes/pki/ca.crt". - CACertPath string `json:"caCertPath"` + CACertPath string `json:"caCertPath,omitempty"` // Discovery specifies the options for the kubelet to use during the TLS Bootstrap process Discovery Discovery `json:"discovery"` @@ -344,7 +344,7 @@ type Discovery struct { // TLSBootstrapToken is a token used for TLS bootstrapping. // If .BootstrapToken is set, this field is defaulted to .BootstrapToken.Token, but can be overridden. // If .File is set, this field **must be set** in case the KubeConfigFile does not contain any other authentication information - TLSBootstrapToken string `json:"tlsBootstrapToken"` + TLSBootstrapToken string `json:"tlsBootstrapToken,omitempty"` // Timeout modifies the discovery timeout Timeout *metav1.Duration `json:"timeout,omitempty"` @@ -372,7 +372,7 @@ type BootstrapTokenDiscovery struct { // UnsafeSkipCAVerification allows token-based discovery // without CA verification via CACertHashes. This can weaken // the security of kubeadm since other nodes can impersonate the control-plane. - UnsafeSkipCAVerification bool `json:"unsafeSkipCAVerification"` + UnsafeSkipCAVerification bool `json:"unsafeSkipCAVerification,omitempty"` } // FileDiscovery is used to specify a file or URL to a kubeconfig file from which to load cluster information diff --git a/cmd/kubeadm/app/cmd/upgrade/common_test.go b/cmd/kubeadm/app/cmd/upgrade/common_test.go index 91483e8694c..bb7f8d791ef 100644 --- a/cmd/kubeadm/app/cmd/upgrade/common_test.go +++ b/cmd/kubeadm/app/cmd/upgrade/common_test.go @@ -180,21 +180,15 @@ func TestPrintConfiguration(t *testing.T) { expectedBytes: []byte(`[upgrade/config] Configuration used: apiServer: {} apiVersion: kubeadm.k8s.io/v1beta2 - certificatesDir: "" - controlPlaneEndpoint: "" controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /some/path - imageRepository: "" kind: ClusterConfiguration kubernetesVersion: v1.7.1 - networking: - dnsDomain: "" - podSubnet: "" - serviceSubnet: "" + networking: {} scheduler: {} `), }, @@ -217,8 +211,6 @@ func TestPrintConfiguration(t *testing.T) { expectedBytes: []byte(`[upgrade/config] Configuration used: apiServer: {} apiVersion: kubeadm.k8s.io/v1beta2 - certificatesDir: "" - controlPlaneEndpoint: "" controllerManager: {} dns: type: CoreDNS @@ -229,12 +221,9 @@ func TestPrintConfiguration(t *testing.T) { endpoints: - https://one-etcd-instance:2379 keyFile: "" - imageRepository: "" kind: ClusterConfiguration kubernetesVersion: v1.7.1 networking: - dnsDomain: "" - podSubnet: "" serviceSubnet: 10.96.0.1/12 scheduler: {} `), diff --git a/cmd/kubeadm/app/util/config/BUILD b/cmd/kubeadm/app/util/config/BUILD index 38d14b17b50..1932744a4d2 100644 --- a/cmd/kubeadm/app/util/config/BUILD +++ b/cmd/kubeadm/app/util/config/BUILD @@ -68,6 +68,7 @@ go_test( "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//vendor/github.com/lithammer/dedent:go_default_library", "//vendor/github.com/pmezard/go-difflib/difflib:go_default_library", + "//vendor/sigs.k8s.io/yaml:go_default_library", ], ) diff --git a/cmd/kubeadm/app/util/config/initconfiguration_test.go b/cmd/kubeadm/app/util/config/initconfiguration_test.go index 51a4f7bee36..0cbc509e048 100644 --- a/cmd/kubeadm/app/util/config/initconfiguration_test.go +++ b/cmd/kubeadm/app/util/config/initconfiguration_test.go @@ -26,7 +26,11 @@ import ( "github.com/pmezard/go-difflib/difflib" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2" "k8s.io/kubernetes/cmd/kubeadm/app/constants" + "sigs.k8s.io/yaml" ) func diff(expected, actual []byte) string { @@ -283,3 +287,80 @@ apiVersion: foo.k8s.io/v1 }) } } + +func TestDefaultTaintsMarshaling(t *testing.T) { + tests := []struct { + desc string + cfg kubeadmapiv1beta2.InitConfiguration + expectedTaintCnt int + }{ + { + desc: "Uninitialized nodeRegistration field produces a single taint (the master one)", + cfg: kubeadmapiv1beta2.InitConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubeadm.k8s.io/v1beta2", + Kind: constants.InitConfigurationKind, + }, + }, + expectedTaintCnt: 1, + }, + { + desc: "Uninitialized taints field produces a single taint (the master one)", + cfg: kubeadmapiv1beta2.InitConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubeadm.k8s.io/v1beta2", + Kind: constants.InitConfigurationKind, + }, + NodeRegistration: kubeadmapiv1beta2.NodeRegistrationOptions{}, + }, + expectedTaintCnt: 1, + }, + { + desc: "Forsing taints to an empty slice produces no taints", + cfg: kubeadmapiv1beta2.InitConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubeadm.k8s.io/v1beta2", + Kind: constants.InitConfigurationKind, + }, + NodeRegistration: kubeadmapiv1beta2.NodeRegistrationOptions{ + Taints: []v1.Taint{}, + }, + }, + expectedTaintCnt: 0, + }, + { + desc: "Custom taints are used", + cfg: kubeadmapiv1beta2.InitConfiguration{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubeadm.k8s.io/v1beta2", + Kind: constants.InitConfigurationKind, + }, + NodeRegistration: kubeadmapiv1beta2.NodeRegistrationOptions{ + Taints: []v1.Taint{ + {Key: "taint1"}, + {Key: "taint2"}, + }, + }, + }, + expectedTaintCnt: 2, + }, + } + + for _, tc := range tests { + t.Run(tc.desc, func(t *testing.T) { + b, err := yaml.Marshal(tc.cfg) + if err != nil { + t.Fatalf("unexpected error while marshalling to YAML: %v", err) + } + + cfg, err := BytesToInitConfiguration(b) + if err != nil { + t.Fatalf("unexpected error of BytesToInitConfiguration: %v\nconfig: %s", err, string(b)) + } + + if tc.expectedTaintCnt != len(cfg.NodeRegistration.Taints) { + t.Fatalf("unexpected taints count\nexpected: %d\ngot: %d\ntaints: %v", tc.expectedTaintCnt, len(cfg.NodeRegistration.Taints), cfg.NodeRegistration.Taints) + } + }) + } +} diff --git a/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted.yaml b/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted.yaml index c6632e004bf..6de881fffd9 100644 --- a/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted.yaml +++ b/cmd/kubeadm/app/util/config/testdata/defaulting/node/defaulted.yaml @@ -11,3 +11,4 @@ kind: JoinConfiguration nodeRegistration: criSocket: /var/run/dockershim.sock name: thegopher + taints: null