Fresh dep ensure

This commit is contained in:
Mike Cronce
2018-11-26 13:23:56 -05:00
parent 93cb8a04d7
commit 407478ab9a
9016 changed files with 551394 additions and 279685 deletions

View File

@ -11,9 +11,9 @@ go_library(
importpath = "k8s.io/kubernetes/cmd/kubeadm/app",
deps = [
"//cmd/kubeadm/app/cmd:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/flag:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
@ -30,6 +30,7 @@ filegroup(
":package-srcs",
"//cmd/kubeadm/app/apis/kubeadm:all-srcs",
"//cmd/kubeadm/app/cmd:all-srcs",
"//cmd/kubeadm/app/componentconfigs:all-srcs",
"//cmd/kubeadm/app/constants:all-srcs",
"//cmd/kubeadm/app/discovery:all-srcs",
"//cmd/kubeadm/app/features:all-srcs",
@ -43,7 +44,7 @@ filegroup(
"//cmd/kubeadm/app/phases/etcd:all-srcs",
"//cmd/kubeadm/app/phases/kubeconfig:all-srcs",
"//cmd/kubeadm/app/phases/kubelet:all-srcs",
"//cmd/kubeadm/app/phases/markmaster:all-srcs",
"//cmd/kubeadm/app/phases/markcontrolplane:all-srcs",
"//cmd/kubeadm/app/phases/patchnode:all-srcs",
"//cmd/kubeadm/app/phases/selfhosting:all-srcs",
"//cmd/kubeadm/app/phases/upgrade:all-srcs",

View File

@ -18,15 +18,15 @@ go_library(
],
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm",
deps = [
"//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library",
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
"//pkg/kubelet/apis/config:go_default_library",
"//pkg/proxy/apis/config: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/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
@ -43,8 +43,8 @@ filegroup(
":package-srcs",
"//cmd/kubeadm/app/apis/kubeadm/fuzzer:all-srcs",
"//cmd/kubeadm/app/apis/kubeadm/scheme:all-srcs",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:all-srcs",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:all-srcs",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha3:all-srcs",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:all-srcs",
"//cmd/kubeadm/app/apis/kubeadm/validation:all-srcs",
],
tags = ["automanaged"],
@ -58,7 +58,8 @@ go_test(
],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)

View File

@ -17,15 +17,16 @@ limitations under the License.
package kubeadm
import (
"fmt"
"sort"
"strings"
"time"
"github.com/pkg/errors"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
bootstraputil "k8s.io/cluster-bootstrap/token/util"
)
// ToSecret converts the given BootstrapToken object to its Secret representation that
@ -84,24 +85,24 @@ func BootstrapTokenFromSecret(secret *v1.Secret) (*BootstrapToken, error) {
// Get the Token ID field from the Secret data
tokenID := getSecretString(secret, bootstrapapi.BootstrapTokenIDKey)
if len(tokenID) == 0 {
return nil, fmt.Errorf("Bootstrap Token Secret has no token-id data: %s", secret.Name)
return nil, errors.Errorf("bootstrap Token Secret has no token-id data: %s", secret.Name)
}
// Enforce the right naming convention
if secret.Name != bootstraputil.BootstrapTokenSecretName(tokenID) {
return nil, fmt.Errorf("bootstrap token name is not of the form '%s(token-id)'. Actual: %q. Expected: %q",
return nil, errors.Errorf("bootstrap token name is not of the form '%s(token-id)'. Actual: %q. Expected: %q",
bootstrapapi.BootstrapTokenSecretPrefix, secret.Name, bootstraputil.BootstrapTokenSecretName(tokenID))
}
tokenSecret := getSecretString(secret, bootstrapapi.BootstrapTokenSecretKey)
if len(tokenSecret) == 0 {
return nil, fmt.Errorf("Bootstrap Token Secret has no token-secret data: %s", secret.Name)
return nil, errors.Errorf("bootstrap Token Secret has no token-secret data: %s", secret.Name)
}
// Create the BootstrapTokenString object based on the ID and Secret
bts, err := NewBootstrapTokenStringFromIDAndSecret(tokenID, tokenSecret)
if err != nil {
return nil, fmt.Errorf("Bootstrap Token Secret is invalid and couldn't be parsed: %v", err)
return nil, errors.Wrap(err, "bootstrap Token Secret is invalid and couldn't be parsed")
}
// Get the description (if any) from the Secret
@ -114,7 +115,7 @@ func BootstrapTokenFromSecret(secret *v1.Secret) (*BootstrapToken, error) {
if len(secretExpiration) > 0 {
expTime, err := time.Parse(time.RFC3339, secretExpiration)
if err != nil {
return nil, fmt.Errorf("can't parse expiration time of bootstrap token %q: %v", secret.Name, err)
return nil, errors.Wrapf(err, "can't parse expiration time of bootstrap token %q", secret.Name)
}
expires = &metav1.Time{Time: expTime}
}

View File

@ -24,8 +24,10 @@ import (
"fmt"
"strings"
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
"github.com/pkg/errors"
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
bootstraputil "k8s.io/cluster-bootstrap/token/util"
)
// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used
@ -77,7 +79,7 @@ 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 nil, errors.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern)
}
return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil

View File

@ -18,9 +18,10 @@ package kubeadm
import (
"encoding/json"
"fmt"
"reflect"
"testing"
"github.com/pkg/errors"
)
func TestMarshalJSON(t *testing.T) {
@ -99,13 +100,13 @@ func roundtrip(input string, bts *BootstrapTokenString) error {
// 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)
return errors.Wrap(err, "expected no unmarshal error, got error")
}
if b, err = json.Marshal(newbts); err != nil {
return fmt.Errorf("expected no marshal error, got error: %v", err)
return errors.Wrap(err, "expected no marshal error, got error")
}
if input != string(b) {
return fmt.Errorf(
return errors.Errorf(
"expected token: %s\n\t actual: %s",
input,
string(b),
@ -113,13 +114,13 @@ func roundtrip(input string, bts *BootstrapTokenString) error {
}
} 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)
return errors.Wrap(err, "expected no marshal error, got error")
}
if err := json.Unmarshal(b, newbts); err != nil {
return fmt.Errorf("expected no unmarshal error, got error: %v", err)
return errors.Wrap(err, "expected no unmarshal error, got error")
}
if !reflect.DeepEqual(bts, newbts) {
return fmt.Errorf(
return errors.Errorf(
"expected object: %v\n\t actual: %v",
bts,
newbts,

View File

@ -14,10 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package kubeadm is the package that contains the libraries that drive the kubeadm binary.
// kubeadm is responsible for handling a Kubernetes cluster's lifecycle.
// +k8s:deepcopy-gen=package
// +groupName=kubeadm.k8s.io
// Package kubeadm is the package that contains the libraries that drive the kubeadm binary.
// kubeadm is responsible for handling a Kubernetes cluster's lifecycle.
package kubeadm // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"

View File

@ -12,13 +12,11 @@ go_library(
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer",
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library",
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
"//pkg/util/pointer:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
],
)
@ -41,6 +39,6 @@ go_test(
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/apitesting/roundtrip:go_default_library",
],
)

View File

@ -17,145 +17,134 @@ limitations under the License.
package fuzzer
import (
"time"
fuzz "github.com/google/gofuzz"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
)
// Funcs returns the fuzzer functions for the kubeadm apis.
func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(obj *kubeadm.MasterConfiguration, c fuzz.Continue) {
c.FuzzNoCustom(obj)
obj.KubernetesVersion = "v10"
obj.API.BindPort = 20
obj.API.AdvertiseAddress = "foo"
obj.Networking.ServiceSubnet = "foo"
obj.Networking.DNSDomain = "foo"
obj.CertificatesDir = "foo"
obj.APIServerCertSANs = []string{"foo"}
fuzzInitConfiguration,
fuzzClusterConfiguration,
fuzzComponentConfigs,
fuzzNodeRegistration,
fuzzDNS,
fuzzLocalEtcd,
fuzzNetworking,
fuzzJoinConfiguration,
}
}
obj.BootstrapTokens = []kubeadm.BootstrapToken{
{
Token: &kubeadm.BootstrapTokenString{
ID: "abcdef",
Secret: "abcdef0123456789",
},
TTL: &metav1.Duration{Duration: 1 * time.Hour},
Usages: []string{"foo"},
Groups: []string{"foo"},
},
}
obj.ImageRepository = "foo"
obj.CIImageRepository = ""
obj.UnifiedControlPlaneImage = "foo"
obj.FeatureGates = map[string]bool{"foo": true}
obj.ClusterName = "foo"
obj.APIServerExtraArgs = map[string]string{"foo": "foo"}
obj.APIServerExtraVolumes = []kubeadm.HostPathMount{{
Name: "foo",
HostPath: "foo",
MountPath: "foo",
Writable: false,
}}
// Note: We don't set values here for obj.Etcd.External, as these are mutually exlusive.
// And to make sure the fuzzer doesn't set a random value for obj.Etcd.External, we let
// kubeadmapi.Etcd implement fuzz.Interface (we handle that ourselves)
obj.Etcd.Local = &kubeadm.LocalEtcd{
Image: "foo",
DataDir: "foo",
ServerCertSANs: []string{"foo"},
PeerCertSANs: []string{"foo"},
ExtraArgs: map[string]string{"foo": "foo"},
}
obj.NodeRegistration = kubeadm.NodeRegistrationOptions{
CRISocket: "foo",
Name: "foo",
Taints: []v1.Taint{},
}
obj.KubeletConfiguration = kubeadm.KubeletConfiguration{
BaseConfig: &kubeletconfigv1beta1.KubeletConfiguration{
StaticPodPath: "foo",
ClusterDNS: []string{"foo"},
ClusterDomain: "foo",
Authorization: kubeletconfigv1beta1.KubeletAuthorization{
Mode: "Webhook",
},
Authentication: kubeletconfigv1beta1.KubeletAuthentication{
X509: kubeletconfigv1beta1.KubeletX509Authentication{
ClientCAFile: "/etc/kubernetes/pki/ca.crt",
},
Anonymous: kubeletconfigv1beta1.KubeletAnonymousAuthentication{
Enabled: utilpointer.BoolPtr(false),
},
},
RotateCertificates: true,
},
}
kubeletconfigv1beta1.SetDefaults_KubeletConfiguration(obj.KubeletConfiguration.BaseConfig)
obj.KubeProxy = kubeadm.KubeProxy{
Config: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{
FeatureGates: map[string]bool{"foo": true},
BindAddress: "foo",
HealthzBindAddress: "foo:10256",
MetricsBindAddress: "foo:",
EnableProfiling: bool(true),
ClusterCIDR: "foo",
HostnameOverride: "foo",
ClientConnection: kubeproxyconfigv1alpha1.ClientConnectionConfiguration{
KubeConfigFile: "foo",
AcceptContentTypes: "foo",
ContentType: "foo",
QPS: float32(5),
Burst: 10,
},
IPVS: kubeproxyconfigv1alpha1.KubeProxyIPVSConfiguration{
SyncPeriod: metav1.Duration{Duration: 1},
},
IPTables: kubeproxyconfigv1alpha1.KubeProxyIPTablesConfiguration{
MasqueradeBit: utilpointer.Int32Ptr(0),
SyncPeriod: metav1.Duration{Duration: 1},
},
OOMScoreAdj: utilpointer.Int32Ptr(0),
ResourceContainer: "foo",
UDPIdleTimeout: metav1.Duration{Duration: 1},
Conntrack: kubeproxyconfigv1alpha1.KubeProxyConntrackConfiguration{
MaxPerCore: utilpointer.Int32Ptr(2),
Min: utilpointer.Int32Ptr(1),
TCPEstablishedTimeout: &metav1.Duration{Duration: 5},
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5},
},
ConfigSyncPeriod: metav1.Duration{Duration: 1},
},
}
obj.AuditPolicyConfiguration = kubeadm.AuditPolicyConfiguration{
Path: "foo",
LogDir: "/foo",
LogMaxAge: utilpointer.Int32Ptr(0),
}
func fuzzInitConfiguration(obj *kubeadm.InitConfiguration, c fuzz.Continue) {
c.FuzzNoCustom(obj)
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
// Since ClusterConfiguration never get serialized in the external variant of InitConfiguration,
// it is necessary to apply external api defaults here to get the round trip internal->external->internal working.
// More specifically:
// internal with manually applied defaults -> external object : loosing ClusterConfiguration) -> internal object with automatically applied defaults
obj.ClusterConfiguration = kubeadm.ClusterConfiguration{
APIServer: kubeadm.APIServer{
TimeoutForControlPlane: &metav1.Duration{
Duration: constants.DefaultControlPlaneTimeout,
},
},
func(obj *kubeadm.NodeConfiguration, c fuzz.Continue) {
c.FuzzNoCustom(obj)
obj.CACertPath = "foo"
obj.DiscoveryFile = "foo"
obj.DiscoveryToken = "foo"
obj.DiscoveryTokenAPIServers = []string{"foo"}
obj.DiscoveryTimeout = &metav1.Duration{Duration: 1}
obj.TLSBootstrapToken = "foo"
obj.Token = "foo"
obj.ClusterName = "foo"
obj.NodeRegistration = kubeadm.NodeRegistrationOptions{
CRISocket: "foo",
Name: "foo",
}
DNS: kubeadm.DNS{
Type: kubeadm.CoreDNS,
},
CertificatesDir: v1beta1.DefaultCertificatesDir,
ClusterName: v1beta1.DefaultClusterName,
Etcd: kubeadm.Etcd{
Local: &kubeadm.LocalEtcd{
DataDir: v1beta1.DefaultEtcdDataDir,
},
},
ImageRepository: v1beta1.DefaultImageRepository,
KubernetesVersion: v1beta1.DefaultKubernetesVersion,
Networking: kubeadm.Networking{
ServiceSubnet: v1beta1.DefaultServicesSubnet,
DNSDomain: v1beta1.DefaultServiceDNSDomain,
},
}
// Adds the default bootstrap token to get the round working
obj.BootstrapTokens = []kubeadm.BootstrapToken{
{
// Description
// Expires
Groups: []string{"foo"},
// Token
TTL: &metav1.Duration{Duration: 1234},
Usages: []string{"foo"},
},
}
}
func fuzzNodeRegistration(obj *kubeadm.NodeRegistrationOptions, c fuzz.Continue) {
c.FuzzNoCustom(obj)
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
obj.CRISocket = "foo"
}
func fuzzClusterConfiguration(obj *kubeadm.ClusterConfiguration, c fuzz.Continue) {
c.FuzzNoCustom(obj)
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
obj.CertificatesDir = "foo"
obj.CIImageRepository = "" //This fields doesn't exists in public API >> using default to get the roundtrip test pass
obj.ClusterName = "bar"
obj.ImageRepository = "baz"
obj.KubernetesVersion = "qux"
obj.APIServer.TimeoutForControlPlane = &metav1.Duration{
Duration: constants.DefaultControlPlaneTimeout,
}
}
func fuzzDNS(obj *kubeadm.DNS, c fuzz.Continue) {
// This is intentionally not calling c.FuzzNoCustom because DNS struct does not exists in v1alpha3 api
// (so no random value will be applied, and this is necessary for getting roundtrip passing)
// Pinning values for fields that get defaults if fuzz value is empty string or nil
obj.Type = kubeadm.CoreDNS
}
func fuzzComponentConfigs(obj *kubeadm.ComponentConfigs, c fuzz.Continue) {
// This is intentionally empty because component config does not exists in the public api
// (empty mean all ComponentConfigs fields nil, and this is necessary for getting roundtrip passing)
}
func fuzzLocalEtcd(obj *kubeadm.LocalEtcd, c fuzz.Continue) {
c.FuzzNoCustom(obj)
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
obj.DataDir = "foo"
// Pinning values for fields that does not exists in v1alpha3 api
obj.ImageRepository = ""
obj.ImageTag = ""
}
func fuzzNetworking(obj *kubeadm.Networking, c fuzz.Continue) {
c.FuzzNoCustom(obj)
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
obj.DNSDomain = "foo"
obj.ServiceSubnet = "bar"
}
func fuzzJoinConfiguration(obj *kubeadm.JoinConfiguration, c fuzz.Continue) {
c.FuzzNoCustom(obj)
// Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail)
obj.CACertPath = "foo"
obj.Discovery = kubeadm.Discovery{
BootstrapToken: &kubeadm.BootstrapTokenDiscovery{Token: "baz"},
TLSBootstrapToken: "qux",
Timeout: &metav1.Duration{Duration: 1234},
}
}

View File

@ -19,7 +19,7 @@ package fuzzer
import (
"testing"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
"k8s.io/apimachinery/pkg/api/apitesting/roundtrip"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
)

View File

@ -46,8 +46,10 @@ func Resource(resource string) schema.GroupResource {
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&MasterConfiguration{},
&NodeConfiguration{},
&InitConfiguration{},
&ClusterConfiguration{},
&ClusterStatus{},
&JoinConfiguration{},
)
return nil
}

View File

@ -7,12 +7,13 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
],
)

View File

@ -21,9 +21,10 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
)
// Scheme is the runtime.Scheme to which all kubeadm api types are registered.
@ -37,10 +38,10 @@ func init() {
AddToScheme(Scheme)
}
// AddToScheme builds the Kubeadm scheme using all known versions of the kubeadm api.
// AddToScheme builds the kubeadm scheme using all known versions of the kubeadm api.
func AddToScheme(scheme *runtime.Scheme) {
kubeadm.AddToScheme(scheme)
v1alpha1.AddToScheme(scheme)
v1alpha2.AddToScheme(scheme)
scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion)
utilruntime.Must(kubeadm.AddToScheme(scheme))
utilruntime.Must(v1alpha3.AddToScheme(scheme))
utilruntime.Must(v1beta1.AddToScheme(scheme))
utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion))
}

View File

@ -17,80 +17,94 @@ limitations under the License.
package kubeadm
import (
fuzz "github.com/google/gofuzz"
v1 "k8s.io/api/core/v1"
"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"
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
kubeproxyconfig "k8s.io/kubernetes/pkg/proxy/apis/config"
)
// +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 {
// InitConfiguration contains a list of fields that are specifically "kubeadm init"-only runtime
// information. The cluster-wide config is stored in ClusterConfiguration. The InitConfiguration
// object IS NOT uploaded to the kubeadm-config ConfigMap in the cluster, only the
// ClusterConfiguration is.
type InitConfiguration struct {
metav1.TypeMeta
// `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.
// ClusterConfiguration holds the cluster-wide information, and embeds that struct (which can be (un)marshalled separately as well)
// When InitConfiguration is marshalled to bytes in the external version, this information IS NOT preserved (which can be seen from
// the `json:"-"` tag in the external variant of these API types. Here, in the internal version `json:",inline"` is used, which means
// that all of ClusterConfiguration's fields will appear as they would be InitConfiguration's fields. This is used in practice solely
// in kubeadm API roundtrip unit testing. Check out `cmd/kubeadm/app/util/config/*_test.go` for more information. Normally, the internal
// type is NEVER marshalled, but always converted to some external version first.
ClusterConfiguration `json:",inline"`
// 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
// NodeRegistration holds fields that relate to registering the new master node to the cluster
NodeRegistration NodeRegistrationOptions
// 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.
// LocalAPIEndpoint represents the endpoint of the API server instance that's deployed on this control plane node
// In HA setups, this differs from ClusterConfiguration.ControlPlaneEndpoint in the sense that ControlPlaneEndpoint
// is the global endpoint for the cluster, which then loadbalances the requests to each individual API server. This
// configuration object lets you customize what IP/DNS name and port the local API server advertises it's accessible
// on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process
// fails you may set the desired value here.
LocalAPIEndpoint APIEndpoint
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterConfiguration contains cluster-wide configuration for a kubeadm cluster
type ClusterConfiguration struct {
metav1.TypeMeta
// ComponentConfigs holds internal ComponentConfig struct types known to kubeadm, should long-term only exist in the internal kubeadm API
// +k8s:conversion-gen=false
ComponentConfigs ComponentConfigs
// API holds configuration for the k8s apiserver.
API API
// KubeProxy holds configuration for the k8s service proxy.
KubeProxy KubeProxy
// Etcd holds configuration for etcd.
Etcd Etcd
// KubeletConfiguration holds configuration for the kubelet.
KubeletConfiguration KubeletConfiguration
// Networking holds configuration for the networking topology of the cluster.
Networking Networking
// KubernetesVersion is the target version of the control plane.
KubernetesVersion string
// APIServerExtraArgs is a set of extra flags to pass to the API Server or override
// default ones in form of <flagname>=<value>.
// TODO: This is temporary and ideally we would like to switch all components to
// use ComponentConfig + ConfigMaps.
APIServerExtraArgs map[string]string
// ControllerManagerExtraArgs is a set of extra flags to pass to the Controller Manager
// or override default ones in form of <flagname>=<value>
// TODO: This is temporary and ideally we would like to switch all components to
// use ComponentConfig + ConfigMaps.
ControllerManagerExtraArgs map[string]string
// SchedulerExtraArgs is a set of extra flags to pass to the Scheduler or override
// default ones in form of <flagname>=<value>
// TODO: This is temporary and ideally we would like to switch all components to
// use ComponentConfig + ConfigMaps.
SchedulerExtraArgs map[string]string
// 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 a 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
// APIServerExtraVolumes is an extra set of host volumes mounted to the API server.
APIServerExtraVolumes []HostPathMount
// ControllerManagerExtraVolumes is an extra set of host volumes mounted to the
// Controller Manager.
ControllerManagerExtraVolumes []HostPathMount
// SchedulerExtraVolumes is an extra set of host volumes mounted to the scheduler.
SchedulerExtraVolumes []HostPathMount
// APIServer contains extra settings for the API server control plane component
APIServer APIServer
// ControllerManager contains extra settings for the controller manager control plane component
ControllerManager ControlPlaneComponent
// Scheduler contains extra settings for the scheduler control plane component
Scheduler ControlPlaneComponent
// DNS defines the options for the DNS add-on installed in the cluster.
DNS DNS
// APIServerCertSANs sets extra Subject Alternative Names for the API Server
// signing cert.
APIServerCertSANs []string
// CertificatesDir specifies where to store or look for all required certificates.
CertificatesDir string
// ImageRepository is the container registry to pull control plane images from.
// ImageRepository sets the container registry to pull images from.
// If empty, `k8s.gcr.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`)
// `gcr.io/kubernetes-ci-images` will be used as a default for control plane components and for kube-proxy, while `k8s.gcr.io`
// will be used for all the other images.
ImageRepository string
// CIImageRepository is the container registry for core images generated by CI.
@ -98,12 +112,8 @@ type MasterConfiguration struct {
// +k8s:conversion-gen=false
CIImageRepository string
// UnifiedControlPlaneImage specifies if a specific container image should be
// used for all control plane components.
UnifiedControlPlaneImage string
// AuditPolicyConfiguration defines the options for the api server audit system.
AuditPolicyConfiguration AuditPolicyConfiguration
// UseHyperKubeImage controls if hyperkube should be used for Kubernetes components instead of their respective separate images
UseHyperKubeImage bool
// FeatureGates enabled by the user.
FeatureGates map[string]bool
@ -112,22 +122,87 @@ type MasterConfiguration struct {
ClusterName string
}
// API struct contains elements of API server address.
type API struct {
// ControlPlaneComponent holds settings common to control plane component of the cluster
type ControlPlaneComponent struct {
// ExtraArgs is an extra set of flags to pass to the control plane component.
// TODO: This is temporary and ideally we would like to switch all components to
// use ComponentConfig + ConfigMaps.
ExtraArgs map[string]string
// ExtraVolumes is an extra set of host volumes, mounted to the control plane component.
ExtraVolumes []HostPathMount
}
// APIServer holds settings necessary for API server deployments in the cluster
type APIServer struct {
ControlPlaneComponent
// CertSANs sets extra Subject Alternative Names for the API Server signing cert.
CertSANs []string
// TimeoutForControlPlane controls the timeout that we use for API server to appear
TimeoutForControlPlane *metav1.Duration
}
// DNSAddOnType defines string identifying DNS add-on types
type DNSAddOnType string
const (
// CoreDNS add-on type
CoreDNS DNSAddOnType = "CoreDNS"
// KubeDNS add-on type
KubeDNS DNSAddOnType = "kube-dns"
)
// DNS defines the DNS addon that should be used in the cluster
type DNS struct {
// Type defines the DNS add-on to be used
Type DNSAddOnType
// ImageMeta allows to customize the image used for the DNS component
ImageMeta `json:",inline"`
}
// ImageMeta allows to customize the image used for components that are not
// originated from the Kubernetes/Kubernetes release process
type ImageMeta struct {
// ImageRepository sets the container registry to pull images from.
// if not set, the ImageRepository defined in ClusterConfiguration will be used instead.
ImageRepository string
// ImageTag allows to specify a tag for the image.
// In case this value is set, kubeadm does not change automatically the version of the above components during upgrades.
ImageTag string
//TODO: evaluate if we need also a ImageName based on user feedbacks
}
// ComponentConfigs holds known internal ComponentConfig types for other components
type ComponentConfigs struct {
// Kubelet holds the ComponentConfiguration for the kubelet
Kubelet *kubeletconfig.KubeletConfiguration
// KubeProxy holds the ComponentConfiguration for the kube-proxy
KubeProxy *kubeproxyconfig.KubeProxyConfiguration
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterStatus contains the cluster status. The ClusterStatus will be stored in the kubeadm-config
// ConfigMap in the cluster, and then updated by kubeadm when additional control plane instance joins or leaves the cluster.
type ClusterStatus struct {
metav1.TypeMeta
// APIEndpoints currently available in the cluster, one for each control plane/api server instance.
// The key of the map is the IP of the host's default interface
APIEndpoints map[string]APIEndpoint
}
// APIEndpoint struct contains elements of API server instance deployed on a node.
type APIEndpoint struct {
// AdvertiseAddress sets the IP address for the API server to advertise.
AdvertiseAddress string
// 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
// BindPort sets the secure port for the API Server to bind to.
// Defaults to 6443.
BindPort int32
@ -151,7 +226,7 @@ type NodeRegistrationOptions struct {
// 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.
// Flags have higher priority when parsing. These values are local and specific to the node kubeadm is executing on.
KubeletExtraArgs map[string]string
}
@ -201,21 +276,10 @@ type Etcd struct {
External *ExternalEtcd
}
// Fuzz is a dummy function here to get the roundtrip tests working in cmd/kubeadm/app/apis/kubeadm/fuzzer working.
// As we split the monolith-etcd struct into two smaller pieces with pointers and they are mutually exclusive, roundtrip
// tests that randomize all values in this struct isn't feasible. Instead, we override the fuzzing function for .Etcd with
// this func by letting Etcd implement the fuzz.Interface interface. As this func does nothing, we rely on the values given
// in fuzzer/fuzzer.go for the roundtrip tests, which is exactly what we want.
// TODO: Remove this function when we remove the v1alpha1 API
func (e Etcd) Fuzz(c fuzz.Continue) {}
// 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
// ImageMeta allows to customize the container used for etcd
ImageMeta `json:",inline"`
// DataDir is the directory etcd will place its data.
// Defaults to "/var/lib/etcd".
@ -247,9 +311,8 @@ type ExternalEtcd struct {
// +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 {
// JoinConfiguration contains elements describing a particular node.
type JoinConfiguration struct {
metav1.TypeMeta
// NodeRegistration holds fields that relate to registering the new master node to the cluster
@ -259,27 +322,50 @@ type NodeConfiguration struct {
// secure comunications between node and master.
// Defaults to "/etc/kubernetes/pki/ca.crt".
CACertPath string
// DiscoveryFile is a file or url to a kubeconfig file from which to
// load cluster information.
DiscoveryFile string
// DiscoveryToken is a token used to validate cluster information
// fetched from the master.
DiscoveryToken string
// 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
// DiscoveryTimeout modifies the discovery timeout
DiscoveryTimeout *metav1.Duration
// TLSBootstrapToken is a token used for TLS bootstrapping.
// Defaults to Token.
TLSBootstrapToken string
// Token is used for both discovery and TLS bootstrapping.
Token string
// The cluster name
ClusterName string
// DiscoveryTokenCACertHashes specifies a set of public key pins to verify
// Discovery specifies the options for the kubelet to use during the TLS Bootstrap process
Discovery Discovery
// ControlPlane defines the additional control plane instance to be deployed on the joining node.
// If nil, no additional control plane instance will be deployed.
ControlPlane *JoinControlPlane
}
// JoinControlPlane contains elements describing an additional control plane instance to be deployed on the joining node.
type JoinControlPlane struct {
// LocalAPIEndpoint represents the endpoint of the API server instance to be deployed on this node.
LocalAPIEndpoint APIEndpoint
}
// Discovery specifies the options for the kubelet to use during the TLS Bootstrap process
type Discovery struct {
// BootstrapToken is used to set the options for bootstrap token based discovery
// BootstrapToken and File are mutually exclusive
BootstrapToken *BootstrapTokenDiscovery
// File is used to specify a file or URL to a kubeconfig file from which to load cluster information
// BootstrapToken and File are mutually exclusive
File *FileDiscovery
// TLSBootstrapToken is a token used for TLS bootstrapping.
// If .BootstrapToken is set, this field is defaulted to .BootstrapToken.Token, but can be overridden.
// If .File is set, this field **must be set** in case the KubeConfigFile does not contain any other authentication information
TLSBootstrapToken string
// Timeout modifies the discovery timeout
Timeout *metav1.Duration
}
// BootstrapTokenDiscovery is used to set the options for bootstrap token based discovery
type BootstrapTokenDiscovery struct {
// Token is a token used to validate cluster information
// fetched from the master.
Token string
// APIServerEndpoint is an IP or domain name to the API server from which info will be fetched.
APIServerEndpoint string
// CACertHashes 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 "<type>:<value>",
@ -287,20 +373,18 @@ type NodeConfiguration struct {
// 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
CACertHashes []string
// DiscoveryTokenUnsafeSkipCAVerification allows token-based discovery
// without CA verification via DiscoveryTokenCACertHashes. This can weaken
// UnsafeSkipCAVerification allows token-based discovery
// without CA verification via CACertHashes. This can weaken
// the security of kubeadm since other nodes can impersonate the master.
DiscoveryTokenUnsafeSkipCAVerification bool
// FeatureGates enabled by the user.
FeatureGates map[string]bool
UnsafeSkipCAVerification bool
}
// KubeletConfiguration contains elements describing initial remote configuration of kubelet.
type KubeletConfiguration struct {
BaseConfig *kubeletconfigv1beta1.KubeletConfiguration
// FileDiscovery is used to specify a file or URL to a kubeconfig file from which to load cluster information
type FileDiscovery struct {
// KubeConfigPath is used to specify the actual file path or URL to the kubeconfig file from which to load cluster information
KubeConfigPath string
}
// GetControlPlaneImageRepository returns name of image repository
@ -308,7 +392,7 @@ type KubeletConfiguration struct {
// It will override location with CI registry name in case user requests special
// Kubernetes version from CI build area.
// (See: kubeadmconstants.DefaultCIImageRepository)
func (cfg *MasterConfiguration) GetControlPlaneImageRepository() string {
func (cfg *ClusterConfiguration) GetControlPlaneImageRepository() string {
if cfg.CIImageRepository != "" {
return cfg.CIImageRepository
}
@ -325,30 +409,14 @@ type HostPathMount struct {
HostPath string
// MountPath is the path inside the pod where hostPath will be mounted.
MountPath string
// Writable controls write access to the volume
Writable bool
// ReadOnly controls write access to the volume
ReadOnly bool
// PathType is the type of the HostPath.
PathType v1.HostPathType
}
// KubeProxy contains elements describing the proxy configuration.
type KubeProxy struct {
Config *kubeproxyconfigv1alpha1.KubeProxyConfiguration
}
// 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
// LogDir is the local path to the directory where logs should be stored.
LogDir string
// LogMaxAge is the number of days logs will be stored for. 0 indicates forever.
LogMaxAge *int32
//TODO(chuckha) add other options for audit policy.
}
// CommonConfiguration defines the list of common configuration elements and the getter
// methods that must exist for both the MasterConfiguration and NodeConfiguration objects.
// methods that must exist for both the InitConfiguration and JoinConfiguration objects.
// This is used internally to deduplicate the kubeadm preflight checks.
type CommonConfiguration interface {
GetCRISocket() string
@ -356,40 +424,40 @@ type CommonConfiguration interface {
GetKubernetesVersion() string
}
// GetCRISocket will return the CRISocket that is defined for the MasterConfiguration.
// GetCRISocket will return the CRISocket that is defined for the InitConfiguration.
// This is used internally to deduplicate the kubeadm preflight checks.
func (cfg *MasterConfiguration) GetCRISocket() string {
func (cfg *InitConfiguration) GetCRISocket() string {
return cfg.NodeRegistration.CRISocket
}
// GetNodeName will return the NodeName that is defined for the MasterConfiguration.
// GetNodeName will return the NodeName that is defined for the InitConfiguration.
// This is used internally to deduplicate the kubeadm preflight checks.
func (cfg *MasterConfiguration) GetNodeName() string {
func (cfg *InitConfiguration) GetNodeName() string {
return cfg.NodeRegistration.Name
}
// GetKubernetesVersion will return the KubernetesVersion that is defined for the MasterConfiguration.
// GetKubernetesVersion will return the KubernetesVersion that is defined for the InitConfiguration.
// This is used internally to deduplicate the kubeadm preflight checks.
func (cfg *MasterConfiguration) GetKubernetesVersion() string {
func (cfg *InitConfiguration) GetKubernetesVersion() string {
return cfg.KubernetesVersion
}
// GetCRISocket will return the CRISocket that is defined for the NodeConfiguration.
// GetCRISocket will return the CRISocket that is defined for the JoinConfiguration.
// This is used internally to deduplicate the kubeadm preflight checks.
func (cfg *NodeConfiguration) GetCRISocket() string {
func (cfg *JoinConfiguration) GetCRISocket() string {
return cfg.NodeRegistration.CRISocket
}
// GetNodeName will return the NodeName that is defined for the NodeConfiguration.
// GetNodeName will return the NodeName that is defined for the JoinConfiguration.
// This is used internally to deduplicate the kubeadm preflight checks.
func (cfg *NodeConfiguration) GetNodeName() string {
func (cfg *JoinConfiguration) GetNodeName() string {
return cfg.NodeRegistration.Name
}
// GetKubernetesVersion will return an empty string since KubernetesVersion is not a
// defined property for NodeConfiguration. This will just cause the regex validation
// defined property for JoinConfiguration. This will just cause the regex validation
// of the defined version to be skipped during the preflight checks.
// This is used internally to deduplicate the kubeadm preflight checks.
func (cfg *NodeConfiguration) GetKubernetesVersion() string {
func (cfg *JoinConfiguration) GetKubernetesVersion() string {
return ""
}

View File

@ -1,102 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"conversion.go",
"defaults.go",
"doc.go",
"register.go",
"types.go",
"upgrade.go",
"zz_generated.conversion.go",
"zz_generated.deepcopy.go",
"zz_generated.defaults.go",
] + select({
"@io_bazel_rules_go//go/platform:android": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"defaults_windows.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1",
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",
"//vendor/github.com/ugorji/go/codec:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer: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 = ["upgrade_test.go"],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
deps = ["//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library"],
)
go_test(
name = "go_default_xtest",
srcs = ["conversion_test.go"],
deps = [
":go_default_library",
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
],
)

View File

@ -1,226 +0,0 @@
/*
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 v1alpha1
import (
"fmt"
"reflect"
"strings"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
)
func addConversionFuncs(scheme *runtime.Scheme) error {
// Add non-generated conversion functions
err := scheme.AddConversionFuncs(
Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration,
Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration,
Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration,
Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration,
Convert_v1alpha1_Etcd_To_kubeadm_Etcd,
Convert_kubeadm_Etcd_To_v1alpha1_Etcd,
)
if err != nil {
return err
}
return nil
}
// Upgrades below
func Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error {
if err := autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in, out, s); err != nil {
return err
}
UpgradeCloudProvider(in, out)
UpgradeAuthorizationModes(in, out)
UpgradeNodeRegistrationOptionsForMaster(in, out)
if err := UpgradeBootstrapTokens(in, out); err != nil {
return err
}
// We don't support migrating information from the .PrivilegedPods field which was removed in v1alpha2
// We don't support migrating information from the .ImagePullPolicy field which was removed in v1alpha2
return nil
}
func Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error {
if err := autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in, out, s); err != nil {
return err
}
// .NodeName has moved to .NodeRegistration.Name
out.NodeRegistration.Name = in.NodeName
// .CRISocket has moved to .NodeRegistration.CRISocket
out.NodeRegistration.CRISocket = in.CRISocket
return nil
}
func Convert_v1alpha1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
if err := autoConvert_v1alpha1_Etcd_To_kubeadm_Etcd(in, out, s); err != nil {
return err
}
// The .Etcd schema changed between v1alpha1 and v1alpha2 API types. The change was to basically only split up the fields into two sub-structs, which can be seen here
if len(in.Endpoints) != 0 {
out.External = &kubeadm.ExternalEtcd{
Endpoints: in.Endpoints,
CAFile: in.CAFile,
CertFile: in.CertFile,
KeyFile: in.KeyFile,
}
} else {
out.Local = &kubeadm.LocalEtcd{
Image: in.Image,
DataDir: in.DataDir,
ExtraArgs: in.ExtraArgs,
ServerCertSANs: in.ServerCertSANs,
PeerCertSANs: in.PeerCertSANs,
}
}
// No need to transfer information about .Etcd.Selfhosted to v1alpha2
return nil
}
// UpgradeCloudProvider handles the removal of .CloudProvider as smoothly as possible
func UpgradeCloudProvider(in *MasterConfiguration, out *kubeadm.MasterConfiguration) {
if len(in.CloudProvider) != 0 {
if out.APIServerExtraArgs == nil {
out.APIServerExtraArgs = map[string]string{}
}
if out.ControllerManagerExtraArgs == nil {
out.ControllerManagerExtraArgs = map[string]string{}
}
if out.NodeRegistration.KubeletExtraArgs == nil {
out.NodeRegistration.KubeletExtraArgs = map[string]string{}
}
out.APIServerExtraArgs["cloud-provider"] = in.CloudProvider
out.ControllerManagerExtraArgs["cloud-provider"] = in.CloudProvider
out.NodeRegistration.KubeletExtraArgs["cloud-provider"] = in.CloudProvider
}
}
func UpgradeAuthorizationModes(in *MasterConfiguration, out *kubeadm.MasterConfiguration) {
// If .AuthorizationModes was set to something else than the default, preserve the information via extraargs
if !reflect.DeepEqual(in.AuthorizationModes, strings.Split(DefaultAuthorizationModes, ",")) {
if out.APIServerExtraArgs == nil {
out.APIServerExtraArgs = map[string]string{}
}
out.APIServerExtraArgs["authorization-mode"] = strings.Join(in.AuthorizationModes, ",")
}
}
func UpgradeNodeRegistrationOptionsForMaster(in *MasterConfiguration, out *kubeadm.MasterConfiguration) {
// .NodeName has moved to .NodeRegistration.Name
out.NodeRegistration.Name = in.NodeName
// .CRISocket has moved to .NodeRegistration.CRISocket
out.NodeRegistration.CRISocket = in.CRISocket
// Transfer the information from .NoTaintMaster to the new layout
if in.NoTaintMaster {
out.NodeRegistration.Taints = []v1.Taint{}
} else {
out.NodeRegistration.Taints = []v1.Taint{constants.MasterTaint}
}
}
// UpgradeBootstrapTokens should create at least one empty bootstrap token in the out config.
func UpgradeBootstrapTokens(in *MasterConfiguration, out *kubeadm.MasterConfiguration) error {
bts, err := kubeadm.NewBootstrapTokenString(in.Token)
// Ignore the error if the incoming token was empty.
if err != nil && in.Token != "" {
return fmt.Errorf("can't parse .Token, and hence can't convert v1alpha1 API to a newer version: %v", err)
}
out.BootstrapTokens = []kubeadm.BootstrapToken{
{
Token: bts,
TTL: in.TokenTTL,
Usages: in.TokenUsages,
Groups: in.TokenGroups,
},
}
return nil
}
// Downgrades below
// This downgrade path IS NOT SUPPORTED. This is just here for roundtripping purposes at the moment.
func Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error {
if err := autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in, out, s); err != nil {
return err
}
// Converting from newer API version to an older API version isn't supported. This is here only for the roundtrip tests meanwhile.
out.NodeName = in.NodeRegistration.Name
out.CRISocket = in.NodeRegistration.CRISocket
out.NoTaintMaster = in.NodeRegistration.Taints != nil && len(in.NodeRegistration.Taints) == 0
if len(in.BootstrapTokens) > 0 {
out.Token = in.BootstrapTokens[0].Token.String()
out.TokenTTL = in.BootstrapTokens[0].TTL
out.TokenUsages = in.BootstrapTokens[0].Usages
out.TokenGroups = in.BootstrapTokens[0].Groups
}
return nil
}
// This downgrade path IS NOT SUPPORTED. This is just here for roundtripping purposes at the moment.
func Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error {
if err := autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in, out, s); err != nil {
return err
}
// Converting from newer API version to an older API version isn't supported. This is here only for the roundtrip tests meanwhile.
out.NodeName = in.NodeRegistration.Name
out.CRISocket = in.NodeRegistration.CRISocket
return nil
}
// This downgrade path IS NOT SUPPORTED. This is just here for roundtripping purposes at the moment.
func Convert_kubeadm_Etcd_To_v1alpha1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
if err := autoConvert_kubeadm_Etcd_To_v1alpha1_Etcd(in, out, s); err != nil {
return err
}
if in.External != nil {
out.Endpoints = in.External.Endpoints
out.CAFile = in.External.CAFile
out.CertFile = in.External.CertFile
out.KeyFile = in.External.KeyFile
} else {
out.Image = in.Local.Image
out.DataDir = in.Local.DataDir
out.ExtraArgs = in.Local.ExtraArgs
out.ServerCertSANs = in.Local.ServerCertSANs
out.PeerCertSANs = in.Local.PeerCertSANs
}
return nil
}

View File

@ -1,103 +0,0 @@
/*
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 v1alpha1_test
import (
"reflect"
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
)
func TestUpgradeBootstrapTokens(t *testing.T) {
testcases := []struct {
name string
in *v1alpha1.MasterConfiguration
expectedOut *kubeadm.MasterConfiguration
expectError bool
}{
{
name: "empty configs should create at least one token",
in: &v1alpha1.MasterConfiguration{},
expectedOut: &kubeadm.MasterConfiguration{
BootstrapTokens: []kubeadm.BootstrapToken{
{
Token: nil,
},
},
},
expectError: false,
},
{
name: "fail at parsing incoming token",
in: &v1alpha1.MasterConfiguration{
Token: "some fake token",
},
expectError: true,
},
{
name: "input has values",
in: &v1alpha1.MasterConfiguration{
Token: "abcdef.abcdefghijklmnop",
TokenTTL: &metav1.Duration{
Duration: time.Duration(10 * time.Hour),
},
TokenUsages: []string{"action"},
TokenGroups: []string{"group", "group2"},
},
expectedOut: &kubeadm.MasterConfiguration{
BootstrapTokens: []kubeadm.BootstrapToken{
{
Token: &kubeadm.BootstrapTokenString{
ID: "abcdef",
Secret: "abcdefghijklmnop",
},
TTL: &metav1.Duration{
Duration: time.Duration(10 * time.Hour),
},
Usages: []string{"action"},
Groups: []string{"group", "group2"},
},
},
},
expectError: false,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
out := &kubeadm.MasterConfiguration{}
err := v1alpha1.UpgradeBootstrapTokens(tc.in, out)
if tc.expectError {
if err == nil {
t.Fatal("expected an error but did not get one.")
}
// do not continue if we got an expected error
return
}
if !reflect.DeepEqual(out.BootstrapTokens, tc.expectedOut.BootstrapTokens) {
t.Fatalf("\nexpected: %v\ngot: %v", tc.expectedOut.BootstrapTokens, out.BootstrapTokens)
}
})
}
}

View File

@ -1,276 +0,0 @@
/*
Copyright 2016 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 v1alpha1
import (
"net/url"
"strings"
"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
// DefaultAuthorizationModes defines default authorization modes
DefaultAuthorizationModes = "Node,RBAC"
// 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"
// DefaultEtcdClusterSize defines the default cluster size when using the etcd-operator
DefaultEtcdClusterSize = 3
// DefaultEtcdOperatorVersion defines the default version of the etcd-operator to use
DefaultEtcdOperatorVersion = "v0.6.0"
// DefaultEtcdCertDir represents the directory where PKI assets are stored for self-hosted etcd
DefaultEtcdCertDir = "/etc/kubernetes/pki/etcd"
// DefaultEtcdClusterServiceName is the default name of the service backing the etcd cluster
DefaultEtcdClusterServiceName = "etcd-cluster"
// 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 len(obj.AuthorizationModes) == 0 {
obj.AuthorizationModes = strings.Split(DefaultAuthorizationModes, ",")
}
if obj.CertificatesDir == "" {
obj.CertificatesDir = DefaultCertificatesDir
}
if obj.TokenTTL == nil {
obj.TokenTTL = &metav1.Duration{
Duration: constants.DefaultTokenDuration,
}
}
if obj.CRISocket == "" {
obj.CRISocket = DefaultCRISocket
}
if len(obj.TokenUsages) == 0 {
obj.TokenUsages = constants.DefaultTokenUsages
}
if len(obj.TokenGroups) == 0 {
obj.TokenGroups = constants.DefaultTokenGroups
}
if obj.ImageRepository == "" {
obj.ImageRepository = DefaultImageRepository
}
if obj.Etcd.DataDir == "" {
obj.Etcd.DataDir = DefaultEtcdDataDir
}
if obj.ClusterName == "" {
obj.ClusterName = DefaultClusterName
}
SetDefaultsEtcdSelfHosted(obj)
SetDefaults_KubeletConfiguration(obj)
SetDefaults_ProxyConfiguration(obj)
SetDefaults_AuditPolicyConfiguration(obj)
}
// 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
}
if obj.CRISocket == "" {
obj.CRISocket = DefaultCRISocket
}
// 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
}
}
// SetDefaultsEtcdSelfHosted sets defaults for self-hosted etcd if used
func SetDefaultsEtcdSelfHosted(obj *MasterConfiguration) {
if obj.Etcd.SelfHosted != nil {
if obj.Etcd.SelfHosted.ClusterServiceName == "" {
obj.Etcd.SelfHosted.ClusterServiceName = DefaultEtcdClusterServiceName
}
if obj.Etcd.SelfHosted.EtcdVersion == "" {
obj.Etcd.SelfHosted.EtcdVersion = constants.DefaultEtcdVersion
}
if obj.Etcd.SelfHosted.OperatorVersion == "" {
obj.Etcd.SelfHosted.OperatorVersion = DefaultEtcdOperatorVersion
}
if obj.Etcd.SelfHosted.CertificatesDir == "" {
obj.Etcd.SelfHosted.CertificatesDir = DefaultEtcdCertDir
}
}
}
// 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)
}
}
// 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
}
}

View File

@ -1,22 +0,0 @@
/*
Copyright 2016 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 v1alpha1 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 v1alpha1 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"

View File

@ -1,299 +0,0 @@
/*
Copyright 2016 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 v1alpha1
import (
v1 "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"`
// 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"`
// CloudProvider is the name of the cloud provider.
CloudProvider string `json:"cloudProvider"`
// NodeName is the name of the node that will host the k8s control plane.
// Defaults to the hostname if not provided.
NodeName string `json:"nodeName"`
// AuthorizationModes is a set of authorization modes used inside the cluster.
// If not specified, defaults to Node and RBAC, meaning both the node
// authorizer and RBAC are enabled.
AuthorizationModes []string `json:"authorizationModes,omitempty"`
// NoTaintMaster will, if set, suppress the tainting of the
// master node allowing workloads to be run on it (e.g. in
// single node configurations).
NoTaintMaster bool `json:"noTaintMaster,omitempty"`
// Mark the controller and api server pods as privileged as some cloud
// controllers like openstack need escalated privileges under some conditions
// example - loading a config drive to fetch node information
PrivilegedPods bool `json:"privilegedPods"`
// Token is used for establishing bidirectional trust between nodes and masters.
// Used for joining nodes in the cluster.
Token string `json:"token"`
// TokenTTL defines the ttl for Token. Defaults to 24h.
TokenTTL *metav1.Duration `json:"tokenTTL,omitempty"`
// TokenUsages describes the ways in which this token can be used.
TokenUsages []string `json:"tokenUsages,omitempty"`
// Extra groups that this token will authenticate as when used for authentication
TokenGroups []string `json:"tokenGroups,omitempty"`
// CRISocket is used to retrieve container runtime info.
CRISocket string `json:"criSocket,omitempty"`
// APIServerExtraArgs is a set of extra flags to pass to the API Server or override
// default ones in form of <flagname>=<value>.
// 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 <flagname>=<value>
// 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 <flagname>=<value>
// 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"`
// ImagePullPolicy that control plane images. Can be Always, IfNotPresent or Never.
ImagePullPolicy v1.PullPolicy `json:"imagePullPolicy,omitempty"`
// 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"`
}
// TokenDiscovery contains elements needed for token discovery.
type TokenDiscovery struct {
// ID is the first part of a bootstrap token. Considered public information.
// It is used when referring to a token without leaking the secret part.
ID string `json:"id"`
// Secret is the second part of a bootstrap token. Should only be shared
// with trusted parties.
Secret string `json:"secret"`
// TODO: Seems unused. Remove?
// Addresses []string `json:"addresses"`
}
// 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"`
}
// Etcd contains elements describing Etcd configuration.
type Etcd 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"`
// 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"`
// 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"`
// SelfHosted holds configuration for self-hosting etcd.
SelfHosted *SelfHostedEtcd `json:"selfHosted,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"`
}
// SelfHostedEtcd describes options required to configure self-hosted etcd.
type SelfHostedEtcd struct {
// CertificatesDir represents the directory where all etcd TLS assets are stored.
// Defaults to "/etc/kubernetes/pki/etcd".
CertificatesDir string `json:"certificatesDir"`
// ClusterServiceName is the name of the service that load balances the etcd cluster.
ClusterServiceName string `json:"clusterServiceName"`
// EtcdVersion is the version of etcd running in the cluster.
EtcdVersion string `json:"etcdVersion"`
// OperatorVersion is the version of the etcd-operator to use.
OperatorVersion string `json:"operatorVersion"`
}
// +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"`
// 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"`
// NodeName is the name of the node to join the cluster. Defaults
// to the name of the host.
NodeName string `json:"nodeName"`
// 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"`
// CRISocket is used to retrieve container runtime info.
CRISocket string `json:"criSocket,omitempty"`
// 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 "<type>:<value>",
// 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.
}

View File

@ -1,98 +0,0 @@
/*
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 v1alpha1
import (
"bytes"
"fmt"
"reflect"
"strconv"
"strings"
"github.com/ugorji/go/codec"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
)
type configMutationFunc func(map[string]interface{}) error
// These migrations are a stop-gap until we get a properly-versioned configuration file for MasterConfiguration.
// https://github.com/kubernetes/kubeadm/issues/750
var migrations = map[string][]configMutationFunc{
"MasterConfiguration": {
proxyFeatureListToMap,
},
}
// Migrate takes a map representing a config file and an object to decode into.
// The map is transformed into a format suitable for encoding into the supplied object, then serialised and decoded.
func Migrate(in map[string]interface{}, obj runtime.Object, codecs serializer.CodecFactory) error {
kind := reflect.TypeOf(obj).Elem().Name()
migrationsForKind := migrations[kind]
for _, m := range migrationsForKind {
err := m(in)
if err != nil {
return err
}
}
// Use codec instead of encoding/json to handle map[interface{}]interface{}
handle := &codec.JsonHandle{}
buf := new(bytes.Buffer)
if err := codec.NewEncoder(buf, handle).Encode(in); err != nil {
return fmt.Errorf("couldn't json encode object: %v", err)
}
return runtime.DecodeInto(codecs.UniversalDecoder(), buf.Bytes(), obj)
}
func proxyFeatureListToMap(m map[string]interface{}) error {
featureGatePath := []string{"kubeProxy", "config", "featureGates"}
// If featureGatePath is already a map, we don't need to do anything.
_, _, err := unstructured.NestedMap(m, featureGatePath...)
if err == nil {
return nil
}
gates, _, err := unstructured.NestedString(m, featureGatePath...)
if err != nil {
return fmt.Errorf("couldn't get featureGates: %v", err)
}
gateMap := make(map[string]interface{})
for _, gate := range strings.Split(gates, ",") {
if gate == "" {
continue
}
parts := strings.SplitN(gate, "=", 2)
if len(parts) != 2 {
return fmt.Errorf("unparsable kubeproxy feature gate %q", gate)
}
val, err := strconv.ParseBool(parts[1])
if err != nil {
return fmt.Errorf("unparsable kubeproxy feature gate %q: %v", gate, err)
}
gateMap[parts[0]] = val
}
unstructured.SetNestedMap(m, gateMap, featureGatePath...)
return nil
}

View File

@ -1,117 +0,0 @@
/*
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 v1alpha1
import (
"testing"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func TestProxyFeatureListToMap(t *testing.T) {
cases := []struct {
name string
featureGates interface{}
expected map[string]interface{}
shouldError bool
}{
{
name: "multiple features",
featureGates: "feature1=true,feature2=false",
expected: map[string]interface{}{
"feature1": true,
"feature2": false,
},
},
{
name: "single feature",
featureGates: "feature1=true",
expected: map[string]interface{}{
"feature1": true,
},
},
{
name: "already a map",
featureGates: map[string]interface{}{
"feature1": true,
},
expected: map[string]interface{}{
"feature1": true,
},
},
{
name: "single feature",
featureGates: "",
expected: map[string]interface{}{},
},
{
name: "malformed string",
featureGates: "test,",
shouldError: true,
},
}
for _, testCase := range cases {
t.Run(testCase.name, func(t *testing.T) {
cfg := map[string]interface{}{
"kubeProxy": map[string]interface{}{
"config": map[string]interface{}{
"featureGates": testCase.featureGates,
},
},
}
err := proxyFeatureListToMap(cfg)
if testCase.shouldError {
if err == nil {
t.Error("expected error, got nil")
}
return
}
if err != nil {
t.Errorf("unexpected error: %v", err)
}
gates, ok, err := unstructured.NestedMap(cfg, "kubeProxy", "config", "featureGates")
if !ok {
t.Errorf("missing map keys in nested map")
}
if err != nil {
t.Errorf("unexpected error in map: %v", err)
}
if len(testCase.expected) != len(gates) {
t.Errorf("expected feature gate size %d, got %d", len(testCase.expected), len(gates))
}
for k, v := range testCase.expected {
gateVal, ok := gates[k]
if !ok {
t.Errorf("featureGates missing key %q", k)
continue
}
if v != gateVal {
t.Errorf("expected value %v, got %v", v, gateVal)
}
}
})
}
}

View File

@ -1,339 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by conversion-gen. DO NOT EDIT.
package v1alpha1
import (
unsafe "unsafe"
v1 "k8s.io/api/core/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
kubeproxyconfig_v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1alpha1_API_To_kubeadm_API,
Convert_kubeadm_API_To_v1alpha1_API,
Convert_v1alpha1_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration,
Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha1_AuditPolicyConfiguration,
Convert_v1alpha1_Etcd_To_kubeadm_Etcd,
Convert_kubeadm_Etcd_To_v1alpha1_Etcd,
Convert_v1alpha1_HostPathMount_To_kubeadm_HostPathMount,
Convert_kubeadm_HostPathMount_To_v1alpha1_HostPathMount,
Convert_v1alpha1_KubeProxy_To_kubeadm_KubeProxy,
Convert_kubeadm_KubeProxy_To_v1alpha1_KubeProxy,
Convert_v1alpha1_KubeletConfiguration_To_kubeadm_KubeletConfiguration,
Convert_kubeadm_KubeletConfiguration_To_v1alpha1_KubeletConfiguration,
Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration,
Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration,
Convert_v1alpha1_Networking_To_kubeadm_Networking,
Convert_kubeadm_Networking_To_v1alpha1_Networking,
Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration,
Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration,
)
}
func autoConvert_v1alpha1_API_To_kubeadm_API(in *API, out *kubeadm.API, s conversion.Scope) error {
out.AdvertiseAddress = in.AdvertiseAddress
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
out.BindPort = in.BindPort
return nil
}
// Convert_v1alpha1_API_To_kubeadm_API is an autogenerated conversion function.
func Convert_v1alpha1_API_To_kubeadm_API(in *API, out *kubeadm.API, s conversion.Scope) error {
return autoConvert_v1alpha1_API_To_kubeadm_API(in, out, s)
}
func autoConvert_kubeadm_API_To_v1alpha1_API(in *kubeadm.API, out *API, s conversion.Scope) error {
out.AdvertiseAddress = in.AdvertiseAddress
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
out.BindPort = in.BindPort
return nil
}
// Convert_kubeadm_API_To_v1alpha1_API is an autogenerated conversion function.
func Convert_kubeadm_API_To_v1alpha1_API(in *kubeadm.API, out *API, s conversion.Scope) error {
return autoConvert_kubeadm_API_To_v1alpha1_API(in, out, s)
}
func autoConvert_v1alpha1_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(in *AuditPolicyConfiguration, out *kubeadm.AuditPolicyConfiguration, s conversion.Scope) error {
out.Path = in.Path
out.LogDir = in.LogDir
out.LogMaxAge = (*int32)(unsafe.Pointer(in.LogMaxAge))
return nil
}
// Convert_v1alpha1_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(in *AuditPolicyConfiguration, out *kubeadm.AuditPolicyConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(in, out, s)
}
func autoConvert_kubeadm_AuditPolicyConfiguration_To_v1alpha1_AuditPolicyConfiguration(in *kubeadm.AuditPolicyConfiguration, out *AuditPolicyConfiguration, s conversion.Scope) error {
out.Path = in.Path
out.LogDir = in.LogDir
out.LogMaxAge = (*int32)(unsafe.Pointer(in.LogMaxAge))
return nil
}
// Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha1_AuditPolicyConfiguration is an autogenerated conversion function.
func Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha1_AuditPolicyConfiguration(in *kubeadm.AuditPolicyConfiguration, out *AuditPolicyConfiguration, s conversion.Scope) error {
return autoConvert_kubeadm_AuditPolicyConfiguration_To_v1alpha1_AuditPolicyConfiguration(in, out, s)
}
func autoConvert_v1alpha1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
// WARNING: in.Endpoints requires manual conversion: does not exist in peer-type
// WARNING: in.CAFile requires manual conversion: does not exist in peer-type
// WARNING: in.CertFile requires manual conversion: does not exist in peer-type
// WARNING: in.KeyFile requires manual conversion: does not exist in peer-type
// WARNING: in.DataDir requires manual conversion: does not exist in peer-type
// WARNING: in.ExtraArgs requires manual conversion: does not exist in peer-type
// WARNING: in.Image requires manual conversion: does not exist in peer-type
// WARNING: in.SelfHosted requires manual conversion: does not exist in peer-type
// WARNING: in.ServerCertSANs requires manual conversion: does not exist in peer-type
// WARNING: in.PeerCertSANs requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_kubeadm_Etcd_To_v1alpha1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
// WARNING: in.Local requires manual conversion: does not exist in peer-type
// WARNING: in.External requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_v1alpha1_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
out.Name = in.Name
out.HostPath = in.HostPath
out.MountPath = in.MountPath
out.Writable = in.Writable
out.PathType = v1.HostPathType(in.PathType)
return nil
}
// Convert_v1alpha1_HostPathMount_To_kubeadm_HostPathMount is an autogenerated conversion function.
func Convert_v1alpha1_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
return autoConvert_v1alpha1_HostPathMount_To_kubeadm_HostPathMount(in, out, s)
}
func autoConvert_kubeadm_HostPathMount_To_v1alpha1_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
out.Name = in.Name
out.HostPath = in.HostPath
out.MountPath = in.MountPath
out.Writable = in.Writable
out.PathType = v1.HostPathType(in.PathType)
return nil
}
// Convert_kubeadm_HostPathMount_To_v1alpha1_HostPathMount is an autogenerated conversion function.
func Convert_kubeadm_HostPathMount_To_v1alpha1_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
return autoConvert_kubeadm_HostPathMount_To_v1alpha1_HostPathMount(in, out, s)
}
func autoConvert_v1alpha1_KubeProxy_To_kubeadm_KubeProxy(in *KubeProxy, out *kubeadm.KubeProxy, s conversion.Scope) error {
out.Config = (*kubeproxyconfig_v1alpha1.KubeProxyConfiguration)(unsafe.Pointer(in.Config))
return nil
}
// Convert_v1alpha1_KubeProxy_To_kubeadm_KubeProxy is an autogenerated conversion function.
func Convert_v1alpha1_KubeProxy_To_kubeadm_KubeProxy(in *KubeProxy, out *kubeadm.KubeProxy, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeProxy_To_kubeadm_KubeProxy(in, out, s)
}
func autoConvert_kubeadm_KubeProxy_To_v1alpha1_KubeProxy(in *kubeadm.KubeProxy, out *KubeProxy, s conversion.Scope) error {
out.Config = (*kubeproxyconfig_v1alpha1.KubeProxyConfiguration)(unsafe.Pointer(in.Config))
return nil
}
// Convert_kubeadm_KubeProxy_To_v1alpha1_KubeProxy is an autogenerated conversion function.
func Convert_kubeadm_KubeProxy_To_v1alpha1_KubeProxy(in *kubeadm.KubeProxy, out *KubeProxy, s conversion.Scope) error {
return autoConvert_kubeadm_KubeProxy_To_v1alpha1_KubeProxy(in, out, s)
}
func autoConvert_v1alpha1_KubeletConfiguration_To_kubeadm_KubeletConfiguration(in *KubeletConfiguration, out *kubeadm.KubeletConfiguration, s conversion.Scope) error {
out.BaseConfig = (*v1beta1.KubeletConfiguration)(unsafe.Pointer(in.BaseConfig))
return nil
}
// Convert_v1alpha1_KubeletConfiguration_To_kubeadm_KubeletConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_KubeletConfiguration_To_kubeadm_KubeletConfiguration(in *KubeletConfiguration, out *kubeadm.KubeletConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_KubeletConfiguration_To_kubeadm_KubeletConfiguration(in, out, s)
}
func autoConvert_kubeadm_KubeletConfiguration_To_v1alpha1_KubeletConfiguration(in *kubeadm.KubeletConfiguration, out *KubeletConfiguration, s conversion.Scope) error {
out.BaseConfig = (*v1beta1.KubeletConfiguration)(unsafe.Pointer(in.BaseConfig))
return nil
}
// Convert_kubeadm_KubeletConfiguration_To_v1alpha1_KubeletConfiguration is an autogenerated conversion function.
func Convert_kubeadm_KubeletConfiguration_To_v1alpha1_KubeletConfiguration(in *kubeadm.KubeletConfiguration, out *KubeletConfiguration, s conversion.Scope) error {
return autoConvert_kubeadm_KubeletConfiguration_To_v1alpha1_KubeletConfiguration(in, out, s)
}
func autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error {
if err := Convert_v1alpha1_API_To_kubeadm_API(&in.API, &out.API, s); err != nil {
return err
}
if err := Convert_v1alpha1_KubeProxy_To_kubeadm_KubeProxy(&in.KubeProxy, &out.KubeProxy, s); err != nil {
return err
}
if err := Convert_v1alpha1_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
return err
}
if err := Convert_v1alpha1_KubeletConfiguration_To_kubeadm_KubeletConfiguration(&in.KubeletConfiguration, &out.KubeletConfiguration, s); err != nil {
return err
}
if err := Convert_v1alpha1_Networking_To_kubeadm_Networking(&in.Networking, &out.Networking, s); err != nil {
return err
}
out.KubernetesVersion = in.KubernetesVersion
// WARNING: in.CloudProvider requires manual conversion: does not exist in peer-type
// WARNING: in.NodeName requires manual conversion: does not exist in peer-type
// WARNING: in.AuthorizationModes requires manual conversion: does not exist in peer-type
// WARNING: in.NoTaintMaster requires manual conversion: does not exist in peer-type
// WARNING: in.PrivilegedPods requires manual conversion: does not exist in peer-type
// WARNING: in.Token requires manual conversion: does not exist in peer-type
// WARNING: in.TokenTTL requires manual conversion: does not exist in peer-type
// WARNING: in.TokenUsages requires manual conversion: does not exist in peer-type
// WARNING: in.TokenGroups requires manual conversion: does not exist in peer-type
// WARNING: in.CRISocket requires manual conversion: does not exist in peer-type
out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs))
out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs))
out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs))
out.APIServerExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.APIServerExtraVolumes))
out.ControllerManagerExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.ControllerManagerExtraVolumes))
out.SchedulerExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.SchedulerExtraVolumes))
out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs))
out.CertificatesDir = in.CertificatesDir
out.ImageRepository = in.ImageRepository
// WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type
out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage
if err := Convert_v1alpha1_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(&in.AuditPolicyConfiguration, &out.AuditPolicyConfiguration, s); err != nil {
return err
}
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.ClusterName = in.ClusterName
return nil
}
func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error {
// WARNING: in.BootstrapTokens requires manual conversion: does not exist in peer-type
// WARNING: in.NodeRegistration requires manual conversion: does not exist in peer-type
if err := Convert_kubeadm_API_To_v1alpha1_API(&in.API, &out.API, s); err != nil {
return err
}
if err := Convert_kubeadm_KubeProxy_To_v1alpha1_KubeProxy(&in.KubeProxy, &out.KubeProxy, s); err != nil {
return err
}
if err := Convert_kubeadm_Etcd_To_v1alpha1_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
return err
}
if err := Convert_kubeadm_KubeletConfiguration_To_v1alpha1_KubeletConfiguration(&in.KubeletConfiguration, &out.KubeletConfiguration, s); err != nil {
return err
}
if err := Convert_kubeadm_Networking_To_v1alpha1_Networking(&in.Networking, &out.Networking, s); err != nil {
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs))
out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs))
out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs))
out.APIServerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.APIServerExtraVolumes))
out.ControllerManagerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.ControllerManagerExtraVolumes))
out.SchedulerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.SchedulerExtraVolumes))
out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs))
out.CertificatesDir = in.CertificatesDir
out.ImageRepository = in.ImageRepository
// INFO: in.CIImageRepository opted out of conversion generation
out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage
if err := Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha1_AuditPolicyConfiguration(&in.AuditPolicyConfiguration, &out.AuditPolicyConfiguration, s); err != nil {
return err
}
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.ClusterName = in.ClusterName
return nil
}
func autoConvert_v1alpha1_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
out.ServiceSubnet = in.ServiceSubnet
out.PodSubnet = in.PodSubnet
out.DNSDomain = in.DNSDomain
return nil
}
// Convert_v1alpha1_Networking_To_kubeadm_Networking is an autogenerated conversion function.
func Convert_v1alpha1_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
return autoConvert_v1alpha1_Networking_To_kubeadm_Networking(in, out, s)
}
func autoConvert_kubeadm_Networking_To_v1alpha1_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
out.ServiceSubnet = in.ServiceSubnet
out.PodSubnet = in.PodSubnet
out.DNSDomain = in.DNSDomain
return nil
}
// Convert_kubeadm_Networking_To_v1alpha1_Networking is an autogenerated conversion function.
func Convert_kubeadm_Networking_To_v1alpha1_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
return autoConvert_kubeadm_Networking_To_v1alpha1_Networking(in, out, s)
}
func autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error {
out.CACertPath = in.CACertPath
out.DiscoveryFile = in.DiscoveryFile
out.DiscoveryToken = in.DiscoveryToken
out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers))
out.DiscoveryTimeout = (*meta_v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout))
// WARNING: in.NodeName requires manual conversion: does not exist in peer-type
out.TLSBootstrapToken = in.TLSBootstrapToken
out.Token = in.Token
// WARNING: in.CRISocket requires manual conversion: does not exist in peer-type
out.ClusterName = in.ClusterName
out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes))
out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
return nil
}
func autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error {
// WARNING: in.NodeRegistration requires manual conversion: does not exist in peer-type
out.CACertPath = in.CACertPath
out.DiscoveryFile = in.DiscoveryFile
out.DiscoveryToken = in.DiscoveryToken
out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers))
out.DiscoveryTimeout = (*meta_v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout))
out.TLSBootstrapToken = in.TLSBootstrapToken
out.Token = in.Token
out.ClusterName = in.ClusterName
out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes))
out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
return nil
}

View File

@ -1,384 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha1
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
kubeproxyconfig_v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *API) DeepCopyInto(out *API) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new API.
func (in *API) DeepCopy() *API {
if in == nil {
return nil
}
out := new(API)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AuditPolicyConfiguration) DeepCopyInto(out *AuditPolicyConfiguration) {
*out = *in
if in.LogMaxAge != nil {
in, out := &in.LogMaxAge, &out.LogMaxAge
if *in == nil {
*out = nil
} else {
*out = new(int32)
**out = **in
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuditPolicyConfiguration.
func (in *AuditPolicyConfiguration) DeepCopy() *AuditPolicyConfiguration {
if in == nil {
return nil
}
out := new(AuditPolicyConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Etcd) DeepCopyInto(out *Etcd) {
*out = *in
if in.Endpoints != nil {
in, out := &in.Endpoints, &out.Endpoints
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ExtraArgs != nil {
in, out := &in.ExtraArgs, &out.ExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.SelfHosted != nil {
in, out := &in.SelfHosted, &out.SelfHosted
if *in == nil {
*out = nil
} else {
*out = new(SelfHostedEtcd)
**out = **in
}
}
if in.ServerCertSANs != nil {
in, out := &in.ServerCertSANs, &out.ServerCertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.PeerCertSANs != nil {
in, out := &in.PeerCertSANs, &out.PeerCertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Etcd.
func (in *Etcd) DeepCopy() *Etcd {
if in == nil {
return nil
}
out := new(Etcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HostPathMount) DeepCopyInto(out *HostPathMount) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPathMount.
func (in *HostPathMount) DeepCopy() *HostPathMount {
if in == nil {
return nil
}
out := new(HostPathMount)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeProxy) DeepCopyInto(out *KubeProxy) {
*out = *in
if in.Config != nil {
in, out := &in.Config, &out.Config
if *in == nil {
*out = nil
} else {
*out = new(kubeproxyconfig_v1alpha1.KubeProxyConfiguration)
(*in).DeepCopyInto(*out)
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeProxy.
func (in *KubeProxy) DeepCopy() *KubeProxy {
if in == nil {
return nil
}
out := new(KubeProxy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) {
*out = *in
if in.BaseConfig != nil {
in, out := &in.BaseConfig, &out.BaseConfig
if *in == nil {
*out = nil
} else {
*out = new(v1beta1.KubeletConfiguration)
(*in).DeepCopyInto(*out)
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeletConfiguration.
func (in *KubeletConfiguration) DeepCopy() *KubeletConfiguration {
if in == nil {
return nil
}
out := new(KubeletConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MasterConfiguration) DeepCopyInto(out *MasterConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
out.API = in.API
in.KubeProxy.DeepCopyInto(&out.KubeProxy)
in.Etcd.DeepCopyInto(&out.Etcd)
in.KubeletConfiguration.DeepCopyInto(&out.KubeletConfiguration)
out.Networking = in.Networking
if in.AuthorizationModes != nil {
in, out := &in.AuthorizationModes, &out.AuthorizationModes
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.TokenTTL != nil {
in, out := &in.TokenTTL, &out.TokenTTL
if *in == nil {
*out = nil
} else {
*out = new(v1.Duration)
**out = **in
}
}
if in.TokenUsages != nil {
in, out := &in.TokenUsages, &out.TokenUsages
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.TokenGroups != nil {
in, out := &in.TokenGroups, &out.TokenGroups
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.APIServerExtraArgs != nil {
in, out := &in.APIServerExtraArgs, &out.APIServerExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.ControllerManagerExtraArgs != nil {
in, out := &in.ControllerManagerExtraArgs, &out.ControllerManagerExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.SchedulerExtraArgs != nil {
in, out := &in.SchedulerExtraArgs, &out.SchedulerExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.APIServerExtraVolumes != nil {
in, out := &in.APIServerExtraVolumes, &out.APIServerExtraVolumes
*out = make([]HostPathMount, len(*in))
copy(*out, *in)
}
if in.ControllerManagerExtraVolumes != nil {
in, out := &in.ControllerManagerExtraVolumes, &out.ControllerManagerExtraVolumes
*out = make([]HostPathMount, len(*in))
copy(*out, *in)
}
if in.SchedulerExtraVolumes != nil {
in, out := &in.SchedulerExtraVolumes, &out.SchedulerExtraVolumes
*out = make([]HostPathMount, len(*in))
copy(*out, *in)
}
if in.APIServerCertSANs != nil {
in, out := &in.APIServerCertSANs, &out.APIServerCertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
in.AuditPolicyConfiguration.DeepCopyInto(&out.AuditPolicyConfiguration)
if in.FeatureGates != nil {
in, out := &in.FeatureGates, &out.FeatureGates
*out = make(map[string]bool, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterConfiguration.
func (in *MasterConfiguration) DeepCopy() *MasterConfiguration {
if in == nil {
return nil
}
out := new(MasterConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *MasterConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Networking) DeepCopyInto(out *Networking) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Networking.
func (in *Networking) DeepCopy() *Networking {
if in == nil {
return nil
}
out := new(Networking)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeConfiguration) DeepCopyInto(out *NodeConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.DiscoveryTokenAPIServers != nil {
in, out := &in.DiscoveryTokenAPIServers, &out.DiscoveryTokenAPIServers
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.DiscoveryTimeout != nil {
in, out := &in.DiscoveryTimeout, &out.DiscoveryTimeout
if *in == nil {
*out = nil
} else {
*out = new(v1.Duration)
**out = **in
}
}
if in.DiscoveryTokenCACertHashes != nil {
in, out := &in.DiscoveryTokenCACertHashes, &out.DiscoveryTokenCACertHashes
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.FeatureGates != nil {
in, out := &in.FeatureGates, &out.FeatureGates
*out = make(map[string]bool, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeConfiguration.
func (in *NodeConfiguration) DeepCopy() *NodeConfiguration {
if in == nil {
return nil
}
out := new(NodeConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *NodeConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SelfHostedEtcd) DeepCopyInto(out *SelfHostedEtcd) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SelfHostedEtcd.
func (in *SelfHostedEtcd) DeepCopy() *SelfHostedEtcd {
if in == nil {
return nil
}
out := new(SelfHostedEtcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TokenDiscovery) DeepCopyInto(out *TokenDiscovery) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenDiscovery.
func (in *TokenDiscovery) DeepCopy() *TokenDiscovery {
if in == nil {
return nil
}
out := new(TokenDiscovery)
in.DeepCopyInto(out)
return out
}

View File

@ -1,50 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by defaulter-gen. DO NOT EDIT.
package v1alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
kubeproxyconfig_v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&MasterConfiguration{}, func(obj interface{}) { SetObjectDefaults_MasterConfiguration(obj.(*MasterConfiguration)) })
scheme.AddTypeDefaultingFunc(&NodeConfiguration{}, func(obj interface{}) { SetObjectDefaults_NodeConfiguration(obj.(*NodeConfiguration)) })
return nil
}
func SetObjectDefaults_MasterConfiguration(in *MasterConfiguration) {
SetDefaults_MasterConfiguration(in)
if in.KubeProxy.Config != nil {
kubeproxyconfig_v1alpha1.SetDefaults_KubeProxyConfiguration(in.KubeProxy.Config)
}
if in.KubeletConfiguration.BaseConfig != nil {
v1beta1.SetDefaults_KubeletConfiguration(in.KubeletConfiguration.BaseConfig)
}
}
func SetObjectDefaults_NodeConfiguration(in *NodeConfiguration) {
SetDefaults_NodeConfiguration(in)
}

View File

@ -1,88 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"bootstraptokenstring.go",
"defaults.go",
"doc.go",
"register.go",
"types.go",
"zz_generated.conversion.go",
"zz_generated.deepcopy.go",
"zz_generated.defaults.go",
] + select({
"@io_bazel_rules_go//go/platform:android": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"defaults_unix.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"defaults_windows.go",
],
"//conditions:default": [],
}),
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",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
"//vendor/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"],
)

View File

@ -1,501 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by conversion-gen. DO NOT EDIT.
package v1alpha2
import (
unsafe "unsafe"
core_v1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1alpha2_API_To_kubeadm_API,
Convert_kubeadm_API_To_v1alpha2_API,
Convert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration,
Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration,
Convert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken,
Convert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken,
Convert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString,
Convert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString,
Convert_v1alpha2_Etcd_To_kubeadm_Etcd,
Convert_kubeadm_Etcd_To_v1alpha2_Etcd,
Convert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd,
Convert_kubeadm_ExternalEtcd_To_v1alpha2_ExternalEtcd,
Convert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount,
Convert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount,
Convert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy,
Convert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy,
Convert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration,
Convert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration,
Convert_v1alpha2_LocalEtcd_To_kubeadm_LocalEtcd,
Convert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd,
Convert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration,
Convert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration,
Convert_v1alpha2_Networking_To_kubeadm_Networking,
Convert_kubeadm_Networking_To_v1alpha2_Networking,
Convert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration,
Convert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration,
Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions,
Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions,
)
}
func autoConvert_v1alpha2_API_To_kubeadm_API(in *API, out *kubeadm.API, s conversion.Scope) error {
out.AdvertiseAddress = in.AdvertiseAddress
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
out.BindPort = in.BindPort
return nil
}
// Convert_v1alpha2_API_To_kubeadm_API is an autogenerated conversion function.
func Convert_v1alpha2_API_To_kubeadm_API(in *API, out *kubeadm.API, s conversion.Scope) error {
return autoConvert_v1alpha2_API_To_kubeadm_API(in, out, s)
}
func autoConvert_kubeadm_API_To_v1alpha2_API(in *kubeadm.API, out *API, s conversion.Scope) error {
out.AdvertiseAddress = in.AdvertiseAddress
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
out.BindPort = in.BindPort
return nil
}
// Convert_kubeadm_API_To_v1alpha2_API is an autogenerated conversion function.
func Convert_kubeadm_API_To_v1alpha2_API(in *kubeadm.API, out *API, s conversion.Scope) error {
return autoConvert_kubeadm_API_To_v1alpha2_API(in, out, s)
}
func autoConvert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(in *AuditPolicyConfiguration, out *kubeadm.AuditPolicyConfiguration, s conversion.Scope) error {
out.Path = in.Path
out.LogDir = in.LogDir
out.LogMaxAge = (*int32)(unsafe.Pointer(in.LogMaxAge))
return nil
}
// Convert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration is an autogenerated conversion function.
func Convert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(in *AuditPolicyConfiguration, out *kubeadm.AuditPolicyConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(in, out, s)
}
func autoConvert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration(in *kubeadm.AuditPolicyConfiguration, out *AuditPolicyConfiguration, s conversion.Scope) error {
out.Path = in.Path
out.LogDir = in.LogDir
out.LogMaxAge = (*int32)(unsafe.Pointer(in.LogMaxAge))
return nil
}
// Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration is an autogenerated conversion function.
func Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration(in *kubeadm.AuditPolicyConfiguration, out *AuditPolicyConfiguration, s conversion.Scope) error {
return autoConvert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration(in, out, s)
}
func autoConvert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
out.Token = (*kubeadm.BootstrapTokenString)(unsafe.Pointer(in.Token))
out.Description = in.Description
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
return nil
}
// Convert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken is an autogenerated conversion function.
func Convert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
return autoConvert_v1alpha2_BootstrapToken_To_kubeadm_BootstrapToken(in, out, s)
}
func autoConvert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
out.Token = (*BootstrapTokenString)(unsafe.Pointer(in.Token))
out.Description = in.Description
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
return nil
}
// Convert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken is an autogenerated conversion function.
func Convert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
return autoConvert_kubeadm_BootstrapToken_To_v1alpha2_BootstrapToken(in, out, s)
}
func autoConvert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
out.ID = in.ID
out.Secret = in.Secret
return nil
}
// Convert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString is an autogenerated conversion function.
func Convert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
return autoConvert_v1alpha2_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in, out, s)
}
func autoConvert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
out.ID = in.ID
out.Secret = in.Secret
return nil
}
// Convert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString is an autogenerated conversion function.
func Convert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
return autoConvert_kubeadm_BootstrapTokenString_To_v1alpha2_BootstrapTokenString(in, out, s)
}
func autoConvert_v1alpha2_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
out.Local = (*kubeadm.LocalEtcd)(unsafe.Pointer(in.Local))
out.External = (*kubeadm.ExternalEtcd)(unsafe.Pointer(in.External))
return nil
}
// Convert_v1alpha2_Etcd_To_kubeadm_Etcd is an autogenerated conversion function.
func Convert_v1alpha2_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
return autoConvert_v1alpha2_Etcd_To_kubeadm_Etcd(in, out, s)
}
func autoConvert_kubeadm_Etcd_To_v1alpha2_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
out.Local = (*LocalEtcd)(unsafe.Pointer(in.Local))
out.External = (*ExternalEtcd)(unsafe.Pointer(in.External))
return nil
}
// Convert_kubeadm_Etcd_To_v1alpha2_Etcd is an autogenerated conversion function.
func Convert_kubeadm_Etcd_To_v1alpha2_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
return autoConvert_kubeadm_Etcd_To_v1alpha2_Etcd(in, out, s)
}
func autoConvert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error {
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
out.CAFile = in.CAFile
out.CertFile = in.CertFile
out.KeyFile = in.KeyFile
return nil
}
// Convert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd is an autogenerated conversion function.
func Convert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error {
return autoConvert_v1alpha2_ExternalEtcd_To_kubeadm_ExternalEtcd(in, out, s)
}
func autoConvert_kubeadm_ExternalEtcd_To_v1alpha2_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error {
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
out.CAFile = in.CAFile
out.CertFile = in.CertFile
out.KeyFile = in.KeyFile
return nil
}
// Convert_kubeadm_ExternalEtcd_To_v1alpha2_ExternalEtcd is an autogenerated conversion function.
func Convert_kubeadm_ExternalEtcd_To_v1alpha2_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error {
return autoConvert_kubeadm_ExternalEtcd_To_v1alpha2_ExternalEtcd(in, out, s)
}
func autoConvert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
out.Name = in.Name
out.HostPath = in.HostPath
out.MountPath = in.MountPath
out.Writable = in.Writable
out.PathType = core_v1.HostPathType(in.PathType)
return nil
}
// Convert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount is an autogenerated conversion function.
func Convert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
return autoConvert_v1alpha2_HostPathMount_To_kubeadm_HostPathMount(in, out, s)
}
func autoConvert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
out.Name = in.Name
out.HostPath = in.HostPath
out.MountPath = in.MountPath
out.Writable = in.Writable
out.PathType = core_v1.HostPathType(in.PathType)
return nil
}
// Convert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount is an autogenerated conversion function.
func Convert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
return autoConvert_kubeadm_HostPathMount_To_v1alpha2_HostPathMount(in, out, s)
}
func autoConvert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy(in *KubeProxy, out *kubeadm.KubeProxy, s conversion.Scope) error {
out.Config = (*v1alpha1.KubeProxyConfiguration)(unsafe.Pointer(in.Config))
return nil
}
// Convert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy is an autogenerated conversion function.
func Convert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy(in *KubeProxy, out *kubeadm.KubeProxy, s conversion.Scope) error {
return autoConvert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy(in, out, s)
}
func autoConvert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy(in *kubeadm.KubeProxy, out *KubeProxy, s conversion.Scope) error {
out.Config = (*v1alpha1.KubeProxyConfiguration)(unsafe.Pointer(in.Config))
return nil
}
// Convert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy is an autogenerated conversion function.
func Convert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy(in *kubeadm.KubeProxy, out *KubeProxy, s conversion.Scope) error {
return autoConvert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy(in, out, s)
}
func autoConvert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration(in *KubeletConfiguration, out *kubeadm.KubeletConfiguration, s conversion.Scope) error {
out.BaseConfig = (*v1beta1.KubeletConfiguration)(unsafe.Pointer(in.BaseConfig))
return nil
}
// Convert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration is an autogenerated conversion function.
func Convert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration(in *KubeletConfiguration, out *kubeadm.KubeletConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration(in, out, s)
}
func autoConvert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration(in *kubeadm.KubeletConfiguration, out *KubeletConfiguration, s conversion.Scope) error {
out.BaseConfig = (*v1beta1.KubeletConfiguration)(unsafe.Pointer(in.BaseConfig))
return nil
}
// Convert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration is an autogenerated conversion function.
func Convert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration(in *kubeadm.KubeletConfiguration, out *KubeletConfiguration, s conversion.Scope) error {
return autoConvert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration(in, out, s)
}
func autoConvert_v1alpha2_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error {
out.Image = in.Image
out.DataDir = in.DataDir
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs))
out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs))
return nil
}
// Convert_v1alpha2_LocalEtcd_To_kubeadm_LocalEtcd is an autogenerated conversion function.
func Convert_v1alpha2_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error {
return autoConvert_v1alpha2_LocalEtcd_To_kubeadm_LocalEtcd(in, out, s)
}
func autoConvert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error {
out.Image = in.Image
out.DataDir = in.DataDir
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs))
out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs))
return nil
}
// Convert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd is an autogenerated conversion function.
func Convert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error {
return autoConvert_kubeadm_LocalEtcd_To_v1alpha2_LocalEtcd(in, out, s)
}
func autoConvert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error {
out.BootstrapTokens = *(*[]kubeadm.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
if err := Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
if err := Convert_v1alpha2_API_To_kubeadm_API(&in.API, &out.API, s); err != nil {
return err
}
if err := Convert_v1alpha2_KubeProxy_To_kubeadm_KubeProxy(&in.KubeProxy, &out.KubeProxy, s); err != nil {
return err
}
if err := Convert_v1alpha2_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
return err
}
if err := Convert_v1alpha2_KubeletConfiguration_To_kubeadm_KubeletConfiguration(&in.KubeletConfiguration, &out.KubeletConfiguration, s); err != nil {
return err
}
if err := Convert_v1alpha2_Networking_To_kubeadm_Networking(&in.Networking, &out.Networking, s); err != nil {
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs))
out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs))
out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs))
out.APIServerExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.APIServerExtraVolumes))
out.ControllerManagerExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.ControllerManagerExtraVolumes))
out.SchedulerExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.SchedulerExtraVolumes))
out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs))
out.CertificatesDir = in.CertificatesDir
out.ImageRepository = in.ImageRepository
out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage
if err := Convert_v1alpha2_AuditPolicyConfiguration_To_kubeadm_AuditPolicyConfiguration(&in.AuditPolicyConfiguration, &out.AuditPolicyConfiguration, s); err != nil {
return err
}
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.ClusterName = in.ClusterName
return nil
}
// Convert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration is an autogenerated conversion function.
func Convert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha2_MasterConfiguration_To_kubeadm_MasterConfiguration(in, out, s)
}
func autoConvert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error {
out.BootstrapTokens = *(*[]BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
if err := Convert_kubeadm_API_To_v1alpha2_API(&in.API, &out.API, s); err != nil {
return err
}
if err := Convert_kubeadm_KubeProxy_To_v1alpha2_KubeProxy(&in.KubeProxy, &out.KubeProxy, s); err != nil {
return err
}
if err := Convert_kubeadm_Etcd_To_v1alpha2_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
return err
}
if err := Convert_kubeadm_KubeletConfiguration_To_v1alpha2_KubeletConfiguration(&in.KubeletConfiguration, &out.KubeletConfiguration, s); err != nil {
return err
}
if err := Convert_kubeadm_Networking_To_v1alpha2_Networking(&in.Networking, &out.Networking, s); err != nil {
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.APIServerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.APIServerExtraArgs))
out.ControllerManagerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ControllerManagerExtraArgs))
out.SchedulerExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.SchedulerExtraArgs))
out.APIServerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.APIServerExtraVolumes))
out.ControllerManagerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.ControllerManagerExtraVolumes))
out.SchedulerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.SchedulerExtraVolumes))
out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs))
out.CertificatesDir = in.CertificatesDir
out.ImageRepository = in.ImageRepository
// INFO: in.CIImageRepository opted out of conversion generation
out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage
if err := Convert_kubeadm_AuditPolicyConfiguration_To_v1alpha2_AuditPolicyConfiguration(&in.AuditPolicyConfiguration, &out.AuditPolicyConfiguration, s); err != nil {
return err
}
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.ClusterName = in.ClusterName
return nil
}
// Convert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration is an autogenerated conversion function.
func Convert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error {
return autoConvert_kubeadm_MasterConfiguration_To_v1alpha2_MasterConfiguration(in, out, s)
}
func autoConvert_v1alpha2_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
out.ServiceSubnet = in.ServiceSubnet
out.PodSubnet = in.PodSubnet
out.DNSDomain = in.DNSDomain
return nil
}
// Convert_v1alpha2_Networking_To_kubeadm_Networking is an autogenerated conversion function.
func Convert_v1alpha2_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
return autoConvert_v1alpha2_Networking_To_kubeadm_Networking(in, out, s)
}
func autoConvert_kubeadm_Networking_To_v1alpha2_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
out.ServiceSubnet = in.ServiceSubnet
out.PodSubnet = in.PodSubnet
out.DNSDomain = in.DNSDomain
return nil
}
// Convert_kubeadm_Networking_To_v1alpha2_Networking is an autogenerated conversion function.
func Convert_kubeadm_Networking_To_v1alpha2_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
return autoConvert_kubeadm_Networking_To_v1alpha2_Networking(in, out, s)
}
func autoConvert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error {
if err := Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
out.CACertPath = in.CACertPath
out.DiscoveryFile = in.DiscoveryFile
out.DiscoveryToken = in.DiscoveryToken
out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers))
out.DiscoveryTimeout = (*v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout))
out.TLSBootstrapToken = in.TLSBootstrapToken
out.Token = in.Token
out.ClusterName = in.ClusterName
out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes))
out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
return nil
}
// Convert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration is an autogenerated conversion function.
func Convert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha2_NodeConfiguration_To_kubeadm_NodeConfiguration(in, out, s)
}
func autoConvert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error {
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
out.CACertPath = in.CACertPath
out.DiscoveryFile = in.DiscoveryFile
out.DiscoveryToken = in.DiscoveryToken
out.DiscoveryTokenAPIServers = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenAPIServers))
out.DiscoveryTimeout = (*v1.Duration)(unsafe.Pointer(in.DiscoveryTimeout))
out.TLSBootstrapToken = in.TLSBootstrapToken
out.Token = in.Token
out.ClusterName = in.ClusterName
out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes))
out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
return nil
}
// Convert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration is an autogenerated conversion function.
func Convert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error {
return autoConvert_kubeadm_NodeConfiguration_To_v1alpha2_NodeConfiguration(in, out, s)
}
func autoConvert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error {
out.Name = in.Name
out.CRISocket = in.CRISocket
out.Taints = *(*[]core_v1.Taint)(unsafe.Pointer(&in.Taints))
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
return nil
}
// Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions is an autogenerated conversion function.
func Convert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error {
return autoConvert_v1alpha2_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in, out, s)
}
func autoConvert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
out.Name = in.Name
out.CRISocket = in.CRISocket
out.Taints = *(*[]core_v1.Taint)(unsafe.Pointer(&in.Taints))
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
return nil
}
// Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions is an autogenerated conversion function.
func Convert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
return autoConvert_kubeadm_NodeRegistrationOptions_To_v1alpha2_NodeRegistrationOptions(in, out, s)
}

View File

@ -0,0 +1,62 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"bootstraptokenstring.go",
"conversion.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/v1alpha3",
visibility = ["//visibility:public"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/images:go_default_library",
"//cmd/kubeadm/app/util: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/cluster-bootstrap/token/api:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
"//vendor/github.com/pkg/errors: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",
"conversion_test.go",
],
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)

View File

@ -14,18 +14,16 @@ 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 v1alpha2
package v1alpha3
import (
"fmt"
"strings"
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
"github.com/pkg/errors"
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
bootstraputil "k8s.io/cluster-bootstrap/token/util"
)
// BootstrapTokenString is a token of the format abcdef.abcdef0123456789 that is used
@ -77,7 +75,7 @@ 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 nil, errors.Errorf("the bootstrap token %q was not of the form %q", token, bootstrapapi.BootstrapTokenPattern)
}
return &BootstrapTokenString{ID: substrs[1], Secret: substrs[2]}, nil

View File

@ -0,0 +1,237 @@
/*
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"
"reflect"
"testing"
"github.com/pkg/errors"
)
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 errors.Wrap(err, "expected no unmarshal error, got error")
}
if b, err = json.Marshal(newbts); err != nil {
return errors.Wrap(err, "expected no marshal error, got error")
}
if input != string(b) {
return errors.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 errors.Wrap(err, "expected no marshal error, got error")
}
if err := json.Unmarshal(b, newbts); err != nil {
return errors.Wrap(err, "expected no unmarshal error, got error")
}
if !reflect.DeepEqual(bts, newbts) {
return errors.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,
)
}
}
}

View File

@ -0,0 +1,315 @@
/*
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 (
"regexp"
"strings"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
"k8s.io/kubernetes/cmd/kubeadm/app/images"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
)
var imageRegEx = regexp.MustCompile(`(?P<repository>.+/)(?P<image>[^:]+)(?P<tag>:.+)`)
func Convert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
if err := autoConvert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(in, out, s); err != nil {
return err
}
return Convert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(&in.APIEndpoint, &out.LocalAPIEndpoint, s)
}
func Convert_kubeadm_InitConfiguration_To_v1alpha3_InitConfiguration(in *kubeadm.InitConfiguration, out *InitConfiguration, s conversion.Scope) error {
if err := autoConvert_kubeadm_InitConfiguration_To_v1alpha3_InitConfiguration(in, out, s); err != nil {
return err
}
return Convert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(&in.LocalAPIEndpoint, &out.APIEndpoint, s)
}
func Convert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConfiguration, out *kubeadm.JoinConfiguration, s conversion.Scope) error {
if err := autoConvert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(in, out, s); err != nil {
return err
}
if len(in.ClusterName) != 0 {
return errors.New("clusterName has been removed from JoinConfiguration and clusterName from ClusterConfiguration will be used instead. Please cleanup JoinConfiguration.ClusterName fields")
}
if len(in.FeatureGates) != 0 {
return errors.New("featureGates has been removed from JoinConfiguration and featureGates from ClusterConfiguration will be used instead. Please cleanup JoinConfiguration.FeatureGates fields")
}
out.Discovery.Timeout = in.DiscoveryTimeout
if len(in.TLSBootstrapToken) != 0 {
out.Discovery.TLSBootstrapToken = in.TLSBootstrapToken
} else {
out.Discovery.TLSBootstrapToken = in.Token
}
if len(in.DiscoveryFile) != 0 {
out.Discovery.File = &kubeadm.FileDiscovery{
KubeConfigPath: in.DiscoveryFile,
}
} else {
out.Discovery.BootstrapToken = &kubeadm.BootstrapTokenDiscovery{
CACertHashes: in.DiscoveryTokenCACertHashes,
UnsafeSkipCAVerification: in.DiscoveryTokenUnsafeSkipCAVerification,
}
if len(in.DiscoveryTokenAPIServers) != 0 {
out.Discovery.BootstrapToken.APIServerEndpoint = in.DiscoveryTokenAPIServers[0]
}
if len(in.DiscoveryToken) != 0 {
out.Discovery.BootstrapToken.Token = in.DiscoveryToken
} else {
out.Discovery.BootstrapToken.Token = in.Token
}
}
if in.ControlPlane == true {
out.ControlPlane = &kubeadm.JoinControlPlane{}
if err := autoConvert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(&in.APIEndpoint, &out.ControlPlane.LocalAPIEndpoint, s); err != nil {
return err
}
}
return nil
}
func Convert_kubeadm_JoinConfiguration_To_v1alpha3_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error {
if err := autoConvert_kubeadm_JoinConfiguration_To_v1alpha3_JoinConfiguration(in, out, s); err != nil {
return err
}
out.DiscoveryTimeout = in.Discovery.Timeout
out.TLSBootstrapToken = in.Discovery.TLSBootstrapToken
if in.Discovery.BootstrapToken != nil {
out.DiscoveryToken = in.Discovery.BootstrapToken.Token
out.DiscoveryTokenAPIServers = []string{in.Discovery.BootstrapToken.APIServerEndpoint}
out.DiscoveryTokenCACertHashes = in.Discovery.BootstrapToken.CACertHashes
out.DiscoveryTokenUnsafeSkipCAVerification = in.Discovery.BootstrapToken.UnsafeSkipCAVerification
} else if in.Discovery.File != nil {
out.DiscoveryFile = in.Discovery.File.KubeConfigPath
}
if in.ControlPlane != nil {
out.ControlPlane = true
if err := autoConvert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(&in.ControlPlane.LocalAPIEndpoint, &out.APIEndpoint, s); err != nil {
return err
}
}
return nil
}
func Convert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
if err := autoConvert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in, out, s); err != nil {
return err
}
if len(in.AuditPolicyConfiguration.Path) > 0 {
return errors.New("AuditPolicyConfiguration has been removed from ClusterConfiguration. Please cleanup ClusterConfiguration.AuditPolicyConfiguration fields")
}
out.APIServer.ExtraArgs = in.APIServerExtraArgs
out.APIServer.CertSANs = in.APIServerCertSANs
out.APIServer.TimeoutForControlPlane = &metav1.Duration{
Duration: constants.DefaultControlPlaneTimeout,
}
if err := convertSlice_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(&in.APIServerExtraVolumes, &out.APIServer.ExtraVolumes, s); err != nil {
return err
}
out.ControllerManager.ExtraArgs = in.ControllerManagerExtraArgs
if err := convertSlice_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(&in.ControllerManagerExtraVolumes, &out.ControllerManager.ExtraVolumes, s); err != nil {
return err
}
out.Scheduler.ExtraArgs = in.SchedulerExtraArgs
if err := convertSlice_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(&in.SchedulerExtraVolumes, &out.Scheduler.ExtraVolumes, s); err != nil {
return err
}
if err := Convert_v1alpha3_UnifiedControlPlaneImage_To_kubeadm_UseHyperKubeImage(in, out); err != nil {
return err
}
// converting v1alpha3 featureGate CoreDNS to internal DNS.Type
if features.Enabled(in.FeatureGates, features.CoreDNS) {
out.DNS.Type = kubeadm.CoreDNS
} else {
out.DNS.Type = kubeadm.KubeDNS
}
delete(out.FeatureGates, features.CoreDNS)
return nil
}
func Convert_v1alpha3_UnifiedControlPlaneImage_To_kubeadm_UseHyperKubeImage(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration) error {
if len(in.UnifiedControlPlaneImage) == 0 {
out.UseHyperKubeImage = false
return nil
}
k8sImageTag := kubeadmutil.KubernetesVersionToImageTag(in.KubernetesVersion)
expectedImage := images.GetGenericImage(in.ImageRepository, constants.HyperKube, k8sImageTag)
if expectedImage == in.UnifiedControlPlaneImage {
out.UseHyperKubeImage = true
return nil
}
return errors.Errorf("cannot convert unifiedControlPlaneImage=%q to useHyperKubeImage", in.UnifiedControlPlaneImage)
}
func Convert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error {
if err := autoConvert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(in, out, s); err != nil {
return err
}
out.APIServerExtraArgs = in.APIServer.ExtraArgs
out.APIServerCertSANs = in.APIServer.CertSANs
if err := convertSlice_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(&in.APIServer.ExtraVolumes, &out.APIServerExtraVolumes, s); err != nil {
return err
}
out.ControllerManagerExtraArgs = in.ControllerManager.ExtraArgs
if err := convertSlice_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(&in.ControllerManager.ExtraVolumes, &out.ControllerManagerExtraVolumes, s); err != nil {
return err
}
out.SchedulerExtraArgs = in.Scheduler.ExtraArgs
if err := convertSlice_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(&in.Scheduler.ExtraVolumes, &out.SchedulerExtraVolumes, s); err != nil {
return err
}
if in.UseHyperKubeImage {
out.UnifiedControlPlaneImage = images.GetKubernetesImage("", in)
} else {
out.UnifiedControlPlaneImage = ""
}
// converting internal DNS.Type to v1alpha3 featureGate CoreDNS (this is only for getting roundtrip passing, but it is never used in reality)
if out.FeatureGates == nil {
out.FeatureGates = map[string]bool{}
}
if in.DNS.Type == kubeadm.KubeDNS {
out.FeatureGates[features.CoreDNS] = false
}
return nil
}
func Convert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
if err := autoConvert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(in, out, s); err != nil {
return err
}
out.ReadOnly = !in.Writable
return nil
}
func Convert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
if err := autoConvert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(in, out, s); err != nil {
return err
}
out.Writable = !in.ReadOnly
return nil
}
func convertSlice_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(in *[]HostPathMount, out *[]kubeadm.HostPathMount, s conversion.Scope) error {
if *in != nil {
*out = make([]kubeadm.HostPathMount, len(*in))
for i := range *in {
if err := Convert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
*out = nil
}
return nil
}
func convertSlice_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(in *[]kubeadm.HostPathMount, out *[]HostPathMount, s conversion.Scope) error {
if *in != nil {
*out = make([]HostPathMount, len(*in))
for i := range *in {
if err := Convert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
*out = nil
}
return nil
}
func Convert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error {
if err := autoConvert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(in, out, s); err != nil {
return err
}
var err error
out.ImageMeta, err = etcdImageToImageMeta(in.Image)
return err
}
func etcdImageToImageMeta(image string) (kubeadm.ImageMeta, error) {
// empty image -> empty image meta
if image == "" {
return kubeadm.ImageMeta{}, nil
}
matches := imageRegEx.FindStringSubmatch(image)
if len(matches) != 4 {
return kubeadm.ImageMeta{}, errors.New("Conversion Error: kubeadm does not support converting v1alpha3 configurations with etcd image without explicit repository or tag definition. Please fix the image name")
}
imageRepository := strings.TrimSuffix(matches[1], "/")
imageName := matches[2]
imageTag := strings.TrimPrefix(matches[3], ":")
if imageName != constants.Etcd {
return kubeadm.ImageMeta{}, errors.New("Conversion Error: kubeadm does not support converting v1alpha3 configurations with etcd imageName different than etcd. Please fix the image name")
}
return kubeadm.ImageMeta{
ImageRepository: imageRepository,
ImageTag: imageTag,
}, nil
}
func Convert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error {
if err := autoConvert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(in, out, s); err != nil {
return err
}
// converting internal LocalEtcd.ImageMeta to v1alpha3 LocalEtcd.Image (this is only for getting roundtrip passing, but it is
// never used in reality)
return nil
}

View File

@ -0,0 +1,214 @@
/*
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 (
"testing"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
)
func TestJoinConfigurationConversion(t *testing.T) {
testcases := map[string]struct {
old *JoinConfiguration
expectedError bool
}{
"conversion succeeds": {
old: &JoinConfiguration{},
expectedError: false,
},
"cluster name fails to be converted": {
old: &JoinConfiguration{
ClusterName: "kubernetes",
},
expectedError: true,
},
"feature gates fails to be converted": {
old: &JoinConfiguration{
FeatureGates: map[string]bool{
"someGate": true,
},
},
expectedError: true,
},
}
for _, tc := range testcases {
internal := &kubeadm.JoinConfiguration{}
err := Convert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(tc.old, internal, nil)
if (err != nil) != tc.expectedError {
t.Errorf("ImageToImageMeta returned unexpected error: %v, saw: %v", tc.expectedError, (err != nil))
return
}
}
}
func TestInitConfigurationConversion(t *testing.T) {
testcases := map[string]struct {
old *InitConfiguration
expectedErr bool
}{
"conversion succeeds": {
old: &InitConfiguration{},
expectedErr: false,
},
"feature gates fails to be converted": {
old: &InitConfiguration{
ClusterConfiguration: ClusterConfiguration{
AuditPolicyConfiguration: AuditPolicyConfiguration{
Path: "test",
},
},
},
expectedErr: true,
},
}
for _, tc := range testcases {
internal := &kubeadm.InitConfiguration{}
err := Convert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(tc.old, internal, nil)
if (err != nil) != tc.expectedErr {
t.Errorf("no error was expected but '%s' was found", err)
}
}
}
func TestConvertToUseHyperKubeImage(t *testing.T) {
tests := []struct {
desc string
in *ClusterConfiguration
useHyperKubeImage bool
expectedErr bool
}{
{
desc: "unset UnifiedControlPlaneImage sets UseHyperKubeImage to false",
in: &ClusterConfiguration{},
useHyperKubeImage: false,
expectedErr: false,
},
{
desc: "matching UnifiedControlPlaneImage sets UseHyperKubeImage to true",
in: &ClusterConfiguration{
ImageRepository: "k8s.gcr.io",
KubernetesVersion: "v1.12.2",
UnifiedControlPlaneImage: "k8s.gcr.io/hyperkube:v1.12.2",
},
useHyperKubeImage: true,
expectedErr: false,
},
{
desc: "mismatching UnifiedControlPlaneImage tag causes an error",
in: &ClusterConfiguration{
ImageRepository: "k8s.gcr.io",
KubernetesVersion: "v1.12.0",
UnifiedControlPlaneImage: "k8s.gcr.io/hyperkube:v1.12.2",
},
expectedErr: true,
},
{
desc: "mismatching UnifiedControlPlaneImage repo causes an error",
in: &ClusterConfiguration{
ImageRepository: "my.repo",
KubernetesVersion: "v1.12.2",
UnifiedControlPlaneImage: "k8s.gcr.io/hyperkube:v1.12.2",
},
expectedErr: true,
},
{
desc: "mismatching UnifiedControlPlaneImage image name causes an error",
in: &ClusterConfiguration{
ImageRepository: "k8s.gcr.io",
KubernetesVersion: "v1.12.2",
UnifiedControlPlaneImage: "k8s.gcr.io/otherimage:v1.12.2",
},
expectedErr: true,
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
out := &kubeadm.ClusterConfiguration{}
err := Convert_v1alpha3_UnifiedControlPlaneImage_To_kubeadm_UseHyperKubeImage(test.in, out)
if test.expectedErr {
if err == nil {
t.Fatalf("unexpected success, UseHyperKubeImage: %t", out.UseHyperKubeImage)
}
} else {
if err != nil {
t.Fatalf("unexpected failure: %v", err)
}
if out.UseHyperKubeImage != test.useHyperKubeImage {
t.Fatalf("mismatching result from conversion:\n\tExpected: %t\n\tReceived: %t", test.useHyperKubeImage, out.UseHyperKubeImage)
}
}
})
}
}
func TestEtcdImageToImageMeta(t *testing.T) {
tests := []struct {
name string
image string
expectedImageMeta kubeadm.ImageMeta
expectedError bool
}{
{
name: "Empty image -> Empty image meta",
image: "",
expectedImageMeta: kubeadm.ImageMeta{
ImageRepository: "",
ImageTag: "",
},
},
{
name: "image with tag and repository",
image: "custom.repo/etcd:custom.tag",
expectedImageMeta: kubeadm.ImageMeta{
ImageRepository: "custom.repo",
ImageTag: "custom.tag",
},
},
{
name: "image with custom imageName",
image: "real.repo/custom-image-name-for-etcd:real.tag",
expectedError: true,
},
{
name: "image without repository",
image: "etcd:real.tag",
expectedError: true,
},
{
name: "image without tag",
image: "real.repo/etcd",
expectedError: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ret, err := etcdImageToImageMeta(test.image)
if (err != nil) != test.expectedError {
t.Errorf("etcdImageToImageMeta returned unexpected error: %v, saw: %v", test.expectedError, (err != nil))
return
}
if ret != test.expectedImageMeta {
t.Errorf("etcdImageToImageMeta returned unexpected ImageMeta: %v, saw: %v", test.expectedImageMeta, ret)
}
})
}
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha2
package v1alpha3
import (
"net/url"
@ -23,11 +23,6 @@ import (
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 (
@ -38,7 +33,7 @@ const (
// DefaultClusterDNSIP defines default DNS IP
DefaultClusterDNSIP = "10.96.0.10"
// DefaultKubernetesVersion defines default kubernetes version
DefaultKubernetesVersion = "stable-1.11"
DefaultKubernetesVersion = "stable-1"
// DefaultAPIBindPort defines default API port
DefaultAPIBindPort = 6443
// DefaultCertificatesDir defines default certificate directory
@ -47,8 +42,6 @@ const (
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"
@ -58,10 +51,7 @@ const (
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 specifies the default discovery timeout for kubeadm (used unless one is specified in the JoinConfiguration)
DefaultDiscoveryTimeout = 5 * time.Minute
)
@ -75,16 +65,20 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error {
return RegisterDefaults(scheme)
}
// SetDefaults_MasterConfiguration assigns default values to Master node
func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
// SetDefaults_InitConfiguration assigns default values for the InitConfiguration
func SetDefaults_InitConfiguration(obj *InitConfiguration) {
SetDefaults_ClusterConfiguration(&obj.ClusterConfiguration)
SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration)
SetDefaults_BootstrapTokens(obj)
SetDefaults_APIEndpoint(&obj.APIEndpoint)
}
// SetDefaults_ClusterConfiguration assigns default values for the ClusterConfiguration
func SetDefaults_ClusterConfiguration(obj *ClusterConfiguration) {
if obj.KubernetesVersion == "" {
obj.KubernetesVersion = DefaultKubernetesVersion
}
if obj.API.BindPort == 0 {
obj.API.BindPort = DefaultAPIBindPort
}
if obj.Networking.ServiceSubnet == "" {
obj.Networking.ServiceSubnet = DefaultServicesSubnet
}
@ -105,16 +99,12 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
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) {
func SetDefaults_Etcd(obj *ClusterConfiguration) {
if obj.Etcd.External == nil && obj.Etcd.Local == nil {
obj.Etcd.Local = &LocalEtcd{}
}
@ -125,24 +115,8 @@ func SetDefaults_Etcd(obj *MasterConfiguration) {
}
}
// 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) {
// SetDefaults_JoinConfiguration assigns default values to a regular node
func SetDefaults_JoinConfiguration(obj *JoinConfiguration) {
if obj.CACertPath == "" {
obj.CACertPath = DefaultCACertPath
}
@ -164,60 +138,9 @@ func SetDefaults_NodeConfiguration(obj *NodeConfiguration) {
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)
}
SetDefaults_APIEndpoint(&obj.APIEndpoint)
}
func SetDefaults_NodeRegistrationOptions(obj *NodeRegistrationOptions) {
@ -227,7 +150,7 @@ func SetDefaults_NodeRegistrationOptions(obj *NodeRegistrationOptions) {
}
// SetDefaults_AuditPolicyConfiguration sets default values for the AuditPolicyConfiguration
func SetDefaults_AuditPolicyConfiguration(obj *MasterConfiguration) {
func SetDefaults_AuditPolicyConfiguration(obj *ClusterConfiguration) {
if obj.AuditPolicyConfiguration.LogDir == "" {
obj.AuditPolicyConfiguration.LogDir = constants.StaticPodAuditPolicyLogDir
}
@ -241,14 +164,14 @@ func SetDefaults_AuditPolicyConfiguration(obj *MasterConfiguration) {
// 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) {
func SetDefaults_BootstrapTokens(obj *InitConfiguration) {
if obj.BootstrapTokens == nil || len(obj.BootstrapTokens) == 0 {
obj.BootstrapTokens = []BootstrapToken{{}}
}
for _, bt := range obj.BootstrapTokens {
SetDefaults_BootstrapToken(&bt)
for i := range obj.BootstrapTokens {
SetDefaults_BootstrapToken(&obj.BootstrapTokens[i])
}
}
@ -267,3 +190,10 @@ func SetDefaults_BootstrapToken(bt *BootstrapToken) {
bt.Groups = constants.DefaultTokenGroups
}
}
// SetDefaults_APIEndpoint sets the defaults for the API server instance deployed on a node.
func SetDefaults_APIEndpoint(obj *APIEndpoint) {
if obj.BindPort == 0 {
obj.BindPort = DefaultAPIBindPort
}
}

View File

@ -0,0 +1,28 @@
// +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
const (
// DefaultCACertPath defines default location of CA certificate on Linux
DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
// DefaultUrlScheme defines default socket url prefix
DefaultUrlScheme = "unix"
// DefaultCRISocket defines the default cri socket
DefaultCRISocket = "/var/run/dockershim.sock"
)

View File

@ -1,7 +1,7 @@
// +build windows
/*
Copyright 2017 The Kubernetes Authors.
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.
@ -16,7 +16,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
package v1alpha3
// DefaultCACertPath defines default location of CA certificate on Windows
const DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt"
const (
// DefaultCACertPath defines default location of CA certificate on Windows
DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt"
// DefaultUrlScheme defines default socket url prefix
DefaultUrlScheme = "tcp"
// DefaultCRISocket defines the default cri socket
DefaultCRISocket = "tcp://localhost:2375"
)

View File

@ -0,0 +1,273 @@
/*
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.
*/
// +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 defines the v1alpha3 version of the kubeadm config file format, that is a big step
// forward the objective of graduate kubeadm config to beta.
//
// One of the biggest changes introduced by this release is the re-design of how component config
// can be provided to kubeadm; this will enable a improved stability of the kubeadm config while the efforts for
// the implementation of component config across Kubernetes ecosystem continues.
//
// Another important change is the separation between cluster wide setting and runtime or node specific
// settings, that is functional to the objective to introduce support for HA clusters in kubeadm.
//
// Migration from old kubeadm config versions
//
// Please convert your v1alpha2 configuration files to v1alpha3 using the kubeadm config migrate command of kubeadm v1.12.x
// (conversion from older releases of kubeadm config files requires older release of kubeadm as well e.g.
// kubeadm v1.11 should be used to migrate v1alpha1 to v1alpha2).
//
// Nevertheless, kubeadm v1.12.x will support reading from v1alpha2 version of the kubeadm config file format, but this support
// will be dropped in the v1.13 release.
//
// Basics
//
// The preferred way to configure kubeadm is to pass an YAML configuration file with the --config option. Some of the
// configuration options defined in the kubeadm config file are also available as command line flags, but only
// the most common/simple use case are supported with this approach.
//
// A kubeadm config file could contain multiple configuration types separated using three dashes (“---”).
//
// The kubeadm config print-defaults command print the default values for all the kubeadm supported configuration types.
//
// apiVersion: kubeadm.k8s.io/v1alpha3
// kind: InitConfiguration
// ...
// ---
// apiVersion: kubeadm.k8s.io/v1alpha3
// kind: ClusterConfiguration
// ...
// ---
// apiVersion: kubelet.config.k8s.io/v1beta1
// kind: KubeletConfiguration
// ...
// ---
// apiVersion: kubeproxy.config.k8s.io/v1alpha1
// kind: KubeProxyConfiguration
// ...
// ---
// apiVersion: kubeadm.k8s.io/v1alpha3
// kind: JoinConfiguration
// ...
//
// The list of configuration types that must be included in a configuration file depends by the action you are
// performing (init or join) and by the configuration options you are going to use (defaults or advanced customization).
//
// If some configuration types are not provided, or provided only partially, kubeadm will use default values; defaults
// provided by kubeadm includes also enforcing consistency of values across components when required (e.g.
// cluster-cidr flag on controller manager and clusterCIDR on kube-proxy).
//
// Users are always allowed to override default values, with the only exception of a small subset of setting with
// relevance for security (e.g. enforce authorization-mode Node and RBAC on api server)
//
// Starting from v1.12.1, if the user provides a configuration types that is not expected for the action you are performing,
// kubeadm will ignore those types and print a warning.
//
// Kubeadm init configuration types
//
// When executing kubeadm init with the --config option, the following configuration types could be used:
// InitConfiguration, ClusterConfiguration, KubeProxyConfiguration, KubeletConfiguration, but only one
// between InitConfiguration and ClusterConfiguration is mandatory.
//
// apiVersion: kubeadm.k8s.io/v1alpha3
// kind: InitConfiguration
// bootstrapTokens:
// ...
// nodeRegistration:
// ...
// apiEndpoint:
// ...
//
// InitConfiguration (and as well ClusterConfiguration afterwards) are originated from the MasterConfiguration type
// in the v1alpha2 kubeadm config version.
//
// - The InitConfiguration type should be used to configure runtime settings, that in case of kubeadm init
// are the configuration of the bootstrap token and all the setting which are specific to the node where kubeadm
// is executed, including:
//
// - NodeRegistration, that holds fields that relate to registering the new node to the cluster;
// use it to customize the node name, the CRI socket to use or any other settings that should apply to this
// node only (e.g. the node ip).
//
// - APIEndpoint, that represents the endpoint of the instance of the API server to be deployed on this node;
// use it e.g. to customize the API server advertise address.
//
// apiVersion: kubeadm.k8s.io/v1alpha3
// kind: ClusterConfiguration
// networking:
// ...
// etcd:
// ...
// apiServerExtraArgs:
// ...
// APIServerExtraVolumes:
// ...
// ...
//
// The ClusterConfiguration type should be used to configure cluster-wide settings,
// including settings for:
//
// - Networking, that holds configuration for the networking topology of the cluster; use it e.g. to customize
// node subnet or services subnet.
//
// - Etcd configurations; use it e.g. to customize the local etcd or to configure the API server
// for using an external etcd cluster.
//
// - kube-apiserver, kube-scheduler, kube-controller-manager configurations; use it to customize control-plane
// components by adding customized setting or overriding kubeadm default settings.
//
// apiVersion: kubeproxy.config.k8s.io/v1alpha1
// kind: KubeProxyConfiguration
// ...
//
// The KubeProxyConfiguration type should be used to change the configuration passed to kube-proxy instances deployed
// in the cluster. If this object is not provided or provided only partially, kubeadm applies defaults.
//
// See https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/ or https://godoc.org/k8s.io/kube-proxy/config/v1alpha1#KubeProxyConfiguration
// for kube proxy official documentation.
//
// apiVersion: kubelet.config.k8s.io/v1beta1
// kind: KubeletConfiguration
// ...
//
// The KubeletConfiguration type should be used to change the configurations that will be passed to all kubelet instances
// deployed in the cluster. If this object is not provided or provided only partially, kubeadm applies defaults.
//
// See https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/ or https://godoc.org/k8s.io/kubelet/config/v1beta1#KubeletConfiguration
// for kube proxy official documentation.
//
// Here is a fully populated example of a single YAML file containing multiple
// configuration types to be used during a `kubeadm init` run.
//
// apiVersion: kubeadm.k8s.io/v1alpha3
// kind: InitConfiguration
// bootstrapTokens:
// - token: "9a08jv.c0izixklcxtmnze7"
// description: "kubeadm bootstrap token"
// ttl: "24h"
// - token: "783bde.3f89s0fje9f38fhf"
// description: "another bootstrap token"
// usages:
// - signing
// groups:
// - system:anonymous
// nodeRegistration:
// name: "ec2-10-100-0-1"
// criSocket: "/var/run/dockershim.sock"
// taints:
// - key: "kubeadmNode"
// value: "master"
// effect: "NoSchedule"
// kubeletExtraArgs:
// cgroupDriver: "cgroupfs"
// apiEndpoint:
// advertiseAddress: "10.100.0.1"
// bindPort: 6443
// ---
// apiVersion: kubeadm.k8s.io/v1alpha3
// kind: ClusterConfiguration
// etcd:
// # one of local or external
// local:
// image: "k8s.gcr.io/etcd-amd64:3.2.18"
// dataDir: "/var/lib/etcd"
// extraArgs:
// listen-client-urls: "http://10.100.0.1:2379"
// serverCertSANs:
// - "ec2-10-100-0-1.compute-1.amazonaws.com"
// peerCertSANs:
// - "10.100.0.1"
// external:
// endpoints:
// - "10.100.0.1:2379"
// - "10.100.0.2:2379"
// caFile: "/etcd/kubernetes/pki/etcd/etcd-ca.crt"
// certFile: "/etcd/kubernetes/pki/etcd/etcd.crt"
// certKey: "/etcd/kubernetes/pki/etcd/etcd.key"
// networking:
// serviceSubnet: "10.96.0.0/12"
// podSubnet: "10.100.0.1/24"
// dnsDomain: "cluster.local"
// kubernetesVersion: "v1.12.0"
// controlPlaneEndpoint: "10.100.0.1:6443"
// apiServerExtraArgs:
// authorization-mode: "Node,RBAC"
// controllerManagerExtraArgs:
// node-cidr-mask-size: 20
// schedulerExtraArgs:
// address: "10.100.0.1"
// apiServerExtraVolumes:
// - name: "some-volume"
// hostPath: "/etc/some-path"
// mountPath: "/etc/some-pod-path"
// writable: true
// pathType: File
// controllerManagerExtraVolumes:
// - name: "some-volume"
// hostPath: "/etc/some-path"
// mountPath: "/etc/some-pod-path"
// writable: true
// pathType: File
// schedulerExtraVolumes:
// - name: "some-volume"
// hostPath: "/etc/some-path"
// mountPath: "/etc/some-pod-path"
// writable: true
// pathType: File
// apiServerCertSANs:
// - "10.100.1.1"
// - "ec2-10-100-0-1.compute-1.amazonaws.com"
// certificatesDir: "/etc/kubernetes/pki"
// imageRepository: "k8s.gcr.io"
// unifiedControlPlaneImage: "k8s.gcr.io/controlplane:v1.12.0"
// auditPolicy:
// # https://kubernetes.io/docs/tasks/debug-application-cluster/audit/#audit-policy
// path: "/var/log/audit/audit.json"
// logDir: "/var/log/audit"
// logMaxAge: 7 # in days
// featureGates:
// selfhosting: false
// clusterName: "example-cluster"
//
// Kubeadm join configuration types
//
// When executing kubeadm join with the --config option, the JoinConfiguration type should be provided.
//
// apiVersion: kubeadm.k8s.io/v1alpha3
// kind: JoinConfiguration
// ...
//
// JoinConfiguration is originated from NodeConfiguration type in the v1alpha2 kubeadm config version.
//
// The JoinConfiguration type should be used to configure runtime settings, that in case of kubeadm join
// are the discovery method used for accessing the cluster info and all the setting which are specific
// to the node where kubeadm is executed, including:
//
// - NodeRegistration, that holds fields that relate to registering the new node to the cluster;
// use it to customize the node name, the CRI socket to use or any other settings that should apply to this
// node only (e.g. the node ip).
//
// - APIEndpoint, that represents the endpoint of the instance of the API server to be eventually deployed on this node.
//
package v1alpha3 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
//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.

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors.
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.
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
package v1alpha3
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -26,7 +26,7 @@ import (
const GroupName = "kubeadm.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha3"}
var (
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
@ -43,7 +43,7 @@ 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, addConversionFuncs)
localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
}
// Kind takes an unqualified kind and returns a Group qualified GroupKind
@ -58,8 +58,10 @@ func Resource(resource string) schema.GroupResource {
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&MasterConfiguration{},
&NodeConfiguration{},
&InitConfiguration{},
&ClusterConfiguration{},
&ClusterStatus{},
&JoinConfiguration{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil

View File

@ -14,22 +14,26 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha2
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 {
// InitConfiguration contains a list of elements that is specific "kubeadm init"-only runtime
// information.
type InitConfiguration struct {
metav1.TypeMeta `json:",inline"`
// ClusterConfiguration holds the cluster-wide information, and embeds that struct (which can be (un)marshalled separately as well)
// When InitConfiguration is marshalled to bytes in the external version, this information IS NOT preserved (which can be seen from
// the `json:"-"` tag. This is due to that when InitConfiguration is (un)marshalled, it turns into two YAML documents, one for the
// InitConfiguration and ClusterConfiguration. Hence, the information must not be duplicated, and is therefore omitted here.
ClusterConfiguration `json:"-"`
// `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.
@ -41,24 +45,38 @@ type MasterConfiguration struct {
// 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.
// APIEndpoint represents the endpoint of the instance of the API server to be deployed on this node.
APIEndpoint APIEndpoint `json:"apiEndpoint,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterConfiguration contains cluster-wide configuration for a kubeadm cluster
type ClusterConfiguration struct {
metav1.TypeMeta `json:",inline"`
// 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"`
// 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 a 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"`
// APIServerExtraArgs is a set of extra flags to pass to the API Server or override
// default ones in form of <flagname>=<value>.
// TODO: This is temporary and ideally we would like to switch all components to
@ -104,22 +122,23 @@ type MasterConfiguration struct {
ClusterName string `json:"clusterName,omitempty"`
}
// API struct contains elements of API server address.
type API struct {
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterStatus contains the cluster status. The ClusterStatus will be stored in the kubeadm-config
// ConfigMap in the cluster, and then updated by kubeadm when additional control plane instance joins or leaves the cluster.
type ClusterStatus struct {
metav1.TypeMeta `json:",inline"`
// APIEndpoints currently available in the cluster, one for each control plane/api server instance.
// The key of the map is the IP of the host's default interface
APIEndpoints map[string]APIEndpoint `json:"apiEndpoints"`
}
// APIEndpoint struct contains elements of API server instance deployed on a node.
type APIEndpoint struct {
// AdvertiseAddress sets the IP address for the API server to advertise.
AdvertiseAddress string `json:"advertiseAddress"`
// 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"`
@ -143,7 +162,7 @@ type NodeRegistrationOptions struct {
// 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.
// Flags have higher priority when parsing. These values are local and specific to the node kubeadm is executing on.
KubeletExtraArgs map[string]string `json:"kubeletExtraArgs,omitempty"`
}
@ -215,9 +234,7 @@ type LocalEtcd struct {
// 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 of etcd members. Required for ExternalEtcd.
Endpoints []string `json:"endpoints"`
// CAFile is an SSL Certificate Authority file used to secure etcd communication.
CAFile string `json:"caFile"`
@ -229,9 +246,9 @@ type ExternalEtcd struct {
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// NodeConfiguration contains elements describing a particular node.
// JoinConfiguration contains elements describing a particular node.
// TODO: This struct should be replaced by dynamic kubelet configuration.
type NodeConfiguration struct {
type JoinConfiguration struct {
metav1.TypeMeta `json:",inline"`
// NodeRegistration holds fields that relate to registering the new master node to the cluster
@ -277,15 +294,17 @@ type NodeConfiguration struct {
// the security of kubeadm since other nodes can impersonate the master.
DiscoveryTokenUnsafeSkipCAVerification bool `json:"discoveryTokenUnsafeSkipCAVerification"`
// ControlPlane flag specifies that the joining node should host an additional
// control plane instance.
ControlPlane bool `json:"controlPlane,omitempty"`
// APIEndpoint represents the endpoint of the instance of the API server eventually to be deployed on this node.
APIEndpoint APIEndpoint `json:"apiEndpoint,omitempty"`
// 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 {
@ -302,11 +321,6 @@ type HostPathMount struct {
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.

View File

@ -0,0 +1,567 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by conversion-gen. DO NOT EDIT.
package v1alpha3
import (
unsafe "unsafe"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*APIEndpoint)(nil), (*kubeadm.APIEndpoint)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(a.(*APIEndpoint), b.(*kubeadm.APIEndpoint), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.APIEndpoint)(nil), (*APIEndpoint)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(a.(*kubeadm.APIEndpoint), b.(*APIEndpoint), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*BootstrapToken)(nil), (*kubeadm.BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_BootstrapToken_To_kubeadm_BootstrapToken(a.(*BootstrapToken), b.(*kubeadm.BootstrapToken), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapToken)(nil), (*BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_BootstrapToken_To_v1alpha3_BootstrapToken(a.(*kubeadm.BootstrapToken), b.(*BootstrapToken), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*BootstrapTokenString)(nil), (*kubeadm.BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(a.(*BootstrapTokenString), b.(*kubeadm.BootstrapTokenString), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapTokenString)(nil), (*BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_BootstrapTokenString_To_v1alpha3_BootstrapTokenString(a.(*kubeadm.BootstrapTokenString), b.(*BootstrapTokenString), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ClusterConfiguration)(nil), (*kubeadm.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(a.(*ClusterConfiguration), b.(*kubeadm.ClusterConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ClusterStatus)(nil), (*kubeadm.ClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_ClusterStatus_To_kubeadm_ClusterStatus(a.(*ClusterStatus), b.(*kubeadm.ClusterStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterStatus)(nil), (*ClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_ClusterStatus_To_v1alpha3_ClusterStatus(a.(*kubeadm.ClusterStatus), b.(*ClusterStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Etcd)(nil), (*kubeadm.Etcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_Etcd_To_kubeadm_Etcd(a.(*Etcd), b.(*kubeadm.Etcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.Etcd)(nil), (*Etcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_Etcd_To_v1alpha3_Etcd(a.(*kubeadm.Etcd), b.(*Etcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ExternalEtcd)(nil), (*kubeadm.ExternalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_ExternalEtcd_To_kubeadm_ExternalEtcd(a.(*ExternalEtcd), b.(*kubeadm.ExternalEtcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.ExternalEtcd)(nil), (*ExternalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_ExternalEtcd_To_v1alpha3_ExternalEtcd(a.(*kubeadm.ExternalEtcd), b.(*ExternalEtcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*HostPathMount)(nil), (*kubeadm.HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(a.(*HostPathMount), b.(*kubeadm.HostPathMount), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.HostPathMount)(nil), (*HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(a.(*kubeadm.HostPathMount), b.(*HostPathMount), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*InitConfiguration)(nil), (*kubeadm.InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(a.(*InitConfiguration), b.(*kubeadm.InitConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.InitConfiguration)(nil), (*InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_InitConfiguration_To_v1alpha3_InitConfiguration(a.(*kubeadm.InitConfiguration), b.(*InitConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*JoinConfiguration)(nil), (*kubeadm.JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(a.(*JoinConfiguration), b.(*kubeadm.JoinConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.JoinConfiguration)(nil), (*JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_JoinConfiguration_To_v1alpha3_JoinConfiguration(a.(*kubeadm.JoinConfiguration), b.(*JoinConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*LocalEtcd)(nil), (*kubeadm.LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(a.(*LocalEtcd), b.(*kubeadm.LocalEtcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.LocalEtcd)(nil), (*LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(a.(*kubeadm.LocalEtcd), b.(*LocalEtcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Networking)(nil), (*kubeadm.Networking)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_Networking_To_kubeadm_Networking(a.(*Networking), b.(*kubeadm.Networking), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.Networking)(nil), (*Networking)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_Networking_To_v1alpha3_Networking(a.(*kubeadm.Networking), b.(*Networking), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*NodeRegistrationOptions)(nil), (*kubeadm.NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(a.(*NodeRegistrationOptions), b.(*kubeadm.NodeRegistrationOptions), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(a.(*kubeadm.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*kubeadm.HostPathMount)(nil), (*HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(a.(*kubeadm.HostPathMount), b.(*HostPathMount), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*kubeadm.InitConfiguration)(nil), (*InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_InitConfiguration_To_v1alpha3_InitConfiguration(a.(*kubeadm.InitConfiguration), b.(*InitConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*kubeadm.JoinConfiguration)(nil), (*JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_JoinConfiguration_To_v1alpha3_JoinConfiguration(a.(*kubeadm.JoinConfiguration), b.(*JoinConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*kubeadm.LocalEtcd)(nil), (*LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(a.(*kubeadm.LocalEtcd), b.(*LocalEtcd), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*ClusterConfiguration)(nil), (*kubeadm.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(a.(*ClusterConfiguration), b.(*kubeadm.ClusterConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*HostPathMount)(nil), (*kubeadm.HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(a.(*HostPathMount), b.(*kubeadm.HostPathMount), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*InitConfiguration)(nil), (*kubeadm.InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(a.(*InitConfiguration), b.(*kubeadm.InitConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*JoinConfiguration)(nil), (*kubeadm.JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(a.(*JoinConfiguration), b.(*kubeadm.JoinConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*LocalEtcd)(nil), (*kubeadm.LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(a.(*LocalEtcd), b.(*kubeadm.LocalEtcd), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(in *APIEndpoint, out *kubeadm.APIEndpoint, s conversion.Scope) error {
out.AdvertiseAddress = in.AdvertiseAddress
out.BindPort = in.BindPort
return nil
}
// Convert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint is an autogenerated conversion function.
func Convert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(in *APIEndpoint, out *kubeadm.APIEndpoint, s conversion.Scope) error {
return autoConvert_v1alpha3_APIEndpoint_To_kubeadm_APIEndpoint(in, out, s)
}
func autoConvert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(in *kubeadm.APIEndpoint, out *APIEndpoint, s conversion.Scope) error {
out.AdvertiseAddress = in.AdvertiseAddress
out.BindPort = in.BindPort
return nil
}
// Convert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint is an autogenerated conversion function.
func Convert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(in *kubeadm.APIEndpoint, out *APIEndpoint, s conversion.Scope) error {
return autoConvert_kubeadm_APIEndpoint_To_v1alpha3_APIEndpoint(in, out, s)
}
func autoConvert_v1alpha3_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
out.Token = (*kubeadm.BootstrapTokenString)(unsafe.Pointer(in.Token))
out.Description = in.Description
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
return nil
}
// Convert_v1alpha3_BootstrapToken_To_kubeadm_BootstrapToken is an autogenerated conversion function.
func Convert_v1alpha3_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
return autoConvert_v1alpha3_BootstrapToken_To_kubeadm_BootstrapToken(in, out, s)
}
func autoConvert_kubeadm_BootstrapToken_To_v1alpha3_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
out.Token = (*BootstrapTokenString)(unsafe.Pointer(in.Token))
out.Description = in.Description
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
return nil
}
// Convert_kubeadm_BootstrapToken_To_v1alpha3_BootstrapToken is an autogenerated conversion function.
func Convert_kubeadm_BootstrapToken_To_v1alpha3_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
return autoConvert_kubeadm_BootstrapToken_To_v1alpha3_BootstrapToken(in, out, s)
}
func autoConvert_v1alpha3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
out.ID = in.ID
out.Secret = in.Secret
return nil
}
// Convert_v1alpha3_BootstrapTokenString_To_kubeadm_BootstrapTokenString is an autogenerated conversion function.
func Convert_v1alpha3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
return autoConvert_v1alpha3_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in, out, s)
}
func autoConvert_kubeadm_BootstrapTokenString_To_v1alpha3_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
out.ID = in.ID
out.Secret = in.Secret
return nil
}
// Convert_kubeadm_BootstrapTokenString_To_v1alpha3_BootstrapTokenString is an autogenerated conversion function.
func Convert_kubeadm_BootstrapTokenString_To_v1alpha3_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
return autoConvert_kubeadm_BootstrapTokenString_To_v1alpha3_BootstrapTokenString(in, out, s)
}
func autoConvert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
if err := Convert_v1alpha3_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
return err
}
if err := Convert_v1alpha3_Networking_To_kubeadm_Networking(&in.Networking, &out.Networking, s); err != nil {
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
// WARNING: in.APIServerExtraArgs requires manual conversion: does not exist in peer-type
// WARNING: in.ControllerManagerExtraArgs requires manual conversion: does not exist in peer-type
// WARNING: in.SchedulerExtraArgs requires manual conversion: does not exist in peer-type
// WARNING: in.APIServerExtraVolumes requires manual conversion: does not exist in peer-type
// WARNING: in.ControllerManagerExtraVolumes requires manual conversion: does not exist in peer-type
// WARNING: in.SchedulerExtraVolumes requires manual conversion: does not exist in peer-type
// WARNING: in.APIServerCertSANs requires manual conversion: does not exist in peer-type
out.CertificatesDir = in.CertificatesDir
out.ImageRepository = in.ImageRepository
// WARNING: in.UnifiedControlPlaneImage requires manual conversion: does not exist in peer-type
// WARNING: in.AuditPolicyConfiguration requires manual conversion: does not exist in peer-type
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.ClusterName = in.ClusterName
return nil
}
func autoConvert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error {
// INFO: in.ComponentConfigs opted out of conversion generation
if err := Convert_kubeadm_Etcd_To_v1alpha3_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
return err
}
if err := Convert_kubeadm_Networking_To_v1alpha3_Networking(&in.Networking, &out.Networking, s); err != nil {
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
// WARNING: in.APIServer requires manual conversion: does not exist in peer-type
// WARNING: in.ControllerManager requires manual conversion: does not exist in peer-type
// WARNING: in.Scheduler requires manual conversion: does not exist in peer-type
// WARNING: in.DNS requires manual conversion: does not exist in peer-type
out.CertificatesDir = in.CertificatesDir
out.ImageRepository = in.ImageRepository
// INFO: in.CIImageRepository opted out of conversion generation
// WARNING: in.UseHyperKubeImage requires manual conversion: does not exist in peer-type
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.ClusterName = in.ClusterName
return nil
}
func autoConvert_v1alpha3_ClusterStatus_To_kubeadm_ClusterStatus(in *ClusterStatus, out *kubeadm.ClusterStatus, s conversion.Scope) error {
out.APIEndpoints = *(*map[string]kubeadm.APIEndpoint)(unsafe.Pointer(&in.APIEndpoints))
return nil
}
// Convert_v1alpha3_ClusterStatus_To_kubeadm_ClusterStatus is an autogenerated conversion function.
func Convert_v1alpha3_ClusterStatus_To_kubeadm_ClusterStatus(in *ClusterStatus, out *kubeadm.ClusterStatus, s conversion.Scope) error {
return autoConvert_v1alpha3_ClusterStatus_To_kubeadm_ClusterStatus(in, out, s)
}
func autoConvert_kubeadm_ClusterStatus_To_v1alpha3_ClusterStatus(in *kubeadm.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
out.APIEndpoints = *(*map[string]APIEndpoint)(unsafe.Pointer(&in.APIEndpoints))
return nil
}
// Convert_kubeadm_ClusterStatus_To_v1alpha3_ClusterStatus is an autogenerated conversion function.
func Convert_kubeadm_ClusterStatus_To_v1alpha3_ClusterStatus(in *kubeadm.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
return autoConvert_kubeadm_ClusterStatus_To_v1alpha3_ClusterStatus(in, out, s)
}
func autoConvert_v1alpha3_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
if in.Local != nil {
in, out := &in.Local, &out.Local
*out = new(kubeadm.LocalEtcd)
if err := Convert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(*in, *out, s); err != nil {
return err
}
} else {
out.Local = nil
}
out.External = (*kubeadm.ExternalEtcd)(unsafe.Pointer(in.External))
return nil
}
// Convert_v1alpha3_Etcd_To_kubeadm_Etcd is an autogenerated conversion function.
func Convert_v1alpha3_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
return autoConvert_v1alpha3_Etcd_To_kubeadm_Etcd(in, out, s)
}
func autoConvert_kubeadm_Etcd_To_v1alpha3_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
if in.Local != nil {
in, out := &in.Local, &out.Local
*out = new(LocalEtcd)
if err := Convert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(*in, *out, s); err != nil {
return err
}
} else {
out.Local = nil
}
out.External = (*ExternalEtcd)(unsafe.Pointer(in.External))
return nil
}
// Convert_kubeadm_Etcd_To_v1alpha3_Etcd is an autogenerated conversion function.
func Convert_kubeadm_Etcd_To_v1alpha3_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
return autoConvert_kubeadm_Etcd_To_v1alpha3_Etcd(in, out, s)
}
func autoConvert_v1alpha3_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error {
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
out.CAFile = in.CAFile
out.CertFile = in.CertFile
out.KeyFile = in.KeyFile
return nil
}
// Convert_v1alpha3_ExternalEtcd_To_kubeadm_ExternalEtcd is an autogenerated conversion function.
func Convert_v1alpha3_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error {
return autoConvert_v1alpha3_ExternalEtcd_To_kubeadm_ExternalEtcd(in, out, s)
}
func autoConvert_kubeadm_ExternalEtcd_To_v1alpha3_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error {
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
out.CAFile = in.CAFile
out.CertFile = in.CertFile
out.KeyFile = in.KeyFile
return nil
}
// Convert_kubeadm_ExternalEtcd_To_v1alpha3_ExternalEtcd is an autogenerated conversion function.
func Convert_kubeadm_ExternalEtcd_To_v1alpha3_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error {
return autoConvert_kubeadm_ExternalEtcd_To_v1alpha3_ExternalEtcd(in, out, s)
}
func autoConvert_v1alpha3_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
out.Name = in.Name
out.HostPath = in.HostPath
out.MountPath = in.MountPath
// WARNING: in.Writable requires manual conversion: does not exist in peer-type
out.PathType = corev1.HostPathType(in.PathType)
return nil
}
func autoConvert_kubeadm_HostPathMount_To_v1alpha3_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
out.Name = in.Name
out.HostPath = in.HostPath
out.MountPath = in.MountPath
// WARNING: in.ReadOnly requires manual conversion: does not exist in peer-type
out.PathType = corev1.HostPathType(in.PathType)
return nil
}
func autoConvert_v1alpha3_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
if err := Convert_v1alpha3_ClusterConfiguration_To_kubeadm_ClusterConfiguration(&in.ClusterConfiguration, &out.ClusterConfiguration, s); err != nil {
return err
}
out.BootstrapTokens = *(*[]kubeadm.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
if err := Convert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
// WARNING: in.APIEndpoint requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_kubeadm_InitConfiguration_To_v1alpha3_InitConfiguration(in *kubeadm.InitConfiguration, out *InitConfiguration, s conversion.Scope) error {
if err := Convert_kubeadm_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(&in.ClusterConfiguration, &out.ClusterConfiguration, s); err != nil {
return err
}
out.BootstrapTokens = *(*[]BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
// WARNING: in.LocalAPIEndpoint requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_v1alpha3_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConfiguration, out *kubeadm.JoinConfiguration, s conversion.Scope) error {
if err := Convert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
out.CACertPath = in.CACertPath
// WARNING: in.DiscoveryFile requires manual conversion: does not exist in peer-type
// WARNING: in.DiscoveryToken requires manual conversion: does not exist in peer-type
// WARNING: in.DiscoveryTokenAPIServers requires manual conversion: does not exist in peer-type
// WARNING: in.DiscoveryTimeout requires manual conversion: does not exist in peer-type
// WARNING: in.TLSBootstrapToken requires manual conversion: does not exist in peer-type
// WARNING: in.Token requires manual conversion: does not exist in peer-type
// WARNING: in.ClusterName requires manual conversion: does not exist in peer-type
// WARNING: in.DiscoveryTokenCACertHashes requires manual conversion: does not exist in peer-type
// WARNING: in.DiscoveryTokenUnsafeSkipCAVerification requires manual conversion: does not exist in peer-type
// WARNING: in.ControlPlane requires manual conversion: inconvertible types (bool vs *k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm.JoinControlPlane)
// WARNING: in.APIEndpoint requires manual conversion: does not exist in peer-type
// WARNING: in.FeatureGates requires manual conversion: does not exist in peer-type
return nil
}
func autoConvert_kubeadm_JoinConfiguration_To_v1alpha3_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error {
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
out.CACertPath = in.CACertPath
// WARNING: in.Discovery requires manual conversion: does not exist in peer-type
// WARNING: in.ControlPlane requires manual conversion: inconvertible types (*k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm.JoinControlPlane vs bool)
return nil
}
func autoConvert_v1alpha3_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error {
// WARNING: in.Image requires manual conversion: does not exist in peer-type
out.DataDir = in.DataDir
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs))
out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs))
return nil
}
func autoConvert_kubeadm_LocalEtcd_To_v1alpha3_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error {
// WARNING: in.ImageMeta requires manual conversion: does not exist in peer-type
out.DataDir = in.DataDir
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs))
out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs))
return nil
}
func autoConvert_v1alpha3_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
out.ServiceSubnet = in.ServiceSubnet
out.PodSubnet = in.PodSubnet
out.DNSDomain = in.DNSDomain
return nil
}
// Convert_v1alpha3_Networking_To_kubeadm_Networking is an autogenerated conversion function.
func Convert_v1alpha3_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
return autoConvert_v1alpha3_Networking_To_kubeadm_Networking(in, out, s)
}
func autoConvert_kubeadm_Networking_To_v1alpha3_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
out.ServiceSubnet = in.ServiceSubnet
out.PodSubnet = in.PodSubnet
out.DNSDomain = in.DNSDomain
return nil
}
// Convert_kubeadm_Networking_To_v1alpha3_Networking is an autogenerated conversion function.
func Convert_kubeadm_Networking_To_v1alpha3_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
return autoConvert_kubeadm_Networking_To_v1alpha3_Networking(in, out, s)
}
func autoConvert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error {
out.Name = in.Name
out.CRISocket = in.CRISocket
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
return nil
}
// Convert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions is an autogenerated conversion function.
func Convert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error {
return autoConvert_v1alpha3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in, out, s)
}
func autoConvert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
out.Name = in.Name
out.CRISocket = in.CRISocket
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
return nil
}
// Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions is an autogenerated conversion function.
func Convert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
return autoConvert_kubeadm_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(in, out, s)
}

View File

@ -18,28 +18,26 @@ limitations under the License.
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha2
package v1alpha3
import (
core_v1 "k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *API) DeepCopyInto(out *API) {
func (in *APIEndpoint) DeepCopyInto(out *APIEndpoint) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new API.
func (in *API) DeepCopy() *API {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIEndpoint.
func (in *APIEndpoint) DeepCopy() *APIEndpoint {
if in == nil {
return nil
}
out := new(API)
out := new(APIEndpoint)
in.DeepCopyInto(out)
return out
}
@ -49,12 +47,8 @@ func (in *AuditPolicyConfiguration) DeepCopyInto(out *AuditPolicyConfiguration)
*out = *in
if in.LogMaxAge != nil {
in, out := &in.LogMaxAge, &out.LogMaxAge
if *in == nil {
*out = nil
} else {
*out = new(int32)
**out = **in
}
*out = new(int32)
**out = **in
}
return
}
@ -74,29 +68,17 @@ func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
*out = *in
if in.Token != nil {
in, out := &in.Token, &out.Token
if *in == nil {
*out = nil
} else {
*out = new(BootstrapTokenString)
**out = **in
}
*out = new(BootstrapTokenString)
**out = **in
}
if in.TTL != nil {
in, out := &in.TTL, &out.TTL
if *in == nil {
*out = nil
} else {
*out = new(v1.Duration)
**out = **in
}
*out = new(v1.Duration)
**out = **in
}
if in.Expires != nil {
in, out := &in.Expires, &out.Expires
if *in == nil {
*out = nil
} else {
*out = (*in).DeepCopy()
}
*out = (*in).DeepCopy()
}
if in.Usages != nil {
in, out := &in.Usages, &out.Usages
@ -138,175 +120,10 @@ func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Etcd) DeepCopyInto(out *Etcd) {
*out = *in
if in.Local != nil {
in, out := &in.Local, &out.Local
if *in == nil {
*out = nil
} else {
*out = new(LocalEtcd)
(*in).DeepCopyInto(*out)
}
}
if in.External != nil {
in, out := &in.External, &out.External
if *in == nil {
*out = nil
} else {
*out = new(ExternalEtcd)
(*in).DeepCopyInto(*out)
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Etcd.
func (in *Etcd) DeepCopy() *Etcd {
if in == nil {
return nil
}
out := new(Etcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalEtcd) DeepCopyInto(out *ExternalEtcd) {
*out = *in
if in.Endpoints != nil {
in, out := &in.Endpoints, &out.Endpoints
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalEtcd.
func (in *ExternalEtcd) DeepCopy() *ExternalEtcd {
if in == nil {
return nil
}
out := new(ExternalEtcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HostPathMount) DeepCopyInto(out *HostPathMount) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPathMount.
func (in *HostPathMount) DeepCopy() *HostPathMount {
if in == nil {
return nil
}
out := new(HostPathMount)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeProxy) DeepCopyInto(out *KubeProxy) {
*out = *in
if in.Config != nil {
in, out := &in.Config, &out.Config
if *in == nil {
*out = nil
} else {
*out = new(v1alpha1.KubeProxyConfiguration)
(*in).DeepCopyInto(*out)
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeProxy.
func (in *KubeProxy) DeepCopy() *KubeProxy {
if in == nil {
return nil
}
out := new(KubeProxy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) {
*out = *in
if in.BaseConfig != nil {
in, out := &in.BaseConfig, &out.BaseConfig
if *in == nil {
*out = nil
} else {
*out = new(v1beta1.KubeletConfiguration)
(*in).DeepCopyInto(*out)
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeletConfiguration.
func (in *KubeletConfiguration) DeepCopy() *KubeletConfiguration {
if in == nil {
return nil
}
out := new(KubeletConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LocalEtcd) DeepCopyInto(out *LocalEtcd) {
*out = *in
if in.ExtraArgs != nil {
in, out := &in.ExtraArgs, &out.ExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.ServerCertSANs != nil {
in, out := &in.ServerCertSANs, &out.ServerCertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.PeerCertSANs != nil {
in, out := &in.PeerCertSANs, &out.PeerCertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalEtcd.
func (in *LocalEtcd) DeepCopy() *LocalEtcd {
if in == nil {
return nil
}
out := new(LocalEtcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MasterConfiguration) DeepCopyInto(out *MasterConfiguration) {
func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.BootstrapTokens != nil {
in, out := &in.BootstrapTokens, &out.BootstrapTokens
*out = make([]BootstrapToken, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
out.API = in.API
in.KubeProxy.DeepCopyInto(&out.KubeProxy)
in.Etcd.DeepCopyInto(&out.Etcd)
in.KubeletConfiguration.DeepCopyInto(&out.KubeletConfiguration)
out.Networking = in.Networking
if in.APIServerExtraArgs != nil {
in, out := &in.APIServerExtraArgs, &out.APIServerExtraArgs
@ -360,24 +177,236 @@ func (in *MasterConfiguration) DeepCopyInto(out *MasterConfiguration) {
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterConfiguration.
func (in *MasterConfiguration) DeepCopy() *MasterConfiguration {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterConfiguration.
func (in *ClusterConfiguration) DeepCopy() *ClusterConfiguration {
if in == nil {
return nil
}
out := new(MasterConfiguration)
out := new(ClusterConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *MasterConfiguration) DeepCopyObject() runtime.Object {
func (in *ClusterConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterStatus) DeepCopyInto(out *ClusterStatus) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.APIEndpoints != nil {
in, out := &in.APIEndpoints, &out.APIEndpoints
*out = make(map[string]APIEndpoint, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterStatus.
func (in *ClusterStatus) DeepCopy() *ClusterStatus {
if in == nil {
return nil
}
out := new(ClusterStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterStatus) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Etcd) DeepCopyInto(out *Etcd) {
*out = *in
if in.Local != nil {
in, out := &in.Local, &out.Local
*out = new(LocalEtcd)
(*in).DeepCopyInto(*out)
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(ExternalEtcd)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Etcd.
func (in *Etcd) DeepCopy() *Etcd {
if in == nil {
return nil
}
out := new(Etcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalEtcd) DeepCopyInto(out *ExternalEtcd) {
*out = *in
if in.Endpoints != nil {
in, out := &in.Endpoints, &out.Endpoints
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalEtcd.
func (in *ExternalEtcd) DeepCopy() *ExternalEtcd {
if in == nil {
return nil
}
out := new(ExternalEtcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HostPathMount) DeepCopyInto(out *HostPathMount) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPathMount.
func (in *HostPathMount) DeepCopy() *HostPathMount {
if in == nil {
return nil
}
out := new(HostPathMount)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InitConfiguration) DeepCopyInto(out *InitConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ClusterConfiguration.DeepCopyInto(&out.ClusterConfiguration)
if in.BootstrapTokens != nil {
in, out := &in.BootstrapTokens, &out.BootstrapTokens
*out = make([]BootstrapToken, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
out.APIEndpoint = in.APIEndpoint
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InitConfiguration.
func (in *InitConfiguration) DeepCopy() *InitConfiguration {
if in == nil {
return nil
}
out := new(InitConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *InitConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JoinConfiguration) DeepCopyInto(out *JoinConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
if in.DiscoveryTokenAPIServers != nil {
in, out := &in.DiscoveryTokenAPIServers, &out.DiscoveryTokenAPIServers
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.DiscoveryTimeout != nil {
in, out := &in.DiscoveryTimeout, &out.DiscoveryTimeout
*out = new(v1.Duration)
**out = **in
}
if in.DiscoveryTokenCACertHashes != nil {
in, out := &in.DiscoveryTokenCACertHashes, &out.DiscoveryTokenCACertHashes
*out = make([]string, len(*in))
copy(*out, *in)
}
out.APIEndpoint = in.APIEndpoint
if in.FeatureGates != nil {
in, out := &in.FeatureGates, &out.FeatureGates
*out = make(map[string]bool, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JoinConfiguration.
func (in *JoinConfiguration) DeepCopy() *JoinConfiguration {
if in == nil {
return nil
}
out := new(JoinConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *JoinConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LocalEtcd) DeepCopyInto(out *LocalEtcd) {
*out = *in
if in.ExtraArgs != nil {
in, out := &in.ExtraArgs, &out.ExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.ServerCertSANs != nil {
in, out := &in.ServerCertSANs, &out.ServerCertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.PeerCertSANs != nil {
in, out := &in.PeerCertSANs, &out.PeerCertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalEtcd.
func (in *LocalEtcd) DeepCopy() *LocalEtcd {
if in == nil {
return nil
}
out := new(LocalEtcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Networking) DeepCopyInto(out *Networking) {
*out = *in
@ -394,64 +423,12 @@ func (in *Networking) DeepCopy() *Networking {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeConfiguration) DeepCopyInto(out *NodeConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
if in.DiscoveryTokenAPIServers != nil {
in, out := &in.DiscoveryTokenAPIServers, &out.DiscoveryTokenAPIServers
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.DiscoveryTimeout != nil {
in, out := &in.DiscoveryTimeout, &out.DiscoveryTimeout
if *in == nil {
*out = nil
} else {
*out = new(v1.Duration)
**out = **in
}
}
if in.DiscoveryTokenCACertHashes != nil {
in, out := &in.DiscoveryTokenCACertHashes, &out.DiscoveryTokenCACertHashes
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.FeatureGates != nil {
in, out := &in.FeatureGates, &out.FeatureGates
*out = make(map[string]bool, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeConfiguration.
func (in *NodeConfiguration) DeepCopy() *NodeConfiguration {
if in == nil {
return nil
}
out := new(NodeConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *NodeConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) {
*out = *in
if in.Taints != nil {
in, out := &in.Taints, &out.Taints
*out = make([]core_v1.Taint, len(*in))
*out = make([]corev1.Taint, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}

View File

@ -18,39 +18,43 @@ limitations under the License.
// Code generated by defaulter-gen. DO NOT EDIT.
package v1alpha2
package v1alpha3
import (
runtime "k8s.io/apimachinery/pkg/runtime"
v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&MasterConfiguration{}, func(obj interface{}) { SetObjectDefaults_MasterConfiguration(obj.(*MasterConfiguration)) })
scheme.AddTypeDefaultingFunc(&NodeConfiguration{}, func(obj interface{}) { SetObjectDefaults_NodeConfiguration(obj.(*NodeConfiguration)) })
scheme.AddTypeDefaultingFunc(&ClusterConfiguration{}, func(obj interface{}) { SetObjectDefaults_ClusterConfiguration(obj.(*ClusterConfiguration)) })
scheme.AddTypeDefaultingFunc(&ClusterStatus{}, func(obj interface{}) { SetObjectDefaults_ClusterStatus(obj.(*ClusterStatus)) })
scheme.AddTypeDefaultingFunc(&InitConfiguration{}, func(obj interface{}) { SetObjectDefaults_InitConfiguration(obj.(*InitConfiguration)) })
scheme.AddTypeDefaultingFunc(&JoinConfiguration{}, func(obj interface{}) { SetObjectDefaults_JoinConfiguration(obj.(*JoinConfiguration)) })
return nil
}
func SetObjectDefaults_MasterConfiguration(in *MasterConfiguration) {
SetDefaults_MasterConfiguration(in)
func SetObjectDefaults_ClusterConfiguration(in *ClusterConfiguration) {
SetDefaults_ClusterConfiguration(in)
}
func SetObjectDefaults_ClusterStatus(in *ClusterStatus) {
}
func SetObjectDefaults_InitConfiguration(in *InitConfiguration) {
SetDefaults_InitConfiguration(in)
SetObjectDefaults_ClusterConfiguration(&in.ClusterConfiguration)
for i := range in.BootstrapTokens {
a := &in.BootstrapTokens[i]
SetDefaults_BootstrapToken(a)
}
SetDefaults_NodeRegistrationOptions(&in.NodeRegistration)
if in.KubeProxy.Config != nil {
v1alpha1.SetDefaults_KubeProxyConfiguration(in.KubeProxy.Config)
}
if in.KubeletConfiguration.BaseConfig != nil {
v1beta1.SetDefaults_KubeletConfiguration(in.KubeletConfiguration.BaseConfig)
}
SetDefaults_APIEndpoint(&in.APIEndpoint)
}
func SetObjectDefaults_NodeConfiguration(in *NodeConfiguration) {
SetDefaults_NodeConfiguration(in)
func SetObjectDefaults_JoinConfiguration(in *JoinConfiguration) {
SetDefaults_JoinConfiguration(in)
SetDefaults_NodeRegistrationOptions(&in.NodeRegistration)
SetDefaults_APIEndpoint(&in.APIEndpoint)
}

View File

@ -0,0 +1,52 @@
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/v1beta1",
visibility = ["//visibility:public"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/constants: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/cluster-bootstrap/token/api:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["bootstraptokenstring_test.go"],
embed = [":go_default_library"],
deps = ["//vendor/github.com/pkg/errors: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"],
)

View File

@ -0,0 +1,88 @@
/*
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 v1beta1
import (
"fmt"
"strings"
"github.com/pkg/errors"
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
bootstraputil "k8s.io/cluster-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, errors.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))
}

View File

@ -14,13 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha2
package v1beta1
import (
"encoding/json"
"fmt"
"reflect"
"testing"
"github.com/pkg/errors"
)
func TestMarshalJSON(t *testing.T) {
@ -99,13 +100,13 @@ func roundtrip(input string, bts *BootstrapTokenString) error {
// 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)
return errors.Wrap(err, "expected no unmarshal error, got error")
}
if b, err = json.Marshal(newbts); err != nil {
return fmt.Errorf("expected no marshal error, got error: %v", err)
return errors.Wrap(err, "expected no marshal error, got error")
}
if input != string(b) {
return fmt.Errorf(
return errors.Errorf(
"expected token: %s\n\t actual: %s",
input,
string(b),
@ -113,13 +114,13 @@ func roundtrip(input string, bts *BootstrapTokenString) error {
}
} 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)
return errors.Wrap(err, "expected no marshal error, got error")
}
if err := json.Unmarshal(b, newbts); err != nil {
return fmt.Errorf("expected no unmarshal error, got error: %v", err)
return errors.Wrap(err, "expected no unmarshal error, got error")
}
if !reflect.DeepEqual(bts, newbts) {
return fmt.Errorf(
return errors.Errorf(
"expected object: %v\n\t actual: %v",
bts,
newbts,

View File

@ -0,0 +1,223 @@
/*
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 v1beta1
import (
"net/url"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
)
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"
// 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"
// 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 = "::"
// DefaultDiscoveryTimeout specifies the default discovery timeout for kubeadm (used unless one is specified in the JoinConfiguration)
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_InitConfiguration assigns default values for the InitConfiguration
func SetDefaults_InitConfiguration(obj *InitConfiguration) {
SetDefaults_ClusterConfiguration(&obj.ClusterConfiguration)
SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration)
SetDefaults_BootstrapTokens(obj)
SetDefaults_APIEndpoint(&obj.LocalAPIEndpoint)
}
// SetDefaults_ClusterConfiguration assigns default values for the ClusterConfiguration
func SetDefaults_ClusterConfiguration(obj *ClusterConfiguration) {
if obj.KubernetesVersion == "" {
obj.KubernetesVersion = DefaultKubernetesVersion
}
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_DNS(obj)
SetDefaults_Etcd(obj)
SetDefaults_APIServer(&obj.APIServer)
}
// SetDefaults_APIServer assigns default values for the API Server
func SetDefaults_APIServer(obj *APIServer) {
if obj.TimeoutForControlPlane == nil {
obj.TimeoutForControlPlane = &metav1.Duration{
Duration: constants.DefaultControlPlaneTimeout,
}
}
}
// SetDefaults_DNS assigns default values for the DNS component
func SetDefaults_DNS(obj *ClusterConfiguration) {
if obj.DNS.Type == "" {
obj.DNS.Type = CoreDNS
}
}
// SetDefaults_Etcd assigns default values for the proxy
func SetDefaults_Etcd(obj *ClusterConfiguration) {
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_JoinConfiguration assigns default values to a regular node
func SetDefaults_JoinConfiguration(obj *JoinConfiguration) {
if obj.CACertPath == "" {
obj.CACertPath = DefaultCACertPath
}
SetDefaults_NodeRegistrationOptions(&obj.NodeRegistration)
SetDefaults_JoinControlPlane(obj.ControlPlane)
SetDefaults_Discovery(&obj.Discovery)
}
func SetDefaults_NodeRegistrationOptions(obj *NodeRegistrationOptions) {
if obj.CRISocket == "" {
obj.CRISocket = DefaultCRISocket
}
}
func SetDefaults_JoinControlPlane(obj *JoinControlPlane) {
if obj != nil {
SetDefaults_APIEndpoint(&obj.LocalAPIEndpoint)
}
}
// SetDefaults_Discovery assigns default values for the discovery process
func SetDefaults_Discovery(obj *Discovery) {
if len(obj.TLSBootstrapToken) == 0 && obj.BootstrapToken != nil {
obj.TLSBootstrapToken = obj.BootstrapToken.Token
}
if obj.Timeout == nil {
obj.Timeout = &metav1.Duration{
Duration: DefaultDiscoveryTimeout,
}
}
if obj.File != nil {
SetDefaults_FileDiscovery(obj.File)
}
}
// SetDefaults_FileDiscovery assigns default values for file based discovery
func SetDefaults_FileDiscovery(obj *FileDiscovery) {
// Make sure file URL becomes path
if len(obj.KubeConfigPath) != 0 {
u, err := url.Parse(obj.KubeConfigPath)
if err == nil && u.Scheme == "file" {
obj.KubeConfigPath = u.Path
}
}
}
// 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 *InitConfiguration) {
if obj.BootstrapTokens == nil || len(obj.BootstrapTokens) == 0 {
obj.BootstrapTokens = []BootstrapToken{{}}
}
for i := range obj.BootstrapTokens {
SetDefaults_BootstrapToken(&obj.BootstrapTokens[i])
}
}
// 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
}
}
// SetDefaults_APIEndpoint sets the defaults for the API server instance deployed on a node.
func SetDefaults_APIEndpoint(obj *APIEndpoint) {
if obj.BindPort == 0 {
obj.BindPort = DefaultAPIBindPort
}
}

View File

@ -0,0 +1,28 @@
// +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 v1beta1
const (
// DefaultCACertPath defines default location of CA certificate on Linux
DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
// DefaultUrlScheme defines default socket url prefix
DefaultUrlScheme = "unix"
// DefaultCRISocket defines the default cri socket
DefaultCRISocket = "/var/run/dockershim.sock"
)

View File

@ -1,3 +1,5 @@
// +build windows
/*
Copyright 2018 The Kubernetes Authors.
@ -14,9 +16,13 @@ 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 v1alpha2 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
package v1beta1
const (
// DefaultCACertPath defines default location of CA certificate on Windows
DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt"
// DefaultUrlScheme defines default socket url prefix
DefaultUrlScheme = "tcp"
// DefaultCRISocket defines the default cri socket
DefaultCRISocket = "tcp://localhost:2375"
)

View File

@ -0,0 +1,280 @@
/*
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.
*/
// +k8s:defaulter-gen=TypeMeta
// +groupName=kubeadm.k8s.io
// +k8s:deepcopy-gen=package
// +k8s:conversion-gen=k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm
// Package v1beta1 defines the v1beta1 version of the kubeadm configuration file format.
// This version graduates the configuration format to BETA and is a big step towards GA.
//
//A list of changes since v1alpha3:
// - "apiServerEndpoint" in InitConfiguration was renamed to "localAPIEndpoint" for better clarity of what the field
// represents.
// - Common fields in ClusterConfiguration such as "*extraArgs" and "*extraVolumes" for control plane components are now moved
// under component structs - i.e. "apiServer", "controllerManager", "scheduler".
// - "auditPolicy" was removed from ClusterConfiguration. Please use "extraArgs" in "apiServer" to configure this feature instead.
// - "unifiedControlPlaneImage" in ClusterConfiguration was changed to a boolean field called "useHyperKubeImage".
// - ClusterConfiguration now has a "dns" field which can be used to select and configure the cluster DNS addon.
// - "featureGates" still exists under ClusterConfiguration, but there are no supported feature gates in 1.13.
// See the Kubernetes 1.13 changelog for further details.
// - Both "localEtcd" and "dns" configurations now support custom image repositories.
// - The "controlPlane*"-related fields in JoinConfiguration were refactored into a sub-structure.
// - "clusterName" was removed from JoinConfiguration and the name is now fetched from the existing cluster.
//
// Migration from old kubeadm config versions
//
// Please convert your v1alpha3 configuration files to v1beta1 using the "kubeadm config migrate" command of kubeadm v1.13.x
// (conversion from older releases of kubeadm config files requires older release of kubeadm as well e.g.
// kubeadm v1.11 should be used to migrate v1alpha1 to v1alpha2; kubeadm v1.12 should be used to translate v1alpha2 to v1alpha3)
//
// Nevertheless, kubeadm v1.13.x will support reading from v1alpha3 version of the kubeadm config file format, but this support
// will be dropped in the v1.14 release.
//
// Basics
//
// The preferred way to configure kubeadm is to pass an YAML configuration file with the --config option. Some of the
// configuration options defined in the kubeadm config file are also available as command line flags, but only
// the most common/simple use case are supported with this approach.
//
// A kubeadm config file could contain multiple configuration types separated using three dashes (“---”).
//
// kubeadm supports the following configuration types:
//
// apiVersion: kubeadm.k8s.io/v1beta1
// kind: InitConfiguration
//
// apiVersion: kubeadm.k8s.io/v1beta1
// kind: ClusterConfiguration
//
// apiVersion: kubelet.config.k8s.io/v1beta1
// kind: KubeletConfiguration
//
// apiVersion: kubeproxy.config.k8s.io/v1alpha1
// kind: KubeProxyConfiguration
//
// apiVersion: kubeadm.k8s.io/v1beta1
// kind: JoinConfiguration
//
// To print the defaults for "init" and "join" actions use the following commands:
// kubeadm config print init-defaults
// kubeadm config print join-defaults
//
// The list of configuration types that must be included in a configuration file depends by the action you are
// performing (init or join) and by the configuration options you are going to use (defaults or advanced customization).
//
// If some configuration types are not provided, or provided only partially, kubeadm will use default values; defaults
// provided by kubeadm includes also enforcing consistency of values across components when required (e.g.
// cluster-cidr flag on controller manager and clusterCIDR on kube-proxy).
//
// Users are always allowed to override default values, with the only exception of a small subset of setting with
// relevance for security (e.g. enforce authorization-mode Node and RBAC on api server)
//
// If the user provides a configuration types that is not expected for the action you are performing, kubeadm will
// ignore those types and print a warning.
//
// Kubeadm init configuration types
//
// When executing kubeadm init with the --config option, the following configuration types could be used:
// InitConfiguration, ClusterConfiguration, KubeProxyConfiguration, KubeletConfiguration, but only one
// between InitConfiguration and ClusterConfiguration is mandatory.
//
// apiVersion: kubeadm.k8s.io/v1beta1
// kind: InitConfiguration
// bootstrapTokens:
// ...
// nodeRegistration:
// ...
//
// The InitConfiguration type should be used to configure runtime settings, that in case of kubeadm init
// are the configuration of the bootstrap token and all the setting which are specific to the node where kubeadm
// is executed, including:
//
// - NodeRegistration, that holds fields that relate to registering the new node to the cluster;
// use it to customize the node name, the CRI socket to use or any other settings that should apply to this
// node only (e.g. the node ip).
//
// - LocalAPIEndpoint, that represents the endpoint of the instance of the API server to be deployed on this node;
// use it e.g. to customize the API server advertise address.
//
// apiVersion: kubeadm.k8s.io/v1beta1
// kind: ClusterConfiguration
// networking:
// ...
// etcd:
// ...
// apiServer:
// extraArgs:
// ...
// extraVolumes:
// ...
// ...
//
// The ClusterConfiguration type should be used to configure cluster-wide settings,
// including settings for:
//
// - Networking, that holds configuration for the networking topology of the cluster; use it e.g. to customize
// node subnet or services subnet.
//
// - Etcd configurations; use it e.g. to customize the local etcd or to configure the API server
// for using an external etcd cluster.
//
// - kube-apiserver, kube-scheduler, kube-controller-manager configurations; use it to customize control-plane
// components by adding customized setting or overriding kubeadm default settings.
//
// apiVersion: kubeproxy.config.k8s.io/v1alpha1
// kind: KubeProxyConfiguration
// ...
//
// The KubeProxyConfiguration type should be used to change the configuration passed to kube-proxy instances deployed
// in the cluster. If this object is not provided or provided only partially, kubeadm applies defaults.
//
// See https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/ or https://godoc.org/k8s.io/kube-proxy/config/v1alpha1#KubeProxyConfiguration
// for kube proxy official documentation.
//
// apiVersion: kubelet.config.k8s.io/v1beta1
// kind: KubeletConfiguration
// ...
//
// The KubeletConfiguration type should be used to change the configurations that will be passed to all kubelet instances
// deployed in the cluster. If this object is not provided or provided only partially, kubeadm applies defaults.
//
// See https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/ or https://godoc.org/k8s.io/kubelet/config/v1beta1#KubeletConfiguration
// for kube proxy official documentation.
//
// Here is a fully populated example of a single YAML file containing multiple
// configuration types to be used during a `kubeadm init` run.
//
// apiVersion: kubeadm.k8s.io/v1beta1
// kind: InitConfiguration
// bootstrapTokens:
// - token: "9a08jv.c0izixklcxtmnze7"
// description: "kubeadm bootstrap token"
// ttl: "24h"
// - token: "783bde.3f89s0fje9f38fhf"
// description: "another bootstrap token"
// usages:
// - authentication
// - signing
// groups:
// - system:bootstrappers:kubeadm:default-node-token
// nodeRegistration:
// name: "ec2-10-100-0-1"
// criSocket: "/var/run/dockershim.sock"
// taints:
// - key: "kubeadmNode"
// value: "master"
// effect: "NoSchedule"
// kubeletExtraArgs:
// cgroupDriver: "cgroupfs"
// localApiEndpoint:
// advertiseAddress: "10.100.0.1"
// bindPort: 6443
// ---
// apiVersion: kubeadm.k8s.io/v1beta1
// kind: ClusterConfiguration
// etcd:
// # one of local or external
// local:
// imageRepository: "k8s.gcr.io"
// imageTag: "3.2.24"
// dataDir: "/var/lib/etcd"
// extraArgs:
// listen-client-urls: "http://10.100.0.1:2379"
// serverCertSANs:
// - "ec2-10-100-0-1.compute-1.amazonaws.com"
// peerCertSANs:
// - "10.100.0.1"
// # external:
// # endpoints:
// # - "10.100.0.1:2379"
// # - "10.100.0.2:2379"
// # caFile: "/etcd/kubernetes/pki/etcd/etcd-ca.crt"
// # certFile: "/etcd/kubernetes/pki/etcd/etcd.crt"
// # keyFile: "/etcd/kubernetes/pki/etcd/etcd.key"
// networking:
// serviceSubnet: "10.96.0.0/12"
// podSubnet: "10.100.0.1/24"
// dnsDomain: "cluster.local"
// kubernetesVersion: "v1.12.0"
// controlPlaneEndpoint: "10.100.0.1:6443"
// apiServer:
// extraArgs:
// authorization-mode: "Node,RBAC"
// extraVolumes:
// - name: "some-volume"
// hostPath: "/etc/some-path"
// mountPath: "/etc/some-pod-path"
// readOnly: false
// pathType: File
// certSANs:
// - "10.100.1.1"
// - "ec2-10-100-0-1.compute-1.amazonaws.com"
// timeoutForControlPlane: 4m0s
// controllerManager:
// extraArgs:
// "node-cidr-mask-size": "20"
// extraVolumes:
// - name: "some-volume"
// hostPath: "/etc/some-path"
// mountPath: "/etc/some-pod-path"
// readOnly: false
// pathType: File
// scheduler:
// extraArgs:
// address: "10.100.0.1"
// extraVolumes:
// - name: "some-volume"
// hostPath: "/etc/some-path"
// mountPath: "/etc/some-pod-path"
// readOnly: false
// pathType: File
// certificatesDir: "/etc/kubernetes/pki"
// imageRepository: "k8s.gcr.io"
// useHyperKubeImage: false
// clusterName: "example-cluster"
// ---
// apiVersion: kubelet.config.k8s.io/v1beta1
// kind: KubeletConfiguration
// # kubelet specific options here
// ---
// apiVersion: kubeproxy.config.k8s.io/v1alpha1
// kind: KubeProxyConfiguration
// # kube-proxy specific options here
//
// Kubeadm join configuration types
//
// When executing kubeadm join with the --config option, the JoinConfiguration type should be provided.
//
// apiVersion: kubeadm.k8s.io/v1beta1
// kind: JoinConfiguration
// ...
//
// The JoinConfiguration type should be used to configure runtime settings, that in case of kubeadm join
// are the discovery method used for accessing the cluster info and all the setting which are specific
// to the node where kubeadm is executed, including:
//
// - NodeRegistration, that holds fields that relate to registering the new node to the cluster;
// use it to customize the node name, the CRI socket to use or any other settings that should apply to this
// node only (e.g. the node ip).
//
// - APIEndpoint, that represents the endpoint of the instance of the API server to be eventually deployed on this node.
//
package v1beta1 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
//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.

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha2
package v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -26,7 +26,7 @@ import (
const GroupName = "kubeadm.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
var (
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
@ -58,8 +58,10 @@ func Resource(resource string) schema.GroupResource {
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&MasterConfiguration{},
&NodeConfiguration{},
&InitConfiguration{},
&ClusterConfiguration{},
&ClusterStatus{},
&JoinConfiguration{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil

View File

@ -0,0 +1,390 @@
/*
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 v1beta1
import (
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// InitConfiguration contains a list of elements that is specific "kubeadm init"-only runtime
// information.
type InitConfiguration struct {
metav1.TypeMeta `json:",inline"`
// ClusterConfiguration holds the cluster-wide information, and embeds that struct (which can be (un)marshalled separately as well)
// When InitConfiguration is marshalled to bytes in the external version, this information IS NOT preserved (which can be seen from
// the `json:"-"` tag. This is due to that when InitConfiguration is (un)marshalled, it turns into two YAML documents, one for the
// InitConfiguration and ClusterConfiguration. Hence, the information must not be duplicated, and is therefore omitted here.
ClusterConfiguration `json:"-"`
// `kubeadm init`-only information. These fields are solely used the first time `kubeadm init` runs.
// After that, the information in the fields IS 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"`
// LocalAPIEndpoint represents the endpoint of the API server instance that's deployed on this control plane node
// In HA setups, this differs from ClusterConfiguration.ControlPlaneEndpoint in the sense that ControlPlaneEndpoint
// is the global endpoint for the cluster, which then loadbalances the requests to each individual API server. This
// configuration object lets you customize what IP/DNS name and port the local API server advertises it's accessible
// on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process
// fails you may set the desired value here.
LocalAPIEndpoint APIEndpoint `json:"localAPIEndpoint,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterConfiguration contains cluster-wide configuration for a kubeadm cluster
type ClusterConfiguration struct {
metav1.TypeMeta `json:",inline"`
// Etcd holds configuration for etcd.
Etcd Etcd `json:"etcd"`
// 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"`
// 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 a 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"`
// APIServer contains extra settings for the API server control plane component
APIServer APIServer `json:"apiServer,omitempty"`
// ControllerManager contains extra settings for the controller manager control plane component
ControllerManager ControlPlaneComponent `json:"controllerManager,omitempty"`
// Scheduler contains extra settings for the scheduler control plane component
Scheduler ControlPlaneComponent `json:"scheduler,omitempty"`
// DNS defines the options for the DNS add-on installed in the cluster.
DNS DNS `json:"dns"`
// CertificatesDir specifies where to store or look for all required certificates.
CertificatesDir string `json:"certificatesDir"`
// ImageRepository sets the container registry to pull images from.
// If empty, `k8s.gcr.io` will be used by default; in case of kubernetes version is a CI build (kubernetes version starts with `ci/` or `ci-cross/`)
// `gcr.io/kubernetes-ci-images` will be used as a default for control plane components and for kube-proxy, while `k8s.gcr.io`
// will be used for all the other images.
ImageRepository string `json:"imageRepository"`
// UseHyperKubeImage controls if hyperkube should be used for Kubernetes components instead of their respective separate images
UseHyperKubeImage bool `json:"useHyperKubeImage,omitempty"`
// FeatureGates enabled by the user.
FeatureGates map[string]bool `json:"featureGates,omitempty"`
// The cluster name
ClusterName string `json:"clusterName,omitempty"`
}
// ControlPlaneComponent holds settings common to control plane component of the cluster
type ControlPlaneComponent struct {
// ExtraArgs is an extra set of flags to pass to the control plane component.
// TODO: This is temporary and ideally we would like to switch all components to
// use ComponentConfig + ConfigMaps.
ExtraArgs map[string]string `json:"extraArgs,omitempty"`
// ExtraVolumes is an extra set of host volumes, mounted to the control plane component.
ExtraVolumes []HostPathMount `json:"extraVolumes,omitempty"`
}
// APIServer holds settings necessary for API server deployments in the cluster
type APIServer struct {
ControlPlaneComponent `json:",inline"`
// CertSANs sets extra Subject Alternative Names for the API Server signing cert.
CertSANs []string `json:"certSANs,omitempty"`
// TimeoutForControlPlane controls the timeout that we use for API server to appear
TimeoutForControlPlane *metav1.Duration `json:"timeoutForControlPlane,omitempty"`
}
// DNSAddOnType defines string identifying DNS add-on types
type DNSAddOnType string
const (
// CoreDNS add-on type
CoreDNS DNSAddOnType = "CoreDNS"
// KubeDNS add-on type
KubeDNS DNSAddOnType = "kube-dns"
)
// DNS defines the DNS addon that should be used in the cluster
type DNS struct {
// Type defines the DNS add-on to be used
Type DNSAddOnType `json:"type"`
// ImageMeta allows to customize the image used for the DNS component
ImageMeta `json:",inline"`
}
// ImageMeta allows to customize the image used for components that are not
// originated from the Kubernetes/Kubernetes release process
type ImageMeta struct {
// ImageRepository sets the container registry to pull images from.
// if not set, the ImageRepository defined in ClusterConfiguration will be used instead.
ImageRepository string `json:"imageRepository,omitempty"`
// ImageTag allows to specify a tag for the image.
// In case this value is set, kubeadm does not change automatically the version of the above components during upgrades.
ImageTag string `json:"imageTag,omitempty"`
//TODO: evaluate if we need also a ImageName based on user feedbacks
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ClusterStatus contains the cluster status. The ClusterStatus will be stored in the kubeadm-config
// ConfigMap in the cluster, and then updated by kubeadm when additional control plane instance joins or leaves the cluster.
type ClusterStatus struct {
metav1.TypeMeta `json:",inline"`
// APIEndpoints currently available in the cluster, one for each control plane/api server instance.
// The key of the map is the IP of the host's default interface
APIEndpoints map[string]APIEndpoint `json:"apiEndpoints"`
}
// APIEndpoint struct contains elements of API server instance deployed on a node.
type APIEndpoint struct {
// AdvertiseAddress sets the IP address for the API server to advertise.
AdvertiseAddress string `json:"advertiseAddress"`
// 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 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 {
// ImageMeta allows to customize the container used for etcd
ImageMeta `json:",inline"`
// 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.
// Kubeadm has no knowledge of where certificate files live and they must be supplied.
type ExternalEtcd struct {
// Endpoints of etcd members. Required for ExternalEtcd.
Endpoints []string `json:"endpoints"`
// CAFile is an SSL Certificate Authority file used to secure etcd communication.
// Required if using a TLS connection.
CAFile string `json:"caFile"`
// CertFile is an SSL certification file used to secure etcd communication.
// Required if using a TLS connection.
CertFile string `json:"certFile"`
// KeyFile is an SSL key file used to secure etcd communication.
// Required if using a TLS connection.
KeyFile string `json:"keyFile"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// JoinConfiguration contains elements describing a particular node.
type JoinConfiguration 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"`
// Discovery specifies the options for the kubelet to use during the TLS Bootstrap process
Discovery Discovery `json:"discovery"`
// ControlPlane defines the additional control plane instance to be deployed on the joining node.
// If nil, no additional control plane instance will be deployed.
ControlPlane *JoinControlPlane `json:"controlPlane,omitempty"`
}
// JoinControlPlane contains elements describing an additional control plane instance to be deployed on the joining node.
type JoinControlPlane struct {
// LocalAPIEndpoint represents the endpoint of the API server instance to be deployed on this node.
LocalAPIEndpoint APIEndpoint `json:"localAPIEndpoint,omitempty"`
}
// Discovery specifies the options for the kubelet to use during the TLS Bootstrap process
type Discovery struct {
// BootstrapToken is used to set the options for bootstrap token based discovery
// BootstrapToken and File are mutually exclusive
BootstrapToken *BootstrapTokenDiscovery `json:"bootstrapToken,omitempty"`
// File is used to specify a file or URL to a kubeconfig file from which to load cluster information
// BootstrapToken and File are mutually exclusive
File *FileDiscovery `json:"file,omitempty"`
// TLSBootstrapToken is a token used for TLS bootstrapping.
// If .BootstrapToken is set, this field is defaulted to .BootstrapToken.Token, but can be overridden.
// If .File is set, this field **must be set** in case the KubeConfigFile does not contain any other authentication information
TLSBootstrapToken string `json:"tlsBootstrapToken"`
// Timeout modifies the discovery timeout
Timeout *metav1.Duration `json:"timeout,omitempty"`
}
// BootstrapTokenDiscovery is used to set the options for bootstrap token based discovery
type BootstrapTokenDiscovery struct {
// Token is a token used to validate cluster information
// fetched from the master.
Token string `json:"token"`
// APIServerEndpoint is an IP or domain name to the API server from which info will be fetched.
APIServerEndpoint string `json:"apiServerEndpoint,omitempty"`
// CACertHashes 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 "<type>:<value>",
// 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
CACertHashes []string `json:"caCertHashes,omitempty"`
// UnsafeSkipCAVerification allows token-based discovery
// without CA verification via CACertHashes. This can weaken
// the security of kubeadm since other nodes can impersonate the master.
UnsafeSkipCAVerification bool `json:"unsafeSkipCAVerification"`
}
// FileDiscovery is used to specify a file or URL to a kubeconfig file from which to load cluster information
type FileDiscovery struct {
// KubeConfigPath is used to specify the actual file path or URL to the kubeconfig file from which to load cluster information
KubeConfigPath string `json:"kubeConfigPath"`
}
// 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"`
// ReadOnly controls write access to the volume
ReadOnly bool `json:"readOnly,omitempty"`
// PathType is the type of the HostPath.
PathType v1.HostPathType `json:"pathType,omitempty"`
}

View File

@ -0,0 +1,839 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by conversion-gen. DO NOT EDIT.
package v1beta1
import (
unsafe "unsafe"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*APIEndpoint)(nil), (*kubeadm.APIEndpoint)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(a.(*APIEndpoint), b.(*kubeadm.APIEndpoint), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.APIEndpoint)(nil), (*APIEndpoint)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(a.(*kubeadm.APIEndpoint), b.(*APIEndpoint), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*APIServer)(nil), (*kubeadm.APIServer)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_APIServer_To_kubeadm_APIServer(a.(*APIServer), b.(*kubeadm.APIServer), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.APIServer)(nil), (*APIServer)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_APIServer_To_v1beta1_APIServer(a.(*kubeadm.APIServer), b.(*APIServer), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*BootstrapToken)(nil), (*kubeadm.BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_BootstrapToken_To_kubeadm_BootstrapToken(a.(*BootstrapToken), b.(*kubeadm.BootstrapToken), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapToken)(nil), (*BootstrapToken)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_BootstrapToken_To_v1beta1_BootstrapToken(a.(*kubeadm.BootstrapToken), b.(*BootstrapToken), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*BootstrapTokenDiscovery)(nil), (*kubeadm.BootstrapTokenDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(a.(*BootstrapTokenDiscovery), b.(*kubeadm.BootstrapTokenDiscovery), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapTokenDiscovery)(nil), (*BootstrapTokenDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_BootstrapTokenDiscovery_To_v1beta1_BootstrapTokenDiscovery(a.(*kubeadm.BootstrapTokenDiscovery), b.(*BootstrapTokenDiscovery), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*BootstrapTokenString)(nil), (*kubeadm.BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_BootstrapTokenString_To_kubeadm_BootstrapTokenString(a.(*BootstrapTokenString), b.(*kubeadm.BootstrapTokenString), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.BootstrapTokenString)(nil), (*BootstrapTokenString)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_BootstrapTokenString_To_v1beta1_BootstrapTokenString(a.(*kubeadm.BootstrapTokenString), b.(*BootstrapTokenString), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ClusterConfiguration)(nil), (*kubeadm.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration(a.(*ClusterConfiguration), b.(*kubeadm.ClusterConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterConfiguration)(nil), (*ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration(a.(*kubeadm.ClusterConfiguration), b.(*ClusterConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ClusterStatus)(nil), (*kubeadm.ClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_ClusterStatus_To_kubeadm_ClusterStatus(a.(*ClusterStatus), b.(*kubeadm.ClusterStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.ClusterStatus)(nil), (*ClusterStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_ClusterStatus_To_v1beta1_ClusterStatus(a.(*kubeadm.ClusterStatus), b.(*ClusterStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ControlPlaneComponent)(nil), (*kubeadm.ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(a.(*ControlPlaneComponent), b.(*kubeadm.ControlPlaneComponent), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.ControlPlaneComponent)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(a.(*kubeadm.ControlPlaneComponent), b.(*ControlPlaneComponent), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*DNS)(nil), (*kubeadm.DNS)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_DNS_To_kubeadm_DNS(a.(*DNS), b.(*kubeadm.DNS), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.DNS)(nil), (*DNS)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_DNS_To_v1beta1_DNS(a.(*kubeadm.DNS), b.(*DNS), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Discovery)(nil), (*kubeadm.Discovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_Discovery_To_kubeadm_Discovery(a.(*Discovery), b.(*kubeadm.Discovery), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.Discovery)(nil), (*Discovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_Discovery_To_v1beta1_Discovery(a.(*kubeadm.Discovery), b.(*Discovery), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Etcd)(nil), (*kubeadm.Etcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_Etcd_To_kubeadm_Etcd(a.(*Etcd), b.(*kubeadm.Etcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.Etcd)(nil), (*Etcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_Etcd_To_v1beta1_Etcd(a.(*kubeadm.Etcd), b.(*Etcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ExternalEtcd)(nil), (*kubeadm.ExternalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_ExternalEtcd_To_kubeadm_ExternalEtcd(a.(*ExternalEtcd), b.(*kubeadm.ExternalEtcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.ExternalEtcd)(nil), (*ExternalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_ExternalEtcd_To_v1beta1_ExternalEtcd(a.(*kubeadm.ExternalEtcd), b.(*ExternalEtcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*FileDiscovery)(nil), (*kubeadm.FileDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_FileDiscovery_To_kubeadm_FileDiscovery(a.(*FileDiscovery), b.(*kubeadm.FileDiscovery), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.FileDiscovery)(nil), (*FileDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_FileDiscovery_To_v1beta1_FileDiscovery(a.(*kubeadm.FileDiscovery), b.(*FileDiscovery), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*HostPathMount)(nil), (*kubeadm.HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_HostPathMount_To_kubeadm_HostPathMount(a.(*HostPathMount), b.(*kubeadm.HostPathMount), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.HostPathMount)(nil), (*HostPathMount)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_HostPathMount_To_v1beta1_HostPathMount(a.(*kubeadm.HostPathMount), b.(*HostPathMount), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ImageMeta)(nil), (*kubeadm.ImageMeta)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(a.(*ImageMeta), b.(*kubeadm.ImageMeta), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.ImageMeta)(nil), (*ImageMeta)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(a.(*kubeadm.ImageMeta), b.(*ImageMeta), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*InitConfiguration)(nil), (*kubeadm.InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_InitConfiguration_To_kubeadm_InitConfiguration(a.(*InitConfiguration), b.(*kubeadm.InitConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.InitConfiguration)(nil), (*InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_InitConfiguration_To_v1beta1_InitConfiguration(a.(*kubeadm.InitConfiguration), b.(*InitConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*JoinConfiguration)(nil), (*kubeadm.JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_JoinConfiguration_To_kubeadm_JoinConfiguration(a.(*JoinConfiguration), b.(*kubeadm.JoinConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.JoinConfiguration)(nil), (*JoinConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_JoinConfiguration_To_v1beta1_JoinConfiguration(a.(*kubeadm.JoinConfiguration), b.(*JoinConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*JoinControlPlane)(nil), (*kubeadm.JoinControlPlane)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_JoinControlPlane_To_kubeadm_JoinControlPlane(a.(*JoinControlPlane), b.(*kubeadm.JoinControlPlane), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.JoinControlPlane)(nil), (*JoinControlPlane)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_JoinControlPlane_To_v1beta1_JoinControlPlane(a.(*kubeadm.JoinControlPlane), b.(*JoinControlPlane), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*LocalEtcd)(nil), (*kubeadm.LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_LocalEtcd_To_kubeadm_LocalEtcd(a.(*LocalEtcd), b.(*kubeadm.LocalEtcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.LocalEtcd)(nil), (*LocalEtcd)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_LocalEtcd_To_v1beta1_LocalEtcd(a.(*kubeadm.LocalEtcd), b.(*LocalEtcd), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Networking)(nil), (*kubeadm.Networking)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_Networking_To_kubeadm_Networking(a.(*Networking), b.(*kubeadm.Networking), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.Networking)(nil), (*Networking)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_Networking_To_v1beta1_Networking(a.(*kubeadm.Networking), b.(*Networking), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*NodeRegistrationOptions)(nil), (*kubeadm.NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(a.(*NodeRegistrationOptions), b.(*kubeadm.NodeRegistrationOptions), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*kubeadm.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(a.(*kubeadm.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(in *APIEndpoint, out *kubeadm.APIEndpoint, s conversion.Scope) error {
out.AdvertiseAddress = in.AdvertiseAddress
out.BindPort = in.BindPort
return nil
}
// Convert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint is an autogenerated conversion function.
func Convert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(in *APIEndpoint, out *kubeadm.APIEndpoint, s conversion.Scope) error {
return autoConvert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(in, out, s)
}
func autoConvert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(in *kubeadm.APIEndpoint, out *APIEndpoint, s conversion.Scope) error {
out.AdvertiseAddress = in.AdvertiseAddress
out.BindPort = in.BindPort
return nil
}
// Convert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint is an autogenerated conversion function.
func Convert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(in *kubeadm.APIEndpoint, out *APIEndpoint, s conversion.Scope) error {
return autoConvert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(in, out, s)
}
func autoConvert_v1beta1_APIServer_To_kubeadm_APIServer(in *APIServer, out *kubeadm.APIServer, s conversion.Scope) error {
if err := Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(&in.ControlPlaneComponent, &out.ControlPlaneComponent, s); err != nil {
return err
}
out.CertSANs = *(*[]string)(unsafe.Pointer(&in.CertSANs))
out.TimeoutForControlPlane = (*v1.Duration)(unsafe.Pointer(in.TimeoutForControlPlane))
return nil
}
// Convert_v1beta1_APIServer_To_kubeadm_APIServer is an autogenerated conversion function.
func Convert_v1beta1_APIServer_To_kubeadm_APIServer(in *APIServer, out *kubeadm.APIServer, s conversion.Scope) error {
return autoConvert_v1beta1_APIServer_To_kubeadm_APIServer(in, out, s)
}
func autoConvert_kubeadm_APIServer_To_v1beta1_APIServer(in *kubeadm.APIServer, out *APIServer, s conversion.Scope) error {
if err := Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(&in.ControlPlaneComponent, &out.ControlPlaneComponent, s); err != nil {
return err
}
out.CertSANs = *(*[]string)(unsafe.Pointer(&in.CertSANs))
out.TimeoutForControlPlane = (*v1.Duration)(unsafe.Pointer(in.TimeoutForControlPlane))
return nil
}
// Convert_kubeadm_APIServer_To_v1beta1_APIServer is an autogenerated conversion function.
func Convert_kubeadm_APIServer_To_v1beta1_APIServer(in *kubeadm.APIServer, out *APIServer, s conversion.Scope) error {
return autoConvert_kubeadm_APIServer_To_v1beta1_APIServer(in, out, s)
}
func autoConvert_v1beta1_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
out.Token = (*kubeadm.BootstrapTokenString)(unsafe.Pointer(in.Token))
out.Description = in.Description
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
return nil
}
// Convert_v1beta1_BootstrapToken_To_kubeadm_BootstrapToken is an autogenerated conversion function.
func Convert_v1beta1_BootstrapToken_To_kubeadm_BootstrapToken(in *BootstrapToken, out *kubeadm.BootstrapToken, s conversion.Scope) error {
return autoConvert_v1beta1_BootstrapToken_To_kubeadm_BootstrapToken(in, out, s)
}
func autoConvert_kubeadm_BootstrapToken_To_v1beta1_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
out.Token = (*BootstrapTokenString)(unsafe.Pointer(in.Token))
out.Description = in.Description
out.TTL = (*v1.Duration)(unsafe.Pointer(in.TTL))
out.Expires = (*v1.Time)(unsafe.Pointer(in.Expires))
out.Usages = *(*[]string)(unsafe.Pointer(&in.Usages))
out.Groups = *(*[]string)(unsafe.Pointer(&in.Groups))
return nil
}
// Convert_kubeadm_BootstrapToken_To_v1beta1_BootstrapToken is an autogenerated conversion function.
func Convert_kubeadm_BootstrapToken_To_v1beta1_BootstrapToken(in *kubeadm.BootstrapToken, out *BootstrapToken, s conversion.Scope) error {
return autoConvert_kubeadm_BootstrapToken_To_v1beta1_BootstrapToken(in, out, s)
}
func autoConvert_v1beta1_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(in *BootstrapTokenDiscovery, out *kubeadm.BootstrapTokenDiscovery, s conversion.Scope) error {
out.Token = in.Token
out.APIServerEndpoint = in.APIServerEndpoint
out.CACertHashes = *(*[]string)(unsafe.Pointer(&in.CACertHashes))
out.UnsafeSkipCAVerification = in.UnsafeSkipCAVerification
return nil
}
// Convert_v1beta1_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery is an autogenerated conversion function.
func Convert_v1beta1_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(in *BootstrapTokenDiscovery, out *kubeadm.BootstrapTokenDiscovery, s conversion.Scope) error {
return autoConvert_v1beta1_BootstrapTokenDiscovery_To_kubeadm_BootstrapTokenDiscovery(in, out, s)
}
func autoConvert_kubeadm_BootstrapTokenDiscovery_To_v1beta1_BootstrapTokenDiscovery(in *kubeadm.BootstrapTokenDiscovery, out *BootstrapTokenDiscovery, s conversion.Scope) error {
out.Token = in.Token
out.APIServerEndpoint = in.APIServerEndpoint
out.CACertHashes = *(*[]string)(unsafe.Pointer(&in.CACertHashes))
out.UnsafeSkipCAVerification = in.UnsafeSkipCAVerification
return nil
}
// Convert_kubeadm_BootstrapTokenDiscovery_To_v1beta1_BootstrapTokenDiscovery is an autogenerated conversion function.
func Convert_kubeadm_BootstrapTokenDiscovery_To_v1beta1_BootstrapTokenDiscovery(in *kubeadm.BootstrapTokenDiscovery, out *BootstrapTokenDiscovery, s conversion.Scope) error {
return autoConvert_kubeadm_BootstrapTokenDiscovery_To_v1beta1_BootstrapTokenDiscovery(in, out, s)
}
func autoConvert_v1beta1_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
out.ID = in.ID
out.Secret = in.Secret
return nil
}
// Convert_v1beta1_BootstrapTokenString_To_kubeadm_BootstrapTokenString is an autogenerated conversion function.
func Convert_v1beta1_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in *BootstrapTokenString, out *kubeadm.BootstrapTokenString, s conversion.Scope) error {
return autoConvert_v1beta1_BootstrapTokenString_To_kubeadm_BootstrapTokenString(in, out, s)
}
func autoConvert_kubeadm_BootstrapTokenString_To_v1beta1_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
out.ID = in.ID
out.Secret = in.Secret
return nil
}
// Convert_kubeadm_BootstrapTokenString_To_v1beta1_BootstrapTokenString is an autogenerated conversion function.
func Convert_kubeadm_BootstrapTokenString_To_v1beta1_BootstrapTokenString(in *kubeadm.BootstrapTokenString, out *BootstrapTokenString, s conversion.Scope) error {
return autoConvert_kubeadm_BootstrapTokenString_To_v1beta1_BootstrapTokenString(in, out, s)
}
func autoConvert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
if err := Convert_v1beta1_Etcd_To_kubeadm_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
return err
}
if err := Convert_v1beta1_Networking_To_kubeadm_Networking(&in.Networking, &out.Networking, s); err != nil {
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
if err := Convert_v1beta1_APIServer_To_kubeadm_APIServer(&in.APIServer, &out.APIServer, s); err != nil {
return err
}
if err := Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil {
return err
}
if err := Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil {
return err
}
if err := Convert_v1beta1_DNS_To_kubeadm_DNS(&in.DNS, &out.DNS, s); err != nil {
return err
}
out.CertificatesDir = in.CertificatesDir
out.ImageRepository = in.ImageRepository
out.UseHyperKubeImage = in.UseHyperKubeImage
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.ClusterName = in.ClusterName
return nil
}
// Convert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration is an autogenerated conversion function.
func Convert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *ClusterConfiguration, out *kubeadm.ClusterConfiguration, s conversion.Scope) error {
return autoConvert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in, out, s)
}
func autoConvert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error {
// INFO: in.ComponentConfigs opted out of conversion generation
if err := Convert_kubeadm_Etcd_To_v1beta1_Etcd(&in.Etcd, &out.Etcd, s); err != nil {
return err
}
if err := Convert_kubeadm_Networking_To_v1beta1_Networking(&in.Networking, &out.Networking, s); err != nil {
return err
}
out.KubernetesVersion = in.KubernetesVersion
out.ControlPlaneEndpoint = in.ControlPlaneEndpoint
if err := Convert_kubeadm_APIServer_To_v1beta1_APIServer(&in.APIServer, &out.APIServer, s); err != nil {
return err
}
if err := Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil {
return err
}
if err := Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil {
return err
}
if err := Convert_kubeadm_DNS_To_v1beta1_DNS(&in.DNS, &out.DNS, s); err != nil {
return err
}
out.CertificatesDir = in.CertificatesDir
out.ImageRepository = in.ImageRepository
// INFO: in.CIImageRepository opted out of conversion generation
out.UseHyperKubeImage = in.UseHyperKubeImage
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.ClusterName = in.ClusterName
return nil
}
// Convert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration is an autogenerated conversion function.
func Convert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration(in *kubeadm.ClusterConfiguration, out *ClusterConfiguration, s conversion.Scope) error {
return autoConvert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration(in, out, s)
}
func autoConvert_v1beta1_ClusterStatus_To_kubeadm_ClusterStatus(in *ClusterStatus, out *kubeadm.ClusterStatus, s conversion.Scope) error {
out.APIEndpoints = *(*map[string]kubeadm.APIEndpoint)(unsafe.Pointer(&in.APIEndpoints))
return nil
}
// Convert_v1beta1_ClusterStatus_To_kubeadm_ClusterStatus is an autogenerated conversion function.
func Convert_v1beta1_ClusterStatus_To_kubeadm_ClusterStatus(in *ClusterStatus, out *kubeadm.ClusterStatus, s conversion.Scope) error {
return autoConvert_v1beta1_ClusterStatus_To_kubeadm_ClusterStatus(in, out, s)
}
func autoConvert_kubeadm_ClusterStatus_To_v1beta1_ClusterStatus(in *kubeadm.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
out.APIEndpoints = *(*map[string]APIEndpoint)(unsafe.Pointer(&in.APIEndpoints))
return nil
}
// Convert_kubeadm_ClusterStatus_To_v1beta1_ClusterStatus is an autogenerated conversion function.
func Convert_kubeadm_ClusterStatus_To_v1beta1_ClusterStatus(in *kubeadm.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
return autoConvert_kubeadm_ClusterStatus_To_v1beta1_ClusterStatus(in, out, s)
}
func autoConvert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(in *ControlPlaneComponent, out *kubeadm.ControlPlaneComponent, s conversion.Scope) error {
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
out.ExtraVolumes = *(*[]kubeadm.HostPathMount)(unsafe.Pointer(&in.ExtraVolumes))
return nil
}
// Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent is an autogenerated conversion function.
func Convert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(in *ControlPlaneComponent, out *kubeadm.ControlPlaneComponent, s conversion.Scope) error {
return autoConvert_v1beta1_ControlPlaneComponent_To_kubeadm_ControlPlaneComponent(in, out, s)
}
func autoConvert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(in *kubeadm.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error {
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
out.ExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.ExtraVolumes))
return nil
}
// Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent is an autogenerated conversion function.
func Convert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(in *kubeadm.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error {
return autoConvert_kubeadm_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(in, out, s)
}
func autoConvert_v1beta1_DNS_To_kubeadm_DNS(in *DNS, out *kubeadm.DNS, s conversion.Scope) error {
out.Type = kubeadm.DNSAddOnType(in.Type)
if err := Convert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil {
return err
}
return nil
}
// Convert_v1beta1_DNS_To_kubeadm_DNS is an autogenerated conversion function.
func Convert_v1beta1_DNS_To_kubeadm_DNS(in *DNS, out *kubeadm.DNS, s conversion.Scope) error {
return autoConvert_v1beta1_DNS_To_kubeadm_DNS(in, out, s)
}
func autoConvert_kubeadm_DNS_To_v1beta1_DNS(in *kubeadm.DNS, out *DNS, s conversion.Scope) error {
out.Type = DNSAddOnType(in.Type)
if err := Convert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil {
return err
}
return nil
}
// Convert_kubeadm_DNS_To_v1beta1_DNS is an autogenerated conversion function.
func Convert_kubeadm_DNS_To_v1beta1_DNS(in *kubeadm.DNS, out *DNS, s conversion.Scope) error {
return autoConvert_kubeadm_DNS_To_v1beta1_DNS(in, out, s)
}
func autoConvert_v1beta1_Discovery_To_kubeadm_Discovery(in *Discovery, out *kubeadm.Discovery, s conversion.Scope) error {
out.BootstrapToken = (*kubeadm.BootstrapTokenDiscovery)(unsafe.Pointer(in.BootstrapToken))
out.File = (*kubeadm.FileDiscovery)(unsafe.Pointer(in.File))
out.TLSBootstrapToken = in.TLSBootstrapToken
out.Timeout = (*v1.Duration)(unsafe.Pointer(in.Timeout))
return nil
}
// Convert_v1beta1_Discovery_To_kubeadm_Discovery is an autogenerated conversion function.
func Convert_v1beta1_Discovery_To_kubeadm_Discovery(in *Discovery, out *kubeadm.Discovery, s conversion.Scope) error {
return autoConvert_v1beta1_Discovery_To_kubeadm_Discovery(in, out, s)
}
func autoConvert_kubeadm_Discovery_To_v1beta1_Discovery(in *kubeadm.Discovery, out *Discovery, s conversion.Scope) error {
out.BootstrapToken = (*BootstrapTokenDiscovery)(unsafe.Pointer(in.BootstrapToken))
out.File = (*FileDiscovery)(unsafe.Pointer(in.File))
out.TLSBootstrapToken = in.TLSBootstrapToken
out.Timeout = (*v1.Duration)(unsafe.Pointer(in.Timeout))
return nil
}
// Convert_kubeadm_Discovery_To_v1beta1_Discovery is an autogenerated conversion function.
func Convert_kubeadm_Discovery_To_v1beta1_Discovery(in *kubeadm.Discovery, out *Discovery, s conversion.Scope) error {
return autoConvert_kubeadm_Discovery_To_v1beta1_Discovery(in, out, s)
}
func autoConvert_v1beta1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
out.Local = (*kubeadm.LocalEtcd)(unsafe.Pointer(in.Local))
out.External = (*kubeadm.ExternalEtcd)(unsafe.Pointer(in.External))
return nil
}
// Convert_v1beta1_Etcd_To_kubeadm_Etcd is an autogenerated conversion function.
func Convert_v1beta1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
return autoConvert_v1beta1_Etcd_To_kubeadm_Etcd(in, out, s)
}
func autoConvert_kubeadm_Etcd_To_v1beta1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
out.Local = (*LocalEtcd)(unsafe.Pointer(in.Local))
out.External = (*ExternalEtcd)(unsafe.Pointer(in.External))
return nil
}
// Convert_kubeadm_Etcd_To_v1beta1_Etcd is an autogenerated conversion function.
func Convert_kubeadm_Etcd_To_v1beta1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
return autoConvert_kubeadm_Etcd_To_v1beta1_Etcd(in, out, s)
}
func autoConvert_v1beta1_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error {
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
out.CAFile = in.CAFile
out.CertFile = in.CertFile
out.KeyFile = in.KeyFile
return nil
}
// Convert_v1beta1_ExternalEtcd_To_kubeadm_ExternalEtcd is an autogenerated conversion function.
func Convert_v1beta1_ExternalEtcd_To_kubeadm_ExternalEtcd(in *ExternalEtcd, out *kubeadm.ExternalEtcd, s conversion.Scope) error {
return autoConvert_v1beta1_ExternalEtcd_To_kubeadm_ExternalEtcd(in, out, s)
}
func autoConvert_kubeadm_ExternalEtcd_To_v1beta1_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error {
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
out.CAFile = in.CAFile
out.CertFile = in.CertFile
out.KeyFile = in.KeyFile
return nil
}
// Convert_kubeadm_ExternalEtcd_To_v1beta1_ExternalEtcd is an autogenerated conversion function.
func Convert_kubeadm_ExternalEtcd_To_v1beta1_ExternalEtcd(in *kubeadm.ExternalEtcd, out *ExternalEtcd, s conversion.Scope) error {
return autoConvert_kubeadm_ExternalEtcd_To_v1beta1_ExternalEtcd(in, out, s)
}
func autoConvert_v1beta1_FileDiscovery_To_kubeadm_FileDiscovery(in *FileDiscovery, out *kubeadm.FileDiscovery, s conversion.Scope) error {
out.KubeConfigPath = in.KubeConfigPath
return nil
}
// Convert_v1beta1_FileDiscovery_To_kubeadm_FileDiscovery is an autogenerated conversion function.
func Convert_v1beta1_FileDiscovery_To_kubeadm_FileDiscovery(in *FileDiscovery, out *kubeadm.FileDiscovery, s conversion.Scope) error {
return autoConvert_v1beta1_FileDiscovery_To_kubeadm_FileDiscovery(in, out, s)
}
func autoConvert_kubeadm_FileDiscovery_To_v1beta1_FileDiscovery(in *kubeadm.FileDiscovery, out *FileDiscovery, s conversion.Scope) error {
out.KubeConfigPath = in.KubeConfigPath
return nil
}
// Convert_kubeadm_FileDiscovery_To_v1beta1_FileDiscovery is an autogenerated conversion function.
func Convert_kubeadm_FileDiscovery_To_v1beta1_FileDiscovery(in *kubeadm.FileDiscovery, out *FileDiscovery, s conversion.Scope) error {
return autoConvert_kubeadm_FileDiscovery_To_v1beta1_FileDiscovery(in, out, s)
}
func autoConvert_v1beta1_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
out.Name = in.Name
out.HostPath = in.HostPath
out.MountPath = in.MountPath
out.ReadOnly = in.ReadOnly
out.PathType = corev1.HostPathType(in.PathType)
return nil
}
// Convert_v1beta1_HostPathMount_To_kubeadm_HostPathMount is an autogenerated conversion function.
func Convert_v1beta1_HostPathMount_To_kubeadm_HostPathMount(in *HostPathMount, out *kubeadm.HostPathMount, s conversion.Scope) error {
return autoConvert_v1beta1_HostPathMount_To_kubeadm_HostPathMount(in, out, s)
}
func autoConvert_kubeadm_HostPathMount_To_v1beta1_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
out.Name = in.Name
out.HostPath = in.HostPath
out.MountPath = in.MountPath
out.ReadOnly = in.ReadOnly
out.PathType = corev1.HostPathType(in.PathType)
return nil
}
// Convert_kubeadm_HostPathMount_To_v1beta1_HostPathMount is an autogenerated conversion function.
func Convert_kubeadm_HostPathMount_To_v1beta1_HostPathMount(in *kubeadm.HostPathMount, out *HostPathMount, s conversion.Scope) error {
return autoConvert_kubeadm_HostPathMount_To_v1beta1_HostPathMount(in, out, s)
}
func autoConvert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(in *ImageMeta, out *kubeadm.ImageMeta, s conversion.Scope) error {
out.ImageRepository = in.ImageRepository
out.ImageTag = in.ImageTag
return nil
}
// Convert_v1beta1_ImageMeta_To_kubeadm_ImageMeta is an autogenerated conversion function.
func Convert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(in *ImageMeta, out *kubeadm.ImageMeta, s conversion.Scope) error {
return autoConvert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(in, out, s)
}
func autoConvert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(in *kubeadm.ImageMeta, out *ImageMeta, s conversion.Scope) error {
out.ImageRepository = in.ImageRepository
out.ImageTag = in.ImageTag
return nil
}
// Convert_kubeadm_ImageMeta_To_v1beta1_ImageMeta is an autogenerated conversion function.
func Convert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(in *kubeadm.ImageMeta, out *ImageMeta, s conversion.Scope) error {
return autoConvert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(in, out, s)
}
func autoConvert_v1beta1_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
if err := Convert_v1beta1_ClusterConfiguration_To_kubeadm_ClusterConfiguration(&in.ClusterConfiguration, &out.ClusterConfiguration, s); err != nil {
return err
}
out.BootstrapTokens = *(*[]kubeadm.BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
if err := Convert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
if err := Convert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(&in.LocalAPIEndpoint, &out.LocalAPIEndpoint, s); err != nil {
return err
}
return nil
}
// Convert_v1beta1_InitConfiguration_To_kubeadm_InitConfiguration is an autogenerated conversion function.
func Convert_v1beta1_InitConfiguration_To_kubeadm_InitConfiguration(in *InitConfiguration, out *kubeadm.InitConfiguration, s conversion.Scope) error {
return autoConvert_v1beta1_InitConfiguration_To_kubeadm_InitConfiguration(in, out, s)
}
func autoConvert_kubeadm_InitConfiguration_To_v1beta1_InitConfiguration(in *kubeadm.InitConfiguration, out *InitConfiguration, s conversion.Scope) error {
if err := Convert_kubeadm_ClusterConfiguration_To_v1beta1_ClusterConfiguration(&in.ClusterConfiguration, &out.ClusterConfiguration, s); err != nil {
return err
}
out.BootstrapTokens = *(*[]BootstrapToken)(unsafe.Pointer(&in.BootstrapTokens))
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
if err := Convert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(&in.LocalAPIEndpoint, &out.LocalAPIEndpoint, s); err != nil {
return err
}
return nil
}
// Convert_kubeadm_InitConfiguration_To_v1beta1_InitConfiguration is an autogenerated conversion function.
func Convert_kubeadm_InitConfiguration_To_v1beta1_InitConfiguration(in *kubeadm.InitConfiguration, out *InitConfiguration, s conversion.Scope) error {
return autoConvert_kubeadm_InitConfiguration_To_v1beta1_InitConfiguration(in, out, s)
}
func autoConvert_v1beta1_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConfiguration, out *kubeadm.JoinConfiguration, s conversion.Scope) error {
if err := Convert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
out.CACertPath = in.CACertPath
if err := Convert_v1beta1_Discovery_To_kubeadm_Discovery(&in.Discovery, &out.Discovery, s); err != nil {
return err
}
out.ControlPlane = (*kubeadm.JoinControlPlane)(unsafe.Pointer(in.ControlPlane))
return nil
}
// Convert_v1beta1_JoinConfiguration_To_kubeadm_JoinConfiguration is an autogenerated conversion function.
func Convert_v1beta1_JoinConfiguration_To_kubeadm_JoinConfiguration(in *JoinConfiguration, out *kubeadm.JoinConfiguration, s conversion.Scope) error {
return autoConvert_v1beta1_JoinConfiguration_To_kubeadm_JoinConfiguration(in, out, s)
}
func autoConvert_kubeadm_JoinConfiguration_To_v1beta1_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error {
if err := Convert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(&in.NodeRegistration, &out.NodeRegistration, s); err != nil {
return err
}
out.CACertPath = in.CACertPath
if err := Convert_kubeadm_Discovery_To_v1beta1_Discovery(&in.Discovery, &out.Discovery, s); err != nil {
return err
}
out.ControlPlane = (*JoinControlPlane)(unsafe.Pointer(in.ControlPlane))
return nil
}
// Convert_kubeadm_JoinConfiguration_To_v1beta1_JoinConfiguration is an autogenerated conversion function.
func Convert_kubeadm_JoinConfiguration_To_v1beta1_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error {
return autoConvert_kubeadm_JoinConfiguration_To_v1beta1_JoinConfiguration(in, out, s)
}
func autoConvert_v1beta1_JoinControlPlane_To_kubeadm_JoinControlPlane(in *JoinControlPlane, out *kubeadm.JoinControlPlane, s conversion.Scope) error {
if err := Convert_v1beta1_APIEndpoint_To_kubeadm_APIEndpoint(&in.LocalAPIEndpoint, &out.LocalAPIEndpoint, s); err != nil {
return err
}
return nil
}
// Convert_v1beta1_JoinControlPlane_To_kubeadm_JoinControlPlane is an autogenerated conversion function.
func Convert_v1beta1_JoinControlPlane_To_kubeadm_JoinControlPlane(in *JoinControlPlane, out *kubeadm.JoinControlPlane, s conversion.Scope) error {
return autoConvert_v1beta1_JoinControlPlane_To_kubeadm_JoinControlPlane(in, out, s)
}
func autoConvert_kubeadm_JoinControlPlane_To_v1beta1_JoinControlPlane(in *kubeadm.JoinControlPlane, out *JoinControlPlane, s conversion.Scope) error {
if err := Convert_kubeadm_APIEndpoint_To_v1beta1_APIEndpoint(&in.LocalAPIEndpoint, &out.LocalAPIEndpoint, s); err != nil {
return err
}
return nil
}
// Convert_kubeadm_JoinControlPlane_To_v1beta1_JoinControlPlane is an autogenerated conversion function.
func Convert_kubeadm_JoinControlPlane_To_v1beta1_JoinControlPlane(in *kubeadm.JoinControlPlane, out *JoinControlPlane, s conversion.Scope) error {
return autoConvert_kubeadm_JoinControlPlane_To_v1beta1_JoinControlPlane(in, out, s)
}
func autoConvert_v1beta1_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error {
if err := Convert_v1beta1_ImageMeta_To_kubeadm_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil {
return err
}
out.DataDir = in.DataDir
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs))
out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs))
return nil
}
// Convert_v1beta1_LocalEtcd_To_kubeadm_LocalEtcd is an autogenerated conversion function.
func Convert_v1beta1_LocalEtcd_To_kubeadm_LocalEtcd(in *LocalEtcd, out *kubeadm.LocalEtcd, s conversion.Scope) error {
return autoConvert_v1beta1_LocalEtcd_To_kubeadm_LocalEtcd(in, out, s)
}
func autoConvert_kubeadm_LocalEtcd_To_v1beta1_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error {
if err := Convert_kubeadm_ImageMeta_To_v1beta1_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil {
return err
}
out.DataDir = in.DataDir
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs))
out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs))
return nil
}
// Convert_kubeadm_LocalEtcd_To_v1beta1_LocalEtcd is an autogenerated conversion function.
func Convert_kubeadm_LocalEtcd_To_v1beta1_LocalEtcd(in *kubeadm.LocalEtcd, out *LocalEtcd, s conversion.Scope) error {
return autoConvert_kubeadm_LocalEtcd_To_v1beta1_LocalEtcd(in, out, s)
}
func autoConvert_v1beta1_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
out.ServiceSubnet = in.ServiceSubnet
out.PodSubnet = in.PodSubnet
out.DNSDomain = in.DNSDomain
return nil
}
// Convert_v1beta1_Networking_To_kubeadm_Networking is an autogenerated conversion function.
func Convert_v1beta1_Networking_To_kubeadm_Networking(in *Networking, out *kubeadm.Networking, s conversion.Scope) error {
return autoConvert_v1beta1_Networking_To_kubeadm_Networking(in, out, s)
}
func autoConvert_kubeadm_Networking_To_v1beta1_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
out.ServiceSubnet = in.ServiceSubnet
out.PodSubnet = in.PodSubnet
out.DNSDomain = in.DNSDomain
return nil
}
// Convert_kubeadm_Networking_To_v1beta1_Networking is an autogenerated conversion function.
func Convert_kubeadm_Networking_To_v1beta1_Networking(in *kubeadm.Networking, out *Networking, s conversion.Scope) error {
return autoConvert_kubeadm_Networking_To_v1beta1_Networking(in, out, s)
}
func autoConvert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error {
out.Name = in.Name
out.CRISocket = in.CRISocket
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
return nil
}
// Convert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions is an autogenerated conversion function.
func Convert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in *NodeRegistrationOptions, out *kubeadm.NodeRegistrationOptions, s conversion.Scope) error {
return autoConvert_v1beta1_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOptions(in, out, s)
}
func autoConvert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
out.Name = in.Name
out.CRISocket = in.CRISocket
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
return nil
}
// Convert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions is an autogenerated conversion function.
func Convert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
return autoConvert_kubeadm_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(in, out, s)
}

View File

@ -0,0 +1,552 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1beta1
import (
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *APIEndpoint) DeepCopyInto(out *APIEndpoint) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIEndpoint.
func (in *APIEndpoint) DeepCopy() *APIEndpoint {
if in == nil {
return nil
}
out := new(APIEndpoint)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *APIServer) DeepCopyInto(out *APIServer) {
*out = *in
in.ControlPlaneComponent.DeepCopyInto(&out.ControlPlaneComponent)
if in.CertSANs != nil {
in, out := &in.CertSANs, &out.CertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.TimeoutForControlPlane != nil {
in, out := &in.TimeoutForControlPlane, &out.TimeoutForControlPlane
*out = new(v1.Duration)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServer.
func (in *APIServer) DeepCopy() *APIServer {
if in == nil {
return nil
}
out := new(APIServer)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
*out = *in
if in.Token != nil {
in, out := &in.Token, &out.Token
*out = new(BootstrapTokenString)
**out = **in
}
if in.TTL != nil {
in, out := &in.TTL, &out.TTL
*out = new(v1.Duration)
**out = **in
}
if in.Expires != nil {
in, out := &in.Expires, &out.Expires
*out = (*in).DeepCopy()
}
if in.Usages != nil {
in, out := &in.Usages, &out.Usages
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Groups != nil {
in, out := &in.Groups, &out.Groups
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapToken.
func (in *BootstrapToken) DeepCopy() *BootstrapToken {
if in == nil {
return nil
}
out := new(BootstrapToken)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *BootstrapTokenDiscovery) DeepCopyInto(out *BootstrapTokenDiscovery) {
*out = *in
if in.CACertHashes != nil {
in, out := &in.CACertHashes, &out.CACertHashes
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenDiscovery.
func (in *BootstrapTokenDiscovery) DeepCopy() *BootstrapTokenDiscovery {
if in == nil {
return nil
}
out := new(BootstrapTokenDiscovery)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenString.
func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString {
if in == nil {
return nil
}
out := new(BootstrapTokenString)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.Etcd.DeepCopyInto(&out.Etcd)
out.Networking = in.Networking
in.APIServer.DeepCopyInto(&out.APIServer)
in.ControllerManager.DeepCopyInto(&out.ControllerManager)
in.Scheduler.DeepCopyInto(&out.Scheduler)
out.DNS = in.DNS
if in.FeatureGates != nil {
in, out := &in.FeatureGates, &out.FeatureGates
*out = make(map[string]bool, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterConfiguration.
func (in *ClusterConfiguration) DeepCopy() *ClusterConfiguration {
if in == nil {
return nil
}
out := new(ClusterConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterStatus) DeepCopyInto(out *ClusterStatus) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.APIEndpoints != nil {
in, out := &in.APIEndpoints, &out.APIEndpoints
*out = make(map[string]APIEndpoint, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterStatus.
func (in *ClusterStatus) DeepCopy() *ClusterStatus {
if in == nil {
return nil
}
out := new(ClusterStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterStatus) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ControlPlaneComponent) DeepCopyInto(out *ControlPlaneComponent) {
*out = *in
if in.ExtraArgs != nil {
in, out := &in.ExtraArgs, &out.ExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.ExtraVolumes != nil {
in, out := &in.ExtraVolumes, &out.ExtraVolumes
*out = make([]HostPathMount, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneComponent.
func (in *ControlPlaneComponent) DeepCopy() *ControlPlaneComponent {
if in == nil {
return nil
}
out := new(ControlPlaneComponent)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DNS) DeepCopyInto(out *DNS) {
*out = *in
out.ImageMeta = in.ImageMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNS.
func (in *DNS) DeepCopy() *DNS {
if in == nil {
return nil
}
out := new(DNS)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Discovery) DeepCopyInto(out *Discovery) {
*out = *in
if in.BootstrapToken != nil {
in, out := &in.BootstrapToken, &out.BootstrapToken
*out = new(BootstrapTokenDiscovery)
(*in).DeepCopyInto(*out)
}
if in.File != nil {
in, out := &in.File, &out.File
*out = new(FileDiscovery)
**out = **in
}
if in.Timeout != nil {
in, out := &in.Timeout, &out.Timeout
*out = new(v1.Duration)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Discovery.
func (in *Discovery) DeepCopy() *Discovery {
if in == nil {
return nil
}
out := new(Discovery)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Etcd) DeepCopyInto(out *Etcd) {
*out = *in
if in.Local != nil {
in, out := &in.Local, &out.Local
*out = new(LocalEtcd)
(*in).DeepCopyInto(*out)
}
if in.External != nil {
in, out := &in.External, &out.External
*out = new(ExternalEtcd)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Etcd.
func (in *Etcd) DeepCopy() *Etcd {
if in == nil {
return nil
}
out := new(Etcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalEtcd) DeepCopyInto(out *ExternalEtcd) {
*out = *in
if in.Endpoints != nil {
in, out := &in.Endpoints, &out.Endpoints
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalEtcd.
func (in *ExternalEtcd) DeepCopy() *ExternalEtcd {
if in == nil {
return nil
}
out := new(ExternalEtcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FileDiscovery) DeepCopyInto(out *FileDiscovery) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileDiscovery.
func (in *FileDiscovery) DeepCopy() *FileDiscovery {
if in == nil {
return nil
}
out := new(FileDiscovery)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HostPathMount) DeepCopyInto(out *HostPathMount) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPathMount.
func (in *HostPathMount) DeepCopy() *HostPathMount {
if in == nil {
return nil
}
out := new(HostPathMount)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageMeta) DeepCopyInto(out *ImageMeta) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageMeta.
func (in *ImageMeta) DeepCopy() *ImageMeta {
if in == nil {
return nil
}
out := new(ImageMeta)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InitConfiguration) DeepCopyInto(out *InitConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ClusterConfiguration.DeepCopyInto(&out.ClusterConfiguration)
if in.BootstrapTokens != nil {
in, out := &in.BootstrapTokens, &out.BootstrapTokens
*out = make([]BootstrapToken, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
out.LocalAPIEndpoint = in.LocalAPIEndpoint
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InitConfiguration.
func (in *InitConfiguration) DeepCopy() *InitConfiguration {
if in == nil {
return nil
}
out := new(InitConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *InitConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JoinConfiguration) DeepCopyInto(out *JoinConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
in.Discovery.DeepCopyInto(&out.Discovery)
if in.ControlPlane != nil {
in, out := &in.ControlPlane, &out.ControlPlane
*out = new(JoinControlPlane)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JoinConfiguration.
func (in *JoinConfiguration) DeepCopy() *JoinConfiguration {
if in == nil {
return nil
}
out := new(JoinConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *JoinConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JoinControlPlane) DeepCopyInto(out *JoinControlPlane) {
*out = *in
out.LocalAPIEndpoint = in.LocalAPIEndpoint
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JoinControlPlane.
func (in *JoinControlPlane) DeepCopy() *JoinControlPlane {
if in == nil {
return nil
}
out := new(JoinControlPlane)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LocalEtcd) DeepCopyInto(out *LocalEtcd) {
*out = *in
out.ImageMeta = in.ImageMeta
if in.ExtraArgs != nil {
in, out := &in.ExtraArgs, &out.ExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.ServerCertSANs != nil {
in, out := &in.ServerCertSANs, &out.ServerCertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.PeerCertSANs != nil {
in, out := &in.PeerCertSANs, &out.PeerCertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalEtcd.
func (in *LocalEtcd) DeepCopy() *LocalEtcd {
if in == nil {
return nil
}
out := new(LocalEtcd)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Networking) DeepCopyInto(out *Networking) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Networking.
func (in *Networking) DeepCopy() *Networking {
if in == nil {
return nil
}
out := new(Networking)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) {
*out = *in
if in.Taints != nil {
in, out := &in.Taints, &out.Taints
*out = make([]corev1.Taint, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.KubeletExtraArgs != nil {
in, out := &in.KubeletExtraArgs, &out.KubeletExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRegistrationOptions.
func (in *NodeRegistrationOptions) DeepCopy() *NodeRegistrationOptions {
if in == nil {
return nil
}
out := new(NodeRegistrationOptions)
in.DeepCopyInto(out)
return out
}

View File

@ -0,0 +1,68 @@
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by defaulter-gen. DO NOT EDIT.
package v1beta1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&ClusterConfiguration{}, func(obj interface{}) { SetObjectDefaults_ClusterConfiguration(obj.(*ClusterConfiguration)) })
scheme.AddTypeDefaultingFunc(&ClusterStatus{}, func(obj interface{}) { SetObjectDefaults_ClusterStatus(obj.(*ClusterStatus)) })
scheme.AddTypeDefaultingFunc(&InitConfiguration{}, func(obj interface{}) { SetObjectDefaults_InitConfiguration(obj.(*InitConfiguration)) })
scheme.AddTypeDefaultingFunc(&JoinConfiguration{}, func(obj interface{}) { SetObjectDefaults_JoinConfiguration(obj.(*JoinConfiguration)) })
return nil
}
func SetObjectDefaults_ClusterConfiguration(in *ClusterConfiguration) {
SetDefaults_ClusterConfiguration(in)
SetDefaults_APIServer(&in.APIServer)
}
func SetObjectDefaults_ClusterStatus(in *ClusterStatus) {
}
func SetObjectDefaults_InitConfiguration(in *InitConfiguration) {
SetDefaults_InitConfiguration(in)
SetObjectDefaults_ClusterConfiguration(&in.ClusterConfiguration)
for i := range in.BootstrapTokens {
a := &in.BootstrapTokens[i]
SetDefaults_BootstrapToken(a)
}
SetDefaults_NodeRegistrationOptions(&in.NodeRegistration)
SetDefaults_APIEndpoint(&in.LocalAPIEndpoint)
}
func SetObjectDefaults_JoinConfiguration(in *JoinConfiguration) {
SetDefaults_JoinConfiguration(in)
SetDefaults_NodeRegistrationOptions(&in.NodeRegistration)
SetDefaults_Discovery(&in.Discovery)
if in.Discovery.File != nil {
SetDefaults_FileDiscovery(in.Discovery.File)
}
if in.ControlPlane != nil {
SetDefaults_JoinControlPlane(in.ControlPlane)
SetDefaults_APIEndpoint(&in.ControlPlane.LocalAPIEndpoint)
}
}

View File

@ -7,24 +7,20 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//cmd/kubeadm/app/componentconfigs:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
"//pkg/apis/core/validation:go_default_library",
"//pkg/kubelet/apis/kubeletconfig:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/validation:go_default_library",
"//pkg/proxy/apis/kubeproxyconfig:go_default_library",
"//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library",
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
"//pkg/proxy/apis/kubeproxyconfig/validation:go_default_library",
"//pkg/registry/core/service/ipallocator:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
],
)
@ -34,12 +30,12 @@ go_test(
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library",
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
"//pkg/util/pointer:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//pkg/proxy/apis/config:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
],
)

View File

@ -22,65 +22,62 @@ import (
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
bootstraputil "k8s.io/cluster-bootstrap/token/util"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
kubeletvalidation "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation"
"k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig"
kubeproxyscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme"
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
proxyvalidation "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation"
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
)
// ValidateMasterConfiguration validates master configuration and collects all encountered errors
func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList {
// ValidateInitConfiguration validates an InitConfiguration object and collects all encountered errors
func ValidateInitConfiguration(c *kubeadm.InitConfiguration) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, ValidateNetworking(&c.Networking, field.NewPath("networking"))...)
allErrs = append(allErrs, ValidateCertSANs(c.APIServerCertSANs, field.NewPath("apiServerCertSANs"))...)
allErrs = append(allErrs, ValidateAbsolutePath(c.CertificatesDir, field.NewPath("certificatesDir"))...)
allErrs = append(allErrs, ValidateNodeRegistrationOptions(&c.NodeRegistration, field.NewPath("nodeRegistration"))...)
allErrs = append(allErrs, ValidateBootstrapTokens(c.BootstrapTokens, field.NewPath("bootstrapTokens"))...)
allErrs = append(allErrs, ValidateFeatureGates(c.FeatureGates, field.NewPath("featureGates"))...)
allErrs = append(allErrs, ValidateAPIEndpoint(&c.API, field.NewPath("api"))...)
allErrs = append(allErrs, ValidateProxy(c.KubeProxy.Config, field.NewPath("kubeProxy").Child("config"))...)
allErrs = append(allErrs, ValidateEtcd(&c.Etcd, field.NewPath("etcd"))...)
allErrs = append(allErrs, ValidateKubeletConfiguration(&c.KubeletConfiguration, field.NewPath("kubeletConfiguration"))...)
allErrs = append(allErrs, ValidateClusterConfiguration(&c.ClusterConfiguration)...)
allErrs = append(allErrs, ValidateAPIEndpoint(&c.LocalAPIEndpoint, field.NewPath("localAPIEndpoint"))...)
return allErrs
}
// ValidateProxy validates proxy configuration and collects all encountered errors
func ValidateProxy(c *kubeproxyconfigv1alpha1.KubeProxyConfiguration, fldPath *field.Path) field.ErrorList {
// ValidateClusterConfiguration validates an ClusterConfiguration object and collects all encountered errors
func ValidateClusterConfiguration(c *kubeadm.ClusterConfiguration) field.ErrorList {
allErrs := field.ErrorList{}
// Convert to the internal version
internalcfg := &kubeproxyconfig.KubeProxyConfiguration{}
err := kubeproxyscheme.Scheme.Convert(c, internalcfg, nil)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "", err.Error()))
return allErrs
}
return proxyvalidation.Validate(internalcfg)
allErrs = append(allErrs, ValidateNetworking(&c.Networking, field.NewPath("networking"))...)
allErrs = append(allErrs, ValidateAPIServer(&c.APIServer, field.NewPath("apiServer"))...)
allErrs = append(allErrs, ValidateAbsolutePath(c.CertificatesDir, field.NewPath("certificatesDir"))...)
allErrs = append(allErrs, ValidateFeatureGates(c.FeatureGates, field.NewPath("featureGates"))...)
allErrs = append(allErrs, ValidateHostPort(c.ControlPlaneEndpoint, field.NewPath("controlPlaneEndpoint"))...)
allErrs = append(allErrs, ValidateEtcd(&c.Etcd, field.NewPath("etcd"))...)
allErrs = append(allErrs, componentconfigs.Known.Validate(c)...)
return allErrs
}
// ValidateNodeConfiguration validates node configuration and collects all encountered errors
func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList {
// ValidateAPIServer validates a APIServer object and collects all encountered errors
func ValidateAPIServer(a *kubeadm.APIServer, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, ValidateDiscovery(c)...)
allErrs = append(allErrs, ValidateCertSANs(a.CertSANs, fldPath.Child("certSANs"))...)
return allErrs
}
// ValidateJoinConfiguration validates node configuration and collects all encountered errors
func ValidateJoinConfiguration(c *kubeadm.JoinConfiguration) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, ValidateDiscovery(&c.Discovery, field.NewPath("discovery"))...)
allErrs = append(allErrs, ValidateNodeRegistrationOptions(&c.NodeRegistration, field.NewPath("nodeRegistration"))...)
allErrs = append(allErrs, ValidateJoinControlPlane(c.ControlPlane, field.NewPath("controlPlane"))...)
if !filepath.IsAbs(c.CACertPath) || !strings.HasSuffix(c.CACertPath, ".crt") {
allErrs = append(allErrs, field.Invalid(field.NewPath("caCertPath"), c.CACertPath, "the ca certificate path must be an absolute path"))
@ -88,6 +85,15 @@ func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList {
return allErrs
}
// ValidateJoinControlPlane validates joining control plane configuration and collects all encountered errors
func ValidateJoinControlPlane(c *kubeadm.JoinControlPlane, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if c != nil {
allErrs = append(allErrs, ValidateAPIEndpoint(&c.LocalAPIEndpoint, fldPath.Child("localAPIEndpoint"))...)
}
return allErrs
}
// ValidateNodeRegistrationOptions validates the NodeRegistrationOptions object
func ValidateNodeRegistrationOptions(nro *kubeadm.NodeRegistrationOptions, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
@ -96,70 +102,77 @@ func ValidateNodeRegistrationOptions(nro *kubeadm.NodeRegistrationOptions, fldPa
} else {
allErrs = append(allErrs, apivalidation.ValidateDNS1123Subdomain(nro.Name, field.NewPath("name"))...)
}
allErrs = append(allErrs, ValidateAbsolutePath(nro.CRISocket, fldPath.Child("criSocket"))...)
allErrs = append(allErrs, ValidateSocketPath(nro.CRISocket, fldPath.Child("criSocket"))...)
// TODO: Maybe validate .Taints as well in the future using something like validateNodeTaints() in pkg/apis/core/validation
return allErrs
}
// ValidateDiscovery validates discovery related configuration and collects all encountered errors
func ValidateDiscovery(c *kubeadm.NodeConfiguration) field.ErrorList {
func ValidateDiscovery(d *kubeadm.Discovery, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(c.DiscoveryToken) != 0 {
allErrs = append(allErrs, ValidateToken(c.DiscoveryToken, field.NewPath("discoveryToken"))...)
}
if len(c.DiscoveryFile) != 0 {
allErrs = append(allErrs, ValidateDiscoveryFile(c.DiscoveryFile, field.NewPath("discoveryFile"))...)
}
allErrs = append(allErrs, ValidateArgSelection(c, field.NewPath("discovery"))...)
allErrs = append(allErrs, ValidateToken(c.TLSBootstrapToken, field.NewPath("tlsBootstrapToken"))...)
allErrs = append(allErrs, ValidateJoinDiscoveryTokenAPIServer(c.DiscoveryTokenAPIServers, field.NewPath("discoveryTokenAPIServers"))...)
return allErrs
}
// ValidateArgSelection validates discovery related configuration and collects all encountered errors
func ValidateArgSelection(cfg *kubeadm.NodeConfiguration, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(cfg.DiscoveryToken) != 0 && len(cfg.DiscoveryFile) != 0 {
allErrs = append(allErrs, field.Invalid(fldPath, "", "discoveryToken and discoveryFile cannot both be set"))
}
if len(cfg.DiscoveryToken) == 0 && len(cfg.DiscoveryFile) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath, "", "discoveryToken or discoveryFile must be set"))
}
if len(cfg.DiscoveryTokenAPIServers) < 1 && len(cfg.DiscoveryToken) != 0 {
allErrs = append(allErrs, field.Required(fldPath, "discoveryTokenAPIServers not set"))
if d.BootstrapToken == nil && d.File == nil {
allErrs = append(allErrs, field.Invalid(fldPath, "", "bootstrapToken or file must be set"))
}
if len(cfg.DiscoveryFile) != 0 && len(cfg.DiscoveryTokenCACertHashes) != 0 {
allErrs = append(allErrs, field.Invalid(fldPath, "", "discoveryTokenCACertHashes cannot be used with discoveryFile"))
if d.BootstrapToken != nil && d.File != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "", "bootstrapToken and file cannot both be set"))
}
if len(cfg.DiscoveryFile) == 0 && len(cfg.DiscoveryToken) != 0 &&
len(cfg.DiscoveryTokenCACertHashes) == 0 && !cfg.DiscoveryTokenUnsafeSkipCAVerification {
allErrs = append(allErrs, field.Invalid(fldPath, "", "using token-based discovery without discoveryTokenCACertHashes can be unsafe. set --discovery-token-unsafe-skip-ca-verification to continue"))
if d.BootstrapToken != nil {
allErrs = append(allErrs, ValidateDiscoveryBootstrapToken(d.BootstrapToken, fldPath.Child("bootstrapToken"))...)
allErrs = append(allErrs, ValidateToken(d.TLSBootstrapToken, fldPath.Child("tlsBootstrapToken"))...)
}
// TODO remove once we support multiple api servers
if len(cfg.DiscoveryTokenAPIServers) > 1 {
fmt.Println("[validation] WARNING: kubeadm doesn't fully support multiple API Servers yet")
}
return allErrs
}
// ValidateJoinDiscoveryTokenAPIServer validates discovery token for API server
func ValidateJoinDiscoveryTokenAPIServer(apiServers []string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for _, m := range apiServers {
_, _, err := net.SplitHostPort(m)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, m, err.Error()))
if d.File != nil {
allErrs = append(allErrs, ValidateDiscoveryFile(d.File, fldPath.Child("file"))...)
if len(d.TLSBootstrapToken) != 0 {
allErrs = append(allErrs, ValidateToken(d.TLSBootstrapToken, fldPath.Child("tlsBootstrapToken"))...)
}
}
return allErrs
}
// ValidateDiscoveryFile validates location of a discovery file
func ValidateDiscoveryFile(discoveryFile string, fldPath *field.Path) field.ErrorList {
// ValidateDiscoveryBootstrapToken validates bootstrap token discovery configuration
func ValidateDiscoveryBootstrapToken(b *kubeadm.BootstrapTokenDiscovery, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(b.APIServerEndpoint) == 0 {
allErrs = append(allErrs, field.Required(fldPath, "APIServerEndpoint is not set"))
}
if len(b.CACertHashes) == 0 && !b.UnsafeSkipCAVerification {
allErrs = append(allErrs, field.Invalid(fldPath, "", "using token-based discovery without caCertHashes can be unsafe. Set unsafeSkipCAVerification to continue"))
}
allErrs = append(allErrs, ValidateToken(b.Token, fldPath.Child("token"))...)
allErrs = append(allErrs, ValidateDiscoveryTokenAPIServer(b.APIServerEndpoint, fldPath.Child("apiServerEndpoints"))...)
return allErrs
}
// ValidateDiscoveryFile validates file discovery configuration
func ValidateDiscoveryFile(f *kubeadm.FileDiscovery, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, ValidateDiscoveryKubeConfigPath(f.KubeConfigPath, fldPath.Child("kubeConfigPath"))...)
return allErrs
}
// ValidateDiscoveryTokenAPIServer validates discovery token for API server
func ValidateDiscoveryTokenAPIServer(apiServer string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
_, _, err := net.SplitHostPort(apiServer)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, apiServer, err.Error()))
}
return allErrs
}
// ValidateDiscoveryKubeConfigPath validates location of a discovery file
func ValidateDiscoveryKubeConfigPath(discoveryFile string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
u, err := url.Parse(discoveryFile)
if err != nil {
@ -324,6 +337,24 @@ func ValidateIPFromString(ipaddr string, fldPath *field.Path) field.ErrorList {
return allErrs
}
// ValidatePort validates port numbers
func ValidatePort(port int32, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if _, err := kubeadmutil.ParsePort(strconv.Itoa(int(port))); err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, port, "port number is not valid"))
}
return allErrs
}
// ValidateHostPort validates host[:port] endpoints
func ValidateHostPort(endpoint string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if _, _, err := kubeadmutil.ParseHostPort(endpoint); endpoint != "" && err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, endpoint, "endpoint is not valid"))
}
return allErrs
}
// ValidateIPNetFromString validates network portion of ip address
func ValidateIPNetFromString(subnet string, minAddrs int64, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
@ -368,7 +399,7 @@ func ValidateMixedArguments(flag *pflag.FlagSet) error {
mixedInvalidFlags := []string{}
flag.Visit(func(f *pflag.Flag) {
if f.Name == "config" || f.Name == "ignore-preflight-errors" || strings.HasPrefix(f.Name, "skip-") || f.Name == "dry-run" || f.Name == "kubeconfig" || f.Name == "v" {
if f.Name == "config" || f.Name == "ignore-preflight-errors" || strings.HasPrefix(f.Name, "skip-") || f.Name == "dry-run" || f.Name == "kubeconfig" || f.Name == "v" || f.Name == "rootfs" || f.Name == "print-join-command" || f.Name == "node-name" || f.Name == "cri-socket" {
// "--skip-*" flags or other whitelisted flags can be set with --config
return
}
@ -376,7 +407,7 @@ func ValidateMixedArguments(flag *pflag.FlagSet) error {
})
if len(mixedInvalidFlags) != 0 {
return fmt.Errorf("can not mix '--config' with arguments %v", mixedInvalidFlags)
return errors.Errorf("can not mix '--config' with arguments %v", mixedInvalidFlags)
}
return nil
}
@ -384,13 +415,12 @@ func ValidateMixedArguments(flag *pflag.FlagSet) error {
// ValidateFeatureGates validates provided feature gates
func ValidateFeatureGates(featureGates map[string]bool, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
validFeatures := features.Keys(features.InitFeatureGates)
// check valid feature names are provided
for k := range featureGates {
if !features.Supports(features.InitFeatureGates, k) {
allErrs = append(allErrs, field.Invalid(fldPath, featureGates,
fmt.Sprintf("%s is not a valid feature name. Valid features are: %s", k, validFeatures)))
fmt.Sprintf("%s is not a valid feature name.", k)))
}
}
@ -398,18 +428,15 @@ func ValidateFeatureGates(featureGates map[string]bool, fldPath *field.Path) fie
}
// ValidateAPIEndpoint validates API server's endpoint
func ValidateAPIEndpoint(c *kubeadm.API, fldPath *field.Path) field.ErrorList {
func ValidateAPIEndpoint(c *kubeadm.APIEndpoint, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
endpoint, err := kubeadmutil.GetMasterEndpoint(c)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, endpoint, err.Error()))
}
allErrs = append(allErrs, ValidateIPFromString(c.AdvertiseAddress, fldPath.Child("advertiseAddress"))...)
allErrs = append(allErrs, ValidatePort(c.BindPort, fldPath.Child("bindPort"))...)
return allErrs
}
// ValidateIgnorePreflightErrors validates duplicates in ignore-preflight-errors flag.
func ValidateIgnorePreflightErrors(ignorePreflightErrors []string, skipPreflightChecks bool) (sets.String, error) {
func ValidateIgnorePreflightErrors(ignorePreflightErrors []string) (sets.String, error) {
ignoreErrors := sets.NewString()
allErrs := field.ErrorList{}
@ -417,11 +444,6 @@ func ValidateIgnorePreflightErrors(ignorePreflightErrors []string, skipPreflight
ignoreErrors.Insert(strings.ToLower(item)) // parameters are case insensitive
}
// TODO: remove once deprecated flag --skip-preflight-checks is removed.
if skipPreflightChecks {
ignoreErrors.Insert("all")
}
if ignoreErrors.Has("all") && ignoreErrors.Len() > 1 {
allErrs = append(allErrs, field.Invalid(field.NewPath("ignore-preflight-errors"), strings.Join(ignoreErrors.List(), ","), "don't specify individual checks if 'all' is used"))
}
@ -429,31 +451,21 @@ func ValidateIgnorePreflightErrors(ignorePreflightErrors []string, skipPreflight
return ignoreErrors, allErrs.ToAggregate()
}
// ValidateKubeletConfiguration validates kubelet configuration and collects all encountered errors
func ValidateKubeletConfiguration(c *kubeadm.KubeletConfiguration, fldPath *field.Path) field.ErrorList {
// ValidateSocketPath validates format of socket path or url
func ValidateSocketPath(socket string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if c.BaseConfig == nil {
return allErrs
u, err := url.Parse(socket)
if err != nil {
return append(allErrs, field.Invalid(fldPath, socket, fmt.Sprintf("url parsing error: %v", err)))
}
scheme, _, err := kubeletscheme.NewSchemeAndCodecs()
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "kubeletConfiguration", err.Error()))
return allErrs
}
// Convert versioned config to internal config
internalcfg := &kubeletconfig.KubeletConfiguration{}
err = scheme.Convert(c.BaseConfig, internalcfg, nil)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "kubeletConfiguration", err.Error()))
return allErrs
}
err = kubeletvalidation.ValidateKubeletConfiguration(internalcfg)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "kubeletConfiguration", err.Error()))
if u.Scheme == "" {
if !filepath.IsAbs(u.Path) {
return append(allErrs, field.Invalid(fldPath, socket, fmt.Sprintf("path is not absolute: %s", socket)))
}
} else if u.Scheme != kubeadmapiv1beta1.DefaultUrlScheme {
return append(allErrs, field.Invalid(fldPath, socket, fmt.Sprintf("url scheme %s is not supported", u.Scheme)))
}
return allErrs

File diff suppressed because it is too large Load Diff

View File

@ -21,50 +21,52 @@ limitations under the License.
package kubeadm
import (
core_v1 "k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
v1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
config "k8s.io/kubernetes/pkg/kubelet/apis/config"
apisconfig "k8s.io/kubernetes/pkg/proxy/apis/config"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *API) DeepCopyInto(out *API) {
func (in *APIEndpoint) DeepCopyInto(out *APIEndpoint) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new API.
func (in *API) DeepCopy() *API {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIEndpoint.
func (in *APIEndpoint) DeepCopy() *APIEndpoint {
if in == nil {
return nil
}
out := new(API)
out := new(APIEndpoint)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AuditPolicyConfiguration) DeepCopyInto(out *AuditPolicyConfiguration) {
func (in *APIServer) DeepCopyInto(out *APIServer) {
*out = *in
if in.LogMaxAge != nil {
in, out := &in.LogMaxAge, &out.LogMaxAge
if *in == nil {
*out = nil
} else {
*out = new(int32)
**out = **in
}
in.ControlPlaneComponent.DeepCopyInto(&out.ControlPlaneComponent)
if in.CertSANs != nil {
in, out := &in.CertSANs, &out.CertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.TimeoutForControlPlane != nil {
in, out := &in.TimeoutForControlPlane, &out.TimeoutForControlPlane
*out = new(v1.Duration)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuditPolicyConfiguration.
func (in *AuditPolicyConfiguration) DeepCopy() *AuditPolicyConfiguration {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServer.
func (in *APIServer) DeepCopy() *APIServer {
if in == nil {
return nil
}
out := new(AuditPolicyConfiguration)
out := new(APIServer)
in.DeepCopyInto(out)
return out
}
@ -74,29 +76,17 @@ func (in *BootstrapToken) DeepCopyInto(out *BootstrapToken) {
*out = *in
if in.Token != nil {
in, out := &in.Token, &out.Token
if *in == nil {
*out = nil
} else {
*out = new(BootstrapTokenString)
**out = **in
}
*out = new(BootstrapTokenString)
**out = **in
}
if in.TTL != nil {
in, out := &in.TTL, &out.TTL
if *in == nil {
*out = nil
} else {
*out = new(v1.Duration)
**out = **in
}
*out = new(v1.Duration)
**out = **in
}
if in.Expires != nil {
in, out := &in.Expires, &out.Expires
if *in == nil {
*out = nil
} else {
*out = (*in).DeepCopy()
}
*out = (*in).DeepCopy()
}
if in.Usages != nil {
in, out := &in.Usages, &out.Usages
@ -121,6 +111,27 @@ func (in *BootstrapToken) DeepCopy() *BootstrapToken {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *BootstrapTokenDiscovery) DeepCopyInto(out *BootstrapTokenDiscovery) {
*out = *in
if in.CACertHashes != nil {
in, out := &in.CACertHashes, &out.CACertHashes
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapTokenDiscovery.
func (in *BootstrapTokenDiscovery) DeepCopy() *BootstrapTokenDiscovery {
if in == nil {
return nil
}
out := new(BootstrapTokenDiscovery)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *BootstrapTokenString) DeepCopyInto(out *BootstrapTokenString) {
*out = *in
@ -137,26 +148,191 @@ func (in *BootstrapTokenString) DeepCopy() *BootstrapTokenString {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ComponentConfigs.DeepCopyInto(&out.ComponentConfigs)
in.Etcd.DeepCopyInto(&out.Etcd)
out.Networking = in.Networking
in.APIServer.DeepCopyInto(&out.APIServer)
in.ControllerManager.DeepCopyInto(&out.ControllerManager)
in.Scheduler.DeepCopyInto(&out.Scheduler)
out.DNS = in.DNS
if in.FeatureGates != nil {
in, out := &in.FeatureGates, &out.FeatureGates
*out = make(map[string]bool, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterConfiguration.
func (in *ClusterConfiguration) DeepCopy() *ClusterConfiguration {
if in == nil {
return nil
}
out := new(ClusterConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterStatus) DeepCopyInto(out *ClusterStatus) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.APIEndpoints != nil {
in, out := &in.APIEndpoints, &out.APIEndpoints
*out = make(map[string]APIEndpoint, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterStatus.
func (in *ClusterStatus) DeepCopy() *ClusterStatus {
if in == nil {
return nil
}
out := new(ClusterStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ClusterStatus) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ComponentConfigs) DeepCopyInto(out *ComponentConfigs) {
*out = *in
if in.Kubelet != nil {
in, out := &in.Kubelet, &out.Kubelet
*out = new(config.KubeletConfiguration)
(*in).DeepCopyInto(*out)
}
if in.KubeProxy != nil {
in, out := &in.KubeProxy, &out.KubeProxy
*out = new(apisconfig.KubeProxyConfiguration)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentConfigs.
func (in *ComponentConfigs) DeepCopy() *ComponentConfigs {
if in == nil {
return nil
}
out := new(ComponentConfigs)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ControlPlaneComponent) DeepCopyInto(out *ControlPlaneComponent) {
*out = *in
if in.ExtraArgs != nil {
in, out := &in.ExtraArgs, &out.ExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.ExtraVolumes != nil {
in, out := &in.ExtraVolumes, &out.ExtraVolumes
*out = make([]HostPathMount, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneComponent.
func (in *ControlPlaneComponent) DeepCopy() *ControlPlaneComponent {
if in == nil {
return nil
}
out := new(ControlPlaneComponent)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DNS) DeepCopyInto(out *DNS) {
*out = *in
out.ImageMeta = in.ImageMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNS.
func (in *DNS) DeepCopy() *DNS {
if in == nil {
return nil
}
out := new(DNS)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Discovery) DeepCopyInto(out *Discovery) {
*out = *in
if in.BootstrapToken != nil {
in, out := &in.BootstrapToken, &out.BootstrapToken
*out = new(BootstrapTokenDiscovery)
(*in).DeepCopyInto(*out)
}
if in.File != nil {
in, out := &in.File, &out.File
*out = new(FileDiscovery)
**out = **in
}
if in.Timeout != nil {
in, out := &in.Timeout, &out.Timeout
*out = new(v1.Duration)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Discovery.
func (in *Discovery) DeepCopy() *Discovery {
if in == nil {
return nil
}
out := new(Discovery)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Etcd) DeepCopyInto(out *Etcd) {
*out = *in
if in.Local != nil {
in, out := &in.Local, &out.Local
if *in == nil {
*out = nil
} else {
*out = new(LocalEtcd)
(*in).DeepCopyInto(*out)
}
*out = new(LocalEtcd)
(*in).DeepCopyInto(*out)
}
if in.External != nil {
in, out := &in.External, &out.External
if *in == nil {
*out = nil
} else {
*out = new(ExternalEtcd)
(*in).DeepCopyInto(*out)
}
*out = new(ExternalEtcd)
(*in).DeepCopyInto(*out)
}
return
}
@ -192,6 +368,22 @@ func (in *ExternalEtcd) DeepCopy() *ExternalEtcd {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FileDiscovery) DeepCopyInto(out *FileDiscovery) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileDiscovery.
func (in *FileDiscovery) DeepCopy() *FileDiscovery {
if in == nil {
return nil
}
out := new(FileDiscovery)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HostPathMount) DeepCopyInto(out *HostPathMount) {
*out = *in
@ -209,51 +401,101 @@ func (in *HostPathMount) DeepCopy() *HostPathMount {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeProxy) DeepCopyInto(out *KubeProxy) {
func (in *ImageMeta) DeepCopyInto(out *ImageMeta) {
*out = *in
if in.Config != nil {
in, out := &in.Config, &out.Config
if *in == nil {
*out = nil
} else {
*out = new(v1alpha1.KubeProxyConfiguration)
(*in).DeepCopyInto(*out)
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeProxy.
func (in *KubeProxy) DeepCopy() *KubeProxy {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageMeta.
func (in *ImageMeta) DeepCopy() *ImageMeta {
if in == nil {
return nil
}
out := new(KubeProxy)
out := new(ImageMeta)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) {
func (in *InitConfiguration) DeepCopyInto(out *InitConfiguration) {
*out = *in
if in.BaseConfig != nil {
in, out := &in.BaseConfig, &out.BaseConfig
if *in == nil {
*out = nil
} else {
*out = new(v1beta1.KubeletConfiguration)
(*in).DeepCopyInto(*out)
out.TypeMeta = in.TypeMeta
in.ClusterConfiguration.DeepCopyInto(&out.ClusterConfiguration)
if in.BootstrapTokens != nil {
in, out := &in.BootstrapTokens, &out.BootstrapTokens
*out = make([]BootstrapToken, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
out.LocalAPIEndpoint = in.LocalAPIEndpoint
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InitConfiguration.
func (in *InitConfiguration) DeepCopy() *InitConfiguration {
if in == nil {
return nil
}
out := new(InitConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *InitConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JoinConfiguration) DeepCopyInto(out *JoinConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
in.Discovery.DeepCopyInto(&out.Discovery)
if in.ControlPlane != nil {
in, out := &in.ControlPlane, &out.ControlPlane
*out = new(JoinControlPlane)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeletConfiguration.
func (in *KubeletConfiguration) DeepCopy() *KubeletConfiguration {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JoinConfiguration.
func (in *JoinConfiguration) DeepCopy() *JoinConfiguration {
if in == nil {
return nil
}
out := new(KubeletConfiguration)
out := new(JoinConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *JoinConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JoinControlPlane) DeepCopyInto(out *JoinControlPlane) {
*out = *in
out.LocalAPIEndpoint = in.LocalAPIEndpoint
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JoinControlPlane.
func (in *JoinControlPlane) DeepCopy() *JoinControlPlane {
if in == nil {
return nil
}
out := new(JoinControlPlane)
in.DeepCopyInto(out)
return out
}
@ -261,6 +503,7 @@ func (in *KubeletConfiguration) DeepCopy() *KubeletConfiguration {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LocalEtcd) DeepCopyInto(out *LocalEtcd) {
*out = *in
out.ImageMeta = in.ImageMeta
if in.ExtraArgs != nil {
in, out := &in.ExtraArgs, &out.ExtraArgs
*out = make(map[string]string, len(*in))
@ -291,93 +534,6 @@ func (in *LocalEtcd) DeepCopy() *LocalEtcd {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MasterConfiguration) DeepCopyInto(out *MasterConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.BootstrapTokens != nil {
in, out := &in.BootstrapTokens, &out.BootstrapTokens
*out = make([]BootstrapToken, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
out.API = in.API
in.KubeProxy.DeepCopyInto(&out.KubeProxy)
in.Etcd.DeepCopyInto(&out.Etcd)
in.KubeletConfiguration.DeepCopyInto(&out.KubeletConfiguration)
out.Networking = in.Networking
if in.APIServerExtraArgs != nil {
in, out := &in.APIServerExtraArgs, &out.APIServerExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.ControllerManagerExtraArgs != nil {
in, out := &in.ControllerManagerExtraArgs, &out.ControllerManagerExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.SchedulerExtraArgs != nil {
in, out := &in.SchedulerExtraArgs, &out.SchedulerExtraArgs
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.APIServerExtraVolumes != nil {
in, out := &in.APIServerExtraVolumes, &out.APIServerExtraVolumes
*out = make([]HostPathMount, len(*in))
copy(*out, *in)
}
if in.ControllerManagerExtraVolumes != nil {
in, out := &in.ControllerManagerExtraVolumes, &out.ControllerManagerExtraVolumes
*out = make([]HostPathMount, len(*in))
copy(*out, *in)
}
if in.SchedulerExtraVolumes != nil {
in, out := &in.SchedulerExtraVolumes, &out.SchedulerExtraVolumes
*out = make([]HostPathMount, len(*in))
copy(*out, *in)
}
if in.APIServerCertSANs != nil {
in, out := &in.APIServerCertSANs, &out.APIServerCertSANs
*out = make([]string, len(*in))
copy(*out, *in)
}
in.AuditPolicyConfiguration.DeepCopyInto(&out.AuditPolicyConfiguration)
if in.FeatureGates != nil {
in, out := &in.FeatureGates, &out.FeatureGates
*out = make(map[string]bool, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MasterConfiguration.
func (in *MasterConfiguration) DeepCopy() *MasterConfiguration {
if in == nil {
return nil
}
out := new(MasterConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *MasterConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Networking) DeepCopyInto(out *Networking) {
*out = *in
@ -394,64 +550,12 @@ func (in *Networking) DeepCopy() *Networking {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeConfiguration) DeepCopyInto(out *NodeConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.NodeRegistration.DeepCopyInto(&out.NodeRegistration)
if in.DiscoveryTokenAPIServers != nil {
in, out := &in.DiscoveryTokenAPIServers, &out.DiscoveryTokenAPIServers
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.DiscoveryTimeout != nil {
in, out := &in.DiscoveryTimeout, &out.DiscoveryTimeout
if *in == nil {
*out = nil
} else {
*out = new(v1.Duration)
**out = **in
}
}
if in.DiscoveryTokenCACertHashes != nil {
in, out := &in.DiscoveryTokenCACertHashes, &out.DiscoveryTokenCACertHashes
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.FeatureGates != nil {
in, out := &in.FeatureGates, &out.FeatureGates
*out = make(map[string]bool, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeConfiguration.
func (in *NodeConfiguration) DeepCopy() *NodeConfiguration {
if in == nil {
return nil
}
out := new(NodeConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *NodeConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) {
*out = *in
if in.Taints != nil {
in, out := &in.Taints, &out.Taints
*out = make([]core_v1.Taint, len(*in))
*out = make([]corev1.Taint, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}

View File

@ -22,57 +22,56 @@ go_library(
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha3:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
"//cmd/kubeadm/app/cmd/alpha:go_default_library",
"//cmd/kubeadm/app/cmd/options:go_default_library",
"//cmd/kubeadm/app/cmd/phases:go_default_library",
"//cmd/kubeadm/app/cmd/phases/workflow:go_default_library",
"//cmd/kubeadm/app/cmd/upgrade:go_default_library",
"//cmd/kubeadm/app/cmd/util:go_default_library",
"//cmd/kubeadm/app/componentconfigs:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/discovery:go_default_library",
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/images:go_default_library",
"//cmd/kubeadm/app/phases/addons/dns:go_default_library",
"//cmd/kubeadm/app/phases/addons/proxy:go_default_library",
"//cmd/kubeadm/app/phases/bootstraptoken/clusterinfo:go_default_library",
"//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library",
"//cmd/kubeadm/app/phases/certs:go_default_library",
"//cmd/kubeadm/app/phases/controlplane:go_default_library",
"//cmd/kubeadm/app/phases/etcd:go_default_library",
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
"//cmd/kubeadm/app/phases/kubelet:go_default_library",
"//cmd/kubeadm/app/phases/markmaster:go_default_library",
"//cmd/kubeadm/app/phases/markcontrolplane:go_default_library",
"//cmd/kubeadm/app/phases/patchnode:go_default_library",
"//cmd/kubeadm/app/phases/selfhosting:go_default_library",
"//cmd/kubeadm/app/phases/uploadconfig:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
"//cmd/kubeadm/app/util/apiclient:go_default_library",
"//cmd/kubeadm/app/util/audit:go_default_library",
"//cmd/kubeadm/app/util/config:go_default_library",
"//cmd/kubeadm/app/util/dryrun:go_default_library",
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
"//pkg/kubectl/util/i18n:go_default_library",
"//cmd/kubeadm/app/util/runtime:go_default_library",
"//cmd/kubeadm/app/util/staticpod:go_default_library",
"//pkg/util/initsystem:go_default_library",
"//pkg/version:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/duration:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/version:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library",
"//staging/src/k8s.io/client-go/util/cert:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/token/util:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/renstrom/dedent:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/duration:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/version:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
"//vendor/k8s.io/client-go/util/cert:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/sigs.k8s.io/yaml:go_default_library",
],
)
@ -80,6 +79,7 @@ go_test(
name = "go_default_test",
srcs = [
"completion_test.go",
"config_test.go",
"join_test.go",
"reset_test.go",
"token_test.go",
@ -89,22 +89,28 @@ go_test(
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
"//cmd/kubeadm/app/componentconfigs:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
"//cmd/kubeadm/app/util/config:go_default_library",
"//cmd/kubeadm/app/util/runtime:go_default_library",
"//cmd/kubeadm/test:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors: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/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library",
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/renstrom/dedent:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/fake:go_default_library",
"//vendor/k8s.io/client-go/testing:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/exec/testing:go_default_library",
"//vendor/sigs.k8s.io/yaml:go_default_library",
],
)
@ -119,6 +125,7 @@ filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//cmd/kubeadm/app/cmd/alpha:all-srcs",
"//cmd/kubeadm/app/cmd/options:all-srcs",
"//cmd/kubeadm/app/cmd/phases:all-srcs",
"//cmd/kubeadm/app/cmd/upgrade:all-srcs",
@ -126,15 +133,3 @@ filegroup(
],
tags = ["automanaged"],
)
go_test(
name = "go_default_xtest",
srcs = ["config_test.go"],
deps = [
":go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/util/config:go_default_library",
"//vendor/github.com/renstrom/dedent:go_default_library",
],
)

View File

@ -0,0 +1,74 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"alpha.go",
"certs.go",
"kubeconfig.go",
"kubelet.go",
"preflight.go",
"selfhosting.go",
],
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/alpha",
visibility = ["//visibility:public"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
"//cmd/kubeadm/app/cmd/options:go_default_library",
"//cmd/kubeadm/app/cmd/phases:go_default_library",
"//cmd/kubeadm/app/cmd/util:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/phases/certs:go_default_library",
"//cmd/kubeadm/app/phases/certs/renewal:go_default_library",
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
"//cmd/kubeadm/app/phases/kubelet:go_default_library",
"//cmd/kubeadm/app/phases/selfhosting:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
"//cmd/kubeadm/app/util/apiclient:go_default_library",
"//cmd/kubeadm/app/util/config:go_default_library",
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
"//pkg/util/normalizer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/version:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/k8s.io/utils/exec: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 = [
"certs_test.go",
"kubeconfig_test.go",
],
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/phases/certs:go_default_library",
"//cmd/kubeadm/app/util/pkiutil:go_default_library",
"//cmd/kubeadm/test:go_default_library",
"//cmd/kubeadm/test/certs:go_default_library",
"//cmd/kubeadm/test/cmd:go_default_library",
"//cmd/kubeadm/test/kubeconfig:go_default_library",
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
],
)

View File

@ -0,0 +1,55 @@
/*
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 alpha
import (
"io"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
)
// NewCmdAlpha returns "kubeadm alpha" command.
func NewCmdAlpha(in io.Reader, out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "alpha",
Short: "Kubeadm experimental sub-commands",
}
cmd.AddCommand(newCmdCertsUtility())
cmd.AddCommand(newCmdKubeletUtility())
cmd.AddCommand(newCmdKubeConfigUtility(out))
cmd.AddCommand(newCmdPreFlightUtility())
cmd.AddCommand(NewCmdSelfhosting(in))
// TODO: This command should be removed as soon as the kubeadm init phase refactoring is completed.
// current phases implemented as cobra.Commands should become workflow.Phases, while other utilities
// hosted under kubeadm alpha phases command should found a new home under kubeadm alpha (without phases)
cmd.AddCommand(newCmdPhase(out))
return cmd
}
func newCmdPhase(out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "phase",
Short: "Invoke subsets of kubeadm functions separately for a manual install",
Long: cmdutil.MacroCommandLongDescription,
}
return cmd
}

View File

@ -0,0 +1,185 @@
/*
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 alpha
import (
"fmt"
"github.com/spf13/cobra"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/renewal"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
genericLongDesc = normalizer.LongDesc(`
Renews the %[1]s, and saves them into %[2]s.cert and %[2]s.key files.
Extra attributes such as SANs will be based on the existing certificates, there is no need to resupply them.
`)
allLongDesc = normalizer.LongDesc(`
Renews all known certificates necessary to run the control plan. Renewals are run unconditionally, regardless
of expiration date. Renewals can also be run individually for more control.
`)
)
// newCmdCertsUtility returns main command for certs phase
func newCmdCertsUtility() *cobra.Command {
cmd := &cobra.Command{
Use: "certs",
Aliases: []string{"certificates"},
Short: "Commands related to handling kubernetes certificates",
}
cmd.AddCommand(newCmdCertsRenewal())
return cmd
}
// newCmdCertsRenewal creates a new `cert renew` command.
func newCmdCertsRenewal() *cobra.Command {
cmd := &cobra.Command{
Use: "renew",
Short: "Renews certificates for a Kubernetes cluster",
Long: cmdutil.MacroCommandLongDescription,
RunE: cmdutil.SubCmdRunE("renew"),
}
cmd.AddCommand(getRenewSubCommands()...)
return cmd
}
type renewConfig struct {
cfgPath string
kubeconfigPath string
cfg kubeadmapiv1beta1.InitConfiguration
useAPI bool
useCSR bool
csrPath string
}
func getRenewSubCommands() []*cobra.Command {
cfg := &renewConfig{
kubeconfigPath: constants.GetAdminKubeConfigPath(),
}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(&cfg.cfg)
certTree, err := certsphase.GetDefaultCertList().AsMap().CertTree()
kubeadmutil.CheckErr(err)
cmdList := []*cobra.Command{}
funcList := []func(){}
for caCert, certs := range certTree {
// Don't offer to renew CAs; would cause serious consequences
for _, cert := range certs {
// get the cobra.Command skeleton for this command
cmd := generateRenewalCommand(cert, cfg)
// get the implementation of renewing this certificate
renewalFunc := generateRenewalFunction(cert, caCert, cfg)
// install the implementation into the command
cmd.Run = func(*cobra.Command, []string) { renewalFunc() }
cmdList = append(cmdList, cmd)
// Collect renewal functions for `renew all`
funcList = append(funcList, renewalFunc)
}
}
allCmd := &cobra.Command{
Use: "all",
Short: "renew all available certificates",
Long: allLongDesc,
Run: func(*cobra.Command, []string) {
for _, f := range funcList {
f()
}
},
}
addFlags(allCmd, cfg)
cmdList = append(cmdList, allCmd)
return cmdList
}
func addFlags(cmd *cobra.Command, cfg *renewConfig) {
options.AddConfigFlag(cmd.Flags(), &cfg.cfgPath)
options.AddCertificateDirFlag(cmd.Flags(), &cfg.cfg.CertificatesDir)
options.AddKubeConfigFlag(cmd.Flags(), &cfg.kubeconfigPath)
options.AddCSRFlag(cmd.Flags(), &cfg.useCSR)
options.AddCSRDirFlag(cmd.Flags(), &cfg.csrPath)
cmd.Flags().BoolVar(&cfg.useAPI, "use-api", cfg.useAPI, "Use the Kubernetes certificate API to renew certificates")
}
func generateRenewalFunction(cert *certsphase.KubeadmCert, caCert *certsphase.KubeadmCert, cfg *renewConfig) func() {
return func() {
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfg.cfgPath, &cfg.cfg)
kubeadmutil.CheckErr(err)
if cfg.useCSR {
path := cfg.csrPath
if path == "" {
path = cfg.cfg.CertificatesDir
}
err := certsphase.CreateCSR(cert, internalcfg, path)
kubeadmutil.CheckErr(err)
return
}
renewer, err := getRenewer(cfg, caCert.BaseName)
kubeadmutil.CheckErr(err)
err = renewal.RenewExistingCert(internalcfg.CertificatesDir, cert.BaseName, renewer)
kubeadmutil.CheckErr(err)
}
}
func generateRenewalCommand(cert *certsphase.KubeadmCert, cfg *renewConfig) *cobra.Command {
cmd := &cobra.Command{
Use: cert.Name,
Short: fmt.Sprintf("Generates the %s", cert.LongName),
Long: fmt.Sprintf(genericLongDesc, cert.LongName, cert.BaseName),
}
addFlags(cmd, cfg)
return cmd
}
func getRenewer(cfg *renewConfig, caCertBaseName string) (renewal.Interface, error) {
if cfg.useAPI {
kubeConfigPath := cmdutil.FindExistingKubeConfig(cfg.kubeconfigPath)
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigPath)
if err != nil {
return nil, err
}
return renewal.NewCertsAPIRenawal(client), nil
}
caCert, caKey, err := certsphase.LoadCertificateAuthority(cfg.cfg.CertificatesDir, caCertBaseName)
if err != nil {
return nil, err
}
return renewal.NewFileRenewal(caCert, caKey), nil
}

View File

@ -0,0 +1,235 @@
/*
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 alpha
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"math/big"
"os"
"strings"
"testing"
"time"
"github.com/spf13/cobra"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
certstestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs"
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
)
func TestCommandsGenerated(t *testing.T) {
expectedFlags := []string{
"cert-dir",
"config",
"use-api",
}
expectedCommands := []string{
"renew all",
"renew apiserver",
"renew apiserver-kubelet-client",
"renew apiserver-etcd-client",
"renew front-proxy-client",
"renew etcd-server",
"renew etcd-peer",
"renew etcd-healthcheck-client",
}
renewCmd := newCmdCertsRenewal()
fakeRoot := &cobra.Command{}
fakeRoot.AddCommand(renewCmd)
for _, cmdPath := range expectedCommands {
t.Run(cmdPath, func(t *testing.T) {
cmd, rem, _ := fakeRoot.Find(strings.Split(cmdPath, " "))
if cmd == nil || len(rem) != 0 {
t.Fatalf("couldn't locate command %q (%v)", cmdPath, rem)
}
for _, flag := range expectedFlags {
if cmd.Flags().Lookup(flag) == nil {
t.Errorf("couldn't find expected flag --%s", flag)
}
}
})
}
}
func TestRunRenewCommands(t *testing.T) {
tests := []struct {
command string
baseNames []string
caBaseNames []string
}{
{
command: "all",
baseNames: []string{
kubeadmconstants.APIServerCertAndKeyBaseName,
kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName,
kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName,
kubeadmconstants.FrontProxyClientCertAndKeyBaseName,
kubeadmconstants.EtcdServerCertAndKeyBaseName,
kubeadmconstants.EtcdPeerCertAndKeyBaseName,
kubeadmconstants.EtcdHealthcheckClientCertAndKeyBaseName,
},
caBaseNames: []string{
kubeadmconstants.CACertAndKeyBaseName,
kubeadmconstants.FrontProxyCACertAndKeyBaseName,
kubeadmconstants.EtcdCACertAndKeyBaseName,
},
},
{
command: "apiserver",
baseNames: []string{kubeadmconstants.APIServerCertAndKeyBaseName},
caBaseNames: []string{kubeadmconstants.CACertAndKeyBaseName},
},
{
command: "apiserver-kubelet-client",
baseNames: []string{kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName},
caBaseNames: []string{kubeadmconstants.CACertAndKeyBaseName},
},
{
command: "apiserver-etcd-client",
baseNames: []string{kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName},
caBaseNames: []string{kubeadmconstants.EtcdCACertAndKeyBaseName},
},
{
command: "front-proxy-client",
baseNames: []string{kubeadmconstants.FrontProxyClientCertAndKeyBaseName},
caBaseNames: []string{kubeadmconstants.FrontProxyCACertAndKeyBaseName},
},
{
command: "etcd-server",
baseNames: []string{kubeadmconstants.EtcdServerCertAndKeyBaseName},
caBaseNames: []string{kubeadmconstants.EtcdCACertAndKeyBaseName},
},
{
command: "etcd-peer",
baseNames: []string{kubeadmconstants.EtcdPeerCertAndKeyBaseName},
caBaseNames: []string{kubeadmconstants.EtcdCACertAndKeyBaseName},
},
{
command: "etcd-healthcheck-client",
baseNames: []string{kubeadmconstants.EtcdHealthcheckClientCertAndKeyBaseName},
caBaseNames: []string{kubeadmconstants.EtcdCACertAndKeyBaseName},
},
}
renewCmds := getRenewSubCommands()
for _, test := range tests {
t.Run(test.command, func(t *testing.T) {
tmpDir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpDir)
caCert, caKey := certstestutil.SetupCertificateAuthorithy(t)
for _, caBaseName := range test.caBaseNames {
if err := pkiutil.WriteCertAndKey(tmpDir, caBaseName, caCert, caKey); err != nil {
t.Fatalf("couldn't write out CA: %v", err)
}
}
certTmpl := x509.Certificate{
Subject: pkix.Name{
CommonName: "test-cert",
Organization: []string{"sig-cluster-lifecycle"},
},
DNSNames: []string{"test-domain.space"},
SerialNumber: new(big.Int).SetInt64(0),
NotBefore: time.Now().Add(-time.Hour * 24 * 365),
NotAfter: time.Now().Add(-time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
t.Fatalf("couldn't generate private key: %v", err)
}
certDERBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, key.Public(), caKey)
if err != nil {
t.Fatalf("couldn't generate private key: %v", err)
}
cert, err := x509.ParseCertificate(certDERBytes)
if err != nil {
t.Fatalf("couldn't generate private key: %v", err)
}
for _, baseName := range test.baseNames {
if err := pkiutil.WriteCertAndKey(tmpDir, baseName, cert, key); err != nil {
t.Fatalf("couldn't write out initial certificate")
}
}
cmdtestutil.RunSubCommand(t, renewCmds, test.command, fmt.Sprintf("--cert-dir=%s", tmpDir))
for _, baseName := range test.baseNames {
newCert, newKey, err := pkiutil.TryLoadCertAndKeyFromDisk(tmpDir, baseName)
if err != nil {
t.Fatalf("couldn't load renewed certificate: %v", err)
}
certstestutil.AssertCertificateIsSignedByCa(t, newCert, caCert)
pool := x509.NewCertPool()
pool.AddCert(caCert)
_, err = newCert.Verify(x509.VerifyOptions{
DNSName: "test-domain.space",
Roots: pool,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
})
if err != nil {
t.Errorf("couldn't verify renewed cert: %v", err)
}
pubKey, ok := newCert.PublicKey.(*rsa.PublicKey)
if !ok {
t.Errorf("unknown public key type %T", newCert.PublicKey)
} else if pubKey.N.Cmp(newKey.N) != 0 {
t.Error("private key does not match public key")
}
}
})
}
}
func TestRenewUsingCSR(t *testing.T) {
tmpDir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpDir)
cert := &certs.KubeadmCertEtcdServer
renewCmds := getRenewSubCommands()
cmdtestutil.RunSubCommand(t, renewCmds, cert.Name, "--csr-only", "--csr-dir="+tmpDir)
if _, _, err := pkiutil.TryLoadCSRAndKeyFromDisk(tmpDir, cert.BaseName); err != nil {
t.Fatalf("couldn't load certificate %q: %v", cert.BaseName, err)
}
}

View File

@ -0,0 +1,106 @@
/*
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 alpha
import (
"io"
"github.com/pkg/errors"
"github.com/spf13/cobra"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
kubeconfigLongDesc = normalizer.LongDesc(`
Kubeconfig file utilities.
` + cmdutil.AlphaDisclaimer)
userKubeconfigLongDesc = normalizer.LongDesc(`
Outputs a kubeconfig file for an additional user.
` + cmdutil.AlphaDisclaimer)
userKubeconfigExample = normalizer.Examples(`
# Outputs a kubeconfig file for an additional user named foo
kubeadm alpha kubeconfig user --client-name=foo
`)
)
// newCmdKubeConfigUtility returns main command for kubeconfig phase
func newCmdKubeConfigUtility(out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "kubeconfig",
Short: "Kubeconfig file utilities",
Long: kubeconfigLongDesc,
}
cmd.AddCommand(newCmdUserKubeConfig(out))
return cmd
}
// newCmdUserKubeConfig returns sub commands for kubeconfig phase
func newCmdUserKubeConfig(out io.Writer) *cobra.Command {
cfg := &kubeadmapiv1beta1.InitConfiguration{}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var token, clientName string
var organizations []string
// Creates the UX Command
cmd := &cobra.Command{
Use: "user",
Short: "Outputs a kubeconfig file for an additional user",
Long: userKubeconfigLongDesc,
Example: userKubeconfigExample,
Run: func(cmd *cobra.Command, args []string) {
if clientName == "" {
kubeadmutil.CheckErr(errors.New("missing required argument --client-name"))
}
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig("", cfg)
kubeadmutil.CheckErr(err)
// if the kubeconfig file for an additional user has to use a token, use it
if token != "" {
kubeadmutil.CheckErr(kubeconfigphase.WriteKubeConfigWithToken(out, internalcfg, clientName, token))
return
}
// Otherwise, write a kubeconfig file with a generate client cert
kubeadmutil.CheckErr(kubeconfigphase.WriteKubeConfigWithClientCert(out, internalcfg, clientName, organizations))
},
}
// Add flags to the command
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where certificates are stored")
cmd.Flags().StringVar(&cfg.LocalAPIEndpoint.AdvertiseAddress, "apiserver-advertise-address", cfg.LocalAPIEndpoint.AdvertiseAddress, "The IP address the API server is accessible on")
cmd.Flags().Int32Var(&cfg.LocalAPIEndpoint.BindPort, "apiserver-bind-port", cfg.LocalAPIEndpoint.BindPort, "The port the API server is accessible on")
cmd.Flags().StringVar(&token, "token", token, "The token that should be used as the authentication mechanism for this kubeconfig, instead of client certificates")
cmd.Flags().StringVar(&clientName, "client-name", clientName, "The name of user. It will be used as the CN if client certificates are created")
cmd.Flags().StringSliceVar(&organizations, "org", organizations, "The orgnizations of the client certificate. It will be used as the O if client certificates are created")
return cmd
}

View File

@ -0,0 +1,104 @@
/*
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 alpha
import (
"bytes"
"fmt"
"os"
"testing"
"k8s.io/client-go/tools/clientcmd"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
kubeconfigtestutil "k8s.io/kubernetes/cmd/kubeadm/test/kubeconfig"
)
func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
// Temporary folders for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// Adds a pki folder with a ca cert to the temp folder
pkidir := testutil.SetupPkiDirWithCertificateAuthorithy(t, tmpdir)
// Retrieves ca cert for assertions
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
if err != nil {
t.Fatalf("couldn't retrieve ca cert: %v", err)
}
commonFlags := []string{
"--apiserver-advertise-address=1.2.3.4",
"--apiserver-bind-port=1234",
"--client-name=myUser",
fmt.Sprintf("--cert-dir=%s", pkidir),
}
var tests = []struct {
command string
withClientCert bool
withToken bool
additionalFlags []string
}{
{ // Test user subCommand withClientCert
command: "user",
withClientCert: true,
},
{ // Test user subCommand withToken
withToken: true,
command: "user",
additionalFlags: []string{"--token=123456"},
},
}
for _, test := range tests {
buf := new(bytes.Buffer)
// Get subcommands working in the temporary directory
cmd := newCmdUserKubeConfig(buf)
// Execute the subcommand
allFlags := append(commonFlags, test.additionalFlags...)
cmd.SetArgs(allFlags)
if err := cmd.Execute(); err != nil {
t.Fatal("Could not execute subcommand")
}
// reads kubeconfig written to stdout
config, err := clientcmd.Load(buf.Bytes())
if err != nil {
t.Errorf("couldn't read kubeconfig file from buffer: %v", err)
continue
}
// checks that CLI flags are properly propagated
kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
if test.withClientCert {
// checks that kubeconfig files have expected client cert
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, "myUser")
}
if test.withToken {
// checks that kubeconfig files have expected token
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myUser", "123456")
}
}
}

View File

@ -0,0 +1,162 @@
/*
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 alpha
import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/version"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
utilsexec "k8s.io/utils/exec"
)
var (
kubeletConfigDownloadLongDesc = normalizer.LongDesc(`
Downloads the kubelet configuration from a ConfigMap of the form "kubelet-config-1.X" in the cluster,
where X is the minor version of the kubelet. Either kubeadm autodetects the kubelet version by exec-ing
"kubelet --version" or respects the --kubelet-version parameter.
` + cmdutil.AlphaDisclaimer)
kubeletConfigDownloadExample = normalizer.Examples(`
# Downloads the kubelet configuration from the ConfigMap in the cluster. Autodetects the kubelet version.
kubeadm alpha phase kubelet config download
# Downloads the kubelet configuration from the ConfigMap in the cluster. Uses a specific desired kubelet version.
kubeadm alpha phase kubelet config download --kubelet-version v1.12.0
`)
kubeletConfigEnableDynamicLongDesc = normalizer.LongDesc(`
Enables or updates dynamic kubelet configuration for a Node, against the kubelet-config-1.X ConfigMap in the cluster,
where X is the minor version of the desired kubelet version.
WARNING: This feature is still experimental, and disabled by default. Enable only if you know what you are doing, as it
may have surprising side-effects at this stage.
` + cmdutil.AlphaDisclaimer)
kubeletConfigEnableDynamicExample = normalizer.Examples(`
# Enables dynamic kubelet configuration for a Node.
kubeadm alpha phase kubelet enable-dynamic-config --node-name node-1 --kubelet-version v1.12.0
WARNING: This feature is still experimental, and disabled by default. Enable only if you know what you are doing, as it
may have surprising side-effects at this stage.
`)
)
// newCmdKubeletUtility returns command for `kubeadm phase kubelet`
func newCmdKubeletUtility() *cobra.Command {
cmd := &cobra.Command{
Use: "kubelet",
Short: "Commands related to handling the kubelet",
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(newCmdKubeletConfig())
return cmd
}
// newCmdKubeletConfig returns command for `kubeadm phase kubelet config`
func newCmdKubeletConfig() *cobra.Command {
cmd := &cobra.Command{
Use: "config",
Short: "Utilities for kubelet configuration",
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(newCmdKubeletConfigDownload())
cmd.AddCommand(newCmdKubeletConfigEnableDynamic())
return cmd
}
// newCmdKubeletConfigDownload calls cobra.Command for downloading the kubelet configuration from the kubelet-config-1.X ConfigMap in the cluster
func newCmdKubeletConfigDownload() *cobra.Command {
var kubeletVersionStr string
// TODO: Be smarter about this and be able to load multiple kubeconfig files in different orders of precedence
kubeConfigFile := constants.GetKubeletKubeConfigPath()
cmd := &cobra.Command{
Use: "download",
Short: "Downloads the kubelet configuration from the cluster ConfigMap kubelet-config-1.X, where X is the minor version of the kubelet.",
Long: kubeletConfigDownloadLongDesc,
Example: kubeletConfigDownloadExample,
Run: func(cmd *cobra.Command, args []string) {
kubeletVersion, err := getKubeletVersion(kubeletVersionStr)
kubeadmutil.CheckErr(err)
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
kubeadmutil.CheckErr(err)
err = kubeletphase.DownloadConfig(client, kubeletVersion, constants.KubeletRunDirectory)
kubeadmutil.CheckErr(err)
},
}
options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile)
cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet. Defaults to being autodetected from 'kubelet --version'.")
return cmd
}
func getKubeletVersion(kubeletVersionStr string) (*version.Version, error) {
if len(kubeletVersionStr) > 0 {
return version.ParseSemantic(kubeletVersionStr)
}
return preflight.GetKubeletVersion(utilsexec.New())
}
// newCmdKubeletConfigEnableDynamic calls cobra.Command for enabling dynamic kubelet configuration on node
// This feature is still in alpha and an experimental state
func newCmdKubeletConfigEnableDynamic() *cobra.Command {
var nodeName, kubeletVersionStr string
kubeConfigFile := constants.GetAdminKubeConfigPath()
cmd := &cobra.Command{
Use: "enable-dynamic",
Short: "EXPERIMENTAL: Enables or updates dynamic kubelet configuration for a Node",
Long: kubeletConfigEnableDynamicLongDesc,
Example: kubeletConfigEnableDynamicExample,
Run: func(cmd *cobra.Command, args []string) {
if len(nodeName) == 0 {
kubeadmutil.CheckErr(errors.New("The --node-name argument is required"))
}
if len(kubeletVersionStr) == 0 {
kubeadmutil.CheckErr(errors.New("The --kubelet-version argument is required"))
}
kubeletVersion, err := version.ParseSemantic(kubeletVersionStr)
kubeadmutil.CheckErr(err)
kubeConfigFile = cmdutil.FindExistingKubeConfig(kubeConfigFile)
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
kubeadmutil.CheckErr(err)
err = kubeletphase.EnableDynamicConfigForNode(client, nodeName, kubeletVersion)
kubeadmutil.CheckErr(err)
},
}
options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile)
cmd.Flags().StringVar(&nodeName, "node-name", nodeName, "Name of the node that should enable the dynamic kubelet configuration")
cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet")
return cmd
}

View File

@ -0,0 +1,103 @@
/*
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 alpha
import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
"k8s.io/kubernetes/pkg/util/normalizer"
utilsexec "k8s.io/utils/exec"
)
var (
nodePreflightLongDesc = normalizer.LongDesc(`
Run node pre-flight checks, functionally equivalent to what implemented by kubeadm join.
` + cmdutil.AlphaDisclaimer)
nodePreflightExample = normalizer.Examples(`
# Run node pre-flight checks.
kubeadm alpha preflight node
`)
errorMissingConfigFlag = errors.New("the --config flag is mandatory")
)
// newCmdPreFlightUtility calls cobra.Command for preflight checks
func newCmdPreFlightUtility() *cobra.Command {
cmd := &cobra.Command{
Use: "preflight",
Short: "Commands related to pre-flight checks",
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(newCmdPreFlightNode())
return cmd
}
// newCmdPreFlightNode calls cobra.Command for node preflight checks
func newCmdPreFlightNode() *cobra.Command {
var cfgPath string
var ignorePreflightErrors []string
cmd := &cobra.Command{
Use: "node",
Short: "Run node pre-flight checks",
Long: nodePreflightLongDesc,
Example: nodePreflightExample,
Run: func(cmd *cobra.Command, args []string) {
if len(cfgPath) == 0 {
kubeadmutil.CheckErr(errorMissingConfigFlag)
}
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors)
kubeadmutil.CheckErr(err)
cfg := &kubeadmapiv1beta1.JoinConfiguration{}
kubeadmscheme.Scheme.Default(cfg)
internalcfg, err := configutil.JoinConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
kubeadmutil.CheckErr(err)
if internalcfg.ControlPlane != nil {
err = configutil.VerifyAPIServerBindAddress(internalcfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress)
kubeadmutil.CheckErr(err)
}
fmt.Println("[preflight] running pre-flight checks")
err = preflight.RunJoinNodeChecks(utilsexec.New(), internalcfg, ignorePreflightErrorsSet)
kubeadmutil.CheckErr(err)
fmt.Println("[preflight] pre-flight checks passed")
},
}
options.AddConfigFlag(cmd.PersistentFlags(), &cfgPath)
options.AddIgnorePreflightErrorsFlag(cmd.PersistentFlags(), &ignorePreflightErrors)
return cmd
}

View File

@ -14,18 +14,22 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package phases
package alpha
import (
"os"
"bufio"
"errors"
"fmt"
"io"
"strings"
"time"
"github.com/spf13/cobra"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
@ -35,6 +39,9 @@ import (
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
"os"
"time"
)
var (
@ -46,16 +53,14 @@ var (
` + cmdutil.AlphaDisclaimer)
selfhostingExample = normalizer.Examples(`
# Converts a static Pod-hosted control plane into a self-hosted one,
# functionally equivalent to what generated by kubeadm init executed
# with --feature-gates=SelfHosting=true.
# Converts a static Pod-hosted control plane into a self-hosted one.
kubeadm alpha phase selfhosting convert-from-staticpods
kubeadm alpha phase self-hosting convert-from-staticpods
`)
)
// NewCmdSelfhosting returns the self-hosting Cobra command
func NewCmdSelfhosting() *cobra.Command {
func NewCmdSelfhosting(in io.Reader) *cobra.Command {
cmd := &cobra.Command{
Use: "selfhosting",
Aliases: []string{"selfhosted", "self-hosting"},
@ -63,28 +68,48 @@ func NewCmdSelfhosting() *cobra.Command {
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(getSelfhostingSubCommand())
cmd.AddCommand(getSelfhostingSubCommand(in))
return cmd
}
// getSelfhostingSubCommand returns sub commands for Selfhosting phase
func getSelfhostingSubCommand() *cobra.Command {
// getSelfhostingSubCommand returns sub commands for Self-hosting phase
func getSelfhostingSubCommand(in io.Reader) *cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
cfg := &kubeadmapiv1beta1.InitConfiguration{}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var cfgPath, kubeConfigFile, featureGatesString string
var cfgPath, featureGatesString string
forcePivot, certsInSecrets := false, false
kubeConfigFile := constants.GetAdminKubeConfigPath()
// Creates the UX Command
cmd := &cobra.Command{
Use: "convert-from-staticpods",
Use: "pivot",
Aliases: []string{"from-staticpods"},
Short: "Converts a static Pod-hosted control plane into a self-hosted one",
Long: selfhostingLongDesc,
Example: selfhostingExample,
Run: func(cmd *cobra.Command, args []string) {
var err error
if !forcePivot {
fmt.Println("WARNING: self-hosted clusters are not supported by kubeadm upgrade and by other kubeadm commands!")
fmt.Print("[pivot] are you sure you want to proceed? [y/n]: ")
s := bufio.NewScanner(in)
s.Scan()
err = s.Err()
kubeadmutil.CheckErr(err)
if strings.ToLower(s.Text()) != "y" {
kubeadmutil.CheckErr(errors.New("aborted pivot operation"))
}
}
fmt.Println("[pivot] pivoting cluster to self-hosted")
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
kubeadmutil.CheckErr(err)
}
@ -93,17 +118,22 @@ func getSelfhostingSubCommand() *cobra.Command {
kubeadmutil.CheckErr(err)
}
// Gets the Kubernetes client
kubeConfigFile = cmdutil.FindExistingKubeConfig(kubeConfigFile)
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
kubeadmutil.CheckErr(err)
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
phases.SetKubernetesVersion(cfg)
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
kubeadmutil.CheckErr(err)
// Gets the kubernetes client
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
kubeadmutil.CheckErr(err)
// Converts the Static Pod-hosted control plane into a self-hosted one
waiter := apiclient.NewKubeWaiter(client, 2*time.Minute, os.Stdout)
err = selfhosting.CreateSelfHostedControlPlane(constants.GetStaticPodDirectory(), constants.KubernetesDir, internalcfg, client, waiter, false)
err = selfhosting.CreateSelfHostedControlPlane(constants.GetStaticPodDirectory(), constants.KubernetesDir, internalcfg, client, waiter, false, certsInSecrets)
kubeadmutil.CheckErr(err)
},
}
@ -112,12 +142,19 @@ func getSelfhostingSubCommand() *cobra.Command {
// flags bound to the configuration object
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, `The path where certificates are stored`)
cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental")
cmd.Flags().StringVar(&featureGatesString, "feature-gates", featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+
"Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n"))
cmd.Flags().BoolVarP(
&certsInSecrets, "store-certs-in-secrets", "s",
false, "Enable storing certs in secrets")
cmd.Flags().BoolVarP(
&forcePivot, "force", "f", false,
"Pivot the cluster without prompting for confirmation",
)
// flags that are not bound to the configuration object
// Note: All flags that are not bound to the cfg object should be whitelisted in cmd/kubeadm/app/apis/kubeadm/validation/validation.go
cmd.Flags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster")
options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile)
return cmd
}

View File

@ -21,50 +21,61 @@ import (
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases"
"github.com/spf13/pflag"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/alpha"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
// Register the kubeadm configuration types because CLI flag generation
// depends on the generated defaults.
)
// NewKubeadmCommand return cobra.Command to run kubeadm command
// NewKubeadmCommand returns cobra.Command to run kubeadm command
func NewKubeadmCommand(in io.Reader, out, err io.Writer) *cobra.Command {
var rootfsPath string
cmds := &cobra.Command{
Use: "kubeadm",
Short: "kubeadm: easily bootstrap a secure Kubernetes cluster",
Long: dedent.Dedent(`
kubeadm: easily bootstrap a secure Kubernetes cluster.
┌──────────────────────────────────────────────────────────┐
│ KUBEADM IS CURRENTLY IN BETA
│ KUBEADM
│ Easily bootstrap a secure Kubernetes cluster │
│ │
But please, try it out and give us feedback at: │
Please give us feedback at:
│ https://github.com/kubernetes/kubeadm/issues │
│ and at-mention @kubernetes/sig-cluster-lifecycle-bugs │
│ or @kubernetes/sig-cluster-lifecycle-feature-requests │
└──────────────────────────────────────────────────────────┘
Example usage:
Create a two-machine cluster with one master (which controls the cluster),
and one node (where your workloads, like Pods and Deployments run).
Create a two-machine cluster with one control-plane node
(which controls the cluster), and one worker node
(where your workloads, like Pods and Deployments run).
┌──────────────────────────────────────────────────────────┐
│ On the first machine: │
├──────────────────────────────────────────────────────────┤
master# kubeadm init
control-plane# kubeadm init │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ On the second machine: │
├──────────────────────────────────────────────────────────┤
node# kubeadm join <arguments-returned-from-init>
worker# kubeadm join <arguments-returned-from-init> │
└──────────────────────────────────────────────────────────┘
You can then repeat the second step on as many other machines as you like.
`),
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if rootfsPath != "" {
if err := kubeadmutil.Chroot(rootfsPath); err != nil {
return err
}
}
return nil
},
}
cmds.ResetFlags()
@ -77,14 +88,17 @@ func NewKubeadmCommand(in io.Reader, out, err io.Writer) *cobra.Command {
cmds.AddCommand(NewCmdVersion(out))
cmds.AddCommand(NewCmdToken(out, err))
cmds.AddCommand(upgrade.NewCmdUpgrade(out))
cmds.AddCommand(alpha.NewCmdAlpha(in, out))
// Wrap not yet fully supported commands in an alpha subcommand
experimentalCmd := &cobra.Command{
Use: "alpha",
Short: "Experimental sub-commands not yet fully functional.",
}
experimentalCmd.AddCommand(phases.NewCmdPhase(out))
cmds.AddCommand(experimentalCmd)
AddKubeadmOtherFlags(cmds.PersistentFlags(), &rootfsPath)
return cmds
}
// AddKubeadmOtherFlags adds flags that are not bound to a configuration file to the given flagset
func AddKubeadmOtherFlags(flagSet *pflag.FlagSet, rootfsPath *string) {
flagSet.StringVar(
rootfsPath, "rootfs", *rootfsPath,
"[EXPERIMENTAL] The path to the 'real' host root filesystem.",
)
}

View File

@ -18,15 +18,14 @@ package cmd
import (
"bytes"
"fmt"
"io"
"github.com/golang/glog"
"github.com/pkg/errors"
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
"k8s.io/klog"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
)
const defaultBoilerPlate = `
@ -103,7 +102,7 @@ func GetSupportedShells() []string {
func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command {
cmd := &cobra.Command{
Use: "completion SHELL",
Short: i18n.T("Output shell completion code for the specified shell (bash or zsh)."),
Short: "Output shell completion code for the specified shell (bash or zsh).",
Long: completionLong,
Example: completionExample,
Run: func(cmd *cobra.Command, args []string) {
@ -119,14 +118,14 @@ func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command {
// RunCompletion checks given arguments and executes command
func RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("shell not specified")
return errors.New("shell not specified")
}
if len(args) > 1 {
return fmt.Errorf("too many arguments. expected only the shell type")
return errors.New("too many arguments. expected only the shell type")
}
run, found := completionShells[args[0]]
if !found {
return fmt.Errorf("unsupported shell type %q", args[0])
return errors.Errorf("unsupported shell type %q", args[0])
}
if len(boilerPlate) == 0 {
@ -139,7 +138,7 @@ func RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args [
}
func runCompletionBash(out io.Writer, kubeadm *cobra.Command) error {
glog.V(1).Infoln("[completion] writing completion code for Bash")
klog.V(1).Infoln("[completion] writing completion code for Bash")
return kubeadm.GenBashCompletion(out)
}
@ -285,12 +284,12 @@ __kubeadm_convert_bash_to_zsh() {
-e "s/\\\$(type${RWORD}/\$(__kubeadm_type/g" \
<<'BASH_COMPLETION_EOF'
`
glog.V(1).Infoln("[completion] writing completion code for Zsh")
klog.V(1).Infoln("[completion] writing completion code for Zsh")
out.Write([]byte(zshInitialization))
buf := new(bytes.Buffer)
kubeadm.GenBashCompletion(buf)
glog.V(1).Infoln("[completion] writing completion code for Bash")
klog.V(1).Infoln("[completion] writing completion code for Bash")
out.Write(buf.Bytes())
zshTail := `

View File

@ -17,23 +17,28 @@ limitations under the License.
package cmd
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"strings"
"github.com/golang/glog"
"github.com/pkg/errors"
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"k8s.io/klog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientset "k8s.io/client-go/kubernetes"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
kubeadmapiv1alpha3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
phaseutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
"k8s.io/kubernetes/cmd/kubeadm/app/images"
@ -41,20 +46,14 @@ import (
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
utilruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime"
utilsexec "k8s.io/utils/exec"
)
const (
// TODO: Figure out how to get these constants from the API machinery
masterConfig = "MasterConfiguration"
nodeConfig = "NodeConfiguration"
)
var (
availableAPIObjects = []string{masterConfig, nodeConfig}
// sillyToken is only set statically to make kubeadm not randomize the token on every run
sillyToken = kubeadmapiv1alpha2.BootstrapToken{
Token: &kubeadmapiv1alpha2.BootstrapTokenString{
// placeholderToken is only set statically to make kubeadm not randomize the token on every run
placeholderToken = kubeadmapiv1beta1.BootstrapToken{
Token: &kubeadmapiv1beta1.BootstrapTokenString{
ID: "abcdef",
Secret: "0123456789abcdef",
},
@ -63,8 +62,8 @@ var (
// NewCmdConfig returns cobra.Command for "kubeadm config" command
func NewCmdConfig(out io.Writer) *cobra.Command {
kubeConfigFile := constants.GetAdminKubeConfigPath()
var kubeConfigFile string
cmd := &cobra.Command{
Use: "config",
Short: "Manage configuration for a kubeadm cluster persisted in a ConfigMap in the cluster.",
@ -73,7 +72,7 @@ func NewCmdConfig(out io.Writer) *cobra.Command {
cluster. kubeadm CLI v1.8.0+ automatically creates this ConfigMap with the config used with 'kubeadm init', but if you
initialized your cluster using kubeadm v1.7.x or lower, you must use the 'config upload' command to create this
ConfigMap. This is required so that 'kubeadm upgrade' can configure your upgraded cluster correctly.
`), metav1.NamespaceSystem, constants.MasterConfigurationConfigMap),
`), metav1.NamespaceSystem, constants.KubeadmConfigConfigMap),
// Without this callback, if a user runs just the "upload"
// command without a subcommand, or with an invalid subcommand,
// cobra will print usage information, but still exit cleanly.
@ -82,8 +81,10 @@ func NewCmdConfig(out io.Writer) *cobra.Command {
RunE: cmdutil.SubCmdRunE("config"),
}
cmd.PersistentFlags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster.")
options.AddKubeConfigFlag(cmd.PersistentFlags(), &kubeConfigFile)
kubeConfigFile = cmdutil.FindExistingKubeConfig(kubeConfigFile)
cmd.AddCommand(NewCmdConfigPrint(out))
cmd.AddCommand(NewCmdConfigPrintDefault(out))
cmd.AddCommand(NewCmdConfigMigrate(out))
cmd.AddCommand(NewCmdConfigUpload(out, &kubeConfigFile))
@ -92,6 +93,63 @@ func NewCmdConfig(out io.Writer) *cobra.Command {
return cmd
}
// NewCmdConfigPrint returns cobra.Command for "kubeadm config print" command
func NewCmdConfigPrint(out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "print",
Short: "Print configuration",
Long: "This command prints configurations for subcommands provided.",
RunE: cmdutil.SubCmdRunE("print"),
}
cmd.AddCommand(NewCmdConfigPrintInitDefaults(out))
cmd.AddCommand(NewCmdConfigPrintJoinDefaults(out))
return cmd
}
// NewCmdConfigPrintInitDefaults returns cobra.Command for "kubeadm config print init-defaults" command
func NewCmdConfigPrintInitDefaults(out io.Writer) *cobra.Command {
return newCmdConfigPrintActionDefaults(out, "init", getDefaultInitConfigBytes)
}
// NewCmdConfigPrintJoinDefaults returns cobra.Command for "kubeadm config print join-defaults" command
func NewCmdConfigPrintJoinDefaults(out io.Writer) *cobra.Command {
return newCmdConfigPrintActionDefaults(out, "join", getDefaultNodeConfigBytes)
}
func newCmdConfigPrintActionDefaults(out io.Writer, action string, configBytesProc func() ([]byte, error)) *cobra.Command {
componentConfigs := []string{}
cmd := &cobra.Command{
Use: fmt.Sprintf("%s-defaults", action),
Short: fmt.Sprintf("Print default %s configuration, that can be used for 'kubeadm %s'", action, action),
Long: fmt.Sprintf(dedent.Dedent(`
This command prints objects such as the default %s configuration that is used for 'kubeadm %s'.
Note that sensitive values like the Bootstrap Token fields are replaced with placeholder values like %q in order to pass validation but
not perform the real computation for creating a token.
`), action, action, placeholderToken),
Run: func(cmd *cobra.Command, args []string) {
runConfigPrintActionDefaults(out, componentConfigs, configBytesProc)
},
}
cmd.Flags().StringSliceVar(&componentConfigs, "component-configs", componentConfigs,
fmt.Sprintf("A comma-separated list for component config API objects to print the default values for. Available values: %v. If this flag is not set, no component configs will be printed.", getSupportedComponentConfigAPIObjects()))
return cmd
}
func runConfigPrintActionDefaults(out io.Writer, componentConfigs []string, configBytesProc func() ([]byte, error)) {
initialConfig, err := configBytesProc()
kubeadmutil.CheckErr(err)
allBytes := [][]byte{initialConfig}
for _, componentConfig := range componentConfigs {
cfgBytes, err := getDefaultComponentConfigAPIObjectBytes(componentConfig)
kubeadmutil.CheckErr(err)
allBytes = append(allBytes, cfgBytes)
}
fmt.Fprint(out, string(bytes.Join(allBytes, []byte(constants.YAMLDocumentSeparator))))
}
// NewCmdConfigPrintDefault returns cobra.Command for "kubeadm config print-default" command
func NewCmdConfigPrintDefault(out io.Writer) *cobra.Command {
apiObjects := []string{}
@ -100,54 +158,149 @@ func NewCmdConfigPrintDefault(out io.Writer) *cobra.Command {
Aliases: []string{"print-defaults"},
Short: "Print the default values for a kubeadm configuration object.",
Long: fmt.Sprintf(dedent.Dedent(`
This command prints the default MasterConfiguration object that is used for 'kubeadm init' and 'kubeadm upgrade',
and the default NodeConfiguration object that is used for 'kubeadm join'.
This command prints objects such as the default InitConfiguration that is used for 'kubeadm init' and 'kubeadm upgrade',
and the default JoinConfiguration object that is used for 'kubeadm join'.
Note that sensitive values like the Bootstrap Token fields are replaced with silly values like %q in order to pass validation but
For documentation visit: https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha3
Note that sensitive values like the Bootstrap Token fields are replaced with placeholder values like %q in order to pass validation but
not perform the real computation for creating a token.
`), sillyToken),
`), placeholderToken),
Deprecated: "Please, use `kubeadm config print` instead.",
Run: func(cmd *cobra.Command, args []string) {
if len(apiObjects) == 0 {
apiObjects = availableAPIObjects
apiObjects = getSupportedAPIObjects()
}
for i, apiObject := range apiObjects {
if i > 0 {
fmt.Fprintln(out, "---")
}
allBytes := [][]byte{}
for _, apiObject := range apiObjects {
cfgBytes, err := getDefaultAPIObjectBytes(apiObject)
kubeadmutil.CheckErr(err)
// Print the API object byte array
fmt.Fprintf(out, "%s", cfgBytes)
allBytes = append(allBytes, cfgBytes)
}
fmt.Fprint(out, string(bytes.Join(allBytes, []byte(constants.YAMLDocumentSeparator))))
},
}
cmd.Flags().StringSliceVar(&apiObjects, "api-objects", apiObjects,
fmt.Sprintf("A comma-separated list for API objects to print the default values for. Available values: %v. This flag unset means 'print all known objects'", availableAPIObjects))
fmt.Sprintf("A comma-separated list for API objects to print the default values for. Available values: %v. This flag unset means 'print all known objects'", getAllAPIObjectNames()))
return cmd
}
func getDefaultComponentConfigAPIObjectBytes(apiObject string) ([]byte, error) {
registration, ok := componentconfigs.Known[componentconfigs.RegistrationKind(apiObject)]
if !ok {
return []byte{}, errors.Errorf("--component-configs needs to contain some of %v", getSupportedComponentConfigAPIObjects())
}
return getDefaultComponentConfigBytes(registration)
}
func getDefaultAPIObjectBytes(apiObject string) ([]byte, error) {
if apiObject == masterConfig {
switch apiObject {
case constants.InitConfigurationKind:
return getDefaultInitConfigBytesByKind(constants.InitConfigurationKind)
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1alpha2.MasterConfiguration{
BootstrapTokens: []kubeadmapiv1alpha2.BootstrapToken{sillyToken},
})
kubeadmutil.CheckErr(err)
case constants.ClusterConfigurationKind:
return getDefaultInitConfigBytesByKind(constants.ClusterConfigurationKind)
return kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs)
case constants.JoinConfigurationKind:
return getDefaultNodeConfigBytes()
default:
// Is this a component config?
registration, ok := componentconfigs.Known[componentconfigs.RegistrationKind(apiObject)]
if !ok {
return []byte{}, errors.Errorf("--api-object needs to be one of %v", getAllAPIObjectNames())
}
return getDefaultComponentConfigBytes(registration)
}
if apiObject == nodeConfig {
internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1alpha2.NodeConfiguration{
Token: sillyToken.Token.String(),
DiscoveryTokenAPIServers: []string{"kube-apiserver:6443"},
DiscoveryTokenUnsafeSkipCAVerification: true,
})
kubeadmutil.CheckErr(err)
}
return kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs)
// getSupportedComponentConfigAPIObjects returns all currently supported component config API object names
func getSupportedComponentConfigAPIObjects() []string {
objects := []string{}
for componentType := range componentconfigs.Known {
objects = append(objects, string(componentType))
}
return []byte{}, fmt.Errorf("--api-object needs to be one of %v", availableAPIObjects)
return objects
}
// getSupportedAPIObjects returns all currently supported API object names
func getSupportedAPIObjects() []string {
baseObjects := []string{constants.InitConfigurationKind, constants.ClusterConfigurationKind, constants.JoinConfigurationKind}
objects := getSupportedComponentConfigAPIObjects()
objects = append(objects, baseObjects...)
return objects
}
// getAllAPIObjectNames returns currently supported API object names and their historical aliases
// NB. currently there is no historical supported API objects, but we keep this function for future changes
func getAllAPIObjectNames() []string {
historicAPIObjectAliases := []string{}
objects := getSupportedAPIObjects()
objects = append(objects, historicAPIObjectAliases...)
return objects
}
func getDefaultedInitConfig() (*kubeadmapi.InitConfiguration, error) {
return configutil.ConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1beta1.InitConfiguration{
// TODO: Probably move to getDefaultedClusterConfig?
LocalAPIEndpoint: kubeadmapiv1beta1.APIEndpoint{AdvertiseAddress: "1.2.3.4"},
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
KubernetesVersion: fmt.Sprintf("v1.%d.0", constants.MinimumControlPlaneVersion.Minor()+1),
},
BootstrapTokens: []kubeadmapiv1beta1.BootstrapToken{placeholderToken},
})
}
func getDefaultInitConfigBytes() ([]byte, error) {
internalcfg, err := getDefaultedInitConfig()
if err != nil {
return []byte{}, err
}
return configutil.MarshalKubeadmConfigObject(internalcfg)
}
func getDefaultInitConfigBytesByKind(kind string) ([]byte, error) {
b, err := getDefaultInitConfigBytes()
if err != nil {
return []byte{}, err
}
gvkmap, err := kubeadmutil.SplitYAMLDocuments(b)
if err != nil {
return []byte{}, err
}
return gvkmap[kubeadmapiv1beta1.SchemeGroupVersion.WithKind(kind)], nil
}
func getDefaultNodeConfigBytes() ([]byte, error) {
internalcfg, err := configutil.JoinConfigFileAndDefaultsToInternalConfig("", &kubeadmapiv1beta1.JoinConfiguration{
Discovery: kubeadmapiv1beta1.Discovery{
BootstrapToken: &kubeadmapiv1beta1.BootstrapTokenDiscovery{
Token: placeholderToken.Token.String(),
APIServerEndpoint: "kube-apiserver:6443",
UnsafeSkipCAVerification: true, // TODO: UnsafeSkipCAVerification: true needs to be set for validation to pass, but shouldn't be recommended as the default
},
},
})
if err != nil {
return []byte{}, err
}
return configutil.MarshalKubeadmConfigObject(internalcfg)
}
func getDefaultComponentConfigBytes(registration componentconfigs.Registration) ([]byte, error) {
defaultedInitConfig, err := getDefaultedInitConfig()
if err != nil {
return []byte{}, err
}
realobj, ok := registration.GetFromInternalConfig(&defaultedInitConfig.ClusterConfiguration)
if !ok {
return []byte{}, errors.New("GetFromInternalConfig failed")
}
return registration.Marshal(realobj)
}
// NewCmdConfigMigrate returns cobra.Command for "kubeadm config migrate" command
@ -170,42 +323,20 @@ func NewCmdConfigMigrate(out io.Writer) *cobra.Command {
In other words, the output of this command is what kubeadm actually would read internally if you
submitted this file to "kubeadm init"
`), kubeadmapiv1alpha2.SchemeGroupVersion.String(), kubeadmapiv1alpha1.SchemeGroupVersion.String(), kubeadmapiv1alpha2.SchemeGroupVersion.String()),
`), kubeadmapiv1alpha3.SchemeGroupVersion.String(), kubeadmapiv1beta1.SchemeGroupVersion.String(), kubeadmapiv1beta1.SchemeGroupVersion.String()),
Run: func(cmd *cobra.Command, args []string) {
if len(oldCfgPath) == 0 {
kubeadmutil.CheckErr(fmt.Errorf("The --old-config flag is mandatory"))
kubeadmutil.CheckErr(errors.New("The --old-config flag is mandatory"))
}
b, err := ioutil.ReadFile(oldCfgPath)
outputBytes, err := configutil.MigrateOldConfigFromFile(oldCfgPath)
kubeadmutil.CheckErr(err)
var outputBytes []byte
gvk, err := kubeadmutil.GroupVersionKindFromBytes(b, kubeadmscheme.Codecs)
kubeadmutil.CheckErr(err)
switch gvk.Kind {
case masterConfig:
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(oldCfgPath, &kubeadmapiv1alpha2.MasterConfiguration{})
kubeadmutil.CheckErr(err)
outputBytes, err = kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs)
kubeadmutil.CheckErr(err)
case nodeConfig:
internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig(oldCfgPath, &kubeadmapiv1alpha2.NodeConfiguration{})
kubeadmutil.CheckErr(err)
// TODO: In the future we might not want to duplicate these two lines of code for every case here.
outputBytes, err = kubeadmutil.MarshalToYamlForCodecs(internalcfg, kubeadmapiv1alpha2.SchemeGroupVersion, kubeadmscheme.Codecs)
kubeadmutil.CheckErr(err)
default:
kubeadmutil.CheckErr(fmt.Errorf("Didn't recognize type with GroupVersionKind: %v", gvk))
}
if newCfgPath == "" {
fmt.Fprint(out, string(outputBytes))
} else {
if err := ioutil.WriteFile(newCfgPath, outputBytes, 0644); err != nil {
kubeadmutil.CheckErr(fmt.Errorf("failed to write the new configuration to the file %q: %v", newCfgPath, err))
kubeadmutil.CheckErr(errors.Wrapf(err, "failed to write the new configuration to the file %q", newCfgPath))
}
}
},
@ -237,9 +368,9 @@ func NewCmdConfigView(out io.Writer, kubeConfigFile *string) *cobra.Command {
Using this command, you can view the ConfigMap in the cluster where the configuration for kubeadm is located.
The configuration is located in the %q namespace in the %q ConfigMap.
`), metav1.NamespaceSystem, constants.MasterConfigurationConfigMap),
`), metav1.NamespaceSystem, constants.KubeadmConfigConfigMap),
Run: func(cmd *cobra.Command, args []string) {
glog.V(1).Infoln("[config] retrieving ClientSet from file")
klog.V(1).Infoln("[config] retrieving ClientSet from file")
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
kubeadmutil.CheckErr(err)
@ -249,7 +380,7 @@ func NewCmdConfigView(out io.Writer, kubeConfigFile *string) *cobra.Command {
}
}
// NewCmdConfigUploadFromFile verifies given kubernetes config file and returns cobra.Command for
// NewCmdConfigUploadFromFile verifies given Kubernetes config file and returns cobra.Command for
// "kubeadm config upload from-file" command
func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Command {
var cfgPath string
@ -262,21 +393,21 @@ func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Co
same config file before upgrading to v1.8 using 'kubeadm upgrade'.
The configuration is located in the %q namespace in the %q ConfigMap.
`), metav1.NamespaceSystem, constants.MasterConfigurationConfigMap),
`), metav1.NamespaceSystem, constants.KubeadmConfigConfigMap),
Run: func(cmd *cobra.Command, args []string) {
if len(cfgPath) == 0 {
kubeadmutil.CheckErr(fmt.Errorf("The --config flag is mandatory"))
kubeadmutil.CheckErr(errors.New("The --config flag is mandatory"))
}
glog.V(1).Infoln("[config] retrieving ClientSet from file")
klog.V(1).Infoln("[config] retrieving ClientSet from file")
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
kubeadmutil.CheckErr(err)
// The default configuration is empty; everything should come from the file on disk
glog.V(1).Infoln("[config] creating empty default configuration")
defaultcfg := &kubeadmapiv1alpha2.MasterConfiguration{}
klog.V(1).Infoln("[config] creating empty default configuration")
defaultcfg := &kubeadmapiv1beta1.InitConfiguration{}
// Upload the configuration using the file; don't care about the defaultcfg really
glog.V(1).Infof("[config] uploading configuration")
klog.V(1).Infof("[config] uploading configuration")
err = uploadConfiguration(client, cfgPath, defaultcfg)
kubeadmutil.CheckErr(err)
},
@ -287,7 +418,7 @@ func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Co
// NewCmdConfigUploadFromFlags returns cobra.Command for "kubeadm config upload from-flags" command
func NewCmdConfigUploadFromFlags(out io.Writer, kubeConfigFile *string) *cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
cfg := &kubeadmapiv1beta1.InitConfiguration{}
kubeadmscheme.Scheme.Default(cfg)
var featureGatesString string
@ -301,20 +432,20 @@ func NewCmdConfigUploadFromFlags(out io.Writer, kubeConfigFile *string) *cobra.C
same flags before upgrading to v1.8 using 'kubeadm upgrade'.
The configuration is located in the %q namespace in the %q ConfigMap.
`), metav1.NamespaceSystem, constants.MasterConfigurationConfigMap),
`), metav1.NamespaceSystem, constants.KubeadmConfigConfigMap),
Run: func(cmd *cobra.Command, args []string) {
var err error
glog.V(1).Infoln("[config] creating new FeatureGates")
klog.V(1).Infoln("[config] creating new FeatureGates")
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
kubeadmutil.CheckErr(err)
}
glog.V(1).Infoln("[config] retrieving ClientSet from file")
klog.V(1).Infoln("[config] retrieving ClientSet from file")
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
kubeadmutil.CheckErr(err)
// Default both statically and dynamically, convert to internal API type, and validate everything
// The cfgPath argument is unset here as we shouldn't load a config file from disk, just go with cfg
glog.V(1).Infof("[config] uploading configuration")
klog.V(1).Infof("[config] uploading configuration")
err = uploadConfiguration(client, "", cfg)
kubeadmutil.CheckErr(err)
},
@ -326,22 +457,25 @@ func NewCmdConfigUploadFromFlags(out io.Writer, kubeConfigFile *string) *cobra.C
// RunConfigView gets the configuration persisted in the cluster
func RunConfigView(out io.Writer, client clientset.Interface) error {
glog.V(1).Infoln("[config] getting the cluster configuration")
cfgConfigMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(constants.MasterConfigurationConfigMap, metav1.GetOptions{})
klog.V(1).Infoln("[config] getting the cluster configuration")
cfgConfigMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(constants.KubeadmConfigConfigMap, metav1.GetOptions{})
if err != nil {
return err
}
// No need to append \n as that already exists in the ConfigMap
fmt.Fprintf(out, "%s", cfgConfigMap.Data[constants.MasterConfigurationConfigMapKey])
fmt.Fprintf(out, "%s", cfgConfigMap.Data[constants.ClusterConfigurationConfigMapKey])
return nil
}
// uploadConfiguration handles the uploading of the configuration internally
func uploadConfiguration(client clientset.Interface, cfgPath string, defaultcfg *kubeadmapiv1alpha2.MasterConfiguration) error {
func uploadConfiguration(client clientset.Interface, cfgPath string, defaultcfg *kubeadmapiv1beta1.InitConfiguration) error {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
phaseutil.SetKubernetesVersion(defaultcfg)
// Default both statically and dynamically, convert to internal API type, and validate everything
// First argument is unset here as we shouldn't load a config file from disk
glog.V(1).Infoln("[config] converting to internal API type")
klog.V(1).Infoln("[config] converting to internal API type")
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, defaultcfg)
if err != nil {
return err
@ -365,8 +499,8 @@ func NewCmdConfigImages(out io.Writer) *cobra.Command {
// NewCmdConfigImagesPull returns the `kubeadm config images pull` command
func NewCmdConfigImagesPull() *cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
kubeadmscheme.Scheme.Default(cfg)
externalcfg := &kubeadmapiv1beta1.InitConfiguration{}
kubeadmscheme.Scheme.Default(externalcfg)
var cfgPath, featureGatesString string
var err error
@ -374,41 +508,41 @@ func NewCmdConfigImagesPull() *cobra.Command {
Use: "pull",
Short: "Pull images used by kubeadm.",
Run: func(_ *cobra.Command, _ []string) {
cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString)
externalcfg.ClusterConfiguration.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString)
kubeadmutil.CheckErr(err)
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, externalcfg)
kubeadmutil.CheckErr(err)
puller, err := images.NewCRInterfacer(utilsexec.New(), internalcfg.GetCRISocket())
containerRuntime, err := utilruntime.NewContainerRuntime(utilsexec.New(), internalcfg.GetCRISocket())
kubeadmutil.CheckErr(err)
imagesPull := NewImagesPull(puller, images.GetAllImages(internalcfg))
imagesPull := NewImagesPull(containerRuntime, images.GetAllImages(&internalcfg.ClusterConfiguration))
kubeadmutil.CheckErr(imagesPull.PullAll())
},
}
AddImagesCommonConfigFlags(cmd.PersistentFlags(), cfg, &cfgPath, &featureGatesString)
AddImagesPullFlags(cmd.PersistentFlags(), cfg)
AddImagesCommonConfigFlags(cmd.PersistentFlags(), externalcfg, &cfgPath, &featureGatesString)
AddImagesPullFlags(cmd.PersistentFlags(), externalcfg)
return cmd
}
// ImagesPull is the struct used to hold information relating to image pulling
type ImagesPull struct {
puller images.Puller
images []string
runtime utilruntime.ContainerRuntime
images []string
}
// NewImagesPull initializes and returns the `kubeadm config images pull` command
func NewImagesPull(puller images.Puller, images []string) *ImagesPull {
func NewImagesPull(runtime utilruntime.ContainerRuntime, images []string) *ImagesPull {
return &ImagesPull{
puller: puller,
images: images,
runtime: runtime,
images: images,
}
}
// PullAll pulls all images that the ImagesPull knows about
func (ip *ImagesPull) PullAll() error {
for _, image := range ip.images {
if err := ip.puller.Pull(image); err != nil {
return fmt.Errorf("failed to pull image %q: %v", image, err)
if err := ip.runtime.PullImage(image); err != nil {
return errors.Wrapf(err, "failed to pull image %q", image)
}
fmt.Printf("[config/images] Pulled %s\n", image)
}
@ -417,53 +551,52 @@ func (ip *ImagesPull) PullAll() error {
// NewCmdConfigImagesList returns the "kubeadm config images list" command
func NewCmdConfigImagesList(out io.Writer, mockK8sVersion *string) *cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
kubeadmscheme.Scheme.Default(cfg)
externalcfg := &kubeadmapiv1beta1.InitConfiguration{}
kubeadmscheme.Scheme.Default(externalcfg)
var cfgPath, featureGatesString string
var err error
// This just sets the kubernetes version for unit testing so kubeadm won't try to
// This just sets the Kubernetes version for unit testing so kubeadm won't try to
// lookup the latest release from the internet.
if mockK8sVersion != nil {
cfg.KubernetesVersion = *mockK8sVersion
externalcfg.KubernetesVersion = *mockK8sVersion
}
cmd := &cobra.Command{
Use: "list",
Short: "Print a list of images kubeadm will use. The configuration file is used in case any images or image repositories are customized.",
Run: func(_ *cobra.Command, _ []string) {
cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString)
externalcfg.ClusterConfiguration.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString)
kubeadmutil.CheckErr(err)
imagesList, err := NewImagesList(cfgPath, cfg)
imagesList, err := NewImagesList(cfgPath, externalcfg)
kubeadmutil.CheckErr(err)
kubeadmutil.CheckErr(imagesList.Run(out))
},
}
AddImagesCommonConfigFlags(cmd.PersistentFlags(), cfg, &cfgPath, &featureGatesString)
AddImagesCommonConfigFlags(cmd.PersistentFlags(), externalcfg, &cfgPath, &featureGatesString)
return cmd
}
// NewImagesList returns the underlying struct for the "kubeadm config images list" command
func NewImagesList(cfgPath string, cfg *kubeadmapiv1alpha2.MasterConfiguration) (*ImagesList, error) {
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
func NewImagesList(cfgPath string, cfg *kubeadmapiv1beta1.InitConfiguration) (*ImagesList, error) {
initcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
if err != nil {
return nil, fmt.Errorf("could not convert cfg to an internal cfg: %v", err)
return nil, errors.Wrap(err, "could not convert cfg to an internal cfg")
}
return &ImagesList{
cfg: internalcfg,
cfg: initcfg,
}, nil
}
// ImagesList defines the struct used for "kubeadm config images list"
type ImagesList struct {
cfg *kubeadmapi.MasterConfiguration
cfg *kubeadmapi.InitConfiguration
}
// Run runs the images command and writes the result to the io.Writer passed in
func (i *ImagesList) Run(out io.Writer) error {
imgs := images.GetAllImages(i.cfg)
imgs := images.GetAllImages(&i.cfg.ClusterConfiguration)
for _, img := range imgs {
fmt.Fprintln(out, img)
}
@ -472,9 +605,9 @@ func (i *ImagesList) Run(out io.Writer) error {
}
// AddImagesCommonConfigFlags adds the flags that configure kubeadm (and affect the images kubeadm will use)
func AddImagesCommonConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.MasterConfiguration, cfgPath *string, featureGatesString *string) {
func AddImagesCommonConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.InitConfiguration, cfgPath *string, featureGatesString *string) {
flagSet.StringVar(
&cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion,
&cfg.ClusterConfiguration.KubernetesVersion, "kubernetes-version", cfg.ClusterConfiguration.KubernetesVersion,
`Choose a specific Kubernetes version for the control plane.`,
)
flagSet.StringVar(featureGatesString, "feature-gates", *featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+
@ -483,6 +616,8 @@ func AddImagesCommonConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.M
}
// AddImagesPullFlags adds flags related to the `kubeadm config images pull` command
func AddImagesPullFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.MasterConfiguration) {
func AddImagesPullFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.InitConfiguration) {
flagSet.StringVar(&cfg.NodeRegistration.CRISocket, "cri-socket", cfg.NodeRegistration.CRISocket, "Specify the CRI socket to connect to.")
flagSet.StringVar(&cfg.NodeRegistration.CRISocket, "cri-socket-path", cfg.NodeRegistration.CRISocket, "Path to the CRI socket.")
flagSet.MarkDeprecated("cri-socket-path", "Please, use --cri-socket instead")
}

View File

@ -14,35 +14,42 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd_test
package cmd
import (
"bytes"
"io"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
"testing"
"github.com/renstrom/dedent"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
"k8s.io/kubernetes/cmd/kubeadm/app/util/config"
"github.com/spf13/cobra"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
utilruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime"
"k8s.io/utils/exec"
fakeexec "k8s.io/utils/exec/testing"
)
const (
defaultNumberOfImages = 8
// dummyKubernetesVersion is just used for unit testing, in order to not make
// kubeadm lookup dl.k8s.io to resolve what the latest stable release is
dummyKubernetesVersion = "v1.10.0"
dummyKubernetesVersion = "v1.12.0"
)
func TestNewCmdConfigImagesList(t *testing.T) {
var output bytes.Buffer
mockK8sVersion := dummyKubernetesVersion
images := cmd.NewCmdConfigImagesList(&output, &mockK8sVersion)
images := NewCmdConfigImagesList(&output, &mockK8sVersion)
images.Run(nil, nil)
actual := strings.Split(output.String(), "\n")
if len(actual) != defaultNumberOfImages {
@ -62,12 +69,12 @@ func TestImagesListRunWithCustomConfigPath(t *testing.T) {
name: "set k8s version",
expectedImageCount: defaultNumberOfImages,
expectedImageSubstrings: []string{
":v1.10.1",
":v1.12.1",
},
configContents: []byte(dedent.Dedent(`
apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.10.1
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.12.1
`)),
},
{
@ -77,11 +84,9 @@ func TestImagesListRunWithCustomConfigPath(t *testing.T) {
"coredns",
},
configContents: []byte(dedent.Dedent(`
apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.11.0
featureGates:
CoreDNS: True
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.12.0
`)),
},
}
@ -95,13 +100,14 @@ func TestImagesListRunWithCustomConfigPath(t *testing.T) {
defer os.RemoveAll(tmpDir)
configFilePath := filepath.Join(tmpDir, "test-config-file")
err = ioutil.WriteFile(configFilePath, tc.configContents, 0644)
if err != nil {
if err := ioutil.WriteFile(configFilePath, tc.configContents, 0644); err != nil {
t.Fatalf("Failed writing a config file: %v", err)
}
i, err := cmd.NewImagesList(configFilePath, &kubeadmapiv1alpha2.MasterConfiguration{
KubernetesVersion: dummyKubernetesVersion,
i, err := NewImagesList(configFilePath, &kubeadmapiv1beta1.InitConfiguration{
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
KubernetesVersion: dummyKubernetesVersion,
},
})
if err != nil {
t.Fatalf("Failed getting the kubeadm images command: %v", err)
@ -127,43 +133,58 @@ func TestImagesListRunWithCustomConfigPath(t *testing.T) {
func TestConfigImagesListRunWithoutPath(t *testing.T) {
testcases := []struct {
name string
cfg kubeadmapiv1alpha2.MasterConfiguration
cfg kubeadmapiv1beta1.InitConfiguration
expectedImages int
}{
{
name: "empty config",
expectedImages: defaultNumberOfImages,
cfg: kubeadmapiv1alpha2.MasterConfiguration{
KubernetesVersion: dummyKubernetesVersion,
cfg: kubeadmapiv1beta1.InitConfiguration{
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
KubernetesVersion: dummyKubernetesVersion,
},
},
},
{
name: "external etcd configuration",
cfg: kubeadmapiv1alpha2.MasterConfiguration{
Etcd: kubeadmapiv1alpha2.Etcd{
External: &kubeadmapiv1alpha2.ExternalEtcd{
Endpoints: []string{"https://some.etcd.com:2379"},
cfg: kubeadmapiv1beta1.InitConfiguration{
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
Etcd: kubeadmapiv1beta1.Etcd{
External: &kubeadmapiv1beta1.ExternalEtcd{
Endpoints: []string{"https://some.etcd.com:2379"},
},
},
KubernetesVersion: dummyKubernetesVersion,
},
KubernetesVersion: dummyKubernetesVersion,
},
expectedImages: defaultNumberOfImages - 1,
},
{
name: "coredns enabled",
cfg: kubeadmapiv1alpha2.MasterConfiguration{
FeatureGates: map[string]bool{
features.CoreDNS: true,
cfg: kubeadmapiv1beta1.InitConfiguration{
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
KubernetesVersion: dummyKubernetesVersion,
},
KubernetesVersion: dummyKubernetesVersion,
},
expectedImages: defaultNumberOfImages,
},
{
name: "kube-dns enabled",
cfg: kubeadmapiv1beta1.InitConfiguration{
ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{
KubernetesVersion: dummyKubernetesVersion,
DNS: kubeadmapiv1beta1.DNS{
Type: kubeadmapiv1beta1.KubeDNS,
},
},
},
expectedImages: defaultNumberOfImages + 2,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
i, err := cmd.NewImagesList("", &tc.cfg)
i, err := NewImagesList("", &tc.cfg)
if err != nil {
t.Fatalf("did not expect an error while creating the Images command: %v", err)
}
@ -181,48 +202,66 @@ func TestConfigImagesListRunWithoutPath(t *testing.T) {
}
}
type fakePuller struct {
count map[string]int
}
func (f *fakePuller) Pull(image string) error {
f.count[image]++
return nil
}
func TestImagesPull(t *testing.T) {
puller := &fakePuller{
count: make(map[string]int),
fcmd := fakeexec.FakeCmd{
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
func() ([]byte, error) { return nil, nil },
func() ([]byte, error) { return nil, nil },
func() ([]byte, error) { return nil, nil },
func() ([]byte, error) { return nil, nil },
func() ([]byte, error) { return nil, nil },
},
}
fexec := fakeexec.FakeExec{
CommandScript: []fakeexec.FakeCommandAction{
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
},
LookPathFunc: func(cmd string) (string, error) { return "/usr/bin/docker", nil },
}
containerRuntime, err := utilruntime.NewContainerRuntime(&fexec, kubeadmapiv1beta1.DefaultCRISocket)
if err != nil {
t.Errorf("unexpected NewContainerRuntime error: %v", err)
}
images := []string{"a", "b", "c", "d", "a"}
ip := cmd.NewImagesPull(puller, images)
err := ip.PullAll()
ip := NewImagesPull(containerRuntime, images)
err = ip.PullAll()
if err != nil {
t.Fatalf("expected nil but found %v", err)
}
if puller.count["a"] != 2 {
t.Fatalf("expected 2 but found %v", puller.count["a"])
if fcmd.CombinedOutputCalls != len(images) {
t.Errorf("expected %d calls, got %d", len(images), fcmd.CombinedOutputCalls)
}
}
func TestMigrate(t *testing.T) {
cfg := []byte(dedent.Dedent(`
apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.10.0
# This is intentionally testing an old API version and the old kind naming and making sure the output is correct
apiVersion: kubeadm.k8s.io/v1alpha3
kind: InitConfiguration
`))
configFile, cleanup := tempConfig(t, cfg)
defer cleanup()
var output bytes.Buffer
command := cmd.NewCmdConfigMigrate(&output)
err := command.Flags().Set("old-config", configFile)
if err != nil {
command := NewCmdConfigMigrate(&output)
if err := command.Flags().Set("old-config", configFile); err != nil {
t.Fatalf("failed to set old-config flag")
}
newConfigPath := filepath.Join(filepath.Dir(configFile), "new-migrated-config")
if err := command.Flags().Set("new-config", newConfigPath); err != nil {
t.Fatalf("failed to set new-config flag")
}
command.Run(nil, nil)
_, err = config.BytesToInternalConfig(output.Bytes())
if err != nil {
if _, err := configutil.ConfigFileAndDefaultsToInternalConfig(newConfigPath, &kubeadmapiv1beta1.InitConfiguration{}); err != nil {
t.Fatalf("Could not read output back into internal type: %v", err)
}
}
@ -235,8 +274,7 @@ func tempConfig(t *testing.T, config []byte) (string, func()) {
t.Fatalf("Unable to create temporary directory: %v", err)
}
configFilePath := filepath.Join(tmpDir, "test-config-file")
err = ioutil.WriteFile(configFilePath, config, 0644)
if err != nil {
if err := ioutil.WriteFile(configFilePath, config, 0644); err != nil {
os.RemoveAll(tmpDir)
t.Fatalf("Failed writing a config file: %v", err)
}
@ -244,3 +282,96 @@ func tempConfig(t *testing.T, config []byte) (string, func()) {
os.RemoveAll(tmpDir)
}
}
func TestNewCmdConfigPrintActionDefaults(t *testing.T) {
tests := []struct {
name string
expectedKinds []string // need to be sorted
componentConfigs string
cmdProc func(out io.Writer) *cobra.Command
}{
{
name: "InitConfiguration: No component configs",
expectedKinds: []string{
constants.ClusterConfigurationKind,
constants.InitConfigurationKind,
},
cmdProc: NewCmdConfigPrintInitDefaults,
},
{
name: "InitConfiguration: KubeProxyConfiguration",
expectedKinds: []string{
constants.ClusterConfigurationKind,
constants.InitConfigurationKind,
string(componentconfigs.KubeProxyConfigurationKind),
},
componentConfigs: "KubeProxyConfiguration",
cmdProc: NewCmdConfigPrintInitDefaults,
},
{
name: "InitConfiguration: KubeProxyConfiguration and KubeletConfiguration",
expectedKinds: []string{
constants.ClusterConfigurationKind,
constants.InitConfigurationKind,
string(componentconfigs.KubeProxyConfigurationKind),
string(componentconfigs.KubeletConfigurationKind),
},
componentConfigs: "KubeProxyConfiguration,KubeletConfiguration",
cmdProc: NewCmdConfigPrintInitDefaults,
},
{
name: "JoinConfiguration: No component configs",
expectedKinds: []string{
constants.JoinConfigurationKind,
},
cmdProc: NewCmdConfigPrintJoinDefaults,
},
{
name: "JoinConfiguration: KubeProxyConfiguration",
expectedKinds: []string{
constants.JoinConfigurationKind,
string(componentconfigs.KubeProxyConfigurationKind),
},
componentConfigs: "KubeProxyConfiguration",
cmdProc: NewCmdConfigPrintJoinDefaults,
},
{
name: "JoinConfiguration: KubeProxyConfiguration and KubeletConfiguration",
expectedKinds: []string{
constants.JoinConfigurationKind,
string(componentconfigs.KubeProxyConfigurationKind),
string(componentconfigs.KubeletConfigurationKind),
},
componentConfigs: "KubeProxyConfiguration,KubeletConfiguration",
cmdProc: NewCmdConfigPrintJoinDefaults,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var output bytes.Buffer
command := test.cmdProc(&output)
if err := command.Flags().Set("component-configs", test.componentConfigs); err != nil {
t.Fatalf("failed to set component-configs flag")
}
command.Run(nil, nil)
gvkmap, err := kubeadmutil.SplitYAMLDocuments(output.Bytes())
if err != nil {
t.Fatalf("unexpected failure of SplitYAMLDocuments: %v", err)
}
gotKinds := []string{}
for gvk := range gvkmap {
gotKinds = append(gotKinds, gvk.Kind)
}
sort.Strings(gotKinds)
if !reflect.DeepEqual(gotKinds, test.expectedKinds) {
t.Fatalf("kinds not matching:\n\texpectedKinds: %v\n\tgotKinds: %v\n", test.expectedKinds, gotKinds)
}
})
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors.
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.
@ -24,45 +24,29 @@ import (
"path/filepath"
"strings"
"text/template"
"time"
"github.com/golang/glog"
"github.com/pkg/errors"
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/util/sets"
clientset "k8s.io/client-go/kubernetes"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
"k8s.io/kubernetes/cmd/kubeadm/app/images"
dnsaddonphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
proxyaddonphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster"
patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
selfhostingphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting"
uploadconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
auditutil "k8s.io/kubernetes/cmd/kubeadm/app/util/audit"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
utilsexec "k8s.io/utils/exec"
)
var (
@ -93,13 +77,6 @@ var (
This error is likely caused by:
- The kubelet is not running
- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
- No internet connection is available so the kubelet cannot pull or find the following control plane images:
- {{ .APIServerImage }}
- {{ .ControllerManagerImage }}
- {{ .SchedulerImage }}
{{ .EtcdImage }}
- You can check or miligate this in beforehand with "kubeadm config images pull" to make sure the images
are downloaded locally and cached.
If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
- 'systemctl status kubelet'
@ -114,423 +91,373 @@ var (
`)))
)
// initOptions defines all the init options exposed via flags by kubeadm init.
// Please note that this structure includes the public kubeadm config API, but only a subset of the options
// supported by this api will be exposed as a flag.
type initOptions struct {
cfgPath string
skipTokenPrint bool
dryRun bool
kubeconfigDir string
kubeconfigPath string
featureGatesString string
ignorePreflightErrors []string
bto *options.BootstrapTokenOptions
externalcfg *kubeadmapiv1beta1.InitConfiguration
}
// initData defines all the runtime information used when running the kubeadm init worklow;
// this data is shared across all the phases that are included in the workflow.
type initData struct {
cfg *kubeadmapi.InitConfiguration
skipTokenPrint bool
dryRun bool
kubeconfigDir string
kubeconfigPath string
ignorePreflightErrors sets.String
certificatesDir string
dryRunDir string
externalCA bool
client clientset.Interface
waiter apiclient.Waiter
outputWriter io.Writer
}
// NewCmdInit returns "kubeadm init" command.
func NewCmdInit(out io.Writer) *cobra.Command {
externalcfg := &kubeadmapiv1alpha2.MasterConfiguration{}
kubeadmscheme.Scheme.Default(externalcfg)
var cfgPath string
var skipPreFlight bool
var skipTokenPrint bool
var dryRun bool
var featureGatesString string
var ignorePreflightErrors []string
// Create the options object for the bootstrap token-related flags, and override the default value for .Description
bto := options.NewBootstrapTokenOptions()
bto.Description = "The default bootstrap token generated by 'kubeadm init'."
initOptions := newInitOptions()
initRunner := workflow.NewRunner()
cmd := &cobra.Command{
Use: "init",
Short: "Run this command in order to set up the Kubernetes master.",
Run: func(cmd *cobra.Command, args []string) {
kubeadmscheme.Scheme.Default(externalcfg)
var err error
if externalcfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
kubeadmutil.CheckErr(err)
}
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight)
c, err := initRunner.InitData()
kubeadmutil.CheckErr(err)
err = validation.ValidateMixedArguments(cmd.Flags())
data := c.(initData)
fmt.Printf("[init] Using Kubernetes version: %s\n", data.cfg.KubernetesVersion)
err = initRunner.Run()
kubeadmutil.CheckErr(err)
err = bto.ApplyTo(externalcfg)
err = showJoinCommand(&data, out)
kubeadmutil.CheckErr(err)
i, err := NewInit(cfgPath, externalcfg, ignorePreflightErrorsSet, skipTokenPrint, dryRun)
kubeadmutil.CheckErr(err)
kubeadmutil.CheckErr(i.Run(out))
},
}
AddInitConfigFlags(cmd.PersistentFlags(), externalcfg, &featureGatesString)
AddInitOtherFlags(cmd.PersistentFlags(), &cfgPath, &skipPreFlight, &skipTokenPrint, &dryRun, &ignorePreflightErrors)
bto.AddTokenFlag(cmd.PersistentFlags())
bto.AddTTLFlag(cmd.PersistentFlags())
// adds flags to the init command
// init command local flags could be eventually inherited by the sub-commands automatically generated for phases
AddInitConfigFlags(cmd.Flags(), initOptions.externalcfg, &initOptions.featureGatesString)
AddInitOtherFlags(cmd.Flags(), &initOptions.cfgPath, &initOptions.skipTokenPrint, &initOptions.dryRun, &initOptions.ignorePreflightErrors)
initOptions.bto.AddTokenFlag(cmd.Flags())
initOptions.bto.AddTTLFlag(cmd.Flags())
options.AddImageMetaFlags(cmd.Flags(), &initOptions.externalcfg.ImageRepository)
// defines additional flag that are not used by the init command but that could be eventually used
// by the sub-commands automatically generated for phases
initRunner.SetAdditionalFlags(func(flags *flag.FlagSet) {
options.AddKubeConfigFlag(flags, &initOptions.kubeconfigPath)
options.AddKubeConfigDirFlag(flags, &initOptions.kubeconfigDir)
options.AddControlPlanExtraArgsFlags(flags, &initOptions.externalcfg.APIServer.ExtraArgs, &initOptions.externalcfg.ControllerManager.ExtraArgs, &initOptions.externalcfg.Scheduler.ExtraArgs)
})
// initialize the workflow runner with the list of phases
initRunner.AppendPhase(phases.NewPreflightMasterPhase())
initRunner.AppendPhase(phases.NewKubeletStartPhase())
initRunner.AppendPhase(phases.NewCertsPhase())
initRunner.AppendPhase(phases.NewKubeConfigPhase())
initRunner.AppendPhase(phases.NewControlPlanePhase())
initRunner.AppendPhase(phases.NewEtcdPhase())
initRunner.AppendPhase(phases.NewWaitControlPlanePhase())
initRunner.AppendPhase(phases.NewUploadConfigPhase())
initRunner.AppendPhase(phases.NewMarkControlPlanePhase())
initRunner.AppendPhase(phases.NewBootstrapTokenPhase())
initRunner.AppendPhase(phases.NewAddonPhase())
// sets the data builder function, that will be used by the runner
// both when running the entire workflow or single phases
initRunner.SetDataInitializer(func(cmd *cobra.Command) (workflow.RunData, error) {
return newInitData(cmd, initOptions, out)
})
// binds the Runner to kubeadm init command by altering
// command help, adding --skip-phases flag and by adding phases subcommands
initRunner.BindToCommand(cmd)
return cmd
}
// AddInitConfigFlags adds init flags bound to the config to the specified flagset
func AddInitConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.MasterConfiguration, featureGatesString *string) {
func AddInitConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.InitConfiguration, featureGatesString *string) {
flagSet.StringVar(
&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress,
&cfg.LocalAPIEndpoint.AdvertiseAddress, options.APIServerAdvertiseAddress, cfg.LocalAPIEndpoint.AdvertiseAddress,
"The IP address the API Server will advertise it's listening on. Specify '0.0.0.0' to use the address of the default network interface.",
)
flagSet.Int32Var(
&cfg.API.BindPort, "apiserver-bind-port", cfg.API.BindPort,
&cfg.LocalAPIEndpoint.BindPort, options.APIServerBindPort, cfg.LocalAPIEndpoint.BindPort,
"Port for the API Server to bind to.",
)
flagSet.StringVar(
&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet,
&cfg.Networking.ServiceSubnet, options.NetworkingServiceSubnet, cfg.Networking.ServiceSubnet,
"Use alternative range of IP address for service VIPs.",
)
flagSet.StringVar(
&cfg.Networking.PodSubnet, "pod-network-cidr", cfg.Networking.PodSubnet,
&cfg.Networking.PodSubnet, options.NetworkingPodSubnet, cfg.Networking.PodSubnet,
"Specify range of IP addresses for the pod network. If set, the control plane will automatically allocate CIDRs for every node.",
)
flagSet.StringVar(
&cfg.Networking.DNSDomain, "service-dns-domain", cfg.Networking.DNSDomain,
&cfg.Networking.DNSDomain, options.NetworkingDNSDomain, cfg.Networking.DNSDomain,
`Use alternative domain for services, e.g. "myorg.internal".`,
)
flagSet.StringVar(
&cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion,
&cfg.KubernetesVersion, options.KubernetesVersion, cfg.KubernetesVersion,
`Choose a specific Kubernetes version for the control plane.`,
)
flagSet.StringVar(
&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir,
&cfg.CertificatesDir, options.CertificatesDir, cfg.CertificatesDir,
`The path where to save and store the certificates.`,
)
flagSet.StringSliceVar(
&cfg.APIServerCertSANs, "apiserver-cert-extra-sans", cfg.APIServerCertSANs,
&cfg.APIServer.CertSANs, options.APIServerCertSANs, cfg.APIServer.CertSANs,
`Optional extra Subject Alternative Names (SANs) to use for the API Server serving certificate. Can be both IP addresses and DNS names.`,
)
flagSet.StringVar(
&cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name,
&cfg.NodeRegistration.Name, options.NodeName, cfg.NodeRegistration.Name,
`Specify the node name.`,
)
flagSet.StringVar(
&cfg.NodeRegistration.CRISocket, "cri-socket", cfg.NodeRegistration.CRISocket,
&cfg.NodeRegistration.CRISocket, options.NodeCRISocket, cfg.NodeRegistration.CRISocket,
`Specify the CRI socket to connect to.`,
)
flagSet.StringVar(featureGatesString, "feature-gates", *featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+
flagSet.StringVar(featureGatesString, options.FeatureGatesString, *featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+
"Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n"))
}
// AddInitOtherFlags adds init flags that are not bound to a configuration file to the given flagset
func AddInitOtherFlags(flagSet *flag.FlagSet, cfgPath *string, skipPreFlight, skipTokenPrint, dryRun *bool, ignorePreflightErrors *[]string) {
func AddInitOtherFlags(flagSet *flag.FlagSet, cfgPath *string, skipTokenPrint, dryRun *bool, ignorePreflightErrors *[]string) {
flagSet.StringVar(
cfgPath, "config", *cfgPath,
cfgPath, options.CfgPath, *cfgPath,
"Path to kubeadm config file. WARNING: Usage of a configuration file is experimental.",
)
flagSet.StringSliceVar(
ignorePreflightErrors, "ignore-preflight-errors", *ignorePreflightErrors,
ignorePreflightErrors, options.IgnorePreflightErrors, *ignorePreflightErrors,
"A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.",
)
// Note: All flags that are not bound to the cfg object should be whitelisted in cmd/kubeadm/app/apis/kubeadm/validation/validation.go
flagSet.BoolVar(
skipPreFlight, "skip-preflight-checks", *skipPreFlight,
"Skip preflight checks which normally run before modifying the system.",
)
flagSet.MarkDeprecated("skip-preflight-checks", "it is now equivalent to --ignore-preflight-errors=all")
// Note: All flags that are not bound to the cfg object should be whitelisted in cmd/kubeadm/app/apis/kubeadm/validation/validation.go
flagSet.BoolVar(
skipTokenPrint, "skip-token-print", *skipTokenPrint,
skipTokenPrint, options.SkipTokenPrint, *skipTokenPrint,
"Skip printing of the default bootstrap token generated by 'kubeadm init'.",
)
// Note: All flags that are not bound to the cfg object should be whitelisted in cmd/kubeadm/app/apis/kubeadm/validation/validation.go
flagSet.BoolVar(
dryRun, "dry-run", *dryRun,
dryRun, options.DryRun, *dryRun,
"Don't apply any changes; just output what would be done.",
)
}
// NewInit validates given arguments and instantiates Init struct with provided information.
func NewInit(cfgPath string, externalcfg *kubeadmapiv1alpha2.MasterConfiguration, ignorePreflightErrors sets.String, skipTokenPrint, dryRun bool) (*Init, error) {
// newInitOptions returns a struct ready for being used for creating cmd init flags.
func newInitOptions() *initOptions {
// initialize the public kubeadm config API by appling defaults
externalcfg := &kubeadmapiv1beta1.InitConfiguration{}
kubeadmscheme.Scheme.Default(externalcfg)
// Either use the config file if specified, or convert the defaults in the external to an internal cfg representation
cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, externalcfg)
if err != nil {
return nil, err
// Create the options object for the bootstrap token-related flags, and override the default value for .Description
bto := options.NewBootstrapTokenOptions()
bto.Description = "The default bootstrap token generated by 'kubeadm init'."
return &initOptions{
externalcfg: externalcfg,
bto: bto,
kubeconfigDir: kubeadmconstants.KubernetesDir,
kubeconfigPath: kubeadmconstants.GetAdminKubeConfigPath(),
}
}
// newInitData returns a new initData struct to be used for the execution of the kubeadm init workflow.
// This func takes care of validating initOptions passed to the command, and then it converts
// options into the internal InitConfiguration type that is used as input all the phases in the kubeadm init workflow
func newInitData(cmd *cobra.Command, options *initOptions, out io.Writer) (initData, error) {
// Re-apply defaults to the public kubeadm API (this will set only values not exposed/not set as a flags)
kubeadmscheme.Scheme.Default(options.externalcfg)
// Validate standalone flags values and/or combination of flags and then assigns
// validated values to the public kubeadm config API when applicable
var err error
if options.externalcfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, options.featureGatesString); err != nil {
return initData{}, err
}
glog.V(1).Infof("[init] validating feature gates")
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(options.ignorePreflightErrors)
kubeadmutil.CheckErr(err)
if err = validation.ValidateMixedArguments(cmd.Flags()); err != nil {
return initData{}, err
}
if err = options.bto.ApplyTo(options.externalcfg); err != nil {
return initData{}, err
}
// Either use the config file if specified, or convert public kubeadm API to the internal InitConfiguration
// and validates InitConfiguration
cfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(options.cfgPath, options.externalcfg)
if err != nil {
return initData{}, err
}
// override node name and CRI socket from the command line options
if options.externalcfg.NodeRegistration.Name != "" {
cfg.NodeRegistration.Name = options.externalcfg.NodeRegistration.Name
}
if options.externalcfg.NodeRegistration.CRISocket != kubeadmapiv1beta1.DefaultCRISocket {
cfg.NodeRegistration.CRISocket = options.externalcfg.NodeRegistration.CRISocket
}
if err := configutil.VerifyAPIServerBindAddress(cfg.LocalAPIEndpoint.AdvertiseAddress); err != nil {
return initData{}, err
}
if err := features.ValidateVersion(features.InitFeatureGates, cfg.FeatureGates, cfg.KubernetesVersion); err != nil {
return nil, err
return initData{}, err
}
fmt.Printf("[init] using Kubernetes version: %s\n", cfg.KubernetesVersion)
fmt.Println("[preflight] running pre-flight checks")
if err := preflight.RunInitMasterChecks(utilsexec.New(), cfg, ignorePreflightErrors); err != nil {
return nil, err
}
if !dryRun {
fmt.Println("[preflight/images] Pulling images required for setting up a Kubernetes cluster")
fmt.Println("[preflight/images] This might take a minute or two, depending on the speed of your internet connection")
fmt.Println("[preflight/images] You can also perform this action in beforehand using 'kubeadm config images pull'")
if err := preflight.RunPullImagesCheck(utilsexec.New(), cfg, ignorePreflightErrors); err != nil {
return nil, err
// if dry running creates a temporary folder for saving kubeadm generated files
dryRunDir := ""
if options.dryRun {
if dryRunDir, err = ioutil.TempDir("", "kubeadm-init-dryrun"); err != nil {
return initData{}, errors.Wrap(err, "couldn't create a temporary directory")
}
} else {
fmt.Println("[preflight/images] Would pull the required images (like 'kubeadm config images pull')")
}
return &Init{cfg: cfg, skipTokenPrint: skipTokenPrint, dryRun: dryRun, ignorePreflightErrors: ignorePreflightErrors}, nil
// Checks if an external CA is provided by the user.
externalCA, _ := certsphase.UsingExternalCA(cfg)
if externalCA {
kubeconfigDir := kubeadmconstants.KubernetesDir
if options.dryRun {
kubeconfigDir = dryRunDir
}
if err := kubeconfigphase.ValidateKubeconfigsForExternalCA(kubeconfigDir, cfg); err != nil {
return initData{}, err
}
}
return initData{
cfg: cfg,
certificatesDir: cfg.CertificatesDir,
skipTokenPrint: options.skipTokenPrint,
dryRun: options.dryRun,
dryRunDir: dryRunDir,
kubeconfigDir: options.kubeconfigDir,
kubeconfigPath: options.kubeconfigPath,
ignorePreflightErrors: ignorePreflightErrorsSet,
externalCA: externalCA,
outputWriter: out,
}, nil
}
// Init defines struct used by "kubeadm init" command
type Init struct {
cfg *kubeadmapi.MasterConfiguration
skipTokenPrint bool
dryRun bool
ignorePreflightErrors sets.String
// Cfg returns initConfiguration.
func (d initData) Cfg() *kubeadmapi.InitConfiguration {
return d.cfg
}
// Run executes master node provisioning, including certificates, needed static pod manifests, etc.
func (i *Init) Run(out io.Writer) error {
// DryRun returns the DryRun flag.
func (d initData) DryRun() bool {
return d.dryRun
}
// Get directories to write files to; can be faked if we're dry-running
glog.V(1).Infof("[init] Getting certificates directory from configuration")
realCertsDir := i.cfg.CertificatesDir
certsDirToWriteTo, kubeConfigDir, manifestDir, kubeletDir, err := getDirectoriesToUse(i.dryRun, i.cfg.CertificatesDir)
if err != nil {
return fmt.Errorf("error getting directories to use: %v", err)
// SkipTokenPrint returns the SkipTokenPrint flag.
func (d initData) SkipTokenPrint() bool {
return d.skipTokenPrint
}
// IgnorePreflightErrors returns the IgnorePreflightErrors flag.
func (d initData) IgnorePreflightErrors() sets.String {
return d.ignorePreflightErrors
}
// CertificateWriteDir returns the path to the certificate folder or the temporary folder path in case of DryRun.
func (d initData) CertificateWriteDir() string {
if d.dryRun {
return d.dryRunDir
}
return d.certificatesDir
}
// First off, configure the kubelet. In this short timeframe, kubeadm is trying to stop/restart the kubelet
// Try to stop the kubelet service so no race conditions occur when configuring it
if !i.dryRun {
glog.V(1).Infof("Stopping the kubelet")
preflight.TryStopKubelet()
// CertificateDir returns the CertificateDir as originally specified by the user.
func (d initData) CertificateDir() string {
return d.certificatesDir
}
// KubeConfigDir returns the path of the Kubernetes configuration folder or the temporary folder path in case of DryRun.
func (d initData) KubeConfigDir() string {
if d.dryRun {
return d.dryRunDir
}
return d.kubeconfigDir
}
// Write env file with flags for the kubelet to use. We do not need to write the --register-with-taints for the master,
// as we handle that ourselves in the markmaster phase
// TODO: Maybe we want to do that some time in the future, in order to remove some logic from the markmaster phase?
if err := kubeletphase.WriteKubeletDynamicEnvFile(&i.cfg.NodeRegistration, i.cfg.FeatureGates, false, kubeletDir); err != nil {
return fmt.Errorf("error writing a dynamic environment file for the kubelet: %v", err)
// KubeConfigPath returns the path to the kubeconfig file to use for connecting to Kubernetes
func (d initData) KubeConfigPath() string {
if d.dryRun {
d.kubeconfigPath = filepath.Join(d.dryRunDir, kubeadmconstants.AdminKubeConfigFileName)
}
return d.kubeconfigPath
}
// Write the kubelet configuration file to disk.
if err := kubeletphase.WriteConfigToDisk(i.cfg.KubeletConfiguration.BaseConfig, kubeletDir); err != nil {
return fmt.Errorf("error writing kubelet configuration to disk: %v", err)
// ManifestDir returns the path where manifest should be stored or the temporary folder path in case of DryRun.
func (d initData) ManifestDir() string {
if d.dryRun {
return d.dryRunDir
}
return kubeadmconstants.GetStaticPodDirectory()
}
if !i.dryRun {
// Try to start the kubelet service in case it's inactive
glog.V(1).Infof("Starting the kubelet")
preflight.TryStartKubelet()
// KubeletDir returns path of the kubelet configuration folder or the temporary folder in case of DryRun.
func (d initData) KubeletDir() string {
if d.dryRun {
return d.dryRunDir
}
return kubeadmconstants.KubeletRunDirectory
}
// certsDirToWriteTo is gonna equal cfg.CertificatesDir in the normal case, but gonna be a temp directory if dryrunning
i.cfg.CertificatesDir = certsDirToWriteTo
// ExternalCA returns true if an external CA is provided by the user.
func (d initData) ExternalCA() bool {
return d.externalCA
}
adminKubeConfigPath := filepath.Join(kubeConfigDir, kubeadmconstants.AdminKubeConfigFileName)
// OutputWriter returns the io.Writer used to write output to by this command.
func (d initData) OutputWriter() io.Writer {
return d.outputWriter
}
if res, _ := certsphase.UsingExternalCA(i.cfg); !res {
// PHASE 1: Generate certificates
glog.V(1).Infof("[init] creating PKI Assets")
if err := certsphase.CreatePKIAssets(i.cfg); err != nil {
return err
}
// PHASE 2: Generate kubeconfig files for the admin and the kubelet
glog.V(2).Infof("[init] generating kubeconfig files")
if err := kubeconfigphase.CreateInitKubeConfigFiles(kubeConfigDir, i.cfg); err != nil {
return err
}
} else {
fmt.Println("[externalca] the file 'ca.key' was not found, yet all other certificates are present. Using external CA mode - certificates or kubeconfig will not be generated")
}
if features.Enabled(i.cfg.FeatureGates, features.Auditing) {
// Setup the AuditPolicy (either it was passed in and exists or it wasn't passed in and generate a default policy)
if i.cfg.AuditPolicyConfiguration.Path != "" {
// TODO(chuckha) ensure passed in audit policy is valid so users don't have to find the error in the api server log.
if _, err := os.Stat(i.cfg.AuditPolicyConfiguration.Path); err != nil {
return fmt.Errorf("error getting file info for audit policy file %q [%v]", i.cfg.AuditPolicyConfiguration.Path, err)
}
// Client returns a Kubernetes client to be used by kubeadm.
// This function is implemented as a singleton, thus avoiding to recreate the client when it is used by different phases.
// Important. This function must be called after the admin.conf kubeconfig file is created.
func (d initData) Client() (clientset.Interface, error) {
if d.client == nil {
if d.dryRun {
// If we're dry-running; we should create a faked client that answers some GETs in order to be able to do the full init flow and just logs the rest of requests
dryRunGetter := apiclient.NewInitDryRunGetter(d.cfg.NodeRegistration.Name, d.cfg.Networking.ServiceSubnet)
d.client = apiclient.NewDryRunClient(dryRunGetter, os.Stdout)
} else {
i.cfg.AuditPolicyConfiguration.Path = filepath.Join(kubeConfigDir, kubeadmconstants.AuditPolicyDir, kubeadmconstants.AuditPolicyFile)
if err := auditutil.CreateDefaultAuditLogPolicy(i.cfg.AuditPolicyConfiguration.Path); err != nil {
return fmt.Errorf("error creating default audit policy %q [%v]", i.cfg.AuditPolicyConfiguration.Path, err)
// If we're acting for real, we should create a connection to the API server and wait for it to come up
var err error
d.client, err = kubeconfigutil.ClientSetFromFile(d.KubeConfigPath())
if err != nil {
return nil, err
}
}
}
return d.client, nil
}
// Temporarily set cfg.CertificatesDir to the "real value" when writing controlplane manifests
// This is needed for writing the right kind of manifests
i.cfg.CertificatesDir = realCertsDir
// PHASE 3: Bootstrap the control plane
glog.V(1).Infof("[init] bootstraping the control plane")
glog.V(1).Infof("[init] creating static pod manifest")
if err := controlplanephase.CreateInitStaticPodManifestFiles(manifestDir, i.cfg); err != nil {
return fmt.Errorf("error creating init static pod manifest files: %v", err)
}
// Add etcd static pod spec only if external etcd is not configured
if i.cfg.Etcd.External == nil {
glog.V(1).Infof("[init] no external etcd found. Creating manifest for local etcd static pod")
if err := etcdphase.CreateLocalEtcdStaticPodManifestFile(manifestDir, i.cfg); err != nil {
return fmt.Errorf("error creating local etcd static pod manifest file: %v", err)
}
}
// Revert the earlier CertificatesDir assignment to the directory that can be written to
i.cfg.CertificatesDir = certsDirToWriteTo
// If we're dry-running, print the generated manifests
if err := printFilesIfDryRunning(i.dryRun, manifestDir); err != nil {
return fmt.Errorf("error printing files on dryrun: %v", err)
}
// Create a kubernetes client and wait for the API server to be healthy (if not dryrunning)
glog.V(1).Infof("creating Kubernetes client")
client, err := createClient(i.cfg, i.dryRun)
if err != nil {
return fmt.Errorf("error creating client: %v", err)
}
// waiter holds the apiclient.Waiter implementation of choice, responsible for querying the API server in various ways and waiting for conditions to be fulfilled
glog.V(1).Infof("[init] waiting for the API server to be healthy")
waiter := getWaiter(i, client)
fmt.Printf("[init] waiting for the kubelet to boot up the control plane as Static Pods from directory %q \n", kubeadmconstants.GetStaticPodDirectory())
fmt.Println("[init] this might take a minute or longer if the control plane images have to be pulled")
if err := waitForKubeletAndFunc(waiter, waiter.WaitForAPI); err != nil {
ctx := map[string]string{
"Error": fmt.Sprintf("%v", err),
"APIServerImage": images.GetCoreImage(kubeadmconstants.KubeAPIServer, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
"ControllerManagerImage": images.GetCoreImage(kubeadmconstants.KubeControllerManager, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
"SchedulerImage": images.GetCoreImage(kubeadmconstants.KubeScheduler, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
}
// Set .EtcdImage conditionally
if i.cfg.Etcd.Local != nil {
ctx["EtcdImage"] = fmt.Sprintf(" - %s", images.GetCoreImage(kubeadmconstants.Etcd, i.cfg.ImageRepository, i.cfg.KubernetesVersion, i.cfg.Etcd.Local.Image))
} else {
ctx["EtcdImage"] = ""
}
kubeletFailTempl.Execute(out, ctx)
return fmt.Errorf("couldn't initialize a Kubernetes cluster")
}
// Upload currently used configuration to the cluster
// Note: This is done right in the beginning of cluster initialization; as we might want to make other phases
// depend on centralized information from this source in the future
glog.V(1).Infof("[init] uploading currently used configuration to the cluster")
if err := uploadconfigphase.UploadConfiguration(i.cfg, client); err != nil {
return fmt.Errorf("error uploading configuration: %v", err)
}
glog.V(1).Infof("[init] creating kubelet configuration configmap")
if err := kubeletphase.CreateConfigMap(i.cfg, client); err != nil {
return fmt.Errorf("error creating kubelet configuration ConfigMap: %v", err)
}
// PHASE 4: Mark the master with the right label/taint
glog.V(1).Infof("[init] marking the master with right label")
if err := markmasterphase.MarkMaster(client, i.cfg.NodeRegistration.Name, i.cfg.NodeRegistration.Taints); err != nil {
return fmt.Errorf("error marking master: %v", err)
}
glog.V(1).Infof("[init] preserving the crisocket information for the master")
if err := patchnodephase.AnnotateCRISocket(client, i.cfg.NodeRegistration.Name, i.cfg.NodeRegistration.CRISocket); err != nil {
return fmt.Errorf("error uploading crisocket: %v", err)
}
// This feature is disabled by default
if features.Enabled(i.cfg.FeatureGates, features.DynamicKubeletConfig) {
kubeletVersion, err := preflight.GetKubeletVersion(utilsexec.New())
if err != nil {
return err
}
// Enable dynamic kubelet configuration for the node.
if err := kubeletphase.EnableDynamicConfigForNode(client, i.cfg.NodeRegistration.Name, kubeletVersion); err != nil {
return fmt.Errorf("error enabling dynamic kubelet configuration: %v", err)
}
}
// PHASE 5: Set up the node bootstrap tokens
// Tokens returns an array of token strings.
func (d initData) Tokens() []string {
tokens := []string{}
for _, bt := range i.cfg.BootstrapTokens {
for _, bt := range d.cfg.BootstrapTokens {
tokens = append(tokens, bt.Token.String())
}
if !i.skipTokenPrint {
if len(tokens) == 1 {
fmt.Printf("[bootstraptoken] using token: %s\n", tokens[0])
} else if len(tokens) > 1 {
fmt.Printf("[bootstraptoken] using tokens: %v\n", tokens)
}
}
// Create the default node bootstrap token
glog.V(1).Infof("[init] creating RBAC rules to generate default bootstrap token")
if err := nodebootstraptokenphase.UpdateOrCreateTokens(client, false, i.cfg.BootstrapTokens); err != nil {
return fmt.Errorf("error updating or creating token: %v", err)
}
// Create RBAC rules that makes the bootstrap tokens able to post CSRs
glog.V(1).Infof("[init] creating RBAC rules to allow bootstrap tokens to post CSR")
if err := nodebootstraptokenphase.AllowBootstrapTokensToPostCSRs(client); err != nil {
return fmt.Errorf("error allowing bootstrap tokens to post CSRs: %v", err)
}
// Create RBAC rules that makes the bootstrap tokens able to get their CSRs approved automatically
glog.V(1).Infof("[init] creating RBAC rules to automatic approval of CSRs automatically")
if err := nodebootstraptokenphase.AutoApproveNodeBootstrapTokens(client); err != nil {
return fmt.Errorf("error auto-approving node bootstrap tokens: %v", err)
}
// Create/update RBAC rules that makes the nodes to rotate certificates and get their CSRs approved automatically
glog.V(1).Infof("[init] creating/updating RBAC rules for rotating certificate")
if err := nodebootstraptokenphase.AutoApproveNodeCertificateRotation(client); err != nil {
return err
}
// Create the cluster-info ConfigMap with the associated RBAC rules
glog.V(1).Infof("[init] creating bootstrap configmap")
if err := clusterinfophase.CreateBootstrapConfigMapIfNotExists(client, adminKubeConfigPath); err != nil {
return fmt.Errorf("error creating bootstrap configmap: %v", err)
}
glog.V(1).Infof("[init] creating ClusterInfo RBAC rules")
if err := clusterinfophase.CreateClusterInfoRBACRules(client); err != nil {
return fmt.Errorf("error creating clusterinfo RBAC rules: %v", err)
}
glog.V(1).Infof("[init] ensuring DNS addon")
if err := dnsaddonphase.EnsureDNSAddon(i.cfg, client); err != nil {
return fmt.Errorf("error ensuring dns addon: %v", err)
}
glog.V(1).Infof("[init] ensuring proxy addon")
if err := proxyaddonphase.EnsureProxyAddon(i.cfg, client); err != nil {
return fmt.Errorf("error ensuring proxy addon: %v", err)
}
// PHASE 7: Make the control plane self-hosted if feature gate is enabled
if features.Enabled(i.cfg.FeatureGates, features.SelfHosting) {
glog.V(1).Infof("[init] feature gate is enabled. Making control plane self-hosted")
// Temporary control plane is up, now we create our self hosted control
// plane components and remove the static manifests:
fmt.Println("[self-hosted] creating self-hosted control plane")
if err := selfhostingphase.CreateSelfHostedControlPlane(manifestDir, kubeConfigDir, i.cfg, client, waiter, i.dryRun); err != nil {
return fmt.Errorf("error creating self hosted control plane: %v", err)
}
}
// Exit earlier if we're dryrunning
if i.dryRun {
fmt.Println("[dryrun] finished dry-running successfully. Above are the resources that would be created")
return nil
}
// Prints the join command, multiple times in case the user has multiple tokens
for _, token := range tokens {
if err := printJoinCommand(out, adminKubeConfigPath, token, i.skipTokenPrint); err != nil {
return fmt.Errorf("failed to print join command: %v", err)
}
}
return nil
return tokens
}
func printJoinCommand(out io.Writer, adminKubeConfigPath, token string, skipTokenPrint bool) error {
@ -547,26 +474,10 @@ func printJoinCommand(out io.Writer, adminKubeConfigPath, token string, skipToke
return initDoneTempl.Execute(out, ctx)
}
// createClient creates a clientset.Interface object
func createClient(cfg *kubeadmapi.MasterConfiguration, dryRun bool) (clientset.Interface, error) {
if dryRun {
// If we're dry-running; we should create a faked client that answers some GETs in order to be able to do the full init flow and just logs the rest of requests
dryRunGetter := apiclient.NewInitDryRunGetter(cfg.NodeRegistration.Name, cfg.Networking.ServiceSubnet)
return apiclient.NewDryRunClient(dryRunGetter, os.Stdout), nil
}
// If we're acting for real, we should create a connection to the API server and wait for it to come up
return kubeconfigutil.ClientSetFromFile(kubeadmconstants.GetAdminKubeConfigPath())
}
// getDirectoriesToUse returns the (in order) certificates, kubeconfig and Static Pod manifest directories, followed by a possible error
// This behaves differently when dry-running vs the normal flow
func getDirectoriesToUse(dryRun bool, defaultPkiDir string) (string, string, string, string, error) {
func getDirectoriesToUse(dryRun bool, dryRunDir string, defaultPkiDir string) (string, string, string, string, error) {
if dryRun {
dryRunDir, err := ioutil.TempDir("", "kubeadm-init-dryrun")
if err != nil {
return "", "", "", "", fmt.Errorf("couldn't create a temporary directory: %v", err)
}
// Use the same temp dir for all
return dryRunDir, dryRunDir, dryRunDir, dryRunDir, nil
}
@ -574,67 +485,16 @@ func getDirectoriesToUse(dryRun bool, defaultPkiDir string) (string, string, str
return defaultPkiDir, kubeadmconstants.KubernetesDir, kubeadmconstants.GetStaticPodDirectory(), kubeadmconstants.KubeletRunDirectory, nil
}
// printFilesIfDryRunning prints the Static Pod manifests to stdout and informs about the temporary directory to go and lookup
func printFilesIfDryRunning(dryRun bool, manifestDir string) error {
if !dryRun {
return nil
}
// showJoinCommand prints the join command after all the phases in init have finished
func showJoinCommand(i *initData, out io.Writer) error {
adminKubeConfigPath := i.KubeConfigPath()
fmt.Printf("[dryrun] wrote certificates, kubeconfig files and control plane manifests to the %q directory\n", manifestDir)
fmt.Println("[dryrun] the certificates or kubeconfig files would not be printed due to their sensitive nature")
fmt.Printf("[dryrun] please examine the %q directory for details about what would be written\n", manifestDir)
// Print the contents of the upgraded manifests and pretend like they were in /etc/kubernetes/manifests
files := []dryrunutil.FileToPrint{}
// Print static pod manifests
for _, component := range kubeadmconstants.MasterComponents {
realPath := kubeadmconstants.GetStaticPodFilepath(component, manifestDir)
outputPath := kubeadmconstants.GetStaticPodFilepath(component, kubeadmconstants.GetStaticPodDirectory())
files = append(files, dryrunutil.NewFileToPrint(realPath, outputPath))
}
// Print kubelet config manifests
kubeletConfigFiles := []string{kubeadmconstants.KubeletConfigurationFileName, kubeadmconstants.KubeletEnvFileName}
for _, filename := range kubeletConfigFiles {
realPath := filepath.Join(manifestDir, filename)
outputPath := filepath.Join(kubeadmconstants.KubeletRunDirectory, filename)
files = append(files, dryrunutil.NewFileToPrint(realPath, outputPath))
}
return dryrunutil.PrintDryRunFiles(files, os.Stdout)
}
// getWaiter gets the right waiter implementation for the right occasion
func getWaiter(i *Init, client clientset.Interface) apiclient.Waiter {
if i.dryRun {
return dryrunutil.NewWaiter()
}
// We know that the images should be cached locally already as we have pulled them using
// crictl in the preflight checks. Hence we can have a pretty short timeout for the kubelet
// to start creating Static Pods.
timeout := 4 * time.Minute
return apiclient.NewKubeWaiter(client, timeout, os.Stdout)
}
// waitForKubeletAndFunc waits primarily for the function f to execute, even though it might take some time. If that takes a long time, and the kubelet
// /healthz continuously are unhealthy, kubeadm will error out after a period of exponential backoff
func waitForKubeletAndFunc(waiter apiclient.Waiter, f func() error) error {
errorChan := make(chan error)
go func(errC chan error, waiter apiclient.Waiter) {
// This goroutine can only make kubeadm init fail. If this check succeeds, it won't do anything special
// TODO: Make 10248 a constant somewhere
if err := waiter.WaitForHealthyKubelet(40*time.Second, "http://localhost:10248/healthz"); err != nil {
errC <- err
// Prints the join command, multiple times in case the user has multiple tokens
for _, token := range i.Tokens() {
if err := printJoinCommand(out, adminKubeConfigPath, token, i.skipTokenPrint); err != nil {
return errors.Wrap(err, "failed to print join command")
}
}(errorChan, waiter)
}
go func(errC chan error, waiter apiclient.Waiter) {
// This main goroutine sends whatever the f function returns (error or not) to the channel
// This in order to continue on success (nil error), or just fail if the function returns an error
errC <- f()
}(errorChan, waiter)
// This call is blocking until one of the goroutines sends to errorChan
return <-errorChan
return nil
}

View File

@ -17,29 +17,36 @@ limitations under the License.
package cmd
import (
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/golang/glog"
"github.com/pkg/errors"
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
certutil "k8s.io/client-go/util/cert"
"k8s.io/klog"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
markcontrolplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markcontrolplane"
patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
uploadconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
@ -49,15 +56,45 @@ import (
)
var (
joinDoneMsgf = dedent.Dedent(`
joinWorkerNodeDoneMsg = dedent.Dedent(`
This node has joined the cluster:
* Certificate signing request was sent to master and a response
was received.
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the master to see this node join the cluster.
`)
notReadyToJoinControPlaneTemp = template.Must(template.New("join").Parse(dedent.Dedent(`
One or more conditions for hosting a new control plane instance is not satisfied.
{{.Error}}
Please ensure that:
* The cluster has a stable controlPlaneEndpoint address.
* The certificates that must be shared among control plane instances are provided.
`)))
joinControPlaneDoneTemp = template.Must(template.New("join").Parse(dedent.Dedent(`
This node has joined the cluster and a new control plane instance was created:
* Certificate signing request was sent to apiserver and approval was received.
* The Kubelet was informed of the new secure connection details.
* Master label and taint were applied to the new node.
* The Kubernetes control plane instances scaled up.
{{.etcdMessage}}
To start administering your cluster from this node, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i {{.KubeConfigPath}} $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Run 'kubectl get nodes' to see this node join the cluster.
`)))
joinLongDescription = dedent.Dedent(`
When joining a kubeadm initialized cluster, we need to establish
bidirectional trust. This is split into discovery (having the Node
@ -82,7 +119,7 @@ var (
where the supported hash type is "sha256". The hash is calculated over
the bytes of the Subject Public Key Info (SPKI) object (as in RFC7469).
This value is available in the output of "kubeadm init" or can be
calcuated using standard tools. The --discovery-token-ca-cert-hash flag
calculated using standard tools. The --discovery-token-ca-cert-hash flag
may be repeated multiple times to allow more than one public key.
If you cannot know the CA public key hash ahead of time, you can pass
@ -101,7 +138,7 @@ var (
--token flag can be used instead of specifying each token individually.
`)
kubeadmJoinFailMsgf = dedent.Dedent(`
kubeadmJoinFailMsg = dedent.Dedent(`
Unfortunately, an error has occurred:
%v
@ -117,155 +154,338 @@ var (
// NewCmdJoin returns "kubeadm join" command.
func NewCmdJoin(out io.Writer) *cobra.Command {
cfg := &kubeadmapiv1alpha2.NodeConfiguration{}
cfg := &kubeadmapiv1beta1.JoinConfiguration{}
kubeadmscheme.Scheme.Default(cfg)
var skipPreFlight bool
fd := &kubeadmapiv1beta1.FileDiscovery{}
btd := &kubeadmapiv1beta1.BootstrapTokenDiscovery{}
var token string
var cfgPath string
var featureGatesString string
var ignorePreflightErrors []string
var controlPlane bool
var advertiseAddress string
var bindPort int32 = kubeadmapiv1beta1.DefaultAPIBindPort
cmd := &cobra.Command{
Use: "join",
Short: "Run this on any machine you wish to join an existing cluster",
Long: joinLongDescription,
Run: func(cmd *cobra.Command, args []string) {
j, err := NewValidJoin(cmd.PersistentFlags(), cfg, args, skipPreFlight, cfgPath, featureGatesString, ignorePreflightErrors)
if len(fd.KubeConfigPath) != 0 {
cfg.Discovery.File = fd
} else {
cfg.Discovery.BootstrapToken = btd
if len(cfg.Discovery.BootstrapToken.Token) == 0 {
cfg.Discovery.BootstrapToken.Token = token
}
if len(args) > 0 {
if len(cfgPath) == 0 && len(args) > 1 {
klog.Warningf("[join] WARNING: More than one API server endpoint supplied on command line %v. Using the first one.", args)
}
cfg.Discovery.BootstrapToken.APIServerEndpoint = args[0]
}
}
if len(cfg.Discovery.TLSBootstrapToken) == 0 {
cfg.Discovery.TLSBootstrapToken = token
}
if controlPlane {
cfg.ControlPlane = &kubeadmapiv1beta1.JoinControlPlane{
LocalAPIEndpoint: kubeadmapiv1beta1.APIEndpoint{
AdvertiseAddress: advertiseAddress,
BindPort: bindPort,
},
}
}
j, err := NewValidJoin(cmd.PersistentFlags(), cfg, cfgPath, ignorePreflightErrors)
kubeadmutil.CheckErr(err)
kubeadmutil.CheckErr(j.Run(out))
},
}
AddJoinConfigFlags(cmd.PersistentFlags(), cfg, &featureGatesString)
AddJoinOtherFlags(cmd.PersistentFlags(), &cfgPath, &skipPreFlight, &ignorePreflightErrors)
AddJoinConfigFlags(cmd.PersistentFlags(), cfg, &token)
AddJoinBootstrapTokenDiscoveryFlags(cmd.PersistentFlags(), btd)
AddJoinFileDiscoveryFlags(cmd.PersistentFlags(), fd)
AddJoinOtherFlags(cmd.PersistentFlags(), &cfgPath, &ignorePreflightErrors, &controlPlane, &advertiseAddress, &bindPort)
return cmd
}
// NewValidJoin validates the command line that are passed to the cobra command
func NewValidJoin(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.NodeConfiguration, args []string, skipPreFlight bool, cfgPath, featureGatesString string, ignorePreflightErrors []string) (*Join, error) {
cfg.DiscoveryTokenAPIServers = args
func NewValidJoin(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.JoinConfiguration, cfgPath string, ignorePreflightErrors []string) (*Join, error) {
var err error
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
if err = validation.ValidateMixedArguments(flagSet); err != nil {
return nil, err
}
if err := validation.ValidateMixedArguments(flagSet); err != nil {
return nil, err
}
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight)
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors)
if err != nil {
return nil, err
}
return NewJoin(cfgPath, args, cfg, ignorePreflightErrorsSet)
return NewJoin(cfgPath, cfg, ignorePreflightErrorsSet)
}
// AddJoinConfigFlags adds join flags bound to the config to the specified flagset
func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1alpha2.NodeConfiguration, featureGatesString *string) {
flagSet.StringVar(
&cfg.DiscoveryFile, "discovery-file", "",
"A file or url from which to load cluster information.")
flagSet.StringVar(
&cfg.DiscoveryToken, "discovery-token", "",
"A token used to validate cluster information fetched from the master.")
func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiv1beta1.JoinConfiguration, token *string) {
flagSet.StringVar(
&cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name,
"Specify the node name.")
flagSet.StringVar(
&cfg.TLSBootstrapToken, "tls-bootstrap-token", "",
"A token used for TLS bootstrapping.")
flagSet.StringSliceVar(
&cfg.DiscoveryTokenCACertHashes, "discovery-token-ca-cert-hash", []string{},
"For token-based discovery, validate that the root CA public key matches this hash (format: \"<type>:<value>\").")
flagSet.BoolVar(
&cfg.DiscoveryTokenUnsafeSkipCAVerification, "discovery-token-unsafe-skip-ca-verification", false,
"For token-based discovery, allow joining without --discovery-token-ca-cert-hash pinning.")
flagSet.StringVar(
&cfg.Token, "token", "",
"Use this token for both discovery-token and tls-bootstrap-token.")
flagSet.StringVar(
featureGatesString, "feature-gates", *featureGatesString,
"A set of key=value pairs that describe feature gates for various features. "+
"Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n"))
token, "token", "",
"Use this token for both discovery-token and tls-bootstrap-token when those values are not provided.")
flagSet.StringVar(
&cfg.NodeRegistration.CRISocket, "cri-socket", cfg.NodeRegistration.CRISocket,
`Specify the CRI socket to connect to.`,
)
}
// AddJoinBootstrapTokenDiscoveryFlags adds bootstrap token specific discovery flags to the specified flagset
func AddJoinBootstrapTokenDiscoveryFlags(flagSet *flag.FlagSet, btd *kubeadmapiv1beta1.BootstrapTokenDiscovery) {
flagSet.StringVar(
&btd.Token, "discovery-token", "",
"A token used to validate cluster information fetched from the API server.")
flagSet.StringSliceVar(
&btd.CACertHashes, "discovery-token-ca-cert-hash", []string{},
"For token-based discovery, validate that the root CA public key matches this hash (format: \"<type>:<value>\").")
flagSet.BoolVar(
&btd.UnsafeSkipCAVerification, "discovery-token-unsafe-skip-ca-verification", false,
"For token-based discovery, allow joining without --discovery-token-ca-cert-hash pinning.")
}
// AddJoinFileDiscoveryFlags adds file discovery flags to the specified flagset
func AddJoinFileDiscoveryFlags(flagSet *flag.FlagSet, fd *kubeadmapiv1beta1.FileDiscovery) {
flagSet.StringVar(
&fd.KubeConfigPath, "discovery-file", "",
"A file or URL from which to load cluster information.")
}
// AddJoinOtherFlags adds join flags that are not bound to a configuration file to the given flagset
func AddJoinOtherFlags(flagSet *flag.FlagSet, cfgPath *string, skipPreFlight *bool, ignorePreflightErrors *[]string) {
func AddJoinOtherFlags(flagSet *flag.FlagSet, cfgPath *string, ignorePreflightErrors *[]string, controlPlane *bool, advertiseAddress *string, bindPort *int32) {
flagSet.StringVar(
cfgPath, "config", *cfgPath,
"Path to kubeadm config file.")
flagSet.StringSliceVar(
ignorePreflightErrors, "ignore-preflight-errors", *ignorePreflightErrors,
"A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.",
)
"A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.")
flagSet.BoolVar(
skipPreFlight, "skip-preflight-checks", false,
"Skip preflight checks which normally run before modifying the system.",
)
flagSet.MarkDeprecated("skip-preflight-checks", "it is now equivalent to --ignore-preflight-errors=all")
controlPlane, "experimental-control-plane", *controlPlane,
"Create a new control plane instance on this node")
flagSet.StringVar(
advertiseAddress, "apiserver-advertise-address", *advertiseAddress,
"If the node should host a new control plane instance, the IP address the API Server will advertise it's listening on.")
flagSet.Int32Var(
bindPort, "apiserver-bind-port", *bindPort,
"If the node should host a new control plane instance, the port for the API Server to bind to.")
}
// Join defines struct used by kubeadm join command
type Join struct {
cfg *kubeadmapi.NodeConfiguration
cfg *kubeadmapi.JoinConfiguration
initCfg *kubeadmapi.InitConfiguration
tlsBootstrapCfg *clientcmdapi.Config
ignorePreflightErrors sets.String
}
// NewJoin instantiates Join struct with given arguments
func NewJoin(cfgPath string, args []string, defaultcfg *kubeadmapiv1alpha2.NodeConfiguration, ignorePreflightErrors sets.String) (*Join, error) {
func NewJoin(cfgPath string, defaultcfg *kubeadmapiv1beta1.JoinConfiguration, ignorePreflightErrors sets.String) (*Join, error) {
if defaultcfg.NodeRegistration.Name == "" {
glog.V(1).Infoln("[join] found NodeName empty")
glog.V(1).Infoln("[join] considered OS hostname as NodeName")
klog.V(1).Infoln("[join] found NodeName empty; using OS hostname as NodeName")
}
internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig(cfgPath, defaultcfg)
if defaultcfg.ControlPlane != nil && defaultcfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress == "" {
klog.V(1).Infoln("[join] found advertiseAddress empty; using default interface's IP address as advertiseAddress")
}
internalCfg, err := configutil.JoinConfigFileAndDefaultsToInternalConfig(cfgPath, defaultcfg)
if err != nil {
return nil, err
}
fmt.Println("[preflight] running pre-flight checks")
// override node name and CRI socket from the command line options
if defaultcfg.NodeRegistration.Name != "" {
internalCfg.NodeRegistration.Name = defaultcfg.NodeRegistration.Name
}
if defaultcfg.NodeRegistration.CRISocket != kubeadmapiv1beta1.DefaultCRISocket {
internalCfg.NodeRegistration.CRISocket = defaultcfg.NodeRegistration.CRISocket
}
// Then continue with the others...
glog.V(1).Infoln("[preflight] running various checks on all nodes")
if err := preflight.RunJoinNodeChecks(utilsexec.New(), internalcfg, ignorePreflightErrors); err != nil {
if defaultcfg.ControlPlane != nil {
if err := configutil.VerifyAPIServerBindAddress(internalCfg.ControlPlane.LocalAPIEndpoint.AdvertiseAddress); err != nil {
return nil, err
}
}
fmt.Println("[preflight] Running pre-flight checks")
// Start with general checks
klog.V(1).Infoln("[preflight] Running general checks")
if err := preflight.RunJoinNodeChecks(utilsexec.New(), internalCfg, ignorePreflightErrors); err != nil {
return nil, err
}
return &Join{cfg: internalcfg, ignorePreflightErrors: ignorePreflightErrors}, nil
// Fetch the init configuration based on the join configuration
klog.V(1).Infoln("[preflight] Fetching init configuration")
initCfg, tlsBootstrapCfg, err := fetchInitConfigurationFromJoinConfiguration(internalCfg)
if err != nil {
return nil, err
}
// Continue with more specific checks based on the init configuration
klog.V(1).Infoln("[preflight] Running configuration dependant checks")
if err := preflight.RunOptionalJoinNodeChecks(utilsexec.New(), initCfg, ignorePreflightErrors); err != nil {
return nil, err
}
return &Join{cfg: internalCfg, initCfg: initCfg, tlsBootstrapCfg: tlsBootstrapCfg, ignorePreflightErrors: ignorePreflightErrors}, nil
}
// Run executes worker node provisioning and tries to join an existing cluster.
func (j *Join) Run(out io.Writer) error {
if j.cfg.ControlPlane != nil {
// Checks if the cluster configuration supports
// joining a new control plane instance and if all the necessary certificates are provided
if err := j.CheckIfReadyForAdditionalControlPlane(j.initCfg); err != nil {
// outputs the not ready for hosting a new control plane instance message
ctx := map[string]string{
"Error": err.Error(),
}
// Perform the Discovery, which turns a Bootstrap Token and optionally (and preferably) a CA cert hash into a KubeConfig
// file that may be used for the TLS Bootstrapping process the kubelet performs using the Certificates API.
glog.V(1).Infoln("[join] retrieving KubeConfig objects")
cfg, err := discovery.For(j.cfg)
if err != nil {
var msg bytes.Buffer
notReadyToJoinControPlaneTemp.Execute(&msg, ctx)
return errors.New(msg.String())
}
// run kubeadm init preflight checks for checking all the prequisites
fmt.Printf("[join] Running pre-flight checks before initializing the new control plane instance\n")
preflight.RunInitMasterChecks(utilsexec.New(), j.initCfg, j.ignorePreflightErrors)
// Prepares the node for hosting a new control plane instance by writing necessary
// kubeconfig files, and static pod manifests
if err := j.PrepareForHostingControlPlane(j.initCfg); err != nil {
return err
}
}
// Executes the kubelet TLS bootstrap process, that completes with the node
// joining the cluster with a dedicates set of credentials as required by
// the node authorizer.
// if the node is hosting a new control plane instance, since it uses static pods for the control plane,
// as soon as the kubelet starts it will take charge of creating control plane
// components on the node.
if err := j.BootstrapKubelet(); err != nil {
return err
}
// if the node is hosting a new control plane instance
if j.cfg.ControlPlane != nil {
// Completes the control plane setup
if err := j.PostInstallControlPlane(j.initCfg); err != nil {
return err
}
// outputs the join control plane done template and exits
etcdMessage := ""
// in case of local etcd
if j.initCfg.Etcd.External == nil {
etcdMessage = "* A new etcd member was added to the local/stacked etcd cluster."
}
ctx := map[string]string{
"KubeConfigPath": kubeadmconstants.GetAdminKubeConfigPath(),
"etcdMessage": etcdMessage,
}
joinControPlaneDoneTemp.Execute(out, ctx)
return nil
}
// otherwise, if the node joined as a worker node;
// outputs the join done message and exits
fmt.Fprintf(out, joinWorkerNodeDoneMsg)
return nil
}
// CheckIfReadyForAdditionalControlPlane ensures that the cluster is in a state that supports
// joining an additional control plane instance and if the node is ready to join
func (j *Join) CheckIfReadyForAdditionalControlPlane(initConfiguration *kubeadmapi.InitConfiguration) error {
// blocks if the cluster was created without a stable control plane endpoint
if initConfiguration.ControlPlaneEndpoint == "" {
return errors.New("unable to add a new control plane instance a cluster that doesn't have a stable controlPlaneEndpoint address")
}
// checks if the certificates that must be equal across contolplane instances are provided
if ret, err := certsphase.SharedCertificateExists(initConfiguration); !ret {
return err
}
return nil
}
// PrepareForHostingControlPlane makes all preparation activities require for a node hosting a new control plane instance
func (j *Join) PrepareForHostingControlPlane(initConfiguration *kubeadmapi.InitConfiguration) error {
// Generate missing certificates (if any)
if err := certsphase.CreatePKIAssets(initConfiguration); err != nil {
return err
}
// Generate kubeconfig files for controller manager, scheduler and for the admin/kubeadm itself
// NB. The kubeconfig file for kubelet will be generated by the TLS bootstrap process in
// following steps of the join --experimental-control plane workflow
if err := kubeconfigphase.CreateJoinControlPlaneKubeConfigFiles(kubeadmconstants.KubernetesDir, initConfiguration); err != nil {
return errors.Wrap(err, "error generating kubeconfig files")
}
// Creates static pod manifests file for the control plane components to be deployed on this node
// Static pods will be created and managed by the kubelet as soon as it starts
if err := controlplanephase.CreateInitStaticPodManifestFiles(kubeadmconstants.GetStaticPodDirectory(), initConfiguration); err != nil {
return errors.Wrap(err, "error creating static pod manifest files for the control plane components")
}
// in case of local etcd
if initConfiguration.Etcd.External == nil {
// Checks that the etcd cluster is healthy
// NB. this check cannot be implemented before because it requires the admin.conf and all the certificates
// for connecting to etcd already in place
kubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.AdminKubeConfigFileName)
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
if err != nil {
return errors.Wrap(err, "couldn't create Kubernetes client")
}
if err := etcdphase.CheckLocalEtcdClusterStatus(client, initConfiguration); err != nil {
return err
}
}
return nil
}
// BootstrapKubelet executes the kubelet TLS bootstrap process.
// This process is executed by the kubelet and completes with the node joining the cluster
// with a dedicates set of credentials as required by the node authorizer
func (j *Join) BootstrapKubelet() error {
bootstrapKubeConfigFile := kubeadmconstants.GetBootstrapKubeletKubeConfigPath()
// Write the bootstrap kubelet config file or the TLS-Boostrapped kubelet config file down to disk
glog.V(1).Infoln("[join] writing bootstrap kubelet config file at", bootstrapKubeConfigFile)
if err := kubeconfigutil.WriteToDisk(bootstrapKubeConfigFile, cfg); err != nil {
return fmt.Errorf("couldn't save bootstrap-kubelet.conf to disk: %v", err)
klog.V(1).Infoln("[join] writing bootstrap kubelet config file at", bootstrapKubeConfigFile)
if err := kubeconfigutil.WriteToDisk(bootstrapKubeConfigFile, j.tlsBootstrapCfg); err != nil {
return errors.Wrap(err, "couldn't save bootstrap-kubelet.conf to disk")
}
// Write the ca certificate to disk so kubelet can use it for authentication
cluster := cfg.Contexts[cfg.CurrentContext].Cluster
if err := certutil.WriteCert(j.cfg.CACertPath, cfg.Clusters[cluster].CertificateAuthorityData); err != nil {
return fmt.Errorf("couldn't save the CA certificate to disk: %v", err)
cluster := j.tlsBootstrapCfg.Contexts[j.tlsBootstrapCfg.CurrentContext].Cluster
if _, err := os.Stat(j.cfg.CACertPath); os.IsNotExist(err) {
if err := certutil.WriteCert(j.cfg.CACertPath, j.tlsBootstrapCfg.Clusters[cluster].CertificateAuthorityData); err != nil {
return errors.Wrap(err, "couldn't save the CA certificate to disk")
}
}
kubeletVersion, err := preflight.GetKubeletVersion(utilsexec.New())
@ -275,34 +495,37 @@ func (j *Join) Run(out io.Writer) error {
bootstrapClient, err := kubeconfigutil.ClientSetFromFile(bootstrapKubeConfigFile)
if err != nil {
return fmt.Errorf("couldn't create client from kubeconfig file %q", bootstrapKubeConfigFile)
return errors.Errorf("couldn't create client from kubeconfig file %q", bootstrapKubeConfigFile)
}
// Configure the kubelet. In this short timeframe, kubeadm is trying to stop/restart the kubelet
// Try to stop the kubelet service so no race conditions occur when configuring it
glog.V(1).Infof("Stopping the kubelet")
preflight.TryStopKubelet()
klog.V(1).Infof("Stopping the kubelet")
kubeletphase.TryStopKubelet()
// Write the configuration for the kubelet (using the bootstrap token credentials) to disk so the kubelet can start
if err := kubeletphase.DownloadConfig(bootstrapClient, kubeletVersion, kubeadmconstants.KubeletRunDirectory); err != nil {
return err
}
// Write env file with flags for the kubelet to use. Also register taints
if err := kubeletphase.WriteKubeletDynamicEnvFile(&j.cfg.NodeRegistration, j.cfg.FeatureGates, true, kubeadmconstants.KubeletRunDirectory); err != nil {
// Write env file with flags for the kubelet to use. We only want to
// register the joining node with the specified taints if the node
// is not a master. The markmaster phase will register the taints otherwise.
registerTaintsUsingFlags := j.cfg.ControlPlane == nil
if err := kubeletphase.WriteKubeletDynamicEnvFile(j.initCfg, registerTaintsUsingFlags, kubeadmconstants.KubeletRunDirectory); err != nil {
return err
}
// Try to start the kubelet service in case it's inactive
glog.V(1).Infof("Starting the kubelet")
preflight.TryStartKubelet()
klog.V(1).Infof("Starting the kubelet")
kubeletphase.TryStartKubelet()
// Now the kubelet will perform the TLS Bootstrap, transforming /etc/kubernetes/bootstrap-kubelet.conf to /etc/kubernetes/kubelet.conf
// Wait for the kubelet to create the /etc/kubernetes/kubelet.conf KubeConfig file. If this process
// Wait for the kubelet to create the /etc/kubernetes/kubelet.conf kubeconfig file. If this process
// times out, display a somewhat user-friendly message.
waiter := apiclient.NewKubeWaiter(nil, kubeadmconstants.TLSBootstrapTimeout, os.Stdout)
if err := waitForKubeletAndFunc(waiter, waitForTLSBootstrappedClient); err != nil {
fmt.Printf(kubeadmJoinFailMsgf, err)
if err := waiter.WaitForKubeletAndFunc(waitForTLSBootstrappedClient); err != nil {
fmt.Printf(kubeadmJoinFailMsg, err)
return err
}
@ -312,19 +535,50 @@ func (j *Join) Run(out io.Writer) error {
return err
}
glog.V(1).Infof("[join] preserving the crisocket information for the node")
klog.V(1).Infof("[join] preserving the crisocket information for the node")
if err := patchnodephase.AnnotateCRISocket(client, j.cfg.NodeRegistration.Name, j.cfg.NodeRegistration.CRISocket); err != nil {
return fmt.Errorf("error uploading crisocket: %v", err)
return errors.Wrap(err, "error uploading crisocket")
}
// This feature is disabled by default in kubeadm
if features.Enabled(j.cfg.FeatureGates, features.DynamicKubeletConfig) {
if err := kubeletphase.EnableDynamicConfigForNode(client, j.cfg.NodeRegistration.Name, kubeletVersion); err != nil {
return fmt.Errorf("error consuming base kubelet configuration: %v", err)
return nil
}
// PostInstallControlPlane marks the new node as master and update the cluster status with information about current node
func (j *Join) PostInstallControlPlane(initConfiguration *kubeadmapi.InitConfiguration) error {
kubeConfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.AdminKubeConfigFileName)
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
if err != nil {
return errors.Wrap(err, "couldn't create Kubernetes client")
}
// in case of local etcd
if initConfiguration.Etcd.External == nil {
// Adds a new etcd instance; in order to do this the new etcd instance should be "announced" to
// the existing etcd members before being created.
// This operation must be executed after kubelet is already started in order to minimize the time
// between the new etcd member is announced and the start of the static pod running the new etcd member, because during
// this time frame etcd gets temporary not available (only when moving from 1 to 2 members in the etcd cluster).
// From https://coreos.com/etcd/docs/latest/v2/runtime-configuration.html
// "If you add a new member to a 1-node cluster, the cluster cannot make progress before the new member starts
// because it needs two members as majority to agree on the consensus. You will only see this behavior between the time
// etcdctl member add informs the cluster about the new member and the new member successfully establishing a connection to the existing one."
klog.V(1).Info("[join] adding etcd")
if err := etcdphase.CreateStackedEtcdStaticPodManifestFile(client, kubeadmconstants.GetStaticPodDirectory(), initConfiguration); err != nil {
return errors.Wrap(err, "error creating local etcd static pod manifest file")
}
}
fmt.Fprintf(out, joinDoneMsgf)
klog.V(1).Info("[join] uploading currently used configuration to the cluster")
if err := uploadconfigphase.UploadConfiguration(initConfiguration, client); err != nil {
return errors.Wrap(err, "error uploading configuration")
}
klog.V(1).Info("[join] marking the control-plane with right label")
if err = markcontrolplanephase.MarkControlPlane(client, initConfiguration.NodeRegistration.Name, initConfiguration.NodeRegistration.Taints); err != nil {
return errors.Wrap(err, "error applying control-plane label and taints")
}
return nil
}
@ -339,3 +593,53 @@ func waitForTLSBootstrappedClient() error {
return (err == nil), nil
})
}
// fetchInitConfigurationFromJoinConfiguration retrieves the init configuration from a join configuration, performing the discovery
func fetchInitConfigurationFromJoinConfiguration(cfg *kubeadmapi.JoinConfiguration) (*kubeadmapi.InitConfiguration, *clientcmdapi.Config, error) {
// Perform the Discovery, which turns a Bootstrap Token and optionally (and preferably) a CA cert hash into a KubeConfig
// file that may be used for the TLS Bootstrapping process the kubelet performs using the Certificates API.
klog.V(1).Infoln("[join] Discovering cluster-info")
tlsBootstrapCfg, err := discovery.For(cfg)
if err != nil {
return nil, nil, err
}
// Retrieves the kubeadm configuration
klog.V(1).Infoln("[join] Retrieving KubeConfig objects")
initConfiguration, err := fetchInitConfiguration(tlsBootstrapCfg)
if err != nil {
return nil, nil, err
}
// Create the final KubeConfig file with the cluster name discovered after fetching the cluster configuration
clusterinfo := kubeconfigutil.GetClusterFromKubeConfig(tlsBootstrapCfg)
tlsBootstrapCfg.Clusters = map[string]*clientcmdapi.Cluster{
initConfiguration.ClusterName: clusterinfo,
}
tlsBootstrapCfg.Contexts[tlsBootstrapCfg.CurrentContext].Cluster = initConfiguration.ClusterName
// injects into the kubeadm configuration the information about the joining node
initConfiguration.NodeRegistration = cfg.NodeRegistration
if cfg.ControlPlane != nil {
initConfiguration.LocalAPIEndpoint = cfg.ControlPlane.LocalAPIEndpoint
}
return initConfiguration, tlsBootstrapCfg, nil
}
// fetchInitConfiguration reads the cluster configuration from the kubeadm-admin configMap
func fetchInitConfiguration(tlsBootstrapCfg *clientcmdapi.Config) (*kubeadmapi.InitConfiguration, error) {
// creates a client to access the cluster using the bootstrap token identity
tlsClient, err := kubeconfigutil.ToClientSet(tlsBootstrapCfg)
if err != nil {
return nil, errors.Wrap(err, "unable to access the cluster")
}
// Fetches the init configuration
initConfiguration, err := configutil.FetchConfigFromFileOrCluster(tlsClient, os.Stdout, "join", "", true)
if err != nil {
return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap")
}
return initConfiguration, nil
}

View File

@ -25,7 +25,7 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
)
const (
@ -70,16 +70,14 @@ func TestNewValidJoin(t *testing.T) {
testCases := []struct {
name string
args []string
skipPreFlight bool
cfgPath string
configToWrite string
featureGatesString string
ignorePreflightErrors []string
testJoinValidate bool
testJoinRun bool
cmdPersistentFlags map[string]string
nodeConfig *kubeadm.NodeConfiguration
nodeConfig *kubeadm.JoinConfiguration
expectedError bool
}{
{
@ -110,11 +108,6 @@ func TestNewValidJoin(t *testing.T) {
ignorePreflightErrors: []string{"some-unsupported-preflight-arg"},
expectedError: true,
},
{
name: "invalid: incorrect featureGatesString",
featureGatesString: "bad-feature-gate-string",
expectedError: true,
},
{
name: "invalid: fail Join.Validate() with wrong flags",
skipPreFlight: true,
@ -146,7 +139,7 @@ func TestNewValidJoin(t *testing.T) {
}
var out bytes.Buffer
cfg := &kubeadmapiv1alpha2.NodeConfiguration{}
cfg := &kubeadmapiv1beta1.JoinConfiguration{}
kubeadmscheme.Scheme.Default(cfg)
errorFormat := "Test case %q: NewValidJoin expected error: %v, saw: %v, error: %v"
@ -163,7 +156,7 @@ func TestNewValidJoin(t *testing.T) {
}
}
join, err := NewValidJoin(cmd.PersistentFlags(), cfg, tc.args, tc.skipPreFlight, tc.cfgPath, tc.featureGatesString, tc.ignorePreflightErrors)
join, err := NewValidJoin(cmd.PersistentFlags(), cfg, tc.cfgPath, tc.ignorePreflightErrors)
if tc.nodeConfig != nil {
join.cfg = tc.nodeConfig

View File

@ -3,16 +3,20 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"certs.go",
"constant.go",
"doc.go",
"generic.go",
"token.go",
],
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options",
visibility = ["//visibility:public"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/flag:go_default_library",
"//staging/src/k8s.io/cluster-bootstrap/token/api:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
],
)

View File

@ -0,0 +1,34 @@
/*
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 options
import "github.com/spf13/pflag"
// AddCertificateDirFlag adds the --certs-dir flag to the given flagset
func AddCertificateDirFlag(fs *pflag.FlagSet, certsDir *string) {
fs.StringVar(certsDir, CertificatesDir, *certsDir, "The path where to save the certificates")
}
// AddCSRFlag adds the --csr-only flag to the given flagset
func AddCSRFlag(fs *pflag.FlagSet, csr *bool) {
fs.BoolVar(csr, CSROnly, *csr, "Create CSRs instead of generating certificates")
}
// AddCSRDirFlag adds the --csr-dir flag to the given flagset
func AddCSRDirFlag(fs *pflag.FlagSet, csrDir *string) {
fs.StringVar(csrDir, CSRDir, *csrDir, "The path to output the CSRs and private keys to")
}

View File

@ -0,0 +1,86 @@
/*
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 options
// APIServerAdvertiseAddress flag sets the IP address the API Server will advertise it's listening on. Specify '0.0.0.0' to use the address of the default network interface.
const APIServerAdvertiseAddress = "apiserver-advertise-address"
// APIServerBindPort flag sets the port for the API Server to bind to.
const APIServerBindPort = "apiserver-bind-port"
// APIServerCertSANs flag sets extra Subject Alternative Names (SANs) to use for the API Server serving certificate. Can be both IP addresses and DNS names.
const APIServerCertSANs = "apiserver-cert-extra-sans"
// APIServerExtraArgs flag sets a extra flags to pass to the API Server or override default ones in form of <flagname>=<value>.
const APIServerExtraArgs = "apiserver-extra-args"
// CertificatesDir flag sets the path where to save and read the certificates.
const CertificatesDir = "cert-dir"
// CfgPath flag sets the path to kubeadm config file.
const CfgPath = "config"
// ControllerManagerExtraArgs flag sets extra flags to pass to the Controller Manager or override default ones in form of <flagname>=<value>.
const ControllerManagerExtraArgs = "controller-manager-extra-args"
// DryRun flag instruct kubeadm to don't apply any changes; just output what would be done.
const DryRun = "dry-run"
// FeatureGatesString flag sets key=value pairs that describe feature gates for various features.
const FeatureGatesString = "feature-gates"
// IgnorePreflightErrors sets the path a list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.
const IgnorePreflightErrors = "ignore-preflight-errors"
// ImageRepository sets the container registry to pull control plane images from.
const ImageRepository = "image-repository"
// KubeconfigDir flag sets the path where to save the kubeconfig file.
const KubeconfigDir = "kubeconfig-dir"
// KubeconfigPath flag sets the kubeconfig file to use when talking to the cluster. If the flag is not set, a set of standard locations are searched for an existing KubeConfig file.
const KubeconfigPath = "kubeconfig"
// KubernetesVersion flag sets the Kubernetes version for the control plane.
const KubernetesVersion = "kubernetes-version"
// NetworkingDNSDomain flag sets the domain for services, e.g. "myorg.internal".
const NetworkingDNSDomain = "service-dns-domain"
// NetworkingServiceSubnet flag sets the range of IP address for service VIPs.
const NetworkingServiceSubnet = "service-cidr"
// NetworkingPodSubnet flag sets the range of IP addresses for the pod network. If set, the control plane will automatically allocate CIDRs for every node.
const NetworkingPodSubnet = "pod-network-cidr"
// NodeCRISocket flag sets the CRI socket to connect to.
const NodeCRISocket = "cri-socket"
// NodeName flag sets the node name.
const NodeName = "node-name"
// SchedulerExtraArgs flag sets extra flags to pass to the Scheduler or override default ones in form of <flagname>=<value>".
const SchedulerExtraArgs = "scheduler-extra-args"
// SkipTokenPrint flag instruct kubeadm to skip printing of the default bootstrap token generated by 'kubeadm init'.
const SkipTokenPrint = "skip-token-print"
// CSROnly flag instructs kubeadm to create CSRs instead of automatically creating or renewing certs
const CSROnly = "csr-only"
// CSRDir flag sets the location for CSRs and flags to be output
const CSRDir = "csr-dir"

View File

@ -0,0 +1,29 @@
/*
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 options provide a central point for defining flags for kubeadm cobra commands,
no matter if hard coded commands or autogenerated command for phases.
New kubeadm flags should always be defined in this package as a constant before their usage,
in order to enforce naming consistency across different commands and to control flag proliferation.
In addition to defining the flags, the package also contains set of utilities for flag management.
For additional details about how flags are managed in phases, please refer to the
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" package.
*/
package options

View File

@ -16,14 +16,42 @@ limitations under the License.
package options
import "github.com/spf13/pflag"
import (
"github.com/spf13/pflag"
utilflag "k8s.io/apiserver/pkg/util/flag"
)
// AddKubeConfigFlag adds the --kubeconfig flag to the given flagset
func AddKubeConfigFlag(fs *pflag.FlagSet, kubeConfigFile *string) {
fs.StringVar(kubeConfigFile, "kubeconfig", *kubeConfigFile, "The KubeConfig file to use when talking to the cluster")
fs.StringVar(kubeConfigFile, KubeconfigPath, *kubeConfigFile, "The kubeconfig file to use when talking to the cluster. If the flag is not set, a set of standard locations are searched for an existing KubeConfig file.")
}
// AddKubeConfigDirFlag adds the --kubeconfig-dir flag to the given flagset
func AddKubeConfigDirFlag(fs *pflag.FlagSet, kubeConfigDir *string) {
fs.StringVar(kubeConfigDir, KubeconfigDir, *kubeConfigDir, "The path where to save the kubeconfig file.")
}
// AddConfigFlag adds the --config flag to the given flagset
func AddConfigFlag(fs *pflag.FlagSet, cfgPath *string) {
fs.StringVar(cfgPath, "config", *cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)")
fs.StringVar(cfgPath, CfgPath, *cfgPath, "Path to a kubeadm configuration file.")
}
// AddIgnorePreflightErrorsFlag adds the --ignore-preflight-errors flag to the given flagset
func AddIgnorePreflightErrorsFlag(fs *pflag.FlagSet, ignorePreflightErrors *[]string) {
fs.StringSliceVar(
ignorePreflightErrors, IgnorePreflightErrors, *ignorePreflightErrors,
"A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.",
)
}
// AddControlPlanExtraArgsFlags adds the ExtraArgs flags for control plane components
func AddControlPlanExtraArgsFlags(fs *pflag.FlagSet, apiServerExtraArgs, controllerManagerExtraArgs, schedulerExtraArgs *map[string]string) {
fs.Var(utilflag.NewMapStringString(apiServerExtraArgs), APIServerExtraArgs, "A set of extra flags to pass to the API Server or override default ones in form of <flagname>=<value>")
fs.Var(utilflag.NewMapStringString(controllerManagerExtraArgs), ControllerManagerExtraArgs, "A set of extra flags to pass to the Controller Manager or override default ones in form of <flagname>=<value>")
fs.Var(utilflag.NewMapStringString(schedulerExtraArgs), SchedulerExtraArgs, "A set of extra flags to pass to the Scheduler or override default ones in form of <flagname>=<value>")
}
// AddImageMetaFlags adds the --image-repository flag to the given flagset
func AddImageMetaFlags(fs *pflag.FlagSet, imageRepository *string) {
fs.StringVar(imageRepository, ImageRepository, *imageRepository, "Choose a container registry to pull control plane images from")
}

View File

@ -22,23 +22,23 @@ import (
"github.com/spf13/pflag"
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
)
// NewBootstrapTokenOptions creates a new BootstrapTokenOptions object with the default values
func NewBootstrapTokenOptions() *BootstrapTokenOptions {
bto := &BootstrapTokenOptions{&kubeadmapiv1alpha2.BootstrapToken{}, ""}
kubeadmapiv1alpha2.SetDefaults_BootstrapToken(bto.BootstrapToken)
bto := &BootstrapTokenOptions{&kubeadmapiv1beta1.BootstrapToken{}, ""}
kubeadmapiv1beta1.SetDefaults_BootstrapToken(bto.BootstrapToken)
return bto
}
// BootstrapTokenOptions is a wrapper struct for adding bootstrap token-related flags to a FlagSet
// and applying the parsed flags to a MasterConfiguration object later at runtime
// and applying the parsed flags to a InitConfiguration object later at runtime
// TODO: In the future, we might want to group the flags in a better way than adding them all individually like this
type BootstrapTokenOptions struct {
*kubeadmapiv1alpha2.BootstrapToken
*kubeadmapiv1beta1.BootstrapToken
TokenStr string
}
@ -87,18 +87,18 @@ func (bto *BootstrapTokenOptions) AddDescriptionFlag(fs *pflag.FlagSet) {
)
}
// ApplyTo applies the values set internally in the BootstrapTokenOptions object to a MasterConfiguration object at runtime
// ApplyTo applies the values set internally in the BootstrapTokenOptions object to a InitConfiguration object at runtime
// If --token was specified in the CLI (as a string), it's parsed and validated before it's added to the BootstrapToken object.
func (bto *BootstrapTokenOptions) ApplyTo(cfg *kubeadmapiv1alpha2.MasterConfiguration) error {
func (bto *BootstrapTokenOptions) ApplyTo(cfg *kubeadmapiv1beta1.InitConfiguration) error {
if len(bto.TokenStr) > 0 {
var err error
bto.Token, err = kubeadmapiv1alpha2.NewBootstrapTokenString(bto.TokenStr)
bto.Token, err = kubeadmapiv1beta1.NewBootstrapTokenString(bto.TokenStr)
if err != nil {
return err
}
}
// Set the token specified by the flags as the first and only token to create in case --config is not specified
cfg.BootstrapTokens = []kubeadmapiv1alpha2.BootstrapToken{*bto.BootstrapToken}
cfg.BootstrapTokens = []kubeadmapiv1beta1.BootstrapToken{*bto.BootstrapToken}
return nil
}

View File

@ -10,24 +10,23 @@ go_library(
"etcd.go",
"kubeconfig.go",
"kubelet.go",
"markmaster.go",
"phase.go",
"markcontrolplane.go",
"preflight.go",
"selfhosting.go",
"uploadconfig.go",
"util.go",
"waitcontrolplane.go",
],
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases",
visibility = ["//visibility:public"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/scheme:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1alpha2:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
"//cmd/kubeadm/app/cmd/options:go_default_library",
"//cmd/kubeadm/app/cmd/phases/workflow:go_default_library",
"//cmd/kubeadm/app/cmd/util:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/phases/addons/dns:go_default_library",
"//cmd/kubeadm/app/phases/addons/proxy:go_default_library",
"//cmd/kubeadm/app/phases/bootstraptoken/clusterinfo:go_default_library",
@ -37,24 +36,25 @@ go_library(
"//cmd/kubeadm/app/phases/etcd:go_default_library",
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
"//cmd/kubeadm/app/phases/kubelet:go_default_library",
"//cmd/kubeadm/app/phases/markmaster:go_default_library",
"//cmd/kubeadm/app/phases/selfhosting:go_default_library",
"//cmd/kubeadm/app/phases/markcontrolplane:go_default_library",
"//cmd/kubeadm/app/phases/patchnode:go_default_library",
"//cmd/kubeadm/app/phases/uploadconfig:go_default_library",
"//cmd/kubeadm/app/preflight:go_default_library",
"//cmd/kubeadm/app/util:go_default_library",
"//cmd/kubeadm/app/util/apiclient:go_default_library",
"//cmd/kubeadm/app/util/config:go_default_library",
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
"//cmd/kubeadm/app/util/dryrun:go_default_library",
"//cmd/kubeadm/app/util/pkiutil:go_default_library",
"//pkg/util/normalizer:go_default_library",
"//pkg/util/version:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//pkg/version:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/renstrom/dedent:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
],
)
@ -62,24 +62,20 @@ go_library(
go_test(
name = "go_default_test",
srcs = [
"addons_test.go",
"certs_test.go",
"controlplane_test.go",
"etcd_test.go",
"kubeconfig_test.go",
"kubelet_test.go",
"util_test.go",
],
embed = [":go_default_library"],
deps = [
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
"//cmd/kubeadm/app/constants:go_default_library",
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
"//cmd/kubeadm/app/apis/kubeadm/v1beta1:go_default_library",
"//cmd/kubeadm/app/cmd/phases/workflow:go_default_library",
"//cmd/kubeadm/app/phases/certs:go_default_library",
"//cmd/kubeadm/app/util/pkiutil:go_default_library",
"//cmd/kubeadm/test:go_default_library",
"//cmd/kubeadm/test/cmd:go_default_library",
"//cmd/kubeadm/test/kubeconfig:go_default_library",
"//pkg/util/node:go_default_library",
"//cmd/kubeadm/test/certs:go_default_library",
"//pkg/version:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
],
)
@ -92,7 +88,10 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
srcs = [
":package-srcs",
"//cmd/kubeadm/app/cmd/phases/workflow:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors.
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.
@ -17,182 +17,116 @@ limitations under the License.
package phases
import (
"strings"
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/pkg/errors"
clientset "k8s.io/client-go/kubernetes"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
dnsaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns"
proxyaddon "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
allAddonsLongDesc = normalizer.LongDesc(`
Installs the CoreDNS and the kube-proxys addons components via the API server.
Please note that although the DNS server is deployed, it will not be scheduled until CNI is installed.
` + cmdutil.AlphaDisclaimer)
allAddonsExample = normalizer.Examples(`
# Installs the CoreDNS and the kube-proxys addons components via the API server,
# functionally equivalent to what installed by kubeadm init.
kubeadm alpha phase selfhosting from-staticpods
`)
corednsAddonsLongDesc = normalizer.LongDesc(`
coreDNSAddonLongDesc = normalizer.LongDesc(`
Installs the CoreDNS addon components via the API server.
Please note that although the DNS server is deployed, it will not be scheduled until CNI is installed.
` + cmdutil.AlphaDisclaimer)
`)
kubeproxyAddonsLongDesc = normalizer.LongDesc(`
kubeProxyAddonLongDesc = normalizer.LongDesc(`
Installs the kube-proxy addon components via the API server.
` + cmdutil.AlphaDisclaimer)
`)
)
// NewCmdAddon returns the addon Cobra command
func NewCmdAddon() *cobra.Command {
cmd := &cobra.Command{
Use: "addon",
Aliases: []string{"addons"},
Short: "Installs required addons for passing Conformance tests",
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(getAddonsSubCommands()...)
return cmd
type addonData interface {
Cfg() *kubeadmapi.InitConfiguration
Client() (clientset.Interface, error)
}
// EnsureAllAddons installs all addons to a Kubernetes cluster
func EnsureAllAddons(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error {
addonActions := []func(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error{
dnsaddon.EnsureDNSAddon,
proxyaddon.EnsureProxyAddon,
}
glog.V(1).Infoln("[addon] installing all addons")
for _, action := range addonActions {
err := action(cfg, client)
if err != nil {
return err
}
}
return nil
}
// getAddonsSubCommands returns sub commands for addons phase
func getAddonsSubCommands() []*cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var cfgPath, kubeConfigFile, featureGatesString string
var subCmds []*cobra.Command
subCmdProperties := []struct {
use string
short string
long string
examples string
cmdFunc func(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error
}{
{
use: "all",
short: "Installs all addons to a Kubernetes cluster",
long: allAddonsLongDesc,
examples: allAddonsExample,
cmdFunc: EnsureAllAddons,
},
{
use: "coredns",
short: "Installs the CoreDNS addon to a Kubernetes cluster",
long: corednsAddonsLongDesc,
cmdFunc: dnsaddon.EnsureDNSAddon,
},
{
use: "kube-proxy",
short: "Installs the kube-proxy addon to a Kubernetes cluster",
long: kubeproxyAddonsLongDesc,
cmdFunc: proxyaddon.EnsureProxyAddon,
// NewAddonPhase returns the addon Cobra command
func NewAddonPhase() workflow.Phase {
return workflow.Phase{
Name: "addon",
Short: "Installs required addons for passing Conformance tests",
Long: cmdutil.MacroCommandLongDescription,
Phases: []workflow.Phase{
{
Name: "all",
Short: "Installs all the addons",
InheritFlags: getAddonPhaseFlags("all"),
RunAllSiblings: true,
},
{
Name: "coredns",
Short: "Installs the CoreDNS addon to a Kubernetes cluster",
Long: coreDNSAddonLongDesc,
InheritFlags: getAddonPhaseFlags("coredns"),
Run: runCoreDNSAddon,
},
{
Name: "kube-proxy",
Short: "Installs the kube-proxy addon to a Kubernetes cluster",
Long: kubeProxyAddonLongDesc,
InheritFlags: getAddonPhaseFlags("kube-proxy"),
Run: runKubeProxyAddon,
},
},
}
for _, properties := range subCmdProperties {
// Creates the UX Command
cmd := &cobra.Command{
Use: properties.use,
Short: properties.short,
Long: properties.long,
Example: properties.examples,
Run: runAddonsCmdFunc(properties.cmdFunc, cfg, &kubeConfigFile, &cfgPath, &featureGatesString),
}
// Add flags to the command
cmd.Flags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster")
cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental")
cmd.Flags().StringVar(&cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion, `Choose a specific Kubernetes version for the control plane`)
cmd.Flags().StringVar(&cfg.ImageRepository, "image-repository", cfg.ImageRepository, `Choose a container registry to pull control plane images from`)
if properties.use == "all" || properties.use == "kube-proxy" {
cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, `The IP address the API server is accessible on`)
cmd.Flags().Int32Var(&cfg.API.BindPort, "apiserver-bind-port", cfg.API.BindPort, `The port the API server is accessible on`)
cmd.Flags().StringVar(&cfg.Networking.PodSubnet, "pod-network-cidr", cfg.Networking.PodSubnet, `The range of IP addresses used for the Pod network`)
}
if properties.use == "all" || properties.use == "coredns" {
cmd.Flags().StringVar(&cfg.Networking.DNSDomain, "service-dns-domain", cfg.Networking.DNSDomain, `Alternative domain for services`)
cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, `The range of IP address used for service VIPs`)
cmd.Flags().StringVar(&featureGatesString, "feature-gates", featureGatesString, "A set of key=value pairs that describe feature gates for various features."+
"Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n"))
}
subCmds = append(subCmds, cmd)
}
return subCmds
}
// runAddonsCmdFunc creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters)
func runAddonsCmdFunc(cmdFunc func(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error, cfg *kubeadmapiv1alpha2.MasterConfiguration, kubeConfigFile *string, cfgPath *string, featureGatesString *string) func(cmd *cobra.Command, args []string) {
// the following statement build a clousure that wraps a call to a cmdFunc, binding
// the function itself with the specific parameters of each sub command.
// Please note that specific parameter should be passed as value, while other parameters - passed as reference -
// are shared between sub commands and gets access to current value e.g. flags value.
return func(cmd *cobra.Command, args []string) {
var err error
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
kubeadmutil.CheckErr(err)
}
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, *featureGatesString); err != nil {
kubeadmutil.CheckErr(err)
}
internalcfg := &kubeadmapi.MasterConfiguration{}
kubeadmscheme.Scheme.Convert(cfg, internalcfg, nil)
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
kubeadmutil.CheckErr(err)
internalcfg, err = configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg)
kubeadmutil.CheckErr(err)
if err := features.ValidateVersion(features.InitFeatureGates, internalcfg.FeatureGates, internalcfg.KubernetesVersion); err != nil {
kubeadmutil.CheckErr(err)
}
// Execute the cmdFunc
err = cmdFunc(internalcfg, client)
kubeadmutil.CheckErr(err)
func getAddonData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.Interface, error) {
data, ok := c.(addonData)
if !ok {
return nil, nil, errors.New("addon phase invoked with an invalid data struct")
}
cfg := data.Cfg()
client, err := data.Client()
if err != nil {
return nil, nil, err
}
return cfg, client, err
}
// runCoreDNSAddon installs CoreDNS addon to a Kubernetes cluster
func runCoreDNSAddon(c workflow.RunData) error {
cfg, client, err := getAddonData(c)
if err != nil {
return err
}
return dnsaddon.EnsureDNSAddon(cfg, client)
}
// runKubeProxyAddon installs KubeProxy addon to a Kubernetes cluster
func runKubeProxyAddon(c workflow.RunData) error {
cfg, client, err := getAddonData(c)
if err != nil {
return err
}
return proxyaddon.EnsureProxyAddon(cfg, client)
}
func getAddonPhaseFlags(name string) []string {
flags := []string{
options.CfgPath,
options.KubeconfigPath,
options.KubernetesVersion,
options.ImageRepository,
}
if name == "all" || name == "kube-proxy" {
flags = append(flags,
options.APIServerAdvertiseAddress,
options.APIServerBindPort,
options.NetworkingPodSubnet,
)
}
if name == "all" || name == "coredns" {
flags = append(flags,
options.FeatureGatesString,
options.NetworkingDNSDomain,
options.NetworkingServiceSubnet,
)
}
return flags
}

View File

@ -1,71 +0,0 @@
/*
Copyright 2017 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 phases
import (
"testing"
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
)
func TestAddonsSubCommandsHasFlags(t *testing.T) {
subCmds := getAddonsSubCommands()
commonFlags := []string{
"kubeconfig",
"config",
"kubernetes-version",
"image-repository",
}
var tests = []struct {
command string
additionalFlags []string
}{
{
command: "all",
additionalFlags: []string{
"apiserver-advertise-address",
"apiserver-bind-port",
"pod-network-cidr",
"service-dns-domain",
"service-cidr",
},
},
{
command: "kube-proxy",
additionalFlags: []string{
"apiserver-advertise-address",
"apiserver-bind-port",
"pod-network-cidr",
},
},
{
command: "coredns",
additionalFlags: []string{
"service-dns-domain",
"service-cidr",
},
},
}
for _, test := range tests {
expectedFlags := append(commonFlags, test.additionalFlags...)
cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...)
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors.
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.
@ -18,317 +18,107 @@ package phases
import (
"fmt"
"path/filepath"
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientset "k8s.io/client-go/kubernetes"
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
nodebootstraptokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
allTokenLongDesc = normalizer.LongDesc(`
bootstrapTokenLongDesc = normalizer.LongDesc(`
Bootstrap tokens are used for establishing bidirectional trust between a node joining
the cluster and a the master node.
the cluster and a the control-plane node.
This command makes all the configurations required to make bootstrap tokens works
and then creates an initial token.
` + cmdutil.AlphaDisclaimer)
allTokenExamples = normalizer.Examples(`
# Makes all the bootstrap token configurations and creates an initial token, functionally
# equivalent to what generated by kubeadm init.
kubeadm alpha phase bootstrap-token all
`)
createTokenLongDesc = normalizer.LongDesc(`
Creates a bootstrap token. If no token value is given, kubeadm will generate a random token instead.
Alternatively, you can use kubeadm token.
` + cmdutil.AlphaDisclaimer)
clusterInfoLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Uploads the %q ConfigMap in the %q namespace, populating it with cluster information extracted from the
given kubeconfig file. The ConfigMap is used for the node bootstrap process in its initial phases,
before the client trusts the API server.
See online documentation about Authenticating with Bootstrap Tokens for more details.
`+cmdutil.AlphaDisclaimer), bootstrapapi.ConfigMapClusterInfo, metav1.NamespacePublic)
nodePostCSRsLongDesc = normalizer.LongDesc(`
Configures RBAC rules to allow node bootstrap tokens to post a certificate signing request,
thus enabling nodes joining the cluster to request long term certificate credentials.
See online documentation about TLS bootstrapping for more details.
` + cmdutil.AlphaDisclaimer)
nodeAutoApproveLongDesc = normalizer.LongDesc(`
Configures RBAC rules to allow the csrapprover controller to automatically approve
certificate signing requests generated by nodes joining the cluster.
It configures also RBAC rules for certificates rotation (with auto approval of new certificates).
See online documentation about TLS bootstrapping for more details.
` + cmdutil.AlphaDisclaimer)
bootstrapTokenExamples = normalizer.Examples(`
# Makes all the bootstrap token configurations and creates an initial token, functionally
# equivalent to what generated by kubeadm init.
kubeadm init phase bootstrap-token
`)
)
// NewCmdBootstrapToken returns the Cobra command for running the mark-master phase
func NewCmdBootstrapToken() *cobra.Command {
var kubeConfigFile string
cmd := &cobra.Command{
Use: "bootstrap-token",
Short: "Manage kubeadm-specific bootstrap token functions",
Long: cmdutil.MacroCommandLongDescription,
type bootstrapTokenData interface {
Cfg() *kubeadmapi.InitConfiguration
Client() (clientset.Interface, error)
KubeConfigDir() string
SkipTokenPrint() bool
Tokens() []string
}
// NewBootstrapTokenPhase returns the phase to boostrapToken
func NewBootstrapTokenPhase() workflow.Phase {
return workflow.Phase{
Name: "bootstrap-token",
Aliases: []string{"bootstraptoken"},
}
cmd.PersistentFlags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster")
// Add subcommands
cmd.AddCommand(NewSubCmdBootstrapTokenAll(&kubeConfigFile))
cmd.AddCommand(NewSubCmdBootstrapToken(&kubeConfigFile))
cmd.AddCommand(NewSubCmdClusterInfo(&kubeConfigFile))
cmd.AddCommand(NewSubCmdNodeBootstrapToken(&kubeConfigFile))
return cmd
}
// NewSubCmdBootstrapTokenAll returns the Cobra command for running the token all sub-phase
func NewSubCmdBootstrapTokenAll(kubeConfigFile *string) *cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{
// KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid
// the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
KubernetesVersion: "v1.10.0",
}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var cfgPath string
var skipTokenPrint bool
bto := options.NewBootstrapTokenOptions()
cmd := &cobra.Command{
Use: "all",
Short: "Makes all the bootstrap token configurations and creates an initial token",
Long: allTokenLongDesc,
Example: allTokenExamples,
Run: func(cmd *cobra.Command, args []string) {
err := validation.ValidateMixedArguments(cmd.Flags())
kubeadmutil.CheckErr(err)
err = bto.ApplyTo(cfg)
kubeadmutil.CheckErr(err)
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
kubeadmutil.CheckErr(err)
// Creates the bootstap token
err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, skipTokenPrint)
kubeadmutil.CheckErr(err)
// Create the cluster-info ConfigMap or update if it already exists
err = clusterinfo.CreateBootstrapConfigMapIfNotExists(client, *kubeConfigFile)
kubeadmutil.CheckErr(err)
// Create the RBAC rules that expose the cluster-info ConfigMap properly
err = clusterinfo.CreateClusterInfoRBACRules(client)
kubeadmutil.CheckErr(err)
// Create RBAC rules that makes the bootstrap tokens able to post CSRs
err = node.AllowBootstrapTokensToPostCSRs(client)
kubeadmutil.CheckErr(err)
// Create RBAC rules that makes the bootstrap tokens able to get their CSRs approved automatically
err = node.AutoApproveNodeBootstrapTokens(client)
kubeadmutil.CheckErr(err)
// Create/update RBAC rules that makes the nodes to rotate certificates and get their CSRs approved automatically
err = node.AutoApproveNodeCertificateRotation(client)
kubeadmutil.CheckErr(err)
Short: "Generates bootstrap tokens used to join a node to a cluster",
Example: bootstrapTokenExamples,
Long: bootstrapTokenLongDesc,
InheritFlags: []string{
options.CfgPath,
options.KubeconfigDir,
options.SkipTokenPrint,
},
Run: runBoostrapToken,
}
// Adds flags to the command
addGenericFlags(cmd.Flags(), &cfgPath, &skipTokenPrint)
bto.AddTokenFlag(cmd.Flags())
bto.AddTTLFlag(cmd.Flags())
bto.AddUsagesFlag(cmd.Flags())
bto.AddGroupsFlag(cmd.Flags())
bto.AddDescriptionFlag(cmd.Flags())
return cmd
}
// NewSubCmdBootstrapToken returns the Cobra command for running the create token phase
func NewSubCmdBootstrapToken(kubeConfigFile *string) *cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{
// KubernetesVersion is not used by bootstrap-token, but we set this explicitly to avoid
// the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
KubernetesVersion: "v1.10.0",
func runBoostrapToken(c workflow.RunData) error {
data, ok := c.(bootstrapTokenData)
if !ok {
return errors.New("bootstrap-token phase invoked with an invalid data struct")
}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var cfgPath string
var skipTokenPrint bool
bto := options.NewBootstrapTokenOptions()
cmd := &cobra.Command{
Use: "create",
Short: "Creates a bootstrap token to be used for node joining",
Long: createTokenLongDesc,
Run: func(cmd *cobra.Command, args []string) {
err := validation.ValidateMixedArguments(cmd.Flags())
kubeadmutil.CheckErr(err)
err = bto.ApplyTo(cfg)
kubeadmutil.CheckErr(err)
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
kubeadmutil.CheckErr(err)
err = createBootstrapToken(*kubeConfigFile, client, cfgPath, cfg, skipTokenPrint)
kubeadmutil.CheckErr(err)
},
}
// Adds flags to the command
addGenericFlags(cmd.Flags(), &cfgPath, &skipTokenPrint)
bto.AddTokenFlag(cmd.Flags())
bto.AddTTLFlag(cmd.Flags())
bto.AddUsagesFlag(cmd.Flags())
bto.AddGroupsFlag(cmd.Flags())
bto.AddDescriptionFlag(cmd.Flags())
return cmd
}
// NewSubCmdClusterInfo returns the Cobra command for running the cluster-info sub-phase
func NewSubCmdClusterInfo(kubeConfigFile *string) *cobra.Command {
cmd := &cobra.Command{
Use: "cluster-info",
Short: "Uploads the cluster-info ConfigMap from the given kubeconfig file",
Long: clusterInfoLongDesc,
Aliases: []string{"clusterinfo"},
Run: func(cmd *cobra.Command, args []string) {
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
kubeadmutil.CheckErr(err)
// Create the cluster-info ConfigMap or update if it already exists
err = clusterinfo.CreateBootstrapConfigMapIfNotExists(client, *kubeConfigFile)
kubeadmutil.CheckErr(err)
// Create the RBAC rules that expose the cluster-info ConfigMap properly
err = clusterinfo.CreateClusterInfoRBACRules(client)
kubeadmutil.CheckErr(err)
},
}
return cmd
}
// NewSubCmdNodeBootstrapToken returns the Cobra command for running the node sub-phase
func NewSubCmdNodeBootstrapToken(kubeConfigFile *string) *cobra.Command {
cmd := &cobra.Command{
Use: "node",
Short: "Configures the node bootstrap process",
Aliases: []string{"clusterinfo"},
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(NewSubCmdNodeBootstrapTokenPostCSRs(kubeConfigFile))
cmd.AddCommand(NewSubCmdNodeBootstrapTokenAutoApprove(kubeConfigFile))
return cmd
}
// NewSubCmdNodeBootstrapTokenPostCSRs returns the Cobra command for running the allow-post-csrs sub-phase
func NewSubCmdNodeBootstrapTokenPostCSRs(kubeConfigFile *string) *cobra.Command {
cmd := &cobra.Command{
Use: "allow-post-csrs",
Short: "Configures RBAC to allow node bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials",
Long: nodePostCSRsLongDesc,
Run: func(cmd *cobra.Command, args []string) {
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
kubeadmutil.CheckErr(err)
// Create RBAC rules that makes the bootstrap tokens able to post CSRs
err = node.AllowBootstrapTokensToPostCSRs(client)
kubeadmutil.CheckErr(err)
},
}
return cmd
}
// NewSubCmdNodeBootstrapTokenAutoApprove returns the Cobra command for running the allow-auto-approve sub-phase
func NewSubCmdNodeBootstrapTokenAutoApprove(kubeConfigFile *string) *cobra.Command {
cmd := &cobra.Command{
Use: "allow-auto-approve",
Short: "Configures RBAC rules to allow the csrapprover controller automatically approve CSRs from a node bootstrap token",
Long: nodeAutoApproveLongDesc,
Run: func(cmd *cobra.Command, args []string) {
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
kubeadmutil.CheckErr(err)
// Create RBAC rules that makes the bootstrap tokens able to get their CSRs approved automatically
err = node.AutoApproveNodeBootstrapTokens(client)
kubeadmutil.CheckErr(err)
// Create/update RBAC rules that makes the nodes to rotate certificates and get their CSRs approved automatically
err = node.AutoApproveNodeCertificateRotation(client)
kubeadmutil.CheckErr(err)
},
}
return cmd
}
func addGenericFlags(flagSet *pflag.FlagSet, cfgPath *string, skipTokenPrint *bool) {
flagSet.StringVar(
cfgPath, "config", *cfgPath,
"Path to kubeadm config file. WARNING: Usage of a configuration file is experimental",
)
flagSet.BoolVar(
skipTokenPrint, "skip-token-print", *skipTokenPrint,
"Skip printing of the bootstrap token",
)
}
func createBootstrapToken(kubeConfigFile string, client clientset.Interface, cfgPath string, cfg *kubeadmapiv1alpha2.MasterConfiguration, skipTokenPrint bool) error {
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
client, err := data.Client()
if err != nil {
return err
}
glog.V(1).Infoln("[bootstraptoken] creating/updating token")
// Creates or updates the token
if err := node.UpdateOrCreateTokens(client, false, internalcfg.BootstrapTokens); err != nil {
if !data.SkipTokenPrint() {
tokens := data.Tokens()
if len(tokens) == 1 {
fmt.Printf("[bootstrap-token] Using token: %s\n", tokens[0])
} else if len(tokens) > 1 {
fmt.Printf("[bootstrap-token] Using tokens: %v\n", tokens)
}
}
fmt.Println("[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles")
// Create the default node bootstrap token
if err := nodebootstraptokenphase.UpdateOrCreateTokens(client, false, data.Cfg().BootstrapTokens); err != nil {
return errors.Wrap(err, "error updating or creating token")
}
// Create RBAC rules that makes the bootstrap tokens able to post CSRs
if err := nodebootstraptokenphase.AllowBootstrapTokensToPostCSRs(client); err != nil {
return errors.Wrap(err, "error allowing bootstrap tokens to post CSRs")
}
// Create RBAC rules that makes the bootstrap tokens able to get their CSRs approved automatically
if err := nodebootstraptokenphase.AutoApproveNodeBootstrapTokens(client); err != nil {
return errors.Wrap(err, "error auto-approving node bootstrap tokens")
}
// Create/update RBAC rules that makes the nodes to rotate certificates and get their CSRs approved automatically
if err := nodebootstraptokenphase.AutoApproveNodeCertificateRotation(client); err != nil {
return err
}
fmt.Println("[bootstraptoken] bootstrap token created")
fmt.Println("[bootstraptoken] you can now join any number of machines by running:")
if len(internalcfg.BootstrapTokens) > 0 {
joinCommand, err := cmdutil.GetJoinCommand(kubeConfigFile, internalcfg.BootstrapTokens[0].Token.String(), skipTokenPrint)
if err != nil {
return fmt.Errorf("failed to get join command: %v", err)
}
fmt.Println(joinCommand)
// Create the cluster-info ConfigMap with the associated RBAC rules
adminKubeConfigPath := filepath.Join(data.KubeConfigDir(), kubeadmconstants.AdminKubeConfigFileName)
if err := clusterinfophase.CreateBootstrapConfigMapIfNotExists(client, adminKubeConfigPath); err != nil {
return errors.Wrap(err, "error creating bootstrap ConfigMap")
}
if err := clusterinfophase.CreateClusterInfoRBACRules(client); err != nil {
return errors.Wrap(err, "error creating clusterinfo RBAC rules")
}
return nil
}

View File

@ -18,278 +18,286 @@ package phases
import (
"fmt"
"strings"
"github.com/spf13/cobra"
"github.com/pkg/errors"
"github.com/spf13/pflag"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
allCertsLongDesc = normalizer.LongDesc(`
Generates a self-signed CA to provision identities for each component in the cluster (including nodes)
and client certificates to be used by various components.
If a given certificate and private key pair both exist, kubeadm skips the generation step and
existing files will be used.
` + cmdutil.AlphaDisclaimer)
allCertsExample = normalizer.Examples(`
# Creates all PKI assets necessary to establish the control plane,
# functionally equivalent to what generated by kubeadm init.
kubeadm alpha phase certs all
# Creates all PKI assets using options read from a configuration file.
kubeadm alpha phase certs all --config masterconfiguration.yaml
`)
caCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the self-signed kubernetes certificate authority and related key, and saves them into %s and %s files.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.CACertName, kubeadmconstants.CAKeyName)
apiServerCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the API server serving certificate and key and saves them into %s and %s files.
The certificate includes default subject alternative names and additional SANs provided by the user;
default SANs are: <node-name>, <apiserver-advertise-address>, kubernetes, kubernetes.default, kubernetes.default.svc,
kubernetes.default.svc.<service-dns-domain>, <internalAPIServerVirtualIP> (that is the .10 address in <service-cidr> address space).
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName)
apiServerKubeletCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the client certificate for the API server to connect to the kubelet securely and the respective key,
and saves them into %s and %s files.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName)
etcdCaCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the self-signed etcd certificate authority and related key and saves them into %s and %s files.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.EtcdCACertName, kubeadmconstants.EtcdCAKeyName)
etcdServerCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the etcd serving certificate and key and saves them into %s and %s files.
The certificate includes default subject alternative names and additional SANs provided by the user;
default SANs are: localhost, 127.0.0.1.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.EtcdServerCertName, kubeadmconstants.EtcdServerKeyName)
etcdPeerCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the etcd peer certificate and key and saves them into %s and %s files.
The certificate includes default subject alternative names and additional SANs provided by the user;
default SANs are: <node-name>, <apiserver-advertise-address>.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.EtcdPeerCertName, kubeadmconstants.EtcdPeerKeyName)
etcdHealthcheckClientCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the client certificate for liveness probes to healthcheck etcd and the respective key,
and saves them into %s and %s files.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.EtcdHealthcheckClientCertName, kubeadmconstants.EtcdHealthcheckClientKeyName)
apiServerEtcdServerCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the client certificate for the API server to connect to etcd securely and the respective key,
and saves them into %s and %s files.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.APIServerEtcdClientCertName, kubeadmconstants.APIServerEtcdClientKeyName)
saKeyLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the private key for signing service account tokens along with its public key, and saves them into
%s and %s files.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName)
frontProxyCaCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the front proxy CA certificate and key and saves them into %s and %s files.
genericLongDesc = normalizer.LongDesc(`
Generates the %[1]s, and saves them into %[2]s.cert and %[2]s.key files.%[3]s
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName)
frontProxyClientCertLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the front proxy client certificate and key and saves them into %s and %s files.
If both files already exist, kubeadm skips the generation step and existing files will be used.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName)
` + cmdutil.AlphaDisclaimer)
)
// NewCmdCerts returns main command for certs phase
func NewCmdCerts() *cobra.Command {
cmd := &cobra.Command{
Use: "certs",
Aliases: []string{"certificates"},
Short: "Generates certificates for a Kubernetes cluster",
Long: cmdutil.MacroCommandLongDescription,
}
var (
csrOnly bool
csrDir string
)
cmd.AddCommand(getCertsSubCommands("")...)
return cmd
// certsData defines the behavior that a runtime data struct passed to the certs phase should
// have. Please note that we are using an interface in order to make this phase reusable in different workflows
// (and thus with different runtime data struct, all of them requested to be compliant to this interface)
type certsData interface {
Cfg() *kubeadmapi.InitConfiguration
ExternalCA() bool
CertificateDir() string
CertificateWriteDir() string
}
// getCertsSubCommands returns sub commands for certs phase
func getCertsSubCommands(defaultKubernetesVersion string) []*cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
// This is used for unit testing only...
// If we wouldn't set this to something, the code would dynamically look up the version from the internet
// By setting this explicitly for tests workarounds that
if defaultKubernetesVersion != "" {
cfg.KubernetesVersion = defaultKubernetesVersion
}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var cfgPath string
var subCmds []*cobra.Command
subCmdProperties := []struct {
use string
short string
long string
examples string
cmdFunc func(cfg *kubeadmapi.MasterConfiguration) error
}{
{
use: "all",
short: "Generates all PKI assets necessary to establish the control plane",
long: allCertsLongDesc,
examples: allCertsExample,
cmdFunc: certsphase.CreatePKIAssets,
},
{
use: "ca",
short: "Generates a self-signed kubernetes CA to provision identities for components of the cluster",
long: caCertLongDesc,
cmdFunc: certsphase.CreateCACertAndKeyFiles,
},
{
use: "apiserver",
short: "Generates an API server serving certificate and key",
long: apiServerCertLongDesc,
cmdFunc: certsphase.CreateAPIServerCertAndKeyFiles,
},
{
use: "apiserver-kubelet-client",
short: "Generates a client certificate for the API server to connect to the kubelets securely",
long: apiServerKubeletCertLongDesc,
cmdFunc: certsphase.CreateAPIServerKubeletClientCertAndKeyFiles,
},
{
use: "etcd-ca",
short: "Generates a self-signed CA to provision identities for etcd",
long: etcdCaCertLongDesc,
cmdFunc: certsphase.CreateEtcdCACertAndKeyFiles,
},
{
use: "etcd-server",
short: "Generates an etcd serving certificate and key",
long: etcdServerCertLongDesc,
cmdFunc: certsphase.CreateEtcdServerCertAndKeyFiles,
},
{
use: "etcd-peer",
short: "Generates an etcd peer certificate and key",
long: etcdPeerCertLongDesc,
cmdFunc: certsphase.CreateEtcdPeerCertAndKeyFiles,
},
{
use: "etcd-healthcheck-client",
short: "Generates a client certificate for liveness probes to healthcheck etcd",
long: etcdHealthcheckClientCertLongDesc,
cmdFunc: certsphase.CreateEtcdHealthcheckClientCertAndKeyFiles,
},
{
use: "apiserver-etcd-client",
short: "Generates a client certificate for the API server to connect to etcd securely",
long: apiServerEtcdServerCertLongDesc,
cmdFunc: certsphase.CreateAPIServerEtcdClientCertAndKeyFiles,
},
{
use: "sa",
short: "Generates a private key for signing service account tokens along with its public key",
long: saKeyLongDesc,
cmdFunc: certsphase.CreateServiceAccountKeyAndPublicKeyFiles,
},
{
use: "front-proxy-ca",
short: "Generates a front proxy CA certificate and key for a Kubernetes cluster",
long: frontProxyCaCertLongDesc,
cmdFunc: certsphase.CreateFrontProxyCACertAndKeyFiles,
},
{
use: "front-proxy-client",
short: "Generates a front proxy CA client certificate and key for a Kubernetes cluster",
long: frontProxyClientCertLongDesc,
cmdFunc: certsphase.CreateFrontProxyClientCertAndKeyFiles,
},
}
for _, properties := range subCmdProperties {
// Creates the UX Command
cmd := &cobra.Command{
Use: properties.use,
Short: properties.short,
Long: properties.long,
Example: properties.examples,
Run: runCmdFunc(properties.cmdFunc, &cfgPath, cfg),
}
// Add flags to the command
cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental")
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where to save the certificates")
if properties.use == "all" || properties.use == "apiserver" {
cmd.Flags().StringVar(&cfg.Networking.DNSDomain, "service-dns-domain", cfg.Networking.DNSDomain, "Alternative domain for services, to use for the API server serving cert")
cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, "Alternative range of IP address for service VIPs, from which derives the internal API server VIP that will be added to the API Server serving cert")
cmd.Flags().StringSliceVar(&cfg.APIServerCertSANs, "apiserver-cert-extra-sans", []string{}, "Optional extra altnames to use for the API server serving cert. Can be both IP addresses and DNS names")
cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, "The IP address the API server is accessible on, to use for the API server serving cert")
}
subCmds = append(subCmds, cmd)
}
return subCmds
}
// runCmdFunc creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters)
func runCmdFunc(cmdFunc func(cfg *kubeadmapi.MasterConfiguration) error, cfgPath *string, cfg *kubeadmapiv1alpha2.MasterConfiguration) func(cmd *cobra.Command, args []string) {
// the following statement build a closure that wraps a call to a cmdFunc, binding
// the function itself with the specific parameters of each sub command.
// Please note that specific parameter should be passed as value, while other parameters - passed as reference -
// are shared between sub commands and gets access to current value e.g. flags value.
return func(cmd *cobra.Command, args []string) {
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
kubeadmutil.CheckErr(err)
}
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg)
kubeadmutil.CheckErr(err)
// Execute the cmdFunc
err = cmdFunc(internalcfg)
kubeadmutil.CheckErr(err)
// NewCertsPhase returns the phase for the certs
func NewCertsPhase() workflow.Phase {
return workflow.Phase{
Name: "certs",
Short: "Certificate generation",
Phases: newCertSubPhases(),
Run: runCerts,
Long: cmdutil.MacroCommandLongDescription,
}
}
func localFlags() *pflag.FlagSet {
set := pflag.NewFlagSet("csr", pflag.ExitOnError)
options.AddCSRFlag(set, &csrOnly)
options.AddCSRDirFlag(set, &csrDir)
return set
}
// newCertSubPhases returns sub phases for certs phase
func newCertSubPhases() []workflow.Phase {
subPhases := []workflow.Phase{}
// All subphase
allPhase := workflow.Phase{
Name: "all",
Short: "Generates all certificates",
InheritFlags: getCertPhaseFlags("all"),
RunAllSiblings: true,
}
subPhases = append(subPhases, allPhase)
certTree, _ := certsphase.GetDefaultCertList().AsMap().CertTree()
for ca, certList := range certTree {
caPhase := newCertSubPhase(ca, runCAPhase(ca))
subPhases = append(subPhases, caPhase)
for _, cert := range certList {
certPhase := newCertSubPhase(cert, runCertPhase(cert, ca))
certPhase.LocalFlags = localFlags()
subPhases = append(subPhases, certPhase)
}
}
// SA creates the private/public key pair, which doesn't use x509 at all
saPhase := workflow.Phase{
Name: "sa",
Short: "Generates a private key for signing service account tokens along with its public key",
Long: saKeyLongDesc,
Run: runCertsSa,
}
subPhases = append(subPhases, saPhase)
return subPhases
}
func newCertSubPhase(certSpec *certsphase.KubeadmCert, run func(c workflow.RunData) error) workflow.Phase {
phase := workflow.Phase{
Name: certSpec.Name,
Short: fmt.Sprintf("Generates the %s", certSpec.LongName),
Long: fmt.Sprintf(
genericLongDesc,
certSpec.LongName,
certSpec.BaseName,
getSANDescription(certSpec),
),
Run: run,
InheritFlags: getCertPhaseFlags(certSpec.Name),
}
return phase
}
func getCertPhaseFlags(name string) []string {
flags := []string{
options.CertificatesDir,
options.CfgPath,
options.CSROnly,
options.CSRDir,
}
if name == "all" || name == "apiserver" {
flags = append(flags,
options.APIServerAdvertiseAddress,
options.APIServerCertSANs,
options.NetworkingDNSDomain,
options.NetworkingServiceSubnet,
)
}
return flags
}
func getSANDescription(certSpec *certsphase.KubeadmCert) string {
//Defaulted config we will use to get SAN certs
defaultConfig := &kubeadmapiv1beta1.InitConfiguration{
LocalAPIEndpoint: kubeadmapiv1beta1.APIEndpoint{
// GetAPIServerAltNames errors without an AdvertiseAddress; this is as good as any.
AdvertiseAddress: "127.0.0.1",
},
}
defaultInternalConfig := &kubeadmapi.InitConfiguration{}
kubeadmscheme.Scheme.Default(defaultConfig)
err := kubeadmscheme.Scheme.Convert(defaultConfig, defaultInternalConfig, nil)
kubeadmutil.CheckErr(err)
certConfig, err := certSpec.GetConfig(defaultInternalConfig)
kubeadmutil.CheckErr(err)
if len(certConfig.AltNames.DNSNames) == 0 && len(certConfig.AltNames.IPs) == 0 {
return ""
}
// This mutates the certConfig, but we're throwing it after we construct the command anyway
sans := []string{}
for _, dnsName := range certConfig.AltNames.DNSNames {
if dnsName != "" {
sans = append(sans, dnsName)
}
}
for _, ip := range certConfig.AltNames.IPs {
sans = append(sans, ip.String())
}
return fmt.Sprintf("\n\nDefault SANs are %s", strings.Join(sans, ", "))
}
func runCertsSa(c workflow.RunData) error {
data, ok := c.(certsData)
if !ok {
return errors.New("certs phase invoked with an invalid data struct")
}
// if external CA mode, skip service account key generation
if data.ExternalCA() {
fmt.Printf("[certs] External CA mode: Using existing sa keys\n")
return nil
}
// if dryrunning, write certificates to a temporary folder (and defer restore to the path originally specified by the user)
cfg := data.Cfg()
cfg.CertificatesDir = data.CertificateWriteDir()
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
// create the new service account key (or use existing)
return certsphase.CreateServiceAccountKeyAndPublicKeyFiles(cfg)
}
func runCerts(c workflow.RunData) error {
data, ok := c.(certsData)
if !ok {
return errors.New("certs phase invoked with an invalid data struct")
}
fmt.Printf("[certs] Using certificateDir folder %q\n", data.CertificateWriteDir())
return nil
}
func runCAPhase(ca *certsphase.KubeadmCert) func(c workflow.RunData) error {
return func(c workflow.RunData) error {
data, ok := c.(certsData)
if !ok {
return errors.New("certs phase invoked with an invalid data struct")
}
// TODO(EKF): can we avoid loading these certificates every time?
if _, err := pkiutil.TryLoadCertFromDisk(data.CertificateDir(), ca.BaseName); err == nil {
if _, err := pkiutil.TryLoadKeyFromDisk(data.CertificateDir(), ca.BaseName); err == nil {
fmt.Printf("[certs] Using existing %s certificate authority\n", ca.BaseName)
return nil
}
fmt.Printf("[certs] Using existing %s keyless certificate authority", ca.BaseName)
return nil
}
// if using external etcd, skips etcd certificate authority generation
if data.Cfg().Etcd.External != nil && ca.Name == "etcd-ca" {
fmt.Printf("[certs] External etcd mode: Skipping %s certificate authority generation\n", ca.BaseName)
return nil
}
// if dryrunning, write certificates authority to a temporary folder (and defer restore to the path originally specified by the user)
cfg := data.Cfg()
cfg.CertificatesDir = data.CertificateWriteDir()
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
// create the new certificate authority (or use existing)
return certsphase.CreateCACertAndKeyFiles(ca, cfg)
}
}
func runCertPhase(cert *certsphase.KubeadmCert, caCert *certsphase.KubeadmCert) func(c workflow.RunData) error {
return func(c workflow.RunData) error {
data, ok := c.(certsData)
if !ok {
return errors.New("certs phase invoked with an invalid data struct")
}
// TODO(EKF): can we avoid loading these certificates every time?
if certData, _, err := pkiutil.TryLoadCertAndKeyFromDisk(data.CertificateDir(), cert.BaseName); err == nil {
caCertData, err := pkiutil.TryLoadCertFromDisk(data.CertificateDir(), caCert.BaseName)
if err != nil {
return errors.Wrapf(err, "couldn't load CA certificate %s", caCert.Name)
}
if err := certData.CheckSignatureFrom(caCertData); err != nil {
return errors.Wrapf(err, "[certs] certificate %s not signed by CA certificate %s", cert.BaseName, caCert.BaseName)
}
fmt.Printf("[certs] Using existing %s certificate and key on disk\n", cert.BaseName)
return nil
}
if csrOnly {
fmt.Printf("[certs] Generating CSR for %s instead of certificate\n", cert.BaseName)
if csrDir == "" {
csrDir = data.CertificateWriteDir()
}
return certsphase.CreateCSR(cert, data.Cfg(), csrDir)
}
// if using external etcd, skips etcd certificates generation
if data.Cfg().Etcd.External != nil && cert.CAName == "etcd-ca" {
fmt.Printf("[certs] External etcd mode: Skipping %s certificate authority generation\n", cert.BaseName)
return nil
}
// if dryrunning, write certificates to a temporary folder (and defer restore to the path originally specified by the user)
cfg := data.Cfg()
cfg.CertificatesDir = data.CertificateWriteDir()
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
// create the new certificate (or use existing)
return certsphase.CreateCertAndKeyFilesWithCA(cert, caCert, cfg)
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors.
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.
@ -17,256 +17,91 @@ limitations under the License.
package phases
import (
"fmt"
"os"
"testing"
"github.com/spf13/cobra"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
"k8s.io/kubernetes/pkg/util/node"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
certstestutil "k8s.io/kubernetes/cmd/kubeadm/test/certs"
)
// phaseTestK8sVersion is a fake kubernetes version to use when testing
const phaseTestK8sVersion = "v1.10.0"
func TestCertsSubCommandsHasFlags(t *testing.T) {
subCmds := getCertsSubCommands(phaseTestK8sVersion)
commonFlags := []string{
"cert-dir",
"config",
}
var tests = []struct {
command string
additionalFlags []string
}{
{
command: "all",
additionalFlags: []string{
"apiserver-advertise-address",
"apiserver-cert-extra-sans",
"service-cidr",
"service-dns-domain",
},
},
{
command: "ca",
},
{
command: "apiserver",
additionalFlags: []string{
"apiserver-advertise-address",
"apiserver-cert-extra-sans",
"service-cidr",
"service-dns-domain",
},
},
{
command: "apiserver-kubelet-client",
},
{
command: "etcd-ca",
},
{
command: "etcd-server",
},
{
command: "etcd-peer",
},
{
command: "etcd-healthcheck-client",
},
{
command: "apiserver-etcd-client",
},
{
command: "sa",
},
{
command: "front-proxy-ca",
},
{
command: "front-proxy-client",
},
}
for _, test := range tests {
expectedFlags := append(commonFlags, test.additionalFlags...)
cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...)
}
type testCertsData struct {
cfg *kubeadmapi.InitConfiguration
}
func TestSubCmdCertsCreateFilesWithFlags(t *testing.T) {
func (t *testCertsData) Cfg() *kubeadmapi.InitConfiguration { return t.cfg }
func (t *testCertsData) ExternalCA() bool { return false }
func (t *testCertsData) CertificateDir() string { return t.cfg.CertificatesDir }
func (t *testCertsData) CertificateWriteDir() string { return t.cfg.CertificatesDir }
subCmds := getCertsSubCommands(phaseTestK8sVersion)
func TestCertsWithCSRs(t *testing.T) {
csrDir := testutil.SetupTempDir(t)
defer os.RemoveAll(csrDir)
certDir := testutil.SetupTempDir(t)
defer os.RemoveAll(certDir)
cert := &certs.KubeadmCertAPIServer
var tests = []struct {
subCmds []string
expectedFiles []string
}{
{
subCmds: []string{"all"},
expectedFiles: []string{
kubeadmconstants.CACertName, kubeadmconstants.CAKeyName,
kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName,
kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName,
kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName,
kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName,
kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName,
},
},
{
subCmds: []string{"ca", "apiserver", "apiserver-kubelet-client"},
expectedFiles: []string{kubeadmconstants.CACertName, kubeadmconstants.CAKeyName, kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName, kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName},
},
{
subCmds: []string{"etcd-ca", "etcd-server", "etcd-peer", "etcd-healthcheck-client", "apiserver-etcd-client"},
expectedFiles: []string{
kubeadmconstants.EtcdCACertName, kubeadmconstants.EtcdCAKeyName,
kubeadmconstants.EtcdServerCertName, kubeadmconstants.EtcdServerKeyName,
kubeadmconstants.EtcdPeerCertName, kubeadmconstants.EtcdPeerKeyName,
kubeadmconstants.EtcdHealthcheckClientCertName, kubeadmconstants.EtcdHealthcheckClientKeyName,
kubeadmconstants.APIServerEtcdClientCertName, kubeadmconstants.APIServerEtcdClientKeyName,
},
},
{
subCmds: []string{"sa"},
expectedFiles: []string{kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName},
},
{
subCmds: []string{"front-proxy-ca", "front-proxy-client"},
expectedFiles: []string{kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName, kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName},
},
certsData := &testCertsData{
cfg: testutil.GetDefaultInternalConfig(t),
}
certsData.cfg.CertificatesDir = certDir
for _, test := range tests {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// global vars
csrOnly = true
csrDir = certDir
defer func() {
csrOnly = false
}()
// executes given sub commands
for _, subCmdName := range test.subCmds {
certDirFlag := fmt.Sprintf("--cert-dir=%s", tmpdir)
cmdtestutil.RunSubCommand(t, subCmds, subCmdName, certDirFlag)
phase := NewCertsPhase()
// find the api cert phase
var apiServerPhase *workflow.Phase
for _, phase := range phase.Phases {
if phase.Name == cert.Name {
apiServerPhase = &phase
break
}
// verify expected files are there
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
}
}
func TestSubCmdCertsApiServerForwardsFlags(t *testing.T) {
subCmds := getCertsSubCommands(phaseTestK8sVersion)
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// creates ca cert
certDirFlag := fmt.Sprintf("--cert-dir=%s", tmpdir)
cmdtestutil.RunSubCommand(t, subCmds, "ca", certDirFlag)
// creates apiserver cert
apiserverFlags := []string{
fmt.Sprintf("--cert-dir=%s", tmpdir),
"--apiserver-cert-extra-sans=foo,boo",
"--service-cidr=10.0.0.0/24",
"--service-dns-domain=mycluster.local",
"--apiserver-advertise-address=1.2.3.4",
if apiServerPhase == nil {
t.Fatalf("couldn't find apiserver phase")
}
cmdtestutil.RunSubCommand(t, subCmds, "apiserver", apiserverFlags...)
// asserts created cert has values from CLI flags
APIserverCert, err := pkiutil.TryLoadCertFromDisk(tmpdir, kubeadmconstants.APIServerCertAndKeyBaseName)
err := apiServerPhase.Run(certsData)
if err != nil {
t.Fatalf("Error loading API server certificate: %v", err)
t.Fatalf("couldn't run API server phase: %v", err)
}
hostname := node.GetHostname("")
for i, name := range []string{hostname, "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.mycluster.local"} {
if APIserverCert.DNSNames[i] != name {
t.Errorf("APIserverCert.DNSNames[%d] is %s instead of %s", i, APIserverCert.DNSNames[i], name)
}
}
for i, ip := range []string{"10.0.0.1", "1.2.3.4"} {
if APIserverCert.IPAddresses[i].String() != ip {
t.Errorf("APIserverCert.IPAddresses[%d] is %s instead of %s", i, APIserverCert.IPAddresses[i], ip)
}
if _, _, err := pkiutil.TryLoadCSRAndKeyFromDisk(csrDir, cert.BaseName); err != nil {
t.Fatalf("couldn't load certificate %q: %v", cert.BaseName, err)
}
}
func TestSubCmdCertsCreateFilesWithConfigFile(t *testing.T) {
func TestCreateSparseCerts(t *testing.T) {
for _, test := range certstestutil.GetSparseCertTestCases(t) {
t.Run(test.Name, func(t *testing.T) {
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
subCmds := getCertsSubCommands(phaseTestK8sVersion)
certstestutil.WritePKIFiles(t, tmpdir, test.Files)
var tests = []struct {
subCmds []string
expectedFiles []string
}{
{
subCmds: []string{"all"},
expectedFiles: []string{
kubeadmconstants.CACertName, kubeadmconstants.CAKeyName,
kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName,
kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName,
kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName,
kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName,
kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName,
},
},
{
subCmds: []string{"ca", "apiserver", "apiserver-kubelet-client"},
expectedFiles: []string{kubeadmconstants.CACertName, kubeadmconstants.CAKeyName, kubeadmconstants.APIServerCertName, kubeadmconstants.APIServerKeyName, kubeadmconstants.APIServerKubeletClientCertName, kubeadmconstants.APIServerKubeletClientKeyName},
},
{
subCmds: []string{"etcd-ca", "etcd-server", "etcd-peer", "etcd-healthcheck-client", "apiserver-etcd-client"},
expectedFiles: []string{
kubeadmconstants.EtcdCACertName, kubeadmconstants.EtcdCAKeyName,
kubeadmconstants.EtcdServerCertName, kubeadmconstants.EtcdServerKeyName,
kubeadmconstants.EtcdPeerCertName, kubeadmconstants.EtcdPeerKeyName,
kubeadmconstants.EtcdHealthcheckClientCertName, kubeadmconstants.EtcdHealthcheckClientKeyName,
kubeadmconstants.APIServerEtcdClientCertName, kubeadmconstants.APIServerEtcdClientKeyName,
},
},
{
subCmds: []string{"front-proxy-ca", "front-proxy-client"},
expectedFiles: []string{kubeadmconstants.FrontProxyCACertName, kubeadmconstants.FrontProxyCAKeyName, kubeadmconstants.FrontProxyClientCertName, kubeadmconstants.FrontProxyClientKeyName},
},
{
subCmds: []string{"sa"},
expectedFiles: []string{kubeadmconstants.ServiceAccountPrivateKeyName, kubeadmconstants.ServiceAccountPublicKeyName},
},
}
r := workflow.NewRunner()
r.AppendPhase(NewCertsPhase())
r.SetDataInitializer(func(*cobra.Command) (workflow.RunData, error) {
certsData := &testCertsData{
cfg: testutil.GetDefaultInternalConfig(t),
}
certsData.cfg.CertificatesDir = tmpdir
return certsData, nil
})
for _, test := range tests {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
certdir := tmpdir
cfg := &kubeadmapi.MasterConfiguration{
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
CertificatesDir: certdir,
NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"},
}
configPath := testutil.SetupMasterConfigurationFile(t, tmpdir, cfg)
// executes given sub commands
for _, subCmdName := range test.subCmds {
configFlag := fmt.Sprintf("--config=%s", configPath)
cmdtestutil.RunSubCommand(t, subCmds, subCmdName, configFlag)
}
// verify expected files are there
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
if err := r.Run(); (err != nil) != test.ExpectError {
t.Fatalf("expected error to be %t, got %t (%v)", test.ExpectError, (err != nil), err)
}
})
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors.
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.
@ -17,184 +17,141 @@ limitations under the License.
package phases
import (
"errors"
"fmt"
"strings"
"github.com/spf13/cobra"
utilflag "k8s.io/apiserver/pkg/util/flag"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/features"
controlplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
allControlplaneLongDesc = normalizer.LongDesc(`
Generates all static Pod manifest files necessary to establish the control plane.
` + cmdutil.AlphaDisclaimer)
allControlplaneExample = normalizer.Examples(`
controlPlaneExample = normalizer.Examples(`
# Generates all static Pod manifest files for control plane components,
# functionally equivalent to what generated by kubeadm init.
kubeadm alpha phase controlplane all
# functionally equivalent to what is generated by kubeadm init.
kubeadm init phase control-plane
# Generates all static Pod manifest files using options read from a configuration file.
kubeadm alpha phase controlplane --config masterconfiguration.yaml
kubeadm init phase control-plane --config config.yaml
`)
apiServerControlplaneLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the static Pod manifest file for the API server and saves it into %s file.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeAPIServer, kubeadmconstants.GetStaticPodDirectory()))
controllerManagerControlplaneLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the static Pod manifest file for the controller-manager and saves it into %s file.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeControllerManager, kubeadmconstants.GetStaticPodDirectory()))
schedulerControlplaneLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the static Pod manifest file for the scheduler and saves it into %s file.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeScheduler, kubeadmconstants.GetStaticPodDirectory()))
controlPlanePhaseProperties = map[string]struct {
name string
short string
}{
kubeadmconstants.KubeAPIServer: {
name: "apiserver",
short: getPhaseDescription(kubeadmconstants.KubeAPIServer),
},
kubeadmconstants.KubeControllerManager: {
name: "controller-manager",
short: getPhaseDescription(kubeadmconstants.KubeControllerManager),
},
kubeadmconstants.KubeScheduler: {
name: "scheduler",
short: getPhaseDescription(kubeadmconstants.KubeScheduler),
},
}
)
// NewCmdControlplane return main command for Controlplane phase
func NewCmdControlplane() *cobra.Command {
cmd := &cobra.Command{
Use: "controlplane",
type controlPlaneData interface {
Cfg() *kubeadmapi.InitConfiguration
KubeConfigDir() string
ManifestDir() string
}
func getPhaseDescription(component string) string {
return fmt.Sprintf("Generates the %s static Pod manifest", component)
}
// NewControlPlanePhase creates a kubeadm workflow phase that implements bootstrapping the control plane.
func NewControlPlanePhase() workflow.Phase {
phase := workflow.Phase{
Name: "control-plane",
Short: "Generates all static Pod manifest files necessary to establish the control plane",
Long: cmdutil.MacroCommandLongDescription,
Phases: []workflow.Phase{
{
Name: "all",
Short: "Generates all static Pod manifest files",
InheritFlags: getControlPlanePhaseFlags("all"),
RunAllSiblings: true,
},
newControlPlaneSubPhase(kubeadmconstants.KubeAPIServer),
newControlPlaneSubPhase(kubeadmconstants.KubeControllerManager),
newControlPlaneSubPhase(kubeadmconstants.KubeScheduler),
},
Run: runControlPlanePhase,
}
manifestPath := kubeadmconstants.GetStaticPodDirectory()
cmd.AddCommand(getControlPlaneSubCommands(manifestPath, "")...)
return cmd
return phase
}
// getControlPlaneSubCommands returns sub commands for Controlplane phase
func getControlPlaneSubCommands(outDir, defaultKubernetesVersion string) []*cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
// This is used for unit testing only...
// If we wouldn't set this to something, the code would dynamically look up the version from the internet
// By setting this explicitly for tests workarounds that
if defaultKubernetesVersion != "" {
cfg.KubernetesVersion = defaultKubernetesVersion
func newControlPlaneSubPhase(component string) workflow.Phase {
phase := workflow.Phase{
Name: controlPlanePhaseProperties[component].name,
Short: controlPlanePhaseProperties[component].short,
Run: runControlPlaneSubPhase(component),
InheritFlags: getControlPlanePhaseFlags(component),
}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var cfgPath, featureGatesString string
var subCmds []*cobra.Command
subCmdProperties := []struct {
use string
short string
long string
examples string
cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration) error
}{
{
use: "all",
short: "Generates all static Pod manifest files necessary to establish the control plane",
long: allControlplaneLongDesc,
examples: allControlplaneExample,
cmdFunc: controlplanephase.CreateInitStaticPodManifestFiles,
},
{
use: "apiserver",
short: "Generates the API server static Pod manifest",
long: apiServerControlplaneLongDesc,
cmdFunc: controlplanephase.CreateAPIServerStaticPodManifestFile,
},
{
use: "controller-manager",
short: "Generates the controller-manager static Pod manifest",
long: controllerManagerControlplaneLongDesc,
cmdFunc: controlplanephase.CreateControllerManagerStaticPodManifestFile,
},
{
use: "scheduler",
short: "Generates the scheduler static Pod manifest",
long: schedulerControlplaneLongDesc,
cmdFunc: controlplanephase.CreateSchedulerStaticPodManifestFile,
},
}
for _, properties := range subCmdProperties {
// Creates the UX Command
cmd := &cobra.Command{
Use: properties.use,
Short: properties.short,
Long: properties.long,
Example: properties.examples,
Run: runCmdControlPlane(properties.cmdFunc, &outDir, &cfgPath, &featureGatesString, cfg),
}
// Add flags to the command
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, `The path where certificates are stored`)
cmd.Flags().StringVar(&cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion, `Choose a specific Kubernetes version for the control plane`)
if properties.use == "all" || properties.use == "apiserver" {
cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, "The IP address of the API server is accessible on")
cmd.Flags().Int32Var(&cfg.API.BindPort, "apiserver-bind-port", cfg.API.BindPort, "The port the API server is accessible on")
cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, "The range of IP address used for service VIPs")
cmd.Flags().StringVar(&featureGatesString, "feature-gates", featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+
"Options are:\n"+strings.Join(features.KnownFeatures(&features.InitFeatureGates), "\n"))
cmd.Flags().Var(utilflag.NewMapStringString(&cfg.APIServerExtraArgs), "apiserver-extra-args", "A set of extra flags to pass to the API Server or override default ones in form of <flagname>=<value>")
}
if properties.use == "all" || properties.use == "controller-manager" {
cmd.Flags().StringVar(&cfg.Networking.PodSubnet, "pod-network-cidr", cfg.Networking.PodSubnet, "The range of IP addresses used for the Pod network")
cmd.Flags().Var(utilflag.NewMapStringString(&cfg.ControllerManagerExtraArgs), "controller-manager-extra-args", "A set of extra flags to pass to the Controller Manager or override default ones in form of <flagname>=<value>")
}
if properties.use == "all" || properties.use == "scheduler" {
cmd.Flags().Var(utilflag.NewMapStringString(&cfg.SchedulerExtraArgs), "scheduler-extra-args", "A set of extra flags to pass to the Scheduler or override default ones in form of <flagname>=<value>")
}
cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental")
subCmds = append(subCmds, cmd)
}
return subCmds
return phase
}
// runCmdControlPlane creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters)
func runCmdControlPlane(cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration) error, outDir, cfgPath *string, featureGatesString *string, cfg *kubeadmapiv1alpha2.MasterConfiguration) func(cmd *cobra.Command, args []string) {
func getControlPlanePhaseFlags(name string) []string {
flags := []string{
options.CfgPath,
options.CertificatesDir,
options.KubernetesVersion,
options.ImageRepository,
}
if name == "all" || name == kubeadmconstants.KubeAPIServer {
flags = append(flags,
options.APIServerAdvertiseAddress,
options.APIServerBindPort,
options.APIServerExtraArgs,
options.FeatureGatesString,
options.NetworkingServiceSubnet,
)
}
if name == "all" || name == kubeadmconstants.KubeControllerManager {
flags = append(flags,
options.ControllerManagerExtraArgs,
options.NetworkingPodSubnet,
)
}
if name == "all" || name == kubeadmconstants.KubeScheduler {
flags = append(flags,
options.SchedulerExtraArgs,
)
}
return flags
}
// the following statement build a closure that wraps a call to a cmdFunc, binding
// the function itself with the specific parameters of each sub command.
// Please note that specific parameter should be passed as value, while other parameters - passed as reference -
// are shared between sub commands and gets access to current value e.g. flags value.
return func(cmd *cobra.Command, args []string) {
var err error
if err = validation.ValidateMixedArguments(cmd.Flags()); err != nil {
kubeadmutil.CheckErr(err)
func runControlPlanePhase(c workflow.RunData) error {
data, ok := c.(controlPlaneData)
if !ok {
return errors.New("control-plane phase invoked with an invalid data struct")
}
fmt.Printf("[control-plane] Using manifest folder %q\n", data.ManifestDir())
return nil
}
func runControlPlaneSubPhase(component string) func(c workflow.RunData) error {
return func(c workflow.RunData) error {
data, ok := c.(controlPlaneData)
if !ok {
return errors.New("control-plane phase invoked with an invalid data struct")
}
cfg := data.Cfg()
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, *featureGatesString); err != nil {
kubeadmutil.CheckErr(err)
fmt.Printf("[control-plane] Creating static Pod manifest for %q\n", component)
if err := controlplane.CreateStaticPodFiles(data.ManifestDir(), cfg, component); err != nil {
return err
}
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg)
kubeadmutil.CheckErr(err)
if err := features.ValidateVersion(features.InitFeatureGates, internalcfg.FeatureGates, internalcfg.KubernetesVersion); err != nil {
kubeadmutil.CheckErr(err)
}
// Execute the cmdFunc
err = cmdFunc(*outDir, internalcfg)
kubeadmutil.CheckErr(err)
return nil
}
}

View File

@ -1,149 +0,0 @@
/*
Copyright 2017 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 phases
import (
"fmt"
"os"
"testing"
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
)
func TestControlPlaneSubCommandsHasFlags(t *testing.T) {
subCmds := getControlPlaneSubCommands("", phaseTestK8sVersion)
commonFlags := []string{
"cert-dir",
"config",
}
var tests = []struct {
command string
additionalFlags []string
}{
{
command: "all",
additionalFlags: []string{
"kubernetes-version",
"apiserver-advertise-address",
"apiserver-bind-port",
"service-cidr",
"pod-network-cidr",
"feature-gates",
},
},
{
command: "apiserver",
additionalFlags: []string{
"kubernetes-version",
"apiserver-advertise-address",
"apiserver-bind-port",
"service-cidr",
"feature-gates",
},
},
{
command: "controller-manager",
additionalFlags: []string{
"kubernetes-version",
"pod-network-cidr",
},
},
{
command: "scheduler",
additionalFlags: []string{
"kubernetes-version",
},
},
}
for _, test := range tests {
expectedFlags := append(commonFlags, test.additionalFlags...)
cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...)
}
}
func TestControlPlaneCreateFilesWithFlags(t *testing.T) {
var tests = []struct {
command string
additionalFlags []string
expectedFiles []string
}{
{
command: "all",
additionalFlags: []string{
"--kubernetes-version=v1.10.0",
"--apiserver-advertise-address=1.2.3.4",
"--apiserver-bind-port=6443",
"--service-cidr=1.2.3.4/16",
"--pod-network-cidr=1.2.3.4/16",
},
expectedFiles: []string{
"kube-apiserver.yaml",
"kube-controller-manager.yaml",
"kube-scheduler.yaml",
},
},
{
command: "apiserver",
additionalFlags: []string{
"--kubernetes-version=v1.10.0",
"--apiserver-advertise-address=1.2.3.4",
"--apiserver-bind-port=6443",
"--service-cidr=1.2.3.4/16",
},
expectedFiles: []string{"kube-apiserver.yaml"},
},
{
command: "controller-manager",
additionalFlags: []string{
"--kubernetes-version=v1.10.0",
"--pod-network-cidr=1.2.3.4/16",
},
expectedFiles: []string{"kube-controller-manager.yaml"},
},
{
command: "scheduler",
additionalFlags: []string{
"--kubernetes-version=v1.10.0",
},
expectedFiles: []string{"kube-scheduler.yaml"},
},
}
for _, test := range tests {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// Get subcommands working in the temporary directory
subCmds := getControlPlaneSubCommands(tmpdir, phaseTestK8sVersion)
// Execute the subcommand
certDirFlag := fmt.Sprintf("--cert-dir=%s", tmpdir)
allFlags := append(test.additionalFlags, certDirFlag)
cmdtestutil.RunSubCommand(t, subCmds, test.command, allFlags...)
// Checks that requested files are there
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
}
}

View File

@ -19,91 +19,83 @@ package phases
import (
"fmt"
"github.com/spf13/cobra"
"github.com/pkg/errors"
"k8s.io/klog"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
etcdLocalLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the static Pod manifest file for a local, single-node etcd instance and saves it to %s file.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.Etcd, kubeadmconstants.GetStaticPodDirectory()))
etcdLocalExample = normalizer.Examples(`
# Generates the static Pod manifest file for etcd, functionally
# equivalent to what generated by kubeadm init.
kubeadm alpha phase etcd local
# equivalent to what is generated by kubeadm init.
kubeadm init phase etcd local
# Generates the static Pod manifest file for etcd.
kubeadm alpha phase etcd local --config masterconfiguration.yaml
# Generates the static Pod manifest file for etcd using options
# read from a configuration file.
kubeadm init phase etcd local --config config.yaml
`)
)
// NewCmdEtcd return main command for Etcd phase
func NewCmdEtcd() *cobra.Command {
cmd := &cobra.Command{
Use: "etcd",
Short: "Generates static Pod manifest file for etcd.",
type etcdData interface {
Cfg() *kubeadmapi.InitConfiguration
ManifestDir() string
}
// NewEtcdPhase creates a kubeadm workflow phase that implements handling of etcd.
func NewEtcdPhase() workflow.Phase {
phase := workflow.Phase{
Name: "etcd",
Short: "Generates static Pod manifest file for local etcd.",
Long: cmdutil.MacroCommandLongDescription,
Phases: []workflow.Phase{
newEtcdLocalSubPhase(),
},
}
manifestPath := kubeadmconstants.GetStaticPodDirectory()
cmd.AddCommand(getEtcdSubCommands(manifestPath, "")...)
return cmd
return phase
}
// getEtcdSubCommands returns sub commands for etcd phase
func getEtcdSubCommands(outDir, defaultKubernetesVersion string) []*cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
// This is used for unit testing only...
// If we wouldn't set this to something, the code would dynamically look up the version from the internet
// By setting this explicitly for tests workarounds that
if defaultKubernetesVersion != "" {
cfg.KubernetesVersion = defaultKubernetesVersion
func newEtcdLocalSubPhase() workflow.Phase {
phase := workflow.Phase{
Name: "local",
Short: "Generates the static Pod manifest file for a local, single-node local etcd instance.",
Example: etcdLocalExample,
Run: runEtcdPhaseLocal(),
InheritFlags: getEtcdPhaseFlags(),
}
return phase
}
func getEtcdPhaseFlags() []string {
flags := []string{
options.CertificatesDir,
options.CfgPath,
options.ImageRepository,
}
return flags
}
func runEtcdPhaseLocal() func(c workflow.RunData) error {
return func(c workflow.RunData) error {
data, ok := c.(etcdData)
if !ok {
return errors.New("etcd phase invoked with an invalid data struct")
}
cfg := data.Cfg()
// Add etcd static pod spec only if external etcd is not configured
if cfg.Etcd.External == nil {
fmt.Printf("[etcd] Creating static Pod manifest for local etcd in %q\n", data.ManifestDir())
if err := etcdphase.CreateLocalEtcdStaticPodManifestFile(data.ManifestDir(), cfg); err != nil {
return errors.Wrap(err, "error creating local etcd static pod manifest file")
}
} else {
klog.V(1).Infof("[etcd] External etcd mode. Skipping the creation of a manifest for local etcd")
}
return nil
}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var cfgPath string
var subCmds []*cobra.Command
properties := struct {
use string
short string
long string
examples string
cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration) error
}{
use: "local",
short: "Generates the static Pod manifest file for a local, single-node etcd instance",
long: etcdLocalLongDesc,
examples: etcdLocalExample,
cmdFunc: etcdphase.CreateLocalEtcdStaticPodManifestFile,
}
// Creates the UX Command
cmd := &cobra.Command{
Use: properties.use,
Short: properties.short,
Long: properties.long,
Example: properties.examples,
Run: runCmdPhase(properties.cmdFunc, &outDir, &cfgPath, cfg),
}
// Add flags to the command
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, `The path where certificates are stored`)
cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental")
subCmds = append(subCmds, cmd)
return subCmds
}

View File

@ -1,83 +0,0 @@
/*
Copyright 2017 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 phases
import (
"fmt"
"os"
"testing"
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
)
func TestEtcdSubCommandsHasFlags(t *testing.T) {
subCmds := getEtcdSubCommands("", phaseTestK8sVersion)
commonFlags := []string{
"cert-dir",
"config",
}
var tests = []struct {
command string
additionalFlags []string
}{
{
command: "local",
},
}
for _, test := range tests {
expectedFlags := append(commonFlags, test.additionalFlags...)
cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...)
}
}
func TestEtcdCreateFilesWithFlags(t *testing.T) {
var tests = []struct {
command string
additionalFlags []string
expectedFiles []string
}{
{
command: "local",
expectedFiles: []string{"etcd.yaml"},
additionalFlags: []string{},
},
}
for _, test := range tests {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// Get subcommands working in the temporary directory
subCmds := getEtcdSubCommands(tmpdir, phaseTestK8sVersion)
// Execute the subcommand
certDirFlag := fmt.Sprintf("--cert-dir=%s", tmpdir)
allFlags := append(test.additionalFlags, certDirFlag)
cmdtestutil.RunSubCommand(t, subCmds, test.command, allFlags...)
// Checks that requested files are there
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors.
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.
@ -18,14 +18,11 @@ package phases
import (
"fmt"
"io"
"path/filepath"
"github.com/spf13/cobra"
"github.com/pkg/errors"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
@ -33,167 +30,128 @@ import (
)
var (
allKubeconfigLongDesc = normalizer.LongDesc(`
Generates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file.
` + cmdutil.AlphaDisclaimer)
allKubeconfigExample = normalizer.Examples(`
# Generates all kubeconfig files, functionally equivalent to what generated
# by kubeadm init.
kubeadm alpha phase kubeconfig all
# Generates all kubeconfig files using options read from a configuration file.
kubeadm alpha phase kubeconfig all --config masterconfiguration.yaml
`)
adminKubeconfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the kubeconfig file for the admin and for kubeadm itself, and saves it to %s file.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.AdminKubeConfigFileName)
kubeletKubeconfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the kubeconfig file for the kubelet to use and saves it to %s file.
Please note that this should *only* be used for bootstrapping purposes. After your control plane is up,
you should request all kubelet credentials from the CSR API.
`+cmdutil.AlphaDisclaimer), filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName))
controllerManagerKubeconfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the kubeconfig file for the controller manager to use and saves it to %s file.
`+cmdutil.AlphaDisclaimer), filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName))
schedulerKubeconfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the kubeconfig file for the scheduler to use and saves it to %s file.
`+cmdutil.AlphaDisclaimer), filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.SchedulerKubeConfigFileName))
userKubeconfigLongDesc = normalizer.LongDesc(`
Outputs a kubeconfig file for an additional user.
` + cmdutil.AlphaDisclaimer)
userKubeconfigExample = normalizer.Examples(`
# Outputs a kubeconfig file for an additional user named foo
kubeadm alpha phase kubeconfig user --client-name=foo
`)
kubeconfigFilePhaseProperties = map[string]struct {
name string
short string
long string
}{
kubeadmconstants.AdminKubeConfigFileName: {
name: "admin",
short: "Generates a kubeconfig file for the admin to use and for kubeadm itself",
long: "Generates the kubeconfig file for the admin and for kubeadm itself, and saves it to %s file.",
},
kubeadmconstants.KubeletKubeConfigFileName: {
name: "kubelet",
short: "Generates a kubeconfig file for the kubelet to use *only* for cluster bootstrapping purposes",
long: normalizer.LongDesc(`
Generates the kubeconfig file for the kubelet to use and saves it to %s file.
Please note that this should *only* be used for cluster bootstrapping purposes. After your control plane is up,
you should request all kubelet credentials from the CSR API.`),
},
kubeadmconstants.ControllerManagerKubeConfigFileName: {
name: "controller-manager",
short: "Generates a kubeconfig file for the controller manager to use",
long: "Generates the kubeconfig file for the controller manager to use and saves it to %s file",
},
kubeadmconstants.SchedulerKubeConfigFileName: {
name: "scheduler",
short: "Generates a kubeconfig file for the scheduler to use",
long: "Generates the kubeconfig file for the scheduler to use and saves it to %s file.",
},
}
)
// NewCmdKubeConfig return main command for kubeconfig phase
func NewCmdKubeConfig(out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "kubeconfig",
// kubeConfigData defines the behavior that a runtime data struct passed to the kubeconfig phase
// should have. Please note that we are using an interface in order to make this phase reusable in different workflows
// (and thus with different runtime data struct, all of them requested to be compliant to this interface)
type kubeConfigData interface {
Cfg() *kubeadmapi.InitConfiguration
ExternalCA() bool
CertificateDir() string
CertificateWriteDir() string
KubeConfigDir() string
}
// NewKubeConfigPhase creates a kubeadm workflow phase that creates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file.
func NewKubeConfigPhase() workflow.Phase {
return workflow.Phase{
Name: "kubeconfig",
Short: "Generates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file",
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(getKubeConfigSubCommands(out, kubeadmconstants.KubernetesDir, "")...)
return cmd
}
// getKubeConfigSubCommands returns sub commands for kubeconfig phase
func getKubeConfigSubCommands(out io.Writer, outDir, defaultKubernetesVersion string) []*cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{}
// This is used for unit testing only...
// If we wouldn't set this to something, the code would dynamically look up the version from the internet
// By setting this explicitly for tests workarounds that
if defaultKubernetesVersion != "" {
cfg.KubernetesVersion = defaultKubernetesVersion
}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var cfgPath, token, clientName string
var organizations []string
var subCmds []*cobra.Command
subCmdProperties := []struct {
use string
short string
long string
examples string
cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration) error
}{
{
use: "all",
short: "Generates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file",
long: allKubeconfigLongDesc,
examples: allKubeconfigExample,
cmdFunc: kubeconfigphase.CreateInitKubeConfigFiles,
},
{
use: "admin",
short: "Generates a kubeconfig file for the admin to use and for kubeadm itself",
long: adminKubeconfigLongDesc,
cmdFunc: kubeconfigphase.CreateAdminKubeConfigFile,
},
{
use: "kubelet",
short: "Generates a kubeconfig file for the kubelet to use. Please note that this should be used *only* for bootstrapping purposes",
long: kubeletKubeconfigLongDesc,
cmdFunc: kubeconfigphase.CreateKubeletKubeConfigFile,
},
{
use: "controller-manager",
short: "Generates a kubeconfig file for the controller manager to use",
long: controllerManagerKubeconfigLongDesc,
cmdFunc: kubeconfigphase.CreateControllerManagerKubeConfigFile,
},
{
use: "scheduler",
short: "Generates a kubeconfig file for the scheduler to use",
long: schedulerKubeconfigLongDesc,
cmdFunc: kubeconfigphase.CreateSchedulerKubeConfigFile,
},
{
use: "user",
short: "Outputs a kubeconfig file for an additional user",
long: userKubeconfigLongDesc,
examples: userKubeconfigExample,
cmdFunc: func(outDir string, cfg *kubeadmapi.MasterConfiguration) error {
if clientName == "" {
return fmt.Errorf("missing required argument --client-name")
}
// if the kubeconfig file for an additional user has to use a token, use it
if token != "" {
return kubeconfigphase.WriteKubeConfigWithToken(out, cfg, clientName, token)
}
// Otherwise, write a kubeconfig file with a generate client cert
return kubeconfigphase.WriteKubeConfigWithClientCert(out, cfg, clientName, organizations)
Phases: []workflow.Phase{
{
Name: "all",
Short: "Generates all kubeconfig files",
InheritFlags: getKubeConfigPhaseFlags("all"),
RunAllSiblings: true,
},
NewKubeConfigFilePhase(kubeadmconstants.AdminKubeConfigFileName),
NewKubeConfigFilePhase(kubeadmconstants.KubeletKubeConfigFileName),
NewKubeConfigFilePhase(kubeadmconstants.ControllerManagerKubeConfigFileName),
NewKubeConfigFilePhase(kubeadmconstants.SchedulerKubeConfigFileName),
},
Run: runKubeConfig,
}
}
// NewKubeConfigFilePhase creates a kubeadm workflow phase that creates a kubeconfig file.
func NewKubeConfigFilePhase(kubeConfigFileName string) workflow.Phase {
return workflow.Phase{
Name: kubeconfigFilePhaseProperties[kubeConfigFileName].name,
Short: kubeconfigFilePhaseProperties[kubeConfigFileName].short,
Long: fmt.Sprintf(kubeconfigFilePhaseProperties[kubeConfigFileName].long, kubeConfigFileName),
Run: runKubeConfigFile(kubeConfigFileName),
InheritFlags: getKubeConfigPhaseFlags(kubeConfigFileName),
}
}
func getKubeConfigPhaseFlags(name string) []string {
flags := []string{
options.APIServerAdvertiseAddress,
options.APIServerBindPort,
options.CertificatesDir,
options.CfgPath,
options.KubeconfigDir,
}
if name == "all" || name == kubeadmconstants.KubeletKubeConfigFileName {
flags = append(flags,
options.NodeName,
)
}
return flags
}
func runKubeConfig(c workflow.RunData) error {
data, ok := c.(kubeConfigData)
if !ok {
return errors.New("kubeconfig phase invoked with an invalid data struct")
}
fmt.Printf("[kubeconfig] Using kubeconfig folder %q\n", data.KubeConfigDir())
return nil
}
// runKubeConfigFile executes kubeconfig creation logic.
func runKubeConfigFile(kubeConfigFileName string) func(workflow.RunData) error {
return func(c workflow.RunData) error {
data, ok := c.(kubeConfigData)
if !ok {
return errors.New("kubeconfig phase invoked with an invalid data struct")
}
// if external CA mode, skip certificate authority generation
if data.ExternalCA() {
fmt.Printf("[kubeconfig] External CA mode: Using user provided %s\n", kubeConfigFileName)
return nil
}
// if dryrunning, reads certificates from a temporary folder (and defer restore to the path originally specified by the user)
cfg := data.Cfg()
cfg.CertificatesDir = data.CertificateWriteDir()
defer func() { cfg.CertificatesDir = data.CertificateDir() }()
// creates the KubeConfig file (or use existing)
return kubeconfigphase.CreateKubeConfigFile(kubeConfigFileName, data.KubeConfigDir(), data.Cfg())
}
for _, properties := range subCmdProperties {
// Creates the UX Command
cmd := &cobra.Command{
Use: properties.use,
Short: properties.short,
Long: properties.long,
Example: properties.examples,
Run: runCmdPhase(properties.cmdFunc, &outDir, &cfgPath, cfg),
}
// Add flags to the command
if properties.use != "user" {
cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental")
}
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where certificates are stored")
cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, "The IP address the API server is accessible on")
cmd.Flags().Int32Var(&cfg.API.BindPort, "apiserver-bind-port", cfg.API.BindPort, "The port the API server is accessible on")
cmd.Flags().StringVar(&outDir, "kubeconfig-dir", outDir, "The path where to save the kubeconfig file")
if properties.use == "all" || properties.use == "kubelet" {
cmd.Flags().StringVar(&cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, `The node name that should be used for the kubelet client certificate`)
}
if properties.use == "user" {
cmd.Flags().StringVar(&token, "token", token, "The token that should be used as the authentication mechanism for this kubeconfig, instead of client certificates")
cmd.Flags().StringVar(&clientName, "client-name", clientName, "The name of user. It will be used as the CN if client certificates are created")
cmd.Flags().StringSliceVar(&organizations, "org", organizations, "The orgnizations of the client certificate. It will be used as the O if client certificates are created")
}
subCmds = append(subCmds, cmd)
}
return subCmds
}

View File

@ -1,388 +0,0 @@
/*
Copyright 2017 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 phases
import (
"bytes"
"fmt"
"os"
"path/filepath"
"testing"
"k8s.io/client-go/tools/clientcmd"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
kubeconfigtestutil "k8s.io/kubernetes/cmd/kubeadm/test/kubeconfig"
)
func TestKubeConfigCSubCommandsHasFlags(t *testing.T) {
subCmds := getKubeConfigSubCommands(nil, "", phaseTestK8sVersion)
commonFlags := []string{
"cert-dir",
"apiserver-advertise-address",
"apiserver-bind-port",
"kubeconfig-dir",
}
var tests = []struct {
command string
additionalFlags []string
}{
{
command: "all",
additionalFlags: []string{
"config",
"node-name",
},
},
{
command: "admin",
additionalFlags: []string{
"config",
},
},
{
command: "kubelet",
additionalFlags: []string{
"config",
"node-name",
},
},
{
command: "controller-manager",
additionalFlags: []string{
"config",
},
},
{
command: "scheduler",
additionalFlags: []string{
"config",
},
},
{
command: "user",
additionalFlags: []string{
"token",
"client-name",
},
},
}
for _, test := range tests {
expectedFlags := append(commonFlags, test.additionalFlags...)
cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...)
}
}
func TestKubeConfigSubCommandsThatCreateFilesWithFlags(t *testing.T) {
commonFlags := []string{
"--apiserver-advertise-address=1.2.3.4",
"--apiserver-bind-port=1234",
}
var tests = []struct {
command string
additionalFlags []string
expectedFiles []string
}{
{
command: "all",
additionalFlags: []string{"--node-name=valid-nome-name"},
expectedFiles: []string{
kubeadmconstants.AdminKubeConfigFileName,
kubeadmconstants.KubeletKubeConfigFileName,
kubeadmconstants.ControllerManagerKubeConfigFileName,
kubeadmconstants.SchedulerKubeConfigFileName,
},
},
{
command: "admin",
expectedFiles: []string{kubeadmconstants.AdminKubeConfigFileName},
},
{
command: "kubelet",
additionalFlags: []string{"--node-name=valid-nome-name"},
expectedFiles: []string{kubeadmconstants.KubeletKubeConfigFileName},
},
{
command: "controller-manager",
expectedFiles: []string{kubeadmconstants.ControllerManagerKubeConfigFileName},
},
{
command: "scheduler",
expectedFiles: []string{kubeadmconstants.SchedulerKubeConfigFileName},
},
}
var kubeConfigAssertions = map[string]struct {
clientName string
organizations []string
}{
kubeadmconstants.AdminKubeConfigFileName: {
clientName: "kubernetes-admin",
organizations: []string{kubeadmconstants.MastersGroup},
},
kubeadmconstants.KubeletKubeConfigFileName: {
clientName: "system:node:valid-nome-name",
organizations: []string{kubeadmconstants.NodesGroup},
},
kubeadmconstants.ControllerManagerKubeConfigFileName: {
clientName: kubeadmconstants.ControllerManagerUser,
},
kubeadmconstants.SchedulerKubeConfigFileName: {
clientName: kubeadmconstants.SchedulerUser,
},
}
for _, test := range tests {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// Adds a pki folder with a ca certs to the temp folder
pkidir := testutil.SetupPkiDirWithCertificateAuthorithy(t, tmpdir)
outputdir := tmpdir
// Retrieves ca cert for assertions
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
if err != nil {
t.Fatalf("couldn't retrieve ca cert: %v", err)
}
// Get subcommands working in the temporary directory
subCmds := getKubeConfigSubCommands(nil, tmpdir, phaseTestK8sVersion)
// Execute the subcommand
certDirFlag := fmt.Sprintf("--cert-dir=%s", pkidir)
outputDirFlag := fmt.Sprintf("--kubeconfig-dir=%s", outputdir)
allFlags := append(commonFlags, certDirFlag)
allFlags = append(allFlags, outputDirFlag)
allFlags = append(allFlags, test.additionalFlags...)
cmdtestutil.RunSubCommand(t, subCmds, test.command, allFlags...)
// Checks that requested files are there
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
// Checks contents of generated files
for _, file := range test.expectedFiles {
// reads generated files
config, err := clientcmd.LoadFromFile(filepath.Join(tmpdir, file))
if err != nil {
t.Errorf("couldn't load generated kubeconfig file: %v", err)
}
// checks that CLI flags are properly propagated and kubeconfig properties are correct
kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
expectedClientName := kubeConfigAssertions[file].clientName
expectedOrganizations := kubeConfigAssertions[file].organizations
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, expectedClientName, expectedOrganizations...)
}
}
}
func TestKubeConfigSubCommandsThatCreateFilesWithConfigFile(t *testing.T) {
var tests = []struct {
command string
expectedFiles []string
}{
{
command: "all",
expectedFiles: []string{
kubeadmconstants.AdminKubeConfigFileName,
kubeadmconstants.KubeletKubeConfigFileName,
kubeadmconstants.ControllerManagerKubeConfigFileName,
kubeadmconstants.SchedulerKubeConfigFileName,
},
},
{
command: "admin",
expectedFiles: []string{kubeadmconstants.AdminKubeConfigFileName},
},
{
command: "kubelet",
expectedFiles: []string{kubeadmconstants.KubeletKubeConfigFileName},
},
{
command: "controller-manager",
expectedFiles: []string{kubeadmconstants.ControllerManagerKubeConfigFileName},
},
{
command: "scheduler",
expectedFiles: []string{kubeadmconstants.SchedulerKubeConfigFileName},
},
}
var kubeConfigAssertions = map[string]struct {
clientName string
organizations []string
}{
kubeadmconstants.AdminKubeConfigFileName: {
clientName: "kubernetes-admin",
organizations: []string{kubeadmconstants.MastersGroup},
},
kubeadmconstants.KubeletKubeConfigFileName: {
clientName: "system:node:valid-node-name",
organizations: []string{kubeadmconstants.NodesGroup},
},
kubeadmconstants.ControllerManagerKubeConfigFileName: {
clientName: kubeadmconstants.ControllerManagerUser,
},
kubeadmconstants.SchedulerKubeConfigFileName: {
clientName: kubeadmconstants.SchedulerUser,
},
}
for _, test := range tests {
// Create temp folder for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// Adds a pki folder with a ca certs to the temp folder
pkidir := testutil.SetupPkiDirWithCertificateAuthorithy(t, tmpdir)
// Retrieves ca cert for assertions
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
if err != nil {
t.Fatalf("couldn't retrieve ca cert: %v", err)
}
// Adds a master configuration file
cfg := &kubeadmapi.MasterConfiguration{
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
CertificatesDir: pkidir,
NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"},
}
cfgPath := testutil.SetupMasterConfigurationFile(t, tmpdir, cfg)
// Get subcommands working in the temporary directory
subCmds := getKubeConfigSubCommands(nil, tmpdir, phaseTestK8sVersion)
// Execute the subcommand
configFlag := fmt.Sprintf("--config=%s", cfgPath)
cmdtestutil.RunSubCommand(t, subCmds, test.command, configFlag)
// Checks that requested files are there
testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
// Checks contents of generated files
for _, file := range test.expectedFiles {
// reads generated files
config, err := clientcmd.LoadFromFile(filepath.Join(tmpdir, file))
if err != nil {
t.Errorf("couldn't load generated kubeconfig file: %v", err)
}
// checks that config file properties are properly propagated and kubeconfig properties are correct
kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
expectedClientName := kubeConfigAssertions[file].clientName
expectedOrganizations := kubeConfigAssertions[file].organizations
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, expectedClientName, expectedOrganizations...)
}
}
}
func TestKubeConfigSubCommandsThatWritesToOut(t *testing.T) {
// Temporary folders for the test case
tmpdir := testutil.SetupTempDir(t)
defer os.RemoveAll(tmpdir)
// Adds a pki folder with a ca cert to the temp folder
pkidir := testutil.SetupPkiDirWithCertificateAuthorithy(t, tmpdir)
outputdir := tmpdir
// Retrieves ca cert for assertions
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
if err != nil {
t.Fatalf("couldn't retrieve ca cert: %v", err)
}
commonFlags := []string{
"--apiserver-advertise-address=1.2.3.4",
"--apiserver-bind-port=1234",
"--client-name=myUser",
fmt.Sprintf("--cert-dir=%s", pkidir),
fmt.Sprintf("--kubeconfig-dir=%s", outputdir),
}
var tests = []struct {
command string
withClientCert bool
withToken bool
additionalFlags []string
}{
{ // Test user subCommand withClientCert
command: "user",
withClientCert: true,
},
{ // Test user subCommand withToken
withToken: true,
command: "user",
additionalFlags: []string{"--token=123456"},
},
}
for _, test := range tests {
buf := new(bytes.Buffer)
// Get subcommands working in the temporary directory
subCmds := getKubeConfigSubCommands(buf, tmpdir, phaseTestK8sVersion)
// Execute the subcommand
allFlags := append(commonFlags, test.additionalFlags...)
cmdtestutil.RunSubCommand(t, subCmds, test.command, allFlags...)
// reads kubeconfig written to stdout
config, err := clientcmd.Load(buf.Bytes())
if err != nil {
t.Errorf("couldn't read kubeconfig file from buffer: %v", err)
continue
}
// checks that CLI flags are properly propagated
kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
if test.withClientCert {
// checks that kubeconfig files have expected client cert
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, "myUser")
}
if test.withToken {
// checks that kubeconfig files have expected token
kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myUser", "123456")
}
}
}

View File

@ -17,318 +17,78 @@ limitations under the License.
package phases
import (
"fmt"
"io/ioutil"
"github.com/spf13/cobra"
"github.com/pkg/errors"
"k8s.io/klog"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
"k8s.io/kubernetes/pkg/util/version"
utilsexec "k8s.io/utils/exec"
)
const (
// TODO: Figure out how to get these constants from the API machinery
masterConfig = "MasterConfiguration"
nodeConfig = "NodeConfiguration"
)
var (
kubeletWriteEnvFileLongDesc = normalizer.LongDesc(`
Writes an environment file with flags that should be passed to the kubelet executing on the master or node.
This --config flag can either consume a MasterConfiguration object or a NodeConfiguration one, as this
function is used for both "kubeadm init" and "kubeadm join".
` + cmdutil.AlphaDisclaimer)
kubeletWriteEnvFileExample = normalizer.Examples(`
# Writes a dynamic environment file with kubelet flags from a MasterConfiguration file.
kubeadm alpha phase kubelet write-env-file --config masterconfig.yaml
# Writes a dynamic environment file with kubelet flags from a NodeConfiguration file.
kubeadm alpha phase kubelet write-env-file --config nodeConfig.yaml
`)
kubeletConfigUploadLongDesc = normalizer.LongDesc(`
Uploads kubelet configuration extracted from the kubeadm MasterConfiguration object to a ConfigMap
of the form kubelet-config-1.X in the cluster, where X is the minor version of the current (API Server) Kubernetes version.
` + cmdutil.AlphaDisclaimer)
kubeletConfigUploadExample = normalizer.Examples(`
# Uploads the kubelet configuration from the kubeadm Config file to a ConfigMap in the cluster.
kubeadm alpha phase kubelet config upload --config kubeadm.yaml
`)
kubeletConfigDownloadLongDesc = normalizer.LongDesc(`
Downloads the kubelet configuration from a ConfigMap of the form "kubelet-config-1.X" in the cluster,
where X is the minor version of the kubelet. Either kubeadm autodetects the kubelet version by exec-ing
"kubelet --version" or respects the --kubelet-version parameter.
` + cmdutil.AlphaDisclaimer)
kubeletConfigDownloadExample = normalizer.Examples(`
# Downloads the kubelet configuration from the ConfigMap in the cluster. Autodetects the kubelet version.
kubeadm alpha phase kubelet config download
# Downloads the kubelet configuration from the ConfigMap in the cluster. Uses a specific desired kubelet version.
kubeadm alpha phase kubelet config download --kubelet-version v1.11.0
`)
kubeletConfigWriteToDiskLongDesc = normalizer.LongDesc(`
Writes kubelet configuration to disk, based on the kubeadm configuration passed via "--config".
` + cmdutil.AlphaDisclaimer)
kubeletConfigWriteToDiskExample = normalizer.Examples(`
# Extracts the kubelet configuration from a kubeadm configuration file
kubeadm alpha phase kubelet config write-to-disk --config kubeadm.yaml
`)
kubeletConfigEnableDynamicLongDesc = normalizer.LongDesc(`
Enables or updates dynamic kubelet configuration for a Node, against the kubelet-config-1.X ConfigMap in the cluster,
where X is the minor version of the desired kubelet version.
WARNING: This feature is still experimental, and disabled by default. Enable only if you know what you are doing, as it
may have surprising side-effects at this stage.
` + cmdutil.AlphaDisclaimer)
kubeletConfigEnableDynamicExample = normalizer.Examples(`
# Enables dynamic kubelet configuration for a Node.
kubeadm alpha phase kubelet enable-dynamic-config --node-name node-1 --kubelet-version v1.11.0
WARNING: This feature is still experimental, and disabled by default. Enable only if you know what you are doing, as it
may have surprising side-effects at this stage.
kubeletStartPhaseExample = normalizer.Examples(`
# Writes a dynamic environment file with kubelet flags from a InitConfiguration file.
kubeadm init phase kubelet-start --config masterconfig.yaml
`)
)
// NewCmdKubelet returns command for `kubeadm phase kubelet`
func NewCmdKubelet() *cobra.Command {
cmd := &cobra.Command{
Use: "kubelet",
Short: "Commands related to handling the kubelet.",
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(NewCmdKubeletConfig())
cmd.AddCommand(NewCmdKubeletWriteEnvFile())
return cmd
// kubeletStartData defines the behavior that a runtime data struct passed to the kubelet start phase
// should have. Please note that we are using an interface in order to make this phase reusable in different workflows
// (and thus with different runtime data struct, all of them requested to be compliant to this interface)
type kubeletStartData interface {
Cfg() *kubeadmapi.InitConfiguration
DryRun() bool
KubeletDir() string
}
// NewCmdKubeletWriteEnvFile calls cobra.Command for writing the dynamic kubelet env file based on a MasterConfiguration or NodeConfiguration object
func NewCmdKubeletWriteEnvFile() *cobra.Command {
var cfgPath string
cmd := &cobra.Command{
Use: "write-env-file",
Short: "Writes an environment file with runtime flags for the kubelet.",
Long: kubeletWriteEnvFileLongDesc,
Example: kubeletWriteEnvFileExample,
Run: func(cmd *cobra.Command, args []string) {
err := RunKubeletWriteEnvFile(cfgPath)
kubeadmutil.CheckErr(err)
// NewKubeletStartPhase creates a kubeadm workflow phase that start kubelet on a node.
func NewKubeletStartPhase() workflow.Phase {
return workflow.Phase{
Name: "kubelet-start",
Short: "Writes kubelet settings and (re)starts the kubelet",
Long: "Writes a file with KubeletConfiguration and an environment file with node specific kubelet settings, and then (re)starts kubelet.",
Example: kubeletStartPhaseExample,
Run: runKubeletStart,
InheritFlags: []string{
options.CfgPath,
options.NodeCRISocket,
options.NodeName,
},
}
options.AddConfigFlag(cmd.Flags(), &cfgPath)
return cmd
}
// RunKubeletWriteEnvFile is the function that is run when "kubeadm phase kubelet write-env-file" is executed
func RunKubeletWriteEnvFile(cfgPath string) error {
b, err := ioutil.ReadFile(cfgPath)
if err != nil {
return err
// runKubeletStart executes kubelet start logic.
func runKubeletStart(c workflow.RunData) error {
data, ok := c.(kubeletStartData)
if !ok {
return errors.New("kubelet-start phase invoked with an invalid data struct")
}
gvk, err := kubeadmutil.GroupVersionKindFromBytes(b, kubeadmscheme.Codecs)
if err != nil {
return err
// First off, configure the kubelet. In this short timeframe, kubeadm is trying to stop/restart the kubelet
// Try to stop the kubelet service so no race conditions occur when configuring it
if !data.DryRun() {
klog.V(1).Infof("Stopping the kubelet")
kubeletphase.TryStopKubelet()
}
var nodeRegistrationObj *kubeadmapi.NodeRegistrationOptions
var featureGates map[string]bool
var registerWithTaints bool
switch gvk.Kind {
case masterConfig:
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{})
if err != nil {
return err
}
nodeRegistrationObj = &internalcfg.NodeRegistration
featureGates = internalcfg.FeatureGates
registerWithTaints = false
case nodeConfig:
internalcfg, err := configutil.NodeConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.NodeConfiguration{})
if err != nil {
return err
}
nodeRegistrationObj = &internalcfg.NodeRegistration
featureGates = internalcfg.FeatureGates
registerWithTaints = true
default:
if err != nil {
return fmt.Errorf("Didn't recognize type with GroupVersionKind: %v", gvk)
}
}
if nodeRegistrationObj == nil {
return fmt.Errorf("couldn't load nodeRegistration field from config file")
// Write env file with flags for the kubelet to use. We do not need to write the --register-with-taints for the master,
// as we handle that ourselves in the markmaster phase
// TODO: Maybe we want to do that some time in the future, in order to remove some logic from the markmaster phase?
if err := kubeletphase.WriteKubeletDynamicEnvFile(data.Cfg(), false, data.KubeletDir()); err != nil {
return errors.Wrap(err, "error writing a dynamic environment file for the kubelet")
}
if err := kubeletphase.WriteKubeletDynamicEnvFile(nodeRegistrationObj, featureGates, registerWithTaints, constants.KubeletRunDirectory); err != nil {
return fmt.Errorf("error writing a dynamic environment file for the kubelet: %v", err)
// Write the kubelet configuration file to disk.
if err := kubeletphase.WriteConfigToDisk(data.Cfg().ComponentConfigs.Kubelet, data.KubeletDir()); err != nil {
return errors.Wrap(err, "error writing kubelet configuration to disk")
}
// Try to start the kubelet service in case it's inactive
if !data.DryRun() {
klog.V(1).Infof("Starting the kubelet")
kubeletphase.TryStartKubelet()
}
return nil
}
// NewCmdKubeletConfig returns command for `kubeadm phase kubelet config`
func NewCmdKubeletConfig() *cobra.Command {
cmd := &cobra.Command{
Use: "config",
Short: "Handles kubelet configuration.",
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(NewCmdKubeletConfigUpload())
cmd.AddCommand(NewCmdKubeletConfigDownload())
cmd.AddCommand(NewCmdKubeletConfigWriteToDisk())
cmd.AddCommand(NewCmdKubeletConfigEnableDynamic())
return cmd
}
// NewCmdKubeletConfigUpload calls cobra.Command for uploading dynamic kubelet configuration
func NewCmdKubeletConfigUpload() *cobra.Command {
var cfgPath string
kubeConfigFile := constants.GetAdminKubeConfigPath()
cmd := &cobra.Command{
Use: "upload",
Short: "Uploads kubelet configuration to a ConfigMap based on a kubeadm MasterConfiguration file.",
Long: kubeletConfigUploadLongDesc,
Example: kubeletConfigUploadExample,
Run: func(cmd *cobra.Command, args []string) {
if len(cfgPath) == 0 {
kubeadmutil.CheckErr(fmt.Errorf("The --config argument is required"))
}
// This call returns the ready-to-use configuration based on the configuration file
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{})
kubeadmutil.CheckErr(err)
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
kubeadmutil.CheckErr(err)
err = kubeletphase.CreateConfigMap(internalcfg, client)
kubeadmutil.CheckErr(err)
},
}
options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile)
options.AddConfigFlag(cmd.Flags(), &cfgPath)
return cmd
}
// NewCmdKubeletConfigDownload calls cobra.Command for downloading the kubelet configuration from the kubelet-config-1.X ConfigMap in the cluster
func NewCmdKubeletConfigDownload() *cobra.Command {
var kubeletVersionStr string
// TODO: Be smarter about this and be able to load multiple kubeconfig files in different orders of precedence
kubeConfigFile := constants.GetKubeletKubeConfigPath()
cmd := &cobra.Command{
Use: "download",
Short: "Downloads the kubelet configuration from the cluster ConfigMap kubelet-config-1.X, where X is the minor version of the kubelet.",
Long: kubeletConfigDownloadLongDesc,
Example: kubeletConfigDownloadExample,
Run: func(cmd *cobra.Command, args []string) {
kubeletVersion, err := getKubeletVersion(kubeletVersionStr)
kubeadmutil.CheckErr(err)
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
kubeadmutil.CheckErr(err)
err = kubeletphase.DownloadConfig(client, kubeletVersion, constants.KubeletRunDirectory)
kubeadmutil.CheckErr(err)
},
}
options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile)
cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet. Defaults to being autodetected from 'kubelet --version'.")
return cmd
}
func getKubeletVersion(kubeletVersionStr string) (*version.Version, error) {
if len(kubeletVersionStr) > 0 {
return version.ParseSemantic(kubeletVersionStr)
}
return preflight.GetKubeletVersion(utilsexec.New())
}
// NewCmdKubeletConfigWriteToDisk calls cobra.Command for writing init kubelet configuration
func NewCmdKubeletConfigWriteToDisk() *cobra.Command {
var cfgPath string
cmd := &cobra.Command{
Use: "write-to-disk",
Short: "Writes kubelet configuration to disk, either based on the --config argument.",
Long: kubeletConfigWriteToDiskLongDesc,
Example: kubeletConfigWriteToDiskExample,
Run: func(cmd *cobra.Command, args []string) {
if len(cfgPath) == 0 {
kubeadmutil.CheckErr(fmt.Errorf("The --config argument is required"))
}
// This call returns the ready-to-use configuration based on the configuration file
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, &kubeadmapiv1alpha2.MasterConfiguration{})
kubeadmutil.CheckErr(err)
err = kubeletphase.WriteConfigToDisk(internalcfg.KubeletConfiguration.BaseConfig, constants.KubeletRunDirectory)
kubeadmutil.CheckErr(err)
},
}
options.AddConfigFlag(cmd.Flags(), &cfgPath)
return cmd
}
// NewCmdKubeletConfigEnableDynamic calls cobra.Command for enabling dynamic kubelet configuration on node
// This feature is still in alpha and an experimental state
func NewCmdKubeletConfigEnableDynamic() *cobra.Command {
var nodeName, kubeletVersionStr string
kubeConfigFile := constants.GetAdminKubeConfigPath()
cmd := &cobra.Command{
Use: "enable-dynamic",
Short: "EXPERIMENTAL: Enables or updates dynamic kubelet configuration for a Node",
Long: kubeletConfigEnableDynamicLongDesc,
Example: kubeletConfigEnableDynamicExample,
Run: func(cmd *cobra.Command, args []string) {
if len(nodeName) == 0 {
kubeadmutil.CheckErr(fmt.Errorf("The --node-name argument is required"))
}
if len(kubeletVersionStr) == 0 {
kubeadmutil.CheckErr(fmt.Errorf("The --kubelet-version argument is required"))
}
kubeletVersion, err := version.ParseSemantic(kubeletVersionStr)
kubeadmutil.CheckErr(err)
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
kubeadmutil.CheckErr(err)
err = kubeletphase.EnableDynamicConfigForNode(client, nodeName, kubeletVersion)
kubeadmutil.CheckErr(err)
},
}
options.AddKubeConfigFlag(cmd.Flags(), &kubeConfigFile)
cmd.Flags().StringVar(&nodeName, "node-name", nodeName, "Name of the node that should enable the dynamic kubelet configuration")
cmd.Flags().StringVar(&kubeletVersionStr, "kubelet-version", kubeletVersionStr, "The desired version for the kubelet")
return cmd
}

View File

@ -1,82 +0,0 @@
/*
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 phases
import (
"testing"
"github.com/spf13/cobra"
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
)
func TestKubeletSubCommandsHasFlags(t *testing.T) {
subCmds := []*cobra.Command{
NewCmdKubeletWriteEnvFile(),
NewCmdKubeletConfigUpload(),
NewCmdKubeletConfigDownload(),
NewCmdKubeletConfigWriteToDisk(),
NewCmdKubeletConfigEnableDynamic(),
}
commonFlags := []string{}
var tests = []struct {
command string
additionalFlags []string
}{
{
command: "write-env-file",
additionalFlags: []string{
"config",
},
},
{
command: "upload",
additionalFlags: []string{
"kubeconfig",
"config",
},
},
{
command: "download",
additionalFlags: []string{
"kubeconfig",
"kubelet-version",
},
},
{
command: "write-to-disk",
additionalFlags: []string{
"config",
},
},
{
command: "enable-dynamic",
additionalFlags: []string{
"kubeconfig",
"node-name",
"kubelet-version",
},
},
}
for _, test := range tests {
expectedFlags := append(commonFlags, test.additionalFlags...)
cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...)
}
}

View File

@ -0,0 +1,77 @@
/*
Copyright 2017 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 phases
import (
"github.com/pkg/errors"
clientset "k8s.io/client-go/kubernetes"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
markcontrolplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markcontrolplane"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
markControlPlaneExample = normalizer.Examples(`
# Applies control-plane label and taint to the current node, functionally equivalent to what executed by kubeadm init.
kubeadm init phase mark-control-plane --config config.yml
# Applies control-plane label and taint to a specific node
kubeadm init phase mark-control-plane --node-name myNode
`)
)
type markControlPlaneData interface {
Cfg() *kubeadmapi.InitConfiguration
Client() (clientset.Interface, error)
DryRun() bool
}
// NewMarkControlPlanePhase creates a kubeadm workflow phase that implements mark-controlplane checks.
func NewMarkControlPlanePhase() workflow.Phase {
return workflow.Phase{
Name: "mark-control-plane",
Short: "Mark a node as a control-plane",
Example: markControlPlaneExample,
InheritFlags: []string{
options.NodeName,
options.CfgPath,
},
Run: runMarkControlPlane,
}
}
// runMarkControlPlane executes markcontrolplane checks logic.
func runMarkControlPlane(c workflow.RunData) error {
data, ok := c.(markControlPlaneData)
if !ok {
return errors.New("mark-control-plane phase invoked with an invalid data struct")
}
client, err := data.Client()
if err != nil {
return err
}
nodeRegistration := data.Cfg().NodeRegistration
if err := markcontrolplanephase.MarkControlPlane(client, nodeRegistration.Name, nodeRegistration.Taints); err != nil {
return err
}
return nil
}

View File

@ -1,88 +0,0 @@
/*
Copyright 2017 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 phases
import (
"github.com/spf13/cobra"
kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
markMasterLongDesc = normalizer.LongDesc(`
Applies a label that specifies that a node is a master and a taint that forces workloads to be deployed accordingly.
` + cmdutil.AlphaDisclaimer)
markMasterExample = normalizer.Examples(`
# Applies master label and taint to the current node, functionally equivalent to what executed by kubeadm init.
kubeadm alpha phase mark-master
# Applies master label and taint to a specific node
kubeadm alpha phase mark-master --node-name myNode
`)
)
// NewCmdMarkMaster returns the Cobra command for running the mark-master phase
func NewCmdMarkMaster() *cobra.Command {
cfg := &kubeadmapiv1alpha2.MasterConfiguration{
// KubernetesVersion is not used by mark master, but we set this explicitly to avoid
// the lookup of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
KubernetesVersion: "v1.10.0",
}
// Default values for the cobra help text
kubeadmscheme.Scheme.Default(cfg)
var cfgPath, kubeConfigFile string
cmd := &cobra.Command{
Use: "mark-master",
Short: "Mark a node as master",
Long: markMasterLongDesc,
Example: markMasterExample,
Aliases: []string{"markmaster"},
Run: func(cmd *cobra.Command, args []string) {
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
kubeadmutil.CheckErr(err)
}
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, cfg)
kubeadmutil.CheckErr(err)
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
kubeadmutil.CheckErr(err)
err = markmasterphase.MarkMaster(client, internalcfg.NodeRegistration.Name, internalcfg.NodeRegistration.Taints)
kubeadmutil.CheckErr(err)
},
}
cmd.Flags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster")
cmd.Flags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental")
cmd.Flags().StringVar(&cfg.NodeRegistration.Name, "node-name", cfg.NodeRegistration.Name, `The node name to which label and taints should apply`)
return cmd
}

View File

@ -1,47 +0,0 @@
/*
Copyright 2017 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 phases
import (
"io"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
)
// NewCmdPhase returns the cobra command for the "kubeadm phase" command (currently alpha-gated)
func NewCmdPhase(out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "phase",
Short: "Invoke subsets of kubeadm functions separately for a manual install.",
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(NewCmdAddon())
cmd.AddCommand(NewCmdBootstrapToken())
cmd.AddCommand(NewCmdCerts())
cmd.AddCommand(NewCmdControlplane())
cmd.AddCommand(NewCmdEtcd())
cmd.AddCommand(NewCmdKubelet())
cmd.AddCommand(NewCmdKubeConfig(out))
cmd.AddCommand(NewCmdMarkMaster())
cmd.AddCommand(NewCmdPreFlight())
cmd.AddCommand(NewCmdSelfhosting())
cmd.AddCommand(NewCmdUploadConfig())
return cmd
}

View File

@ -17,80 +17,71 @@ limitations under the License.
package phases
import (
"github.com/spf13/cobra"
"fmt"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/util/sets"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/pkg/util/normalizer"
utilsexec "k8s.io/utils/exec"
)
var (
masterPreflightLongDesc = normalizer.LongDesc(`
Run master pre-flight checks, functionally equivalent to what implemented by kubeadm init.
` + cmdutil.AlphaDisclaimer)
masterPreflightExample = normalizer.Examples(`
# Run master pre-flight checks.
kubeadm alpha phase preflight master
# Run master pre-flight checks using a config file.
kubeadm init phase preflight --config kubeadm-config.yml
`)
nodePreflightLongDesc = normalizer.LongDesc(`
Run node pre-flight checks, functionally equivalent to what implemented by kubeadm join.
` + cmdutil.AlphaDisclaimer)
nodePreflightExample = normalizer.Examples(`
# Run node pre-flight checks.
kubeadm alpha phase preflight node
`)
)
// NewCmdPreFlight calls cobra.Command for preflight checks
func NewCmdPreFlight() *cobra.Command {
cmd := &cobra.Command{
Use: "preflight",
Short: "Run pre-flight checks",
Long: cmdutil.MacroCommandLongDescription,
}
cmd.AddCommand(NewCmdPreFlightMaster())
cmd.AddCommand(NewCmdPreFlightNode())
return cmd
// preflightMasterData defines the behavior that a runtime data struct passed to the PreflightMaster master phase
// should have. Please note that we are using an interface in order to make this phase reusable in different workflows
// (and thus with different runtime data struct, all of them requested to be compliant to this interface)
type preflightMasterData interface {
Cfg() *kubeadmapi.InitConfiguration
DryRun() bool
IgnorePreflightErrors() sets.String
}
// NewCmdPreFlightMaster calls cobra.Command for master preflight checks
func NewCmdPreFlightMaster() *cobra.Command {
cmd := &cobra.Command{
Use: "master",
// NewPreflightMasterPhase creates a kubeadm workflow phase that implements preflight checks for a new master node.
func NewPreflightMasterPhase() workflow.Phase {
return workflow.Phase{
Name: "preflight",
Short: "Run master pre-flight checks",
Long: masterPreflightLongDesc,
Long: "Run master pre-flight checks, functionally equivalent to what implemented by kubeadm init.",
Example: masterPreflightExample,
Run: func(cmd *cobra.Command, args []string) {
cfg := &kubeadmapi.MasterConfiguration{}
err := preflight.RunInitMasterChecks(utilsexec.New(), cfg, sets.NewString())
kubeadmutil.CheckErr(err)
Run: runPreflightMaster,
InheritFlags: []string{
options.CfgPath,
options.IgnorePreflightErrors,
},
}
return cmd
}
// NewCmdPreFlightNode calls cobra.Command for node preflight checks
func NewCmdPreFlightNode() *cobra.Command {
cmd := &cobra.Command{
Use: "node",
Short: "Run node pre-flight checks",
Long: nodePreflightLongDesc,
Example: nodePreflightExample,
Run: func(cmd *cobra.Command, args []string) {
cfg := &kubeadmapi.NodeConfiguration{}
err := preflight.RunJoinNodeChecks(utilsexec.New(), cfg, sets.NewString())
kubeadmutil.CheckErr(err)
},
// runPreflightMaster executes preflight checks logic.
func runPreflightMaster(c workflow.RunData) error {
data, ok := c.(preflightMasterData)
if !ok {
return errors.New("preflight phase invoked with an invalid data struct")
}
return cmd
fmt.Println("[preflight] Running pre-flight checks")
if err := preflight.RunInitMasterChecks(utilsexec.New(), data.Cfg(), data.IgnorePreflightErrors()); err != nil {
return err
}
if !data.DryRun() {
fmt.Println("[preflight] Pulling images required for setting up a Kubernetes cluster")
fmt.Println("[preflight] This might take a minute or two, depending on the speed of your internet connection")
fmt.Println("[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'")
if err := preflight.RunPullImagesCheck(utilsexec.New(), data.Cfg(), data.IgnorePreflightErrors()); err != nil {
return err
}
} else {
fmt.Println("[preflight] Would pull the required images (like 'kubeadm config images pull')")
}
return nil
}

View File

@ -19,60 +19,133 @@ package phases
import (
"fmt"
"github.com/spf13/cobra"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/klog"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/util/normalizer"
)
var (
uploadConfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Uploads the kubeadm init configuration of your cluster to a ConfigMap called %s in the %s namespace.
uploadKubeadmConfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Uploads the kubeadm ClusterConfiguration to a ConfigMap called %s in the %s namespace.
This enables correct configuration of system components and a seamless user experience when upgrading.
Alternatively, you can use kubeadm config.
`+cmdutil.AlphaDisclaimer), kubeadmconstants.MasterConfigurationConfigMap, metav1.NamespaceSystem)
`), kubeadmconstants.KubeadmConfigConfigMap, metav1.NamespaceSystem)
uploadConfigExample = normalizer.Examples(`
uploadKubeadmConfigExample = normalizer.Examples(`
# uploads the configuration of your cluster
kubeadm alpha phase upload-config --config=myConfig.yaml
kubeadm init phase upload-config --config=myConfig.yaml
`)
uploadKubeletConfigLongDesc = normalizer.LongDesc(`
Uploads kubelet configuration extracted from the kubeadm InitConfiguration object to a ConfigMap
of the form kubelet-config-1.X in the cluster, where X is the minor version of the current (API Server) Kubernetes version.
`)
uploadKubeletConfigExample = normalizer.Examples(`
# Uploads the kubelet configuration from the kubeadm Config file to a ConfigMap in the cluster.
kubeadm init phase upload-config kubelet --config kubeadm.yaml
`)
)
// NewCmdUploadConfig returns the Cobra command for running the uploadconfig phase
func NewCmdUploadConfig() *cobra.Command {
var cfgPath, kubeConfigFile string
cmd := &cobra.Command{
Use: "upload-config",
Short: "Uploads the currently used configuration for kubeadm to a ConfigMap",
Long: uploadConfigLongDesc,
Example: uploadConfigExample,
type uploadConfigData interface {
Cfg() *kubeadmapi.InitConfiguration
Client() (clientset.Interface, error)
}
// NewUploadConfigPhase returns the phase to uploadConfig
func NewUploadConfigPhase() workflow.Phase {
return workflow.Phase{
Name: "upload-config",
Aliases: []string{"uploadconfig"},
Run: func(_ *cobra.Command, args []string) {
if len(cfgPath) == 0 {
kubeadmutil.CheckErr(fmt.Errorf("the --config flag is mandatory"))
}
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
kubeadmutil.CheckErr(err)
defaultcfg := &kubeadmapiv1alpha2.MasterConfiguration{}
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, defaultcfg)
kubeadmutil.CheckErr(err)
err = uploadconfig.UploadConfiguration(internalcfg, client)
kubeadmutil.CheckErr(err)
Short: "Uploads the kubeadm and kubelet configuration to a ConfigMap",
Long: cmdutil.MacroCommandLongDescription,
Phases: []workflow.Phase{
{
Name: "all",
Short: "Uploads all configuration to a config map",
RunAllSiblings: true,
InheritFlags: getUploadConfigPhaseFlags(),
},
{
Name: "kubeadm",
Short: "Uploads the kubeadm ClusterConfiguration to a ConfigMap",
Long: uploadKubeadmConfigLongDesc,
Example: uploadKubeadmConfigExample,
Run: runUploadKubeadmConfig,
InheritFlags: getUploadConfigPhaseFlags(),
},
{
Name: "kubelet",
Short: "Uploads the kubelet component config to a ConfigMap",
Long: uploadKubeletConfigLongDesc,
Example: uploadKubeletConfigExample,
Run: runUploadKubeletConfig,
InheritFlags: getUploadConfigPhaseFlags(),
},
},
}
cmd.Flags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster")
cmd.Flags().StringVar(&cfgPath, "config", "", "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental")
return cmd
}
func getUploadConfigPhaseFlags() []string {
return []string{
options.CfgPath,
options.KubeconfigPath,
}
}
// runUploadKubeadmConfig uploads the kubeadm configuration to a ConfigMap
func runUploadKubeadmConfig(c workflow.RunData) error {
cfg, client, err := getUploadConfigData(c)
if err != nil {
return err
}
klog.V(1).Infof("[upload-config] Uploading the kubeadm ClusterConfiguration to a ConfigMap")
if err := uploadconfig.UploadConfiguration(cfg, client); err != nil {
return errors.Wrap(err, "error uploading the kubeadm ClusterConfiguration")
}
return nil
}
// runUploadKubeletConfig uploads the kubelet configuration to a ConfigMap
func runUploadKubeletConfig(c workflow.RunData) error {
cfg, client, err := getUploadConfigData(c)
if err != nil {
return err
}
klog.V(1).Infof("[upload-config] Uploading the kubelet component config to a ConfigMap")
if err = kubeletphase.CreateConfigMap(cfg, client); err != nil {
return errors.Wrap(err, "error creating kubelet configuration ConfigMap")
}
klog.V(1).Infof("[upload-config] Preserving the CRISocket information for the control-plane node")
if err := patchnodephase.AnnotateCRISocket(client, cfg.NodeRegistration.Name, cfg.NodeRegistration.CRISocket); err != nil {
return errors.Wrap(err, "Error writing Crisocket information for the control-plane node")
}
return nil
}
func getUploadConfigData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.Interface, error) {
data, ok := c.(uploadConfigData)
if !ok {
return nil, nil, errors.New("upload-config phase invoked with an invalid data struct")
}
cfg := data.Cfg()
client, err := data.Client()
if err != nil {
return nil, nil, err
}
return cfg, client, err
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors.
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.
@ -20,14 +20,15 @@ import (
"github.com/spf13/cobra"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapiv1alpha2 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha2"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
"k8s.io/kubernetes/pkg/version"
)
// runCmdPhase creates a cobra.Command Run function, by composing the call to the given cmdFunc with necessary additional steps (e.g preparation of input parameters)
func runCmdPhase(cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration) error, outDir, cfgPath *string, cfg *kubeadmapiv1alpha2.MasterConfiguration) func(cmd *cobra.Command, args []string) {
func runCmdPhase(cmdFunc func(outDir string, cfg *kubeadmapi.InitConfiguration) error, outDir, cfgPath *string, cfg *kubeadmapiv1beta1.InitConfiguration, defaultKubernetesVersion string) func(cmd *cobra.Command, args []string) {
// the following statement build a closure that wraps a call to a cmdFunc, binding
// the function itself with the specific parameters of each sub command.
@ -39,6 +40,17 @@ func runCmdPhase(cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration
kubeadmutil.CheckErr(err)
}
// This is used for unit testing only...
// If we wouldn't set this to something, the code would dynamically look up the version from the internet
// By setting this explicitly for tests workarounds that
if defaultKubernetesVersion != "" {
cfg.KubernetesVersion = defaultKubernetesVersion
} else {
// KubernetesVersion is not used, but we set it explicitly to avoid the lookup
// of the version from the internet when executing ConfigFileAndDefaultsToInternalConfig
SetKubernetesVersion(cfg)
}
// This call returns the ready-to-use configuration based on the configuration file that might or might not exist and the default cfg populated by flags
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(*cfgPath, cfg)
kubeadmutil.CheckErr(err)
@ -48,3 +60,13 @@ func runCmdPhase(cmdFunc func(outDir string, cfg *kubeadmapi.MasterConfiguration
kubeadmutil.CheckErr(err)
}
}
// SetKubernetesVersion gets the current Kubeadm version and sets it as KubeadmVersion in the config,
// unless it's already set to a value different from the default.
func SetKubernetesVersion(cfg *kubeadmapiv1beta1.InitConfiguration) {
if cfg.KubernetesVersion != kubeadmapiv1beta1.DefaultKubernetesVersion && cfg.KubernetesVersion != "" {
return
}
cfg.KubernetesVersion = version.Get().String()
}

View File

@ -0,0 +1,61 @@
/*
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 phases
import (
"testing"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
"k8s.io/kubernetes/pkg/version"
)
func TestSetKubernetesVersion(t *testing.T) {
ver := version.Get().String()
tests := []struct {
name string
input string
output string
}{
{
name: "empty version is processed",
input: "",
output: ver,
},
{
name: "default version is processed",
input: kubeadmapiv1beta1.DefaultKubernetesVersion,
output: ver,
},
{
name: "any other version is skipped",
input: "v1.12.0",
output: "v1.12.0",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
cfg := &kubeadmapiv1beta1.InitConfiguration{ClusterConfiguration: kubeadmapiv1beta1.ClusterConfiguration{KubernetesVersion: test.input}}
SetKubernetesVersion(cfg)
if cfg.KubernetesVersion != test.output {
t.Fatalf("expected %q, got %q", test.output, cfg.KubernetesVersion)
}
})
}
}

Some files were not shown because too many files have changed in this diff Show More