mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 21:17:23 +00:00
Merge pull request #92435 from rosti/kubeadm-cc-test-refactor
kubeadm: refactor and cleanup component config tests
This commit is contained in:
commit
6eca9f653b
@ -45,12 +45,14 @@ go_test(
|
|||||||
srcs = [
|
srcs = [
|
||||||
"checksums_test.go",
|
"checksums_test.go",
|
||||||
"configset_test.go",
|
"configset_test.go",
|
||||||
|
"fakeconfig_test.go",
|
||||||
"kubelet_test.go",
|
"kubelet_test.go",
|
||||||
"kubeproxy_test.go",
|
"kubeproxy_test.go",
|
||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
"//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/kubeadm/v1beta2:go_default_library",
|
||||||
"//cmd/kubeadm/app/apis/output:go_default_library",
|
"//cmd/kubeadm/app/apis/output:go_default_library",
|
||||||
"//cmd/kubeadm/app/constants: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/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/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/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/client-go/kubernetes/fake:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/config/v1alpha1: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",
|
"//staging/src/k8s.io/kube-proxy/config/v1alpha1:go_default_library",
|
||||||
|
@ -17,25 +17,26 @@ limitations under the License.
|
|||||||
package componentconfigs
|
package componentconfigs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lithammer/dedent"
|
"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/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
|
||||||
clientsetfake "k8s.io/client-go/kubernetes/fake"
|
clientsetfake "k8s.io/client-go/kubernetes/fake"
|
||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
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"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func testClusterCfg() *kubeadmapi.ClusterConfiguration {
|
||||||
|
return &kubeadmapi.ClusterConfiguration{
|
||||||
|
KubernetesVersion: constants.CurrentKubernetesVersion.String(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDefault(t *testing.T) {
|
func TestDefault(t *testing.T) {
|
||||||
clusterCfg := &kubeadmapi.ClusterConfiguration{}
|
clusterCfg := testClusterCfg()
|
||||||
localAPIEndpoint := &kubeadmapi.APIEndpoint{}
|
localAPIEndpoint := &kubeadmapi.APIEndpoint{}
|
||||||
nodeRegOps := &kubeadmapi.NodeRegistrationOptions{}
|
nodeRegOps := &kubeadmapi.NodeRegistrationOptions{}
|
||||||
|
|
||||||
@ -47,39 +48,18 @@ func TestDefault(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFromCluster(t *testing.T) {
|
func TestFromCluster(t *testing.T) {
|
||||||
clusterCfg := &kubeadmapi.ClusterConfiguration{
|
|
||||||
KubernetesVersion: constants.CurrentKubernetesVersion.String(),
|
|
||||||
}
|
|
||||||
|
|
||||||
k8sVersion := version.MustParseGeneric(clusterCfg.KubernetesVersion)
|
|
||||||
|
|
||||||
objects := []runtime.Object{
|
objects := []runtime.Object{
|
||||||
&v1.ConfigMap{
|
testKubeProxyConfigMap(`
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: constants.KubeProxyConfigMap,
|
|
||||||
Namespace: metav1.NamespaceSystem,
|
|
||||||
},
|
|
||||||
Data: map[string]string{
|
|
||||||
constants.KubeProxyConfigMapKey: dedent.Dedent(`
|
|
||||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||||
kind: KubeProxyConfiguration
|
kind: KubeProxyConfiguration
|
||||||
`),
|
`),
|
||||||
},
|
testKubeletConfigMap(`
|
||||||
},
|
|
||||||
&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
|
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||||
kind: KubeletConfiguration
|
kind: KubeletConfiguration
|
||||||
`),
|
`),
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
client := clientsetfake.NewSimpleClientset(objects...)
|
client := clientsetfake.NewSimpleClientset(objects...)
|
||||||
|
clusterCfg := testClusterCfg()
|
||||||
|
|
||||||
if err := FetchFromCluster(clusterCfg, client); err != nil {
|
if err := FetchFromCluster(clusterCfg, client); err != nil {
|
||||||
t.Fatalf("FetchFromCluster failed: %v", err)
|
t.Fatalf("FetchFromCluster failed: %v", err)
|
||||||
@ -103,7 +83,7 @@ func TestFetchFromDocumentMap(t *testing.T) {
|
|||||||
t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
|
t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
clusterCfg := &kubeadmapi.ClusterConfiguration{}
|
clusterCfg := testClusterCfg()
|
||||||
if err = FetchFromDocumentMap(clusterCfg, gvkmap); err != nil {
|
if err = FetchFromDocumentMap(clusterCfg, gvkmap); err != nil {
|
||||||
t.Fatalf("FetchFromDocumentMap failed: %v", err)
|
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))
|
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
|
package componentconfigs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lithammer/dedent"
|
"github.com/lithammer/dedent"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/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"
|
clientsetfake "k8s.io/client-go/kubernetes/fake"
|
||||||
kubeletconfig "k8s.io/kubelet/config/v1beta1"
|
kubeletconfig "k8s.io/kubelet/config/v1beta1"
|
||||||
utilpointer "k8s.io/utils/pointer"
|
utilpointer "k8s.io/utils/pointer"
|
||||||
@ -37,139 +35,17 @@ import (
|
|||||||
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
"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
|
func testKubeletConfigMap(contents string) *v1.ConfigMap {
|
||||||
var kubeletMarshalCases = []struct {
|
return &v1.ConfigMap{
|
||||||
name string
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
obj *kubeletConfig
|
Name: constants.GetKubeletConfigMapName(constants.CurrentKubernetesVersion),
|
||||||
yaml string
|
Namespace: metav1.NamespaceSystem,
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Empty config",
|
|
||||||
obj: &kubeletConfig{
|
|
||||||
configBase: configBase{
|
|
||||||
GroupVersion: kubeletconfig.SchemeGroupVersion,
|
|
||||||
},
|
},
|
||||||
config: kubeletconfig.KubeletConfiguration{
|
Data: map[string]string{
|
||||||
TypeMeta: metav1.TypeMeta{
|
constants.KubeletBaseConfigurationConfigMapKey: dedent.Dedent(contents),
|
||||||
APIVersion: kubeletconfig.SchemeGroupVersion.String(),
|
|
||||||
Kind: "KubeletConfiguration",
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
},
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
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
|
// 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)) {
|
func runKubeletFromTest(t *testing.T, perform func(gvk schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error)) {
|
||||||
tests := []struct {
|
const (
|
||||||
name string
|
kind = "KubeletConfiguration"
|
||||||
in string
|
clusterDomain = "foo.bar"
|
||||||
out *kubeletConfig
|
)
|
||||||
expectErr bool
|
|
||||||
}{
|
gvk := kubeletHandler.GroupVersion.WithKind(kind)
|
||||||
{
|
yaml := fmt.Sprintf("apiVersion: %s\nkind: %s\nclusterDomain: %s", kubeletHandler.GroupVersion, kind, clusterDomain)
|
||||||
name: "Empty document map should return nothing successfully",
|
|
||||||
},
|
cfg, err := perform(gvk, yaml)
|
||||||
{
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
componentCfg, err := perform(t, test.in)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !test.expectErr {
|
t.Fatalf("unexpected failure: %v", err)
|
||||||
t.Errorf("unexpected failure: %v", err)
|
|
||||||
}
|
}
|
||||||
} else {
|
if cfg == nil {
|
||||||
if test.expectErr {
|
t.Fatal("no config loaded where it should have been")
|
||||||
t.Error("unexpected success")
|
|
||||||
} else {
|
|
||||||
if componentCfg == nil {
|
|
||||||
if test.out != nil {
|
|
||||||
t.Error("unexpected nil result")
|
|
||||||
}
|
}
|
||||||
} else {
|
if kubeletCfg, ok := cfg.(*kubeletConfig); !ok {
|
||||||
if got, ok := componentCfg.(*kubeletConfig); !ok {
|
t.Fatalf("found different object type than expected: %s", reflect.TypeOf(cfg))
|
||||||
t.Error("different result type")
|
} else if kubeletCfg.config.ClusterDomain != clusterDomain {
|
||||||
} else {
|
t.Fatalf("unexpected control value (clusterDomain):\n\tgot: %q\n\texpected: %q", kubeletCfg.config.ClusterDomain, clusterDomain)
|
||||||
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 TestKubeletFromDocumentMap(t *testing.T) {
|
func TestKubeletFromDocumentMap(t *testing.T) {
|
||||||
runKubeletFromTest(t, func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error) {
|
runKubeletFromTest(t, func(gvk schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error) {
|
||||||
gvkmap, err := kubeadmutil.SplitYAMLDocuments([]byte(in))
|
return kubeletHandler.FromDocumentMap(kubeadmapi.DocumentMap{
|
||||||
if err != nil {
|
gvk: []byte(yaml),
|
||||||
t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
|
})
|
||||||
}
|
|
||||||
|
|
||||||
return kubeletHandler.FromDocumentMap(gvkmap)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKubeletFromCluster(t *testing.T) {
|
func TestKubeletFromCluster(t *testing.T) {
|
||||||
runKubeletFromTest(t, func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error) {
|
runKubeletFromTest(t, func(_ schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error) {
|
||||||
clusterCfg := &kubeadmapi.ClusterConfiguration{
|
|
||||||
KubernetesVersion: constants.CurrentKubernetesVersion.String(),
|
|
||||||
}
|
|
||||||
|
|
||||||
k8sVersion := version.MustParseGeneric(clusterCfg.KubernetesVersion)
|
|
||||||
|
|
||||||
client := clientsetfake.NewSimpleClientset(
|
client := clientsetfake.NewSimpleClientset(
|
||||||
&v1.ConfigMap{
|
testKubeletConfigMap(yaml),
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: constants.GetKubeletConfigMapName(k8sVersion),
|
|
||||||
Namespace: metav1.NamespaceSystem,
|
|
||||||
},
|
|
||||||
Data: map[string]string{
|
|
||||||
constants.KubeletBaseConfigurationConfigMapKey: in,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
return kubeletHandler.FromCluster(client, testClusterCfg())
|
||||||
return kubeletHandler.FromCluster(client, clusterCfg)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
package componentconfigs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lithammer/dedent"
|
"github.com/lithammer/dedent"
|
||||||
@ -31,185 +29,22 @@ import (
|
|||||||
componentbaseconfig "k8s.io/component-base/config/v1alpha1"
|
componentbaseconfig "k8s.io/component-base/config/v1alpha1"
|
||||||
kubeproxyconfig "k8s.io/kube-proxy/config/v1alpha1"
|
kubeproxyconfig "k8s.io/kube-proxy/config/v1alpha1"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
"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
|
func testKubeProxyConfigMap(contents string) *v1.ConfigMap {
|
||||||
var kubeProxyMarshalCases = []struct {
|
return &v1.ConfigMap{
|
||||||
name string
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
obj *kubeProxyConfig
|
Name: constants.KubeProxyConfigMap,
|
||||||
yaml string
|
Namespace: metav1.NamespaceSystem,
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Empty config",
|
|
||||||
obj: &kubeProxyConfig{
|
|
||||||
configBase: configBase{
|
|
||||||
GroupVersion: kubeproxyconfig.SchemeGroupVersion,
|
|
||||||
},
|
},
|
||||||
config: kubeproxyconfig.KubeProxyConfiguration{
|
Data: map[string]string{
|
||||||
TypeMeta: metav1.TypeMeta{
|
constants.KubeProxyConfigMapKey: dedent.Dedent(contents),
|
||||||
APIVersion: kubeproxyconfig.SchemeGroupVersion.String(),
|
|
||||||
Kind: "KubeProxyConfiguration",
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
},
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
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
|
// 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)) {
|
func runKubeProxyFromTest(t *testing.T, perform func(gvk schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error)) {
|
||||||
tests := []struct {
|
const (
|
||||||
name string
|
kind = "KubeProxyConfiguration"
|
||||||
in string
|
clusterCIDR = "1.2.3.4/16"
|
||||||
out *kubeProxyConfig
|
)
|
||||||
expectErr bool
|
|
||||||
}{
|
gvk := kubeProxyHandler.GroupVersion.WithKind(kind)
|
||||||
{
|
yaml := fmt.Sprintf("apiVersion: %s\nkind: %s\nclusterCIDR: %s", kubeProxyHandler.GroupVersion, kind, clusterCIDR)
|
||||||
name: "Empty document map should return nothing successfully",
|
|
||||||
},
|
cfg, err := perform(gvk, yaml)
|
||||||
{
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
componentCfg, err := perform(t, test.in)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !test.expectErr {
|
t.Fatalf("unexpected failure: %v", err)
|
||||||
t.Errorf("unexpected failure: %v", err)
|
|
||||||
}
|
}
|
||||||
} else {
|
if cfg == nil {
|
||||||
if test.expectErr {
|
t.Fatal("no config loaded where it should have been")
|
||||||
t.Error("unexpected success")
|
|
||||||
} else {
|
|
||||||
if componentCfg == nil {
|
|
||||||
if test.out != nil {
|
|
||||||
t.Error("unexpected nil result")
|
|
||||||
}
|
}
|
||||||
} else {
|
if kubeproxyCfg, ok := cfg.(*kubeProxyConfig); !ok {
|
||||||
if got, ok := componentCfg.(*kubeProxyConfig); !ok {
|
t.Fatalf("found different object type than expected: %s", reflect.TypeOf(cfg))
|
||||||
t.Error("different result type")
|
} else if kubeproxyCfg.config.ClusterCIDR != clusterCIDR {
|
||||||
} else {
|
t.Fatalf("unexpected control value (clusterDomain):\n\tgot: %q\n\texpected: %q", kubeproxyCfg.config.ClusterCIDR, clusterCIDR)
|
||||||
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 TestKubeProxyFromDocumentMap(t *testing.T) {
|
func TestKubeProxyFromDocumentMap(t *testing.T) {
|
||||||
runKubeProxyFromTest(t, func(t *testing.T, in string) (kubeadmapi.ComponentConfig, error) {
|
runKubeProxyFromTest(t, func(gvk schema.GroupVersionKind, yaml string) (kubeadmapi.ComponentConfig, error) {
|
||||||
gvkmap, err := kubeadmutil.SplitYAMLDocuments([]byte(in))
|
return kubeProxyHandler.FromDocumentMap(kubeadmapi.DocumentMap{
|
||||||
if err != nil {
|
gvk: []byte(yaml),
|
||||||
t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
|
})
|
||||||
}
|
|
||||||
|
|
||||||
return kubeProxyHandler.FromDocumentMap(gvkmap)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKubeProxyFromCluster(t *testing.T) {
|
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(
|
client := clientsetfake.NewSimpleClientset(
|
||||||
&v1.ConfigMap{
|
testKubeProxyConfigMap(yaml),
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: constants.KubeProxyConfigMap,
|
|
||||||
Namespace: metav1.NamespaceSystem,
|
|
||||||
},
|
|
||||||
Data: map[string]string{
|
|
||||||
constants.KubeProxyConfigMapKey: in,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
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"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
"//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/apis/kubeadm/v1beta2:go_default_library",
|
||||||
"//cmd/kubeadm/app/componentconfigs:go_default_library",
|
"//cmd/kubeadm/app/componentconfigs:go_default_library",
|
||||||
"//cmd/kubeadm/app/constants: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",
|
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||||
"//vendor/github.com/lithammer/dedent:go_default_library",
|
"//vendor/github.com/lithammer/dedent:go_default_library",
|
||||||
"//vendor/github.com/pkg/errors: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",
|
"//vendor/sigs.k8s.io/yaml:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -23,8 +23,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pmezard/go-difflib/difflib"
|
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
kubeadmapiv1beta2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
|
||||||
@ -32,24 +30,11 @@ import (
|
|||||||
"sigs.k8s.io/yaml"
|
"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) {
|
func TestLoadInitConfigurationFromFile(t *testing.T) {
|
||||||
// Create temp folder for the test case
|
// Create temp folder for the test case
|
||||||
tmpdir, err := ioutil.TempDir("", "")
|
tmpdir, err := ioutil.TempDir("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Couldn't create tmpdir")
|
t.Fatalf("Couldn't create tmpdir: %v", err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
|
|
||||||
@ -100,7 +85,7 @@ func TestLoadInitConfigurationFromFile(t *testing.T) {
|
|||||||
cfgPath := filepath.Join(tmpdir, rt.name)
|
cfgPath := filepath.Join(tmpdir, rt.name)
|
||||||
err := ioutil.WriteFile(cfgPath, rt.fileContents, 0644)
|
err := ioutil.WriteFile(cfgPath, rt.fileContents, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Couldn't create file")
|
t.Errorf("Couldn't create file: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +101,7 @@ func TestLoadInitConfigurationFromFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if obj == nil {
|
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
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"github.com/lithammer/dedent"
|
||||||
"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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoadJoinConfigurationFromFile(t *testing.T) {
|
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 {
|
var tests = []struct {
|
||||||
name, in, out string
|
name string
|
||||||
groupVersion schema.GroupVersion
|
fileContents string
|
||||||
expectedErr bool
|
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
|
name: "empty file causes error",
|
||||||
{ // v1beta1 -> internal
|
expectErr: true,
|
||||||
name: "v1beta1ToInternal",
|
|
||||||
in: nodeV1beta1YAML,
|
|
||||||
out: nodeInternalYAML,
|
|
||||||
groupVersion: kubeadm.SchemeGroupVersion,
|
|
||||||
},
|
},
|
||||||
{ // v1beta1 -> internal -> v1beta1
|
{
|
||||||
name: "v1beta1Tov1beta1",
|
name: "Invalid v1beta1 causes error",
|
||||||
in: nodeV1beta1YAML,
|
fileContents: dedent.Dedent(`
|
||||||
out: nodeV1beta1YAML,
|
apiVersion: kubeadm.k8s.io/v1beta1
|
||||||
groupVersion: kubeadmapiv1beta1.SchemeGroupVersion,
|
kind: JoinConfiguration
|
||||||
|
`),
|
||||||
|
expectErr: true,
|
||||||
},
|
},
|
||||||
{ // v1beta2 -> internal
|
{
|
||||||
name: "v1beta2ToInternal",
|
name: "valid v1beta1 is loaded",
|
||||||
in: nodeV1beta2YAML,
|
fileContents: dedent.Dedent(`
|
||||||
out: nodeInternalYAML,
|
apiVersion: kubeadm.k8s.io/v1beta1
|
||||||
groupVersion: kubeadm.SchemeGroupVersion,
|
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",
|
name: "Invalid v1beta2 causes error",
|
||||||
in: nodeV1beta2YAML,
|
fileContents: dedent.Dedent(`
|
||||||
out: nodeV1beta2YAML,
|
apiVersion: kubeadm.k8s.io/v1beta2
|
||||||
groupVersion: kubeadmapiv1beta2.SchemeGroupVersion,
|
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
|
name: "valid v1beta2 is loaded",
|
||||||
{ // v1beta2 -> default -> validate -> internal -> v1beta2
|
fileContents: dedent.Dedent(`
|
||||||
name: "incompleteYAMLToDefaultedv1beta2",
|
apiVersion: kubeadm.k8s.io/v1beta2
|
||||||
in: nodeIncompleteYAML,
|
kind: JoinConfiguration
|
||||||
out: nodeDefaultedYAML,
|
caCertPath: /etc/kubernetes/pki/ca.crt
|
||||||
groupVersion: kubeadmapiv1beta2.SchemeGroupVersion,
|
discovery:
|
||||||
},
|
bootstrapToken:
|
||||||
{ // v1beta2 -> validation should fail
|
apiServerEndpoint: kube-apiserver:6443
|
||||||
name: "invalidYAMLShouldFail",
|
token: abcdef.0123456789abcdef
|
||||||
in: nodeInvalidYAML,
|
unsafeSkipCAVerification: true
|
||||||
expectedErr: true,
|
timeout: 5m0s
|
||||||
|
tlsBootstrapToken: abcdef.0123456789abcdef
|
||||||
|
`),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
t.Run(rt.name, func(t2 *testing.T) {
|
t.Run(rt.name, func(t2 *testing.T) {
|
||||||
|
cfgPath := filepath.Join(tmpdir, rt.name)
|
||||||
internalcfg, err := LoadJoinConfigurationFromFile(rt.in)
|
err := ioutil.WriteFile(cfgPath, []byte(rt.fileContents), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if rt.expectedErr {
|
t.Errorf("Couldn't create file: %v", err)
|
||||||
return
|
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)
|
obj, err := LoadJoinConfigurationFromFile(cfgPath)
|
||||||
|
if rt.expectErr {
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Unexpected success")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t2.Fatalf("couldn't marshal internal object: %v", err)
|
t.Errorf("Error reading file: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expected, err := ioutil.ReadFile(rt.out)
|
if obj == nil {
|
||||||
if err != nil {
|
t.Error("Unexpected nil return value")
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
Loading…
Reference in New Issue
Block a user