mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Merge pull request #92435 from rosti/kubeadm-cc-test-refactor
kubeadm: refactor and cleanup component config tests
This commit is contained in:
		@@ -45,12 +45,14 @@ go_test(
 | 
			
		||||
    srcs = [
 | 
			
		||||
        "checksums_test.go",
 | 
			
		||||
        "configset_test.go",
 | 
			
		||||
        "fakeconfig_test.go",
 | 
			
		||||
        "kubelet_test.go",
 | 
			
		||||
        "kubeproxy_test.go",
 | 
			
		||||
    ],
 | 
			
		||||
    embed = [":go_default_library"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//cmd/kubeadm/app/apis/kubeadm:go_default_library",
 | 
			
		||||
        "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
 | 
			
		||||
        "//cmd/kubeadm/app/apis/kubeadm/v1beta2:go_default_library",
 | 
			
		||||
        "//cmd/kubeadm/app/apis/output:go_default_library",
 | 
			
		||||
        "//cmd/kubeadm/app/constants:go_default_library",
 | 
			
		||||
@@ -59,7 +61,8 @@ go_test(
 | 
			
		||||
        "//staging/src/k8s.io/api/core/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/component-base/config/v1alpha1:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/kube-proxy/config/v1alpha1:go_default_library",
 | 
			
		||||
 
 | 
			
		||||
@@ -17,25 +17,26 @@ limitations under the License.
 | 
			
		||||
package componentconfigs
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/lithammer/dedent"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/version"
 | 
			
		||||
	clientsetfake "k8s.io/client-go/kubernetes/fake"
 | 
			
		||||
 | 
			
		||||
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
 | 
			
		||||
	outputapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/output"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
			
		||||
	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func testClusterCfg() *kubeadmapi.ClusterConfiguration {
 | 
			
		||||
	return &kubeadmapi.ClusterConfiguration{
 | 
			
		||||
		KubernetesVersion: constants.CurrentKubernetesVersion.String(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDefault(t *testing.T) {
 | 
			
		||||
	clusterCfg := &kubeadmapi.ClusterConfiguration{}
 | 
			
		||||
	clusterCfg := testClusterCfg()
 | 
			
		||||
	localAPIEndpoint := &kubeadmapi.APIEndpoint{}
 | 
			
		||||
	nodeRegOps := &kubeadmapi.NodeRegistrationOptions{}
 | 
			
		||||
 | 
			
		||||
@@ -47,39 +48,18 @@ func TestDefault(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestFromCluster(t *testing.T) {
 | 
			
		||||
	clusterCfg := &kubeadmapi.ClusterConfiguration{
 | 
			
		||||
		KubernetesVersion: constants.CurrentKubernetesVersion.String(),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	k8sVersion := version.MustParseGeneric(clusterCfg.KubernetesVersion)
 | 
			
		||||
 | 
			
		||||
	objects := []runtime.Object{
 | 
			
		||||
		&v1.ConfigMap{
 | 
			
		||||
			ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
				Name:      constants.KubeProxyConfigMap,
 | 
			
		||||
				Namespace: metav1.NamespaceSystem,
 | 
			
		||||
			},
 | 
			
		||||
			Data: map[string]string{
 | 
			
		||||
				constants.KubeProxyConfigMapKey: dedent.Dedent(`
 | 
			
		||||
					apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
					kind: KubeProxyConfiguration
 | 
			
		||||
				`),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		&v1.ConfigMap{
 | 
			
		||||
			ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
				Name:      constants.GetKubeletConfigMapName(k8sVersion),
 | 
			
		||||
				Namespace: metav1.NamespaceSystem,
 | 
			
		||||
			},
 | 
			
		||||
			Data: map[string]string{
 | 
			
		||||
				constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
					apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
					kind: KubeletConfiguration
 | 
			
		||||
				`),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		testKubeProxyConfigMap(`
 | 
			
		||||
			apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
			kind: KubeProxyConfiguration
 | 
			
		||||
		`),
 | 
			
		||||
		testKubeletConfigMap(`
 | 
			
		||||
			apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
			kind: KubeletConfiguration
 | 
			
		||||
		`),
 | 
			
		||||
	}
 | 
			
		||||
	client := clientsetfake.NewSimpleClientset(objects...)
 | 
			
		||||
	clusterCfg := testClusterCfg()
 | 
			
		||||
 | 
			
		||||
	if err := FetchFromCluster(clusterCfg, client); err != nil {
 | 
			
		||||
		t.Fatalf("FetchFromCluster failed: %v", err)
 | 
			
		||||
@@ -103,7 +83,7 @@ func TestFetchFromDocumentMap(t *testing.T) {
 | 
			
		||||
		t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	clusterCfg := &kubeadmapi.ClusterConfiguration{}
 | 
			
		||||
	clusterCfg := testClusterCfg()
 | 
			
		||||
	if err = FetchFromDocumentMap(clusterCfg, gvkmap); err != nil {
 | 
			
		||||
		t.Fatalf("FetchFromDocumentMap failed: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -112,542 +92,3 @@ func TestFetchFromDocumentMap(t *testing.T) {
 | 
			
		||||
		t.Fatalf("missmatch between supplied and loaded type numbers:\n\tgot: %d\n\texpected: %d", len(clusterCfg.ComponentConfigs), len(gvkmap))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func kubeproxyConfigMap(contents string) *v1.ConfigMap {
 | 
			
		||||
	return &v1.ConfigMap{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name:      constants.KubeProxyConfigMap,
 | 
			
		||||
			Namespace: metav1.NamespaceSystem,
 | 
			
		||||
		},
 | 
			
		||||
		Data: map[string]string{
 | 
			
		||||
			constants.KubeProxyConfigMapKey: dedent.Dedent(contents),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestFetchFromClusterWithLocalUpgrades(t *testing.T) {
 | 
			
		||||
	cases := []struct {
 | 
			
		||||
		desc          string
 | 
			
		||||
		obj           runtime.Object
 | 
			
		||||
		config        string
 | 
			
		||||
		expectedValue string
 | 
			
		||||
		expectedErr   bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			desc: "reconginzed cluster object without overwrite is used",
 | 
			
		||||
			obj: kubeproxyConfigMap(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
				hostnameOverride: foo
 | 
			
		||||
			`),
 | 
			
		||||
			expectedValue: "foo",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "reconginzed cluster object with overwrite is not used",
 | 
			
		||||
			obj: kubeproxyConfigMap(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
				hostnameOverride: foo
 | 
			
		||||
			`),
 | 
			
		||||
			config: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
				hostnameOverride: bar
 | 
			
		||||
			`),
 | 
			
		||||
			expectedValue: "bar",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "old config without overwrite returns an error",
 | 
			
		||||
			obj: kubeproxyConfigMap(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
				hostnameOverride: foo
 | 
			
		||||
			`),
 | 
			
		||||
			expectedErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "old config with recognized overwrite returns success",
 | 
			
		||||
			obj: kubeproxyConfigMap(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
				hostnameOverride: foo
 | 
			
		||||
			`),
 | 
			
		||||
			config: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
				hostnameOverride: bar
 | 
			
		||||
			`),
 | 
			
		||||
			expectedValue: "bar",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "old config with old overwrite returns an error",
 | 
			
		||||
			obj: kubeproxyConfigMap(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
				hostnameOverride: foo
 | 
			
		||||
			`),
 | 
			
		||||
			config: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
				hostnameOverride: bar
 | 
			
		||||
			`),
 | 
			
		||||
			expectedErr: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, test := range cases {
 | 
			
		||||
		t.Run(test.desc, func(t *testing.T) {
 | 
			
		||||
			clusterCfg := &kubeadmapi.ClusterConfiguration{
 | 
			
		||||
				KubernetesVersion: constants.CurrentKubernetesVersion.String(),
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			k8sVersion := version.MustParseGeneric(clusterCfg.KubernetesVersion)
 | 
			
		||||
 | 
			
		||||
			client := clientsetfake.NewSimpleClientset(
 | 
			
		||||
				test.obj,
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.GetKubeletConfigMapName(k8sVersion),
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
							kind: KubeletConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			)
 | 
			
		||||
 | 
			
		||||
			docmap, err := kubeadmutil.SplitYAMLDocuments([]byte(test.config))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			err = FetchFromClusterWithLocalOverwrites(clusterCfg, client, docmap)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				if !test.expectedErr {
 | 
			
		||||
					t.Errorf("unexpected failure: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				if test.expectedErr {
 | 
			
		||||
					t.Error("unexpected success")
 | 
			
		||||
				} else {
 | 
			
		||||
					kubeproxyCfg, ok := clusterCfg.ComponentConfigs[KubeProxyGroup]
 | 
			
		||||
					if !ok {
 | 
			
		||||
						t.Error("the config was reported as loaded, but was not in reality")
 | 
			
		||||
					} else {
 | 
			
		||||
						actualConfig, ok := kubeproxyCfg.(*kubeProxyConfig)
 | 
			
		||||
						if !ok {
 | 
			
		||||
							t.Error("the config is not of the expected type")
 | 
			
		||||
						} else if actualConfig.config.HostnameOverride != test.expectedValue {
 | 
			
		||||
							t.Errorf("unexpected value:\n\tgot: %q\n\texpected: %q", actualConfig.config.HostnameOverride, test.expectedValue)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGetVersionStates(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		desc        string
 | 
			
		||||
		objects     []runtime.Object
 | 
			
		||||
		substitutes string
 | 
			
		||||
		expected    []outputapi.ComponentConfigVersionState
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			desc: "Normal config",
 | 
			
		||||
			objects: []runtime.Object{
 | 
			
		||||
				kubeproxyConfigMap(`
 | 
			
		||||
					apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
					kind: KubeProxyConfiguration
 | 
			
		||||
				`),
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
							kind: KubeletConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expected: []outputapi.ComponentConfigVersionState{
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubeproxy.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha1",
 | 
			
		||||
					PreferredVersion:      "v1alpha1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubelet.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1beta1",
 | 
			
		||||
					PreferredVersion:      "v1beta1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "Normal config ignoring a current substitute",
 | 
			
		||||
			objects: []runtime.Object{
 | 
			
		||||
				kubeproxyConfigMap(`
 | 
			
		||||
					apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
					kind: KubeProxyConfiguration
 | 
			
		||||
				`),
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
							kind: KubeletConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			substitutes: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
			`),
 | 
			
		||||
			expected: []outputapi.ComponentConfigVersionState{
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubeproxy.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha1",
 | 
			
		||||
					PreferredVersion:      "v1alpha1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubelet.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1beta1",
 | 
			
		||||
					PreferredVersion:      "v1beta1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "Normal config with an old substitute",
 | 
			
		||||
			objects: []runtime.Object{
 | 
			
		||||
				kubeproxyConfigMap(`
 | 
			
		||||
					apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
					kind: KubeProxyConfiguration
 | 
			
		||||
				`),
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
							kind: KubeletConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			substitutes: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
			`),
 | 
			
		||||
			expected: []outputapi.ComponentConfigVersionState{
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubeproxy.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha0",
 | 
			
		||||
					PreferredVersion:      "v1alpha1",
 | 
			
		||||
					ManualUpgradeRequired: true,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubelet.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1beta1",
 | 
			
		||||
					PreferredVersion:      "v1beta1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "Old user supplied config",
 | 
			
		||||
			objects: []runtime.Object{
 | 
			
		||||
				kubeproxyConfigMap(`
 | 
			
		||||
					apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
					kind: KubeProxyConfiguration
 | 
			
		||||
				`),
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubelet.config.k8s.io/v1alpha1
 | 
			
		||||
							kind: KubeletConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expected: []outputapi.ComponentConfigVersionState{
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubeproxy.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha0",
 | 
			
		||||
					PreferredVersion:      "v1alpha1",
 | 
			
		||||
					ManualUpgradeRequired: true,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubelet.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha1",
 | 
			
		||||
					PreferredVersion:      "v1beta1",
 | 
			
		||||
					ManualUpgradeRequired: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "Old user supplied config with a proper substitute",
 | 
			
		||||
			objects: []runtime.Object{
 | 
			
		||||
				kubeproxyConfigMap(`
 | 
			
		||||
					apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
					kind: KubeProxyConfiguration
 | 
			
		||||
				`),
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubelet.config.k8s.io/v1alpha1
 | 
			
		||||
							kind: KubeletConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			substitutes: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
			`),
 | 
			
		||||
			expected: []outputapi.ComponentConfigVersionState{
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubeproxy.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha1",
 | 
			
		||||
					PreferredVersion:      "v1alpha1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubelet.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha1",
 | 
			
		||||
					PreferredVersion:      "v1beta1",
 | 
			
		||||
					ManualUpgradeRequired: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "Old user supplied config with an old substitute",
 | 
			
		||||
			objects: []runtime.Object{
 | 
			
		||||
				kubeproxyConfigMap(`
 | 
			
		||||
					apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
					kind: KubeProxyConfiguration
 | 
			
		||||
				`),
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubelet.config.k8s.io/v1alpha1
 | 
			
		||||
							kind: KubeletConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			substitutes: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
			`),
 | 
			
		||||
			expected: []outputapi.ComponentConfigVersionState{
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubeproxy.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha0",
 | 
			
		||||
					PreferredVersion:      "v1alpha1",
 | 
			
		||||
					ManualUpgradeRequired: true,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubelet.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha1",
 | 
			
		||||
					PreferredVersion:      "v1beta1",
 | 
			
		||||
					ManualUpgradeRequired: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "Old kubeadm generated config",
 | 
			
		||||
			objects: []runtime.Object{
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.KubeProxyConfigMap,
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
						Annotations: map[string]string{
 | 
			
		||||
							constants.ComponentConfigHashAnnotationKey: "sha256:8d3dfd7abcac205f6744d8e9db44505cce0c15b0a5395501e272fc18bd54c13c",
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeProxyConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
							kind: KubeProxyConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
							kind: KubeletConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expected: []outputapi.ComponentConfigVersionState{
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubeproxy.config.k8s.io",
 | 
			
		||||
					PreferredVersion:      "v1alpha1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubelet.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1beta1",
 | 
			
		||||
					PreferredVersion:      "v1beta1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "Old kubeadm generated config with a proper substitute",
 | 
			
		||||
			objects: []runtime.Object{
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.KubeProxyConfigMap,
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
						Annotations: map[string]string{
 | 
			
		||||
							constants.ComponentConfigHashAnnotationKey: "sha256:8d3dfd7abcac205f6744d8e9db44505cce0c15b0a5395501e272fc18bd54c13c",
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeProxyConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
							kind: KubeProxyConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
							kind: KubeletConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			substitutes: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
			`),
 | 
			
		||||
			expected: []outputapi.ComponentConfigVersionState{
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubeproxy.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha1",
 | 
			
		||||
					PreferredVersion:      "v1alpha1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubelet.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1beta1",
 | 
			
		||||
					PreferredVersion:      "v1beta1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			desc: "Old kubeadm generated config with an old substitute",
 | 
			
		||||
			objects: []runtime.Object{
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.KubeProxyConfigMap,
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
						Annotations: map[string]string{
 | 
			
		||||
							constants.ComponentConfigHashAnnotationKey: "sha256:8d3dfd7abcac205f6744d8e9db44505cce0c15b0a5395501e272fc18bd54c13c",
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeProxyConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
							kind: KubeProxyConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				&v1.ConfigMap{
 | 
			
		||||
					ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
						Name:      constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
 | 
			
		||||
						Namespace: metav1.NamespaceSystem,
 | 
			
		||||
					},
 | 
			
		||||
					Data: map[string]string{
 | 
			
		||||
						constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(`
 | 
			
		||||
							apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
							kind: KubeletConfiguration
 | 
			
		||||
						`),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			substitutes: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
			`),
 | 
			
		||||
			expected: []outputapi.ComponentConfigVersionState{
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubeproxy.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1alpha0",
 | 
			
		||||
					PreferredVersion:      "v1alpha1",
 | 
			
		||||
					ManualUpgradeRequired: true,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Group:                 "kubelet.config.k8s.io",
 | 
			
		||||
					CurrentVersion:        "v1beta1",
 | 
			
		||||
					PreferredVersion:      "v1beta1",
 | 
			
		||||
					ManualUpgradeRequired: false,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		t.Run(test.desc, func(t *testing.T) {
 | 
			
		||||
			docmap, err := kubeadmutil.SplitYAMLDocuments([]byte(test.substitutes))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			clusterCfg := &kubeadmapi.ClusterConfiguration{
 | 
			
		||||
				KubernetesVersion: constants.CurrentKubernetesVersion.String(),
 | 
			
		||||
			}
 | 
			
		||||
			client := clientsetfake.NewSimpleClientset(test.objects...)
 | 
			
		||||
			got, err := GetVersionStates(clusterCfg, client, docmap)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !reflect.DeepEqual(got, test.expected) {
 | 
			
		||||
				t.Fatalf("unexpected result:\n\texpected: %v\n\tgot: %v", test.expected, got)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										722
									
								
								cmd/kubeadm/app/componentconfigs/fakeconfig_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										722
									
								
								cmd/kubeadm/app/componentconfigs/fakeconfig_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,722 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2020 The Kubernetes Authors.
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package componentconfigs
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/lithammer/dedent"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
			
		||||
	clientset "k8s.io/client-go/kubernetes"
 | 
			
		||||
	clientsetfake "k8s.io/client-go/kubernetes/fake"
 | 
			
		||||
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
 | 
			
		||||
	kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
 | 
			
		||||
	kubeadmapiv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
 | 
			
		||||
	outputapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/output"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
			
		||||
	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// All tests in this file use an alternative set of `known` component configs.
 | 
			
		||||
// In this case it's just one known config and it's kubeadm's very own ClusterConfiguration.
 | 
			
		||||
// ClusterConfiguration is normally not managed by this package. It's only used, because of the following:
 | 
			
		||||
// - It's a versioned API that is under the control of kubeadm maintainers. This enables us to test
 | 
			
		||||
//   the componentconfigs package more thoroughly without having to have full and always up to date
 | 
			
		||||
//   knowledge about the config of another component.
 | 
			
		||||
// - Other components often introduce new fields in their configs without bumping up the config version.
 | 
			
		||||
//   This, often times, requires that the PR that introduces such new fields to touch kubeadm test code.
 | 
			
		||||
//   Doing so, requires more work on the part of developers and reviewers. When kubeadm moves out of k/k
 | 
			
		||||
//   this would allow for more sporadic breaks in kubeadm tests as PRs that merge in k/k and introduce
 | 
			
		||||
//   new fields won't be able to fix the tests in kubeadm.
 | 
			
		||||
// - If we implement tests for all common functionality using the config of another component and it gets
 | 
			
		||||
//   deprecated and/or we stop supporting it in production, we'll have to focus on a massive test refactoring
 | 
			
		||||
//   or just continue importing this config just for test use.
 | 
			
		||||
//
 | 
			
		||||
// Thus, to reduce maintenance costs without sacrificing test coverage, we introduce this mini-framework
 | 
			
		||||
// and set of tests here which replace the normal component configs with a single one (ClusterConfiguration)
 | 
			
		||||
// and test the component config independent logic of this package.
 | 
			
		||||
 | 
			
		||||
// clusterConfigHandler is the handler instance for the latest supported ClusterConfiguration to be used in tests
 | 
			
		||||
var clusterConfigHandler = handler{
 | 
			
		||||
	GroupVersion: kubeadmapiv1.SchemeGroupVersion,
 | 
			
		||||
	AddToScheme:  kubeadmapiv1.AddToScheme,
 | 
			
		||||
	CreateEmpty: func() kubeadmapi.ComponentConfig {
 | 
			
		||||
		return &clusterConfig{
 | 
			
		||||
			configBase: configBase{
 | 
			
		||||
				GroupVersion: kubeadmapiv1.SchemeGroupVersion,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	fromCluster: clusterConfigFromCluster,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func clusterConfigFromCluster(h *handler, clientset clientset.Interface, _ *kubeadmapi.ClusterConfiguration) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
	return h.fromConfigMap(clientset, constants.KubeadmConfigConfigMap, constants.ClusterConfigurationConfigMapKey, true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type clusterConfig struct {
 | 
			
		||||
	configBase
 | 
			
		||||
	config kubeadmapiv1.ClusterConfiguration
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cc *clusterConfig) DeepCopy() kubeadmapi.ComponentConfig {
 | 
			
		||||
	result := &clusterConfig{}
 | 
			
		||||
	cc.configBase.DeepCopyInto(&result.configBase)
 | 
			
		||||
	cc.config.DeepCopyInto(&result.config)
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cc *clusterConfig) Marshal() ([]byte, error) {
 | 
			
		||||
	return cc.configBase.Marshal(&cc.config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cc *clusterConfig) Unmarshal(docmap kubeadmapi.DocumentMap) error {
 | 
			
		||||
	return cc.configBase.Unmarshal(docmap, &cc.config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cc *clusterConfig) Default(_ *kubeadmapi.ClusterConfiguration, _ *kubeadmapi.APIEndpoint, _ *kubeadmapi.NodeRegistrationOptions) {
 | 
			
		||||
	cc.config.ClusterName = "foo"
 | 
			
		||||
	cc.config.KubernetesVersion = "bar"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fakeKnown replaces temporarily during the execution of each test here known (in configset.go)
 | 
			
		||||
var fakeKnown = []*handler{
 | 
			
		||||
	&clusterConfigHandler,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// fakeKnownContext is the func that houses the fake component config context.
 | 
			
		||||
// NOTE: It does not support concurrent test execution!
 | 
			
		||||
func fakeKnownContext(f func()) {
 | 
			
		||||
	// Save the real values
 | 
			
		||||
	realKnown := known
 | 
			
		||||
	realScheme := Scheme
 | 
			
		||||
	realCodecs := Codecs
 | 
			
		||||
 | 
			
		||||
	// Replace the context with the fake context
 | 
			
		||||
	known = fakeKnown
 | 
			
		||||
	Scheme = kubeadmscheme.Scheme
 | 
			
		||||
	Codecs = kubeadmscheme.Codecs
 | 
			
		||||
 | 
			
		||||
	// Upon function exit, restore the real values
 | 
			
		||||
	defer func() {
 | 
			
		||||
		known = realKnown
 | 
			
		||||
		Scheme = realScheme
 | 
			
		||||
		Codecs = realCodecs
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	// Call f in the fake context
 | 
			
		||||
	f()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// testClusterConfigMap is a short hand for creating and possibly signing a test config map.
 | 
			
		||||
// This produces config maps that can be loaded by clusterConfigFromCluster
 | 
			
		||||
func testClusterConfigMap(yaml string, signIt bool) *v1.ConfigMap {
 | 
			
		||||
	cm := &v1.ConfigMap{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name:      constants.KubeadmConfigConfigMap,
 | 
			
		||||
			Namespace: metav1.NamespaceSystem,
 | 
			
		||||
		},
 | 
			
		||||
		Data: map[string]string{
 | 
			
		||||
			constants.ClusterConfigurationConfigMapKey: dedent.Dedent(yaml),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if signIt {
 | 
			
		||||
		SignConfigMap(cm)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cm
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// oldClusterConfigVersion is used as an old unsupported version in tests throughout this file
 | 
			
		||||
const oldClusterConfigVersion = "v1alpha1"
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// currentClusterConfigVersion represents the current actively supported version of ClusterConfiguration
 | 
			
		||||
	currentClusterConfigVersion = kubeadmapiv1.SchemeGroupVersion.Version
 | 
			
		||||
 | 
			
		||||
	// currentFooClusterConfig is a minimal currently supported ClusterConfiguration
 | 
			
		||||
	// with a well known value of clusterName (in this case `foo`)
 | 
			
		||||
	currentFooClusterConfig = fmt.Sprintf(`
 | 
			
		||||
		apiVersion: %s
 | 
			
		||||
		kind: ClusterConfiguration
 | 
			
		||||
		clusterName: foo
 | 
			
		||||
	`, kubeadmapiv1.SchemeGroupVersion)
 | 
			
		||||
 | 
			
		||||
	// oldFooClusterConfig is a minimal unsupported ClusterConfiguration
 | 
			
		||||
	// with a well known value of clusterName (in this case `foo`)
 | 
			
		||||
	oldFooClusterConfig = fmt.Sprintf(`
 | 
			
		||||
		apiVersion: %s/%s
 | 
			
		||||
		kind: ClusterConfiguration
 | 
			
		||||
		clusterName: foo
 | 
			
		||||
	`, kubeadmapiv1.GroupName, oldClusterConfigVersion)
 | 
			
		||||
 | 
			
		||||
	// currentBarClusterConfig is a minimal currently supported ClusterConfiguration
 | 
			
		||||
	// with a well known value of clusterName (in this case `bar`)
 | 
			
		||||
	currentBarClusterConfig = fmt.Sprintf(`
 | 
			
		||||
		apiVersion: %s
 | 
			
		||||
		kind: ClusterConfiguration
 | 
			
		||||
		clusterName: bar
 | 
			
		||||
	`, kubeadmapiv1.SchemeGroupVersion)
 | 
			
		||||
 | 
			
		||||
	// oldBarClusterConfig is a minimal unsupported ClusterConfiguration
 | 
			
		||||
	// with a well known value of clusterName (in this case `bar`)
 | 
			
		||||
	oldBarClusterConfig = fmt.Sprintf(`
 | 
			
		||||
		apiVersion: %s/%s
 | 
			
		||||
		kind: ClusterConfiguration
 | 
			
		||||
		clusterName: bar
 | 
			
		||||
	`, kubeadmapiv1.GroupName, oldClusterConfigVersion)
 | 
			
		||||
 | 
			
		||||
	// This is the "minimal" valid config that can be unmarshalled to and from YAML.
 | 
			
		||||
	// Due to same static defaulting it's not exactly small in size.
 | 
			
		||||
	validUnmarshallableClusterConfig = struct {
 | 
			
		||||
		yaml string
 | 
			
		||||
		obj  kubeadmapiv1.ClusterConfiguration
 | 
			
		||||
	}{
 | 
			
		||||
		yaml: dedent.Dedent(`
 | 
			
		||||
			apiServer:
 | 
			
		||||
			  timeoutForControlPlane: 4m
 | 
			
		||||
			apiVersion: kubeadm.k8s.io/v1beta2
 | 
			
		||||
			certificatesDir: /etc/kubernetes/pki
 | 
			
		||||
			clusterName: LeCluster
 | 
			
		||||
			controllerManager: {}
 | 
			
		||||
			dns:
 | 
			
		||||
			  type: CoreDNS
 | 
			
		||||
			etcd:
 | 
			
		||||
			  local:
 | 
			
		||||
			    dataDir: /var/lib/etcd
 | 
			
		||||
			imageRepository: k8s.gcr.io
 | 
			
		||||
			kind: ClusterConfiguration
 | 
			
		||||
			kubernetesVersion: 1.2.3
 | 
			
		||||
			networking:
 | 
			
		||||
			  dnsDomain: cluster.local
 | 
			
		||||
			  serviceSubnet: 10.96.0.0/12
 | 
			
		||||
			scheduler: {}
 | 
			
		||||
		`),
 | 
			
		||||
		obj: kubeadmapiv1.ClusterConfiguration{
 | 
			
		||||
			TypeMeta: metav1.TypeMeta{
 | 
			
		||||
				APIVersion: kubeadmapiv1.SchemeGroupVersion.String(),
 | 
			
		||||
				Kind:       "ClusterConfiguration",
 | 
			
		||||
			},
 | 
			
		||||
			ClusterName:       "LeCluster",
 | 
			
		||||
			KubernetesVersion: "1.2.3",
 | 
			
		||||
			CertificatesDir:   "/etc/kubernetes/pki",
 | 
			
		||||
			ImageRepository:   "k8s.gcr.io",
 | 
			
		||||
			Networking: kubeadmapiv1.Networking{
 | 
			
		||||
				DNSDomain:     "cluster.local",
 | 
			
		||||
				ServiceSubnet: "10.96.0.0/12",
 | 
			
		||||
			},
 | 
			
		||||
			DNS: kubeadmapiv1.DNS{
 | 
			
		||||
				Type: kubeadmapiv1.CoreDNS,
 | 
			
		||||
			},
 | 
			
		||||
			Etcd: kubeadmapiv1.Etcd{
 | 
			
		||||
				Local: &kubeadmapiv1.LocalEtcd{
 | 
			
		||||
					DataDir: "/var/lib/etcd",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			APIServer: kubeadmapiv1.APIServer{
 | 
			
		||||
				TimeoutForControlPlane: &metav1.Duration{
 | 
			
		||||
					Duration: 4 * time.Minute,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestConfigBaseMarshal(t *testing.T) {
 | 
			
		||||
	fakeKnownContext(func() {
 | 
			
		||||
		cfg := &clusterConfig{
 | 
			
		||||
			configBase: configBase{
 | 
			
		||||
				GroupVersion: kubeadmapiv1.SchemeGroupVersion,
 | 
			
		||||
			},
 | 
			
		||||
			config: kubeadmapiv1.ClusterConfiguration{
 | 
			
		||||
				TypeMeta: metav1.TypeMeta{
 | 
			
		||||
					APIVersion: kubeadmapiv1.SchemeGroupVersion.String(),
 | 
			
		||||
					Kind:       "ClusterConfiguration",
 | 
			
		||||
				},
 | 
			
		||||
				ClusterName:       "LeCluster",
 | 
			
		||||
				KubernetesVersion: "1.2.3",
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		b, err := cfg.Marshal()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("Marshal failed: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		got := strings.TrimSpace(string(b))
 | 
			
		||||
		expected := strings.TrimSpace(dedent.Dedent(`
 | 
			
		||||
			apiServer: {}
 | 
			
		||||
			apiVersion: kubeadm.k8s.io/v1beta2
 | 
			
		||||
			clusterName: LeCluster
 | 
			
		||||
			controllerManager: {}
 | 
			
		||||
			dns:
 | 
			
		||||
			  type: ""
 | 
			
		||||
			etcd: {}
 | 
			
		||||
			kind: ClusterConfiguration
 | 
			
		||||
			kubernetesVersion: 1.2.3
 | 
			
		||||
			networking: {}
 | 
			
		||||
			scheduler: {}
 | 
			
		||||
		`))
 | 
			
		||||
 | 
			
		||||
		if expected != got {
 | 
			
		||||
			t.Fatalf("Missmatch between expected and got:\nExpected:\n%s\n---\nGot:\n%s", expected, got)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestConfigBaseUnmarshal(t *testing.T) {
 | 
			
		||||
	fakeKnownContext(func() {
 | 
			
		||||
		expected := &clusterConfig{
 | 
			
		||||
			configBase: configBase{
 | 
			
		||||
				GroupVersion: kubeadmapiv1.SchemeGroupVersion,
 | 
			
		||||
			},
 | 
			
		||||
			config: validUnmarshallableClusterConfig.obj,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		gvkmap, err := kubeadmutil.SplitYAMLDocuments([]byte(validUnmarshallableClusterConfig.yaml))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		got := &clusterConfig{
 | 
			
		||||
			configBase: configBase{
 | 
			
		||||
				GroupVersion: kubeadmapiv1.SchemeGroupVersion,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		if err = got.Unmarshal(gvkmap); err != nil {
 | 
			
		||||
			t.Fatalf("unexpected failure of Unmarshal: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !reflect.DeepEqual(got, expected) {
 | 
			
		||||
			t.Fatalf("Missmatch between expected and got:\nExpected:\n%v\n---\nGot:\n%v", expected, got)
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGeneratedConfigFromCluster(t *testing.T) {
 | 
			
		||||
	fakeKnownContext(func() {
 | 
			
		||||
		testYAML := dedent.Dedent(`
 | 
			
		||||
			apiVersion: kubeadm.k8s.io/v1beta2
 | 
			
		||||
			kind: ClusterConfiguration
 | 
			
		||||
		`)
 | 
			
		||||
		testYAMLHash := fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(testYAML)))
 | 
			
		||||
		// The SHA256 sum of "The quick brown fox jumps over the lazy dog"
 | 
			
		||||
		const mismatchHash = "sha256:d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
 | 
			
		||||
		tests := []struct {
 | 
			
		||||
			name         string
 | 
			
		||||
			hash         string
 | 
			
		||||
			userSupplied bool
 | 
			
		||||
		}{
 | 
			
		||||
			{
 | 
			
		||||
				name: "Matching hash means generated config",
 | 
			
		||||
				hash: testYAMLHash,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				name:         "Missmatching hash means user supplied config",
 | 
			
		||||
				hash:         mismatchHash,
 | 
			
		||||
				userSupplied: true,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				name:         "No hash means user supplied config",
 | 
			
		||||
				userSupplied: true,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
		for _, test := range tests {
 | 
			
		||||
			t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
				configMap := testClusterConfigMap(testYAML, false)
 | 
			
		||||
				if test.hash != "" {
 | 
			
		||||
					configMap.Annotations = map[string]string{
 | 
			
		||||
						constants.ComponentConfigHashAnnotationKey: test.hash,
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				client := clientsetfake.NewSimpleClientset(configMap)
 | 
			
		||||
				cfg, err := clusterConfigHandler.FromCluster(client, testClusterCfg())
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatalf("unexpected failure of FromCluster: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				got := cfg.IsUserSupplied()
 | 
			
		||||
				if got != test.userSupplied {
 | 
			
		||||
					t.Fatalf("mismatch between expected and got:\n\tExpected: %t\n\tGot: %t", test.userSupplied, got)
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// runClusterConfigFromTest holds common test case data and evaluation code for handler.From* functions
 | 
			
		||||
func runClusterConfigFromTest(t *testing.T, perform func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error)) {
 | 
			
		||||
	fakeKnownContext(func() {
 | 
			
		||||
		tests := []struct {
 | 
			
		||||
			name      string
 | 
			
		||||
			in        string
 | 
			
		||||
			out       *clusterConfig
 | 
			
		||||
			expectErr bool
 | 
			
		||||
		}{
 | 
			
		||||
			{
 | 
			
		||||
				name: "Empty document map should return nothing successfully",
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				name: "Non-empty document map without the proper API group returns nothing successfully",
 | 
			
		||||
				in: dedent.Dedent(`
 | 
			
		||||
					apiVersion: api.example.com/v1
 | 
			
		||||
					kind: Configuration
 | 
			
		||||
				`),
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				name: "Old config version returns an error",
 | 
			
		||||
				in: dedent.Dedent(`
 | 
			
		||||
					apiVersion: kubeadm.k8s.io/v1alpha1
 | 
			
		||||
					kind: ClusterConfiguration
 | 
			
		||||
				`),
 | 
			
		||||
				expectErr: true,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				name: "Unknown kind returns an error",
 | 
			
		||||
				in: dedent.Dedent(`
 | 
			
		||||
					apiVersion: kubeadm.k8s.io/v1beta2
 | 
			
		||||
					kind: Configuration
 | 
			
		||||
				`),
 | 
			
		||||
				expectErr: true,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				name: "Valid config gets loaded",
 | 
			
		||||
				in:   validUnmarshallableClusterConfig.yaml,
 | 
			
		||||
				out: &clusterConfig{
 | 
			
		||||
					configBase: configBase{
 | 
			
		||||
						GroupVersion: clusterConfigHandler.GroupVersion,
 | 
			
		||||
						userSupplied: true,
 | 
			
		||||
					},
 | 
			
		||||
					config: validUnmarshallableClusterConfig.obj,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				name: "Valid config gets loaded even if coupled with an extra document",
 | 
			
		||||
				in:   "apiVersion: api.example.com/v1\nkind: Configuration\n---\n" + validUnmarshallableClusterConfig.yaml,
 | 
			
		||||
				out: &clusterConfig{
 | 
			
		||||
					configBase: configBase{
 | 
			
		||||
						GroupVersion: clusterConfigHandler.GroupVersion,
 | 
			
		||||
						userSupplied: true,
 | 
			
		||||
					},
 | 
			
		||||
					config: validUnmarshallableClusterConfig.obj,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, test := range tests {
 | 
			
		||||
			t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
				componentCfg, err := perform(t, test.in)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					if !test.expectErr {
 | 
			
		||||
						t.Errorf("unexpected failure: %v", err)
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					if test.expectErr {
 | 
			
		||||
						t.Error("unexpected success")
 | 
			
		||||
					} else {
 | 
			
		||||
						if componentCfg == nil {
 | 
			
		||||
							if test.out != nil {
 | 
			
		||||
								t.Error("unexpected nil result")
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							if got, ok := componentCfg.(*clusterConfig); !ok {
 | 
			
		||||
								t.Error("different result type")
 | 
			
		||||
							} else {
 | 
			
		||||
								if test.out == nil {
 | 
			
		||||
									t.Errorf("unexpected result: %v", got)
 | 
			
		||||
								} else {
 | 
			
		||||
									if !reflect.DeepEqual(test.out, got) {
 | 
			
		||||
										t.Errorf("missmatch between expected and got:\nExpected:\n%v\n---\nGot:\n%v", test.out, got)
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestLoadingFromDocumentMap(t *testing.T) {
 | 
			
		||||
	runClusterConfigFromTest(t, func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
		gvkmap, err := kubeadmutil.SplitYAMLDocuments([]byte(in))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return clusterConfigHandler.FromDocumentMap(gvkmap)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestLoadingFromCluster(t *testing.T) {
 | 
			
		||||
	runClusterConfigFromTest(t, func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
		client := clientsetfake.NewSimpleClientset(
 | 
			
		||||
			testClusterConfigMap(in, false),
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		return clusterConfigHandler.FromCluster(client, testClusterCfg())
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestFetchFromClusterWithLocalOverwrites(t *testing.T) {
 | 
			
		||||
	fakeKnownContext(func() {
 | 
			
		||||
		cases := []struct {
 | 
			
		||||
			desc          string
 | 
			
		||||
			obj           runtime.Object
 | 
			
		||||
			config        string
 | 
			
		||||
			expectedValue string
 | 
			
		||||
			isNotLoaded   bool
 | 
			
		||||
			expectedErr   bool
 | 
			
		||||
		}{
 | 
			
		||||
			{
 | 
			
		||||
				desc:          "appropriate cluster object without overwrite is used",
 | 
			
		||||
				obj:           testClusterConfigMap(currentFooClusterConfig, false),
 | 
			
		||||
				expectedValue: "foo",
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:          "appropriate cluster object with appropriate overwrite is overwritten",
 | 
			
		||||
				obj:           testClusterConfigMap(currentFooClusterConfig, false),
 | 
			
		||||
				config:        dedent.Dedent(currentBarClusterConfig),
 | 
			
		||||
				expectedValue: "bar",
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:        "appropriate cluster object with old overwrite returns an error",
 | 
			
		||||
				obj:         testClusterConfigMap(currentFooClusterConfig, false),
 | 
			
		||||
				config:      dedent.Dedent(oldBarClusterConfig),
 | 
			
		||||
				expectedErr: true,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:        "old config without overwrite returns an error",
 | 
			
		||||
				obj:         testClusterConfigMap(oldFooClusterConfig, false),
 | 
			
		||||
				expectedErr: true,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:          "old config with appropriate overwrite returns the substitute",
 | 
			
		||||
				obj:           testClusterConfigMap(oldFooClusterConfig, false),
 | 
			
		||||
				config:        dedent.Dedent(currentBarClusterConfig),
 | 
			
		||||
				expectedValue: "bar",
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:        "old config with old overwrite returns an error",
 | 
			
		||||
				obj:         testClusterConfigMap(oldFooClusterConfig, false),
 | 
			
		||||
				config:      dedent.Dedent(oldBarClusterConfig),
 | 
			
		||||
				expectedErr: true,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:          "appropriate signed cluster object without overwrite is used",
 | 
			
		||||
				obj:           testClusterConfigMap(currentFooClusterConfig, true),
 | 
			
		||||
				expectedValue: "foo",
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:          "appropriate signed cluster object with appropriate overwrite is overwritten",
 | 
			
		||||
				obj:           testClusterConfigMap(currentFooClusterConfig, true),
 | 
			
		||||
				config:        dedent.Dedent(currentBarClusterConfig),
 | 
			
		||||
				expectedValue: "bar",
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:        "appropriate signed cluster object with old overwrite returns an error",
 | 
			
		||||
				obj:         testClusterConfigMap(currentFooClusterConfig, true),
 | 
			
		||||
				config:      dedent.Dedent(oldBarClusterConfig),
 | 
			
		||||
				expectedErr: true,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:        "old signed config without an overwrite is not loaded",
 | 
			
		||||
				obj:         testClusterConfigMap(oldFooClusterConfig, true),
 | 
			
		||||
				isNotLoaded: true,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:          "old signed config with appropriate overwrite returns the substitute",
 | 
			
		||||
				obj:           testClusterConfigMap(oldFooClusterConfig, true),
 | 
			
		||||
				config:        dedent.Dedent(currentBarClusterConfig),
 | 
			
		||||
				expectedValue: "bar",
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:        "old signed config with old overwrite returns an error",
 | 
			
		||||
				obj:         testClusterConfigMap(oldFooClusterConfig, true),
 | 
			
		||||
				config:      dedent.Dedent(oldBarClusterConfig),
 | 
			
		||||
				expectedErr: true,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, test := range cases {
 | 
			
		||||
			t.Run(test.desc, func(t *testing.T) {
 | 
			
		||||
				client := clientsetfake.NewSimpleClientset(test.obj)
 | 
			
		||||
 | 
			
		||||
				docmap, err := kubeadmutil.SplitYAMLDocuments([]byte(test.config))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				clusterCfg := testClusterCfg()
 | 
			
		||||
 | 
			
		||||
				err = FetchFromClusterWithLocalOverwrites(clusterCfg, client, docmap)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					if !test.expectedErr {
 | 
			
		||||
						t.Errorf("unexpected failure: %v", err)
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					if test.expectedErr {
 | 
			
		||||
						t.Error("unexpected success")
 | 
			
		||||
					} else {
 | 
			
		||||
						clusterCfg, ok := clusterCfg.ComponentConfigs[kubeadmapiv1.GroupName]
 | 
			
		||||
						if !ok {
 | 
			
		||||
							if !test.isNotLoaded {
 | 
			
		||||
								t.Error("no config was loaded when it should have been")
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							actualConfig, ok := clusterCfg.(*clusterConfig)
 | 
			
		||||
							if !ok {
 | 
			
		||||
								t.Error("the config is not of the expected type")
 | 
			
		||||
							} else if actualConfig.config.ClusterName != test.expectedValue {
 | 
			
		||||
								t.Errorf("unexpected value:\n\tgot: %q\n\texpected: %q", actualConfig.config.ClusterName, test.expectedValue)
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGetVersionStates(t *testing.T) {
 | 
			
		||||
	fakeKnownContext(func() {
 | 
			
		||||
		versionStateCurrent := outputapi.ComponentConfigVersionState{
 | 
			
		||||
			Group:            kubeadmapiv1.GroupName,
 | 
			
		||||
			CurrentVersion:   currentClusterConfigVersion,
 | 
			
		||||
			PreferredVersion: currentClusterConfigVersion,
 | 
			
		||||
		}
 | 
			
		||||
		versionStateOld := outputapi.ComponentConfigVersionState{
 | 
			
		||||
			Group:                 kubeadmapiv1.GroupName,
 | 
			
		||||
			CurrentVersion:        oldClusterConfigVersion,
 | 
			
		||||
			PreferredVersion:      currentClusterConfigVersion,
 | 
			
		||||
			ManualUpgradeRequired: true,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cases := []struct {
 | 
			
		||||
			desc     string
 | 
			
		||||
			obj      runtime.Object
 | 
			
		||||
			config   string
 | 
			
		||||
			expected outputapi.ComponentConfigVersionState
 | 
			
		||||
		}{
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "appropriate cluster object without overwrite",
 | 
			
		||||
				obj:      testClusterConfigMap(currentFooClusterConfig, false),
 | 
			
		||||
				expected: versionStateCurrent,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "appropriate cluster object with appropriate overwrite",
 | 
			
		||||
				obj:      testClusterConfigMap(currentFooClusterConfig, false),
 | 
			
		||||
				config:   dedent.Dedent(currentBarClusterConfig),
 | 
			
		||||
				expected: versionStateCurrent,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "appropriate cluster object with old overwrite",
 | 
			
		||||
				obj:      testClusterConfigMap(currentFooClusterConfig, false),
 | 
			
		||||
				config:   dedent.Dedent(oldBarClusterConfig),
 | 
			
		||||
				expected: versionStateOld,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "old config without overwrite returns an error",
 | 
			
		||||
				obj:      testClusterConfigMap(oldFooClusterConfig, false),
 | 
			
		||||
				expected: versionStateOld,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "old config with appropriate overwrite",
 | 
			
		||||
				obj:      testClusterConfigMap(oldFooClusterConfig, false),
 | 
			
		||||
				config:   dedent.Dedent(currentBarClusterConfig),
 | 
			
		||||
				expected: versionStateCurrent,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "old config with old overwrite",
 | 
			
		||||
				obj:      testClusterConfigMap(oldFooClusterConfig, false),
 | 
			
		||||
				config:   dedent.Dedent(oldBarClusterConfig),
 | 
			
		||||
				expected: versionStateOld,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "appropriate signed cluster object without overwrite",
 | 
			
		||||
				obj:      testClusterConfigMap(currentFooClusterConfig, true),
 | 
			
		||||
				expected: versionStateCurrent,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "appropriate signed cluster object with appropriate overwrite",
 | 
			
		||||
				obj:      testClusterConfigMap(currentFooClusterConfig, true),
 | 
			
		||||
				config:   dedent.Dedent(currentBarClusterConfig),
 | 
			
		||||
				expected: versionStateCurrent,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "appropriate signed cluster object with old overwrit",
 | 
			
		||||
				obj:      testClusterConfigMap(currentFooClusterConfig, true),
 | 
			
		||||
				config:   dedent.Dedent(oldBarClusterConfig),
 | 
			
		||||
				expected: versionStateOld,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc: "old signed config without an overwrite",
 | 
			
		||||
				obj:  testClusterConfigMap(oldFooClusterConfig, true),
 | 
			
		||||
				expected: outputapi.ComponentConfigVersionState{
 | 
			
		||||
					Group:            kubeadmapiv1.GroupName,
 | 
			
		||||
					CurrentVersion:   "", // The config is treated as if it's missing
 | 
			
		||||
					PreferredVersion: currentClusterConfigVersion,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "old signed config with appropriate overwrite",
 | 
			
		||||
				obj:      testClusterConfigMap(oldFooClusterConfig, true),
 | 
			
		||||
				config:   dedent.Dedent(currentBarClusterConfig),
 | 
			
		||||
				expected: versionStateCurrent,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				desc:     "old signed config with old overwrite",
 | 
			
		||||
				obj:      testClusterConfigMap(oldFooClusterConfig, true),
 | 
			
		||||
				config:   dedent.Dedent(oldBarClusterConfig),
 | 
			
		||||
				expected: versionStateOld,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, test := range cases {
 | 
			
		||||
			t.Run(test.desc, func(t *testing.T) {
 | 
			
		||||
				client := clientsetfake.NewSimpleClientset(test.obj)
 | 
			
		||||
 | 
			
		||||
				docmap, err := kubeadmutil.SplitYAMLDocuments([]byte(test.config))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				clusterCfg := testClusterCfg()
 | 
			
		||||
 | 
			
		||||
				got, err := GetVersionStates(clusterCfg, client, docmap)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Errorf("unexpected error: %v", err)
 | 
			
		||||
				} else if len(got) != 1 {
 | 
			
		||||
					t.Errorf("got %d, but expected only a single result: %v", len(got), got)
 | 
			
		||||
				} else if got[0] != test.expected {
 | 
			
		||||
					t.Errorf("unexpected result:\n\texpected: %v\n\tgot: %v", test.expected, got[0])
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
@@ -17,18 +17,16 @@ limitations under the License.
 | 
			
		||||
package componentconfigs
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/lithammer/dedent"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/util/version"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
	clientsetfake "k8s.io/client-go/kubernetes/fake"
 | 
			
		||||
	kubeletconfig "k8s.io/kubelet/config/v1beta1"
 | 
			
		||||
	utilpointer "k8s.io/utils/pointer"
 | 
			
		||||
@@ -37,139 +35,17 @@ import (
 | 
			
		||||
	kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/features"
 | 
			
		||||
	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// kubeletMarshalCases holds common marshal test cases for both the marshal and unmarshal tests
 | 
			
		||||
var kubeletMarshalCases = []struct {
 | 
			
		||||
	name string
 | 
			
		||||
	obj  *kubeletConfig
 | 
			
		||||
	yaml string
 | 
			
		||||
}{
 | 
			
		||||
	{
 | 
			
		||||
		name: "Empty config",
 | 
			
		||||
		obj: &kubeletConfig{
 | 
			
		||||
			configBase: configBase{
 | 
			
		||||
				GroupVersion: kubeletconfig.SchemeGroupVersion,
 | 
			
		||||
			},
 | 
			
		||||
			config: kubeletconfig.KubeletConfiguration{
 | 
			
		||||
				TypeMeta: metav1.TypeMeta{
 | 
			
		||||
					APIVersion: kubeletconfig.SchemeGroupVersion.String(),
 | 
			
		||||
					Kind:       "KubeletConfiguration",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
func testKubeletConfigMap(contents string) *v1.ConfigMap {
 | 
			
		||||
	return &v1.ConfigMap{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name:      constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
 | 
			
		||||
			Namespace: metav1.NamespaceSystem,
 | 
			
		||||
		},
 | 
			
		||||
		yaml: dedent.Dedent(`
 | 
			
		||||
			apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
			authentication:
 | 
			
		||||
			  anonymous: {}
 | 
			
		||||
			  webhook:
 | 
			
		||||
			    cacheTTL: 0s
 | 
			
		||||
			  x509: {}
 | 
			
		||||
			authorization:
 | 
			
		||||
			  webhook:
 | 
			
		||||
			    cacheAuthorizedTTL: 0s
 | 
			
		||||
			    cacheUnauthorizedTTL: 0s
 | 
			
		||||
			cpuManagerReconcilePeriod: 0s
 | 
			
		||||
			evictionPressureTransitionPeriod: 0s
 | 
			
		||||
			fileCheckFrequency: 0s
 | 
			
		||||
			httpCheckFrequency: 0s
 | 
			
		||||
			imageMinimumGCAge: 0s
 | 
			
		||||
			kind: KubeletConfiguration
 | 
			
		||||
			logging: {}
 | 
			
		||||
			nodeStatusReportFrequency: 0s
 | 
			
		||||
			nodeStatusUpdateFrequency: 0s
 | 
			
		||||
			runtimeRequestTimeout: 0s
 | 
			
		||||
			streamingConnectionIdleTimeout: 0s
 | 
			
		||||
			syncFrequency: 0s
 | 
			
		||||
			volumeStatsAggPeriod: 0s
 | 
			
		||||
		`),
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		name: "Non empty config",
 | 
			
		||||
		obj: &kubeletConfig{
 | 
			
		||||
			configBase: configBase{
 | 
			
		||||
				GroupVersion: kubeletconfig.SchemeGroupVersion,
 | 
			
		||||
			},
 | 
			
		||||
			config: kubeletconfig.KubeletConfiguration{
 | 
			
		||||
				TypeMeta: metav1.TypeMeta{
 | 
			
		||||
					APIVersion: kubeletconfig.SchemeGroupVersion.String(),
 | 
			
		||||
					Kind:       "KubeletConfiguration",
 | 
			
		||||
				},
 | 
			
		||||
				Address:            "1.2.3.4",
 | 
			
		||||
				Port:               12345,
 | 
			
		||||
				RotateCertificates: true,
 | 
			
		||||
			},
 | 
			
		||||
		Data: map[string]string{
 | 
			
		||||
			constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(contents),
 | 
			
		||||
		},
 | 
			
		||||
		yaml: dedent.Dedent(`
 | 
			
		||||
			address: 1.2.3.4
 | 
			
		||||
			apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
			authentication:
 | 
			
		||||
			  anonymous: {}
 | 
			
		||||
			  webhook:
 | 
			
		||||
			    cacheTTL: 0s
 | 
			
		||||
			  x509: {}
 | 
			
		||||
			authorization:
 | 
			
		||||
			  webhook:
 | 
			
		||||
			    cacheAuthorizedTTL: 0s
 | 
			
		||||
			    cacheUnauthorizedTTL: 0s
 | 
			
		||||
			cpuManagerReconcilePeriod: 0s
 | 
			
		||||
			evictionPressureTransitionPeriod: 0s
 | 
			
		||||
			fileCheckFrequency: 0s
 | 
			
		||||
			httpCheckFrequency: 0s
 | 
			
		||||
			imageMinimumGCAge: 0s
 | 
			
		||||
			kind: KubeletConfiguration
 | 
			
		||||
			logging: {}
 | 
			
		||||
			nodeStatusReportFrequency: 0s
 | 
			
		||||
			nodeStatusUpdateFrequency: 0s
 | 
			
		||||
			port: 12345
 | 
			
		||||
			rotateCertificates: true
 | 
			
		||||
			runtimeRequestTimeout: 0s
 | 
			
		||||
			streamingConnectionIdleTimeout: 0s
 | 
			
		||||
			syncFrequency: 0s
 | 
			
		||||
			volumeStatsAggPeriod: 0s
 | 
			
		||||
		`),
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestKubeletMarshal(t *testing.T) {
 | 
			
		||||
	for _, test := range kubeletMarshalCases {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			b, err := test.obj.Marshal()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("Marshal failed: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			got := strings.TrimSpace(string(b))
 | 
			
		||||
			expected := strings.TrimSpace(test.yaml)
 | 
			
		||||
			if expected != string(got) {
 | 
			
		||||
				t.Fatalf("Missmatch between expected and got:\nExpected:\n%s\n---\nGot:\n%s", expected, string(got))
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestKubeletUnmarshal(t *testing.T) {
 | 
			
		||||
	for _, test := range kubeletMarshalCases {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			gvkmap, err := kubeadmutil.SplitYAMLDocuments([]byte(test.yaml))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			got := &kubeletConfig{
 | 
			
		||||
				configBase: configBase{
 | 
			
		||||
					GroupVersion: kubeletconfig.SchemeGroupVersion,
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
			if err = got.Unmarshal(gvkmap); err != nil {
 | 
			
		||||
				t.Fatalf("unexpected failure of Unmarshal: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !reflect.DeepEqual(got, test.obj) {
 | 
			
		||||
				t.Fatalf("Missmatch between expected and got:\nExpected:\n%v\n---\nGot:\n%v", test.obj, got)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -411,227 +287,43 @@ func TestKubeletDefault(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// runKubeletFromTest holds common test case data and evaluation code for kubeletHandler.From* functions
 | 
			
		||||
func runKubeletFromTest(t *testing.T, perform func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error)) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name      string
 | 
			
		||||
		in        string
 | 
			
		||||
		out       *kubeletConfig
 | 
			
		||||
		expectErr bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "Empty document map should return nothing successfully",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Non-empty non-kubelet document map returns nothing successfully",
 | 
			
		||||
			in: dedent.Dedent(`
 | 
			
		||||
				apiVersion: api.example.com/v1
 | 
			
		||||
				kind: Configuration
 | 
			
		||||
			`),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Old kubelet version returns an error",
 | 
			
		||||
			in: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubelet.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: KubeletConfiguration
 | 
			
		||||
			`),
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Wrong kubelet kind returns an error",
 | 
			
		||||
			in: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
				kind: Configuration
 | 
			
		||||
			`),
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Valid kubelet only config gets loaded",
 | 
			
		||||
			in: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
				kind: KubeletConfiguration
 | 
			
		||||
				address: 1.2.3.4
 | 
			
		||||
				port: 12345
 | 
			
		||||
				rotateCertificates: true
 | 
			
		||||
			`),
 | 
			
		||||
			out: &kubeletConfig{
 | 
			
		||||
				configBase: configBase{
 | 
			
		||||
					GroupVersion: kubeletHandler.GroupVersion,
 | 
			
		||||
					userSupplied: true,
 | 
			
		||||
				},
 | 
			
		||||
				config: kubeletconfig.KubeletConfiguration{
 | 
			
		||||
					TypeMeta: metav1.TypeMeta{
 | 
			
		||||
						APIVersion: kubeletHandler.GroupVersion.String(),
 | 
			
		||||
						Kind:       "KubeletConfiguration",
 | 
			
		||||
					},
 | 
			
		||||
					Address:            "1.2.3.4",
 | 
			
		||||
					Port:               12345,
 | 
			
		||||
					RotateCertificates: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Valid kubelet config gets loaded when coupled with an extra document",
 | 
			
		||||
			in: dedent.Dedent(`
 | 
			
		||||
				apiVersion: api.example.com/v1
 | 
			
		||||
				kind: Configuration
 | 
			
		||||
				---
 | 
			
		||||
				apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
				kind: KubeletConfiguration
 | 
			
		||||
				address: 1.2.3.4
 | 
			
		||||
				port: 12345
 | 
			
		||||
				rotateCertificates: true
 | 
			
		||||
			`),
 | 
			
		||||
			out: &kubeletConfig{
 | 
			
		||||
				configBase: configBase{
 | 
			
		||||
					GroupVersion: kubeletHandler.GroupVersion,
 | 
			
		||||
					userSupplied: true,
 | 
			
		||||
				},
 | 
			
		||||
				config: kubeletconfig.KubeletConfiguration{
 | 
			
		||||
					TypeMeta: metav1.TypeMeta{
 | 
			
		||||
						APIVersion: kubeletHandler.GroupVersion.String(),
 | 
			
		||||
						Kind:       "KubeletConfiguration",
 | 
			
		||||
					},
 | 
			
		||||
					Address:            "1.2.3.4",
 | 
			
		||||
					Port:               12345,
 | 
			
		||||
					RotateCertificates: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
func runKubeletFromTest(t *testing.T, perform func(gvk schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error)) {
 | 
			
		||||
	const (
 | 
			
		||||
		kind          = "KubeletConfiguration"
 | 
			
		||||
		clusterDomain = "foo.bar"
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			componentCfg, err := perform(t, test.in)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				if !test.expectErr {
 | 
			
		||||
					t.Errorf("unexpected failure: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				if test.expectErr {
 | 
			
		||||
					t.Error("unexpected success")
 | 
			
		||||
				} else {
 | 
			
		||||
					if componentCfg == nil {
 | 
			
		||||
						if test.out != nil {
 | 
			
		||||
							t.Error("unexpected nil result")
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						if got, ok := componentCfg.(*kubeletConfig); !ok {
 | 
			
		||||
							t.Error("different result type")
 | 
			
		||||
						} else {
 | 
			
		||||
							if test.out == nil {
 | 
			
		||||
								t.Errorf("unexpected result: %v", got)
 | 
			
		||||
							} else {
 | 
			
		||||
								if !reflect.DeepEqual(test.out, got) {
 | 
			
		||||
									t.Errorf("missmatch between expected and got:\nExpected:\n%v\n---\nGot:\n%v", test.out, got)
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	gvk := kubeletHandler.GroupVersion.WithKind(kind)
 | 
			
		||||
	yaml := fmt.Sprintf("apiVersion: %s\nkind: %s\nclusterDomain: %s", kubeletHandler.GroupVersion, kind, clusterDomain)
 | 
			
		||||
 | 
			
		||||
	cfg, err := perform(gvk, yaml)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected failure: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if cfg == nil {
 | 
			
		||||
		t.Fatal("no config loaded where it should have been")
 | 
			
		||||
	}
 | 
			
		||||
	if kubeletCfg, ok := cfg.(*kubeletConfig); !ok {
 | 
			
		||||
		t.Fatalf("found different object type than expected: %s", reflect.TypeOf(cfg))
 | 
			
		||||
	} else if kubeletCfg.config.ClusterDomain != clusterDomain {
 | 
			
		||||
		t.Fatalf("unexpected control value (clusterDomain):\n\tgot: %q\n\texpected: %q", kubeletCfg.config.ClusterDomain, clusterDomain)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestKubeletFromDocumentMap(t *testing.T) {
 | 
			
		||||
	runKubeletFromTest(t, func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
		gvkmap, err := kubeadmutil.SplitYAMLDocuments([]byte(in))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return kubeletHandler.FromDocumentMap(gvkmap)
 | 
			
		||||
	runKubeletFromTest(t, func(gvk schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
		return kubeletHandler.FromDocumentMap(kubeadmapi.DocumentMap{
 | 
			
		||||
			gvk: []byte(yaml),
 | 
			
		||||
		})
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestKubeletFromCluster(t *testing.T) {
 | 
			
		||||
	runKubeletFromTest(t, func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
		clusterCfg := &kubeadmapi.ClusterConfiguration{
 | 
			
		||||
			KubernetesVersion: constants.CurrentKubernetesVersion.String(),
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		k8sVersion := version.MustParseGeneric(clusterCfg.KubernetesVersion)
 | 
			
		||||
 | 
			
		||||
	runKubeletFromTest(t, func(_ schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
		client := clientsetfake.NewSimpleClientset(
 | 
			
		||||
			&v1.ConfigMap{
 | 
			
		||||
				ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
					Name:      constants.GetKubeletConfigMapName(k8sVersion),
 | 
			
		||||
					Namespace: metav1.NamespaceSystem,
 | 
			
		||||
				},
 | 
			
		||||
				Data: map[string]string{
 | 
			
		||||
					constants.KubeletBaseConfigurationConfigMapKey: in,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			testKubeletConfigMap(yaml),
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		return kubeletHandler.FromCluster(client, clusterCfg)
 | 
			
		||||
		return kubeletHandler.FromCluster(client, testClusterCfg())
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGeneratedKubeletFromCluster(t *testing.T) {
 | 
			
		||||
	testYAML := dedent.Dedent(`
 | 
			
		||||
		apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
		kind: KubeletConfiguration
 | 
			
		||||
		address: 1.2.3.4
 | 
			
		||||
		port: 12345
 | 
			
		||||
		rotateCertificates: true
 | 
			
		||||
	`)
 | 
			
		||||
	testYAMLHash := fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(testYAML)))
 | 
			
		||||
	// The SHA256 sum of "The quick brown fox jumps over the lazy dog"
 | 
			
		||||
	const mismatchHash = "sha256:d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name         string
 | 
			
		||||
		hash         string
 | 
			
		||||
		userSupplied bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "Matching hash means generated config",
 | 
			
		||||
			hash: testYAMLHash,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:         "Missmatching hash means user supplied config",
 | 
			
		||||
			hash:         mismatchHash,
 | 
			
		||||
			userSupplied: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:         "No hash means user supplied config",
 | 
			
		||||
			userSupplied: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			clusterCfg := &kubeadmapi.ClusterConfiguration{
 | 
			
		||||
				KubernetesVersion: constants.CurrentKubernetesVersion.String(),
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			k8sVersion := version.MustParseGeneric(clusterCfg.KubernetesVersion)
 | 
			
		||||
 | 
			
		||||
			configMap := &v1.ConfigMap{
 | 
			
		||||
				ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
					Name:      constants.GetKubeletConfigMapName(k8sVersion),
 | 
			
		||||
					Namespace: metav1.NamespaceSystem,
 | 
			
		||||
				},
 | 
			
		||||
				Data: map[string]string{
 | 
			
		||||
					constants.KubeletBaseConfigurationConfigMapKey: testYAML,
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if test.hash != "" {
 | 
			
		||||
				configMap.Annotations = map[string]string{
 | 
			
		||||
					constants.ComponentConfigHashAnnotationKey: test.hash,
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			client := clientsetfake.NewSimpleClientset(configMap)
 | 
			
		||||
			cfg, err := kubeletHandler.FromCluster(client, clusterCfg)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected failure of FromCluster: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			got := cfg.IsUserSupplied()
 | 
			
		||||
			if got != test.userSupplied {
 | 
			
		||||
				t.Fatalf("mismatch between expected and got:\n\tExpected: %t\n\tGot: %t", test.userSupplied, got)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,10 +17,8 @@ limitations under the License.
 | 
			
		||||
package componentconfigs
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/lithammer/dedent"
 | 
			
		||||
@@ -31,185 +29,22 @@ import (
 | 
			
		||||
	componentbaseconfig "k8s.io/component-base/config/v1alpha1"
 | 
			
		||||
	kubeproxyconfig "k8s.io/kube-proxy/config/v1alpha1"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
 | 
			
		||||
	kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/features"
 | 
			
		||||
	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// kubeProxyMarshalCases holds common marshal test cases for both the marshal and unmarshal tests
 | 
			
		||||
var kubeProxyMarshalCases = []struct {
 | 
			
		||||
	name string
 | 
			
		||||
	obj  *kubeProxyConfig
 | 
			
		||||
	yaml string
 | 
			
		||||
}{
 | 
			
		||||
	{
 | 
			
		||||
		name: "Empty config",
 | 
			
		||||
		obj: &kubeProxyConfig{
 | 
			
		||||
			configBase: configBase{
 | 
			
		||||
				GroupVersion: kubeproxyconfig.SchemeGroupVersion,
 | 
			
		||||
			},
 | 
			
		||||
			config: kubeproxyconfig.KubeProxyConfiguration{
 | 
			
		||||
				TypeMeta: metav1.TypeMeta{
 | 
			
		||||
					APIVersion: kubeproxyconfig.SchemeGroupVersion.String(),
 | 
			
		||||
					Kind:       "KubeProxyConfiguration",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
func testKubeProxyConfigMap(contents string) *v1.ConfigMap {
 | 
			
		||||
	return &v1.ConfigMap{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name:      constants.KubeProxyConfigMap,
 | 
			
		||||
			Namespace: metav1.NamespaceSystem,
 | 
			
		||||
		},
 | 
			
		||||
		yaml: dedent.Dedent(`
 | 
			
		||||
			apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
			bindAddress: ""
 | 
			
		||||
			bindAddressHardFail: false
 | 
			
		||||
			clientConnection:
 | 
			
		||||
			  acceptContentTypes: ""
 | 
			
		||||
			  burst: 0
 | 
			
		||||
			  contentType: ""
 | 
			
		||||
			  kubeconfig: ""
 | 
			
		||||
			  qps: 0
 | 
			
		||||
			clusterCIDR: ""
 | 
			
		||||
			configSyncPeriod: 0s
 | 
			
		||||
			conntrack:
 | 
			
		||||
			  maxPerCore: null
 | 
			
		||||
			  min: null
 | 
			
		||||
			  tcpCloseWaitTimeout: null
 | 
			
		||||
			  tcpEstablishedTimeout: null
 | 
			
		||||
			detectLocalMode: ""
 | 
			
		||||
			enableProfiling: false
 | 
			
		||||
			healthzBindAddress: ""
 | 
			
		||||
			hostnameOverride: ""
 | 
			
		||||
			iptables:
 | 
			
		||||
			  masqueradeAll: false
 | 
			
		||||
			  masqueradeBit: null
 | 
			
		||||
			  minSyncPeriod: 0s
 | 
			
		||||
			  syncPeriod: 0s
 | 
			
		||||
			ipvs:
 | 
			
		||||
			  excludeCIDRs: null
 | 
			
		||||
			  minSyncPeriod: 0s
 | 
			
		||||
			  scheduler: ""
 | 
			
		||||
			  strictARP: false
 | 
			
		||||
			  syncPeriod: 0s
 | 
			
		||||
			  tcpFinTimeout: 0s
 | 
			
		||||
			  tcpTimeout: 0s
 | 
			
		||||
			  udpTimeout: 0s
 | 
			
		||||
			kind: KubeProxyConfiguration
 | 
			
		||||
			metricsBindAddress: ""
 | 
			
		||||
			mode: ""
 | 
			
		||||
			nodePortAddresses: null
 | 
			
		||||
			oomScoreAdj: null
 | 
			
		||||
			portRange: ""
 | 
			
		||||
			showHiddenMetricsForVersion: ""
 | 
			
		||||
			udpIdleTimeout: 0s
 | 
			
		||||
			winkernel:
 | 
			
		||||
			  enableDSR: false
 | 
			
		||||
			  networkName: ""
 | 
			
		||||
			  sourceVip: ""
 | 
			
		||||
		`),
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		name: "Non empty config",
 | 
			
		||||
		obj: &kubeProxyConfig{
 | 
			
		||||
			configBase: configBase{
 | 
			
		||||
				GroupVersion: kubeproxyconfig.SchemeGroupVersion,
 | 
			
		||||
			},
 | 
			
		||||
			config: kubeproxyconfig.KubeProxyConfiguration{
 | 
			
		||||
				TypeMeta: metav1.TypeMeta{
 | 
			
		||||
					APIVersion: kubeproxyconfig.SchemeGroupVersion.String(),
 | 
			
		||||
					Kind:       "KubeProxyConfiguration",
 | 
			
		||||
				},
 | 
			
		||||
				BindAddress:     "1.2.3.4",
 | 
			
		||||
				EnableProfiling: true,
 | 
			
		||||
			},
 | 
			
		||||
		Data: map[string]string{
 | 
			
		||||
			constants.KubeProxyConfigMapKey: dedent.Dedent(contents),
 | 
			
		||||
		},
 | 
			
		||||
		yaml: dedent.Dedent(`
 | 
			
		||||
			apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
			bindAddress: 1.2.3.4
 | 
			
		||||
			bindAddressHardFail: false
 | 
			
		||||
			clientConnection:
 | 
			
		||||
			  acceptContentTypes: ""
 | 
			
		||||
			  burst: 0
 | 
			
		||||
			  contentType: ""
 | 
			
		||||
			  kubeconfig: ""
 | 
			
		||||
			  qps: 0
 | 
			
		||||
			clusterCIDR: ""
 | 
			
		||||
			configSyncPeriod: 0s
 | 
			
		||||
			conntrack:
 | 
			
		||||
			  maxPerCore: null
 | 
			
		||||
			  min: null
 | 
			
		||||
			  tcpCloseWaitTimeout: null
 | 
			
		||||
			  tcpEstablishedTimeout: null
 | 
			
		||||
			detectLocalMode: ""
 | 
			
		||||
			enableProfiling: true
 | 
			
		||||
			healthzBindAddress: ""
 | 
			
		||||
			hostnameOverride: ""
 | 
			
		||||
			iptables:
 | 
			
		||||
			  masqueradeAll: false
 | 
			
		||||
			  masqueradeBit: null
 | 
			
		||||
			  minSyncPeriod: 0s
 | 
			
		||||
			  syncPeriod: 0s
 | 
			
		||||
			ipvs:
 | 
			
		||||
			  excludeCIDRs: null
 | 
			
		||||
			  minSyncPeriod: 0s
 | 
			
		||||
			  scheduler: ""
 | 
			
		||||
			  strictARP: false
 | 
			
		||||
			  syncPeriod: 0s
 | 
			
		||||
			  tcpFinTimeout: 0s
 | 
			
		||||
			  tcpTimeout: 0s
 | 
			
		||||
			  udpTimeout: 0s
 | 
			
		||||
			kind: KubeProxyConfiguration
 | 
			
		||||
			metricsBindAddress: ""
 | 
			
		||||
			mode: ""
 | 
			
		||||
			nodePortAddresses: null
 | 
			
		||||
			oomScoreAdj: null
 | 
			
		||||
			portRange: ""
 | 
			
		||||
			showHiddenMetricsForVersion: ""
 | 
			
		||||
			udpIdleTimeout: 0s
 | 
			
		||||
			winkernel:
 | 
			
		||||
			  enableDSR: false
 | 
			
		||||
			  networkName: ""
 | 
			
		||||
			  sourceVip: ""
 | 
			
		||||
		`),
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestKubeProxyMarshal(t *testing.T) {
 | 
			
		||||
	for _, test := range kubeProxyMarshalCases {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			b, err := test.obj.Marshal()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("Marshal failed: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			got := strings.TrimSpace(string(b))
 | 
			
		||||
			expected := strings.TrimSpace(test.yaml)
 | 
			
		||||
			if expected != string(got) {
 | 
			
		||||
				t.Fatalf("Missmatch between expected and got:\nExpected:\n%s\n---\nGot:\n%s", expected, string(got))
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestKubeProxyUnmarshal(t *testing.T) {
 | 
			
		||||
	for _, test := range kubeProxyMarshalCases {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			gvkmap, err := kubeadmutil.SplitYAMLDocuments([]byte(test.yaml))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			got := &kubeProxyConfig{
 | 
			
		||||
				configBase: configBase{
 | 
			
		||||
					GroupVersion: kubeproxyconfig.SchemeGroupVersion,
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
			if err = got.Unmarshal(gvkmap); err != nil {
 | 
			
		||||
				t.Fatalf("unexpected failure of Unmarshal: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !reflect.DeepEqual(got, test.obj) {
 | 
			
		||||
				t.Fatalf("Missmatch between expected and got:\nExpected:\n%v\n---\nGot:\n%v", test.obj, got)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -331,210 +166,44 @@ func TestKubeProxyDefault(t *testing.T) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// runKubeProxyFromTest holds common test case data and evaluation code for kubeProxyHandler.From* functions
 | 
			
		||||
func runKubeProxyFromTest(t *testing.T, perform func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error)) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name      string
 | 
			
		||||
		in        string
 | 
			
		||||
		out       *kubeProxyConfig
 | 
			
		||||
		expectErr bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "Empty document map should return nothing successfully",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Non-empty non-kube-proxy document map returns nothing successfully",
 | 
			
		||||
			in: dedent.Dedent(`
 | 
			
		||||
				apiVersion: api.example.com/v1
 | 
			
		||||
				kind: Configuration
 | 
			
		||||
			`),
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Old kube-proxy version returns an error",
 | 
			
		||||
			in: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha0
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
			`),
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Wrong kube-proxy kind returns an error",
 | 
			
		||||
			in: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: Configuration
 | 
			
		||||
			`),
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Valid kube-proxy only config gets loaded",
 | 
			
		||||
			in: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
				bindAddress: 1.2.3.4
 | 
			
		||||
				enableProfiling: true
 | 
			
		||||
			`),
 | 
			
		||||
			out: &kubeProxyConfig{
 | 
			
		||||
				configBase: configBase{
 | 
			
		||||
					GroupVersion: kubeProxyHandler.GroupVersion,
 | 
			
		||||
					userSupplied: true,
 | 
			
		||||
				},
 | 
			
		||||
				config: kubeproxyconfig.KubeProxyConfiguration{
 | 
			
		||||
					TypeMeta: metav1.TypeMeta{
 | 
			
		||||
						APIVersion: kubeProxyHandler.GroupVersion.String(),
 | 
			
		||||
						Kind:       "KubeProxyConfiguration",
 | 
			
		||||
					},
 | 
			
		||||
					BindAddress:     "1.2.3.4",
 | 
			
		||||
					EnableProfiling: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "Valid kube-proxy config gets loaded when coupled with an extra document",
 | 
			
		||||
			in: dedent.Dedent(`
 | 
			
		||||
				apiVersion: api.example.com/v1
 | 
			
		||||
				kind: Configuration
 | 
			
		||||
				---
 | 
			
		||||
				apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
				kind: KubeProxyConfiguration
 | 
			
		||||
				bindAddress: 1.2.3.4
 | 
			
		||||
				enableProfiling: true
 | 
			
		||||
			`),
 | 
			
		||||
			out: &kubeProxyConfig{
 | 
			
		||||
				configBase: configBase{
 | 
			
		||||
					GroupVersion: kubeProxyHandler.GroupVersion,
 | 
			
		||||
					userSupplied: true,
 | 
			
		||||
				},
 | 
			
		||||
				config: kubeproxyconfig.KubeProxyConfiguration{
 | 
			
		||||
					TypeMeta: metav1.TypeMeta{
 | 
			
		||||
						APIVersion: kubeProxyHandler.GroupVersion.String(),
 | 
			
		||||
						Kind:       "KubeProxyConfiguration",
 | 
			
		||||
					},
 | 
			
		||||
					BindAddress:     "1.2.3.4",
 | 
			
		||||
					EnableProfiling: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
func runKubeProxyFromTest(t *testing.T, perform func(gvk schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error)) {
 | 
			
		||||
	const (
 | 
			
		||||
		kind        = "KubeProxyConfiguration"
 | 
			
		||||
		clusterCIDR = "1.2.3.4/16"
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			componentCfg, err := perform(t, test.in)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				if !test.expectErr {
 | 
			
		||||
					t.Errorf("unexpected failure: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				if test.expectErr {
 | 
			
		||||
					t.Error("unexpected success")
 | 
			
		||||
				} else {
 | 
			
		||||
					if componentCfg == nil {
 | 
			
		||||
						if test.out != nil {
 | 
			
		||||
							t.Error("unexpected nil result")
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						if got, ok := componentCfg.(*kubeProxyConfig); !ok {
 | 
			
		||||
							t.Error("different result type")
 | 
			
		||||
						} else {
 | 
			
		||||
							if test.out == nil {
 | 
			
		||||
								t.Errorf("unexpected result: %v", got)
 | 
			
		||||
							} else {
 | 
			
		||||
								if !reflect.DeepEqual(test.out, got) {
 | 
			
		||||
									t.Errorf("missmatch between expected and got:\nExpected:\n%v\n---\nGot:\n%v", test.out, got)
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	gvk := kubeProxyHandler.GroupVersion.WithKind(kind)
 | 
			
		||||
	yaml := fmt.Sprintf("apiVersion: %s\nkind: %s\nclusterCIDR: %s", kubeProxyHandler.GroupVersion, kind, clusterCIDR)
 | 
			
		||||
 | 
			
		||||
	cfg, err := perform(gvk, yaml)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected failure: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if cfg == nil {
 | 
			
		||||
		t.Fatal("no config loaded where it should have been")
 | 
			
		||||
	}
 | 
			
		||||
	if kubeproxyCfg, ok := cfg.(*kubeProxyConfig); !ok {
 | 
			
		||||
		t.Fatalf("found different object type than expected: %s", reflect.TypeOf(cfg))
 | 
			
		||||
	} else if kubeproxyCfg.config.ClusterCIDR != clusterCIDR {
 | 
			
		||||
		t.Fatalf("unexpected control value (clusterDomain):\n\tgot: %q\n\texpected: %q", kubeproxyCfg.config.ClusterCIDR, clusterCIDR)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestKubeProxyFromDocumentMap(t *testing.T) {
 | 
			
		||||
	runKubeProxyFromTest(t, func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
		gvkmap, err := kubeadmutil.SplitYAMLDocuments([]byte(in))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return kubeProxyHandler.FromDocumentMap(gvkmap)
 | 
			
		||||
	runKubeProxyFromTest(t, func(gvk schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
		return kubeProxyHandler.FromDocumentMap(kubeadmapi.DocumentMap{
 | 
			
		||||
			gvk: []byte(yaml),
 | 
			
		||||
		})
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestKubeProxyFromCluster(t *testing.T) {
 | 
			
		||||
	runKubeProxyFromTest(t, func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
	runKubeProxyFromTest(t, func(_ schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error) {
 | 
			
		||||
		client := clientsetfake.NewSimpleClientset(
 | 
			
		||||
			&v1.ConfigMap{
 | 
			
		||||
				ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
					Name:      constants.KubeProxyConfigMap,
 | 
			
		||||
					Namespace: metav1.NamespaceSystem,
 | 
			
		||||
				},
 | 
			
		||||
				Data: map[string]string{
 | 
			
		||||
					constants.KubeProxyConfigMapKey: in,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			testKubeProxyConfigMap(yaml),
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		return kubeProxyHandler.FromCluster(client, &kubeadmapi.ClusterConfiguration{})
 | 
			
		||||
		return kubeProxyHandler.FromCluster(client, testClusterCfg())
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGeneratedKubeProxyFromCluster(t *testing.T) {
 | 
			
		||||
	testYAML := dedent.Dedent(`
 | 
			
		||||
		apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
		kind: KubeProxyConfiguration
 | 
			
		||||
		bindAddress: 1.2.3.4
 | 
			
		||||
		enableProfiling: true
 | 
			
		||||
	`)
 | 
			
		||||
	testYAMLHash := fmt.Sprintf("sha256:%x", sha256.Sum256([]byte(testYAML)))
 | 
			
		||||
	// The SHA256 sum of "The quick brown fox jumps over the lazy dog"
 | 
			
		||||
	const mismatchHash = "sha256:d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name         string
 | 
			
		||||
		hash         string
 | 
			
		||||
		userSupplied bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "Matching hash means generated config",
 | 
			
		||||
			hash: testYAMLHash,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:         "Missmatching hash means user supplied config",
 | 
			
		||||
			hash:         mismatchHash,
 | 
			
		||||
			userSupplied: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:         "No hash means user supplied config",
 | 
			
		||||
			userSupplied: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			configMap := &v1.ConfigMap{
 | 
			
		||||
				ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
					Name:      constants.KubeProxyConfigMap,
 | 
			
		||||
					Namespace: metav1.NamespaceSystem,
 | 
			
		||||
				},
 | 
			
		||||
				Data: map[string]string{
 | 
			
		||||
					constants.KubeProxyConfigMapKey: testYAML,
 | 
			
		||||
				},
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if test.hash != "" {
 | 
			
		||||
				configMap.Annotations = map[string]string{
 | 
			
		||||
					constants.ComponentConfigHashAnnotationKey: test.hash,
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			client := clientsetfake.NewSimpleClientset(configMap)
 | 
			
		||||
			cfg, err := kubeProxyHandler.FromCluster(client, &kubeadmapi.ClusterConfiguration{})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected failure of FromCluster: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			got := cfg.IsUserSupplied()
 | 
			
		||||
			if got != test.userSupplied {
 | 
			
		||||
				t.Fatalf("mismatch between expected and got:\n\tExpected: %t\n\tGot: %t", test.userSupplied, got)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -56,8 +56,6 @@ go_test(
 | 
			
		||||
    embed = [":go_default_library"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//cmd/kubeadm/app/apis/kubeadm:go_default_library",
 | 
			
		||||
        "//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
 | 
			
		||||
        "//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
 | 
			
		||||
        "//cmd/kubeadm/app/apis/kubeadm/v1beta2:go_default_library",
 | 
			
		||||
        "//cmd/kubeadm/app/componentconfigs:go_default_library",
 | 
			
		||||
        "//cmd/kubeadm/app/constants:go_default_library",
 | 
			
		||||
@@ -74,7 +72,6 @@ go_test(
 | 
			
		||||
        "//staging/src/k8s.io/client-go/testing:go_default_library",
 | 
			
		||||
        "//vendor/github.com/lithammer/dedent:go_default_library",
 | 
			
		||||
        "//vendor/github.com/pkg/errors:go_default_library",
 | 
			
		||||
        "//vendor/github.com/pmezard/go-difflib/difflib:go_default_library",
 | 
			
		||||
        "//vendor/sigs.k8s.io/yaml:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,6 @@ import (
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"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"
 | 
			
		||||
@@ -32,24 +30,11 @@ import (
 | 
			
		||||
	"sigs.k8s.io/yaml"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func diff(expected, actual []byte) string {
 | 
			
		||||
	// Write out the diff
 | 
			
		||||
	var diffBytes bytes.Buffer
 | 
			
		||||
	difflib.WriteUnifiedDiff(&diffBytes, difflib.UnifiedDiff{
 | 
			
		||||
		A:        difflib.SplitLines(string(expected)),
 | 
			
		||||
		B:        difflib.SplitLines(string(actual)),
 | 
			
		||||
		FromFile: "expected",
 | 
			
		||||
		ToFile:   "actual",
 | 
			
		||||
		Context:  3,
 | 
			
		||||
	})
 | 
			
		||||
	return diffBytes.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestLoadInitConfigurationFromFile(t *testing.T) {
 | 
			
		||||
	// Create temp folder for the test case
 | 
			
		||||
	tmpdir, err := ioutil.TempDir("", "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Couldn't create tmpdir")
 | 
			
		||||
		t.Fatalf("Couldn't create tmpdir: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer os.RemoveAll(tmpdir)
 | 
			
		||||
 | 
			
		||||
@@ -100,7 +85,7 @@ func TestLoadInitConfigurationFromFile(t *testing.T) {
 | 
			
		||||
			cfgPath := filepath.Join(tmpdir, rt.name)
 | 
			
		||||
			err := ioutil.WriteFile(cfgPath, rt.fileContents, 0644)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Errorf("Couldn't create file")
 | 
			
		||||
				t.Errorf("Couldn't create file: %v", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -116,7 +101,7 @@ func TestLoadInitConfigurationFromFile(t *testing.T) {
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if obj == nil {
 | 
			
		||||
					t.Errorf("Unexpected nil return value")
 | 
			
		||||
					t.Error("Unexpected nil return value")
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
 
 | 
			
		||||
@@ -17,100 +17,103 @@ limitations under the License.
 | 
			
		||||
package config
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
 | 
			
		||||
	"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
 | 
			
		||||
	kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
 | 
			
		||||
	kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
 | 
			
		||||
	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	nodeV1beta1YAML    = "testdata/conversion/node/v1beta1.yaml"
 | 
			
		||||
	nodeV1beta2YAML    = "testdata/conversion/node/v1beta2.yaml"
 | 
			
		||||
	nodeInternalYAML   = "testdata/conversion/node/internal.yaml"
 | 
			
		||||
	nodeIncompleteYAML = "testdata/defaulting/node/incomplete.yaml"
 | 
			
		||||
	nodeDefaultedYAML  = "testdata/defaulting/node/defaulted.yaml"
 | 
			
		||||
	nodeInvalidYAML    = "testdata/validation/invalid_nodecfg.yaml"
 | 
			
		||||
	"github.com/lithammer/dedent"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestLoadJoinConfigurationFromFile(t *testing.T) {
 | 
			
		||||
	// Create temp folder for the test case
 | 
			
		||||
	tmpdir, err := ioutil.TempDir("", "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Couldn't create tmpdir: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer os.RemoveAll(tmpdir)
 | 
			
		||||
 | 
			
		||||
	// cfgFiles is in cluster_test.go
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		name, in, out string
 | 
			
		||||
		groupVersion  schema.GroupVersion
 | 
			
		||||
		expectedErr   bool
 | 
			
		||||
		name         string
 | 
			
		||||
		fileContents string
 | 
			
		||||
		expectErr    bool
 | 
			
		||||
	}{
 | 
			
		||||
		// These tests are reading one file, loading it using LoadJoinConfigurationFromFile that all of kubeadm is using for unmarshal of our API types,
 | 
			
		||||
		// and then marshals the internal object to the expected groupVersion
 | 
			
		||||
		{ // v1beta1 -> internal
 | 
			
		||||
			name:         "v1beta1ToInternal",
 | 
			
		||||
			in:           nodeV1beta1YAML,
 | 
			
		||||
			out:          nodeInternalYAML,
 | 
			
		||||
			groupVersion: kubeadm.SchemeGroupVersion,
 | 
			
		||||
		{
 | 
			
		||||
			name:      "empty file causes error",
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		{ // v1beta1 -> internal -> v1beta1
 | 
			
		||||
			name:         "v1beta1Tov1beta1",
 | 
			
		||||
			in:           nodeV1beta1YAML,
 | 
			
		||||
			out:          nodeV1beta1YAML,
 | 
			
		||||
			groupVersion: kubeadmapiv1beta1.SchemeGroupVersion,
 | 
			
		||||
		{
 | 
			
		||||
			name: "Invalid v1beta1 causes error",
 | 
			
		||||
			fileContents: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
				kind: JoinConfiguration
 | 
			
		||||
			`),
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		{ // v1beta2 -> internal
 | 
			
		||||
			name:         "v1beta2ToInternal",
 | 
			
		||||
			in:           nodeV1beta2YAML,
 | 
			
		||||
			out:          nodeInternalYAML,
 | 
			
		||||
			groupVersion: kubeadm.SchemeGroupVersion,
 | 
			
		||||
		{
 | 
			
		||||
			name: "valid v1beta1 is loaded",
 | 
			
		||||
			fileContents: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
				kind: JoinConfiguration
 | 
			
		||||
				caCertPath: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
				discovery:
 | 
			
		||||
				  bootstrapToken:
 | 
			
		||||
				    apiServerEndpoint: kube-apiserver:6443
 | 
			
		||||
				    token: abcdef.0123456789abcdef
 | 
			
		||||
				    unsafeSkipCAVerification: true
 | 
			
		||||
				  timeout: 5m0s
 | 
			
		||||
				  tlsBootstrapToken: abcdef.0123456789abcdef
 | 
			
		||||
			`),
 | 
			
		||||
		},
 | 
			
		||||
		{ // v1beta2 -> internal -> v1beta2
 | 
			
		||||
			name:         "v1beta2Tov1beta2",
 | 
			
		||||
			in:           nodeV1beta2YAML,
 | 
			
		||||
			out:          nodeV1beta2YAML,
 | 
			
		||||
			groupVersion: kubeadmapiv1beta2.SchemeGroupVersion,
 | 
			
		||||
		{
 | 
			
		||||
			name: "Invalid v1beta2 causes error",
 | 
			
		||||
			fileContents: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeadm.k8s.io/v1beta2
 | 
			
		||||
				kind: JoinConfiguration
 | 
			
		||||
			`),
 | 
			
		||||
			expectErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		// These tests are reading one file that has only a subset of the fields populated, loading it using LoadJoinConfigurationFromFile,
 | 
			
		||||
		// and then marshals the internal object to the expected groupVersion
 | 
			
		||||
		{ // v1beta2 -> default -> validate -> internal -> v1beta2
 | 
			
		||||
			name:         "incompleteYAMLToDefaultedv1beta2",
 | 
			
		||||
			in:           nodeIncompleteYAML,
 | 
			
		||||
			out:          nodeDefaultedYAML,
 | 
			
		||||
			groupVersion: kubeadmapiv1beta2.SchemeGroupVersion,
 | 
			
		||||
		},
 | 
			
		||||
		{ // v1beta2 -> validation should fail
 | 
			
		||||
			name:        "invalidYAMLShouldFail",
 | 
			
		||||
			in:          nodeInvalidYAML,
 | 
			
		||||
			expectedErr: true,
 | 
			
		||||
		{
 | 
			
		||||
			name: "valid v1beta2 is loaded",
 | 
			
		||||
			fileContents: dedent.Dedent(`
 | 
			
		||||
				apiVersion: kubeadm.k8s.io/v1beta2
 | 
			
		||||
				kind: JoinConfiguration
 | 
			
		||||
				caCertPath: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
				discovery:
 | 
			
		||||
				  bootstrapToken:
 | 
			
		||||
				    apiServerEndpoint: kube-apiserver:6443
 | 
			
		||||
				    token: abcdef.0123456789abcdef
 | 
			
		||||
				    unsafeSkipCAVerification: true
 | 
			
		||||
				  timeout: 5m0s
 | 
			
		||||
				  tlsBootstrapToken: abcdef.0123456789abcdef
 | 
			
		||||
			`),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, rt := range tests {
 | 
			
		||||
		t.Run(rt.name, func(t2 *testing.T) {
 | 
			
		||||
 | 
			
		||||
			internalcfg, err := LoadJoinConfigurationFromFile(rt.in)
 | 
			
		||||
			cfgPath := filepath.Join(tmpdir, rt.name)
 | 
			
		||||
			err := ioutil.WriteFile(cfgPath, []byte(rt.fileContents), 0644)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				if rt.expectedErr {
 | 
			
		||||
				t.Errorf("Couldn't create file: %v", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			obj, err := LoadJoinConfigurationFromFile(cfgPath)
 | 
			
		||||
			if rt.expectErr {
 | 
			
		||||
				if err == nil {
 | 
			
		||||
					t.Error("Unexpected success")
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					t.Errorf("Error reading file: %v", err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				t2.Fatalf("couldn't unmarshal test data: %v", err)
 | 
			
		||||
			} else if rt.expectedErr {
 | 
			
		||||
				t2.Fatalf("expected error, but no error returned")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			actual, err := kubeadmutil.MarshalToYamlForCodecs(internalcfg, rt.groupVersion, scheme.Codecs)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t2.Fatalf("couldn't marshal internal object: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			expected, err := ioutil.ReadFile(rt.out)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t2.Fatalf("couldn't read test data: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !bytes.Equal(expected, actual) {
 | 
			
		||||
				t2.Errorf("the expected and actual output differs.\n\tin: %s\n\tout: %s\n\tgroupversion: %s\n\tdiff: \n%s\n",
 | 
			
		||||
					rt.in, rt.out, rt.groupVersion.String(), diff(expected, actual))
 | 
			
		||||
				if obj == nil {
 | 
			
		||||
					t.Error("Unexpected nil return value")
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,208 +0,0 @@
 | 
			
		||||
APIServer:
 | 
			
		||||
  CertSANs: null
 | 
			
		||||
  ExtraArgs:
 | 
			
		||||
    authorization-mode: Node,RBAC,Webhook
 | 
			
		||||
  ExtraVolumes:
 | 
			
		||||
  - HostPath: /host/read-only
 | 
			
		||||
    MountPath: /mount/read-only
 | 
			
		||||
    Name: ReadOnlyVolume
 | 
			
		||||
    PathType: ""
 | 
			
		||||
    ReadOnly: true
 | 
			
		||||
  - HostPath: /host/writable
 | 
			
		||||
    MountPath: /mount/writable
 | 
			
		||||
    Name: WritableVolume
 | 
			
		||||
    PathType: ""
 | 
			
		||||
    ReadOnly: false
 | 
			
		||||
  TimeoutForControlPlane: 4m0s
 | 
			
		||||
BootstrapTokens:
 | 
			
		||||
- Description: ""
 | 
			
		||||
  Expires: null
 | 
			
		||||
  Groups:
 | 
			
		||||
  - system:bootstrappers:kubeadm:default-node-token
 | 
			
		||||
  TTL: 24h0m0s
 | 
			
		||||
  Token: s73ybu.6tw6wnqgp5z0wb77
 | 
			
		||||
  Usages:
 | 
			
		||||
  - signing
 | 
			
		||||
  - authentication
 | 
			
		||||
CIImageRepository: ""
 | 
			
		||||
CertificatesDir: /etc/kubernetes/pki
 | 
			
		||||
ClusterName: kubernetes
 | 
			
		||||
ComponentConfigs:
 | 
			
		||||
  KubeProxy:
 | 
			
		||||
    BindAddress: 0.0.0.0
 | 
			
		||||
    BindAddressHardFail: false
 | 
			
		||||
    ClientConnection:
 | 
			
		||||
      AcceptContentTypes: ""
 | 
			
		||||
      Burst: 10
 | 
			
		||||
      ContentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
      Kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
 | 
			
		||||
      QPS: 5
 | 
			
		||||
    ClusterCIDR: ""
 | 
			
		||||
    ConfigSyncPeriod: 15m0s
 | 
			
		||||
    Conntrack:
 | 
			
		||||
      MaxPerCore: 32768
 | 
			
		||||
      Min: 131072
 | 
			
		||||
      TCPCloseWaitTimeout: 1h0m0s
 | 
			
		||||
      TCPEstablishedTimeout: 24h0m0s
 | 
			
		||||
    EnableProfiling: false
 | 
			
		||||
    FeatureGates:
 | 
			
		||||
      ServiceNodeExclusion: true
 | 
			
		||||
      SupportIPVSProxyMode: true
 | 
			
		||||
    HealthzBindAddress: 0.0.0.0:10256
 | 
			
		||||
    HostnameOverride: ""
 | 
			
		||||
    IPTables:
 | 
			
		||||
      MasqueradeAll: false
 | 
			
		||||
      MasqueradeBit: 14
 | 
			
		||||
      MinSyncPeriod: 0s
 | 
			
		||||
      SyncPeriod: 30s
 | 
			
		||||
    IPVS:
 | 
			
		||||
      ExcludeCIDRs: null
 | 
			
		||||
      MinSyncPeriod: 0s
 | 
			
		||||
      Scheduler: ""
 | 
			
		||||
      SyncPeriod: 30s
 | 
			
		||||
    MetricsBindAddress: 127.0.0.1:10249
 | 
			
		||||
    Mode: iptables
 | 
			
		||||
    NodePortAddresses: null
 | 
			
		||||
    OOMScoreAdj: -999
 | 
			
		||||
    PortRange: ""
 | 
			
		||||
    UDPIdleTimeout: 250ms
 | 
			
		||||
    Winkernel:
 | 
			
		||||
      EnableDSR: false
 | 
			
		||||
      NetworkName: ""
 | 
			
		||||
      SourceVip: ""
 | 
			
		||||
  Kubelet:
 | 
			
		||||
    Address: 1.2.3.4
 | 
			
		||||
    AllowedUnsafeSysctls: null
 | 
			
		||||
    Authentication:
 | 
			
		||||
      Anonymous:
 | 
			
		||||
        Enabled: false
 | 
			
		||||
      Webhook:
 | 
			
		||||
        CacheTTL: 2m0s
 | 
			
		||||
        Enabled: true
 | 
			
		||||
      X509:
 | 
			
		||||
        ClientCAFile: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
    Authorization:
 | 
			
		||||
      Mode: Webhook
 | 
			
		||||
      Webhook:
 | 
			
		||||
        CacheAuthorizedTTL: 5m0s
 | 
			
		||||
        CacheUnauthorizedTTL: 30s
 | 
			
		||||
    CPUCFSQuota: true
 | 
			
		||||
    CPUCFSQuotaPeriod: 0s
 | 
			
		||||
    CPUManagerPolicy: none
 | 
			
		||||
    CPUManagerReconcilePeriod: 10s
 | 
			
		||||
    CgroupDriver: cgroupfs
 | 
			
		||||
    CgroupRoot: ""
 | 
			
		||||
    CgroupsPerQOS: true
 | 
			
		||||
    ClusterDNS:
 | 
			
		||||
    - 10.96.0.10
 | 
			
		||||
    ClusterDomain: cluster.local
 | 
			
		||||
    ConfigMapAndSecretChangeDetectionStrategy: Watch
 | 
			
		||||
    ContainerLogMaxFiles: 5
 | 
			
		||||
    ContainerLogMaxSize: 10Mi
 | 
			
		||||
    ContentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
    EnableContentionProfiling: false
 | 
			
		||||
    EnableControllerAttachDetach: true
 | 
			
		||||
    EnableDebuggingHandlers: true
 | 
			
		||||
    EnforceNodeAllocatable:
 | 
			
		||||
    - pods
 | 
			
		||||
    EventBurst: 10
 | 
			
		||||
    EventRecordQPS: 5
 | 
			
		||||
    EvictionHard:
 | 
			
		||||
      imagefs.available: 15%
 | 
			
		||||
      memory.available: 100Mi
 | 
			
		||||
      nodefs.available: 10%
 | 
			
		||||
      nodefs.inodesFree: 5%
 | 
			
		||||
    EvictionMaxPodGracePeriod: 0
 | 
			
		||||
    EvictionMinimumReclaim: null
 | 
			
		||||
    EvictionPressureTransitionPeriod: 5m0s
 | 
			
		||||
    EvictionSoft: null
 | 
			
		||||
    EvictionSoftGracePeriod: null
 | 
			
		||||
    FailSwapOn: true
 | 
			
		||||
    FeatureGates: null
 | 
			
		||||
    FileCheckFrequency: 20s
 | 
			
		||||
    HTTPCheckFrequency: 20s
 | 
			
		||||
    HairpinMode: promiscuous-bridge
 | 
			
		||||
    HealthzBindAddress: 127.0.0.1
 | 
			
		||||
    HealthzPort: 10248
 | 
			
		||||
    IPTablesDropBit: 15
 | 
			
		||||
    IPTablesMasqueradeBit: 14
 | 
			
		||||
    ImageGCHighThresholdPercent: 85
 | 
			
		||||
    ImageGCLowThresholdPercent: 80
 | 
			
		||||
    ImageMinimumGCAge: 2m0s
 | 
			
		||||
    KubeAPIBurst: 10
 | 
			
		||||
    KubeAPIQPS: 5
 | 
			
		||||
    KubeReserved: null
 | 
			
		||||
    KubeReservedCgroup: ""
 | 
			
		||||
    KubeletCgroups: ""
 | 
			
		||||
    MakeIPTablesUtilChains: true
 | 
			
		||||
    MaxOpenFiles: 1000000
 | 
			
		||||
    MaxPods: 110
 | 
			
		||||
    NodeLeaseDurationSeconds: 40
 | 
			
		||||
    NodeStatusReportFrequency: 1m0s
 | 
			
		||||
    NodeStatusUpdateFrequency: 10s
 | 
			
		||||
    OOMScoreAdj: -999
 | 
			
		||||
    PodCIDR: ""
 | 
			
		||||
    PodPidsLimit: -1
 | 
			
		||||
    PodsPerCore: 0
 | 
			
		||||
    Port: 10250
 | 
			
		||||
    ProtectKernelDefaults: false
 | 
			
		||||
    QOSReserved: null
 | 
			
		||||
    ReadOnlyPort: 0
 | 
			
		||||
    RegistryBurst: 10
 | 
			
		||||
    RegistryPullQPS: 5
 | 
			
		||||
    ResolverConfig: /etc/resolv.conf
 | 
			
		||||
    RotateCertificates: true
 | 
			
		||||
    RuntimeRequestTimeout: 2m0s
 | 
			
		||||
    SerializeImagePulls: true
 | 
			
		||||
    ServerTLSBootstrap: false
 | 
			
		||||
    StaticPodPath: /etc/kubernetes/manifests
 | 
			
		||||
    StaticPodURL: ""
 | 
			
		||||
    StaticPodURLHeader: null
 | 
			
		||||
    StreamingConnectionIdleTimeout: 4h0m0s
 | 
			
		||||
    SyncFrequency: 1m0s
 | 
			
		||||
    SystemCgroups: ""
 | 
			
		||||
    SystemReserved: null
 | 
			
		||||
    SystemReservedCgroup: ""
 | 
			
		||||
    TLSCertFile: ""
 | 
			
		||||
    TLSCipherSuites: null
 | 
			
		||||
    TLSMinVersion: ""
 | 
			
		||||
    TLSPrivateKeyFile: ""
 | 
			
		||||
    VolumeStatsAggPeriod: 1m0s
 | 
			
		||||
ControlPlaneEndpoint: ""
 | 
			
		||||
ControllerManager:
 | 
			
		||||
  ExtraArgs: null
 | 
			
		||||
  ExtraVolumes: null
 | 
			
		||||
DNS:
 | 
			
		||||
  ImageRepository: ""
 | 
			
		||||
  ImageTag: ""
 | 
			
		||||
  Type: CoreDNS
 | 
			
		||||
Etcd:
 | 
			
		||||
  External: null
 | 
			
		||||
  Local:
 | 
			
		||||
    DataDir: /var/lib/etcd
 | 
			
		||||
    ExtraArgs: null
 | 
			
		||||
    ImageRepository: ""
 | 
			
		||||
    ImageTag: ""
 | 
			
		||||
    PeerCertSANs: null
 | 
			
		||||
    ServerCertSANs: null
 | 
			
		||||
FeatureGates: null
 | 
			
		||||
ImageRepository: k8s.gcr.io
 | 
			
		||||
KubernetesVersion: v1.12.2
 | 
			
		||||
LocalAPIEndpoint:
 | 
			
		||||
  AdvertiseAddress: 192.168.2.2
 | 
			
		||||
  BindPort: 6443
 | 
			
		||||
Networking:
 | 
			
		||||
  DNSDomain: cluster.local
 | 
			
		||||
  PodSubnet: ""
 | 
			
		||||
  ServiceSubnet: 10.96.0.0/12
 | 
			
		||||
NodeRegistration:
 | 
			
		||||
  CRISocket: /var/run/dockershim.sock
 | 
			
		||||
  KubeletExtraArgs: null
 | 
			
		||||
  Name: control-plane-1
 | 
			
		||||
  Taints:
 | 
			
		||||
  - effect: NoSchedule
 | 
			
		||||
    key: node-role.kubernetes.io/master
 | 
			
		||||
Scheduler:
 | 
			
		||||
  ExtraArgs: null
 | 
			
		||||
  ExtraVolumes: null
 | 
			
		||||
UseHyperKubeImage: true
 | 
			
		||||
@@ -1,206 +0,0 @@
 | 
			
		||||
APIServer:
 | 
			
		||||
  CertSANs: null
 | 
			
		||||
  ExtraArgs:
 | 
			
		||||
    authorization-mode: Node,RBAC,Webhook
 | 
			
		||||
  ExtraVolumes:
 | 
			
		||||
  - HostPath: /host/read-only
 | 
			
		||||
    MountPath: /mount/read-only
 | 
			
		||||
    Name: ReadOnlyVolume
 | 
			
		||||
    PathType: ""
 | 
			
		||||
    ReadOnly: true
 | 
			
		||||
  - HostPath: /host/writable
 | 
			
		||||
    MountPath: /mount/writable
 | 
			
		||||
    Name: WritableVolume
 | 
			
		||||
    PathType: ""
 | 
			
		||||
    ReadOnly: false
 | 
			
		||||
  TimeoutForControlPlane: 4m0s
 | 
			
		||||
BootstrapTokens:
 | 
			
		||||
- Description: ""
 | 
			
		||||
  Expires: null
 | 
			
		||||
  Groups:
 | 
			
		||||
  - system:bootstrappers:kubeadm:default-node-token
 | 
			
		||||
  TTL: 24h0m0s
 | 
			
		||||
  Token: s73ybu.6tw6wnqgp5z0wb77
 | 
			
		||||
  Usages:
 | 
			
		||||
  - signing
 | 
			
		||||
  - authentication
 | 
			
		||||
CIImageRepository: ""
 | 
			
		||||
CertificatesDir: /etc/kubernetes/pki
 | 
			
		||||
ClusterName: kubernetes
 | 
			
		||||
ComponentConfigs:
 | 
			
		||||
  KubeProxy:
 | 
			
		||||
    BindAddress: 0.0.0.0
 | 
			
		||||
    BindAddressHardFail: false
 | 
			
		||||
    ClientConnection:
 | 
			
		||||
      AcceptContentTypes: ""
 | 
			
		||||
      Burst: 10
 | 
			
		||||
      ContentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
      Kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
 | 
			
		||||
      QPS: 5
 | 
			
		||||
    ClusterCIDR: ""
 | 
			
		||||
    ConfigSyncPeriod: 15m0s
 | 
			
		||||
    Conntrack:
 | 
			
		||||
      MaxPerCore: 32768
 | 
			
		||||
      Min: 131072
 | 
			
		||||
      TCPCloseWaitTimeout: 1h0m0s
 | 
			
		||||
      TCPEstablishedTimeout: 24h0m0s
 | 
			
		||||
    EnableProfiling: false
 | 
			
		||||
    FeatureGates:
 | 
			
		||||
      ServiceNodeExclusion: true
 | 
			
		||||
      SupportIPVSProxyMode: true
 | 
			
		||||
    HealthzBindAddress: 0.0.0.0:10256
 | 
			
		||||
    HostnameOverride: ""
 | 
			
		||||
    IPTables:
 | 
			
		||||
      MasqueradeAll: false
 | 
			
		||||
      MasqueradeBit: 14
 | 
			
		||||
      MinSyncPeriod: 0s
 | 
			
		||||
      SyncPeriod: 30s
 | 
			
		||||
    IPVS:
 | 
			
		||||
      ExcludeCIDRs: null
 | 
			
		||||
      MinSyncPeriod: 0s
 | 
			
		||||
      Scheduler: ""
 | 
			
		||||
      SyncPeriod: 30s
 | 
			
		||||
    MetricsBindAddress: 127.0.0.1:10249
 | 
			
		||||
    Mode: iptables
 | 
			
		||||
    NodePortAddresses: null
 | 
			
		||||
    OOMScoreAdj: -999
 | 
			
		||||
    PortRange: ""
 | 
			
		||||
    UDPIdleTimeout: 250ms
 | 
			
		||||
    Winkernel:
 | 
			
		||||
      EnableDSR: false
 | 
			
		||||
      NetworkName: ""
 | 
			
		||||
      SourceVip: ""
 | 
			
		||||
  Kubelet:
 | 
			
		||||
    Address: 1.2.3.4
 | 
			
		||||
    Authentication:
 | 
			
		||||
      Anonymous:
 | 
			
		||||
        Enabled: false
 | 
			
		||||
      Webhook:
 | 
			
		||||
        CacheTTL: 2m0s
 | 
			
		||||
        Enabled: true
 | 
			
		||||
      X509:
 | 
			
		||||
        ClientCAFile: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
    Authorization:
 | 
			
		||||
      Mode: Webhook
 | 
			
		||||
      Webhook:
 | 
			
		||||
        CacheAuthorizedTTL: 5m0s
 | 
			
		||||
        CacheUnauthorizedTTL: 30s
 | 
			
		||||
    CPUCFSQuota: true
 | 
			
		||||
    CPUCFSQuotaPeriod: 0s
 | 
			
		||||
    CPUManagerPolicy: none
 | 
			
		||||
    CPUManagerReconcilePeriod: 10s
 | 
			
		||||
    CgroupDriver: cgroupfs
 | 
			
		||||
    CgroupRoot: ""
 | 
			
		||||
    CgroupsPerQOS: true
 | 
			
		||||
    ClusterDNS:
 | 
			
		||||
    - 10.96.0.10
 | 
			
		||||
    ClusterDomain: cluster.local
 | 
			
		||||
    ConfigMapAndSecretChangeDetectionStrategy: Watch
 | 
			
		||||
    ContainerLogMaxFiles: 5
 | 
			
		||||
    ContainerLogMaxSize: 10Mi
 | 
			
		||||
    ContentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
    EnableContentionProfiling: false
 | 
			
		||||
    EnableControllerAttachDetach: true
 | 
			
		||||
    EnableDebuggingHandlers: true
 | 
			
		||||
    EnforceNodeAllocatable:
 | 
			
		||||
    - pods
 | 
			
		||||
    EventBurst: 10
 | 
			
		||||
    EventRecordQPS: 5
 | 
			
		||||
    EvictionHard:
 | 
			
		||||
      imagefs.available: 15%
 | 
			
		||||
      memory.available: 100Mi
 | 
			
		||||
      nodefs.available: 10%
 | 
			
		||||
    EvictionMaxPodGracePeriod: 0
 | 
			
		||||
    EvictionMinimumReclaim: null
 | 
			
		||||
    EvictionPressureTransitionPeriod: 5m0s
 | 
			
		||||
    EvictionSoft: null
 | 
			
		||||
    EvictionSoftGracePeriod: null
 | 
			
		||||
    FailSwapOn: true
 | 
			
		||||
    FeatureGates: null
 | 
			
		||||
    FileCheckFrequency: 20s
 | 
			
		||||
    HTTPCheckFrequency: 20s
 | 
			
		||||
    HairpinMode: promiscuous-bridge
 | 
			
		||||
    HealthzBindAddress: 127.0.0.1
 | 
			
		||||
    HealthzPort: 10248
 | 
			
		||||
    IPTablesDropBit: 15
 | 
			
		||||
    IPTablesMasqueradeBit: 14
 | 
			
		||||
    ImageGCHighThresholdPercent: 85
 | 
			
		||||
    ImageGCLowThresholdPercent: 80
 | 
			
		||||
    ImageMinimumGCAge: 2m0s
 | 
			
		||||
    KubeAPIBurst: 10
 | 
			
		||||
    KubeAPIQPS: 5
 | 
			
		||||
    KubeReserved: null
 | 
			
		||||
    KubeReservedCgroup: ""
 | 
			
		||||
    KubeletCgroups: ""
 | 
			
		||||
    MakeIPTablesUtilChains: true
 | 
			
		||||
    MaxOpenFiles: 1000000
 | 
			
		||||
    MaxPods: 110
 | 
			
		||||
    NodeLeaseDurationSeconds: 40
 | 
			
		||||
    NodeStatusReportFrequency: 1m0s
 | 
			
		||||
    NodeStatusUpdateFrequency: 10s
 | 
			
		||||
    OOMScoreAdj: -999
 | 
			
		||||
    PodCIDR: ""
 | 
			
		||||
    PodPidsLimit: -1
 | 
			
		||||
    PodsPerCore: 0
 | 
			
		||||
    Port: 10250
 | 
			
		||||
    ProtectKernelDefaults: false
 | 
			
		||||
    QOSReserved: null
 | 
			
		||||
    ReadOnlyPort: 0
 | 
			
		||||
    RegistryBurst: 10
 | 
			
		||||
    RegistryPullQPS: 5
 | 
			
		||||
    ResolverConfig: /etc/resolv.conf
 | 
			
		||||
    RotateCertificates: true
 | 
			
		||||
    RuntimeRequestTimeout: 2m0s
 | 
			
		||||
    SerializeImagePulls: true
 | 
			
		||||
    ServerTLSBootstrap: false
 | 
			
		||||
    StaticPodPath: /etc/kubernetes/manifests
 | 
			
		||||
    StaticPodURL: ""
 | 
			
		||||
    StaticPodURLHeader: null
 | 
			
		||||
    StreamingConnectionIdleTimeout: 4h0m0s
 | 
			
		||||
    SyncFrequency: 1m0s
 | 
			
		||||
    SystemCgroups: ""
 | 
			
		||||
    SystemReserved: null
 | 
			
		||||
    SystemReservedCgroup: ""
 | 
			
		||||
    TLSCertFile: ""
 | 
			
		||||
    TLSCipherSuites: null
 | 
			
		||||
    TLSMinVersion: ""
 | 
			
		||||
    TLSPrivateKeyFile: ""
 | 
			
		||||
    VolumeStatsAggPeriod: 1m0s
 | 
			
		||||
ControlPlaneEndpoint: ""
 | 
			
		||||
ControllerManager:
 | 
			
		||||
  ExtraArgs: null
 | 
			
		||||
  ExtraVolumes: null
 | 
			
		||||
DNS:
 | 
			
		||||
  ImageRepository: ""
 | 
			
		||||
  ImageTag: ""
 | 
			
		||||
  Type: CoreDNS
 | 
			
		||||
Etcd:
 | 
			
		||||
  External: null
 | 
			
		||||
  Local:
 | 
			
		||||
    DataDir: /var/lib/etcd
 | 
			
		||||
    ExtraArgs: null
 | 
			
		||||
    ImageRepository: ""
 | 
			
		||||
    ImageTag: ""
 | 
			
		||||
    PeerCertSANs: null
 | 
			
		||||
    ServerCertSANs: null
 | 
			
		||||
FeatureGates: null
 | 
			
		||||
ImageRepository: k8s.gcr.io
 | 
			
		||||
KubernetesVersion: v1.12.2
 | 
			
		||||
LocalAPIEndpoint:
 | 
			
		||||
  AdvertiseAddress: 192.168.2.2
 | 
			
		||||
  BindPort: 6443
 | 
			
		||||
Networking:
 | 
			
		||||
  DNSDomain: cluster.local
 | 
			
		||||
  PodSubnet: ""
 | 
			
		||||
  ServiceSubnet: 10.96.0.0/12
 | 
			
		||||
NodeRegistration:
 | 
			
		||||
  CRISocket: /var/run/dockershim.sock
 | 
			
		||||
  KubeletExtraArgs: null
 | 
			
		||||
  Name: control-plane-1
 | 
			
		||||
  Taints:
 | 
			
		||||
  - effect: NoSchedule
 | 
			
		||||
    key: node-role.kubernetes.io/master
 | 
			
		||||
Scheduler:
 | 
			
		||||
  ExtraArgs: null
 | 
			
		||||
  ExtraVolumes: null
 | 
			
		||||
UseHyperKubeImage: true
 | 
			
		||||
@@ -1,170 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
bootstrapTokens:
 | 
			
		||||
- groups:
 | 
			
		||||
  - system:bootstrappers:kubeadm:default-node-token
 | 
			
		||||
  token: s73ybu.6tw6wnqgp5z0wb77
 | 
			
		||||
  ttl: 24h0m0s
 | 
			
		||||
  usages:
 | 
			
		||||
  - signing
 | 
			
		||||
  - authentication
 | 
			
		||||
kind: InitConfiguration
 | 
			
		||||
localAPIEndpoint:
 | 
			
		||||
  advertiseAddress: 192.168.2.2
 | 
			
		||||
  bindPort: 6443
 | 
			
		||||
nodeRegistration:
 | 
			
		||||
  criSocket: /var/run/dockershim.sock
 | 
			
		||||
  name: control-plane-1
 | 
			
		||||
  taints:
 | 
			
		||||
  - effect: NoSchedule
 | 
			
		||||
    key: node-role.kubernetes.io/master
 | 
			
		||||
---
 | 
			
		||||
apiServer:
 | 
			
		||||
  extraArgs:
 | 
			
		||||
    authorization-mode: Node,RBAC,Webhook
 | 
			
		||||
  extraVolumes:
 | 
			
		||||
  - hostPath: /host/read-only
 | 
			
		||||
    mountPath: /mount/read-only
 | 
			
		||||
    name: ReadOnlyVolume
 | 
			
		||||
    readOnly: true
 | 
			
		||||
  - hostPath: /host/writable
 | 
			
		||||
    mountPath: /mount/writable
 | 
			
		||||
    name: WritableVolume
 | 
			
		||||
  timeoutForControlPlane: 4m0s
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
certificatesDir: /etc/kubernetes/pki
 | 
			
		||||
clusterName: kubernetes
 | 
			
		||||
controlPlaneEndpoint: ""
 | 
			
		||||
controllerManager: {}
 | 
			
		||||
dns:
 | 
			
		||||
  type: CoreDNS
 | 
			
		||||
etcd:
 | 
			
		||||
  local:
 | 
			
		||||
    dataDir: /var/lib/etcd
 | 
			
		||||
imageRepository: k8s.gcr.io
 | 
			
		||||
kind: ClusterConfiguration
 | 
			
		||||
kubernetesVersion: v1.12.2
 | 
			
		||||
networking:
 | 
			
		||||
  dnsDomain: cluster.local
 | 
			
		||||
  podSubnet: ""
 | 
			
		||||
  serviceSubnet: 10.96.0.0/12
 | 
			
		||||
scheduler: {}
 | 
			
		||||
useHyperKubeImage: true
 | 
			
		||||
---
 | 
			
		||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
bindAddress: 0.0.0.0
 | 
			
		||||
bindAddressHardFail: false
 | 
			
		||||
clientConnection:
 | 
			
		||||
  acceptContentTypes: ""
 | 
			
		||||
  burst: 10
 | 
			
		||||
  contentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
  kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
 | 
			
		||||
  qps: 5
 | 
			
		||||
clusterCIDR: ""
 | 
			
		||||
configSyncPeriod: 15m0s
 | 
			
		||||
conntrack:
 | 
			
		||||
  maxPerCore: 32768
 | 
			
		||||
  min: 131072
 | 
			
		||||
  tcpCloseWaitTimeout: 1h0m0s
 | 
			
		||||
  tcpEstablishedTimeout: 24h0m0s
 | 
			
		||||
enableProfiling: false
 | 
			
		||||
featureGates:
 | 
			
		||||
  ServiceNodeExclusion: true
 | 
			
		||||
  SupportIPVSProxyMode: true
 | 
			
		||||
healthzBindAddress: 0.0.0.0:10256
 | 
			
		||||
hostnameOverride: ""
 | 
			
		||||
iptables:
 | 
			
		||||
  masqueradeAll: false
 | 
			
		||||
  masqueradeBit: 14
 | 
			
		||||
  minSyncPeriod: 0s
 | 
			
		||||
  syncPeriod: 30s
 | 
			
		||||
ipvs:
 | 
			
		||||
  excludeCIDRs: null
 | 
			
		||||
  minSyncPeriod: 0s
 | 
			
		||||
  scheduler: ""
 | 
			
		||||
  syncPeriod: 30s
 | 
			
		||||
kind: KubeProxyConfiguration
 | 
			
		||||
metricsBindAddress: 127.0.0.1:10249
 | 
			
		||||
mode: iptables
 | 
			
		||||
nodePortAddresses: null
 | 
			
		||||
oomScoreAdj: -999
 | 
			
		||||
portRange: ""
 | 
			
		||||
udpIdleTimeout: 250ms
 | 
			
		||||
winkernel:
 | 
			
		||||
  enableDSR: false
 | 
			
		||||
  networkName: ""
 | 
			
		||||
  sourceVip: ""
 | 
			
		||||
---
 | 
			
		||||
address: 1.2.3.4
 | 
			
		||||
apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
authentication:
 | 
			
		||||
  anonymous:
 | 
			
		||||
    enabled: false
 | 
			
		||||
  webhook:
 | 
			
		||||
    cacheTTL: 2m0s
 | 
			
		||||
    enabled: true
 | 
			
		||||
  x509:
 | 
			
		||||
    clientCAFile: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
authorization:
 | 
			
		||||
  mode: Webhook
 | 
			
		||||
  webhook:
 | 
			
		||||
    cacheAuthorizedTTL: 5m0s
 | 
			
		||||
    cacheUnauthorizedTTL: 30s
 | 
			
		||||
cgroupDriver: cgroupfs
 | 
			
		||||
cgroupsPerQOS: true
 | 
			
		||||
clusterDNS:
 | 
			
		||||
- 10.96.0.10
 | 
			
		||||
clusterDomain: cluster.local
 | 
			
		||||
configMapAndSecretChangeDetectionStrategy: Watch
 | 
			
		||||
containerLogMaxFiles: 5
 | 
			
		||||
containerLogMaxSize: 10Mi
 | 
			
		||||
contentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
cpuCFSQuota: true
 | 
			
		||||
cpuCFSQuotaPeriod: 0s
 | 
			
		||||
cpuManagerPolicy: none
 | 
			
		||||
cpuManagerReconcilePeriod: 10s
 | 
			
		||||
enableControllerAttachDetach: true
 | 
			
		||||
enableDebuggingHandlers: true
 | 
			
		||||
enforceNodeAllocatable:
 | 
			
		||||
- pods
 | 
			
		||||
eventBurst: 10
 | 
			
		||||
eventRecordQPS: 5
 | 
			
		||||
evictionHard:
 | 
			
		||||
  imagefs.available: 15%
 | 
			
		||||
  memory.available: 100Mi
 | 
			
		||||
  nodefs.available: 10%
 | 
			
		||||
  nodefs.inodesFree: 5%
 | 
			
		||||
evictionPressureTransitionPeriod: 5m0s
 | 
			
		||||
failSwapOn: true
 | 
			
		||||
fileCheckFrequency: 20s
 | 
			
		||||
hairpinMode: promiscuous-bridge
 | 
			
		||||
healthzBindAddress: 127.0.0.1
 | 
			
		||||
healthzPort: 10248
 | 
			
		||||
httpCheckFrequency: 20s
 | 
			
		||||
imageGCHighThresholdPercent: 85
 | 
			
		||||
imageGCLowThresholdPercent: 80
 | 
			
		||||
imageMinimumGCAge: 2m0s
 | 
			
		||||
iptablesDropBit: 15
 | 
			
		||||
iptablesMasqueradeBit: 14
 | 
			
		||||
kind: KubeletConfiguration
 | 
			
		||||
kubeAPIBurst: 10
 | 
			
		||||
kubeAPIQPS: 5
 | 
			
		||||
makeIPTablesUtilChains: true
 | 
			
		||||
maxOpenFiles: 1000000
 | 
			
		||||
maxPods: 110
 | 
			
		||||
nodeLeaseDurationSeconds: 40
 | 
			
		||||
nodeStatusReportFrequency: 1m0s
 | 
			
		||||
nodeStatusUpdateFrequency: 10s
 | 
			
		||||
oomScoreAdj: -999
 | 
			
		||||
podPidsLimit: -1
 | 
			
		||||
port: 10250
 | 
			
		||||
registryBurst: 10
 | 
			
		||||
registryPullQPS: 5
 | 
			
		||||
resolvConf: /etc/resolv.conf
 | 
			
		||||
rotateCertificates: true
 | 
			
		||||
runtimeRequestTimeout: 2m0s
 | 
			
		||||
serializeImagePulls: true
 | 
			
		||||
staticPodPath: /etc/kubernetes/manifests
 | 
			
		||||
streamingConnectionIdleTimeout: 4h0m0s
 | 
			
		||||
syncFrequency: 1m0s
 | 
			
		||||
volumeStatsAggPeriod: 1m0s
 | 
			
		||||
allowedUnsafeSysctls: []
 | 
			
		||||
@@ -1,168 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
bootstrapTokens:
 | 
			
		||||
- groups:
 | 
			
		||||
  - system:bootstrappers:kubeadm:default-node-token
 | 
			
		||||
  token: s73ybu.6tw6wnqgp5z0wb77
 | 
			
		||||
  ttl: 24h0m0s
 | 
			
		||||
  usages:
 | 
			
		||||
  - signing
 | 
			
		||||
  - authentication
 | 
			
		||||
kind: InitConfiguration
 | 
			
		||||
localAPIEndpoint:
 | 
			
		||||
  advertiseAddress: 192.168.2.2
 | 
			
		||||
  bindPort: 6443
 | 
			
		||||
nodeRegistration:
 | 
			
		||||
  criSocket: /var/run/dockershim.sock
 | 
			
		||||
  name: control-plane-1
 | 
			
		||||
  taints:
 | 
			
		||||
  - effect: NoSchedule
 | 
			
		||||
    key: node-role.kubernetes.io/master
 | 
			
		||||
---
 | 
			
		||||
apiServer:
 | 
			
		||||
  extraArgs:
 | 
			
		||||
    authorization-mode: Node,RBAC,Webhook
 | 
			
		||||
  extraVolumes:
 | 
			
		||||
  - hostPath: /host/read-only
 | 
			
		||||
    mountPath: /mount/read-only
 | 
			
		||||
    name: ReadOnlyVolume
 | 
			
		||||
    readOnly: true
 | 
			
		||||
  - hostPath: /host/writable
 | 
			
		||||
    mountPath: /mount/writable
 | 
			
		||||
    name: WritableVolume
 | 
			
		||||
  timeoutForControlPlane: 4m0s
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
certificatesDir: /etc/kubernetes/pki
 | 
			
		||||
clusterName: kubernetes
 | 
			
		||||
controlPlaneEndpoint: ""
 | 
			
		||||
controllerManager: {}
 | 
			
		||||
dns:
 | 
			
		||||
  type: CoreDNS
 | 
			
		||||
etcd:
 | 
			
		||||
  local:
 | 
			
		||||
    dataDir: /var/lib/etcd
 | 
			
		||||
imageRepository: k8s.gcr.io
 | 
			
		||||
kind: ClusterConfiguration
 | 
			
		||||
kubernetesVersion: v1.12.2
 | 
			
		||||
networking:
 | 
			
		||||
  dnsDomain: cluster.local
 | 
			
		||||
  podSubnet: ""
 | 
			
		||||
  serviceSubnet: 10.96.0.0/12
 | 
			
		||||
scheduler: {}
 | 
			
		||||
useHyperKubeImage: true
 | 
			
		||||
---
 | 
			
		||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
bindAddress: 0.0.0.0
 | 
			
		||||
bindAddressHardFail: false
 | 
			
		||||
clientConnection:
 | 
			
		||||
  acceptContentTypes: ""
 | 
			
		||||
  burst: 10
 | 
			
		||||
  contentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
  kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
 | 
			
		||||
  qps: 5
 | 
			
		||||
clusterCIDR: ""
 | 
			
		||||
configSyncPeriod: 15m0s
 | 
			
		||||
conntrack:
 | 
			
		||||
  maxPerCore: 32768
 | 
			
		||||
  min: 131072
 | 
			
		||||
  tcpCloseWaitTimeout: 1h0m0s
 | 
			
		||||
  tcpEstablishedTimeout: 24h0m0s
 | 
			
		||||
enableProfiling: false
 | 
			
		||||
featureGates:
 | 
			
		||||
  ServiceNodeExclusion: true
 | 
			
		||||
  SupportIPVSProxyMode: true
 | 
			
		||||
healthzBindAddress: 0.0.0.0:10256
 | 
			
		||||
hostnameOverride: ""
 | 
			
		||||
iptables:
 | 
			
		||||
  masqueradeAll: false
 | 
			
		||||
  masqueradeBit: 14
 | 
			
		||||
  minSyncPeriod: 0s
 | 
			
		||||
  syncPeriod: 30s
 | 
			
		||||
ipvs:
 | 
			
		||||
  excludeCIDRs: null
 | 
			
		||||
  minSyncPeriod: 0s
 | 
			
		||||
  scheduler: ""
 | 
			
		||||
  syncPeriod: 30s
 | 
			
		||||
kind: KubeProxyConfiguration
 | 
			
		||||
metricsBindAddress: 127.0.0.1:10249
 | 
			
		||||
mode: iptables
 | 
			
		||||
nodePortAddresses: null
 | 
			
		||||
oomScoreAdj: -999
 | 
			
		||||
portRange: ""
 | 
			
		||||
udpIdleTimeout: 250ms
 | 
			
		||||
winkernel:
 | 
			
		||||
  enableDSR: false
 | 
			
		||||
  networkName: ""
 | 
			
		||||
  sourceVip: ""
 | 
			
		||||
---
 | 
			
		||||
address: 1.2.3.4
 | 
			
		||||
apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
authentication:
 | 
			
		||||
  anonymous:
 | 
			
		||||
    enabled: false
 | 
			
		||||
  webhook:
 | 
			
		||||
    cacheTTL: 2m0s
 | 
			
		||||
    enabled: true
 | 
			
		||||
  x509:
 | 
			
		||||
    clientCAFile: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
authorization:
 | 
			
		||||
  mode: Webhook
 | 
			
		||||
  webhook:
 | 
			
		||||
    cacheAuthorizedTTL: 5m0s
 | 
			
		||||
    cacheUnauthorizedTTL: 30s
 | 
			
		||||
cgroupDriver: cgroupfs
 | 
			
		||||
cgroupsPerQOS: true
 | 
			
		||||
clusterDNS:
 | 
			
		||||
- 10.96.0.10
 | 
			
		||||
clusterDomain: cluster.local
 | 
			
		||||
configMapAndSecretChangeDetectionStrategy: Watch
 | 
			
		||||
containerLogMaxFiles: 5
 | 
			
		||||
containerLogMaxSize: 10Mi
 | 
			
		||||
contentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
cpuCFSQuota: true
 | 
			
		||||
cpuCFSQuotaPeriod: 0s
 | 
			
		||||
cpuManagerPolicy: none
 | 
			
		||||
cpuManagerReconcilePeriod: 10s
 | 
			
		||||
enableControllerAttachDetach: true
 | 
			
		||||
enableDebuggingHandlers: true
 | 
			
		||||
enforceNodeAllocatable:
 | 
			
		||||
- pods
 | 
			
		||||
eventBurst: 10
 | 
			
		||||
eventRecordQPS: 5
 | 
			
		||||
evictionHard:
 | 
			
		||||
  imagefs.available: 15%
 | 
			
		||||
  memory.available: 100Mi
 | 
			
		||||
  nodefs.available: 10%
 | 
			
		||||
evictionPressureTransitionPeriod: 5m0s
 | 
			
		||||
failSwapOn: true
 | 
			
		||||
fileCheckFrequency: 20s
 | 
			
		||||
hairpinMode: promiscuous-bridge
 | 
			
		||||
healthzBindAddress: 127.0.0.1
 | 
			
		||||
healthzPort: 10248
 | 
			
		||||
httpCheckFrequency: 20s
 | 
			
		||||
imageGCHighThresholdPercent: 85
 | 
			
		||||
imageGCLowThresholdPercent: 80
 | 
			
		||||
imageMinimumGCAge: 2m0s
 | 
			
		||||
iptablesDropBit: 15
 | 
			
		||||
iptablesMasqueradeBit: 14
 | 
			
		||||
kind: KubeletConfiguration
 | 
			
		||||
kubeAPIBurst: 10
 | 
			
		||||
kubeAPIQPS: 5
 | 
			
		||||
makeIPTablesUtilChains: true
 | 
			
		||||
maxOpenFiles: 1000000
 | 
			
		||||
maxPods: 110
 | 
			
		||||
nodeLeaseDurationSeconds: 40
 | 
			
		||||
nodeStatusReportFrequency: 1m0s
 | 
			
		||||
nodeStatusUpdateFrequency: 10s
 | 
			
		||||
oomScoreAdj: -999
 | 
			
		||||
podPidsLimit: -1
 | 
			
		||||
port: 10250
 | 
			
		||||
registryBurst: 10
 | 
			
		||||
registryPullQPS: 5
 | 
			
		||||
resolvConf: /etc/resolv.conf
 | 
			
		||||
rotateCertificates: true
 | 
			
		||||
runtimeRequestTimeout: 2m0s
 | 
			
		||||
serializeImagePulls: true
 | 
			
		||||
staticPodPath: /etc/kubernetes/manifests
 | 
			
		||||
streamingConnectionIdleTimeout: 4h0m0s
 | 
			
		||||
syncFrequency: 1m0s
 | 
			
		||||
volumeStatsAggPeriod: 1m0s
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
CACertPath: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
ControlPlane:
 | 
			
		||||
  CertificateKey: ""
 | 
			
		||||
  LocalAPIEndpoint:
 | 
			
		||||
    AdvertiseAddress: 192.168.2.2
 | 
			
		||||
    BindPort: 6443
 | 
			
		||||
Discovery:
 | 
			
		||||
  BootstrapToken:
 | 
			
		||||
    APIServerEndpoint: kube-apiserver:6443
 | 
			
		||||
    CACertHashes: null
 | 
			
		||||
    Token: abcdef.0123456789abcdef
 | 
			
		||||
    UnsafeSkipCAVerification: true
 | 
			
		||||
  File: null
 | 
			
		||||
  TLSBootstrapToken: abcdef.0123456789abcdef
 | 
			
		||||
  Timeout: 5m0s
 | 
			
		||||
NodeRegistration:
 | 
			
		||||
  CRISocket: /var/run/dockershim.sock
 | 
			
		||||
  IgnorePreflightErrors: null
 | 
			
		||||
  KubeletExtraArgs: null
 | 
			
		||||
  Name: control-plane-1
 | 
			
		||||
  Taints:
 | 
			
		||||
  - effect: NoSchedule
 | 
			
		||||
    key: node-role.kubernetes.io/master
 | 
			
		||||
@@ -1,20 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
caCertPath: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
controlPlane:
 | 
			
		||||
  localAPIEndpoint:
 | 
			
		||||
    advertiseAddress: 192.168.2.2
 | 
			
		||||
    bindPort: 6443
 | 
			
		||||
discovery:
 | 
			
		||||
  bootstrapToken:
 | 
			
		||||
    apiServerEndpoint: kube-apiserver:6443
 | 
			
		||||
    token: abcdef.0123456789abcdef
 | 
			
		||||
    unsafeSkipCAVerification: true
 | 
			
		||||
  timeout: 5m0s
 | 
			
		||||
  tlsBootstrapToken: abcdef.0123456789abcdef
 | 
			
		||||
kind: JoinConfiguration
 | 
			
		||||
nodeRegistration:
 | 
			
		||||
  criSocket: /var/run/dockershim.sock
 | 
			
		||||
  name: control-plane-1
 | 
			
		||||
  taints:
 | 
			
		||||
  - effect: NoSchedule
 | 
			
		||||
    key: node-role.kubernetes.io/master
 | 
			
		||||
@@ -1,20 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta2
 | 
			
		||||
caCertPath: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
controlPlane:
 | 
			
		||||
  localAPIEndpoint:
 | 
			
		||||
    advertiseAddress: 192.168.2.2
 | 
			
		||||
    bindPort: 6443
 | 
			
		||||
discovery:
 | 
			
		||||
  bootstrapToken:
 | 
			
		||||
    apiServerEndpoint: kube-apiserver:6443
 | 
			
		||||
    token: abcdef.0123456789abcdef
 | 
			
		||||
    unsafeSkipCAVerification: true
 | 
			
		||||
  timeout: 5m0s
 | 
			
		||||
  tlsBootstrapToken: abcdef.0123456789abcdef
 | 
			
		||||
kind: JoinConfiguration
 | 
			
		||||
nodeRegistration:
 | 
			
		||||
  criSocket: /var/run/dockershim.sock
 | 
			
		||||
  name: control-plane-1
 | 
			
		||||
  taints:
 | 
			
		||||
  - effect: NoSchedule
 | 
			
		||||
    key: node-role.kubernetes.io/master
 | 
			
		||||
@@ -1,155 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
bootstrapTokens:
 | 
			
		||||
- groups:
 | 
			
		||||
  - system:bootstrappers:kubeadm:default-node-token
 | 
			
		||||
  token: s73ybu.6tw6wnqgp5z0wb77
 | 
			
		||||
  ttl: 24h0m0s
 | 
			
		||||
  usages:
 | 
			
		||||
  - signing
 | 
			
		||||
  - authentication
 | 
			
		||||
kind: InitConfiguration
 | 
			
		||||
localAPIEndpoint:
 | 
			
		||||
  advertiseAddress: 192.168.2.2
 | 
			
		||||
  bindPort: 6443
 | 
			
		||||
nodeRegistration:
 | 
			
		||||
  criSocket: /var/run/criruntime.sock
 | 
			
		||||
  name: control-plane-1
 | 
			
		||||
  taints:
 | 
			
		||||
  - effect: NoSchedule
 | 
			
		||||
    key: node-role.kubernetes.io/master
 | 
			
		||||
---
 | 
			
		||||
apiServer:
 | 
			
		||||
  timeoutForControlPlane: 4m0s
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
certificatesDir: /var/lib/kubernetes/pki
 | 
			
		||||
clusterName: kubernetes
 | 
			
		||||
controlPlaneEndpoint: ""
 | 
			
		||||
controllerManager: {}
 | 
			
		||||
dns:
 | 
			
		||||
  type: CoreDNS
 | 
			
		||||
etcd:
 | 
			
		||||
  local:
 | 
			
		||||
    dataDir: /var/lib/etcd
 | 
			
		||||
imageRepository: my-company.com
 | 
			
		||||
kind: ClusterConfiguration
 | 
			
		||||
kubernetesVersion: v1.13.0
 | 
			
		||||
networking:
 | 
			
		||||
  dnsDomain: cluster.global
 | 
			
		||||
  podSubnet: 10.148.0.0/16
 | 
			
		||||
  serviceSubnet: 10.196.0.0/12
 | 
			
		||||
scheduler: {}
 | 
			
		||||
---
 | 
			
		||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
bindAddress: 0.0.0.0
 | 
			
		||||
bindAddressHardFail: false
 | 
			
		||||
clientConnection:
 | 
			
		||||
  acceptContentTypes: ""
 | 
			
		||||
  burst: 10
 | 
			
		||||
  contentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
  kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
 | 
			
		||||
  qps: 5
 | 
			
		||||
clusterCIDR: 10.148.0.0/16
 | 
			
		||||
configSyncPeriod: 15m0s
 | 
			
		||||
conntrack:
 | 
			
		||||
  maxPerCore: 32768
 | 
			
		||||
  min: 131072
 | 
			
		||||
  tcpCloseWaitTimeout: 1h0m0s
 | 
			
		||||
  tcpEstablishedTimeout: 24h0m0s
 | 
			
		||||
enableProfiling: false
 | 
			
		||||
healthzBindAddress: 0.0.0.0:10256
 | 
			
		||||
hostnameOverride: ""
 | 
			
		||||
iptables:
 | 
			
		||||
  masqueradeAll: false
 | 
			
		||||
  masqueradeBit: 14
 | 
			
		||||
  minSyncPeriod: 0s
 | 
			
		||||
  syncPeriod: 30s
 | 
			
		||||
ipvs:
 | 
			
		||||
  excludeCIDRs: null
 | 
			
		||||
  minSyncPeriod: 0s
 | 
			
		||||
  scheduler: ""
 | 
			
		||||
  syncPeriod: 30s
 | 
			
		||||
kind: KubeProxyConfiguration
 | 
			
		||||
metricsBindAddress: 127.0.0.1:10249
 | 
			
		||||
mode: ""
 | 
			
		||||
nodePortAddresses: null
 | 
			
		||||
oomScoreAdj: -999
 | 
			
		||||
portRange: ""
 | 
			
		||||
udpIdleTimeout: 250ms
 | 
			
		||||
winkernel:
 | 
			
		||||
  enableDSR: false
 | 
			
		||||
  networkName: ""
 | 
			
		||||
  sourceVip: ""
 | 
			
		||||
---
 | 
			
		||||
address: 0.0.0.0
 | 
			
		||||
apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
authentication:
 | 
			
		||||
  anonymous:
 | 
			
		||||
    enabled: false
 | 
			
		||||
  webhook:
 | 
			
		||||
    cacheTTL: 2m0s
 | 
			
		||||
    enabled: true
 | 
			
		||||
  x509:
 | 
			
		||||
    clientCAFile: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
authorization:
 | 
			
		||||
  mode: Webhook
 | 
			
		||||
  webhook:
 | 
			
		||||
    cacheAuthorizedTTL: 5m0s
 | 
			
		||||
    cacheUnauthorizedTTL: 30s
 | 
			
		||||
cgroupDriver: cgroupfs
 | 
			
		||||
cgroupsPerQOS: true
 | 
			
		||||
clusterDNS:
 | 
			
		||||
- 10.192.0.10
 | 
			
		||||
clusterDomain: cluster.global
 | 
			
		||||
configMapAndSecretChangeDetectionStrategy: Watch
 | 
			
		||||
containerLogMaxFiles: 5
 | 
			
		||||
containerLogMaxSize: 10Mi
 | 
			
		||||
contentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
cpuCFSQuota: true
 | 
			
		||||
cpuCFSQuotaPeriod: 100ms
 | 
			
		||||
cpuManagerPolicy: none
 | 
			
		||||
cpuManagerReconcilePeriod: 10s
 | 
			
		||||
enableControllerAttachDetach: true
 | 
			
		||||
enableDebuggingHandlers: true
 | 
			
		||||
enforceNodeAllocatable:
 | 
			
		||||
- pods
 | 
			
		||||
eventBurst: 10
 | 
			
		||||
eventRecordQPS: 5
 | 
			
		||||
evictionHard:
 | 
			
		||||
  imagefs.available: 15%
 | 
			
		||||
  memory.available: 100Mi
 | 
			
		||||
  nodefs.available: 10%
 | 
			
		||||
  nodefs.inodesFree: 5%
 | 
			
		||||
evictionPressureTransitionPeriod: 5m0s
 | 
			
		||||
failSwapOn: true
 | 
			
		||||
fileCheckFrequency: 20s
 | 
			
		||||
hairpinMode: promiscuous-bridge
 | 
			
		||||
healthzBindAddress: 127.0.0.1
 | 
			
		||||
healthzPort: 10248
 | 
			
		||||
httpCheckFrequency: 20s
 | 
			
		||||
imageGCHighThresholdPercent: 85
 | 
			
		||||
imageGCLowThresholdPercent: 80
 | 
			
		||||
imageMinimumGCAge: 2m0s
 | 
			
		||||
iptablesDropBit: 15
 | 
			
		||||
iptablesMasqueradeBit: 14
 | 
			
		||||
kind: KubeletConfiguration
 | 
			
		||||
kubeAPIBurst: 10
 | 
			
		||||
kubeAPIQPS: 5
 | 
			
		||||
makeIPTablesUtilChains: true
 | 
			
		||||
maxOpenFiles: 1000000
 | 
			
		||||
maxPods: 110
 | 
			
		||||
nodeLeaseDurationSeconds: 40
 | 
			
		||||
nodeStatusReportFrequency: 1m0s
 | 
			
		||||
nodeStatusUpdateFrequency: 10s
 | 
			
		||||
oomScoreAdj: -999
 | 
			
		||||
podPidsLimit: -1
 | 
			
		||||
port: 10250
 | 
			
		||||
registryBurst: 10
 | 
			
		||||
registryPullQPS: 5
 | 
			
		||||
resolvConf: /etc/resolv.conf
 | 
			
		||||
rotateCertificates: true
 | 
			
		||||
runtimeRequestTimeout: 2m0s
 | 
			
		||||
serializeImagePulls: true
 | 
			
		||||
staticPodPath: /etc/kubernetes/manifests
 | 
			
		||||
streamingConnectionIdleTimeout: 4h0m0s
 | 
			
		||||
syncFrequency: 1m0s
 | 
			
		||||
volumeStatsAggPeriod: 1m0s
 | 
			
		||||
@@ -1,154 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
bootstrapTokens:
 | 
			
		||||
- groups:
 | 
			
		||||
  - system:bootstrappers:kubeadm:default-node-token
 | 
			
		||||
  token: s73ybu.6tw6wnqgp5z0wb77
 | 
			
		||||
  ttl: 24h0m0s
 | 
			
		||||
  usages:
 | 
			
		||||
  - signing
 | 
			
		||||
  - authentication
 | 
			
		||||
kind: InitConfiguration
 | 
			
		||||
localAPIEndpoint:
 | 
			
		||||
  advertiseAddress: 192.168.2.2
 | 
			
		||||
  bindPort: 6443
 | 
			
		||||
nodeRegistration:
 | 
			
		||||
  criSocket: /var/run/criruntime.sock
 | 
			
		||||
  name: control-plane-1
 | 
			
		||||
  taints:
 | 
			
		||||
  - effect: NoSchedule
 | 
			
		||||
    key: node-role.kubernetes.io/master
 | 
			
		||||
---
 | 
			
		||||
apiServer:
 | 
			
		||||
  timeoutForControlPlane: 4m0s
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
certificatesDir: /var/lib/kubernetes/pki
 | 
			
		||||
clusterName: kubernetes
 | 
			
		||||
controlPlaneEndpoint: ""
 | 
			
		||||
controllerManager: {}
 | 
			
		||||
dns:
 | 
			
		||||
  type: CoreDNS
 | 
			
		||||
etcd:
 | 
			
		||||
  local:
 | 
			
		||||
    dataDir: /var/lib/etcd
 | 
			
		||||
imageRepository: my-company.com
 | 
			
		||||
kind: ClusterConfiguration
 | 
			
		||||
kubernetesVersion: v1.13.0
 | 
			
		||||
networking:
 | 
			
		||||
  dnsDomain: cluster.global
 | 
			
		||||
  podSubnet: 10.148.0.0/16
 | 
			
		||||
  serviceSubnet: 10.196.0.0/12
 | 
			
		||||
scheduler: {}
 | 
			
		||||
---
 | 
			
		||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
 | 
			
		||||
bindAddress: 0.0.0.0
 | 
			
		||||
bindAddressHardFail: false
 | 
			
		||||
clientConnection:
 | 
			
		||||
  acceptContentTypes: ""
 | 
			
		||||
  burst: 10
 | 
			
		||||
  contentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
  kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
 | 
			
		||||
  qps: 5
 | 
			
		||||
clusterCIDR: 10.148.0.0/16
 | 
			
		||||
configSyncPeriod: 15m0s
 | 
			
		||||
conntrack:
 | 
			
		||||
  maxPerCore: 32768
 | 
			
		||||
  min: 131072
 | 
			
		||||
  tcpCloseWaitTimeout: 1h0m0s
 | 
			
		||||
  tcpEstablishedTimeout: 24h0m0s
 | 
			
		||||
enableProfiling: false
 | 
			
		||||
healthzBindAddress: 0.0.0.0:10256
 | 
			
		||||
hostnameOverride: ""
 | 
			
		||||
iptables:
 | 
			
		||||
  masqueradeAll: false
 | 
			
		||||
  masqueradeBit: 14
 | 
			
		||||
  minSyncPeriod: 0s
 | 
			
		||||
  syncPeriod: 30s
 | 
			
		||||
ipvs:
 | 
			
		||||
  excludeCIDRs: null
 | 
			
		||||
  minSyncPeriod: 0s
 | 
			
		||||
  scheduler: ""
 | 
			
		||||
  syncPeriod: 30s
 | 
			
		||||
kind: KubeProxyConfiguration
 | 
			
		||||
metricsBindAddress: 127.0.0.1:10249
 | 
			
		||||
mode: ""
 | 
			
		||||
nodePortAddresses: null
 | 
			
		||||
oomScoreAdj: -999
 | 
			
		||||
portRange: ""
 | 
			
		||||
udpIdleTimeout: 250ms
 | 
			
		||||
winkernel:
 | 
			
		||||
  enableDSR: false
 | 
			
		||||
  networkName: ""
 | 
			
		||||
  sourceVip: ""
 | 
			
		||||
---
 | 
			
		||||
address: 0.0.0.0
 | 
			
		||||
apiVersion: kubelet.config.k8s.io/v1beta1
 | 
			
		||||
authentication:
 | 
			
		||||
  anonymous:
 | 
			
		||||
    enabled: false
 | 
			
		||||
  webhook:
 | 
			
		||||
    cacheTTL: 2m0s
 | 
			
		||||
    enabled: true
 | 
			
		||||
  x509:
 | 
			
		||||
    clientCAFile: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
authorization:
 | 
			
		||||
  mode: Webhook
 | 
			
		||||
  webhook:
 | 
			
		||||
    cacheAuthorizedTTL: 5m0s
 | 
			
		||||
    cacheUnauthorizedTTL: 30s
 | 
			
		||||
cgroupDriver: cgroupfs
 | 
			
		||||
cgroupsPerQOS: true
 | 
			
		||||
clusterDNS:
 | 
			
		||||
- 10.192.0.10
 | 
			
		||||
clusterDomain: cluster.global
 | 
			
		||||
configMapAndSecretChangeDetectionStrategy: Watch
 | 
			
		||||
containerLogMaxFiles: 5
 | 
			
		||||
containerLogMaxSize: 10Mi
 | 
			
		||||
contentType: application/vnd.kubernetes.protobuf
 | 
			
		||||
cpuCFSQuota: true
 | 
			
		||||
cpuCFSQuotaPeriod: 100ms
 | 
			
		||||
cpuManagerPolicy: none
 | 
			
		||||
cpuManagerReconcilePeriod: 10s
 | 
			
		||||
enableControllerAttachDetach: true
 | 
			
		||||
enableDebuggingHandlers: true
 | 
			
		||||
enforceNodeAllocatable:
 | 
			
		||||
- pods
 | 
			
		||||
eventBurst: 10
 | 
			
		||||
eventRecordQPS: 5
 | 
			
		||||
evictionHard:
 | 
			
		||||
  imagefs.available: 15%
 | 
			
		||||
  memory.available: 100Mi
 | 
			
		||||
  nodefs.available: 10%
 | 
			
		||||
evictionPressureTransitionPeriod: 5m0s
 | 
			
		||||
failSwapOn: true
 | 
			
		||||
fileCheckFrequency: 20s
 | 
			
		||||
hairpinMode: promiscuous-bridge
 | 
			
		||||
healthzBindAddress: 127.0.0.1
 | 
			
		||||
healthzPort: 10248
 | 
			
		||||
httpCheckFrequency: 20s
 | 
			
		||||
imageGCHighThresholdPercent: 85
 | 
			
		||||
imageGCLowThresholdPercent: 80
 | 
			
		||||
imageMinimumGCAge: 2m0s
 | 
			
		||||
iptablesDropBit: 15
 | 
			
		||||
iptablesMasqueradeBit: 14
 | 
			
		||||
kind: KubeletConfiguration
 | 
			
		||||
kubeAPIBurst: 10
 | 
			
		||||
kubeAPIQPS: 5
 | 
			
		||||
makeIPTablesUtilChains: true
 | 
			
		||||
maxOpenFiles: 1000000
 | 
			
		||||
maxPods: 110
 | 
			
		||||
nodeLeaseDurationSeconds: 40
 | 
			
		||||
nodeStatusReportFrequency: 1m0s
 | 
			
		||||
nodeStatusUpdateFrequency: 10s
 | 
			
		||||
oomScoreAdj: -999
 | 
			
		||||
podPidsLimit: -1
 | 
			
		||||
port: 10250
 | 
			
		||||
registryBurst: 10
 | 
			
		||||
registryPullQPS: 5
 | 
			
		||||
resolvConf: /etc/resolv.conf
 | 
			
		||||
rotateCertificates: true
 | 
			
		||||
runtimeRequestTimeout: 2m0s
 | 
			
		||||
serializeImagePulls: true
 | 
			
		||||
staticPodPath: /etc/kubernetes/manifests
 | 
			
		||||
streamingConnectionIdleTimeout: 4h0m0s
 | 
			
		||||
syncFrequency: 1m0s
 | 
			
		||||
volumeStatsAggPeriod: 1m0s
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
kind: InitConfiguration
 | 
			
		||||
bootstrapTokens:
 | 
			
		||||
- token: s73ybu.6tw6wnqgp5z0wb77
 | 
			
		||||
localAPIEndpoint:
 | 
			
		||||
  advertiseAddress: 192.168.2.2
 | 
			
		||||
nodeRegistration:
 | 
			
		||||
  criSocket: /var/run/criruntime.sock
 | 
			
		||||
  name: control-plane-1
 | 
			
		||||
---
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
certificatesDir: /var/lib/kubernetes/pki
 | 
			
		||||
imageRepository: my-company.com
 | 
			
		||||
kind: ClusterConfiguration
 | 
			
		||||
kubernetesVersion: v1.13.0
 | 
			
		||||
networking:
 | 
			
		||||
  dnsDomain: cluster.global
 | 
			
		||||
  podSubnet: 10.148.0.0/16
 | 
			
		||||
  serviceSubnet: 10.196.0.0/12
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta2
 | 
			
		||||
caCertPath: /etc/kubernetes/pki/ca.crt
 | 
			
		||||
discovery:
 | 
			
		||||
  bootstrapToken:
 | 
			
		||||
    apiServerEndpoint: kube-apiserver:6443
 | 
			
		||||
    token: abcdef.0123456789abcdef
 | 
			
		||||
    unsafeSkipCAVerification: true
 | 
			
		||||
  timeout: 5m0s
 | 
			
		||||
  tlsBootstrapToken: abcdef.0123456789abcdef
 | 
			
		||||
kind: JoinConfiguration
 | 
			
		||||
nodeRegistration:
 | 
			
		||||
  criSocket: /var/run/dockershim.sock
 | 
			
		||||
  name: thegopher
 | 
			
		||||
  taints: null
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta2
 | 
			
		||||
discovery:
 | 
			
		||||
  bootstrapToken:
 | 
			
		||||
    apiServerEndpoint: kube-apiserver:6443
 | 
			
		||||
    token: abcdef.0123456789abcdef
 | 
			
		||||
    unsafeSkipCAVerification: true
 | 
			
		||||
  tlsBootstrapToken: abcdef.0123456789abcdef
 | 
			
		||||
kind: JoinConfiguration
 | 
			
		||||
nodeRegistration:
 | 
			
		||||
  criSocket: /var/run/dockershim.sock
 | 
			
		||||
  name: thegopher
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta1
 | 
			
		||||
kind: ClusterConfiguration
 | 
			
		||||
networking:
 | 
			
		||||
  dnsDomain: INVALID-DOMAIN-!!!!
 | 
			
		||||
  podSubnet: ""
 | 
			
		||||
  serviceSubnet: 10.96.0.0/12
 | 
			
		||||
useHyperKubeImage: false
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
apiVersion: kubeadm.k8s.io/v1beta2
 | 
			
		||||
kind: NodeConfiguration
 | 
			
		||||
caCertPath: relativepath
 | 
			
		||||
discovery:
 | 
			
		||||
  timeout: not-a-time
 | 
			
		||||
  bootstrapToken:
 | 
			
		||||
    token: invalidtoken
 | 
			
		||||
    apiServerEndpoints:
 | 
			
		||||
    - INVALID_URL
 | 
			
		||||
    unsafeSkipCAVerification: false
 | 
			
		||||
  file:
 | 
			
		||||
    kubeConfigPath: relativepath
 | 
			
		||||
nodeRegistration:
 | 
			
		||||
  criSocket: relativepath
 | 
			
		||||
  name: NODE-1
 | 
			
		||||
		Reference in New Issue
	
	Block a user