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