From e5c03607735c4e3bd51b346ac9a4af0c61f25927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Tue, 3 Jul 2018 20:55:11 +0300 Subject: [PATCH] Add a duplicated v1alpha3 API --- cmd/kubeadm/app/apis/kubeadm/v1alpha3/BUILD | 55 +++ .../kubeadm/v1alpha3/bootstraptokenstring.go | 90 +++++ .../v1alpha3/bootstraptokenstring_test.go | 236 +++++++++++++ .../app/apis/kubeadm/v1alpha3/defaults.go | 269 +++++++++++++++ .../apis/kubeadm/v1alpha3/defaults_unix.go | 22 ++ .../apis/kubeadm/v1alpha3/defaults_windows.go | 22 ++ cmd/kubeadm/app/apis/kubeadm/v1alpha3/doc.go | 22 ++ .../app/apis/kubeadm/v1alpha3/register.go | 66 ++++ .../app/apis/kubeadm/v1alpha3/types.go | 319 ++++++++++++++++++ 9 files changed, 1101 insertions(+) create mode 100644 cmd/kubeadm/app/apis/kubeadm/v1alpha3/BUILD create mode 100644 cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring.go create mode 100644 cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring_test.go create mode 100644 cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go create mode 100644 cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_unix.go create mode 100644 cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_windows.go create mode 100644 cmd/kubeadm/app/apis/kubeadm/v1alpha3/doc.go create mode 100644 cmd/kubeadm/app/apis/kubeadm/v1alpha3/register.go create mode 100644 cmd/kubeadm/app/apis/kubeadm/v1alpha3/types.go diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/BUILD b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/BUILD new file mode 100644 index 00000000000..cd95d23b323 --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/BUILD @@ -0,0 +1,55 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "bootstraptokenstring.go", + "defaults.go", + "defaults_unix.go", + "defaults_windows.go", + "doc.go", + "register.go", + "types.go", + "zz_generated.conversion.go", + "zz_generated.deepcopy.go", + "zz_generated.defaults.go", + ], + importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2", + visibility = ["//visibility:public"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//cmd/kubeadm/app/constants:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library", + "//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library", + "//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library", + "//pkg/util/pointer:go_default_library", + "//staging/src/k8s.io/api/core/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//staging/src/k8s.io/client-go/tools/bootstrap/token/api:go_default_library", + "//staging/src/k8s.io/client-go/tools/bootstrap/token/util:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["bootstraptokenstring_test.go"], + embed = [":go_default_library"], +) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring.go new file mode 100644 index 00000000000..b7efd0e4f3c --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring.go @@ -0,0 +1,90 @@ +/* +Copyright 2018 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 v1alpha2 holds the external kubeadm API types of version v1alpha2 +// Note: This file should be kept in sync with the similar one for the internal API +// TODO: The BootstrapTokenString object should move out to either k8s.io/client-go or k8s.io/api in the future +// (probably as part of Bootstrap Tokens going GA). It should not be staged under the kubeadm API as it is now. +package v1alpha3 + +import ( + "fmt" + "strings" + + bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api" + bootstraputil "k8s.io/client-go/tools/bootstrap/token/util" +) + +// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used +// for both validation of the practically of the API server from a joining node's point +// of view and as an authentication method for the node in the bootstrap phase of +// "kubeadm join". This token is and should be short-lived +type BootstrapTokenString struct { + ID string + Secret string +} + +// MarshalJSON implements the json.Marshaler interface. +func (bts BootstrapTokenString) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf(`"%s"`, bts.String())), nil +} + +// UnmarshalJSON implements the json.Unmarshaller interface. +func (bts *BootstrapTokenString) UnmarshalJSON(b []byte) error { + // If the token is represented as "", just return quickly without an error + if len(b) == 0 { + return nil + } + + // Remove unnecessary " characters coming from the JSON parser + token := strings.Replace(string(b), `"`, ``, -1) + // Convert the string Token to a BootstrapTokenString object + newbts, err := NewBootstrapTokenString(token) + if err != nil { + return err + } + bts.ID = newbts.ID + bts.Secret = newbts.Secret + return nil +} + +// String returns the string representation of the BootstrapTokenString +func (bts BootstrapTokenString) String() string { + if len(bts.ID) > 0 && len(bts.Secret) > 0 { + return bootstraputil.TokenFromIDAndSecret(bts.ID, bts.Secret) + } + return "" +} + +// NewBootstrapTokenString converts the given Bootstrap Token as a string +// to the BootstrapTokenString object used for serialization/deserialization +// and internal usage. It also automatically validates that the given token +// is of the right format +func NewBootstrapTokenString(token string) (*BootstrapTokenString, error) { + substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(token) + // TODO: Add a constant for the 3 value here, and explain better why it's needed (other than because how the regexp parsin works) + if len(substrs) != 3 { + return nil, fmt.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern) + } + + return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil +} + +// NewBootstrapTokenStringFromIDAndSecret is a wrapper around NewBootstrapTokenString +// that allows the caller to specify the ID and Secret separately +func NewBootstrapTokenStringFromIDAndSecret(id, secret string) (*BootstrapTokenString, error) { + return NewBootstrapTokenString(bootstraputil.TokenFromIDAndSecret(id, secret)) +} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring_test.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring_test.go new file mode 100644 index 00000000000..9c4d4f47a9a --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/bootstraptokenstring_test.go @@ -0,0 +1,236 @@ +/* +Copyright 2018 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 v1alpha3 + +import ( + "encoding/json" + "fmt" + "reflect" + "testing" +) + +func TestMarshalJSON(t *testing.T) { + var tests = []struct { + bts BootstrapTokenString + expected string + }{ + {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, `"abcdef.abcdef0123456789"`}, + {BootstrapTokenString{ID: "foo", Secret: "bar"}, `"foo.bar"`}, + {BootstrapTokenString{ID: "h", Secret: "b"}, `"h.b"`}, + } + for _, rt := range tests { + b, err := json.Marshal(rt.bts) + if err != nil { + t.Fatalf("json.Marshal returned an unexpected error: %v", err) + } + if string(b) != rt.expected { + t.Errorf( + "failed BootstrapTokenString.MarshalJSON:\n\texpected: %s\n\t actual: %s", + rt.expected, + string(b), + ) + } + } +} + +func TestUnmarshalJSON(t *testing.T) { + var tests = []struct { + input string + bts *BootstrapTokenString + expectedError bool + }{ + {`"f.s"`, &BootstrapTokenString{}, true}, + {`"abcdef."`, &BootstrapTokenString{}, true}, + {`"abcdef:abcdef0123456789"`, &BootstrapTokenString{}, true}, + {`abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, + {`"abcdef.abcdef0123456789`, &BootstrapTokenString{}, true}, + {`"abcdef.ABCDEF0123456789"`, &BootstrapTokenString{}, true}, + {`"abcdef.abcdef0123456789"`, &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, false}, + {`"123456.aabbccddeeffgghh"`, &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}, false}, + } + for _, rt := range tests { + newbts := &BootstrapTokenString{} + err := json.Unmarshal([]byte(rt.input), newbts) + if (err != nil) != rt.expectedError { + t.Errorf("failed BootstrapTokenString.UnmarshalJSON:\n\texpected error: %t\n\t actual error: %v", rt.expectedError, err) + } else if !reflect.DeepEqual(rt.bts, newbts) { + t.Errorf( + "failed BootstrapTokenString.UnmarshalJSON:\n\texpected: %v\n\t actual: %v", + rt.bts, + newbts, + ) + } + } +} + +func TestJSONRoundtrip(t *testing.T) { + var tests = []struct { + input string + bts *BootstrapTokenString + }{ + {`"abcdef.abcdef0123456789"`, nil}, + {"", &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + } + for _, rt := range tests { + if err := roundtrip(rt.input, rt.bts); err != nil { + t.Errorf("failed BootstrapTokenString JSON roundtrip with error: %v", err) + } + } +} + +func roundtrip(input string, bts *BootstrapTokenString) error { + var b []byte + var err error + newbts := &BootstrapTokenString{} + // If string input was specified, roundtrip like this: string -> (unmarshal) -> object -> (marshal) -> string + if len(input) > 0 { + if err := json.Unmarshal([]byte(input), newbts); err != nil { + return fmt.Errorf("expected no unmarshal error, got error: %v", err) + } + if b, err = json.Marshal(newbts); err != nil { + return fmt.Errorf("expected no marshal error, got error: %v", err) + } + if input != string(b) { + return fmt.Errorf( + "expected token: %s\n\t actual: %s", + input, + string(b), + ) + } + } else { // Otherwise, roundtrip like this: object -> (marshal) -> string -> (unmarshal) -> object + if b, err = json.Marshal(bts); err != nil { + return fmt.Errorf("expected no marshal error, got error: %v", err) + } + if err := json.Unmarshal(b, newbts); err != nil { + return fmt.Errorf("expected no unmarshal error, got error: %v", err) + } + if !reflect.DeepEqual(bts, newbts) { + return fmt.Errorf( + "expected object: %v\n\t actual: %v", + bts, + newbts, + ) + } + } + return nil +} + +func TestTokenFromIDAndSecret(t *testing.T) { + var tests = []struct { + bts BootstrapTokenString + expected string + }{ + {BootstrapTokenString{ID: "foo", Secret: "bar"}, "foo.bar"}, + {BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}, "abcdef.abcdef0123456789"}, + {BootstrapTokenString{ID: "h", Secret: "b"}, "h.b"}, + } + for _, rt := range tests { + actual := rt.bts.String() + if actual != rt.expected { + t.Errorf( + "failed BootstrapTokenString.String():\n\texpected: %s\n\t actual: %s", + rt.expected, + actual, + ) + } + } +} + +func TestNewBootstrapTokenString(t *testing.T) { + var tests = []struct { + token string + expectedError bool + bts *BootstrapTokenString + }{ + {token: "", expectedError: true, bts: nil}, + {token: ".", expectedError: true, bts: nil}, + {token: "1234567890123456789012", expectedError: true, bts: nil}, // invalid parcel size + {token: "12345.1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {token: ".1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {token: "123456.", expectedError: true, bts: nil}, // invalid parcel size + {token: "123456:1234567890.123456", expectedError: true, bts: nil}, // invalid separation + {token: "abcdef:1234567890123456", expectedError: true, bts: nil}, // invalid separation + {token: "Abcdef.1234567890123456", expectedError: true, bts: nil}, // invalid token id + {token: "123456.AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret + {token: "123456.AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character + {token: "abc*ef.1234567890123456", expectedError: true, bts: nil}, // invalid character + {token: "abcdef.1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, + {token: "123456.aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, + {token: "abcdef.abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + {token: "123456.1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, + } + for _, rt := range tests { + actual, err := NewBootstrapTokenString(rt.token) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected error: %t\n\t actual error: %v", + rt.token, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenString for the token %q\n\texpected: %v\n\t actual: %v", + rt.token, + rt.bts, + actual, + ) + } + } +} + +func TestNewBootstrapTokenStringFromIDAndSecret(t *testing.T) { + var tests = []struct { + id, secret string + expectedError bool + bts *BootstrapTokenString + }{ + {id: "", secret: "", expectedError: true, bts: nil}, + {id: "1234567890123456789012", secret: "", expectedError: true, bts: nil}, // invalid parcel size + {id: "12345", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {id: "", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid parcel size + {id: "123456", secret: "", expectedError: true, bts: nil}, // invalid parcel size + {id: "Abcdef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid token id + {id: "123456", secret: "AABBCCDDEEFFGGHH", expectedError: true, bts: nil}, // invalid token secret + {id: "123456", secret: "AABBCCD-EEFFGGHH", expectedError: true, bts: nil}, // invalid character + {id: "abc*ef", secret: "1234567890123456", expectedError: true, bts: nil}, // invalid character + {id: "abcdef", secret: "1234567890123456", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "1234567890123456"}}, + {id: "123456", secret: "aabbccddeeffgghh", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "aabbccddeeffgghh"}}, + {id: "abcdef", secret: "abcdef0123456789", expectedError: false, bts: &BootstrapTokenString{ID: "abcdef", Secret: "abcdef0123456789"}}, + {id: "123456", secret: "1234560123456789", expectedError: false, bts: &BootstrapTokenString{ID: "123456", Secret: "1234560123456789"}}, + } + for _, rt := range tests { + actual, err := NewBootstrapTokenStringFromIDAndSecret(rt.id, rt.secret) + if (err != nil) != rt.expectedError { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected error: %t\n\t actual error: %v", + rt.id, + rt.secret, + rt.expectedError, + err, + ) + } else if !reflect.DeepEqual(actual, rt.bts) { + t.Errorf( + "failed NewBootstrapTokenStringFromIDAndSecret for the token with id %q and secret %q\n\texpected: %v\n\t actual: %v", + rt.id, + rt.secret, + rt.bts, + actual, + ) + } + } +} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go new file mode 100644 index 00000000000..a2c6d73423b --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults.go @@ -0,0 +1,269 @@ +/* +Copyright 2018 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 v1alpha3 + +import ( + "net/url" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme" + kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + kubeproxyscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme" + kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" + utilpointer "k8s.io/kubernetes/pkg/util/pointer" +) + +const ( + // DefaultServiceDNSDomain defines default cluster-internal domain name for Services and Pods + DefaultServiceDNSDomain = "cluster.local" + // DefaultServicesSubnet defines default service subnet range + DefaultServicesSubnet = "10.96.0.0/12" + // DefaultClusterDNSIP defines default DNS IP + DefaultClusterDNSIP = "10.96.0.10" + // DefaultKubernetesVersion defines default kubernetes version + DefaultKubernetesVersion = "stable-1.11" + // DefaultAPIBindPort defines default API port + DefaultAPIBindPort = 6443 + // DefaultCertificatesDir defines default certificate directory + DefaultCertificatesDir = "/etc/kubernetes/pki" + // DefaultImageRepository defines default image registry + DefaultImageRepository = "k8s.gcr.io" + // DefaultManifestsDir defines default manifests directory + DefaultManifestsDir = "/etc/kubernetes/manifests" + // DefaultCRISocket defines the default cri socket + DefaultCRISocket = "/var/run/dockershim.sock" + // DefaultClusterName defines the default cluster name + DefaultClusterName = "kubernetes" + + // DefaultEtcdDataDir defines default location of etcd where static pods will save data to + DefaultEtcdDataDir = "/var/lib/etcd" + // DefaultProxyBindAddressv4 is the default bind address when the advertise address is v4 + DefaultProxyBindAddressv4 = "0.0.0.0" + // DefaultProxyBindAddressv6 is the default bind address when the advertise address is v6 + DefaultProxyBindAddressv6 = "::" + // KubeproxyKubeConfigFileName defines the file name for the kube-proxy's KubeConfig file + KubeproxyKubeConfigFileName = "/var/lib/kube-proxy/kubeconfig.conf" + + // DefaultDiscoveryTimeout specifies the default discovery timeout for kubeadm (used unless one is specified in the NodeConfiguration) + DefaultDiscoveryTimeout = 5 * time.Minute +) + +var ( + // DefaultAuditPolicyLogMaxAge is defined as a var so its address can be taken + // It is the number of days to store audit logs + DefaultAuditPolicyLogMaxAge = int32(2) +) + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + return RegisterDefaults(scheme) +} + +// SetDefaults_MasterConfiguration assigns default values to Master node +func SetDefaults_MasterConfiguration(obj *MasterConfiguration) { + if obj.KubernetesVersion == "" { + obj.KubernetesVersion = DefaultKubernetesVersion + } + + if obj.API.BindPort == 0 { + obj.API.BindPort = DefaultAPIBindPort + } + + if obj.Networking.ServiceSubnet == "" { + obj.Networking.ServiceSubnet = DefaultServicesSubnet + } + + if obj.Networking.DNSDomain == "" { + obj.Networking.DNSDomain = DefaultServiceDNSDomain + } + + if obj.CertificatesDir == "" { + obj.CertificatesDir = DefaultCertificatesDir + } + + if obj.ImageRepository == "" { + obj.ImageRepository = DefaultImageRepository + } + + if obj.ClusterName == "" { + obj.ClusterName = DefaultClusterName + } + + SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration) + SetDefaults_BootstrapTokens(obj) + SetDefaults_KubeletConfiguration(obj) + SetDefaults_Etcd(obj) + SetDefaults_ProxyConfiguration(obj) + SetDefaults_AuditPolicyConfiguration(obj) +} + +// SetDefaults_Etcd assigns default values for the Proxy +func SetDefaults_Etcd(obj *MasterConfiguration) { + if obj.Etcd.External == nil && obj.Etcd.Local == nil { + obj.Etcd.Local = &LocalEtcd{} + } + if obj.Etcd.Local != nil { + if obj.Etcd.Local.DataDir == "" { + obj.Etcd.Local.DataDir = DefaultEtcdDataDir + } + } +} + +// SetDefaults_ProxyConfiguration assigns default values for the Proxy +func SetDefaults_ProxyConfiguration(obj *MasterConfiguration) { + if obj.KubeProxy.Config == nil { + obj.KubeProxy.Config = &kubeproxyconfigv1alpha1.KubeProxyConfiguration{} + } + if obj.KubeProxy.Config.ClusterCIDR == "" && obj.Networking.PodSubnet != "" { + obj.KubeProxy.Config.ClusterCIDR = obj.Networking.PodSubnet + } + + if obj.KubeProxy.Config.ClientConnection.KubeConfigFile == "" { + obj.KubeProxy.Config.ClientConnection.KubeConfigFile = KubeproxyKubeConfigFileName + } + + kubeproxyscheme.Scheme.Default(obj.KubeProxy.Config) +} + +// SetDefaults_NodeConfiguration assigns default values to a regular node +func SetDefaults_NodeConfiguration(obj *NodeConfiguration) { + if obj.CACertPath == "" { + obj.CACertPath = DefaultCACertPath + } + if len(obj.TLSBootstrapToken) == 0 { + obj.TLSBootstrapToken = obj.Token + } + if len(obj.DiscoveryToken) == 0 && len(obj.DiscoveryFile) == 0 { + obj.DiscoveryToken = obj.Token + } + // Make sure file URLs become paths + if len(obj.DiscoveryFile) != 0 { + u, err := url.Parse(obj.DiscoveryFile) + if err == nil && u.Scheme == "file" { + obj.DiscoveryFile = u.Path + } + } + if obj.DiscoveryTimeout == nil { + obj.DiscoveryTimeout = &metav1.Duration{ + Duration: DefaultDiscoveryTimeout, + } + } + if obj.ClusterName == "" { + obj.ClusterName = DefaultClusterName + } + + SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration) +} + +// SetDefaults_KubeletConfiguration assigns default values to kubelet +func SetDefaults_KubeletConfiguration(obj *MasterConfiguration) { + if obj.KubeletConfiguration.BaseConfig == nil { + obj.KubeletConfiguration.BaseConfig = &kubeletconfigv1beta1.KubeletConfiguration{} + } + if obj.KubeletConfiguration.BaseConfig.StaticPodPath == "" { + obj.KubeletConfiguration.BaseConfig.StaticPodPath = DefaultManifestsDir + } + if obj.KubeletConfiguration.BaseConfig.ClusterDNS == nil { + dnsIP, err := constants.GetDNSIP(obj.Networking.ServiceSubnet) + if err != nil { + obj.KubeletConfiguration.BaseConfig.ClusterDNS = []string{DefaultClusterDNSIP} + } else { + obj.KubeletConfiguration.BaseConfig.ClusterDNS = []string{dnsIP.String()} + } + } + if obj.KubeletConfiguration.BaseConfig.ClusterDomain == "" { + obj.KubeletConfiguration.BaseConfig.ClusterDomain = obj.Networking.DNSDomain + } + + // Enforce security-related kubelet options + + // Require all clients to the kubelet API to have client certs signed by the cluster CA + obj.KubeletConfiguration.BaseConfig.Authentication.X509.ClientCAFile = DefaultCACertPath + obj.KubeletConfiguration.BaseConfig.Authentication.Anonymous.Enabled = utilpointer.BoolPtr(false) + + // On every client request to the kubelet API, execute a webhook (SubjectAccessReview request) to the API server + // and ask it whether the client is authorized to access the kubelet API + obj.KubeletConfiguration.BaseConfig.Authorization.Mode = kubeletconfigv1beta1.KubeletAuthorizationModeWebhook + + // Let clients using other authentication methods like ServiceAccount tokens also access the kubelet API + obj.KubeletConfiguration.BaseConfig.Authentication.Webhook.Enabled = utilpointer.BoolPtr(true) + + // Disable the readonly port of the kubelet, in order to not expose unnecessary information + obj.KubeletConfiguration.BaseConfig.ReadOnlyPort = 0 + + // Enables client certificate rotation for the kubelet + obj.KubeletConfiguration.BaseConfig.RotateCertificates = true + + // Serve a /healthz webserver on localhost:10248 that kubeadm can talk to + obj.KubeletConfiguration.BaseConfig.HealthzBindAddress = "127.0.0.1" + obj.KubeletConfiguration.BaseConfig.HealthzPort = utilpointer.Int32Ptr(10248) + + scheme, _, _ := kubeletscheme.NewSchemeAndCodecs() + if scheme != nil { + scheme.Default(obj.KubeletConfiguration.BaseConfig) + } +} + +func SetDefaults_NodeRegistrationOptions(obj *NodeRegistrationOptions) { + if obj.CRISocket == "" { + obj.CRISocket = DefaultCRISocket + } +} + +// SetDefaults_AuditPolicyConfiguration sets default values for the AuditPolicyConfiguration +func SetDefaults_AuditPolicyConfiguration(obj *MasterConfiguration) { + if obj.AuditPolicyConfiguration.LogDir == "" { + obj.AuditPolicyConfiguration.LogDir = constants.StaticPodAuditPolicyLogDir + } + if obj.AuditPolicyConfiguration.LogMaxAge == nil { + obj.AuditPolicyConfiguration.LogMaxAge = &DefaultAuditPolicyLogMaxAge + } +} + +// SetDefaults_BootstrapTokens sets the defaults for the .BootstrapTokens field +// If the slice is empty, it's defaulted with one token. Otherwise it just loops +// through the slice and sets the defaults for the omitempty fields that are TTL, +// Usages and Groups. Token is NOT defaulted with a random one in the API defaulting +// layer, but set to a random value later at runtime if not set before. +func SetDefaults_BootstrapTokens(obj *MasterConfiguration) { + + if obj.BootstrapTokens == nil || len(obj.BootstrapTokens) == 0 { + obj.BootstrapTokens = []BootstrapToken{{}} + } + + for _, bt := range obj.BootstrapTokens { + SetDefaults_BootstrapToken(&bt) + } +} + +// SetDefaults_BootstrapToken sets the defaults for an individual Bootstrap Token +func SetDefaults_BootstrapToken(bt *BootstrapToken) { + if bt.TTL == nil { + bt.TTL = &metav1.Duration{ + Duration: constants.DefaultTokenDuration, + } + } + if len(bt.Usages) == 0 { + bt.Usages = constants.DefaultTokenUsages + } + + if len(bt.Groups) == 0 { + bt.Groups = constants.DefaultTokenGroups + } +} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_unix.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_unix.go new file mode 100644 index 00000000000..aad0f9a772e --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_unix.go @@ -0,0 +1,22 @@ +// +build !windows + +/* +Copyright 2018 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 v1alpha3 + +// DefaultCACertPath defines default location of CA certificate on Linux +const DefaultCACertPath = "/etc/kubernetes/pki/ca.crt" diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_windows.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_windows.go new file mode 100644 index 00000000000..4449239aa40 --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/defaults_windows.go @@ -0,0 +1,22 @@ +// +build windows + +/* +Copyright 2018 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 v1alpha3 + +// DefaultCACertPath defines default location of CA certificate on Windows +const DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt" diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/doc.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/doc.go new file mode 100644 index 00000000000..d328aff21d5 --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2018 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 v1alpha2 is the package that contains the libraries that drive the kubeadm binary. +// +k8s:defaulter-gen=TypeMeta +// +groupName=kubeadm.k8s.io +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm +package v1alpha3 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3" diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/register.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/register.go new file mode 100644 index 00000000000..6df066b3de5 --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/register.go @@ -0,0 +1,66 @@ +/* +Copyright 2018 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 v1alpha3 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "kubeadm.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha3"} + +var ( + // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api. + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + + // SchemeBuilder points to a list of functions added to Scheme. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // AddToScheme applies all the stored functions to the scheme. + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs) +} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &MasterConfiguration{}, + &NodeConfiguration{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha3/types.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/types.go new file mode 100644 index 00000000000..fcb0f78005f --- /dev/null +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha3/types.go @@ -0,0 +1,319 @@ +/* +Copyright 2018 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 v1alpha3 + +import ( + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1" + kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MasterConfiguration contains a list of elements which make up master's +// configuration object. +type MasterConfiguration struct { + metav1.TypeMeta `json:",inline"` + + // `kubeadm init`-only information. These fields are solely used the first time `kubeadm init` runs. + // After that, the information in the fields ARE NOT uploaded to the `kubeadm-config` ConfigMap + // that is used by `kubeadm upgrade` for instance. These fields must be omitempty. + + // BootstrapTokens is respected at `kubeadm init` time and describes a set of Bootstrap Tokens to create. + // This information IS NOT uploaded to the kubeadm cluster configmap, partly because of its sensitive nature + BootstrapTokens []BootstrapToken `json:"bootstrapTokens,omitempty"` + + // NodeRegistration holds fields that relate to registering the new master node to the cluster + NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty"` + + // Cluster-wide configuration + // TODO: Move these fields under some kind of ClusterConfiguration or similar struct that describes + // one cluster. Eventually we want this kind of spec to align well with the Cluster API spec. + + // API holds configuration for the k8s apiserver. + API API `json:"api"` + // KubeProxy holds configuration for the k8s service proxy. + KubeProxy KubeProxy `json:"kubeProxy"` + // Etcd holds configuration for etcd. + Etcd Etcd `json:"etcd"` + // KubeletConfiguration holds configuration for the kubelet. + KubeletConfiguration KubeletConfiguration `json:"kubeletConfiguration"` + // Networking holds configuration for the networking topology of the cluster. + Networking Networking `json:"networking"` + + // KubernetesVersion is the target version of the control plane. + KubernetesVersion string `json:"kubernetesVersion"` + + // APIServerExtraArgs is a set of extra flags to pass to the API Server or override + // default ones in form of =. + // TODO: This is temporary and ideally we would like to switch all components to + // use ComponentConfig + ConfigMaps. + APIServerExtraArgs map[string]string `json:"apiServerExtraArgs,omitempty"` + // ControllerManagerExtraArgs is a set of extra flags to pass to the Controller Manager + // or override default ones in form of = + // TODO: This is temporary and ideally we would like to switch all components to + // use ComponentConfig + ConfigMaps. + ControllerManagerExtraArgs map[string]string `json:"controllerManagerExtraArgs,omitempty"` + // SchedulerExtraArgs is a set of extra flags to pass to the Scheduler or override + // default ones in form of = + // TODO: This is temporary and ideally we would like to switch all components to + // use ComponentConfig + ConfigMaps. + SchedulerExtraArgs map[string]string `json:"schedulerExtraArgs,omitempty"` + + // APIServerExtraVolumes is an extra set of host volumes mounted to the API server. + APIServerExtraVolumes []HostPathMount `json:"apiServerExtraVolumes,omitempty"` + // ControllerManagerExtraVolumes is an extra set of host volumes mounted to the + // Controller Manager. + ControllerManagerExtraVolumes []HostPathMount `json:"controllerManagerExtraVolumes,omitempty"` + // SchedulerExtraVolumes is an extra set of host volumes mounted to the scheduler. + SchedulerExtraVolumes []HostPathMount `json:"schedulerExtraVolumes,omitempty"` + + // APIServerCertSANs sets extra Subject Alternative Names for the API Server signing cert. + APIServerCertSANs []string `json:"apiServerCertSANs,omitempty"` + // CertificatesDir specifies where to store or look for all required certificates. + CertificatesDir string `json:"certificatesDir"` + + // ImageRepository what container registry to pull control plane images from + ImageRepository string `json:"imageRepository"` + // UnifiedControlPlaneImage specifies if a specific container image should + // be used for all control plane components. + UnifiedControlPlaneImage string `json:"unifiedControlPlaneImage"` + + // AuditPolicyConfiguration defines the options for the api server audit system + AuditPolicyConfiguration AuditPolicyConfiguration `json:"auditPolicy"` + + // FeatureGates enabled by the user. + FeatureGates map[string]bool `json:"featureGates,omitempty"` + + // The cluster name + ClusterName string `json:"clusterName,omitempty"` +} + +// API struct contains elements of API server address. +type API struct { + // AdvertiseAddress sets the IP address for the API server to advertise. + AdvertiseAddress string `json:"advertiseAddress"` + // ControlPlaneEndpoint sets a stable IP address or DNS name for the control plane; it + // can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port. + // In case the ControlPlaneEndpoint is not specified, the AdvertiseAddress + BindPort + // are used; in case the ControlPlaneEndpoint is specified but without a TCP port, + // the BindPort is used. + // Possible usages are: + // e.g. In an cluster with more than one control plane instances, this field should be + // assigned the address of the external load balancer in front of the + // control plane instances. + // e.g. in environments with enforced node recycling, the ControlPlaneEndpoint + // could be used for assigning a stable DNS to the control plane. + ControlPlaneEndpoint string `json:"controlPlaneEndpoint"` + // BindPort sets the secure port for the API Server to bind to. + // Defaults to 6443. + BindPort int32 `json:"bindPort"` +} + +// NodeRegistrationOptions holds fields that relate to registering a new master or node to the cluster, either via "kubeadm init" or "kubeadm join" +type NodeRegistrationOptions struct { + + // Name is the `.Metadata.Name` field of the Node API object that will be created in this `kubeadm init` or `kubeadm joiƄ` operation. + // This field is also used in the CommonName field of the kubelet's client certificate to the API server. + // Defaults to the hostname of the node if not provided. + Name string `json:"name,omitempty"` + + // CRISocket is used to retrieve container runtime info. This information will be annotated to the Node API object, for later re-use + CRISocket string `json:"criSocket,omitempty"` + + // Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, in the `kubeadm init` process + // it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your master node, set this field to an + // empty slice, i.e. `taints: {}` in the YAML file. This field is solely used for Node registration. + Taints []v1.Taint `json:"taints,omitempty"` + + // KubeletExtraArgs passes through extra arguments to the kubelet. The arguments here are passed to the kubelet command line via the environment file + // kubeadm writes at runtime for the kubelet to source. This overrides the generic base-level configuration in the kubelet-config-1.X ConfigMap + // Flags have higher higher priority when parsing. These values are local and specific to the node kubeadm is executing on. + KubeletExtraArgs map[string]string `json:"kubeletExtraArgs,omitempty"` +} + +// Networking contains elements describing cluster's networking configuration +type Networking struct { + // ServiceSubnet is the subnet used by k8s services. Defaults to "10.96.0.0/12". + ServiceSubnet string `json:"serviceSubnet"` + // PodSubnet is the subnet used by pods. + PodSubnet string `json:"podSubnet"` + // DNSDomain is the dns domain used by k8s services. Defaults to "cluster.local". + DNSDomain string `json:"dnsDomain"` +} + +// BootstrapToken describes one bootstrap token, stored as a Secret in the cluster +type BootstrapToken struct { + // Token is used for establishing bidirectional trust between nodes and masters. + // Used for joining nodes in the cluster. + Token *BootstrapTokenString `json:"token"` + // Description sets a human-friendly message why this token exists and what it's used + // for, so other administrators can know its purpose. + Description string `json:"description,omitempty"` + // TTL defines the time to live for this token. Defaults to 24h. + // Expires and TTL are mutually exclusive. + TTL *metav1.Duration `json:"ttl,omitempty"` + // Expires specifies the timestamp when this token expires. Defaults to being set + // dynamically at runtime based on the TTL. Expires and TTL are mutually exclusive. + Expires *metav1.Time `json:"expires,omitempty"` + // Usages describes the ways in which this token can be used. Can by default be used + // for establishing bidirectional trust, but that can be changed here. + Usages []string `json:"usages,omitempty"` + // Groups specifies the extra groups that this token will authenticate as when/if + // used for authentication + Groups []string `json:"groups,omitempty"` +} + +// Etcd contains elements describing Etcd configuration. +type Etcd struct { + + // Local provides configuration knobs for configuring the local etcd instance + // Local and External are mutually exclusive + Local *LocalEtcd `json:"local,omitempty"` + + // External describes how to connect to an external etcd cluster + // Local and External are mutually exclusive + External *ExternalEtcd `json:"external,omitempty"` +} + +// LocalEtcd describes that kubeadm should run an etcd cluster locally +type LocalEtcd struct { + + // Image specifies which container image to use for running etcd. + // If empty, automatically populated by kubeadm using the image + // repository and default etcd version. + Image string `json:"image"` + + // DataDir is the directory etcd will place its data. + // Defaults to "/var/lib/etcd". + DataDir string `json:"dataDir"` + + // ExtraArgs are extra arguments provided to the etcd binary + // when run inside a static pod. + ExtraArgs map[string]string `json:"extraArgs,omitempty"` + + // ServerCertSANs sets extra Subject Alternative Names for the etcd server signing cert. + ServerCertSANs []string `json:"serverCertSANs,omitempty"` + // PeerCertSANs sets extra Subject Alternative Names for the etcd peer signing cert. + PeerCertSANs []string `json:"peerCertSANs,omitempty"` +} + +// ExternalEtcd describes an external etcd cluster +type ExternalEtcd struct { + + // Endpoints of etcd members. Useful for using external etcd. + // If not provided, kubeadm will run etcd in a static pod. + Endpoints []string `json:"endpoints"` + // CAFile is an SSL Certificate Authority file used to secure etcd communication. + CAFile string `json:"caFile"` + // CertFile is an SSL certification file used to secure etcd communication. + CertFile string `json:"certFile"` + // KeyFile is an SSL key file used to secure etcd communication. + KeyFile string `json:"keyFile"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NodeConfiguration contains elements describing a particular node. +// TODO: This struct should be replaced by dynamic kubelet configuration. +type NodeConfiguration struct { + metav1.TypeMeta `json:",inline"` + + // NodeRegistration holds fields that relate to registering the new master node to the cluster + NodeRegistration NodeRegistrationOptions `json:"nodeRegistration"` + + // CACertPath is the path to the SSL certificate authority used to + // secure comunications between node and master. + // Defaults to "/etc/kubernetes/pki/ca.crt". + CACertPath string `json:"caCertPath"` + // DiscoveryFile is a file or url to a kubeconfig file from which to + // load cluster information. + DiscoveryFile string `json:"discoveryFile"` + // DiscoveryToken is a token used to validate cluster information + // fetched from the master. + DiscoveryToken string `json:"discoveryToken"` + // DiscoveryTokenAPIServers is a set of IPs to API servers from which info + // will be fetched. Currently we only pay attention to one API server but + // hope to support >1 in the future. + DiscoveryTokenAPIServers []string `json:"discoveryTokenAPIServers,omitempty"` + // DiscoveryTimeout modifies the discovery timeout + DiscoveryTimeout *metav1.Duration `json:"discoveryTimeout,omitempty"` + // TLSBootstrapToken is a token used for TLS bootstrapping. + // Defaults to Token. + TLSBootstrapToken string `json:"tlsBootstrapToken"` + // Token is used for both discovery and TLS bootstrapping. + Token string `json:"token"` + + // ClusterName is the name for the cluster in kubeconfig. + ClusterName string `json:"clusterName,omitempty"` + + // DiscoveryTokenCACertHashes specifies a set of public key pins to verify + // when token-based discovery is used. The root CA found during discovery + // must match one of these values. Specifying an empty set disables root CA + // pinning, which can be unsafe. Each hash is specified as ":", + // where the only currently supported type is "sha256". This is a hex-encoded + // SHA-256 hash of the Subject Public Key Info (SPKI) object in DER-encoded + // ASN.1. These hashes can be calculated using, for example, OpenSSL: + // openssl x509 -pubkey -in ca.crt openssl rsa -pubin -outform der 2>&/dev/null | openssl dgst -sha256 -hex + DiscoveryTokenCACertHashes []string `json:"discoveryTokenCACertHashes,omitempty"` + + // DiscoveryTokenUnsafeSkipCAVerification allows token-based discovery + // without CA verification via DiscoveryTokenCACertHashes. This can weaken + // the security of kubeadm since other nodes can impersonate the master. + DiscoveryTokenUnsafeSkipCAVerification bool `json:"discoveryTokenUnsafeSkipCAVerification"` + + // FeatureGates enabled by the user. + FeatureGates map[string]bool `json:"featureGates,omitempty"` +} + +// KubeletConfiguration contains elements describing initial remote configuration of kubelet. +type KubeletConfiguration struct { + BaseConfig *kubeletconfigv1beta1.KubeletConfiguration `json:"baseConfig,omitempty"` +} + +// HostPathMount contains elements describing volumes that are mounted from the +// host. +type HostPathMount struct { + // Name of the volume inside the pod template. + Name string `json:"name"` + // HostPath is the path in the host that will be mounted inside + // the pod. + HostPath string `json:"hostPath"` + // MountPath is the path inside the pod where hostPath will be mounted. + MountPath string `json:"mountPath"` + // Writable controls write access to the volume + Writable bool `json:"writable,omitempty"` + // PathType is the type of the HostPath. + PathType v1.HostPathType `json:"pathType,omitempty"` +} + +// KubeProxy contains elements describing the proxy configuration. +type KubeProxy struct { + Config *kubeproxyconfigv1alpha1.KubeProxyConfiguration `json:"config,omitempty"` +} + +// AuditPolicyConfiguration holds the options for configuring the api server audit policy. +type AuditPolicyConfiguration struct { + // Path is the local path to an audit policy. + Path string `json:"path"` + // LogDir is the local path to the directory where logs should be stored. + LogDir string `json:"logDir"` + // LogMaxAge is the number of days logs will be stored for. 0 indicates forever. + LogMaxAge *int32 `json:"logMaxAge,omitempty"` + //TODO(chuckha) add other options for audit policy. +}