mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 10:53:34 +00:00
vendor files
This commit is contained in:
54
vendor/k8s.io/kubernetes/cmd/kubeadm/app/BUILD
generated
vendored
Normal file
54
vendor/k8s.io/kubernetes/cmd/kubeadm/app/BUILD
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["kubeadm.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/install:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm:all-srcs",
|
||||
"//cmd/kubeadm/app/cmd:all-srcs",
|
||||
"//cmd/kubeadm/app/constants:all-srcs",
|
||||
"//cmd/kubeadm/app/discovery:all-srcs",
|
||||
"//cmd/kubeadm/app/features:all-srcs",
|
||||
"//cmd/kubeadm/app/images:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/addons/dns:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/addons/proxy:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/bootstraptoken/clusterinfo:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/bootstraptoken/node:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/certs:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/controlplane:all-srcs",
|
||||
"//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/selfhosting:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/token:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/upgrade:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/uploadconfig:all-srcs",
|
||||
"//cmd/kubeadm/app/preflight:all-srcs",
|
||||
"//cmd/kubeadm/app/util:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
44
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/BUILD
generated
vendored
Normal file
44
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/BUILD
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
"well_known_labels.go",
|
||||
"zz_generated.deepcopy.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm",
|
||||
deps = [
|
||||
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
|
||||
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1: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",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/fuzzer:all-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/install:all-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:all-srcs",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
23
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/doc.go
generated
vendored
Normal file
23
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/doc.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
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 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 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
34
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD
generated
vendored
Normal file
34
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/BUILD
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["fuzzer.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
|
||||
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
|
||||
"//pkg/util/pointer:go_default_library",
|
||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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"],
|
||||
)
|
127
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go
generated
vendored
Normal file
127
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
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 fuzzer
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/gofuzz"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
||||
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
|
||||
)
|
||||
|
||||
// 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.TokenTTL = &metav1.Duration{Duration: 1 * time.Hour}
|
||||
obj.API.AdvertiseAddress = "foo"
|
||||
obj.Networking.ServiceSubnet = "foo"
|
||||
obj.Networking.DNSDomain = "foo"
|
||||
obj.AuthorizationModes = []string{"foo"}
|
||||
obj.CertificatesDir = "foo"
|
||||
obj.APIServerCertSANs = []string{"foo"}
|
||||
obj.Token = "foo"
|
||||
obj.Etcd.Image = "foo"
|
||||
obj.Etcd.DataDir = "foo"
|
||||
obj.ImageRepository = "foo"
|
||||
obj.CIImageRepository = ""
|
||||
obj.UnifiedControlPlaneImage = "foo"
|
||||
obj.FeatureGates = map[string]bool{"foo": true}
|
||||
obj.APIServerExtraArgs = map[string]string{"foo": "foo"}
|
||||
obj.APIServerExtraVolumes = []kubeadm.HostPathMount{{
|
||||
Name: "foo",
|
||||
HostPath: "foo",
|
||||
MountPath: "foo",
|
||||
}}
|
||||
obj.Etcd.ExtraArgs = map[string]string{"foo": "foo"}
|
||||
obj.Etcd.SelfHosted = &kubeadm.SelfHostedEtcd{
|
||||
CertificatesDir: "/etc/kubernetes/pki/etcd",
|
||||
ClusterServiceName: "etcd-cluster",
|
||||
EtcdVersion: "v0.1.0",
|
||||
OperatorVersion: "v0.1.0",
|
||||
}
|
||||
obj.KubeletConfiguration = kubeadm.KubeletConfiguration{
|
||||
BaseConfig: &kubeletconfigv1alpha1.KubeletConfiguration{
|
||||
PodManifestPath: "foo",
|
||||
AllowPrivileged: utilpointer.BoolPtr(true),
|
||||
ClusterDNS: []string{"foo"},
|
||||
ClusterDomain: "foo",
|
||||
Authorization: kubeletconfigv1alpha1.KubeletAuthorization{Mode: "foo"},
|
||||
Authentication: kubeletconfigv1alpha1.KubeletAuthentication{
|
||||
X509: kubeletconfigv1alpha1.KubeletX509Authentication{ClientCAFile: "foo"},
|
||||
},
|
||||
CAdvisorPort: utilpointer.Int32Ptr(0),
|
||||
},
|
||||
}
|
||||
kubeletconfigv1alpha1.SetDefaults_KubeletConfiguration(obj.KubeletConfiguration.BaseConfig)
|
||||
obj.KubeProxy = kubeadm.KubeProxy{
|
||||
Config: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{
|
||||
FeatureGates: "foo",
|
||||
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},
|
||||
},
|
||||
}
|
||||
},
|
||||
func(obj *kubeadm.NodeConfiguration, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
obj.CACertPath = "foo"
|
||||
obj.CACertPath = "foo"
|
||||
obj.DiscoveryFile = "foo"
|
||||
obj.DiscoveryToken = "foo"
|
||||
obj.DiscoveryTokenAPIServers = []string{"foo"}
|
||||
obj.TLSBootstrapToken = "foo"
|
||||
obj.Token = "foo"
|
||||
},
|
||||
}
|
||||
}
|
48
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/BUILD
generated
vendored
Normal file
48
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/BUILD
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"install.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["install_test.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/fuzzer:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
|
||||
],
|
||||
)
|
17
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/doc.go
generated
vendored
Normal file
17
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/doc.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
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 install // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install"
|
46
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install.go
generated
vendored
Normal file
46
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
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 install
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apimachinery/announced"
|
||||
"k8s.io/apimachinery/pkg/apimachinery/registered"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Install(legacyscheme.GroupFactoryRegistry, legacyscheme.Registry, legacyscheme.Scheme)
|
||||
}
|
||||
|
||||
// Install registers the API group and adds types to a scheme
|
||||
func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) {
|
||||
if err := announced.NewGroupMetaFactory(
|
||||
&announced.GroupMetaFactoryArgs{
|
||||
GroupName: kubeadm.GroupName,
|
||||
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
|
||||
AddInternalObjectsToScheme: kubeadm.AddToScheme,
|
||||
},
|
||||
announced.VersionToSchemeFunc{
|
||||
v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme,
|
||||
},
|
||||
).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install_test.go
generated
vendored
Normal file
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install_test.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
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 install
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
|
||||
kubeadmfuzzer "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer"
|
||||
)
|
||||
|
||||
func TestRoundTripTypes(t *testing.T) {
|
||||
roundtrip.RoundTripTestForAPIGroup(t, Install, kubeadmfuzzer.Funcs)
|
||||
}
|
53
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/register.go
generated
vendored
Normal file
53
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/register.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
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 kubeadm
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "kubeadm.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
|
||||
|
||||
var (
|
||||
// SchemeBuilder points to a list of functions added to Scheme.
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
// AddToScheme applies all the stored functions to the scheme.
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Kind takes an unqualified kind and returns a Group qualified GroupKind
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&MasterConfiguration{},
|
||||
&NodeConfiguration{},
|
||||
)
|
||||
return nil
|
||||
}
|
182
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/types.go
generated
vendored
Normal file
182
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/types.go
generated
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
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 kubeadm
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||
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
|
||||
|
||||
API API
|
||||
KubeProxy KubeProxy
|
||||
Etcd Etcd
|
||||
KubeletConfiguration KubeletConfiguration
|
||||
Networking Networking
|
||||
KubernetesVersion string
|
||||
CloudProvider string
|
||||
NodeName string
|
||||
AuthorizationModes []string
|
||||
|
||||
Token string
|
||||
TokenTTL *metav1.Duration
|
||||
|
||||
APIServerExtraArgs map[string]string
|
||||
ControllerManagerExtraArgs map[string]string
|
||||
SchedulerExtraArgs map[string]string
|
||||
|
||||
APIServerExtraVolumes []HostPathMount
|
||||
ControllerManagerExtraVolumes []HostPathMount
|
||||
SchedulerExtraVolumes []HostPathMount
|
||||
|
||||
// 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 what container registry to pull control plane images from
|
||||
ImageRepository string
|
||||
|
||||
// Container registry for core images generated by CI
|
||||
// +k8s:conversion-gen=false
|
||||
CIImageRepository string
|
||||
|
||||
// UnifiedControlPlaneImage specifies if a specific container image should be used for all control plane components
|
||||
UnifiedControlPlaneImage string
|
||||
|
||||
// FeatureGates enabled by the user
|
||||
FeatureGates map[string]bool
|
||||
}
|
||||
|
||||
// API struct contains elements of API server address.
|
||||
type API struct {
|
||||
// AdvertiseAddress sets the address for the API server to advertise.
|
||||
AdvertiseAddress string
|
||||
// BindPort sets the secure port for the API Server to bind to
|
||||
BindPort int32
|
||||
}
|
||||
|
||||
// TokenDiscovery contains elements needed for token discovery
|
||||
type TokenDiscovery struct {
|
||||
ID string
|
||||
Secret string
|
||||
Addresses []string
|
||||
}
|
||||
|
||||
// Networking contains elements describing cluster's networking configuration
|
||||
type Networking struct {
|
||||
ServiceSubnet string
|
||||
PodSubnet string
|
||||
DNSDomain string
|
||||
}
|
||||
|
||||
// Etcd contains elements describing Etcd configuration
|
||||
type Etcd struct {
|
||||
Endpoints []string
|
||||
CAFile string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
DataDir string
|
||||
ExtraArgs map[string]string
|
||||
// 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
|
||||
SelfHosted *SelfHostedEtcd
|
||||
}
|
||||
|
||||
// SelfHostedEtcd describes options required to configure self-hosted etcd
|
||||
type SelfHostedEtcd struct {
|
||||
// CertificatesDir represents the directory where all etcd TLS assets are stored. By default this is
|
||||
// a dir names "etcd" in the main CertificatesDir value.
|
||||
CertificatesDir string
|
||||
// ClusterServiceName is the name of the service that load balances the etcd cluster
|
||||
ClusterServiceName string
|
||||
// EtcdVersion is the version of etcd running in the cluster.
|
||||
EtcdVersion string
|
||||
// OperatorVersion is the version of the etcd-operator to use.
|
||||
OperatorVersion string
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// NodeConfiguration contains elements describing a particular node
|
||||
type NodeConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
CACertPath string
|
||||
DiscoveryFile string
|
||||
DiscoveryToken string
|
||||
// Currently we only pay attention to one api server but hope to support >1 in the future
|
||||
DiscoveryTokenAPIServers []string
|
||||
NodeName string
|
||||
TLSBootstrapToken string
|
||||
Token string
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
|
||||
// FeatureGates enabled by the user
|
||||
FeatureGates map[string]bool
|
||||
}
|
||||
|
||||
// KubeletConfiguration contains elements describing initial remote configuration of kubelet
|
||||
type KubeletConfiguration struct {
|
||||
BaseConfig *kubeletconfigv1alpha1.KubeletConfiguration
|
||||
}
|
||||
|
||||
// GetControlPlaneImageRepository returns name of image repository
|
||||
// for control plane images (API,Controller Manager,Scheduler and Proxy)
|
||||
// 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 {
|
||||
if cfg.CIImageRepository != "" {
|
||||
return cfg.CIImageRepository
|
||||
}
|
||||
return cfg.ImageRepository
|
||||
}
|
||||
|
||||
// HostPathMount contains elements describing volumes that are mounted from the
|
||||
// host
|
||||
type HostPathMount struct {
|
||||
Name string
|
||||
HostPath string
|
||||
MountPath string
|
||||
}
|
||||
|
||||
// KubeProxy contains elements describing the proxy configuration
|
||||
type KubeProxy struct {
|
||||
Config *kubeproxyconfigv1alpha1.KubeProxyConfiguration
|
||||
}
|
50
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD
generated
vendored
Normal file
50
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"defaults.go",
|
||||
"defaults_unix.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:windows_amd64": [
|
||||
"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",
|
||||
"//cmd/kubeadm/app/features:go_default_library",
|
||||
"//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library",
|
||||
"//pkg/kubelet/apis/kubeletconfig/v1alpha1: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/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",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
216
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go
generated
vendored
Normal file
216
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go
generated
vendored
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
|
||||
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||
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.9"
|
||||
// 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 = "gcr.io/google_containers"
|
||||
// DefaultManifestsDir defines default manifests directory
|
||||
DefaultManifestsDir = "/etc/kubernetes/manifests"
|
||||
|
||||
// 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 efines the file name for the kube-proxy's KubeConfig file
|
||||
KubeproxyKubeConfigFileName = "/var/lib/kube-proxy/kubeconfig.conf"
|
||||
)
|
||||
|
||||
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.ImageRepository == "" {
|
||||
obj.ImageRepository = DefaultImageRepository
|
||||
}
|
||||
|
||||
if obj.Etcd.DataDir == "" {
|
||||
obj.Etcd.DataDir = DefaultEtcdDataDir
|
||||
}
|
||||
|
||||
SetDefaultsEtcdSelfHosted(obj)
|
||||
if features.Enabled(obj.FeatureGates, features.DynamicKubeletConfig) {
|
||||
SetDefaults_KubeletConfiguration(obj)
|
||||
}
|
||||
SetDefaults_ProxyConfiguration(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
|
||||
}
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 = &kubeletconfigv1alpha1.KubeletConfiguration{}
|
||||
}
|
||||
if obj.KubeletConfiguration.BaseConfig.PodManifestPath == "" {
|
||||
obj.KubeletConfiguration.BaseConfig.PodManifestPath = DefaultManifestsDir
|
||||
}
|
||||
if obj.KubeletConfiguration.BaseConfig.AllowPrivileged == nil {
|
||||
obj.KubeletConfiguration.BaseConfig.AllowPrivileged = utilpointer.BoolPtr(true)
|
||||
}
|
||||
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 = DefaultServiceDNSDomain
|
||||
}
|
||||
if obj.KubeletConfiguration.BaseConfig.Authorization.Mode == "" {
|
||||
obj.KubeletConfiguration.BaseConfig.Authorization.Mode = kubeletconfigv1alpha1.KubeletAuthorizationModeWebhook
|
||||
}
|
||||
if obj.KubeletConfiguration.BaseConfig.Authentication.X509.ClientCAFile == "" {
|
||||
obj.KubeletConfiguration.BaseConfig.Authentication.X509.ClientCAFile = DefaultCACertPath
|
||||
}
|
||||
if obj.KubeletConfiguration.BaseConfig.CAdvisorPort == nil {
|
||||
obj.KubeletConfiguration.BaseConfig.CAdvisorPort = utilpointer.Int32Ptr(0)
|
||||
}
|
||||
|
||||
scheme, _, _ := kubeletscheme.NewSchemeAndCodecs()
|
||||
if scheme != nil {
|
||||
scheme.Default(obj.KubeletConfiguration.BaseConfig)
|
||||
}
|
||||
}
|
22
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults_unix.go
generated
vendored
Normal file
22
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults_unix.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
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 v1alpha1
|
||||
|
||||
// DefaultCACertPath defines default location of CA certificate on Linux
|
||||
const DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
|
22
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults_windows.go
generated
vendored
Normal file
22
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults_windows.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
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 v1alpha1
|
||||
|
||||
// DefaultCACertPath defines default location of CA certificate on Windows
|
||||
const DefaultCACertPath = "C:/etc/kubernetes/pki/ca.crt"
|
22
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/doc.go
generated
vendored
Normal file
22
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/doc.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
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"
|
66
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/register.go
generated
vendored
Normal file
66
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/register.go
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
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 (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "kubeadm.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
|
||||
|
||||
var (
|
||||
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
|
||||
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
|
||||
|
||||
// SchemeBuilder points to a list of functions added to Scheme.
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// AddToScheme applies all the stored functions to the scheme.
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
// We only register manually written functions here. The registration of the
|
||||
// generated functions takes place in the generated files. The separation
|
||||
// makes the code compile even when the generated files are missing.
|
||||
localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
|
||||
}
|
||||
|
||||
// Kind takes an unqualified kind and returns a Group qualified GroupKind
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&MasterConfiguration{},
|
||||
&NodeConfiguration{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
164
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go
generated
vendored
Normal file
164
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
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 (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||
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 API `json:"api"`
|
||||
KubeProxy KubeProxy `json:"kubeProxy"`
|
||||
Etcd Etcd `json:"etcd"`
|
||||
KubeletConfiguration KubeletConfiguration `json:"kubeletConfiguration"`
|
||||
Networking Networking `json:"networking"`
|
||||
KubernetesVersion string `json:"kubernetesVersion"`
|
||||
CloudProvider string `json:"cloudProvider"`
|
||||
NodeName string `json:"nodeName"`
|
||||
AuthorizationModes []string `json:"authorizationModes,omitempty"`
|
||||
|
||||
Token string `json:"token"`
|
||||
TokenTTL *metav1.Duration `json:"tokenTTL,omitempty"`
|
||||
|
||||
APIServerExtraArgs map[string]string `json:"apiServerExtraArgs,omitempty"`
|
||||
ControllerManagerExtraArgs map[string]string `json:"controllerManagerExtraArgs,omitempty"`
|
||||
SchedulerExtraArgs map[string]string `json:"schedulerExtraArgs,omitempty"`
|
||||
|
||||
APIServerExtraVolumes []HostPathMount `json:"apiServerExtraVolumes,omitempty"`
|
||||
ControllerManagerExtraVolumes []HostPathMount `json:"controllerManagerExtraVolumes,omitempty"`
|
||||
SchedulerExtraVolumes []HostPathMount `json:"schedulerExtraVolumes,omitempty"`
|
||||
|
||||
// APIServerCertSANs sets extra Subject Alternative Names for the API Server signing cert
|
||||
APIServerCertSANs []string `json:"apiServerCertSANs,omitempty"`
|
||||
// CertificatesDir specifies where to store or look for all required certificates
|
||||
CertificatesDir string `json:"certificatesDir"`
|
||||
|
||||
// ImageRepository what container registry to pull control plane images from
|
||||
ImageRepository string `json:"imageRepository"`
|
||||
// UnifiedControlPlaneImage specifies if a specific container image should be used for all control plane components
|
||||
UnifiedControlPlaneImage string `json:"unifiedControlPlaneImage"`
|
||||
|
||||
// FeatureGates enabled by the user
|
||||
FeatureGates map[string]bool `json:"featureGates,omitempty"`
|
||||
}
|
||||
|
||||
// API struct contains elements of API server address.
|
||||
type API struct {
|
||||
// AdvertiseAddress sets the address for the API server to advertise.
|
||||
AdvertiseAddress string `json:"advertiseAddress"`
|
||||
// BindPort sets the secure port for the API Server to bind to
|
||||
BindPort int32 `json:"bindPort"`
|
||||
}
|
||||
|
||||
// TokenDiscovery contains elements needed for token discovery
|
||||
type TokenDiscovery struct {
|
||||
ID string `json:"id"`
|
||||
Secret string `json:"secret"`
|
||||
Addresses []string `json:"addresses"`
|
||||
}
|
||||
|
||||
// Networking contains elements describing cluster's networking configuration
|
||||
type Networking struct {
|
||||
ServiceSubnet string `json:"serviceSubnet"`
|
||||
PodSubnet string `json:"podSubnet"`
|
||||
DNSDomain string `json:"dnsDomain"`
|
||||
}
|
||||
|
||||
// Etcd contains elements describing Etcd configuration
|
||||
type Etcd struct {
|
||||
Endpoints []string `json:"endpoints"`
|
||||
CAFile string `json:"caFile"`
|
||||
CertFile string `json:"certFile"`
|
||||
KeyFile string `json:"keyFile"`
|
||||
DataDir string `json:"dataDir"`
|
||||
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 *SelfHostedEtcd `json:"selfHosted,omitempty"`
|
||||
}
|
||||
|
||||
// SelfHostedEtcd describes options required to configure self-hosted etcd
|
||||
type SelfHostedEtcd struct {
|
||||
// CertificatesDir represents the directory where all etcd TLS assets are stored. By default this is
|
||||
// a dir names "etcd" in the main CertificatesDir value.
|
||||
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
|
||||
type NodeConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
CACertPath string `json:"caCertPath"`
|
||||
DiscoveryFile string `json:"discoveryFile"`
|
||||
DiscoveryToken string `json:"discoveryToken"`
|
||||
DiscoveryTokenAPIServers []string `json:"discoveryTokenAPIServers,omitempty"`
|
||||
NodeName string `json:"nodeName"`
|
||||
TLSBootstrapToken string `json:"tlsBootstrapToken"`
|
||||
Token string `json:"token"`
|
||||
|
||||
// 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 *kubeletconfigv1alpha1.KubeletConfiguration `json:"baseConfig,omitempty"`
|
||||
}
|
||||
|
||||
// HostPathMount contains elements describing volumes that are mounted from the
|
||||
// host
|
||||
type HostPathMount struct {
|
||||
Name string `json:"name"`
|
||||
HostPath string `json:"hostPath"`
|
||||
MountPath string `json:"mountPath"`
|
||||
}
|
||||
|
||||
// KubeProxy contains elements describing the proxy configuration
|
||||
type KubeProxy struct {
|
||||
Config *kubeproxyconfigv1alpha1.KubeProxyConfiguration `json:"config,omitempty"`
|
||||
}
|
377
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.conversion.go
generated
vendored
Normal file
377
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.conversion.go
generated
vendored
Normal file
@ -0,0 +1,377 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by conversion-gen. Do not edit it manually!
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
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"
|
||||
kubeletconfig_v1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||
kubeproxyconfig_v1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
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_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,
|
||||
Convert_v1alpha1_SelfHostedEtcd_To_kubeadm_SelfHostedEtcd,
|
||||
Convert_kubeadm_SelfHostedEtcd_To_v1alpha1_SelfHostedEtcd,
|
||||
Convert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery,
|
||||
Convert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery,
|
||||
)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_API_To_kubeadm_API(in *API, out *kubeadm.API, s conversion.Scope) error {
|
||||
out.AdvertiseAddress = in.AdvertiseAddress
|
||||
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.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_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
|
||||
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
|
||||
out.CAFile = in.CAFile
|
||||
out.CertFile = in.CertFile
|
||||
out.KeyFile = in.KeyFile
|
||||
out.DataDir = in.DataDir
|
||||
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
|
||||
out.Image = in.Image
|
||||
out.SelfHosted = (*kubeadm.SelfHostedEtcd)(unsafe.Pointer(in.SelfHosted))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_Etcd_To_kubeadm_Etcd is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_Etcd_To_kubeadm_Etcd(in *Etcd, out *kubeadm.Etcd, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_Etcd_To_kubeadm_Etcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_Etcd_To_v1alpha1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
|
||||
out.Endpoints = *(*[]string)(unsafe.Pointer(&in.Endpoints))
|
||||
out.CAFile = in.CAFile
|
||||
out.CertFile = in.CertFile
|
||||
out.KeyFile = in.KeyFile
|
||||
out.DataDir = in.DataDir
|
||||
out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs))
|
||||
out.Image = in.Image
|
||||
out.SelfHosted = (*SelfHostedEtcd)(unsafe.Pointer(in.SelfHosted))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_Etcd_To_v1alpha1_Etcd is an autogenerated conversion function.
|
||||
func Convert_kubeadm_Etcd_To_v1alpha1_Etcd(in *kubeadm.Etcd, out *Etcd, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_Etcd_To_v1alpha1_Etcd(in, out, s)
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
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 = (*kubeletconfig_v1alpha1.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 = (*kubeletconfig_v1alpha1.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
|
||||
out.CloudProvider = in.CloudProvider
|
||||
out.NodeName = in.NodeName
|
||||
out.AuthorizationModes = *(*[]string)(unsafe.Pointer(&in.AuthorizationModes))
|
||||
out.Token = in.Token
|
||||
out.TokenTTL = (*v1.Duration)(unsafe.Pointer(in.TokenTTL))
|
||||
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
|
||||
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in *MasterConfiguration, out *kubeadm.MasterConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error {
|
||||
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.CloudProvider = in.CloudProvider
|
||||
out.NodeName = in.NodeName
|
||||
out.AuthorizationModes = *(*[]string)(unsafe.Pointer(&in.AuthorizationModes))
|
||||
out.Token = in.Token
|
||||
out.TokenTTL = (*v1.Duration)(unsafe.Pointer(in.TokenTTL))
|
||||
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
|
||||
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration is an autogenerated conversion function.
|
||||
func Convert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in *kubeadm.MasterConfiguration, out *MasterConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
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.NodeName = in.NodeName
|
||||
out.TLSBootstrapToken = in.TLSBootstrapToken
|
||||
out.Token = in.Token
|
||||
out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes))
|
||||
out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification
|
||||
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *NodeConfiguration, out *kubeadm.NodeConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kubeadm.NodeConfiguration, out *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.NodeName = in.NodeName
|
||||
out.TLSBootstrapToken = in.TLSBootstrapToken
|
||||
out.Token = in.Token
|
||||
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_v1alpha1_NodeConfiguration is an autogenerated conversion function.
|
||||
func Convert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kubeadm.NodeConfiguration, out *NodeConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_SelfHostedEtcd_To_kubeadm_SelfHostedEtcd(in *SelfHostedEtcd, out *kubeadm.SelfHostedEtcd, s conversion.Scope) error {
|
||||
out.CertificatesDir = in.CertificatesDir
|
||||
out.ClusterServiceName = in.ClusterServiceName
|
||||
out.EtcdVersion = in.EtcdVersion
|
||||
out.OperatorVersion = in.OperatorVersion
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_SelfHostedEtcd_To_kubeadm_SelfHostedEtcd is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_SelfHostedEtcd_To_kubeadm_SelfHostedEtcd(in *SelfHostedEtcd, out *kubeadm.SelfHostedEtcd, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_SelfHostedEtcd_To_kubeadm_SelfHostedEtcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_SelfHostedEtcd_To_v1alpha1_SelfHostedEtcd(in *kubeadm.SelfHostedEtcd, out *SelfHostedEtcd, s conversion.Scope) error {
|
||||
out.CertificatesDir = in.CertificatesDir
|
||||
out.ClusterServiceName = in.ClusterServiceName
|
||||
out.EtcdVersion = in.EtcdVersion
|
||||
out.OperatorVersion = in.OperatorVersion
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_SelfHostedEtcd_To_v1alpha1_SelfHostedEtcd is an autogenerated conversion function.
|
||||
func Convert_kubeadm_SelfHostedEtcd_To_v1alpha1_SelfHostedEtcd(in *kubeadm.SelfHostedEtcd, out *SelfHostedEtcd, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_SelfHostedEtcd_To_v1alpha1_SelfHostedEtcd(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery(in *TokenDiscovery, out *kubeadm.TokenDiscovery, s conversion.Scope) error {
|
||||
out.ID = in.ID
|
||||
out.Secret = in.Secret
|
||||
out.Addresses = *(*[]string)(unsafe.Pointer(&in.Addresses))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery(in *TokenDiscovery, out *kubeadm.TokenDiscovery, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_TokenDiscovery_To_kubeadm_TokenDiscovery(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery(in *kubeadm.TokenDiscovery, out *TokenDiscovery, s conversion.Scope) error {
|
||||
out.ID = in.ID
|
||||
out.Secret = in.Secret
|
||||
out.Addresses = *(*[]string)(unsafe.Pointer(&in.Addresses))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery is an autogenerated conversion function.
|
||||
func Convert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery(in *kubeadm.TokenDiscovery, out *TokenDiscovery, s conversion.Scope) error {
|
||||
return autoConvert_kubeadm_TokenDiscovery_To_v1alpha1_TokenDiscovery(in, out, s)
|
||||
}
|
336
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.deepcopy.go
generated
vendored
Normal file
336
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.deepcopy.go
generated
vendored
Normal file
@ -0,0 +1,336 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
kubeletconfig_v1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||
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 *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
|
||||
}
|
||||
}
|
||||
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(kubeletconfig_v1alpha1.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.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)
|
||||
}
|
||||
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
|
||||
} else {
|
||||
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.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
|
||||
} else {
|
||||
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
|
||||
if in.Addresses != nil {
|
||||
in, out := &in.Addresses, &out.Addresses
|
||||
*out = make([]string, len(*in))
|
||||
copy(*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
|
||||
}
|
50
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.defaults.go
generated
vendored
Normal file
50
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.defaults.go
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by defaulter-gen. Do not edit it manually!
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
kubeletconfig_v1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||
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 {
|
||||
kubeletconfig_v1alpha1.SetDefaults_KubeletConfiguration(in.KubeletConfiguration.BaseConfig)
|
||||
}
|
||||
}
|
||||
|
||||
func SetObjectDefaults_NodeConfiguration(in *NodeConfiguration) {
|
||||
SetDefaults_NodeConfiguration(in)
|
||||
}
|
59
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/BUILD
generated
vendored
Normal file
59
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/BUILD
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["validation.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation",
|
||||
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/util:go_default_library",
|
||||
"//cmd/kubeadm/app/util/token:go_default_library",
|
||||
"//pkg/apis/core/validation:go_default_library",
|
||||
"//pkg/kubeapiserver/authorizer/modes: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/validation:go_default_library",
|
||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||
"//pkg/util/node: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",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["validation_test.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
|
||||
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
|
||||
"//pkg/util/pointer: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",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
403
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation.go
generated
vendored
Normal file
403
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation.go
generated
vendored
Normal file
@ -0,0 +1,403 @@
|
||||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token"
|
||||
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
||||
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||
"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"
|
||||
proxyvalidation "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/validation"
|
||||
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||
"k8s.io/kubernetes/pkg/util/node"
|
||||
)
|
||||
|
||||
// TODO: Break out the cloudprovider functionality out of core and only support the new flow
|
||||
// described in https://github.com/kubernetes/community/pull/128
|
||||
var cloudproviders = []string{
|
||||
"aws",
|
||||
"azure",
|
||||
"cloudstack",
|
||||
"gce",
|
||||
"openstack",
|
||||
"ovirt",
|
||||
"photon",
|
||||
"vsphere",
|
||||
}
|
||||
|
||||
// Describes the authorization modes that are enforced by kubeadm
|
||||
var requiredAuthzModes = []string{
|
||||
authzmodes.ModeRBAC,
|
||||
authzmodes.ModeNode,
|
||||
}
|
||||
|
||||
// ValidateMasterConfiguration validates master configuration and collects all encountered errors
|
||||
func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateCloudProvider(c.CloudProvider, field.NewPath("cloudprovider"))...)
|
||||
allErrs = append(allErrs, ValidateAuthorizationModes(c.AuthorizationModes, field.NewPath("authorization-modes"))...)
|
||||
allErrs = append(allErrs, ValidateNetworking(&c.Networking, field.NewPath("networking"))...)
|
||||
allErrs = append(allErrs, ValidateAPIServerCertSANs(c.APIServerCertSANs, field.NewPath("cert-altnames"))...)
|
||||
allErrs = append(allErrs, ValidateAbsolutePath(c.CertificatesDir, field.NewPath("certificates-dir"))...)
|
||||
allErrs = append(allErrs, ValidateNodeName(c.NodeName, field.NewPath("node-name"))...)
|
||||
allErrs = append(allErrs, ValidateToken(c.Token, field.NewPath("token"))...)
|
||||
allErrs = append(allErrs, ValidateFeatureGates(c.FeatureGates, field.NewPath("feature-gates"))...)
|
||||
allErrs = append(allErrs, ValidateAPIEndpoint(c, field.NewPath("api-endpoint"))...)
|
||||
allErrs = append(allErrs, ValidateProxy(c, field.NewPath("kube-proxy"))...)
|
||||
if features.Enabled(c.FeatureGates, features.DynamicKubeletConfig) {
|
||||
allErrs = append(allErrs, ValidateKubeletConfiguration(&c.KubeletConfiguration, field.NewPath("kubeletConfiguration"))...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateProxy validates proxy configuration and collects all encountered errors
|
||||
func ValidateProxy(c *kubeadm.MasterConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
// Convert to the internal version
|
||||
internalcfg := &kubeproxyconfig.KubeProxyConfiguration{}
|
||||
err := kubeproxyscheme.Scheme.Convert(c.KubeProxy.Config, internalcfg, nil)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, "KubeProxy.Config", err.Error()))
|
||||
return allErrs
|
||||
}
|
||||
return proxyvalidation.Validate(internalcfg)
|
||||
}
|
||||
|
||||
// ValidateNodeConfiguration validates node configuration and collects all encountered errors
|
||||
func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateDiscovery(c, field.NewPath("discovery"))...)
|
||||
|
||||
if !filepath.IsAbs(c.CACertPath) || !strings.HasSuffix(c.CACertPath, ".crt") {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("ca-cert-path"), c.CACertPath, "the ca certificate path must be an absolute path"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateAuthorizationModes validates authorization modes and collects all encountered errors
|
||||
func ValidateAuthorizationModes(authzModes []string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
found := map[string]bool{}
|
||||
for _, authzMode := range authzModes {
|
||||
if !authzmodes.IsValidAuthorizationMode(authzMode) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, authzMode, "invalid authorization mode"))
|
||||
}
|
||||
|
||||
if found[authzMode] {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, authzMode, "duplicate authorization mode"))
|
||||
continue
|
||||
}
|
||||
found[authzMode] = true
|
||||
}
|
||||
for _, requiredMode := range requiredAuthzModes {
|
||||
if !found[requiredMode] {
|
||||
allErrs = append(allErrs, field.Required(fldPath, fmt.Sprintf("authorization mode %s must be enabled", requiredMode)))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateDiscovery validates discovery related configuration and collects all encountered errors
|
||||
func ValidateDiscovery(c *kubeadm.NodeConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(c.DiscoveryToken) != 0 {
|
||||
allErrs = append(allErrs, ValidateToken(c.DiscoveryToken, fldPath)...)
|
||||
}
|
||||
if len(c.DiscoveryFile) != 0 {
|
||||
allErrs = append(allErrs, ValidateDiscoveryFile(c.DiscoveryFile, fldPath)...)
|
||||
}
|
||||
allErrs = append(allErrs, ValidateArgSelection(c, fldPath)...)
|
||||
allErrs = append(allErrs, ValidateToken(c.TLSBootstrapToken, fldPath)...)
|
||||
allErrs = append(allErrs, ValidateJoinDiscoveryTokenAPIServer(c, fldPath)...)
|
||||
|
||||
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 len(cfg.DiscoveryFile) != 0 && len(cfg.DiscoveryTokenCACertHashes) != 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, "", "DiscoveryTokenCACertHashes cannot be used with DiscoveryFile"))
|
||||
}
|
||||
|
||||
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"))
|
||||
}
|
||||
|
||||
// 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(c *kubeadm.NodeConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
for _, m := range c.DiscoveryTokenAPIServers {
|
||||
_, _, err := net.SplitHostPort(m)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, m, err.Error()))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateDiscoveryFile validates location of a discovery file
|
||||
func ValidateDiscoveryFile(discoveryFile string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
u, err := url.Parse(discoveryFile)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, discoveryFile, "not a valid HTTPS URL or a file on disk"))
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if u.Scheme == "" {
|
||||
// URIs with no scheme should be treated as files
|
||||
if _, err := os.Stat(discoveryFile); os.IsNotExist(err) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, discoveryFile, "not a valid HTTPS URL or a file on disk"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if u.Scheme != "https" {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, discoveryFile, "if an URL is used, the scheme must be https"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateToken validates token
|
||||
func ValidateToken(t string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
id, secret, err := tokenutil.ParseToken(t)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, t, err.Error()))
|
||||
}
|
||||
|
||||
if len(id) == 0 || len(secret) == 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, t, "token must be of form '[a-z0-9]{6}.[a-z0-9]{16}'"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateAPIServerCertSANs validates alternative names
|
||||
func ValidateAPIServerCertSANs(altnames []string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
for _, altname := range altnames {
|
||||
if len(validation.IsDNS1123Subdomain(altname)) != 0 && net.ParseIP(altname) == nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, altname, "altname is not a valid dns label or ip address"))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIPFromString validates ip address
|
||||
func ValidateIPFromString(ipaddr string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if net.ParseIP(ipaddr) == nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, ipaddr, "ip address 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{}
|
||||
_, svcSubnet, err := net.ParseCIDR(subnet)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, subnet, "couldn't parse subnet"))
|
||||
return allErrs
|
||||
}
|
||||
numAddresses := ipallocator.RangeSize(svcSubnet)
|
||||
if numAddresses < minAddrs {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, subnet, "subnet is too small"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateNetworking validates networking configuration
|
||||
func ValidateNetworking(c *kubeadm.Networking, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, apivalidation.ValidateDNS1123Subdomain(c.DNSDomain, field.NewPath("dns-domain"))...)
|
||||
allErrs = append(allErrs, ValidateIPNetFromString(c.ServiceSubnet, constants.MinimumAddressesInServiceSubnet, field.NewPath("service-subnet"))...)
|
||||
if len(c.PodSubnet) != 0 {
|
||||
allErrs = append(allErrs, ValidateIPNetFromString(c.PodSubnet, constants.MinimumAddressesInServiceSubnet, field.NewPath("pod-subnet"))...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateAbsolutePath validates whether provided path is absolute or not
|
||||
func ValidateAbsolutePath(path string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if !filepath.IsAbs(path) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, path, "path is not absolute"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateNodeName validates the name of a node
|
||||
func ValidateNodeName(nodename string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if node.GetHostname(nodename) != nodename {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, nodename, "nodename is not valid, must be lower case"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCloudProvider validates if cloud provider is supported
|
||||
func ValidateCloudProvider(provider string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(provider) == 0 {
|
||||
return allErrs
|
||||
}
|
||||
for _, supported := range cloudproviders {
|
||||
if provider == supported {
|
||||
return allErrs
|
||||
}
|
||||
}
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, provider, "cloudprovider not supported"))
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateMixedArguments validates passed arguments
|
||||
func ValidateMixedArguments(flag *pflag.FlagSet) error {
|
||||
// If --config isn't set, we have nothing to validate
|
||||
if !flag.Changed("config") {
|
||||
return nil
|
||||
}
|
||||
|
||||
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" {
|
||||
// "--skip-*" flags or other whitelisted flags can be set with --config
|
||||
return
|
||||
}
|
||||
mixedInvalidFlags = append(mixedInvalidFlags, f.Name)
|
||||
})
|
||||
|
||||
if len(mixedInvalidFlags) != 0 {
|
||||
return fmt.Errorf("can not mix '--config' with arguments %v", mixedInvalidFlags)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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)))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateAPIEndpoint validates API server's endpoint
|
||||
func ValidateAPIEndpoint(c *kubeadm.MasterConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
endpoint, err := kubeadmutil.GetMasterEndpoint(c)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, endpoint, "Invalid API Endpoint"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIgnorePreflightErrors validates duplicates in ignore-preflight-errors flag.
|
||||
func ValidateIgnorePreflightErrors(ignorePreflightErrors []string, skipPreflightChecks bool) (sets.String, error) {
|
||||
ignoreErrors := sets.NewString()
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
for _, item := range ignorePreflightErrors {
|
||||
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"))
|
||||
}
|
||||
|
||||
return ignoreErrors, allErrs.ToAggregate()
|
||||
}
|
||||
|
||||
// ValidateKubeletConfiguration validates kubelet configuration and collects all encountered errors
|
||||
func ValidateKubeletConfiguration(c *kubeadm.KubeletConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
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()))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
608
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go
generated
vendored
Normal file
608
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go
generated
vendored
Normal file
@ -0,0 +1,608 @@
|
||||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
||||
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
|
||||
)
|
||||
|
||||
func TestValidateTokenDiscovery(t *testing.T) {
|
||||
var tests = []struct {
|
||||
c *kubeadm.NodeConfiguration
|
||||
f *field.Path
|
||||
expected bool
|
||||
}{
|
||||
{&kubeadm.NodeConfiguration{Token: "772ef5.6b6baab1d4a0a171", DiscoveryTokenAPIServers: []string{"192.168.122.100:9898"}}, nil, true},
|
||||
{&kubeadm.NodeConfiguration{Token: ".6b6baab1d4a0a171", DiscoveryTokenAPIServers: []string{"192.168.122.100:9898"}}, nil, false},
|
||||
{&kubeadm.NodeConfiguration{Token: "772ef5.", DiscoveryTokenAPIServers: []string{"192.168.122.100:9898"}}, nil, false},
|
||||
{&kubeadm.NodeConfiguration{Token: "772ef5.6b6baab1d4a0a171", DiscoveryTokenAPIServers: []string{"2001:db8::100:9898"}}, nil, true},
|
||||
{&kubeadm.NodeConfiguration{Token: ".6b6baab1d4a0a171", DiscoveryTokenAPIServers: []string{"2001:db8::100:9898"}}, nil, false},
|
||||
{&kubeadm.NodeConfiguration{Token: "772ef5.", DiscoveryTokenAPIServers: []string{"2001:db8::100:9898"}}, nil, false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
err := ValidateToken(rt.c.Token, rt.f).ToAggregate()
|
||||
if (err == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateTokenDiscovery:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(err == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateAuthorizationModes(t *testing.T) {
|
||||
var tests = []struct {
|
||||
s []string
|
||||
f *field.Path
|
||||
expected bool
|
||||
}{
|
||||
{[]string{""}, nil, false},
|
||||
{[]string{"rBAC"}, nil, false}, // mode not supported
|
||||
{[]string{"rBAC", "Webhook"}, nil, false}, // mode not supported
|
||||
{[]string{"RBAC", "Webhook"}, nil, false}, // mode Node required
|
||||
{[]string{"Node", "RBAC", "Webhook", "Webhook"}, nil, false}, // no duplicates allowed
|
||||
{[]string{"not valid"}, nil, false}, // invalid mode
|
||||
{[]string{"Node", "RBAC"}, nil, true}, // supported
|
||||
{[]string{"RBAC", "Node"}, nil, true}, // supported
|
||||
{[]string{"Node", "RBAC", "Webhook", "ABAC"}, nil, true}, // supported
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateAuthorizationModes(rt.s, rt.f)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateAuthorizationModes:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateNodeName(t *testing.T) {
|
||||
var tests = []struct {
|
||||
s string
|
||||
f *field.Path
|
||||
expected bool
|
||||
}{
|
||||
{"", nil, false}, // ok if not provided
|
||||
{"1234", nil, true}, // supported
|
||||
{"valid-nodename", nil, true}, // supported
|
||||
{"INVALID-NODENAME", nil, false}, // Upper cases is invalid
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateNodeName(rt.s, rt.f)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateNodeName:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCloudProvider(t *testing.T) {
|
||||
var tests = []struct {
|
||||
s string
|
||||
f *field.Path
|
||||
expected bool
|
||||
}{
|
||||
{"", nil, true}, // if not provided, ok, it's optional
|
||||
{"1234", nil, false}, // not supported
|
||||
{"awws", nil, false}, // not supported
|
||||
{"aws", nil, true}, // supported
|
||||
{"gce", nil, true}, // supported
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateCloudProvider(rt.s, rt.f)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateCloudProvider:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateAPIServerCertSANs(t *testing.T) {
|
||||
var tests = []struct {
|
||||
sans []string
|
||||
expected bool
|
||||
}{
|
||||
{[]string{}, true}, // ok if not provided
|
||||
{[]string{"1,2,,3"}, false}, // not a DNS label or IP
|
||||
{[]string{"my-hostname", "???&?.garbage"}, false}, // not valid
|
||||
{[]string{"my-hostname", "my.subdomain", "1.2.3.4"}, true}, // supported
|
||||
{[]string{"my-hostname2", "my.other.subdomain", "10.0.0.10"}, true}, // supported
|
||||
{[]string{"my-hostname", "my.subdomain", "2001:db8::4"}, true}, // supported
|
||||
{[]string{"my-hostname2", "my.other.subdomain", "2001:db8::10"}, true}, // supported
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateAPIServerCertSANs(rt.sans, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateAPIServerCertSANs:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIPFromString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
ip string
|
||||
expected bool
|
||||
}{
|
||||
{"invalid missing address", "", false},
|
||||
{"invalid missing decimal points in IPv4 address", "1234", false},
|
||||
{"invalid incomplete IPv4 address", "1.2", false},
|
||||
{"invalid IPv4 CIDR provided instead of IPv4 address", "1.2.3.4/16", false},
|
||||
{"valid IPv4 address", "1.2.3.4", true},
|
||||
{"valid IPv6 address", "2001:db8::1", true},
|
||||
{"invalid IPv6 CIDR provided instead of IPv6 address", "2001:db8::1/64", false},
|
||||
{"invalid hex character in IPv6 address", "2001:xb8::", false},
|
||||
{"invalid use of colons in IPv6 address", "2001::db8::", false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateIPFromString(rt.ip, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%s test case failed:\n\texpected: %t\n\t actual: %t",
|
||||
rt.name,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIPNetFromString(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
subnet string
|
||||
minaddrs int64
|
||||
expected bool
|
||||
}{
|
||||
{"invalid missing CIDR", "", 0, false},
|
||||
{"invalid CIDR missing decimal points in IPv4 address and / mask", "1234", 0, false},
|
||||
{"invalid CIDR use of letters instead of numbers and / mask", "abc", 0, false},
|
||||
{"invalid IPv4 address provided instead of CIDR representation", "1.2.3.4", 0, false},
|
||||
{"invalid IPv6 address provided instead of CIDR representation", "2001:db8::1", 0, false},
|
||||
{"valid, but IPv4 CIDR too small. At least 10 addresses needed", "10.0.0.16/29", 10, false},
|
||||
{"valid, but IPv6 CIDR too small. At least 10 addresses needed", "2001:db8::/125", 10, false},
|
||||
{"valid IPv4 CIDR", "10.0.0.16/12", 10, true},
|
||||
{"valid IPv6 CIDR", "2001:db8::/98", 10, true},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateIPNetFromString(rt.subnet, rt.minaddrs, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%s test case failed :\n\texpected: %t\n\t actual: %t",
|
||||
rt.name,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateAPIEndpoint(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
s *kubeadm.MasterConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "Missing configuration",
|
||||
s: &kubeadm.MasterConfiguration{},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Valid IPv4 address and default port",
|
||||
s: &kubeadm.MasterConfiguration{
|
||||
API: kubeadm.API{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 6443,
|
||||
},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Valid IPv6 address and port",
|
||||
s: &kubeadm.MasterConfiguration{
|
||||
API: kubeadm.API{
|
||||
AdvertiseAddress: "2001:db7::1",
|
||||
BindPort: 3446,
|
||||
},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid IPv4 address",
|
||||
s: &kubeadm.MasterConfiguration{
|
||||
API: kubeadm.API{
|
||||
AdvertiseAddress: "1.2.34",
|
||||
BindPort: 6443,
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid IPv6 address",
|
||||
s: &kubeadm.MasterConfiguration{
|
||||
API: kubeadm.API{
|
||||
AdvertiseAddress: "2001:db7:1",
|
||||
BindPort: 3446,
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateAPIEndpoint(rt.s, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%s test case failed:\n\texpected: %t\n\t actual: %t",
|
||||
rt.name,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateMasterConfiguration(t *testing.T) {
|
||||
nodename := "valid-nodename"
|
||||
var tests = []struct {
|
||||
name string
|
||||
s *kubeadm.MasterConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{"invalid missing master configuration",
|
||||
&kubeadm.MasterConfiguration{}, false},
|
||||
{"invalid missing token with IPv4 service subnet",
|
||||
&kubeadm.MasterConfiguration{
|
||||
API: kubeadm.API{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 6443,
|
||||
},
|
||||
AuthorizationModes: []string{"Node", "RBAC"},
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "10.96.0.1/12",
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/cert/dir",
|
||||
NodeName: nodename,
|
||||
}, false},
|
||||
{"invalid missing token with IPv6 service subnet",
|
||||
&kubeadm.MasterConfiguration{
|
||||
API: kubeadm.API{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 6443,
|
||||
},
|
||||
AuthorizationModes: []string{"Node", "RBAC"},
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "2001:db8::1/98",
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/cert/dir",
|
||||
NodeName: nodename,
|
||||
}, false},
|
||||
{"invalid missing node name",
|
||||
&kubeadm.MasterConfiguration{
|
||||
API: kubeadm.API{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 6443,
|
||||
},
|
||||
AuthorizationModes: []string{"Node", "RBAC"},
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "10.96.0.1/12",
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
Token: "abcdef.0123456789abcdef",
|
||||
}, false},
|
||||
{"valid master configuration with IPv4 service subnet",
|
||||
&kubeadm.MasterConfiguration{
|
||||
API: kubeadm.API{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 6443,
|
||||
},
|
||||
KubeProxy: kubeadm.KubeProxy{
|
||||
Config: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{
|
||||
BindAddress: "192.168.59.103",
|
||||
HealthzBindAddress: "0.0.0.0:10256",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
ClusterCIDR: "192.168.59.0/24",
|
||||
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
IPTables: kubeproxyconfigv1alpha1.KubeProxyIPTablesConfiguration{
|
||||
MasqueradeAll: true,
|
||||
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||
},
|
||||
IPVS: kubeproxyconfigv1alpha1.KubeProxyIPVSConfiguration{
|
||||
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
Conntrack: kubeproxyconfigv1alpha1.KubeProxyConntrackConfiguration{
|
||||
Max: utilpointer.Int32Ptr(2),
|
||||
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||
Min: utilpointer.Int32Ptr(1),
|
||||
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
},
|
||||
},
|
||||
AuthorizationModes: []string{"Node", "RBAC"},
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "10.96.0.1/12",
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
Token: "abcdef.0123456789abcdef",
|
||||
NodeName: nodename,
|
||||
}, true},
|
||||
{"valid master configuration using IPv6 service subnet",
|
||||
&kubeadm.MasterConfiguration{
|
||||
API: kubeadm.API{
|
||||
AdvertiseAddress: "1:2:3::4",
|
||||
BindPort: 3446,
|
||||
},
|
||||
KubeProxy: kubeadm.KubeProxy{
|
||||
Config: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{
|
||||
BindAddress: "192.168.59.103",
|
||||
HealthzBindAddress: "0.0.0.0:10256",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
ClusterCIDR: "192.168.59.0/24",
|
||||
UDPIdleTimeout: metav1.Duration{Duration: 1 * time.Second},
|
||||
ConfigSyncPeriod: metav1.Duration{Duration: 1 * time.Second},
|
||||
IPTables: kubeproxyconfigv1alpha1.KubeProxyIPTablesConfiguration{
|
||||
MasqueradeAll: true,
|
||||
SyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 2 * time.Second},
|
||||
},
|
||||
IPVS: kubeproxyconfigv1alpha1.KubeProxyIPVSConfiguration{
|
||||
SyncPeriod: metav1.Duration{Duration: 10 * time.Second},
|
||||
MinSyncPeriod: metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
Conntrack: kubeproxyconfigv1alpha1.KubeProxyConntrackConfiguration{
|
||||
Max: utilpointer.Int32Ptr(2),
|
||||
MaxPerCore: utilpointer.Int32Ptr(1),
|
||||
Min: utilpointer.Int32Ptr(1),
|
||||
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
},
|
||||
},
|
||||
AuthorizationModes: []string{"Node", "RBAC"},
|
||||
Networking: kubeadm.Networking{
|
||||
ServiceSubnet: "2001:db8::1/98",
|
||||
DNSDomain: "cluster.local",
|
||||
},
|
||||
CertificatesDir: "/some/other/cert/dir",
|
||||
Token: "abcdef.0123456789abcdef",
|
||||
NodeName: nodename,
|
||||
}, true},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateMasterConfiguration(rt.s)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"%s test case failed:\n\texpected: %t\n\t actual: %t",
|
||||
rt.name,
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateNodeConfiguration(t *testing.T) {
|
||||
var tests = []struct {
|
||||
s *kubeadm.NodeConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{&kubeadm.NodeConfiguration{}, false},
|
||||
{&kubeadm.NodeConfiguration{
|
||||
DiscoveryFile: "foo",
|
||||
DiscoveryToken: "abcdef.1234567890123456@foobar",
|
||||
CACertPath: "/some/cert.crt",
|
||||
}, false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateNodeConfiguration(rt.s)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateNodeConfiguration:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateMixedArguments(t *testing.T) {
|
||||
var tests = []struct {
|
||||
args []string
|
||||
expected bool
|
||||
}{
|
||||
// Expected to succeed, --config is mixed with skip-* flags only or no other flags
|
||||
{[]string{"--foo=bar"}, true},
|
||||
{[]string{"--config=hello"}, true},
|
||||
{[]string{"--config=hello", "--skip-preflight-checks=true"}, true},
|
||||
{[]string{"--config=hello", "--skip-token-print=true"}, true},
|
||||
{[]string{"--config=hello", "--skip-preflight-checks", "--skip-token-print"}, true},
|
||||
// Expected to fail, --config is mixed with the --foo flag
|
||||
{[]string{"--config=hello", "--skip-preflight-checks", "--foo=bar"}, false},
|
||||
{[]string{"--config=hello", "--foo=bar"}, false},
|
||||
}
|
||||
|
||||
var cfgPath string
|
||||
for _, rt := range tests {
|
||||
f := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
if f.Parsed() {
|
||||
t.Error("f.Parse() = true before Parse")
|
||||
}
|
||||
f.String("foo", "", "flag bound to config object")
|
||||
f.Bool("skip-preflight-checks", false, "flag not bound to config object")
|
||||
f.Bool("skip-token-print", false, "flag not bound to config object")
|
||||
f.StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file")
|
||||
if err := f.Parse(rt.args); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
actual := ValidateMixedArguments(f)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed ValidateMixedArguments:\n\texpected: %t\n\t actual: %t testdata: %v",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
rt.args,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateFeatureGates(t *testing.T) {
|
||||
type featureFlag map[string]bool
|
||||
var tests = []struct {
|
||||
featureGates featureFlag
|
||||
expected bool
|
||||
}{
|
||||
{featureFlag{"SelfHosting": true}, true},
|
||||
{featureFlag{"SelfHosting": false}, true},
|
||||
{featureFlag{"StoreCertsInSecrets": true}, true},
|
||||
{featureFlag{"StoreCertsInSecrets": false}, true},
|
||||
{featureFlag{"Foo": true}, false},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateFeatureGates(rt.featureGates, nil)
|
||||
if (len(actual) == 0) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed featureGates:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(len(actual) == 0),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIgnorePreflightErrors(t *testing.T) {
|
||||
var tests = []struct {
|
||||
ignorePreflightErrors []string
|
||||
skipPreflightChecks bool
|
||||
expectedLen int
|
||||
expectedError bool
|
||||
}{
|
||||
{[]string{}, false, 0, false}, // empty list, no old skip-preflight-checks
|
||||
{[]string{}, true, 1, false}, // empty list, old skip-preflight-checks
|
||||
{[]string{"check1", "check2"}, false, 2, false}, // non-duplicate
|
||||
{[]string{"check1", "check2"}, true, 3, true}, // non-duplicate, but skip-preflight-checks
|
||||
{[]string{"check1", "check2", "check1"}, false, 2, false}, // duplicates
|
||||
{[]string{"check1", "check2", "all"}, false, 3, true}, // non-duplicate, but 'all' present together wth individual checks
|
||||
{[]string{"all"}, false, 1, false}, // skip all checks by using new flag
|
||||
{[]string{"all"}, true, 1, false}, // skip all checks by using both old and new flags at the same time
|
||||
}
|
||||
for _, rt := range tests {
|
||||
result, err := ValidateIgnorePreflightErrors(rt.ignorePreflightErrors, rt.skipPreflightChecks)
|
||||
switch {
|
||||
case err != nil && !rt.expectedError:
|
||||
t.Errorf("ValidateIgnorePreflightErrors: unexpected error for input (%s, %v), error: %v", rt.ignorePreflightErrors, rt.skipPreflightChecks, err)
|
||||
case err == nil && rt.expectedError:
|
||||
t.Errorf("ValidateIgnorePreflightErrors: expected error for input (%s, %v) but got: %v", rt.ignorePreflightErrors, rt.skipPreflightChecks, result)
|
||||
case result.Len() != rt.expectedLen:
|
||||
t.Errorf("ValidateIgnorePreflightErrors: expected Len = %d for input (%s, %v) but got: %v, %v", rt.expectedLen, rt.ignorePreflightErrors, rt.skipPreflightChecks, result.Len(), result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateKubeletConfiguration(t *testing.T) {
|
||||
successCase := &kubeadm.KubeletConfiguration{
|
||||
BaseConfig: &kubeletconfigv1alpha1.KubeletConfiguration{
|
||||
CgroupsPerQOS: utilpointer.BoolPtr(true),
|
||||
EnforceNodeAllocatable: []string{"pods", "system-reserved", "kube-reserved"},
|
||||
SystemCgroups: "",
|
||||
CgroupRoot: "",
|
||||
CAdvisorPort: utilpointer.Int32Ptr(0),
|
||||
EventBurst: 10,
|
||||
EventRecordQPS: utilpointer.Int32Ptr(5),
|
||||
HealthzPort: utilpointer.Int32Ptr(10248),
|
||||
ImageGCHighThresholdPercent: utilpointer.Int32Ptr(85),
|
||||
ImageGCLowThresholdPercent: utilpointer.Int32Ptr(80),
|
||||
IPTablesDropBit: utilpointer.Int32Ptr(15),
|
||||
IPTablesMasqueradeBit: utilpointer.Int32Ptr(14),
|
||||
KubeAPIBurst: 10,
|
||||
KubeAPIQPS: utilpointer.Int32Ptr(5),
|
||||
MaxOpenFiles: 1000000,
|
||||
MaxPods: 110,
|
||||
OOMScoreAdj: utilpointer.Int32Ptr(-999),
|
||||
PodsPerCore: 100,
|
||||
Port: 65535,
|
||||
ReadOnlyPort: utilpointer.Int32Ptr(0),
|
||||
RegistryBurst: 10,
|
||||
RegistryPullQPS: utilpointer.Int32Ptr(5),
|
||||
},
|
||||
}
|
||||
if allErrors := ValidateKubeletConfiguration(successCase, nil); len(allErrors) != 0 {
|
||||
t.Errorf("failed ValidateKubeletConfiguration: expect no errors but got %v", allErrors)
|
||||
}
|
||||
|
||||
errorCase := &kubeadm.KubeletConfiguration{
|
||||
BaseConfig: &kubeletconfigv1alpha1.KubeletConfiguration{
|
||||
CgroupsPerQOS: utilpointer.BoolPtr(false),
|
||||
EnforceNodeAllocatable: []string{"pods", "system-reserved", "kube-reserved", "illegal-key"},
|
||||
SystemCgroups: "/",
|
||||
CgroupRoot: "",
|
||||
CAdvisorPort: utilpointer.Int32Ptr(-10),
|
||||
EventBurst: -10,
|
||||
EventRecordQPS: utilpointer.Int32Ptr(-10),
|
||||
HealthzPort: utilpointer.Int32Ptr(-10),
|
||||
ImageGCHighThresholdPercent: utilpointer.Int32Ptr(101),
|
||||
ImageGCLowThresholdPercent: utilpointer.Int32Ptr(101),
|
||||
IPTablesDropBit: utilpointer.Int32Ptr(-10),
|
||||
IPTablesMasqueradeBit: utilpointer.Int32Ptr(-10),
|
||||
KubeAPIBurst: -10,
|
||||
KubeAPIQPS: utilpointer.Int32Ptr(-10),
|
||||
MaxOpenFiles: -10,
|
||||
MaxPods: -10,
|
||||
OOMScoreAdj: utilpointer.Int32Ptr(-1001),
|
||||
PodsPerCore: -10,
|
||||
Port: 0,
|
||||
ReadOnlyPort: utilpointer.Int32Ptr(-10),
|
||||
RegistryBurst: -10,
|
||||
RegistryPullQPS: utilpointer.Int32Ptr(-10),
|
||||
},
|
||||
}
|
||||
if allErrors := ValidateKubeletConfiguration(errorCase, nil); len(allErrors) == 0 {
|
||||
t.Errorf("failed ValidateKubeletConfiguration: expect errors but got no error")
|
||||
}
|
||||
}
|
43
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/well_known_labels.go
generated
vendored
Normal file
43
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/well_known_labels.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
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 kubeadm
|
||||
|
||||
// Role labels are applied to Nodes to mark their purpose. In particular, we
|
||||
// usually want to distinguish the master, so that we can isolate privileged
|
||||
// pods and operations.
|
||||
//
|
||||
// Originally we relied on not registering the master, on the fact that the
|
||||
// master was Unschedulable, and on static manifests for master components.
|
||||
// But we now do register masters in many environments, are generally moving
|
||||
// away from static manifests (for better manageability), and working towards
|
||||
// deprecating the unschedulable field (replacing it with taints & tolerations
|
||||
// instead).
|
||||
//
|
||||
// Even with tainting, a label remains the easiest way of making a positive
|
||||
// selection, so that pods can schedule only to master nodes for example, and
|
||||
// thus installations will likely define a label for their master nodes.
|
||||
//
|
||||
// So that we can recognize master nodes in consequent places though (such as
|
||||
// kubectl get nodes), we encourage installations to use the well-known labels.
|
||||
// We define NodeLabelRole, which is the preferred form, but we will also recognize
|
||||
// other forms that are known to be in widespread use (NodeLabelKubeadmAlphaRole).
|
||||
|
||||
const (
|
||||
// NodeLabelKubeadmAlphaRole is a label that kubeadm applies to a Node as a hint that it has a particular purpose.
|
||||
// Use of NodeLabelRole is preferred.
|
||||
NodeLabelKubeadmAlphaRole = "kubeadm.alpha.kubernetes.io/role"
|
||||
)
|
336
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go
generated
vendored
Normal file
336
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go
generated
vendored
Normal file
@ -0,0 +1,336 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
|
||||
package kubeadm
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
kubeletconfig_v1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||
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 *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
|
||||
}
|
||||
}
|
||||
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(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(kubeletconfig_v1alpha1.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.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)
|
||||
}
|
||||
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
|
||||
} else {
|
||||
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.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
|
||||
} else {
|
||||
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
|
||||
if in.Addresses != nil {
|
||||
in, out := &in.Addresses, &out.Addresses
|
||||
*out = make([]string, len(*in))
|
||||
copy(*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
|
||||
}
|
114
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/BUILD
generated
vendored
Normal file
114
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/BUILD
generated
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cmd.go",
|
||||
"completion.go",
|
||||
"config.go",
|
||||
"init.go",
|
||||
"join.go",
|
||||
"reset.go",
|
||||
"token.go",
|
||||
"version.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/install:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/phases:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/upgrade:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd/util: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/certs/pkiutil: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/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/config:go_default_library",
|
||||
"//cmd/kubeadm/app/util/dryrun:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/util/pubkeypin:go_default_library",
|
||||
"//cmd/kubeadm/app/util/token:go_default_library",
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/bootstrap/api:go_default_library",
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
"//pkg/kubectl/util/i18n:go_default_library",
|
||||
"//pkg/printers:go_default_library",
|
||||
"//pkg/util/initsystem:go_default_library",
|
||||
"//pkg/util/node:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
"//vendor/github.com/ghodss/yaml: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/api/core/v1: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/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/version: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/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/cert:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"reset_test.go",
|
||||
"token_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//cmd/kubeadm/app/cmd/phases:all-srcs",
|
||||
"//cmd/kubeadm/app/cmd/upgrade:all-srcs",
|
||||
"//cmd/kubeadm/app/cmd/util:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
94
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/cmd.go
generated
vendored
Normal file
94
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/cmd.go
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/apiserver/pkg/util/flag"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade"
|
||||
|
||||
// Register the kubeadm configuration types because CLI flag generation
|
||||
// depends on the generated defaults.
|
||||
_ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install"
|
||||
)
|
||||
|
||||
// NewKubeadmCommand return cobra.Command to run kubeadm command
|
||||
func NewKubeadmCommand(_ io.Reader, out, err io.Writer) *cobra.Command {
|
||||
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 │
|
||||
│ │
|
||||
│ But please, try it out and 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).
|
||||
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ On the first machine: │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ master# kubeadm init │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ On the second machine: │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ node# kubeadm join <arguments-returned-from-init> │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
|
||||
You can then repeat the second step on as many other machines as you like.
|
||||
|
||||
`),
|
||||
}
|
||||
|
||||
cmds.ResetFlags()
|
||||
cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc)
|
||||
|
||||
cmds.AddCommand(NewCmdCompletion(out, ""))
|
||||
cmds.AddCommand(NewCmdConfig(out))
|
||||
cmds.AddCommand(NewCmdInit(out))
|
||||
cmds.AddCommand(NewCmdJoin(out))
|
||||
cmds.AddCommand(NewCmdReset(out))
|
||||
cmds.AddCommand(NewCmdVersion(out))
|
||||
cmds.AddCommand(NewCmdToken(out, err))
|
||||
cmds.AddCommand(upgrade.NewCmdUpgrade(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)
|
||||
|
||||
return cmds
|
||||
}
|
295
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/completion.go
generated
vendored
Normal file
295
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/completion.go
generated
vendored
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
|
||||
)
|
||||
|
||||
const defaultBoilerPlate = `
|
||||
# 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.
|
||||
`
|
||||
|
||||
var (
|
||||
completionLong = dedent.Dedent(`
|
||||
Output shell completion code for the specified shell (bash or zsh).
|
||||
The shell code must be evalutated to provide interactive
|
||||
completion of kubeadm commands. This can be done by sourcing it from
|
||||
the .bash_profile.
|
||||
|
||||
Note: this requires the bash-completion framework, which is not installed
|
||||
by default on Mac. This can be installed by using homebrew:
|
||||
|
||||
$ brew install bash-completion
|
||||
|
||||
Once installed, bash_completion must be evaluated. This can be done by adding the
|
||||
following line to the .bash_profile
|
||||
|
||||
$ source $(brew --prefix)/etc/bash_completion
|
||||
|
||||
Note for zsh users: [1] zsh completions are only supported in versions of zsh >= 5.2`)
|
||||
|
||||
completionExample = dedent.Dedent(`
|
||||
# Install bash completion on a Mac using homebrew
|
||||
brew install bash-completion
|
||||
printf "\n# Bash completion support\nsource $(brew --prefix)/etc/bash_completion\n" >> $HOME/.bash_profile
|
||||
source $HOME/.bash_profile
|
||||
|
||||
# Load the kubeadm completion code for bash into the current shell
|
||||
source <(kubeadm completion bash)
|
||||
|
||||
# Write bash completion code to a file and source if from .bash_profile
|
||||
kubeadm completion bash > ~/.kube/kubeadm_completion.bash.inc
|
||||
printf "\n# Kubeadm shell completion\nsource '$HOME/.kube/kubeadm_completion.bash.inc'\n" >> $HOME/.bash_profile
|
||||
source $HOME/.bash_profile
|
||||
|
||||
# Load the kubeadm completion code for zsh[1] into the current shell
|
||||
source <(kubeadm completion zsh)`)
|
||||
)
|
||||
|
||||
var (
|
||||
completionShells = map[string]func(out io.Writer, cmd *cobra.Command) error{
|
||||
"bash": runCompletionBash,
|
||||
"zsh": runCompletionZsh,
|
||||
}
|
||||
)
|
||||
|
||||
// NewCmdCompletion return command for executing "kubeadm completion" command
|
||||
func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command {
|
||||
shells := []string{}
|
||||
for s := range completionShells {
|
||||
shells = append(shells, s)
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "completion SHELL",
|
||||
Short: i18n.T("Output shell completion code for the specified shell (bash or zsh)."),
|
||||
Long: completionLong,
|
||||
Example: completionExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunCompletion(out, boilerPlate, cmd, args)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
ValidArgs: shells,
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
if len(args) > 1 {
|
||||
return fmt.Errorf("too many arguments. expected only the shell type")
|
||||
}
|
||||
run, found := completionShells[args[0]]
|
||||
if !found {
|
||||
return fmt.Errorf("unsupported shell type %q", args[0])
|
||||
}
|
||||
|
||||
if len(boilerPlate) == 0 {
|
||||
boilerPlate = defaultBoilerPlate
|
||||
}
|
||||
if _, err := out.Write([]byte(boilerPlate)); err != nil {
|
||||
return err
|
||||
}
|
||||
return run(out, cmd.Parent())
|
||||
}
|
||||
|
||||
func runCompletionBash(out io.Writer, kubeadm *cobra.Command) error {
|
||||
return kubeadm.GenBashCompletion(out)
|
||||
}
|
||||
|
||||
func runCompletionZsh(out io.Writer, kubeadm *cobra.Command) error {
|
||||
zshInitialization := `
|
||||
__kubeadm_bash_source() {
|
||||
alias shopt=':'
|
||||
alias _expand=_bash_expand
|
||||
alias _complete=_bash_comp
|
||||
emulate -L sh
|
||||
setopt kshglob noshglob braceexpand
|
||||
|
||||
source "$@"
|
||||
}
|
||||
|
||||
__kubeadm_type() {
|
||||
# -t is not supported by zsh
|
||||
if [ "$1" == "-t" ]; then
|
||||
shift
|
||||
|
||||
# fake Bash 4 to disable "complete -o nospace". Instead
|
||||
# "compopt +-o nospace" is used in the code to toggle trailing
|
||||
# spaces. We don't support that, but leave trailing spaces on
|
||||
# all the time
|
||||
if [ "$1" = "__kubeadm_compopt" ]; then
|
||||
echo builtin
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
type "$@"
|
||||
}
|
||||
|
||||
__kubeadm_compgen() {
|
||||
local completions w
|
||||
completions=( $(compgen "$@") ) || return $?
|
||||
|
||||
# filter by given word as prefix
|
||||
while [[ "$1" = -* && "$1" != -- ]]; do
|
||||
shift
|
||||
shift
|
||||
done
|
||||
if [[ "$1" == -- ]]; then
|
||||
shift
|
||||
fi
|
||||
for w in "${completions[@]}"; do
|
||||
if [[ "${w}" = "$1"* ]]; then
|
||||
echo "${w}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
__kubeadm_compopt() {
|
||||
true # don't do anything. Not supported by bashcompinit in zsh
|
||||
}
|
||||
|
||||
__kubeadm_ltrim_colon_completions()
|
||||
{
|
||||
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
|
||||
# Remove colon-word prefix from COMPREPLY items
|
||||
local colon_word=${1%${1##*:}}
|
||||
local i=${#COMPREPLY[*]}
|
||||
while [[ $((--i)) -ge 0 ]]; do
|
||||
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
__kubeadm_get_comp_words_by_ref() {
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[${COMP_CWORD}-1]}"
|
||||
words=("${COMP_WORDS[@]}")
|
||||
cword=("${COMP_CWORD[@]}")
|
||||
}
|
||||
|
||||
__kubeadm_filedir() {
|
||||
local RET OLD_IFS w qw
|
||||
|
||||
__debug "_filedir $@ cur=$cur"
|
||||
if [[ "$1" = \~* ]]; then
|
||||
# somehow does not work. Maybe, zsh does not call this at all
|
||||
eval echo "$1"
|
||||
return 0
|
||||
fi
|
||||
|
||||
OLD_IFS="$IFS"
|
||||
IFS=$'\n'
|
||||
if [ "$1" = "-d" ]; then
|
||||
shift
|
||||
RET=( $(compgen -d) )
|
||||
else
|
||||
RET=( $(compgen -f) )
|
||||
fi
|
||||
IFS="$OLD_IFS"
|
||||
|
||||
IFS="," __debug "RET=${RET[@]} len=${#RET[@]}"
|
||||
|
||||
for w in ${RET[@]}; do
|
||||
if [[ ! "${w}" = "${cur}"* ]]; then
|
||||
continue
|
||||
fi
|
||||
if eval "[[ \"\${w}\" = *.$1 || -d \"\${w}\" ]]"; then
|
||||
qw="$(__kubeadm_quote "${w}")"
|
||||
if [ -d "${w}" ]; then
|
||||
COMPREPLY+=("${qw}/")
|
||||
else
|
||||
COMPREPLY+=("${qw}")
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
__kubeadm_quote() {
|
||||
if [[ $1 == \'* || $1 == \"* ]]; then
|
||||
# Leave out first character
|
||||
printf %q "${1:1}"
|
||||
else
|
||||
printf %q "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
autoload -U +X bashcompinit && bashcompinit
|
||||
|
||||
# use word boundary patterns for BSD or GNU sed
|
||||
LWORD='[[:<:]]'
|
||||
RWORD='[[:>:]]'
|
||||
if sed --help 2>&1 | grep -q GNU; then
|
||||
LWORD='\<'
|
||||
RWORD='\>'
|
||||
fi
|
||||
|
||||
__kubeadm_convert_bash_to_zsh() {
|
||||
sed \
|
||||
-e 's/declare -F/whence -w/' \
|
||||
-e 's/local \([a-zA-Z0-9_]*\)=/local \1; \1=/' \
|
||||
-e 's/flags+=("\(--.*\)=")/flags+=("\1"); two_word_flags+=("\1")/' \
|
||||
-e 's/must_have_one_flag+=("\(--.*\)=")/must_have_one_flag+=("\1")/' \
|
||||
-e "s/${LWORD}_filedir${RWORD}/__kubeadm_filedir/g" \
|
||||
-e "s/${LWORD}_get_comp_words_by_ref${RWORD}/__kubeadm_get_comp_words_by_ref/g" \
|
||||
-e "s/${LWORD}__ltrim_colon_completions${RWORD}/__kubeadm_ltrim_colon_completions/g" \
|
||||
-e "s/${LWORD}compgen${RWORD}/__kubeadm_compgen/g" \
|
||||
-e "s/${LWORD}compopt${RWORD}/__kubeadm_compopt/g" \
|
||||
-e "s/${LWORD}declare${RWORD}/builtin declare/g" \
|
||||
-e "s/\\\$(type${RWORD}/\$(__kubeadm_type/g" \
|
||||
<<'BASH_COMPLETION_EOF'
|
||||
`
|
||||
out.Write([]byte(zshInitialization))
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
kubeadm.GenBashCompletion(buf)
|
||||
out.Write(buf.Bytes())
|
||||
|
||||
zshTail := `
|
||||
BASH_COMPLETION_EOF
|
||||
}
|
||||
|
||||
__kubeadm_bash_source <(__kubeadm_convert_bash_to_zsh)
|
||||
`
|
||||
out.Write([]byte(zshTail))
|
||||
return nil
|
||||
}
|
194
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/config.go
generated
vendored
Normal file
194
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/config.go
generated
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"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/api/legacyscheme"
|
||||
)
|
||||
|
||||
// NewCmdConfig returns cobra.Command for "kubeadm config" command
|
||||
func NewCmdConfig(out io.Writer) *cobra.Command {
|
||||
|
||||
var kubeConfigFile string
|
||||
cmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Manage configuration for a kubeadm cluster persisted in a ConfigMap in the cluster.",
|
||||
Long: fmt.Sprintf(dedent.Dedent(`
|
||||
There is a ConfigMap in the %s namespace called %q that kubeadm uses to store internal configuration about the
|
||||
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),
|
||||
// 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.
|
||||
// We want to return an error code in these cases so that the
|
||||
// user knows that their command was invalid.
|
||||
RunE: cmdutil.SubCmdRunE("config"),
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVar(&kubeConfigFile, "kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster.")
|
||||
|
||||
cmd.AddCommand(NewCmdConfigUpload(out, &kubeConfigFile))
|
||||
cmd.AddCommand(NewCmdConfigView(out, &kubeConfigFile))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigUpload returs cobra.Command for "kubeadm config upload" command
|
||||
func NewCmdConfigUpload(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "upload",
|
||||
Short: "Upload configuration about the current state, so that 'kubeadm upgrade' can later know how to configure the upgraded cluster.",
|
||||
RunE: cmdutil.SubCmdRunE("upload"),
|
||||
}
|
||||
|
||||
cmd.AddCommand(NewCmdConfigUploadFromFile(out, kubeConfigFile))
|
||||
cmd.AddCommand(NewCmdConfigUploadFromFlags(out, kubeConfigFile))
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigView returs cobra.Command for "kubeadm config view" command
|
||||
func NewCmdConfigView(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "view",
|
||||
Short: "View the kubeadm configuration stored inside the cluster.",
|
||||
Long: fmt.Sprintf(dedent.Dedent(`
|
||||
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),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = RunConfigView(out, client)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdConfigUploadFromFile verifies given kubernetes config file and returs cobra.Command for
|
||||
// "kubeadm config upload from-file" command
|
||||
func NewCmdConfigUploadFromFile(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
var cfgPath string
|
||||
cmd := &cobra.Command{
|
||||
Use: "from-file",
|
||||
Short: "Upload a configuration file to the in-cluster ConfigMap for kubeadm configuration.",
|
||||
Long: fmt.Sprintf(dedent.Dedent(`
|
||||
Using this command, you can upload configuration to the ConfigMap in the cluster using the same config file you gave to 'kubeadm init'.
|
||||
If you initialized your cluster using a v1.7.x or lower kubeadm client and used the --config option, you need to run this command with the
|
||||
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),
|
||||
Run: func(cmd *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)
|
||||
|
||||
// The default configuration is empty; everything should come from the file on disk
|
||||
defaultcfg := &kubeadmapiext.MasterConfiguration{}
|
||||
// Upload the configuration using the file; don't care about the defaultcfg really
|
||||
err = uploadConfiguration(client, cfgPath, defaultcfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVar(&cfgPath, "config", "", "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental.")
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewCmdConfigUploadFromFlags returs cobra.Command for "kubeadm config upload from-flags" command
|
||||
func NewCmdConfigUploadFromFlags(out io.Writer, kubeConfigFile *string) *cobra.Command {
|
||||
cfg := &kubeadmapiext.MasterConfiguration{}
|
||||
legacyscheme.Scheme.Default(cfg)
|
||||
|
||||
var featureGatesString string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "from-flags",
|
||||
Short: "Create the in-cluster configuration file for the first time from using flags.",
|
||||
Long: fmt.Sprintf(dedent.Dedent(`
|
||||
Using this command, you can upload configuration to the ConfigMap in the cluster using the same flags you gave to 'kubeadm init'.
|
||||
If you initialized your cluster using a v1.7.x or lower kubeadm client and set certain flags, you need to run this command with the
|
||||
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),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
|
||||
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
|
||||
err = uploadConfiguration(client, "", cfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
AddInitConfigFlags(cmd.PersistentFlags(), cfg, &featureGatesString)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunConfigView gets the configuration persisted in the cluster
|
||||
func RunConfigView(out io.Writer, client clientset.Interface) error {
|
||||
|
||||
cfgConfigMap, err := client.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(constants.MasterConfigurationConfigMap, 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])
|
||||
return nil
|
||||
}
|
||||
|
||||
// uploadConfiguration handles the uploading of the configuration internally
|
||||
func uploadConfiguration(client clientset.Interface, cfgPath string, defaultcfg *kubeadmapiext.MasterConfiguration) error {
|
||||
|
||||
// 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
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, defaultcfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Then just call the uploadconfig phase to do the rest of the work
|
||||
return uploadconfig.UploadConfiguration(internalcfg, client)
|
||||
}
|
558
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go
generated
vendored
Normal file
558
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go
generated
vendored
Normal file
@ -0,0 +1,558 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
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"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
utilsexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
var (
|
||||
initDoneTempl = template.Must(template.New("init").Parse(dedent.Dedent(`
|
||||
Your Kubernetes master has initialized successfully!
|
||||
|
||||
To start using your cluster, 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
|
||||
|
||||
You should now deploy a pod network to the cluster.
|
||||
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
|
||||
https://kubernetes.io/docs/concepts/cluster-administration/addons/
|
||||
|
||||
You can now join any number of machines by running the following on each node
|
||||
as root:
|
||||
|
||||
kubeadm join --token {{.Token}} {{.MasterHostPort}} --discovery-token-ca-cert-hash {{.CAPubKeyPin}}
|
||||
|
||||
`)))
|
||||
|
||||
kubeletFailTempl = template.Must(template.New("init").Parse(dedent.Dedent(`
|
||||
Unfortunately, an error has occurred:
|
||||
{{ .Error }}
|
||||
|
||||
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)
|
||||
- There is no internet connection, so the kubelet cannot pull the following control plane images:
|
||||
- {{ .APIServerImage }}
|
||||
- {{ .ControllerManagerImage }}
|
||||
- {{ .SchedulerImage }}
|
||||
|
||||
If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
|
||||
- 'systemctl status kubelet'
|
||||
- 'journalctl -xeu kubelet'
|
||||
`)))
|
||||
)
|
||||
|
||||
// NewCmdInit returns "kubeadm init" command.
|
||||
func NewCmdInit(out io.Writer) *cobra.Command {
|
||||
cfg := &kubeadmapiext.MasterConfiguration{}
|
||||
legacyscheme.Scheme.Default(cfg)
|
||||
|
||||
var cfgPath string
|
||||
var skipPreFlight bool
|
||||
var skipTokenPrint bool
|
||||
var dryRun bool
|
||||
var featureGatesString string
|
||||
var criSocket string
|
||||
var ignorePreflightErrors []string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Run this command in order to set up the Kubernetes master.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
|
||||
legacyscheme.Scheme.Default(cfg)
|
||||
internalcfg := &kubeadmapi.MasterConfiguration{}
|
||||
legacyscheme.Scheme.Convert(cfg, internalcfg, nil)
|
||||
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
i, err := NewInit(cfgPath, internalcfg, ignorePreflightErrorsSet, skipTokenPrint, dryRun, criSocket)
|
||||
kubeadmutil.CheckErr(err)
|
||||
kubeadmutil.CheckErr(i.Validate(cmd))
|
||||
kubeadmutil.CheckErr(i.Run(out))
|
||||
},
|
||||
}
|
||||
|
||||
AddInitConfigFlags(cmd.PersistentFlags(), cfg, &featureGatesString)
|
||||
AddInitOtherFlags(cmd.PersistentFlags(), &cfgPath, &skipPreFlight, &skipTokenPrint, &dryRun, &criSocket, &ignorePreflightErrors)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// AddInitConfigFlags adds init flags bound to the config to the specified flagset
|
||||
func AddInitConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiext.MasterConfiguration, featureGatesString *string) {
|
||||
flagSet.StringVar(
|
||||
&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.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,
|
||||
"Port for the API Server to bind to.",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet,
|
||||
"Use alternative range of IP address for service VIPs.",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.Networking.PodSubnet, "pod-network-cidr", 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,
|
||||
`Use alternative domain for services, e.g. "myorg.internal".`,
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion,
|
||||
`Choose a specific Kubernetes version for the control plane.`,
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir,
|
||||
`The path where to save and store the certificates.`,
|
||||
)
|
||||
flagSet.StringSliceVar(
|
||||
&cfg.APIServerCertSANs, "apiserver-cert-extra-sans", cfg.APIServerCertSANs,
|
||||
`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.NodeName, "node-name", cfg.NodeName,
|
||||
`Specify the node name.`,
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.Token, "token", cfg.Token,
|
||||
"The token to use for establishing bidirectional trust between nodes and masters.",
|
||||
)
|
||||
flagSet.DurationVar(
|
||||
&cfg.TokenTTL.Duration, "token-ttl", cfg.TokenTTL.Duration,
|
||||
"The duration before the bootstrap token is automatically deleted. If set to '0', the token will never expire.",
|
||||
)
|
||||
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"))
|
||||
}
|
||||
|
||||
// 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, criSocket *string, ignorePreflightErrors *[]string) {
|
||||
flagSet.StringVar(
|
||||
cfgPath, "config", *cfgPath,
|
||||
"Path to kubeadm config file. WARNING: Usage of a configuration file is experimental.",
|
||||
)
|
||||
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.",
|
||||
)
|
||||
// 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,
|
||||
"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,
|
||||
"Don't apply any changes; just output what would be done.",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
criSocket, "cri-socket", "/var/run/dockershim.sock",
|
||||
`Specify the CRI socket to connect to.`,
|
||||
)
|
||||
}
|
||||
|
||||
// NewInit validates given arguments and instantiates Init struct with provided information.
|
||||
func NewInit(cfgPath string, cfg *kubeadmapi.MasterConfiguration, ignorePreflightErrors sets.String, skipTokenPrint, dryRun bool, criSocket string) (*Init, error) {
|
||||
|
||||
if cfgPath != "" {
|
||||
b, err := ioutil.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
if err := runtime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), b, cfg); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Set defaults dynamically that the API group defaulting can't (by fetching information from the internet, looking up network interfaces, etc.)
|
||||
err := configutil.SetInitDynamicDefaults(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := features.ValidateVersion(features.InitFeatureGates, cfg.FeatureGates, cfg.KubernetesVersion); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("[init] Using Kubernetes version: %s\n", cfg.KubernetesVersion)
|
||||
fmt.Printf("[init] Using Authorization modes: %v\n", cfg.AuthorizationModes)
|
||||
|
||||
// Warn about the limitations with the current cloudprovider solution.
|
||||
if cfg.CloudProvider != "" {
|
||||
fmt.Println("[init] WARNING: For cloudprovider integrations to work --cloud-provider must be set for all kubelets in the cluster.")
|
||||
fmt.Println("\t(/etc/systemd/system/kubelet.service.d/10-kubeadm.conf should be edited for this purpose)")
|
||||
}
|
||||
|
||||
fmt.Println("[preflight] Running pre-flight checks.")
|
||||
|
||||
if err := preflight.RunInitMasterChecks(utilsexec.New(), cfg, criSocket, ignorePreflightErrors); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Try to start the kubelet service in case it's inactive
|
||||
preflight.TryStartKubelet(ignorePreflightErrors)
|
||||
|
||||
return &Init{cfg: cfg, skipTokenPrint: skipTokenPrint, dryRun: dryRun}, nil
|
||||
}
|
||||
|
||||
// Init defines struct used by "kubeadm init" command
|
||||
type Init struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
skipTokenPrint bool
|
||||
dryRun bool
|
||||
}
|
||||
|
||||
// Validate validates configuration passed to "kubeadm init"
|
||||
func (i *Init) Validate(cmd *cobra.Command) error {
|
||||
if err := validation.ValidateMixedArguments(cmd.Flags()); err != nil {
|
||||
return err
|
||||
}
|
||||
return validation.ValidateMasterConfiguration(i.cfg).ToAggregate()
|
||||
}
|
||||
|
||||
// Run executes master node provisioning, including certificates, needed static pod manifests, etc.
|
||||
func (i *Init) Run(out io.Writer) error {
|
||||
// Get directories to write files to; can be faked if we're dry-running
|
||||
realCertsDir := i.cfg.CertificatesDir
|
||||
certsDirToWriteTo, kubeConfigDir, manifestDir, err := getDirectoriesToUse(i.dryRun, i.cfg.CertificatesDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting directories to use: %v", err)
|
||||
}
|
||||
// certsDirToWriteTo is gonna equal cfg.CertificatesDir in the normal case, but gonna be a temp directory if dryrunning
|
||||
i.cfg.CertificatesDir = certsDirToWriteTo
|
||||
|
||||
adminKubeConfigPath := filepath.Join(kubeConfigDir, kubeadmconstants.AdminKubeConfigFileName)
|
||||
|
||||
if res, _ := certsphase.UsingExternalCA(i.cfg); !res {
|
||||
|
||||
// PHASE 1: Generate certificates
|
||||
if err := certsphase.CreatePKIAssets(i.cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// PHASE 2: Generate kubeconfig files for the admin and the kubelet
|
||||
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.")
|
||||
}
|
||||
|
||||
// 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
|
||||
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 len(i.cfg.Etcd.Endpoints) == 0 {
|
||||
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)
|
||||
}
|
||||
|
||||
// NOTE: flag "--dynamic-config-dir" should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
|
||||
if features.Enabled(i.cfg.FeatureGates, features.DynamicKubeletConfig) {
|
||||
// Write base kubelet configuration for dynamic kubelet configuration feature.
|
||||
if err := kubeletphase.WriteInitKubeletConfigToDiskOnMaster(i.cfg); err != nil {
|
||||
return fmt.Errorf("error writing base kubelet configuration to disk: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a kubernetes client and wait for the API server to be healthy (if not dryrunning)
|
||||
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
|
||||
waiter := getWaiter(i.dryRun, client)
|
||||
|
||||
if err := waitForAPIAndKubelet(waiter); 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),
|
||||
}
|
||||
|
||||
kubeletFailTempl.Execute(out, ctx)
|
||||
|
||||
return fmt.Errorf("couldn't initialize a Kubernetes cluster")
|
||||
}
|
||||
|
||||
// NOTE: flag "--dynamic-config-dir" should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
|
||||
if features.Enabled(i.cfg.FeatureGates, features.DynamicKubeletConfig) {
|
||||
// Create base kubelet configuration for dynamic kubelet configuration feature.
|
||||
if err := kubeletphase.CreateBaseKubeletConfiguration(i.cfg, client); err != nil {
|
||||
return fmt.Errorf("error creating base kubelet configuration: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
if err := uploadconfigphase.UploadConfiguration(i.cfg, client); err != nil {
|
||||
return fmt.Errorf("error uploading configuration: %v", err)
|
||||
}
|
||||
|
||||
// PHASE 4: Mark the master with the right label/taint
|
||||
if err := markmasterphase.MarkMaster(client, i.cfg.NodeName); err != nil {
|
||||
return fmt.Errorf("error marking master: %v", err)
|
||||
}
|
||||
|
||||
// PHASE 5: Set up the node bootstrap tokens
|
||||
if !i.skipTokenPrint {
|
||||
fmt.Printf("[bootstraptoken] Using token: %s\n", i.cfg.Token)
|
||||
}
|
||||
|
||||
// Create the default node bootstrap token
|
||||
tokenDescription := "The default bootstrap token generated by 'kubeadm init'."
|
||||
if err := nodebootstraptokenphase.UpdateOrCreateToken(client, i.cfg.Token, false, i.cfg.TokenTTL.Duration, kubeadmconstants.DefaultTokenUsages, []string{kubeadmconstants.NodeBootstrapTokenAuthGroup}, tokenDescription); err != nil {
|
||||
return fmt.Errorf("error updating or creating token: %v", err)
|
||||
}
|
||||
// Create RBAC rules that makes the bootstrap tokens able to post CSRs
|
||||
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
|
||||
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
|
||||
if err := nodebootstraptokenphase.AutoApproveNodeCertificateRotation(client); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create the cluster-info ConfigMap with the associated RBAC rules
|
||||
if err := clusterinfophase.CreateBootstrapConfigMapIfNotExists(client, adminKubeConfigPath); err != nil {
|
||||
return fmt.Errorf("error creating bootstrap configmap: %v", err)
|
||||
}
|
||||
if err := clusterinfophase.CreateClusterInfoRBACRules(client); err != nil {
|
||||
return fmt.Errorf("error creating clusterinfo RBAC rules: %v", err)
|
||||
}
|
||||
|
||||
if err := dnsaddonphase.EnsureDNSAddon(i.cfg, client); err != nil {
|
||||
return fmt.Errorf("error ensuring dns addon: %v", err)
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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
|
||||
}
|
||||
|
||||
// Load the CA certificate from so we can pin its public key
|
||||
caCert, err := pkiutil.TryLoadCertFromDisk(i.cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading ca cert from disk: %v", err)
|
||||
}
|
||||
|
||||
// Generate the Master host/port pair used by initDoneTempl
|
||||
masterHostPort, err := kubeadmutil.GetMasterHostPort(i.cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting master host port: %v", err)
|
||||
}
|
||||
|
||||
ctx := map[string]string{
|
||||
"KubeConfigPath": adminKubeConfigPath,
|
||||
"Token": i.cfg.Token,
|
||||
"CAPubKeyPin": pubkeypin.Hash(caCert),
|
||||
"MasterHostPort": masterHostPort,
|
||||
}
|
||||
if i.skipTokenPrint {
|
||||
ctx["Token"] = "<value withheld>"
|
||||
}
|
||||
|
||||
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.NodeName, 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, 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, nil
|
||||
}
|
||||
|
||||
return defaultPkiDir, kubeadmconstants.KubernetesDir, kubeadmconstants.GetStaticPodDirectory(), 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
|
||||
}
|
||||
|
||||
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{}
|
||||
for _, component := range kubeadmconstants.MasterComponents {
|
||||
realPath := kubeadmconstants.GetStaticPodFilepath(component, manifestDir)
|
||||
outputPath := kubeadmconstants.GetStaticPodFilepath(component, kubeadmconstants.GetStaticPodDirectory())
|
||||
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(dryRun bool, client clientset.Interface) apiclient.Waiter {
|
||||
if dryRun {
|
||||
return dryrunutil.NewWaiter()
|
||||
}
|
||||
return apiclient.NewKubeWaiter(client, 30*time.Minute, os.Stdout)
|
||||
}
|
||||
|
||||
// waitForAPIAndKubelet waits primarily for the API server to come up. If that takes a long time, and the kubelet
|
||||
// /healthz and /healthz/syncloop endpoints continuously are unhealthy, kubeadm will error out after a period of
|
||||
// backoffing exponentially
|
||||
func waitForAPIAndKubelet(waiter apiclient.Waiter) error {
|
||||
errorChan := make(chan error)
|
||||
|
||||
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.")
|
||||
|
||||
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
|
||||
if err := waiter.WaitForHealthyKubelet(40*time.Second, "http://localhost:10255/healthz"); err != nil {
|
||||
errC <- err
|
||||
}
|
||||
}(errorChan, waiter)
|
||||
|
||||
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
|
||||
if err := waiter.WaitForHealthyKubelet(60*time.Second, "http://localhost:10255/healthz/syncloop"); err != nil {
|
||||
errC <- err
|
||||
}
|
||||
}(errorChan, waiter)
|
||||
|
||||
go func(errC chan error, waiter apiclient.Waiter) {
|
||||
// This main goroutine sends whatever WaitForAPI returns (error or not) to the channel
|
||||
// This in order to continue on success (nil error), or just fail if
|
||||
errC <- waiter.WaitForAPI()
|
||||
}(errorChan, waiter)
|
||||
|
||||
// This call is blocking until one of the goroutines sends to errorChan
|
||||
return <-errorChan
|
||||
}
|
268
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join.go
generated
vendored
Normal file
268
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join.go
generated
vendored
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
flag "github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"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"
|
||||
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/api/legacyscheme"
|
||||
nodeutil "k8s.io/kubernetes/pkg/util/node"
|
||||
utilsexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
var (
|
||||
joinDoneMsgf = dedent.Dedent(`
|
||||
This node has joined the cluster:
|
||||
* Certificate signing request was sent to master 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.
|
||||
`)
|
||||
|
||||
joinLongDescription = dedent.Dedent(`
|
||||
When joining a kubeadm initialized cluster, we need to establish
|
||||
bidirectional trust. This is split into discovery (having the Node
|
||||
trust the Kubernetes Master) and TLS bootstrap (having the Kubernetes
|
||||
Master trust the Node).
|
||||
|
||||
There are 2 main schemes for discovery. The first is to use a shared
|
||||
token along with the IP address of the API server. The second is to
|
||||
provide a file - a subset of the standard kubeconfig file. This file
|
||||
can be a local file or downloaded via an HTTPS URL. The forms are
|
||||
kubeadm join --discovery-token abcdef.1234567890abcdef 1.2.3.4:6443,
|
||||
kubeadm join --discovery-file path/to/file.conf, or kubeadm join
|
||||
--discovery-file https://url/file.conf. Only one form can be used. If
|
||||
the discovery information is loaded from a URL, HTTPS must be used.
|
||||
Also, in that case the host installed CA bundle is used to verify
|
||||
the connection.
|
||||
|
||||
If you use a shared token for discovery, you should also pass the
|
||||
--discovery-token-ca-cert-hash flag to validate the public key of the
|
||||
root certificate authority (CA) presented by the Kubernetes Master. The
|
||||
value of this flag is specified as "<hash-type>:<hex-encoded-value>",
|
||||
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
|
||||
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
|
||||
the --discovery-token-unsafe-skip-ca-verification flag to disable this
|
||||
verification. This weakens the kubeadm security model since other nodes
|
||||
can potentially impersonate the Kubernetes Master.
|
||||
|
||||
The TLS bootstrap mechanism is also driven via a shared token. This is
|
||||
used to temporarily authenticate with the Kubernetes Master to submit a
|
||||
certificate signing request (CSR) for a locally created key pair. By
|
||||
default, kubeadm will set up the Kubernetes Master to automatically
|
||||
approve these signing requests. This token is passed in with the
|
||||
--tls-bootstrap-token abcdef.1234567890abcdef flag.
|
||||
|
||||
Often times the same token is used for both parts. In this case, the
|
||||
--token flag can be used instead of specifying each token individually.
|
||||
`)
|
||||
)
|
||||
|
||||
// NewCmdJoin returns "kubeadm join" command.
|
||||
func NewCmdJoin(out io.Writer) *cobra.Command {
|
||||
cfg := &kubeadmapiext.NodeConfiguration{}
|
||||
legacyscheme.Scheme.Default(cfg)
|
||||
|
||||
var skipPreFlight bool
|
||||
var cfgPath string
|
||||
var criSocket string
|
||||
var featureGatesString string
|
||||
var ignorePreflightErrors []string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "join [flags]",
|
||||
Short: "Run this on any machine you wish to join an existing cluster",
|
||||
Long: joinLongDescription,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cfg.DiscoveryTokenAPIServers = args
|
||||
|
||||
var err error
|
||||
if cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
|
||||
legacyscheme.Scheme.Default(cfg)
|
||||
internalcfg := &kubeadmapi.NodeConfiguration{}
|
||||
legacyscheme.Scheme.Convert(cfg, internalcfg, nil)
|
||||
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
j, err := NewJoin(cfgPath, args, internalcfg, ignorePreflightErrorsSet, criSocket)
|
||||
kubeadmutil.CheckErr(err)
|
||||
kubeadmutil.CheckErr(j.Validate(cmd))
|
||||
kubeadmutil.CheckErr(j.Run(out))
|
||||
},
|
||||
}
|
||||
|
||||
AddJoinConfigFlags(cmd.PersistentFlags(), cfg, &featureGatesString)
|
||||
AddJoinOtherFlags(cmd.PersistentFlags(), &cfgPath, &skipPreFlight, &criSocket, &ignorePreflightErrors)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// AddJoinConfigFlags adds join flags bound to the config to the specified flagset
|
||||
func AddJoinConfigFlags(flagSet *flag.FlagSet, cfg *kubeadmapiext.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.")
|
||||
flagSet.StringVar(
|
||||
&cfg.NodeName, "node-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"))
|
||||
}
|
||||
|
||||
// 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, criSocket *string, ignorePreflightErrors *[]string) {
|
||||
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.",
|
||||
)
|
||||
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")
|
||||
flagSet.StringVar(
|
||||
criSocket, "cri-socket", "/var/run/dockershim.sock",
|
||||
`Specify the CRI socket to connect to.`,
|
||||
)
|
||||
}
|
||||
|
||||
// Join defines struct used by kubeadm join command
|
||||
type Join struct {
|
||||
cfg *kubeadmapi.NodeConfiguration
|
||||
}
|
||||
|
||||
// NewJoin instantiates Join struct with given arguments
|
||||
func NewJoin(cfgPath string, args []string, cfg *kubeadmapi.NodeConfiguration, ignorePreflightErrors sets.String, criSocket string) (*Join, error) {
|
||||
|
||||
if cfg.NodeName == "" {
|
||||
cfg.NodeName = nodeutil.GetHostname("")
|
||||
}
|
||||
|
||||
if cfgPath != "" {
|
||||
b, err := ioutil.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
if err := runtime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), b, cfg); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("[preflight] Running pre-flight checks.")
|
||||
|
||||
// Then continue with the others...
|
||||
if err := preflight.RunJoinNodeChecks(utilsexec.New(), cfg, criSocket, ignorePreflightErrors); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Try to start the kubelet service in case it's inactive
|
||||
preflight.TryStartKubelet(ignorePreflightErrors)
|
||||
|
||||
return &Join{cfg: cfg}, nil
|
||||
}
|
||||
|
||||
// Validate validates mixed arguments passed to cobra.Command
|
||||
func (j *Join) Validate(cmd *cobra.Command) error {
|
||||
if err := validation.ValidateMixedArguments(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
}
|
||||
return validation.ValidateNodeConfiguration(j.cfg).ToAggregate()
|
||||
}
|
||||
|
||||
// Run executes worker node provisioning and tries to join an existing cluster.
|
||||
func (j *Join) Run(out io.Writer) error {
|
||||
cfg, err := discovery.For(j.cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName)
|
||||
|
||||
// Write the bootstrap kubelet config file or the TLS-Boostrapped kubelet config file down to disk
|
||||
if err := kubeconfigutil.WriteToDisk(kubeconfigFile, cfg); err != nil {
|
||||
return fmt.Errorf("couldn't save bootstrap-kubelet.conf to disk: %v", err)
|
||||
}
|
||||
|
||||
// Write the ca certificate to disk so kubelet can use it for authentication
|
||||
cluster := cfg.Contexts[cfg.CurrentContext].Cluster
|
||||
err = certutil.WriteCert(j.cfg.CACertPath, cfg.Clusters[cluster].CertificateAuthorityData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't save the CA certificate to disk: %v", err)
|
||||
}
|
||||
|
||||
// NOTE: flag "--dynamic-config-dir" should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
|
||||
if features.Enabled(j.cfg.FeatureGates, features.DynamicKubeletConfig) {
|
||||
if err := kubeletphase.ConsumeBaseKubeletConfiguration(j.cfg.NodeName); err != nil {
|
||||
return fmt.Errorf("error consuming base kubelet configuration: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, joinDoneMsgf)
|
||||
return nil
|
||||
}
|
98
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/BUILD
generated
vendored
Normal file
98
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/BUILD
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"addons.go",
|
||||
"bootstraptoken.go",
|
||||
"certs.go",
|
||||
"controlplane.go",
|
||||
"etcd.go",
|
||||
"kubeconfig.go",
|
||||
"markmaster.go",
|
||||
"phase.go",
|
||||
"preflight.go",
|
||||
"selfhosting.go",
|
||||
"uploadconfig.go",
|
||||
"util.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/validation: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",
|
||||
"//cmd/kubeadm/app/phases/bootstraptoken/node:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs/pkiutil: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/markmaster: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/config:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/util/pubkeypin:go_default_library",
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/bootstrap/api:go_default_library",
|
||||
"//pkg/util/normalizer: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/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"addons_test.go",
|
||||
"certs_test.go",
|
||||
"controlplane_test.go",
|
||||
"etcd_test.go",
|
||||
"kubeconfig_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/install:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs/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",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
196
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons.go
generated
vendored
Normal file
196
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons.go
generated
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
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 (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
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/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
allAddonsLongDesc = normalizer.LongDesc(`
|
||||
Installs the kube-dns 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 kube-dns and the kube-proxys addons components via the API server,
|
||||
# functionally equivalent to what installed by kubeadm init.
|
||||
|
||||
kubeadm alpha phase selfhosting from-staticpods
|
||||
`)
|
||||
|
||||
kubednsAddonsLongDesc = normalizer.LongDesc(`
|
||||
Installs the kube-dns 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(`
|
||||
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
|
||||
}
|
||||
|
||||
// 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,
|
||||
}
|
||||
|
||||
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 := &kubeadmapiext.MasterConfiguration{}
|
||||
// Default values for the cobra help text
|
||||
legacyscheme.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: "kube-dns",
|
||||
short: "Installs the kube-dns addon to a Kubernetes cluster",
|
||||
long: kubednsAddonsLongDesc,
|
||||
cmdFunc: dnsaddon.EnsureDNSAddon,
|
||||
},
|
||||
{
|
||||
use: "kube-proxy",
|
||||
short: "Installs the kube-proxy addon to a Kubernetes cluster",
|
||||
long: kubeproxyAddonsLongDesc,
|
||||
cmdFunc: proxyaddon.EnsureProxyAddon,
|
||||
},
|
||||
}
|
||||
|
||||
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 or DNS name 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 == "kube-dns" {
|
||||
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 *kubeadmapiext.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{}
|
||||
legacyscheme.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)
|
||||
}
|
||||
}
|
74
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons_test.go
generated
vendored
Normal file
74
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/addons_test.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
// required for triggering api machinery startup when running unit tests
|
||||
_ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install"
|
||||
|
||||
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: "kube-dns",
|
||||
additionalFlags: []string{
|
||||
"service-dns-domain",
|
||||
"service-cidr",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
expectedFlags := append(commonFlags, test.additionalFlags...)
|
||||
cmdtestutil.AssertSubCommandHasFlags(t, subCmds, test.command, expectedFlags...)
|
||||
}
|
||||
}
|
358
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/bootstraptoken.go
generated
vendored
Normal file
358
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/bootstraptoken.go
generated
vendored
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
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"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pkiutil"
|
||||
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/util/pubkeypin"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
allTokenLongDesc = normalizer.LongDesc(`
|
||||
Bootstrap tokens are used for establishing bidirectional trust between a node joining
|
||||
the cluster and a the master 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)
|
||||
)
|
||||
|
||||
// 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,
|
||||
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 := &kubeadmapiext.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.9.0",
|
||||
}
|
||||
|
||||
// Default values for the cobra help text
|
||||
legacyscheme.Scheme.Default(cfg)
|
||||
|
||||
var cfgPath, description string
|
||||
var usages, extraGroups []string
|
||||
var skipTokenPrint bool
|
||||
|
||||
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)
|
||||
|
||||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Creates the bootstap token
|
||||
err = createBootstrapToken(client, cfgPath, cfg, description, usages, extraGroups, 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)
|
||||
},
|
||||
}
|
||||
|
||||
// Adds flags to the command
|
||||
addBootstrapTokenFlags(cmd.Flags(), cfg, &cfgPath, &description, &usages, &extraGroups, &skipTokenPrint)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewSubCmdBootstrapToken returns the Cobra command for running the create token phase
|
||||
func NewSubCmdBootstrapToken(kubeConfigFile *string) *cobra.Command {
|
||||
cfg := &kubeadmapiext.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.9.0",
|
||||
}
|
||||
|
||||
// Default values for the cobra help text
|
||||
legacyscheme.Scheme.Default(cfg)
|
||||
|
||||
var cfgPath, description string
|
||||
var usages, extraGroups []string
|
||||
var skipTokenPrint bool
|
||||
|
||||
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)
|
||||
|
||||
client, err := kubeconfigutil.ClientSetFromFile(*kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = createBootstrapToken(client, cfgPath, cfg, description, usages, extraGroups, skipTokenPrint)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
// Adds flags to the command
|
||||
addBootstrapTokenFlags(cmd.Flags(), cfg, &cfgPath, &description, &usages, &extraGroups, &skipTokenPrint)
|
||||
|
||||
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 addBootstrapTokenFlags(flagSet *pflag.FlagSet, cfg *kubeadmapiext.MasterConfiguration, cfgPath, description *string, usages, extraGroups *[]string, skipTokenPrint *bool) {
|
||||
flagSet.StringVar(
|
||||
cfgPath, "config", *cfgPath,
|
||||
"Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir,
|
||||
"The path where certificates are stored",
|
||||
)
|
||||
flagSet.StringVar(
|
||||
&cfg.Token, "token", cfg.Token,
|
||||
"The token to use for establishing bidirectional trust between nodes and masters",
|
||||
)
|
||||
flagSet.DurationVar(
|
||||
&cfg.TokenTTL.Duration, "ttl", kubeadmconstants.DefaultTokenDuration,
|
||||
"The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire",
|
||||
)
|
||||
flagSet.StringSliceVar(
|
||||
usages, "usages", kubeadmconstants.DefaultTokenUsages,
|
||||
fmt.Sprintf("Describes the ways in which this token can be used. You can pass --usages multiple times or provide a comma separated list of options. Valid options: [%s]", strings.Join(kubeadmconstants.DefaultTokenUsages, ",")),
|
||||
)
|
||||
flagSet.StringSliceVar(
|
||||
extraGroups, "groups", []string{kubeadmconstants.NodeBootstrapTokenAuthGroup},
|
||||
fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q", bootstrapapi.BootstrapGroupPattern),
|
||||
)
|
||||
flagSet.StringVar(
|
||||
description, "description", "The default bootstrap token generated by 'kubeadm init'.",
|
||||
"A human friendly description of how this token is used.",
|
||||
)
|
||||
flagSet.BoolVar(
|
||||
skipTokenPrint, "skip-token-print", *skipTokenPrint,
|
||||
"Skip printing of the bootstrap token",
|
||||
)
|
||||
}
|
||||
|
||||
func createBootstrapToken(client clientset.Interface, cfgPath string, cfg *kubeadmapiext.MasterConfiguration, description string, usages, extraGroups []string, skipTokenPrint bool) error {
|
||||
// adding groups only makes sense for authentication
|
||||
usagesSet := sets.NewString(usages...)
|
||||
usageAuthentication := strings.TrimPrefix(bootstrapapi.BootstrapTokenUsageAuthentication, bootstrapapi.BootstrapTokenUsagePrefix)
|
||||
if len(extraGroups) > 0 && !usagesSet.Has(usageAuthentication) {
|
||||
return fmt.Errorf("--groups cannot be specified unless --usages includes %q", usageAuthentication)
|
||||
}
|
||||
|
||||
// validate any extra group names
|
||||
for _, group := range extraGroups {
|
||||
if err := bootstrapapi.ValidateBootstrapGroupName(group); 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)
|
||||
|
||||
// Load the CA certificate from so we can pin its public key
|
||||
caCert, err := pkiutil.TryLoadCertFromDisk(internalcfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading ca cert from disk: %v", err)
|
||||
}
|
||||
|
||||
// Creates or updates the token
|
||||
if err := node.UpdateOrCreateToken(client, internalcfg.Token, false, internalcfg.TokenTTL.Duration, usages, extraGroups, description); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("[bootstraptoken] Bootstrap token Created")
|
||||
if skipTokenPrint {
|
||||
internalcfg.Token = "{token}"
|
||||
}
|
||||
fmt.Println("[bootstraptoken] You can now join any number of machines by running:")
|
||||
fmt.Printf("[bootstraptoken] kubeadm join {master} --token %s --discovery-token-ca-cert-hash %s \n", internalcfg.Token, pubkeypin.Hash(caCert))
|
||||
|
||||
return nil
|
||||
}
|
227
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs.go
generated
vendored
Normal file
227
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs.go
generated
vendored
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
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/pkg/api/legacyscheme"
|
||||
"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 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 eventually 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)
|
||||
|
||||
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.
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
// 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,
|
||||
}
|
||||
|
||||
cmd.AddCommand(getCertsSubCommands("")...)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// getCertsSubCommands returns sub commands for certs phase
|
||||
func getCertsSubCommands(defaultKubernetesVersion string) []*cobra.Command {
|
||||
|
||||
cfg := &kubeadmapiext.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 explicitely for tests workarounds that
|
||||
if defaultKubernetesVersion != "" {
|
||||
cfg.KubernetesVersion = defaultKubernetesVersion
|
||||
}
|
||||
|
||||
// Default values for the cobra help text
|
||||
legacyscheme.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 self-signed CA to provision identities for each component in the cluster",
|
||||
long: caCertLongDesc,
|
||||
cmdFunc: certsphase.CreateCACertAndKeyfiles,
|
||||
},
|
||||
{
|
||||
use: "apiserver",
|
||||
short: "Generates API server serving certificate and key",
|
||||
long: apiServerCertLongDesc,
|
||||
cmdFunc: certsphase.CreateAPIServerCertAndKeyFiles,
|
||||
},
|
||||
{
|
||||
use: "apiserver-kubelet-client",
|
||||
short: "Generates client certificate for the API server to connect to the kubelets securely",
|
||||
long: apiServerKubeletCertLongDesc,
|
||||
cmdFunc: certsphase.CreateAPIServerKubeletClientCertAndKeyFiles,
|
||||
},
|
||||
{
|
||||
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 front proxy CA certificate and key for a Kubernetes cluster",
|
||||
long: frontProxyCaCertLongDesc,
|
||||
cmdFunc: certsphase.CreateFrontProxyCACertAndKeyFiles,
|
||||
},
|
||||
{
|
||||
use: "front-proxy-client",
|
||||
short: "Generates 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 *kubeadmapiext.MasterConfiguration) 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) {
|
||||
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)
|
||||
}
|
||||
}
|
240
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs_test.go
generated
vendored
Normal file
240
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/certs_test.go
generated
vendored
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
// required for triggering api machinery startup when running unit tests
|
||||
_ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install"
|
||||
|
||||
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"
|
||||
|
||||
testutil "k8s.io/kubernetes/cmd/kubeadm/test"
|
||||
cmdtestutil "k8s.io/kubernetes/cmd/kubeadm/test/cmd"
|
||||
)
|
||||
|
||||
// phaseTestK8sVersion is a fake kubernetes version to use when testing
|
||||
const phaseTestK8sVersion = "v1.8.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: "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...)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubCmdCertsCreateFilesWithFlags(t *testing.T) {
|
||||
|
||||
subCmds := getCertsSubCommands(phaseTestK8sVersion)
|
||||
|
||||
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{"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},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
// Create temp folder for the test case
|
||||
tmpdir := testutil.SetupTempDir(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
// executes given sub commands
|
||||
for _, subCmdName := range test.subCmds {
|
||||
certDirFlag := fmt.Sprintf("--cert-dir=%s", tmpdir)
|
||||
cmdtestutil.RunSubCommand(t, subCmds, subCmdName, certDirFlag)
|
||||
}
|
||||
|
||||
// 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",
|
||||
}
|
||||
cmdtestutil.RunSubCommand(t, subCmds, "apiserver", apiserverFlags...)
|
||||
|
||||
// asserts created cert has values from CLI flags
|
||||
APIserverCert, err := pkiutil.TryLoadCertFromDisk(tmpdir, kubeadmconstants.APIServerCertAndKeyBaseName)
|
||||
if err != nil {
|
||||
t.Fatalf("Error loading API server certificate: %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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubCmdCertsCreateFilesWithConfigFile(t *testing.T) {
|
||||
|
||||
subCmds := getCertsSubCommands(phaseTestK8sVersion)
|
||||
|
||||
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{"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},
|
||||
},
|
||||
}
|
||||
|
||||
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,
|
||||
NodeName: "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...)
|
||||
}
|
||||
}
|
193
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane.go
generated
vendored
Normal file
193
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane.go
generated
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
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"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
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/pkg/api/legacyscheme"
|
||||
"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(`
|
||||
# Generates all static Pod manifest files for control plane components,
|
||||
# functionally equivalent to what generated by kubeadm init.
|
||||
kubeadm alpha phase controlplane all
|
||||
|
||||
# Generates all static Pod manifest files using options read from a configuration file.
|
||||
kubeadm alpha phase controlplane --config masterconfiguration.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()))
|
||||
)
|
||||
|
||||
// NewCmdControlplane return main command for Controlplane phase
|
||||
func NewCmdControlplane() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "controlplane",
|
||||
Short: "Generates all static Pod manifest files necessary to establish the control plane",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
}
|
||||
|
||||
manifestPath := kubeadmconstants.GetStaticPodDirectory()
|
||||
cmd.AddCommand(getControlPlaneSubCommands(manifestPath, "")...)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// getControlPlaneSubCommands returns sub commands for Controlplane phase
|
||||
func getControlPlaneSubCommands(outDir, defaultKubernetesVersion string) []*cobra.Command {
|
||||
|
||||
cfg := &kubeadmapiext.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 explicitely for tests workarounds that
|
||||
if defaultKubernetesVersion != "" {
|
||||
cfg.KubernetesVersion = defaultKubernetesVersion
|
||||
}
|
||||
|
||||
// Default values for the cobra help text
|
||||
legacyscheme.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 or DNS name 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"))
|
||||
}
|
||||
|
||||
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().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file (WARNING: Usage of a configuration file is experimental)")
|
||||
|
||||
subCmds = append(subCmds, cmd)
|
||||
}
|
||||
|
||||
return subCmds
|
||||
}
|
||||
|
||||
// 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 *kubeadmapiext.MasterConfiguration) 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
152
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane_test.go
generated
vendored
Normal file
152
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/controlplane_test.go
generated
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
// required for triggering api machinery startup when running unit tests
|
||||
_ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install"
|
||||
|
||||
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.8.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.8.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.8.0",
|
||||
"--pod-network-cidr=1.2.3.4/16",
|
||||
},
|
||||
expectedFiles: []string{"kube-controller-manager.yaml"},
|
||||
},
|
||||
{
|
||||
command: "scheduler",
|
||||
additionalFlags: []string{
|
||||
"--kubernetes-version=v1.8.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...)
|
||||
}
|
||||
}
|
109
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd.go
generated
vendored
Normal file
109
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
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/api/legacyscheme"
|
||||
"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
|
||||
|
||||
# Generates the static Pod manifest file for etcd.
|
||||
kubeadm alpha phase etcd local --config masterconfiguration.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.",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
}
|
||||
|
||||
manifestPath := kubeadmconstants.GetStaticPodDirectory()
|
||||
cmd.AddCommand(getEtcdSubCommands(manifestPath, "")...)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// getEtcdSubCommands returns sub commands for etcd phase
|
||||
func getEtcdSubCommands(outDir, defaultKubernetesVersion string) []*cobra.Command {
|
||||
|
||||
cfg := &kubeadmapiext.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 explicitely for tests workarounds that
|
||||
if defaultKubernetesVersion != "" {
|
||||
cfg.KubernetesVersion = defaultKubernetesVersion
|
||||
}
|
||||
|
||||
// Default values for the cobra help text
|
||||
legacyscheme.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
|
||||
}
|
86
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd_test.go
generated
vendored
Normal file
86
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/etcd_test.go
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
// required for triggering api machinery startup when running unit tests
|
||||
_ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install"
|
||||
|
||||
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...)
|
||||
}
|
||||
}
|
197
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig.go
generated
vendored
Normal file
197
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig.go
generated
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
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"
|
||||
"io"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
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"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
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
|
||||
`)
|
||||
)
|
||||
|
||||
// NewCmdKubeConfig return main command for kubeconfig phase
|
||||
func NewCmdKubeConfig(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "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 := &kubeadmapiext.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 explicitely for tests workarounds that
|
||||
if defaultKubernetesVersion != "" {
|
||||
cfg.KubernetesVersion = defaultKubernetesVersion
|
||||
}
|
||||
|
||||
// Default values for the cobra help text
|
||||
legacyscheme.Scheme.Default(cfg)
|
||||
|
||||
var cfgPath, token, clientName 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)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
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 port where to save the kubeconfig file")
|
||||
if properties.use == "all" || properties.use == "kubelet" {
|
||||
cmd.Flags().StringVar(&cfg.NodeName, "node-name", cfg.NodeName, `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")
|
||||
}
|
||||
|
||||
subCmds = append(subCmds, cmd)
|
||||
}
|
||||
|
||||
return subCmds
|
||||
}
|
391
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go
generated
vendored
Normal file
391
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/kubeconfig_test.go
generated
vendored
Normal file
@ -0,0 +1,391 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
// required for triggering api machinery startup when running unit tests
|
||||
_ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install"
|
||||
|
||||
"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
|
||||
|
||||
// Retrives ca cert for assertions
|
||||
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't retrive 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)
|
||||
|
||||
// Retrives ca cert for assertions
|
||||
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't retrive ca cert: %v", err)
|
||||
}
|
||||
|
||||
// Adds a master configuration file
|
||||
cfg := &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
|
||||
CertificatesDir: pkidir,
|
||||
NodeName: "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
|
||||
|
||||
// Retrives ca cert for assertions
|
||||
caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't retrive 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")
|
||||
}
|
||||
}
|
||||
}
|
88
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/markmaster.go
generated
vendored
Normal file
88
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/markmaster.go
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"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/api/legacyscheme"
|
||||
"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 := &kubeadmapiext.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.9.0",
|
||||
}
|
||||
|
||||
// Default values for the cobra help text
|
||||
legacyscheme.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.NodeName)
|
||||
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.NodeName, "node-name", cfg.NodeName, `The node name to which label and taints should apply`)
|
||||
|
||||
return cmd
|
||||
}
|
46
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/phase.go
generated
vendored
Normal file
46
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/phase.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
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(NewCmdKubeConfig(out))
|
||||
cmd.AddCommand(NewCmdMarkMaster())
|
||||
cmd.AddCommand(NewCmdPreFlight())
|
||||
cmd.AddCommand(NewCmdSelfhosting())
|
||||
cmd.AddCommand(NewCmdUploadConfig())
|
||||
|
||||
return cmd
|
||||
}
|
98
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/preflight.go
generated
vendored
Normal file
98
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/preflight.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
"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/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
|
||||
`)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// NewCmdPreFlightMaster calls cobra.Command for master preflight checks
|
||||
func NewCmdPreFlightMaster() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "master",
|
||||
Short: "Run master pre-flight checks",
|
||||
Long: masterPreflightLongDesc,
|
||||
Example: masterPreflightExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cfg := &kubeadmapi.MasterConfiguration{}
|
||||
criSocket := ""
|
||||
err := preflight.RunInitMasterChecks(utilsexec.New(), cfg, criSocket, sets.NewString())
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
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{}
|
||||
criSocket := ""
|
||||
err := preflight.RunJoinNodeChecks(utilsexec.New(), cfg, criSocket, sets.NewString())
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
123
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/selfhosting.go
generated
vendored
Normal file
123
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/selfhosting.go
generated
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
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 (
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
selfhostingLongDesc = normalizer.LongDesc(`
|
||||
Converts static Pod files for control plane components into self-hosted DaemonSets configured via the Kubernetes API.
|
||||
|
||||
See the documentation for self-hosting limitations.
|
||||
|
||||
` + 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.
|
||||
|
||||
kubeadm alpha phase selfhosting convert-from-staticpods
|
||||
`)
|
||||
)
|
||||
|
||||
// NewCmdSelfhosting returns the self-hosting Cobra command
|
||||
func NewCmdSelfhosting() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "selfhosting",
|
||||
Aliases: []string{"selfhosted", "self-hosting"},
|
||||
Short: "Makes a kubeadm cluster self-hosted",
|
||||
Long: cmdutil.MacroCommandLongDescription,
|
||||
}
|
||||
|
||||
cmd.AddCommand(getSelfhostingSubCommand())
|
||||
return cmd
|
||||
}
|
||||
|
||||
// getSelfhostingSubCommand returns sub commands for Selfhosting phase
|
||||
func getSelfhostingSubCommand() *cobra.Command {
|
||||
|
||||
cfg := &kubeadmapiext.MasterConfiguration{}
|
||||
// Default values for the cobra help text
|
||||
legacyscheme.Scheme.Default(cfg)
|
||||
|
||||
var cfgPath, kubeConfigFile, featureGatesString string
|
||||
|
||||
// Creates the UX Command
|
||||
cmd := &cobra.Command{
|
||||
Use: "convert-from-staticpods",
|
||||
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 cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, featureGatesString); err != nil {
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
// 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)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
// Add flags to the 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"))
|
||||
|
||||
// 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")
|
||||
|
||||
return cmd
|
||||
}
|
78
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/uploadconfig.go
generated
vendored
Normal file
78
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/uploadconfig.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"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.
|
||||
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)
|
||||
|
||||
uploadConfigExample = normalizer.Examples(`
|
||||
# uploads the configuration of your cluster
|
||||
kubeadm alpha phase upload-config --config=myConfig.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,
|
||||
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 := &kubeadmapiext.MasterConfiguration{}
|
||||
internalcfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(cfgPath, defaultcfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = uploadconfig.UploadConfiguration(internalcfg, client)
|
||||
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", "", "Path to a kubeadm config file. WARNING: Usage of a configuration file is experimental!")
|
||||
|
||||
return cmd
|
||||
}
|
50
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/util.go
generated
vendored
Normal file
50
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/util.go
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"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"
|
||||
)
|
||||
|
||||
// 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 *kubeadmapiext.MasterConfiguration) 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) {
|
||||
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(*outDir, internalcfg)
|
||||
kubeadmutil.CheckErr(err)
|
||||
}
|
||||
}
|
264
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset.go
generated
vendored
Normal file
264
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset.go
generated
vendored
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/util/initsystem"
|
||||
utilsexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
var (
|
||||
crictlSandboxesParamsFormat = "%s -r %s sandboxes --quiet | xargs -r"
|
||||
crictlStopParamsFormat = "%s -r %s stops %s"
|
||||
crictlRemoveParamsFormat = "%s -r %s rms %s"
|
||||
)
|
||||
|
||||
// NewCmdReset returns the "kubeadm reset" command
|
||||
func NewCmdReset(out io.Writer) *cobra.Command {
|
||||
var skipPreFlight bool
|
||||
var certsDir string
|
||||
var criSocketPath string
|
||||
var ignorePreflightErrors []string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "reset",
|
||||
Short: "Run this to revert any changes made to this host by 'kubeadm init' or 'kubeadm join'.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ignorePreflightErrorsSet, err := validation.ValidateIgnorePreflightErrors(ignorePreflightErrors, skipPreFlight)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
r, err := NewReset(ignorePreflightErrorsSet, certsDir, criSocketPath)
|
||||
kubeadmutil.CheckErr(err)
|
||||
kubeadmutil.CheckErr(r.Run(out))
|
||||
},
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().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.",
|
||||
)
|
||||
cmd.PersistentFlags().BoolVar(
|
||||
&skipPreFlight, "skip-preflight-checks", false,
|
||||
"Skip preflight checks which normally run before modifying the system.",
|
||||
)
|
||||
cmd.PersistentFlags().MarkDeprecated("skip-preflight-checks", "it is now equivalent to --ignore-preflight-errors=all")
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&certsDir, "cert-dir", kubeadmapiext.DefaultCertificatesDir,
|
||||
"The path to the directory where the certificates are stored. If specified, clean this directory.",
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&criSocketPath, "cri-socket", "/var/run/dockershim.sock",
|
||||
"The path to the CRI socket to use with crictl when cleaning up containers.",
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Reset defines struct used for kubeadm reset command
|
||||
type Reset struct {
|
||||
certsDir string
|
||||
criSocketPath string
|
||||
}
|
||||
|
||||
// NewReset instantiate Reset struct
|
||||
func NewReset(ignorePreflightErrors sets.String, certsDir, criSocketPath string) (*Reset, error) {
|
||||
fmt.Println("[preflight] Running pre-flight checks.")
|
||||
|
||||
if err := preflight.RunRootCheckOnly(ignorePreflightErrors); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Reset{
|
||||
certsDir: certsDir,
|
||||
criSocketPath: criSocketPath,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Run reverts any changes made to this host by "kubeadm init" or "kubeadm join".
|
||||
func (r *Reset) Run(out io.Writer) error {
|
||||
|
||||
// Try to stop the kubelet service
|
||||
initSystem, err := initsystem.GetInitSystem()
|
||||
if err != nil {
|
||||
fmt.Println("[reset] WARNING: The kubelet service could not be stopped by kubeadm. Unable to detect a supported init system!")
|
||||
fmt.Println("[reset] WARNING: Please ensure kubelet is stopped manually.")
|
||||
} else {
|
||||
fmt.Println("[reset] Stopping the kubelet service.")
|
||||
if err := initSystem.ServiceStop("kubelet"); err != nil {
|
||||
fmt.Printf("[reset] WARNING: The kubelet service could not be stopped by kubeadm: [%v]\n", err)
|
||||
fmt.Println("[reset] WARNING: Please ensure kubelet is stopped manually.")
|
||||
}
|
||||
}
|
||||
|
||||
// Try to unmount mounted directories under /var/lib/kubelet in order to be able to remove the /var/lib/kubelet directory later
|
||||
fmt.Printf("[reset] Unmounting mounted directories in %q\n", "/var/lib/kubelet")
|
||||
umountDirsCmd := "awk '$2 ~ path {print $2}' path=/var/lib/kubelet /proc/mounts | xargs -r umount"
|
||||
umountOutputBytes, err := exec.Command("sh", "-c", umountDirsCmd).Output()
|
||||
if err != nil {
|
||||
fmt.Printf("[reset] Failed to unmount mounted directories in /var/lib/kubelet: %s\n", string(umountOutputBytes))
|
||||
}
|
||||
|
||||
fmt.Println("[reset] Removing kubernetes-managed containers.")
|
||||
dockerCheck := preflight.ServiceCheck{Service: "docker", CheckIfActive: true}
|
||||
execer := utilsexec.New()
|
||||
|
||||
reset(execer, dockerCheck, r.criSocketPath)
|
||||
|
||||
dirsToClean := []string{"/var/lib/kubelet", "/etc/cni/net.d", "/var/lib/dockershim", "/var/run/kubernetes"}
|
||||
|
||||
// Only clear etcd data when the etcd manifest is found. In case it is not found, we must assume that the user
|
||||
// provided external etcd endpoints. In that case, it is his own responsibility to reset etcd
|
||||
etcdManifestPath := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ManifestsSubDirName, "etcd.yaml")
|
||||
if _, err := os.Stat(etcdManifestPath); err == nil {
|
||||
dirsToClean = append(dirsToClean, "/var/lib/etcd")
|
||||
} else {
|
||||
fmt.Printf("[reset] No etcd manifest found in %q. Assuming external etcd.\n", etcdManifestPath)
|
||||
}
|
||||
|
||||
// Then clean contents from the stateful kubelet, etcd and cni directories
|
||||
fmt.Printf("[reset] Deleting contents of stateful directories: %v\n", dirsToClean)
|
||||
for _, dir := range dirsToClean {
|
||||
cleanDir(dir)
|
||||
}
|
||||
|
||||
// Remove contents from the config and pki directories
|
||||
if r.certsDir != kubeadmapiext.DefaultCertificatesDir {
|
||||
fmt.Printf("[reset] WARNING: Cleaning a non-default certificates directory: %q\n", r.certsDir)
|
||||
}
|
||||
resetConfigDir(kubeadmconstants.KubernetesDir, r.certsDir)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func reset(execer utilsexec.Interface, dockerCheck preflight.Checker, criSocketPath string) {
|
||||
crictlPath, err := execer.LookPath("crictl")
|
||||
if err == nil {
|
||||
resetWithCrictl(execer, dockerCheck, criSocketPath, crictlPath)
|
||||
} else {
|
||||
resetWithDocker(execer, dockerCheck)
|
||||
}
|
||||
}
|
||||
|
||||
func resetWithDocker(execer utilsexec.Interface, dockerCheck preflight.Checker) {
|
||||
if _, errors := dockerCheck.Check(); len(errors) == 0 {
|
||||
if err := execer.Command("sh", "-c", "docker ps -a --filter name=k8s_ -q | xargs -r docker rm --force --volumes").Run(); err != nil {
|
||||
fmt.Println("[reset] Failed to stop the running containers.")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("[reset] Docker doesn't seem to be running. Skipping the removal of running Kubernetes containers.")
|
||||
}
|
||||
}
|
||||
|
||||
func resetWithCrictl(execer utilsexec.Interface, dockerCheck preflight.Checker, criSocketPath, crictlPath string) {
|
||||
if criSocketPath != "" {
|
||||
fmt.Printf("[reset] Cleaning up running containers using crictl with socket %s\n", criSocketPath)
|
||||
listcmd := fmt.Sprintf(crictlSandboxesParamsFormat, crictlPath, criSocketPath)
|
||||
output, err := execer.Command("sh", "-c", listcmd).CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Println("[reset] Failed to list running pods using crictl. Trying using docker instead.")
|
||||
resetWithDocker(execer, dockerCheck)
|
||||
return
|
||||
}
|
||||
sandboxes := strings.Split(string(output), " ")
|
||||
for _, s := range sandboxes {
|
||||
stopcmd := fmt.Sprintf(crictlStopParamsFormat, crictlPath, criSocketPath, s)
|
||||
if err := execer.Command("sh", "-c", stopcmd).Run(); err != nil {
|
||||
fmt.Println("[reset] Failed to stop the running containers using crictl. Trying using docker instead.")
|
||||
resetWithDocker(execer, dockerCheck)
|
||||
return
|
||||
}
|
||||
removecmd := fmt.Sprintf(crictlRemoveParamsFormat, crictlPath, criSocketPath, s)
|
||||
if err := execer.Command("sh", "-c", removecmd).Run(); err != nil {
|
||||
fmt.Println("[reset] Failed to remove the running containers using crictl. Trying using docker instead.")
|
||||
resetWithDocker(execer, dockerCheck)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Println("[reset] CRI socket path not provided for crictl. Trying docker instead.")
|
||||
resetWithDocker(execer, dockerCheck)
|
||||
}
|
||||
}
|
||||
|
||||
// cleanDir removes everything in a directory, but not the directory itself
|
||||
func cleanDir(filePath string) error {
|
||||
// If the directory doesn't even exist there's nothing to do, and we do
|
||||
// not consider this an error
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
d, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer d.Close()
|
||||
names, err := d.Readdirnames(-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, name := range names {
|
||||
if err = os.RemoveAll(filepath.Join(filePath, name)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// resetConfigDir is used to cleanup the files kubeadm writes in /etc/kubernetes/.
|
||||
func resetConfigDir(configPathDir, pkiPathDir string) {
|
||||
dirsToClean := []string{
|
||||
filepath.Join(configPathDir, kubeadmconstants.ManifestsSubDirName),
|
||||
pkiPathDir,
|
||||
}
|
||||
fmt.Printf("[reset] Deleting contents of config directories: %v\n", dirsToClean)
|
||||
for _, dir := range dirsToClean {
|
||||
if err := cleanDir(dir); err != nil {
|
||||
fmt.Printf("[reset] Failed to remove directory: %q [%v]\n", dir, err)
|
||||
}
|
||||
}
|
||||
|
||||
filesToClean := []string{
|
||||
filepath.Join(configPathDir, kubeadmconstants.AdminKubeConfigFileName),
|
||||
filepath.Join(configPathDir, kubeadmconstants.KubeletKubeConfigFileName),
|
||||
filepath.Join(configPathDir, kubeadmconstants.ControllerManagerKubeConfigFileName),
|
||||
filepath.Join(configPathDir, kubeadmconstants.SchedulerKubeConfigFileName),
|
||||
}
|
||||
fmt.Printf("[reset] Deleting files: %v\n", filesToClean)
|
||||
for _, path := range filesToClean {
|
||||
if err := os.RemoveAll(path); err != nil {
|
||||
fmt.Printf("[reset] Failed to remove file: %q [%v]\n", path, err)
|
||||
}
|
||||
}
|
||||
}
|
345
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset_test.go
generated
vendored
Normal file
345
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset_test.go
generated
vendored
Normal file
@ -0,0 +1,345 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
"k8s.io/utils/exec"
|
||||
fakeexec "k8s.io/utils/exec/testing"
|
||||
)
|
||||
|
||||
func assertExists(t *testing.T, path string) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
t.Errorf("file/directory does not exist; error: %s", err)
|
||||
t.Errorf("file/directory does not exist: %s", path)
|
||||
}
|
||||
}
|
||||
|
||||
func assertNotExists(t *testing.T, path string) {
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
t.Errorf("file/dir exists: %s", path)
|
||||
}
|
||||
}
|
||||
|
||||
// assertDirEmpty verifies a directory either does not exist, or is empty.
|
||||
func assertDirEmpty(t *testing.T, path string) {
|
||||
dac := preflight.DirAvailableCheck{Path: path}
|
||||
_, errors := dac.Check()
|
||||
if len(errors) != 0 {
|
||||
t.Errorf("directory not empty: [%v]", errors)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigDirCleaner(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
setupDirs []string
|
||||
setupFiles []string
|
||||
verifyExists []string
|
||||
verifyNotExists []string
|
||||
}{
|
||||
"simple reset": {
|
||||
setupDirs: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
},
|
||||
setupFiles: []string{
|
||||
"manifests/etcd.yaml",
|
||||
"manifests/kube-apiserver.yaml",
|
||||
"pki/ca.pem",
|
||||
kubeadmconstants.AdminKubeConfigFileName,
|
||||
kubeadmconstants.KubeletKubeConfigFileName,
|
||||
},
|
||||
verifyExists: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
},
|
||||
},
|
||||
"partial reset": {
|
||||
setupDirs: []string{
|
||||
"pki",
|
||||
},
|
||||
setupFiles: []string{
|
||||
"pki/ca.pem",
|
||||
kubeadmconstants.KubeletKubeConfigFileName,
|
||||
},
|
||||
verifyExists: []string{
|
||||
"pki",
|
||||
},
|
||||
verifyNotExists: []string{
|
||||
"manifests",
|
||||
},
|
||||
},
|
||||
"preserve cloud-config": {
|
||||
setupDirs: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
},
|
||||
setupFiles: []string{
|
||||
"manifests/etcd.yaml",
|
||||
"manifests/kube-apiserver.yaml",
|
||||
"pki/ca.pem",
|
||||
kubeadmconstants.AdminKubeConfigFileName,
|
||||
kubeadmconstants.KubeletKubeConfigFileName,
|
||||
"cloud-config",
|
||||
},
|
||||
verifyExists: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
"cloud-config",
|
||||
},
|
||||
},
|
||||
"preserve hidden files and directories": {
|
||||
setupDirs: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
".mydir",
|
||||
},
|
||||
setupFiles: []string{
|
||||
"manifests/etcd.yaml",
|
||||
"manifests/kube-apiserver.yaml",
|
||||
"pki/ca.pem",
|
||||
kubeadmconstants.AdminKubeConfigFileName,
|
||||
kubeadmconstants.KubeletKubeConfigFileName,
|
||||
".cloud-config",
|
||||
".mydir/.myfile",
|
||||
},
|
||||
verifyExists: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
".cloud-config",
|
||||
".mydir",
|
||||
".mydir/.myfile",
|
||||
},
|
||||
},
|
||||
"no-op reset": {
|
||||
verifyNotExists: []string{
|
||||
"pki",
|
||||
"manifests",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Logf("Running test: %s", name)
|
||||
|
||||
// Create a temporary directory for our fake config dir:
|
||||
tmpDir, err := ioutil.TempDir("", "kubeadm-reset-test")
|
||||
if err != nil {
|
||||
t.Errorf("Unable to create temporary directory: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
for _, createDir := range test.setupDirs {
|
||||
err := os.Mkdir(filepath.Join(tmpDir, createDir), 0700)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to setup test config directory: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, createFile := range test.setupFiles {
|
||||
fullPath := filepath.Join(tmpDir, createFile)
|
||||
f, err := os.Create(fullPath)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to create test file: %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
}
|
||||
|
||||
resetConfigDir(tmpDir, filepath.Join(tmpDir, "pki"))
|
||||
|
||||
// Verify the files we cleanup implicitly in every test:
|
||||
assertExists(t, tmpDir)
|
||||
assertNotExists(t, filepath.Join(tmpDir, kubeadmconstants.AdminKubeConfigFileName))
|
||||
assertNotExists(t, filepath.Join(tmpDir, kubeadmconstants.KubeletKubeConfigFileName))
|
||||
assertDirEmpty(t, filepath.Join(tmpDir, "manifests"))
|
||||
assertDirEmpty(t, filepath.Join(tmpDir, "pki"))
|
||||
|
||||
// Verify the files as requested by the test:
|
||||
for _, path := range test.verifyExists {
|
||||
assertExists(t, filepath.Join(tmpDir, path))
|
||||
}
|
||||
for _, path := range test.verifyNotExists {
|
||||
assertNotExists(t, filepath.Join(tmpDir, path))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type fakeDockerChecker struct {
|
||||
warnings []error
|
||||
errors []error
|
||||
}
|
||||
|
||||
func (c *fakeDockerChecker) Check() (warnings, errors []error) {
|
||||
return c.warnings, c.errors
|
||||
}
|
||||
|
||||
func (c *fakeDockerChecker) Name() string {
|
||||
return "FakeDocker"
|
||||
}
|
||||
|
||||
func newFakeDockerChecker(warnings, errors []error) preflight.Checker {
|
||||
return &fakeDockerChecker{warnings: warnings, errors: errors}
|
||||
}
|
||||
|
||||
func TestResetWithDocker(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
RunScript: []fakeexec.FakeRunAction{
|
||||
func() ([]byte, []byte, error) { return nil, nil, nil },
|
||||
func() ([]byte, []byte, error) { return nil, nil, errors.New("docker error") },
|
||||
func() ([]byte, []byte, error) { return nil, 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...) },
|
||||
},
|
||||
}
|
||||
resetWithDocker(&fexec, newFakeDockerChecker(nil, nil))
|
||||
if fcmd.RunCalls != 1 {
|
||||
t.Errorf("expected 1 call to Run, got %d", fcmd.RunCalls)
|
||||
}
|
||||
resetWithDocker(&fexec, newFakeDockerChecker(nil, nil))
|
||||
if fcmd.RunCalls != 2 {
|
||||
t.Errorf("expected 2 calls to Run, got %d", fcmd.RunCalls)
|
||||
}
|
||||
resetWithDocker(&fexec, newFakeDockerChecker(nil, []error{errors.New("test error")}))
|
||||
if fcmd.RunCalls != 2 {
|
||||
t.Errorf("expected 2 calls to Run, got %d", fcmd.RunCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResetWithCrictl(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||
// 2: socket path provided, not runnning with crictl (1x CombinedOutput, 2x Run)
|
||||
func() ([]byte, error) { return []byte("1"), nil },
|
||||
// 3: socket path provided, crictl fails, reset with docker (1x CombinedOuput fail, 1x Run)
|
||||
func() ([]byte, error) { return nil, errors.New("crictl list err") },
|
||||
},
|
||||
RunScript: []fakeexec.FakeRunAction{
|
||||
// 1: socket path not provided, running with docker
|
||||
func() ([]byte, []byte, error) { return nil, nil, nil },
|
||||
// 2: socket path provided, now runnning with crictl (1x CombinedOutput, 2x Run)
|
||||
func() ([]byte, []byte, error) { return nil, nil, nil },
|
||||
func() ([]byte, []byte, error) { return nil, nil, nil },
|
||||
// 3: socket path provided, crictl fails, reset with docker (1x CombinedOuput, 1x Run)
|
||||
func() ([]byte, []byte, error) { return nil, nil, nil },
|
||||
// 4: running with no socket and docker fails (1x Run)
|
||||
func() ([]byte, []byte, error) { return nil, 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...) },
|
||||
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...) },
|
||||
},
|
||||
}
|
||||
|
||||
// 1: socket path not provided, running with docker
|
||||
resetWithCrictl(&fexec, newFakeDockerChecker(nil, nil), "", "crictl")
|
||||
if fcmd.RunCalls != 1 {
|
||||
t.Errorf("expected 1 call to Run, got %d", fcmd.RunCalls)
|
||||
}
|
||||
if !strings.Contains(fcmd.RunLog[0][2], "docker") {
|
||||
t.Errorf("expected a call to docker, got %v", fcmd.RunLog[0])
|
||||
}
|
||||
|
||||
// 2: socket path provided, now runnning with crictl (1x CombinedOutput, 2x Run)
|
||||
resetWithCrictl(&fexec, newFakeDockerChecker(nil, nil), "/test.sock", "crictl")
|
||||
if fcmd.RunCalls != 3 {
|
||||
t.Errorf("expected 3 calls to Run, got %d", fcmd.RunCalls)
|
||||
}
|
||||
if !strings.Contains(fcmd.RunLog[1][2], "crictl") {
|
||||
t.Errorf("expected a call to crictl, got %v", fcmd.RunLog[0])
|
||||
}
|
||||
if !strings.Contains(fcmd.RunLog[2][2], "crictl") {
|
||||
t.Errorf("expected a call to crictl, got %v", fcmd.RunLog[0])
|
||||
}
|
||||
|
||||
// 3: socket path provided, crictl fails, reset with docker
|
||||
resetWithCrictl(&fexec, newFakeDockerChecker(nil, nil), "/test.sock", "crictl")
|
||||
if fcmd.RunCalls != 4 {
|
||||
t.Errorf("expected 4 calls to Run, got %d", fcmd.RunCalls)
|
||||
}
|
||||
if !strings.Contains(fcmd.RunLog[3][2], "docker") {
|
||||
t.Errorf("expected a call to docker, got %v", fcmd.RunLog[0])
|
||||
}
|
||||
|
||||
// 4: running with no socket and docker fails (1x Run)
|
||||
resetWithCrictl(&fexec, newFakeDockerChecker(nil, []error{errors.New("test error")}), "", "crictl")
|
||||
if fcmd.RunCalls != 4 {
|
||||
t.Errorf("expected 4 calls to Run, got %d", fcmd.RunCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReset(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||
func() ([]byte, error) { return []byte("1"), nil },
|
||||
func() ([]byte, error) { return []byte("1"), nil },
|
||||
func() ([]byte, error) { return []byte("1"), nil },
|
||||
},
|
||||
RunScript: []fakeexec.FakeRunAction{
|
||||
func() ([]byte, []byte, error) { return nil, nil, nil },
|
||||
func() ([]byte, []byte, error) { return nil, nil, nil },
|
||||
func() ([]byte, []byte, error) { return nil, 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...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
},
|
||||
LookPathFunc: func(cmd string) (string, error) { return cmd, nil },
|
||||
}
|
||||
|
||||
reset(&fexec, newFakeDockerChecker(nil, nil), "/test.sock")
|
||||
if fcmd.RunCalls != 2 {
|
||||
t.Errorf("expected 2 call to Run, got %d", fcmd.RunCalls)
|
||||
}
|
||||
if !strings.Contains(fcmd.RunLog[0][2], "crictl") {
|
||||
t.Errorf("expected a call to crictl, got %v", fcmd.RunLog[0])
|
||||
}
|
||||
|
||||
fexec.LookPathFunc = func(cmd string) (string, error) { return "", errors.New("no crictl") }
|
||||
reset(&fexec, newFakeDockerChecker(nil, nil), "/test.sock")
|
||||
if fcmd.RunCalls != 3 {
|
||||
t.Errorf("expected 3 calls to Run, got %d", fcmd.RunCalls)
|
||||
}
|
||||
if !strings.Contains(fcmd.RunLog[2][2], "docker") {
|
||||
t.Errorf("expected a call to docker, got %v", fcmd.RunLog[0])
|
||||
}
|
||||
}
|
444
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token.go
generated
vendored
Normal file
444
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token.go
generated
vendored
Normal file
@ -0,0 +1,444 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcertutil "k8s.io/client-go/util/cert"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
tokenphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
||||
tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
)
|
||||
|
||||
var joinCommandTemplate = template.Must(template.New("join").Parse(`` +
|
||||
`kubeadm join --token {{.Token}} {{.MasterHostPort}}{{range $h := .CAPubKeyPins}} --discovery-token-ca-cert-hash {{$h}}{{end}}`,
|
||||
))
|
||||
|
||||
// NewCmdToken returns cobra.Command for token management
|
||||
func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command {
|
||||
var kubeConfigFile string
|
||||
var dryRun bool
|
||||
tokenCmd := &cobra.Command{
|
||||
Use: "token",
|
||||
Short: "Manage bootstrap tokens.",
|
||||
Long: dedent.Dedent(`
|
||||
This command manages bootstrap tokens. It is optional and needed only for advanced use cases.
|
||||
|
||||
In short, bootstrap tokens are used for establishing bidirectional trust between a client and a server.
|
||||
A bootstrap token can be used when a client (for example a node that is about to join the cluster) needs
|
||||
to trust the server it is talking to. Then a bootstrap token with the "signing" usage can be used.
|
||||
bootstrap tokens can also function as a way to allow short-lived authentication to the API Server
|
||||
(the token serves as a way for the API Server to trust the client), for example for doing the TLS Bootstrap.
|
||||
|
||||
What is a bootstrap token more exactly?
|
||||
- It is a Secret in the kube-system namespace of type "bootstrap.kubernetes.io/token".
|
||||
- A bootstrap token must be of the form "[a-z0-9]{6}.[a-z0-9]{16}". The former part is the public token ID,
|
||||
while the latter is the Token Secret and it must be kept private at all circumstances!
|
||||
- The name of the Secret must be named "bootstrap-token-(token-id)".
|
||||
|
||||
You can read more about bootstrap tokens here:
|
||||
https://kubernetes.io/docs/admin/bootstrap-tokens/
|
||||
`),
|
||||
|
||||
// Without this callback, if a user runs just the "token"
|
||||
// command without a subcommand, or with an invalid subcommand,
|
||||
// cobra will print usage information, but still exit cleanly.
|
||||
// We want to return an error code in these cases so that the
|
||||
// user knows that their command was invalid.
|
||||
RunE: cmdutil.SubCmdRunE("token"),
|
||||
}
|
||||
|
||||
tokenCmd.PersistentFlags().StringVar(&kubeConfigFile,
|
||||
"kubeconfig", "/etc/kubernetes/admin.conf", "The KubeConfig file to use when talking to the cluster")
|
||||
tokenCmd.PersistentFlags().BoolVar(&dryRun,
|
||||
"dry-run", dryRun, "Whether to enable dry-run mode or not")
|
||||
|
||||
var usages []string
|
||||
var extraGroups []string
|
||||
var tokenDuration time.Duration
|
||||
var description string
|
||||
var printJoinCommand bool
|
||||
createCmd := &cobra.Command{
|
||||
Use: "create [token]",
|
||||
Short: "Create bootstrap tokens on the server.",
|
||||
Long: dedent.Dedent(`
|
||||
This command will create a bootstrap token for you.
|
||||
You can specify the usages for this token, the "time to live" and an optional human friendly description.
|
||||
|
||||
The [token] is the actual token to write.
|
||||
This should be a securely generated random token of the form "[a-z0-9]{6}.[a-z0-9]{16}".
|
||||
If no [token] is given, kubeadm will generate a random token instead.
|
||||
`),
|
||||
Run: func(tokenCmd *cobra.Command, args []string) {
|
||||
token := ""
|
||||
if len(args) != 0 {
|
||||
token = args[0]
|
||||
}
|
||||
client, err := getClientset(kubeConfigFile, dryRun)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = RunCreateToken(out, client, token, tokenDuration, usages, extraGroups, description, printJoinCommand, kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
createCmd.Flags().DurationVar(&tokenDuration,
|
||||
"ttl", kubeadmconstants.DefaultTokenDuration, "The duration before the token is automatically deleted (e.g. 1s, 2m, 3h). If set to '0', the token will never expire.")
|
||||
createCmd.Flags().StringSliceVar(&usages,
|
||||
"usages", kubeadmconstants.DefaultTokenUsages, fmt.Sprintf("Describes the ways in which this token can be used. You can pass --usages multiple times or provide a comma separated list of options. Valid options: [%s].", strings.Join(kubeadmconstants.DefaultTokenUsages, ",")))
|
||||
createCmd.Flags().StringSliceVar(&extraGroups,
|
||||
"groups", []string{kubeadmconstants.NodeBootstrapTokenAuthGroup},
|
||||
fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q.", bootstrapapi.BootstrapGroupPattern))
|
||||
createCmd.Flags().StringVar(&description,
|
||||
"description", "", "A human friendly description of how this token is used.")
|
||||
createCmd.Flags().BoolVar(&printJoinCommand,
|
||||
"print-join-command", false, "Instead of printing only the token, print the full 'kubeadm join' flag needed to join the cluster using the token.")
|
||||
tokenCmd.AddCommand(createCmd)
|
||||
|
||||
tokenCmd.AddCommand(NewCmdTokenGenerate(out))
|
||||
|
||||
listCmd := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List bootstrap tokens on the server.",
|
||||
Long: dedent.Dedent(`
|
||||
This command will list all bootstrap tokens for you.
|
||||
`),
|
||||
Run: func(tokenCmd *cobra.Command, args []string) {
|
||||
client, err := getClientset(kubeConfigFile, dryRun)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = RunListTokens(out, errW, client)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
tokenCmd.AddCommand(listCmd)
|
||||
|
||||
deleteCmd := &cobra.Command{
|
||||
Use: "delete [token-value]",
|
||||
Short: "Delete bootstrap tokens on the server.",
|
||||
Long: dedent.Dedent(`
|
||||
This command will delete a given bootstrap token for you.
|
||||
|
||||
The [token-value] is the full Token of the form "[a-z0-9]{6}.[a-z0-9]{16}" or the
|
||||
Token ID of the form "[a-z0-9]{6}" to delete.
|
||||
`),
|
||||
Run: func(tokenCmd *cobra.Command, args []string) {
|
||||
if len(args) < 1 {
|
||||
kubeadmutil.CheckErr(fmt.Errorf("missing subcommand; 'token delete' is missing token of form [%q]", tokenutil.TokenIDRegexpString))
|
||||
}
|
||||
client, err := getClientset(kubeConfigFile, dryRun)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = RunDeleteToken(out, client, args[0])
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
tokenCmd.AddCommand(deleteCmd)
|
||||
|
||||
return tokenCmd
|
||||
}
|
||||
|
||||
// NewCmdTokenGenerate returns cobra.Command to generate new token
|
||||
func NewCmdTokenGenerate(out io.Writer) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "Generate and print a bootstrap token, but do not create it on the server.",
|
||||
Long: dedent.Dedent(`
|
||||
This command will print out a randomly-generated bootstrap token that can be used with
|
||||
the "init" and "join" commands.
|
||||
|
||||
You don't have to use this command in order to generate a token. You can do so
|
||||
yourself as long as it is in the format "[a-z0-9]{6}.[a-z0-9]{16}". This
|
||||
command is provided for convenience to generate tokens in the given format.
|
||||
|
||||
You can also use "kubeadm init" without specifying a token and it will
|
||||
generate and print one for you.
|
||||
`),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunGenerateToken(out)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// RunCreateToken generates a new bootstrap token and stores it as a secret on the server.
|
||||
func RunCreateToken(out io.Writer, client clientset.Interface, token string, tokenDuration time.Duration, usages []string, extraGroups []string, description string, printJoinCommand bool, kubeConfigFile string) error {
|
||||
if len(token) == 0 {
|
||||
var err error
|
||||
token, err = tokenutil.GenerateToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
_, _, err := tokenutil.ParseToken(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// adding groups only makes sense for authentication
|
||||
usagesSet := sets.NewString(usages...)
|
||||
usageAuthentication := strings.TrimPrefix(bootstrapapi.BootstrapTokenUsageAuthentication, bootstrapapi.BootstrapTokenUsagePrefix)
|
||||
if len(extraGroups) > 0 && !usagesSet.Has(usageAuthentication) {
|
||||
return fmt.Errorf("--groups cannot be specified unless --usages includes %q", usageAuthentication)
|
||||
}
|
||||
|
||||
// validate any extra group names
|
||||
for _, group := range extraGroups {
|
||||
if err := bootstrapapi.ValidateBootstrapGroupName(group); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// validate usages
|
||||
if err := bootstrapapi.ValidateUsages(usages); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := tokenphase.CreateNewToken(client, token, tokenDuration, usages, extraGroups, description)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if --print-join-command was specified, print the full `kubeadm join` command
|
||||
// otherwise, just print the token
|
||||
if printJoinCommand {
|
||||
joinCommand, err := getJoinCommand(token, kubeConfigFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get join command: %v", err)
|
||||
}
|
||||
fmt.Fprintln(out, joinCommand)
|
||||
} else {
|
||||
fmt.Fprintln(out, token)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunGenerateToken just generates a random token for the user
|
||||
func RunGenerateToken(out io.Writer) error {
|
||||
token, err := tokenutil.GenerateToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(out, token)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunListTokens lists details on all existing bootstrap tokens on the server.
|
||||
func RunListTokens(out io.Writer, errW io.Writer, client clientset.Interface) error {
|
||||
// First, build our selector for bootstrap tokens only
|
||||
tokenSelector := fields.SelectorFromSet(
|
||||
map[string]string{
|
||||
api.SecretTypeField: string(bootstrapapi.SecretTypeBootstrapToken),
|
||||
},
|
||||
)
|
||||
listOptions := metav1.ListOptions{
|
||||
FieldSelector: tokenSelector.String(),
|
||||
}
|
||||
|
||||
secrets, err := client.CoreV1().Secrets(metav1.NamespaceSystem).List(listOptions)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list bootstrap tokens [%v]", err)
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(out, 10, 4, 3, ' ', 0)
|
||||
fmt.Fprintln(w, "TOKEN\tTTL\tEXPIRES\tUSAGES\tDESCRIPTION\tEXTRA GROUPS")
|
||||
for _, secret := range secrets.Items {
|
||||
tokenID := getSecretString(&secret, bootstrapapi.BootstrapTokenIDKey)
|
||||
if len(tokenID) == 0 {
|
||||
fmt.Fprintf(errW, "bootstrap token has no token-id data: %s\n", secret.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
// enforce the right naming convention
|
||||
if secret.Name != fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenID) {
|
||||
fmt.Fprintf(errW, "bootstrap token name is not of the form '%s(token-id)': %s\n", bootstrapapi.BootstrapTokenSecretPrefix, secret.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
tokenSecret := getSecretString(&secret, bootstrapapi.BootstrapTokenSecretKey)
|
||||
if len(tokenSecret) == 0 {
|
||||
fmt.Fprintf(errW, "bootstrap token has no token-secret data: %s\n", secret.Name)
|
||||
continue
|
||||
}
|
||||
td := &kubeadmapi.TokenDiscovery{ID: tokenID, Secret: tokenSecret}
|
||||
|
||||
// Expiration time is optional, if not specified this implies the token
|
||||
// never expires.
|
||||
ttl := "<forever>"
|
||||
expires := "<never>"
|
||||
secretExpiration := getSecretString(&secret, bootstrapapi.BootstrapTokenExpirationKey)
|
||||
if len(secretExpiration) > 0 {
|
||||
expireTime, err := time.Parse(time.RFC3339, secretExpiration)
|
||||
if err != nil {
|
||||
fmt.Fprintf(errW, "can't parse expiration time of bootstrap token %s\n", secret.Name)
|
||||
continue
|
||||
}
|
||||
ttl = printers.ShortHumanDuration(expireTime.Sub(time.Now()))
|
||||
expires = expireTime.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
usages := []string{}
|
||||
for k, v := range secret.Data {
|
||||
// Skip all fields that don't include this prefix
|
||||
if !strings.HasPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix) {
|
||||
continue
|
||||
}
|
||||
// Skip those that don't have this usage set to true
|
||||
if string(v) != "true" {
|
||||
continue
|
||||
}
|
||||
usages = append(usages, strings.TrimPrefix(k, bootstrapapi.BootstrapTokenUsagePrefix))
|
||||
}
|
||||
sort.Strings(usages)
|
||||
usageString := strings.Join(usages, ",")
|
||||
if len(usageString) == 0 {
|
||||
usageString = "<none>"
|
||||
}
|
||||
|
||||
description := getSecretString(&secret, bootstrapapi.BootstrapTokenDescriptionKey)
|
||||
if len(description) == 0 {
|
||||
description = "<none>"
|
||||
}
|
||||
|
||||
groups := getSecretString(&secret, bootstrapapi.BootstrapTokenExtraGroupsKey)
|
||||
if len(groups) == 0 {
|
||||
groups = "<none>"
|
||||
}
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n", tokenutil.BearerToken(td), ttl, expires, usageString, description, groups)
|
||||
}
|
||||
w.Flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunDeleteToken removes a bootstrap token from the server.
|
||||
func RunDeleteToken(out io.Writer, client clientset.Interface, tokenIDOrToken string) error {
|
||||
// Assume the given first argument is a token id and try to parse it
|
||||
tokenID := tokenIDOrToken
|
||||
if err := tokenutil.ParseTokenID(tokenIDOrToken); err != nil {
|
||||
if tokenID, _, err = tokenutil.ParseToken(tokenIDOrToken); err != nil {
|
||||
return fmt.Errorf("given token or token id %q didn't match pattern [%q] or [%q]", tokenIDOrToken, tokenutil.TokenIDRegexpString, tokenutil.TokenRegexpString)
|
||||
}
|
||||
}
|
||||
|
||||
tokenSecretName := fmt.Sprintf("%s%s", bootstrapapi.BootstrapTokenSecretPrefix, tokenID)
|
||||
if err := client.CoreV1().Secrets(metav1.NamespaceSystem).Delete(tokenSecretName, nil); err != nil {
|
||||
return fmt.Errorf("failed to delete bootstrap token [%v]", err)
|
||||
}
|
||||
fmt.Fprintf(out, "bootstrap token with id %q deleted\n", tokenID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSecretString(secret *v1.Secret, key string) string {
|
||||
if secret.Data == nil {
|
||||
return ""
|
||||
}
|
||||
if val, ok := secret.Data[key]; ok {
|
||||
return string(val)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getClientset(file string, dryRun bool) (clientset.Interface, error) {
|
||||
if dryRun {
|
||||
dryRunGetter, err := apiclient.NewClientBackedDryRunGetterFromKubeconfig(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return apiclient.NewDryRunClient(dryRunGetter, os.Stdout), nil
|
||||
}
|
||||
client, err := kubeconfigutil.ClientSetFromFile(file)
|
||||
return client, err
|
||||
}
|
||||
|
||||
func getJoinCommand(token string, kubeConfigFile string) (string, error) {
|
||||
// load the kubeconfig file to get the CA certificate and endpoint
|
||||
config, err := clientcmd.LoadFromFile(kubeConfigFile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to load kubeconfig: %v", err)
|
||||
}
|
||||
|
||||
// load the default cluster config
|
||||
clusterConfig := kubeconfigutil.GetClusterFromKubeConfig(config)
|
||||
if clusterConfig == nil {
|
||||
return "", fmt.Errorf("failed to get default cluster config")
|
||||
}
|
||||
|
||||
// load CA certificates from the kubeconfig (either from PEM data or by file path)
|
||||
var caCerts []*x509.Certificate
|
||||
if clusterConfig.CertificateAuthorityData != nil {
|
||||
caCerts, err = clientcertutil.ParseCertsPEM(clusterConfig.CertificateAuthorityData)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse CA certificate from kubeconfig: %v", err)
|
||||
}
|
||||
} else if clusterConfig.CertificateAuthority != "" {
|
||||
caCerts, err = clientcertutil.CertsFromFile(clusterConfig.CertificateAuthority)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to load CA certificate referenced by kubeconfig: %v", err)
|
||||
}
|
||||
} else {
|
||||
return "", fmt.Errorf("no CA certificates found in kubeconfig")
|
||||
}
|
||||
|
||||
// hash all the CA certs and include their public key pins as trusted values
|
||||
publicKeyPins := make([]string, 0, len(caCerts))
|
||||
for _, caCert := range caCerts {
|
||||
publicKeyPins = append(publicKeyPins, pubkeypin.Hash(caCert))
|
||||
}
|
||||
|
||||
ctx := map[string]interface{}{
|
||||
"Token": token,
|
||||
"CAPubKeyPins": publicKeyPins,
|
||||
"MasterHostPort": strings.Replace(clusterConfig.Server, "https://", "", -1),
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
err = joinCommandTemplate.Execute(&out, ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to render join command template: %v", err)
|
||||
}
|
||||
return out.String(), nil
|
||||
}
|
46
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token_test.go
generated
vendored
Normal file
46
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token_test.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
TokenExpectedRegex = "^\\S{6}\\.\\S{16}\n$"
|
||||
)
|
||||
|
||||
func TestRunGenerateToken(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
|
||||
err := RunGenerateToken(&buf)
|
||||
if err != nil {
|
||||
t.Errorf("RunGenerateToken returned an error: %v", err)
|
||||
}
|
||||
|
||||
output := buf.String()
|
||||
|
||||
matched, err := regexp.MatchString(TokenExpectedRegex, output)
|
||||
if err != nil {
|
||||
t.Fatalf("encountered an error while trying to match RunGenerateToken's output: %v", err)
|
||||
}
|
||||
if !matched {
|
||||
t.Errorf("RunGenerateToken's output did not match expected regex; wanted: [%s], got: [%s]", TokenExpectedRegex, output)
|
||||
}
|
||||
}
|
65
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/BUILD
generated
vendored
Normal file
65
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/BUILD
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"apply.go",
|
||||
"common.go",
|
||||
"plan.go",
|
||||
"upgrade.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade",
|
||||
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/validation: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/controlplane:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/upgrade: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/dryrun:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/util/version:go_default_library",
|
||||
"//vendor/github.com/ghodss/yaml:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/client-go/discovery/fake:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"apply_test.go",
|
||||
"common_test.go",
|
||||
"plan_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/upgrade: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"],
|
||||
)
|
280
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go
generated
vendored
Normal file
280
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go
generated
vendored
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
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 upgrade
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/controlplane"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
const (
|
||||
upgradeManifestTimeout = 1 * time.Minute
|
||||
)
|
||||
|
||||
// applyFlags holds the information about the flags that can be passed to apply
|
||||
type applyFlags struct {
|
||||
nonInteractiveMode bool
|
||||
force bool
|
||||
dryRun bool
|
||||
etcdUpgrade bool
|
||||
newK8sVersionStr string
|
||||
newK8sVersion *version.Version
|
||||
imagePullTimeout time.Duration
|
||||
parent *cmdUpgradeFlags
|
||||
}
|
||||
|
||||
// SessionIsInteractive returns true if the session is of an interactive type (the default, can be opted out of with -y, -f or --dry-run)
|
||||
func (f *applyFlags) SessionIsInteractive() bool {
|
||||
return !f.nonInteractiveMode
|
||||
}
|
||||
|
||||
// NewCmdApply returns the cobra command for `kubeadm upgrade apply`
|
||||
func NewCmdApply(parentFlags *cmdUpgradeFlags) *cobra.Command {
|
||||
flags := &applyFlags{
|
||||
parent: parentFlags,
|
||||
imagePullTimeout: 15 * time.Minute,
|
||||
etcdUpgrade: true,
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "apply [version]",
|
||||
Short: "Upgrade your Kubernetes cluster to the specified version.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
flags.parent.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(flags.parent.ignorePreflightErrors, flags.parent.skipPreFlight)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// Ensure the user is root
|
||||
err = runPreflightChecks(flags.parent.ignorePreflightErrorsSet)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = cmdutil.ValidateExactArgNumber(args, []string{"version"})
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
// It's safe to use args[0] here as the slice has been validated above
|
||||
flags.newK8sVersionStr = args[0]
|
||||
|
||||
// Default the flags dynamically, based on each others' value
|
||||
err = SetImplicitFlags(flags)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = RunApply(flags)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
// Specify the valid flags specific for apply
|
||||
cmd.Flags().BoolVarP(&flags.nonInteractiveMode, "yes", "y", flags.nonInteractiveMode, "Perform the upgrade and do not prompt for confirmation (non-interactive mode).")
|
||||
cmd.Flags().BoolVarP(&flags.force, "force", "f", flags.force, "Force upgrading although some requirements might not be met. This also implies non-interactive mode.")
|
||||
cmd.Flags().BoolVar(&flags.dryRun, "dry-run", flags.dryRun, "Do not change any state, just output what actions would be performed.")
|
||||
cmd.Flags().BoolVar(&flags.etcdUpgrade, "etcd-upgrade", flags.etcdUpgrade, "Perform the upgrade of etcd.")
|
||||
cmd.Flags().DurationVar(&flags.imagePullTimeout, "image-pull-timeout", flags.imagePullTimeout, "The maximum amount of time to wait for the control plane pods to be downloaded.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunApply takes care of the actual upgrade functionality
|
||||
// It does the following things:
|
||||
// - Checks if the cluster is healthy
|
||||
// - Gets the configuration from the kubeadm-config ConfigMap in the cluster
|
||||
// - Enforces all version skew policies
|
||||
// - Asks the user if they really want to upgrade
|
||||
// - Makes sure the control plane images are available locally on the master(s)
|
||||
// - Upgrades the control plane components
|
||||
// - Applies the other resources that'd be created with kubeadm init as well, like
|
||||
// - Creating the RBAC rules for the bootstrap tokens and the cluster-info ConfigMap
|
||||
// - Applying new kube-dns and kube-proxy manifests
|
||||
// - Uploads the newly used configuration to the cluster ConfigMap
|
||||
func RunApply(flags *applyFlags) error {
|
||||
|
||||
// Start with the basics, verify that the cluster is healthy and get the configuration from the cluster (using the ConfigMap)
|
||||
upgradeVars, err := enforceRequirements(flags.parent, flags.dryRun, flags.newK8sVersionStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Grab the external, versioned configuration and convert it to the internal type for usage here later
|
||||
internalcfg := &kubeadmapi.MasterConfiguration{}
|
||||
legacyscheme.Scheme.Convert(upgradeVars.cfg, internalcfg, nil)
|
||||
|
||||
// Validate requested and validate actual version
|
||||
if err := configutil.NormalizeKubernetesVersion(internalcfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Use normalized version string in all following code.
|
||||
flags.newK8sVersionStr = internalcfg.KubernetesVersion
|
||||
k8sVer, err := version.ParseSemantic(flags.newK8sVersionStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse normalized version %q as a semantic version", flags.newK8sVersionStr)
|
||||
}
|
||||
flags.newK8sVersion = k8sVer
|
||||
|
||||
if err := features.ValidateVersion(features.InitFeatureGates, internalcfg.FeatureGates, internalcfg.KubernetesVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Enforce the version skew policies
|
||||
if err := EnforceVersionPolicies(flags, upgradeVars.versionGetter); err != nil {
|
||||
return fmt.Errorf("[upgrade/version] FATAL: %v", err)
|
||||
}
|
||||
|
||||
// If the current session is interactive, ask the user whether they really want to upgrade
|
||||
if flags.SessionIsInteractive() {
|
||||
if err := InteractivelyConfirmUpgrade("Are you sure you want to proceed with the upgrade?"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Use a prepuller implementation based on creating DaemonSets
|
||||
// and block until all DaemonSets are ready; then we know for sure that all control plane images are cached locally
|
||||
prepuller := upgrade.NewDaemonSetPrepuller(upgradeVars.client, upgradeVars.waiter, internalcfg)
|
||||
upgrade.PrepullImagesInParallel(prepuller, flags.imagePullTimeout)
|
||||
|
||||
// Now; perform the upgrade procedure
|
||||
if err := PerformControlPlaneUpgrade(flags, upgradeVars.client, upgradeVars.waiter, internalcfg); err != nil {
|
||||
return fmt.Errorf("[upgrade/apply] FATAL: %v", err)
|
||||
}
|
||||
|
||||
// Upgrade RBAC rules and addons.
|
||||
if err := upgrade.PerformPostUpgradeTasks(upgradeVars.client, internalcfg, flags.newK8sVersion, flags.dryRun); err != nil {
|
||||
return fmt.Errorf("[upgrade/postupgrade] FATAL post-upgrade error: %v", err)
|
||||
}
|
||||
|
||||
if flags.dryRun {
|
||||
fmt.Println("[dryrun] Finished dryrunning successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
fmt.Printf("[upgrade/successful] SUCCESS! Your cluster was upgraded to %q. Enjoy!\n", flags.newK8sVersionStr)
|
||||
fmt.Println("")
|
||||
fmt.Println("[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets in turn.")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetImplicitFlags handles dynamically defaulting flags based on each other's value
|
||||
func SetImplicitFlags(flags *applyFlags) error {
|
||||
// If we are in dry-run or force mode; we should automatically execute this command non-interactively
|
||||
if flags.dryRun || flags.force {
|
||||
flags.nonInteractiveMode = true
|
||||
}
|
||||
|
||||
if len(flags.newK8sVersionStr) == 0 {
|
||||
return fmt.Errorf("version string can't be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnforceVersionPolicies makes sure that the version the user specified is valid to upgrade to
|
||||
// There are both fatal and skippable (with --force) errors
|
||||
func EnforceVersionPolicies(flags *applyFlags, versionGetter upgrade.VersionGetter) error {
|
||||
fmt.Printf("[upgrade/version] You have chosen to change the cluster version to %q\n", flags.newK8sVersionStr)
|
||||
|
||||
versionSkewErrs := upgrade.EnforceVersionPolicies(versionGetter, flags.newK8sVersionStr, flags.newK8sVersion, flags.parent.allowExperimentalUpgrades, flags.parent.allowRCUpgrades)
|
||||
if versionSkewErrs != nil {
|
||||
|
||||
if len(versionSkewErrs.Mandatory) > 0 {
|
||||
return fmt.Errorf("The --version argument is invalid due to these fatal errors:\n\n%v\nPlease fix the misalignments highlighted above and try upgrading again", kubeadmutil.FormatErrMsg(versionSkewErrs.Mandatory))
|
||||
}
|
||||
|
||||
if len(versionSkewErrs.Skippable) > 0 {
|
||||
// Return the error if the user hasn't specified the --force flag
|
||||
if !flags.force {
|
||||
return fmt.Errorf("The --version argument is invalid due to these errors:\n\n%v\nCan be bypassed if you pass the --force flag", kubeadmutil.FormatErrMsg(versionSkewErrs.Skippable))
|
||||
}
|
||||
// Soft errors found, but --force was specified
|
||||
fmt.Printf("[upgrade/version] Found %d potential version compatibility errors but skipping since the --force flag is set: \n\n%v", len(versionSkewErrs.Skippable), kubeadmutil.FormatErrMsg(versionSkewErrs.Skippable))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PerformControlPlaneUpgrade actually performs the upgrade procedure for the cluster of your type (self-hosted or static-pod-hosted)
|
||||
func PerformControlPlaneUpgrade(flags *applyFlags, client clientset.Interface, waiter apiclient.Waiter, internalcfg *kubeadmapi.MasterConfiguration) error {
|
||||
|
||||
// Check if the cluster is self-hosted and act accordingly
|
||||
if upgrade.IsControlPlaneSelfHosted(client) {
|
||||
fmt.Printf("[upgrade/apply] Upgrading your Self-Hosted control plane to version %q...\n", flags.newK8sVersionStr)
|
||||
|
||||
// Upgrade the self-hosted cluster
|
||||
return upgrade.SelfHostedControlPlane(client, waiter, internalcfg, flags.newK8sVersion)
|
||||
}
|
||||
|
||||
// OK, the cluster is hosted using static pods. Upgrade a static-pod hosted cluster
|
||||
fmt.Printf("[upgrade/apply] Upgrading your Static Pod-hosted control plane to version %q...\n", flags.newK8sVersionStr)
|
||||
|
||||
if flags.dryRun {
|
||||
return DryRunStaticPodUpgrade(internalcfg)
|
||||
}
|
||||
|
||||
return PerformStaticPodUpgrade(client, waiter, internalcfg, flags.etcdUpgrade)
|
||||
}
|
||||
|
||||
// PerformStaticPodUpgrade performs the upgrade of the control plane components for a static pod hosted cluster
|
||||
func PerformStaticPodUpgrade(client clientset.Interface, waiter apiclient.Waiter, internalcfg *kubeadmapi.MasterConfiguration, etcdUpgrade bool) error {
|
||||
pathManager, err := upgrade.NewKubeStaticPodPathManagerUsingTempDirs(constants.GetStaticPodDirectory())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return upgrade.StaticPodControlPlane(waiter, pathManager, internalcfg, etcdUpgrade)
|
||||
}
|
||||
|
||||
// DryRunStaticPodUpgrade fakes an upgrade of the control plane
|
||||
func DryRunStaticPodUpgrade(internalcfg *kubeadmapi.MasterConfiguration) error {
|
||||
|
||||
dryRunManifestDir, err := constants.CreateTempDirForKubeadm("kubeadm-upgrade-dryrun")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(dryRunManifestDir)
|
||||
|
||||
if err := controlplane.CreateInitStaticPodManifestFiles(dryRunManifestDir, internalcfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Print the contents of the upgraded manifests and pretend like they were in /etc/kubernetes/manifests
|
||||
files := []dryrunutil.FileToPrint{}
|
||||
for _, component := range constants.MasterComponents {
|
||||
realPath := constants.GetStaticPodFilepath(component, dryRunManifestDir)
|
||||
outputPath := constants.GetStaticPodFilepath(component, constants.GetStaticPodDirectory())
|
||||
files = append(files, dryrunutil.NewFileToPrint(realPath, outputPath))
|
||||
}
|
||||
|
||||
return dryrunutil.PrintDryRunFiles(files, os.Stdout)
|
||||
}
|
147
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply_test.go
generated
vendored
Normal file
147
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply_test.go
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
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 upgrade
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSetImplicitFlags(t *testing.T) {
|
||||
var tests = []struct {
|
||||
flags *applyFlags
|
||||
expectedFlags applyFlags
|
||||
errExpected bool
|
||||
}{
|
||||
{ // if not dryRun or force is set; the nonInteractiveMode field should not be touched
|
||||
flags: &applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: false,
|
||||
force: false,
|
||||
nonInteractiveMode: false,
|
||||
},
|
||||
expectedFlags: applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: false,
|
||||
force: false,
|
||||
nonInteractiveMode: false,
|
||||
},
|
||||
},
|
||||
{ // if not dryRun or force is set; the nonInteractiveMode field should not be touched
|
||||
flags: &applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: false,
|
||||
force: false,
|
||||
nonInteractiveMode: true,
|
||||
},
|
||||
expectedFlags: applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: false,
|
||||
force: false,
|
||||
nonInteractiveMode: true,
|
||||
},
|
||||
},
|
||||
{ // if dryRun or force is set; the nonInteractiveMode field should be set to true
|
||||
flags: &applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: true,
|
||||
force: false,
|
||||
nonInteractiveMode: false,
|
||||
},
|
||||
expectedFlags: applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: true,
|
||||
force: false,
|
||||
nonInteractiveMode: true,
|
||||
},
|
||||
},
|
||||
{ // if dryRun or force is set; the nonInteractiveMode field should be set to true
|
||||
flags: &applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: false,
|
||||
force: true,
|
||||
nonInteractiveMode: false,
|
||||
},
|
||||
expectedFlags: applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: false,
|
||||
force: true,
|
||||
nonInteractiveMode: true,
|
||||
},
|
||||
},
|
||||
{ // if dryRun or force is set; the nonInteractiveMode field should be set to true
|
||||
flags: &applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: true,
|
||||
force: true,
|
||||
nonInteractiveMode: false,
|
||||
},
|
||||
expectedFlags: applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: true,
|
||||
force: true,
|
||||
nonInteractiveMode: true,
|
||||
},
|
||||
},
|
||||
{ // if dryRun or force is set; the nonInteractiveMode field should be set to true
|
||||
flags: &applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: true,
|
||||
force: true,
|
||||
nonInteractiveMode: true,
|
||||
},
|
||||
expectedFlags: applyFlags{
|
||||
newK8sVersionStr: "v1.8.0",
|
||||
dryRun: true,
|
||||
force: true,
|
||||
nonInteractiveMode: true,
|
||||
},
|
||||
},
|
||||
{ // if the new version is empty; it should error out
|
||||
flags: &applyFlags{
|
||||
newK8sVersionStr: "",
|
||||
},
|
||||
expectedFlags: applyFlags{
|
||||
newK8sVersionStr: "",
|
||||
},
|
||||
errExpected: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actualErr := SetImplicitFlags(rt.flags)
|
||||
|
||||
// If an error was returned; make newK8sVersion nil so it's easy to match using reflect.DeepEqual later (instead of a random pointer)
|
||||
if actualErr != nil {
|
||||
rt.flags.newK8sVersion = nil
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(*rt.flags, rt.expectedFlags) {
|
||||
t.Errorf(
|
||||
"failed SetImplicitFlags:\n\texpected flags: %v\n\t actual: %v",
|
||||
rt.expectedFlags,
|
||||
*rt.flags,
|
||||
)
|
||||
}
|
||||
if (actualErr != nil) != rt.errExpected {
|
||||
t.Errorf(
|
||||
"failed SetImplicitFlags:\n\texpected error: %t\n\t actual: %t",
|
||||
rt.errExpected,
|
||||
(actualErr != nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
173
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common.go
generated
vendored
Normal file
173
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common.go
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
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 upgrade
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
dryrunutil "k8s.io/kubernetes/cmd/kubeadm/app/util/dryrun"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
)
|
||||
|
||||
// upgradeVariables holds variables needed for performing an upgrade or planning to do so
|
||||
// TODO - Restructure or rename upgradeVariables
|
||||
type upgradeVariables struct {
|
||||
client clientset.Interface
|
||||
cfg *kubeadmapiext.MasterConfiguration
|
||||
versionGetter upgrade.VersionGetter
|
||||
waiter apiclient.Waiter
|
||||
}
|
||||
|
||||
// enforceRequirements verifies that it's okay to upgrade and then returns the variables needed for the rest of the procedure
|
||||
func enforceRequirements(flags *cmdUpgradeFlags, dryRun bool, newK8sVersion string) (*upgradeVariables, error) {
|
||||
client, err := getClient(flags.kubeConfigPath, dryRun)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't create a Kubernetes client from file %q: %v", flags.kubeConfigPath, err)
|
||||
}
|
||||
|
||||
// Run healthchecks against the cluster
|
||||
if err := upgrade.CheckClusterHealth(client, flags.ignorePreflightErrorsSet); err != nil {
|
||||
return nil, fmt.Errorf("[upgrade/health] FATAL: %v", err)
|
||||
}
|
||||
|
||||
// Fetch the configuration from a file or ConfigMap and validate it
|
||||
cfg, err := upgrade.FetchConfiguration(client, os.Stdout, flags.cfgPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[upgrade/config] FATAL: %v", err)
|
||||
}
|
||||
|
||||
// If a new k8s version should be set, apply the change before printing the config
|
||||
if len(newK8sVersion) != 0 {
|
||||
cfg.KubernetesVersion = newK8sVersion
|
||||
}
|
||||
|
||||
// If the user told us to print this information out; do it!
|
||||
if flags.printConfig {
|
||||
printConfiguration(cfg, os.Stdout)
|
||||
}
|
||||
|
||||
cfg.FeatureGates, err = features.NewFeatureGate(&features.InitFeatureGates, flags.featureGatesString)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[upgrade/config] FATAL: %v", err)
|
||||
}
|
||||
|
||||
return &upgradeVariables{
|
||||
client: client,
|
||||
cfg: cfg,
|
||||
// Use a real version getter interface that queries the API server, the kubeadm client and the Kubernetes CI system for latest versions
|
||||
versionGetter: upgrade.NewKubeVersionGetter(client, os.Stdout),
|
||||
// Use the waiter conditionally based on the dryrunning variable
|
||||
waiter: getWaiter(dryRun, client),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// printConfiguration prints the external version of the API to yaml
|
||||
func printConfiguration(cfg *kubeadmapiext.MasterConfiguration, w io.Writer) {
|
||||
// Short-circuit if cfg is nil, so we can safely get the value of the pointer below
|
||||
if cfg == nil {
|
||||
return
|
||||
}
|
||||
|
||||
cfgYaml, err := yaml.Marshal(*cfg)
|
||||
if err == nil {
|
||||
fmt.Fprintln(w, "[upgrade/config] Configuration used:")
|
||||
|
||||
scanner := bufio.NewScanner(bytes.NewReader(cfgYaml))
|
||||
for scanner.Scan() {
|
||||
fmt.Fprintf(w, "\t%s\n", scanner.Text())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// runPreflightChecks runs the root preflight check
|
||||
func runPreflightChecks(ignorePreflightErrors sets.String) error {
|
||||
fmt.Println("[preflight] Running pre-flight checks.")
|
||||
return preflight.RunRootCheckOnly(ignorePreflightErrors)
|
||||
}
|
||||
|
||||
// getClient gets a real or fake client depending on whether the user is dry-running or not
|
||||
func getClient(file string, dryRun bool) (clientset.Interface, error) {
|
||||
if dryRun {
|
||||
dryRunGetter, err := apiclient.NewClientBackedDryRunGetterFromKubeconfig(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// In order for fakeclient.Discovery().ServerVersion() to return the backing API Server's
|
||||
// real version; we have to do some clever API machinery tricks. First, we get the real
|
||||
// API Server's version
|
||||
realServerVersion, err := dryRunGetter.Client().Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get server version: %v", err)
|
||||
}
|
||||
|
||||
// Get the fake clientset
|
||||
fakeclient := apiclient.NewDryRunClient(dryRunGetter, os.Stdout)
|
||||
// As we know the return of Discovery() of the fake clientset is of type *fakediscovery.FakeDiscovery
|
||||
// we can convert it to that struct.
|
||||
fakeclientDiscovery, ok := fakeclient.Discovery().(*fakediscovery.FakeDiscovery)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("couldn't set fake discovery's server version")
|
||||
}
|
||||
// Lastly, set the right server version to be used
|
||||
fakeclientDiscovery.FakedServerVersion = realServerVersion
|
||||
// return the fake clientset used for dry-running
|
||||
return fakeclient, nil
|
||||
}
|
||||
return kubeconfigutil.ClientSetFromFile(file)
|
||||
}
|
||||
|
||||
// getWaiter gets the right waiter implementation
|
||||
func getWaiter(dryRun bool, client clientset.Interface) apiclient.Waiter {
|
||||
if dryRun {
|
||||
return dryrunutil.NewWaiter()
|
||||
}
|
||||
return apiclient.NewKubeWaiter(client, upgradeManifestTimeout, os.Stdout)
|
||||
}
|
||||
|
||||
// InteractivelyConfirmUpgrade asks the user whether they _really_ want to upgrade.
|
||||
func InteractivelyConfirmUpgrade(question string) error {
|
||||
|
||||
fmt.Printf("[upgrade/confirm] %s [y/N]: ", question)
|
||||
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
scanner.Scan()
|
||||
if err := scanner.Err(); err != nil {
|
||||
return fmt.Errorf("couldn't read from standard input: %v", err)
|
||||
}
|
||||
answer := scanner.Text()
|
||||
if strings.ToLower(answer) == "y" || strings.ToLower(answer) == "yes" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("won't proceed; the user didn't answer (Y|y) in order to continue")
|
||||
}
|
155
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common_test.go
generated
vendored
Normal file
155
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/common_test.go
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
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 upgrade
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
)
|
||||
|
||||
func TestPrintConfiguration(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapiext.MasterConfiguration
|
||||
buf *bytes.Buffer
|
||||
expectedBytes []byte
|
||||
}{
|
||||
{
|
||||
cfg: nil,
|
||||
expectedBytes: []byte(""),
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapiext.MasterConfiguration{
|
||||
KubernetesVersion: "v1.7.1",
|
||||
},
|
||||
expectedBytes: []byte(`[upgrade/config] Configuration used:
|
||||
api:
|
||||
advertiseAddress: ""
|
||||
bindPort: 0
|
||||
certificatesDir: ""
|
||||
cloudProvider: ""
|
||||
etcd:
|
||||
caFile: ""
|
||||
certFile: ""
|
||||
dataDir: ""
|
||||
endpoints: null
|
||||
image: ""
|
||||
keyFile: ""
|
||||
imageRepository: ""
|
||||
kubeProxy: {}
|
||||
kubeletConfiguration: {}
|
||||
kubernetesVersion: v1.7.1
|
||||
networking:
|
||||
dnsDomain: ""
|
||||
podSubnet: ""
|
||||
serviceSubnet: ""
|
||||
nodeName: ""
|
||||
token: ""
|
||||
unifiedControlPlaneImage: ""
|
||||
`),
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapiext.MasterConfiguration{
|
||||
KubernetesVersion: "v1.7.1",
|
||||
Networking: kubeadmapiext.Networking{
|
||||
ServiceSubnet: "10.96.0.1/12",
|
||||
},
|
||||
},
|
||||
expectedBytes: []byte(`[upgrade/config] Configuration used:
|
||||
api:
|
||||
advertiseAddress: ""
|
||||
bindPort: 0
|
||||
certificatesDir: ""
|
||||
cloudProvider: ""
|
||||
etcd:
|
||||
caFile: ""
|
||||
certFile: ""
|
||||
dataDir: ""
|
||||
endpoints: null
|
||||
image: ""
|
||||
keyFile: ""
|
||||
imageRepository: ""
|
||||
kubeProxy: {}
|
||||
kubeletConfiguration: {}
|
||||
kubernetesVersion: v1.7.1
|
||||
networking:
|
||||
dnsDomain: ""
|
||||
podSubnet: ""
|
||||
serviceSubnet: 10.96.0.1/12
|
||||
nodeName: ""
|
||||
token: ""
|
||||
unifiedControlPlaneImage: ""
|
||||
`),
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapiext.MasterConfiguration{
|
||||
KubernetesVersion: "v1.7.1",
|
||||
Etcd: kubeadmapiext.Etcd{
|
||||
SelfHosted: &kubeadmapiext.SelfHostedEtcd{
|
||||
CertificatesDir: "/var/foo",
|
||||
ClusterServiceName: "foo",
|
||||
EtcdVersion: "v0.1.0",
|
||||
OperatorVersion: "v0.1.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedBytes: []byte(`[upgrade/config] Configuration used:
|
||||
api:
|
||||
advertiseAddress: ""
|
||||
bindPort: 0
|
||||
certificatesDir: ""
|
||||
cloudProvider: ""
|
||||
etcd:
|
||||
caFile: ""
|
||||
certFile: ""
|
||||
dataDir: ""
|
||||
endpoints: null
|
||||
image: ""
|
||||
keyFile: ""
|
||||
selfHosted:
|
||||
certificatesDir: /var/foo
|
||||
clusterServiceName: foo
|
||||
etcdVersion: v0.1.0
|
||||
operatorVersion: v0.1.0
|
||||
imageRepository: ""
|
||||
kubeProxy: {}
|
||||
kubeletConfiguration: {}
|
||||
kubernetesVersion: v1.7.1
|
||||
networking:
|
||||
dnsDomain: ""
|
||||
podSubnet: ""
|
||||
serviceSubnet: ""
|
||||
nodeName: ""
|
||||
token: ""
|
||||
unifiedControlPlaneImage: ""
|
||||
`),
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
rt.buf = bytes.NewBufferString("")
|
||||
printConfiguration(rt.cfg, rt.buf)
|
||||
actualBytes := rt.buf.Bytes()
|
||||
if !bytes.Equal(actualBytes, rt.expectedBytes) {
|
||||
t.Errorf(
|
||||
"failed PrintConfiguration:\n\texpected: %q\n\t actual: %q",
|
||||
string(rt.expectedBytes),
|
||||
string(actualBytes),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
154
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan.go
generated
vendored
Normal file
154
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
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 upgrade
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
)
|
||||
|
||||
// NewCmdPlan returns the cobra command for `kubeadm upgrade plan`
|
||||
func NewCmdPlan(parentFlags *cmdUpgradeFlags) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "plan",
|
||||
Short: "Check which versions are available to upgrade to and validate whether your current cluster is upgradeable.",
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
var err error
|
||||
parentFlags.ignorePreflightErrorsSet, err = validation.ValidateIgnorePreflightErrors(parentFlags.ignorePreflightErrors, parentFlags.skipPreFlight)
|
||||
kubeadmutil.CheckErr(err)
|
||||
// Ensure the user is root
|
||||
err = runPreflightChecks(parentFlags.ignorePreflightErrorsSet)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = RunPlan(parentFlags)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunPlan takes care of outputting available versions to upgrade to for the user
|
||||
func RunPlan(parentFlags *cmdUpgradeFlags) error {
|
||||
// Start with the basics, verify that the cluster is healthy, build a client and a versionGetter. Never dry-run when planning.
|
||||
upgradeVars, err := enforceRequirements(parentFlags, false, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Define Local Etcd cluster to be able to retrieve information
|
||||
etcdCluster := kubeadmutil.LocalEtcdCluster{}
|
||||
|
||||
// Compute which upgrade possibilities there are
|
||||
availUpgrades, err := upgrade.GetAvailableUpgrades(upgradeVars.versionGetter, parentFlags.allowExperimentalUpgrades, parentFlags.allowRCUpgrades, etcdCluster, upgradeVars.cfg.FeatureGates)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[upgrade/versions] FATAL: %v", err)
|
||||
}
|
||||
|
||||
// Tell the user which upgrades are available
|
||||
printAvailableUpgrades(availUpgrades, os.Stdout, upgradeVars.cfg.FeatureGates)
|
||||
return nil
|
||||
}
|
||||
|
||||
// printAvailableUpgrades prints a UX-friendly overview of what versions are available to upgrade to
|
||||
// TODO look into columnize or some other formatter when time permits instead of using the tabwriter
|
||||
func printAvailableUpgrades(upgrades []upgrade.Upgrade, w io.Writer, featureGates map[string]bool) {
|
||||
|
||||
// Return quickly if no upgrades can be made
|
||||
if len(upgrades) == 0 {
|
||||
fmt.Fprintln(w, "Awesome, you're up-to-date! Enjoy!")
|
||||
return
|
||||
}
|
||||
// The tab writer writes to the "real" writer w
|
||||
tabw := tabwriter.NewWriter(w, 10, 4, 3, ' ', 0)
|
||||
|
||||
// Loop through the upgrade possibilities and output text to the command line
|
||||
for _, upgrade := range upgrades {
|
||||
|
||||
if upgrade.CanUpgradeKubelets() {
|
||||
fmt.Fprintln(w, "Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':")
|
||||
fmt.Fprintln(tabw, "COMPONENT\tCURRENT\tAVAILABLE")
|
||||
firstPrinted := false
|
||||
|
||||
// The map is of the form <old-version>:<node-count>. Here all the keys are put into a slice and sorted
|
||||
// in order to always get the right order. Then the map value is extracted separately
|
||||
for _, oldVersion := range sortedSliceFromStringIntMap(upgrade.Before.KubeletVersions) {
|
||||
nodeCount := upgrade.Before.KubeletVersions[oldVersion]
|
||||
if !firstPrinted {
|
||||
// Output the Kubelet header only on the first version pair
|
||||
fmt.Fprintf(tabw, "Kubelet\t%d x %s\t%s\n", nodeCount, oldVersion, upgrade.After.KubeVersion)
|
||||
firstPrinted = true
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(tabw, "\t\t%d x %s\t%s\n", nodeCount, oldVersion, upgrade.After.KubeVersion)
|
||||
}
|
||||
// We should flush the writer here at this stage; as the columns will now be of the right size, adjusted to the above content
|
||||
tabw.Flush()
|
||||
fmt.Fprintln(w, "")
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "Upgrade to the latest %s:\n", upgrade.Description)
|
||||
fmt.Fprintln(w, "")
|
||||
fmt.Fprintln(tabw, "COMPONENT\tCURRENT\tAVAILABLE")
|
||||
fmt.Fprintf(tabw, "API Server\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
|
||||
fmt.Fprintf(tabw, "Controller Manager\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
|
||||
fmt.Fprintf(tabw, "Scheduler\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
|
||||
fmt.Fprintf(tabw, "Kube Proxy\t%s\t%s\n", upgrade.Before.KubeVersion, upgrade.After.KubeVersion)
|
||||
if features.Enabled(featureGates, features.CoreDNS) {
|
||||
fmt.Fprintf(tabw, "CoreDNS\t%s\t%s\n", upgrade.Before.DNSVersion, upgrade.After.DNSVersion)
|
||||
} else {
|
||||
fmt.Fprintf(tabw, "Kube DNS\t%s\t%s\n", upgrade.Before.DNSVersion, upgrade.After.DNSVersion)
|
||||
}
|
||||
fmt.Fprintf(tabw, "Etcd\t%s\t%s\n", upgrade.Before.EtcdVersion, upgrade.After.EtcdVersion)
|
||||
|
||||
// The tabwriter should be flushed at this stage as we have now put in all the required content for this time. This is required for the tabs' size to be correct.
|
||||
tabw.Flush()
|
||||
fmt.Fprintln(w, "")
|
||||
fmt.Fprintln(w, "You can now apply the upgrade by executing the following command:")
|
||||
fmt.Fprintln(w, "")
|
||||
fmt.Fprintf(w, "\tkubeadm upgrade apply %s\n", upgrade.After.KubeVersion)
|
||||
fmt.Fprintln(w, "")
|
||||
|
||||
if upgrade.Before.KubeadmVersion != upgrade.After.KubeadmVersion {
|
||||
fmt.Fprintf(w, "Note: Before you can perform this upgrade, you have to update kubeadm to %s.\n", upgrade.After.KubeadmVersion)
|
||||
fmt.Fprintln(w, "")
|
||||
}
|
||||
|
||||
fmt.Fprintln(w, "_____________________________________________________________________")
|
||||
fmt.Fprintln(w, "")
|
||||
}
|
||||
}
|
||||
|
||||
// sortedSliceFromStringIntMap returns a slice of the keys in the map sorted alphabetically
|
||||
func sortedSliceFromStringIntMap(strMap map[string]uint16) []string {
|
||||
strSlice := []string{}
|
||||
for k := range strMap {
|
||||
strSlice = append(strSlice, k)
|
||||
}
|
||||
sort.Strings(strSlice)
|
||||
return strSlice
|
||||
}
|
348
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan_test.go
generated
vendored
Normal file
348
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/plan_test.go
generated
vendored
Normal file
@ -0,0 +1,348 @@
|
||||
/*
|
||||
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 upgrade
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||
)
|
||||
|
||||
func TestSortedSliceFromStringIntMap(t *testing.T) {
|
||||
var tests = []struct {
|
||||
strMap map[string]uint16
|
||||
expectedSlice []string
|
||||
}{ // The returned slice should be alphabetically sorted based on the string keys in the map
|
||||
{
|
||||
strMap: map[string]uint16{"foo": 1, "bar": 2},
|
||||
expectedSlice: []string{"bar", "foo"},
|
||||
},
|
||||
{ // The int value should not affect this func
|
||||
strMap: map[string]uint16{"foo": 2, "bar": 1},
|
||||
expectedSlice: []string{"bar", "foo"},
|
||||
},
|
||||
{
|
||||
strMap: map[string]uint16{"b": 2, "a": 1, "cb": 0, "ca": 1000},
|
||||
expectedSlice: []string{"a", "b", "ca", "cb"},
|
||||
},
|
||||
{ // This should work for version numbers as well; and the lowest version should come first
|
||||
strMap: map[string]uint16{"v1.7.0": 1, "v1.6.1": 1, "v1.6.2": 1, "v1.8.0": 1, "v1.8.0-alpha.1": 1},
|
||||
expectedSlice: []string{"v1.6.1", "v1.6.2", "v1.7.0", "v1.8.0", "v1.8.0-alpha.1"},
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actualSlice := sortedSliceFromStringIntMap(rt.strMap)
|
||||
if !reflect.DeepEqual(actualSlice, rt.expectedSlice) {
|
||||
t.Errorf(
|
||||
"failed SortedSliceFromStringIntMap:\n\texpected: %v\n\t actual: %v",
|
||||
rt.expectedSlice,
|
||||
actualSlice,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Think about modifying this test to be less verbose checking b/c it can be brittle.
|
||||
func TestPrintAvailableUpgrades(t *testing.T) {
|
||||
featureGates := make(map[string]bool)
|
||||
var tests = []struct {
|
||||
upgrades []upgrade.Upgrade
|
||||
buf *bytes.Buffer
|
||||
expectedBytes []byte
|
||||
}{
|
||||
{
|
||||
upgrades: []upgrade.Upgrade{},
|
||||
expectedBytes: []byte(`Awesome, you're up-to-date! Enjoy!
|
||||
`),
|
||||
},
|
||||
{
|
||||
upgrades: []upgrade.Upgrade{
|
||||
{
|
||||
Description: "version in the v1.8 series",
|
||||
Before: upgrade.ClusterState{
|
||||
KubeVersion: "v1.8.1",
|
||||
KubeletVersions: map[string]uint16{
|
||||
"v1.8.1": 1,
|
||||
},
|
||||
KubeadmVersion: "v1.8.2",
|
||||
DNSVersion: "1.14.5",
|
||||
EtcdVersion: "3.0.17",
|
||||
},
|
||||
After: upgrade.ClusterState{
|
||||
KubeVersion: "v1.8.3",
|
||||
KubeadmVersion: "v1.8.3",
|
||||
DNSVersion: "1.14.5",
|
||||
EtcdVersion: "3.0.17",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
Kubelet 1 x v1.8.1 v1.8.3
|
||||
|
||||
Upgrade to the latest version in the v1.8 series:
|
||||
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
API Server v1.8.1 v1.8.3
|
||||
Controller Manager v1.8.1 v1.8.3
|
||||
Scheduler v1.8.1 v1.8.3
|
||||
Kube Proxy v1.8.1 v1.8.3
|
||||
Kube DNS 1.14.5 1.14.5
|
||||
Etcd 3.0.17 3.0.17
|
||||
|
||||
You can now apply the upgrade by executing the following command:
|
||||
|
||||
kubeadm upgrade apply v1.8.3
|
||||
|
||||
Note: Before you can perform this upgrade, you have to update kubeadm to v1.8.3.
|
||||
|
||||
_____________________________________________________________________
|
||||
|
||||
`),
|
||||
},
|
||||
{
|
||||
upgrades: []upgrade.Upgrade{
|
||||
{
|
||||
Description: "stable version",
|
||||
Before: upgrade.ClusterState{
|
||||
KubeVersion: "v1.8.3",
|
||||
KubeletVersions: map[string]uint16{
|
||||
"v1.8.3": 1,
|
||||
},
|
||||
KubeadmVersion: "v1.9.0",
|
||||
DNSVersion: "1.14.5",
|
||||
EtcdVersion: "3.0.17",
|
||||
},
|
||||
After: upgrade.ClusterState{
|
||||
KubeVersion: "v1.9.0",
|
||||
KubeadmVersion: "v1.9.0",
|
||||
DNSVersion: "1.14.7",
|
||||
EtcdVersion: "3.1.10",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
Kubelet 1 x v1.8.3 v1.9.0
|
||||
|
||||
Upgrade to the latest stable version:
|
||||
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
API Server v1.8.3 v1.9.0
|
||||
Controller Manager v1.8.3 v1.9.0
|
||||
Scheduler v1.8.3 v1.9.0
|
||||
Kube Proxy v1.8.3 v1.9.0
|
||||
Kube DNS 1.14.5 1.14.7
|
||||
Etcd 3.0.17 3.1.10
|
||||
|
||||
You can now apply the upgrade by executing the following command:
|
||||
|
||||
kubeadm upgrade apply v1.9.0
|
||||
|
||||
_____________________________________________________________________
|
||||
|
||||
`),
|
||||
},
|
||||
{
|
||||
upgrades: []upgrade.Upgrade{
|
||||
{
|
||||
Description: "version in the v1.8 series",
|
||||
Before: upgrade.ClusterState{
|
||||
KubeVersion: "v1.8.3",
|
||||
KubeletVersions: map[string]uint16{
|
||||
"v1.8.3": 1,
|
||||
},
|
||||
KubeadmVersion: "v1.8.3",
|
||||
DNSVersion: "1.14.5",
|
||||
EtcdVersion: "3.0.17",
|
||||
},
|
||||
After: upgrade.ClusterState{
|
||||
KubeVersion: "v1.8.5",
|
||||
KubeadmVersion: "v1.8.3",
|
||||
DNSVersion: "1.14.5",
|
||||
EtcdVersion: "3.0.17",
|
||||
},
|
||||
},
|
||||
{
|
||||
Description: "stable version",
|
||||
Before: upgrade.ClusterState{
|
||||
KubeVersion: "v1.8.3",
|
||||
KubeletVersions: map[string]uint16{
|
||||
"v1.8.3": 1,
|
||||
},
|
||||
KubeadmVersion: "v1.8.3",
|
||||
DNSVersion: "1.14.5",
|
||||
EtcdVersion: "3.0.17",
|
||||
},
|
||||
After: upgrade.ClusterState{
|
||||
KubeVersion: "v1.9.0",
|
||||
KubeadmVersion: "v1.9.0",
|
||||
DNSVersion: "1.14.7",
|
||||
EtcdVersion: "3.1.10",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
Kubelet 1 x v1.8.3 v1.8.5
|
||||
|
||||
Upgrade to the latest version in the v1.8 series:
|
||||
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
API Server v1.8.3 v1.8.5
|
||||
Controller Manager v1.8.3 v1.8.5
|
||||
Scheduler v1.8.3 v1.8.5
|
||||
Kube Proxy v1.8.3 v1.8.5
|
||||
Kube DNS 1.14.5 1.14.5
|
||||
Etcd 3.0.17 3.0.17
|
||||
|
||||
You can now apply the upgrade by executing the following command:
|
||||
|
||||
kubeadm upgrade apply v1.8.5
|
||||
|
||||
_____________________________________________________________________
|
||||
|
||||
Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
Kubelet 1 x v1.8.3 v1.9.0
|
||||
|
||||
Upgrade to the latest stable version:
|
||||
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
API Server v1.8.3 v1.9.0
|
||||
Controller Manager v1.8.3 v1.9.0
|
||||
Scheduler v1.8.3 v1.9.0
|
||||
Kube Proxy v1.8.3 v1.9.0
|
||||
Kube DNS 1.14.5 1.14.7
|
||||
Etcd 3.0.17 3.1.10
|
||||
|
||||
You can now apply the upgrade by executing the following command:
|
||||
|
||||
kubeadm upgrade apply v1.9.0
|
||||
|
||||
Note: Before you can perform this upgrade, you have to update kubeadm to v1.9.0.
|
||||
|
||||
_____________________________________________________________________
|
||||
|
||||
`),
|
||||
},
|
||||
{
|
||||
upgrades: []upgrade.Upgrade{
|
||||
{
|
||||
Description: "experimental version",
|
||||
Before: upgrade.ClusterState{
|
||||
KubeVersion: "v1.8.5",
|
||||
KubeletVersions: map[string]uint16{
|
||||
"v1.8.5": 1,
|
||||
},
|
||||
KubeadmVersion: "v1.8.5",
|
||||
DNSVersion: "1.14.5",
|
||||
EtcdVersion: "3.0.17",
|
||||
},
|
||||
After: upgrade.ClusterState{
|
||||
KubeVersion: "v1.9.0-beta.1",
|
||||
KubeadmVersion: "v1.9.0-beta.1",
|
||||
DNSVersion: "1.14.7",
|
||||
EtcdVersion: "3.1.10",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
Kubelet 1 x v1.8.5 v1.9.0-beta.1
|
||||
|
||||
Upgrade to the latest experimental version:
|
||||
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
API Server v1.8.5 v1.9.0-beta.1
|
||||
Controller Manager v1.8.5 v1.9.0-beta.1
|
||||
Scheduler v1.8.5 v1.9.0-beta.1
|
||||
Kube Proxy v1.8.5 v1.9.0-beta.1
|
||||
Kube DNS 1.14.5 1.14.7
|
||||
Etcd 3.0.17 3.1.10
|
||||
|
||||
You can now apply the upgrade by executing the following command:
|
||||
|
||||
kubeadm upgrade apply v1.9.0-beta.1
|
||||
|
||||
Note: Before you can perform this upgrade, you have to update kubeadm to v1.9.0-beta.1.
|
||||
|
||||
_____________________________________________________________________
|
||||
|
||||
`),
|
||||
},
|
||||
{
|
||||
upgrades: []upgrade.Upgrade{
|
||||
{
|
||||
Description: "release candidate version",
|
||||
Before: upgrade.ClusterState{
|
||||
KubeVersion: "v1.8.5",
|
||||
KubeletVersions: map[string]uint16{
|
||||
"v1.8.5": 1,
|
||||
},
|
||||
KubeadmVersion: "v1.8.5",
|
||||
DNSVersion: "1.14.5",
|
||||
EtcdVersion: "3.0.17",
|
||||
},
|
||||
After: upgrade.ClusterState{
|
||||
KubeVersion: "v1.9.0-rc.1",
|
||||
KubeadmVersion: "v1.9.0-rc.1",
|
||||
DNSVersion: "1.14.7",
|
||||
EtcdVersion: "3.1.10",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedBytes: []byte(`Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
Kubelet 1 x v1.8.5 v1.9.0-rc.1
|
||||
|
||||
Upgrade to the latest release candidate version:
|
||||
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
API Server v1.8.5 v1.9.0-rc.1
|
||||
Controller Manager v1.8.5 v1.9.0-rc.1
|
||||
Scheduler v1.8.5 v1.9.0-rc.1
|
||||
Kube Proxy v1.8.5 v1.9.0-rc.1
|
||||
Kube DNS 1.14.5 1.14.7
|
||||
Etcd 3.0.17 3.1.10
|
||||
|
||||
You can now apply the upgrade by executing the following command:
|
||||
|
||||
kubeadm upgrade apply v1.9.0-rc.1
|
||||
|
||||
Note: Before you can perform this upgrade, you have to update kubeadm to v1.9.0-rc.1.
|
||||
|
||||
_____________________________________________________________________
|
||||
|
||||
`),
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
rt.buf = bytes.NewBufferString("")
|
||||
printAvailableUpgrades(rt.upgrades, rt.buf, featureGates)
|
||||
actualBytes := rt.buf.Bytes()
|
||||
if !bytes.Equal(actualBytes, rt.expectedBytes) {
|
||||
t.Errorf(
|
||||
"failed PrintAvailableUpgrades:\n\texpected: %q\n\t actual: %q",
|
||||
string(rt.expectedBytes),
|
||||
string(actualBytes),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
76
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/upgrade.go
generated
vendored
Normal file
76
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/upgrade/upgrade.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
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 upgrade
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
)
|
||||
|
||||
// cmdUpgradeFlags holds the values for the common flags in `kubeadm upgrade`
|
||||
type cmdUpgradeFlags struct {
|
||||
kubeConfigPath string
|
||||
cfgPath string
|
||||
featureGatesString string
|
||||
allowExperimentalUpgrades bool
|
||||
allowRCUpgrades bool
|
||||
printConfig bool
|
||||
skipPreFlight bool
|
||||
ignorePreflightErrors []string
|
||||
ignorePreflightErrorsSet sets.String
|
||||
}
|
||||
|
||||
// NewCmdUpgrade returns the cobra command for `kubeadm upgrade`
|
||||
func NewCmdUpgrade(out io.Writer) *cobra.Command {
|
||||
flags := &cmdUpgradeFlags{
|
||||
kubeConfigPath: "/etc/kubernetes/admin.conf",
|
||||
cfgPath: "",
|
||||
featureGatesString: "",
|
||||
allowExperimentalUpgrades: false,
|
||||
allowRCUpgrades: false,
|
||||
printConfig: false,
|
||||
skipPreFlight: false,
|
||||
ignorePreflightErrorsSet: sets.NewString(),
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "upgrade",
|
||||
Short: "Upgrade your cluster smoothly to a newer version with this command.",
|
||||
RunE: cmdutil.SubCmdRunE("upgrade"),
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVar(&flags.kubeConfigPath, "kubeconfig", flags.kubeConfigPath, "The KubeConfig file to use when talking to the cluster.")
|
||||
cmd.PersistentFlags().StringVar(&flags.cfgPath, "config", flags.cfgPath, "Path to kubeadm config file. WARNING: Usage of a configuration file is experimental!")
|
||||
cmd.PersistentFlags().BoolVar(&flags.allowExperimentalUpgrades, "allow-experimental-upgrades", flags.allowExperimentalUpgrades, "Show unstable versions of Kubernetes as an upgrade alternative and allow upgrading to an alpha/beta/release candidate versions of Kubernetes.")
|
||||
cmd.PersistentFlags().BoolVar(&flags.allowRCUpgrades, "allow-release-candidate-upgrades", flags.allowRCUpgrades, "Show release candidate versions of Kubernetes as an upgrade alternative and allow upgrading to a release candidate versions of Kubernetes.")
|
||||
cmd.PersistentFlags().BoolVar(&flags.printConfig, "print-config", flags.printConfig, "Specifies whether the configuration file that will be used in the upgrade should be printed or not.")
|
||||
cmd.PersistentFlags().StringSliceVar(&flags.ignorePreflightErrors, "ignore-preflight-errors", flags.ignorePreflightErrors, "A list of checks whose errors will be shown as warnings. Example: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.")
|
||||
cmd.PersistentFlags().BoolVar(&flags.skipPreFlight, "skip-preflight-checks", flags.skipPreFlight, "Skip preflight checks that normally run before modifying the system.")
|
||||
cmd.PersistentFlags().MarkDeprecated("skip-preflight-checks", "it is now equivalent to --ignore-preflight-errors=all")
|
||||
cmd.PersistentFlags().StringVar(&flags.featureGatesString, "feature-gates", flags.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.AddCommand(NewCmdApply(flags))
|
||||
cmd.AddCommand(NewCmdPlan(flags))
|
||||
|
||||
return cmd
|
||||
}
|
36
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/util/BUILD
generated
vendored
Normal file
36
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/util/BUILD
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cmdutil.go",
|
||||
"documentation.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/util/normalizer:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["cmdutil_test.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util",
|
||||
library = ":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"],
|
||||
)
|
59
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/util/cmdutil.go
generated
vendored
Normal file
59
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/util/cmdutil.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// SubCmdRunE returns a function that handles a case where a subcommand must be specified
|
||||
// Without this callback, if a user runs just the command without a subcommand,
|
||||
// or with an invalid subcommand, cobra will print usage information, but still exit cleanly.
|
||||
// We want to return an error code in these cases so that the
|
||||
// user knows that their command was invalid.
|
||||
func SubCmdRunE(name string) func(*cobra.Command, []string) error {
|
||||
return func(_ *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("missing subcommand; %q is not meant to be run on its own", name)
|
||||
}
|
||||
|
||||
return fmt.Errorf("invalid subcommand: %q", args[0])
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateExactArgNumber validates that the required top-level arguments are specified
|
||||
func ValidateExactArgNumber(args []string, supportedArgs []string) error {
|
||||
lenSupported := len(supportedArgs)
|
||||
validArgs := 0
|
||||
// Disregard possible "" arguments; they are invalid
|
||||
for _, arg := range args {
|
||||
if len(arg) > 0 {
|
||||
validArgs++
|
||||
}
|
||||
// break early for too many arguments
|
||||
if validArgs > lenSupported {
|
||||
return fmt.Errorf("too many arguments. Required arguments: %v", supportedArgs)
|
||||
}
|
||||
}
|
||||
|
||||
if validArgs < lenSupported {
|
||||
return fmt.Errorf("missing one or more required arguments. Required arguments: %v", supportedArgs)
|
||||
}
|
||||
return nil
|
||||
}
|
64
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/util/cmdutil_test.go
generated
vendored
Normal file
64
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/util/cmdutil_test.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidateExactArgNumber(t *testing.T) {
|
||||
var tests = []struct {
|
||||
args, supportedArgs []string
|
||||
expectedErr bool
|
||||
}{
|
||||
{ // one arg given and one arg expected
|
||||
args: []string{"my-node-1234"},
|
||||
supportedArgs: []string{"node-name"},
|
||||
expectedErr: false,
|
||||
},
|
||||
{ // two args given and two args expected
|
||||
args: []string{"my-node-1234", "foo"},
|
||||
supportedArgs: []string{"node-name", "second-toplevel-arg"},
|
||||
expectedErr: false,
|
||||
},
|
||||
{ // too few supplied args
|
||||
args: []string{},
|
||||
supportedArgs: []string{"node-name"},
|
||||
expectedErr: true,
|
||||
},
|
||||
{ // too few non-empty args
|
||||
args: []string{""},
|
||||
supportedArgs: []string{"node-name"},
|
||||
expectedErr: true,
|
||||
},
|
||||
{ // too many args
|
||||
args: []string{"my-node-1234", "foo"},
|
||||
supportedArgs: []string{"node-name"},
|
||||
expectedErr: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := ValidateExactArgNumber(rt.args, rt.supportedArgs)
|
||||
if (actual != nil) != rt.expectedErr {
|
||||
t.Errorf(
|
||||
"failed ValidateExactArgNumber:\n\texpected error: %t\n\t actual error: %t",
|
||||
rt.expectedErr,
|
||||
(actual != nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
33
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/util/documentation.go
generated
vendored
Normal file
33
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/util/documentation.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/util/normalizer"
|
||||
)
|
||||
|
||||
var (
|
||||
// AlphaDisclaimer to be places at the end of description of commands in alpha release
|
||||
AlphaDisclaimer = `
|
||||
Alpha Disclaimer: this command is currently alpha.
|
||||
`
|
||||
|
||||
// MacroCommandLongDescription provide a standard description for "macro" commands
|
||||
MacroCommandLongDescription = normalizer.LongDesc(`
|
||||
This command is not meant to be run on its own. See list of available subcommands.
|
||||
`)
|
||||
)
|
83
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version.go
generated
vendored
Normal file
83
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
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 cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
)
|
||||
|
||||
// Version provides the version information of kubeadm.
|
||||
type Version struct {
|
||||
ClientVersion *apimachineryversion.Info `json:"clientVersion"`
|
||||
}
|
||||
|
||||
// NewCmdVersion provides the version information of kubeadm.
|
||||
func NewCmdVersion(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: i18n.T("Print the version of kubeadm"),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunVersion(out, cmd)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringP("output", "o", "", "Output format; available options are 'yaml', 'json' and 'short'")
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunVersion provides the version information of kubeadm in format depending on arguments
|
||||
// specified in cobra.Command.
|
||||
func RunVersion(out io.Writer, cmd *cobra.Command) error {
|
||||
clientVersion := version.Get()
|
||||
v := Version{
|
||||
ClientVersion: &clientVersion,
|
||||
}
|
||||
|
||||
switch of := cmdutil.GetFlagString(cmd, "output"); of {
|
||||
case "":
|
||||
fmt.Fprintf(out, "kubeadm version: %#v\n", v.ClientVersion)
|
||||
case "short":
|
||||
fmt.Fprintf(out, "%s\n", v.ClientVersion.GitVersion)
|
||||
case "yaml":
|
||||
y, err := yaml.Marshal(&v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(out, string(y))
|
||||
case "json":
|
||||
y, err := json.MarshalIndent(&v, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(out, string(y))
|
||||
default:
|
||||
return fmt.Errorf("invalid output format: %s", of)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
39
vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/BUILD
generated
vendored
Normal file
39
vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/BUILD
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["constants.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/constants",
|
||||
deps = [
|
||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||
"//pkg/util/version:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["constants_test.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/constants",
|
||||
library = ":go_default_library",
|
||||
deps = ["//pkg/util/version:go_default_library"],
|
||||
)
|
312
vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants.go
generated
vendored
Normal file
312
vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants.go
generated
vendored
Normal file
@ -0,0 +1,312 @@
|
||||
/*
|
||||
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 constants
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
// KubernetesDir is the directory kubernetes owns for storing various configuration files
|
||||
// This semi-constant MUST NOT be modified during runtime. It's a variable solely for use in unit testing.
|
||||
var KubernetesDir = "/etc/kubernetes"
|
||||
|
||||
const (
|
||||
// ManifestsSubDirName defines directory name to store manifests
|
||||
ManifestsSubDirName = "manifests"
|
||||
// TempDirForKubeadm defines temporary directory for kubeadm
|
||||
TempDirForKubeadm = "/etc/kubernetes/tmp"
|
||||
|
||||
// CACertAndKeyBaseName defines certificate authority base name
|
||||
CACertAndKeyBaseName = "ca"
|
||||
// CACertName defines certificate name
|
||||
CACertName = "ca.crt"
|
||||
// CAKeyName defines certificate name
|
||||
CAKeyName = "ca.key"
|
||||
|
||||
// APIServerCertAndKeyBaseName defines API's server certificate and key base name
|
||||
APIServerCertAndKeyBaseName = "apiserver"
|
||||
// APIServerCertName defines API's server certificate name
|
||||
APIServerCertName = "apiserver.crt"
|
||||
// APIServerKeyName defines API's server key name
|
||||
APIServerKeyName = "apiserver.key"
|
||||
// APIServerCertCommonName defines API's server certificate common name (CN)
|
||||
APIServerCertCommonName = "kube-apiserver"
|
||||
|
||||
// APIServerKubeletClientCertAndKeyBaseName defines kubelet client certificate and key base name
|
||||
APIServerKubeletClientCertAndKeyBaseName = "apiserver-kubelet-client"
|
||||
// APIServerKubeletClientCertName defines kubelet client certificate name
|
||||
APIServerKubeletClientCertName = "apiserver-kubelet-client.crt"
|
||||
// APIServerKubeletClientKeyName defines kubelet client key name
|
||||
APIServerKubeletClientKeyName = "apiserver-kubelet-client.key"
|
||||
// APIServerKubeletClientCertCommonName defines kubelet client certificate common name (CN)
|
||||
APIServerKubeletClientCertCommonName = "kube-apiserver-kubelet-client"
|
||||
|
||||
// ServiceAccountKeyBaseName defines SA key base name
|
||||
ServiceAccountKeyBaseName = "sa"
|
||||
// ServiceAccountPublicKeyName defines SA public key base name
|
||||
ServiceAccountPublicKeyName = "sa.pub"
|
||||
// ServiceAccountPrivateKeyName defines SA private key base name
|
||||
ServiceAccountPrivateKeyName = "sa.key"
|
||||
|
||||
// FrontProxyCACertAndKeyBaseName defines front proxy CA certificate and key base name
|
||||
FrontProxyCACertAndKeyBaseName = "front-proxy-ca"
|
||||
// FrontProxyCACertName defines front proxy CA certificate name
|
||||
FrontProxyCACertName = "front-proxy-ca.crt"
|
||||
// FrontProxyCAKeyName defines front proxy CA key name
|
||||
FrontProxyCAKeyName = "front-proxy-ca.key"
|
||||
|
||||
// FrontProxyClientCertAndKeyBaseName defines front proxy certificate and key base name
|
||||
FrontProxyClientCertAndKeyBaseName = "front-proxy-client"
|
||||
// FrontProxyClientCertName defines front proxy certificate name
|
||||
FrontProxyClientCertName = "front-proxy-client.crt"
|
||||
// FrontProxyClientKeyName defines front proxy key name
|
||||
FrontProxyClientKeyName = "front-proxy-client.key"
|
||||
// FrontProxyClientCertCommonName defines front proxy certificate common name
|
||||
FrontProxyClientCertCommonName = "front-proxy-client" //used as subject.commonname attribute (CN)
|
||||
|
||||
// AdminKubeConfigFileName defines name for the KubeConfig aimed to be used by the superuser/admin of the cluster
|
||||
AdminKubeConfigFileName = "admin.conf"
|
||||
// KubeletBootstrapKubeConfigFileName defines the file name for the KubeConfig that the kubelet will use to do
|
||||
// the TLS bootstrap to get itself an unique credential
|
||||
KubeletBootstrapKubeConfigFileName = "bootstrap-kubelet.conf"
|
||||
|
||||
// KubeletKubeConfigFileName defines the file name for the KubeConfig that the master kubelet will use for talking
|
||||
// to the API server
|
||||
KubeletKubeConfigFileName = "kubelet.conf"
|
||||
// ControllerManagerKubeConfigFileName defines the file name for the controller manager's KubeConfig file
|
||||
ControllerManagerKubeConfigFileName = "controller-manager.conf"
|
||||
// SchedulerKubeConfigFileName defines the file name for the scheduler's KubeConfig file
|
||||
SchedulerKubeConfigFileName = "scheduler.conf"
|
||||
|
||||
// Some well-known users and groups in the core Kubernetes authorization system
|
||||
|
||||
// ControllerManagerUser defines the well-known user the controller-manager should be authenticated as
|
||||
ControllerManagerUser = "system:kube-controller-manager"
|
||||
// SchedulerUser defines the well-known user the scheduler should be authenticated as
|
||||
SchedulerUser = "system:kube-scheduler"
|
||||
// MastersGroup defines the well-known group for the apiservers. This group is also superuser by default
|
||||
// (i.e. bound to the cluster-admin ClusterRole)
|
||||
MastersGroup = "system:masters"
|
||||
// NodesGroup defines the well-known group for all nodes.
|
||||
NodesGroup = "system:nodes"
|
||||
// NodesClusterRoleBinding defines the well-known ClusterRoleBinding which binds the too permissive system:node
|
||||
// ClusterRole to the system:nodes group. Since kubeadm is using the Node Authorizer, this ClusterRoleBinding's
|
||||
// system:nodes group subject is removed if present.
|
||||
NodesClusterRoleBinding = "system:node"
|
||||
|
||||
// KubeletBaseConfigMapRoleName defines the base kubelet configuration ConfigMap.
|
||||
KubeletBaseConfigMapRoleName = "kubeadm:kubelet-base-configmap"
|
||||
|
||||
// APICallRetryInterval defines how long kubeadm should wait before retrying a failed API operation
|
||||
APICallRetryInterval = 500 * time.Millisecond
|
||||
// DiscoveryRetryInterval specifies how long kubeadm should wait before retrying to connect to the master when doing discovery
|
||||
DiscoveryRetryInterval = 5 * time.Second
|
||||
// MarkMasterTimeout specifies how long kubeadm should wait for applying the label and taint on the master before timing out
|
||||
MarkMasterTimeout = 2 * time.Minute
|
||||
// UpdateNodeTimeout specifies how long kubeadm should wait for updating node with the initial remote configuration of kubelet before timing out
|
||||
UpdateNodeTimeout = 2 * time.Minute
|
||||
|
||||
// MinimumAddressesInServiceSubnet defines minimum amount of nodes the Service subnet should allow.
|
||||
// We need at least ten, because the DNS service is always at the tenth cluster clusterIP
|
||||
MinimumAddressesInServiceSubnet = 10
|
||||
|
||||
// DefaultTokenDuration specifies the default amount of time that a bootstrap token will be valid
|
||||
// Default behaviour is 24 hours
|
||||
DefaultTokenDuration = 24 * time.Hour
|
||||
|
||||
// LabelNodeRoleMaster specifies that a node is a master
|
||||
// This is a duplicate definition of the constant in pkg/controller/service/service_controller.go
|
||||
LabelNodeRoleMaster = "node-role.kubernetes.io/master"
|
||||
|
||||
// MasterConfigurationConfigMap specifies in what ConfigMap in the kube-system namespace the `kubeadm init` configuration should be stored
|
||||
MasterConfigurationConfigMap = "kubeadm-config"
|
||||
|
||||
// MasterConfigurationConfigMapKey specifies in what ConfigMap key the master configuration should be stored
|
||||
MasterConfigurationConfigMapKey = "MasterConfiguration"
|
||||
|
||||
// KubeletBaseConfigurationConfigMap specifies in what ConfigMap in the kube-system namespace the initial remote configuration of kubelet should be stored
|
||||
KubeletBaseConfigurationConfigMap = "kubelet-base-config-1.9"
|
||||
|
||||
// KubeletBaseConfigurationConfigMapKey specifies in what ConfigMap key the initial remote configuration of kubelet should be stored
|
||||
// TODO: Use the constant ("kubelet.config.k8s.io") defined in pkg/kubelet/kubeletconfig/util/keys/keys.go
|
||||
// after https://github.com/kubernetes/kubernetes/pull/53833 being merged.
|
||||
KubeletBaseConfigurationConfigMapKey = "kubelet"
|
||||
|
||||
// KubeletBaseConfigurationDir specifies the directory on the node where stores the initial remote configuration of kubelet
|
||||
KubeletBaseConfigurationDir = "/var/lib/kubelet/config/init"
|
||||
|
||||
// KubeletBaseConfigurationFile specifies the file name on the node which stores initial remote configuration of kubelet
|
||||
// TODO: Use the constant ("kubelet.config.k8s.io") defined in pkg/kubelet/kubeletconfig/util/keys/keys.go
|
||||
// after https://github.com/kubernetes/kubernetes/pull/53833 being merged.
|
||||
KubeletBaseConfigurationFile = "kubelet"
|
||||
|
||||
// MinExternalEtcdVersion indicates minimum external etcd version which kubeadm supports
|
||||
MinExternalEtcdVersion = "3.0.14"
|
||||
|
||||
// DefaultEtcdVersion indicates the default etcd version that kubeadm uses
|
||||
DefaultEtcdVersion = "3.1.10"
|
||||
|
||||
// Etcd defines variable used internally when referring to etcd component
|
||||
Etcd = "etcd"
|
||||
// KubeAPIServer defines variable used internally when referring to kube-apiserver component
|
||||
KubeAPIServer = "kube-apiserver"
|
||||
// KubeControllerManager defines variable used internally when referring to kube-controller-manager component
|
||||
KubeControllerManager = "kube-controller-manager"
|
||||
// KubeScheduler defines variable used internally when referring to kube-scheduler component
|
||||
KubeScheduler = "kube-scheduler"
|
||||
// KubeProxy defines variable used internally when referring to kube-proxy component
|
||||
KubeProxy = "kube-proxy"
|
||||
|
||||
// SelfHostingPrefix describes the prefix workloads that are self-hosted by kubeadm has
|
||||
SelfHostingPrefix = "self-hosted-"
|
||||
|
||||
// KubeCertificatesVolumeName specifies the name for the Volume that is used for injecting certificates to control plane components (can be both a hostPath volume or a projected, all-in-one volume)
|
||||
KubeCertificatesVolumeName = "k8s-certs"
|
||||
|
||||
// KubeConfigVolumeName specifies the name for the Volume that is used for injecting the kubeconfig to talk securely to the api server for a control plane component if applicable
|
||||
KubeConfigVolumeName = "kubeconfig"
|
||||
|
||||
// NodeBootstrapTokenAuthGroup specifies which group a Node Bootstrap Token should be authenticated in
|
||||
NodeBootstrapTokenAuthGroup = "system:bootstrappers:kubeadm:default-node-token"
|
||||
|
||||
// DefaultCIImageRepository points to image registry where CI uploads images from ci-cross build job
|
||||
DefaultCIImageRepository = "gcr.io/kubernetes-ci-images"
|
||||
|
||||
// CoreDNS defines a variable used internally when referring to the CoreDNS addon for a cluster
|
||||
CoreDNS = "coredns"
|
||||
// KubeDNS defines a variable used internally when referring to the kube-dns addon for a cluster
|
||||
KubeDNS = "kube-dns"
|
||||
)
|
||||
|
||||
var (
|
||||
// MasterTaint is the taint to apply on the PodSpec for being able to run that Pod on the master
|
||||
MasterTaint = v1.Taint{
|
||||
Key: LabelNodeRoleMaster,
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
}
|
||||
|
||||
// MasterToleration is the toleration to apply on the PodSpec for being able to run that Pod on the master
|
||||
MasterToleration = v1.Toleration{
|
||||
Key: LabelNodeRoleMaster,
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
}
|
||||
|
||||
// AuthorizationPolicyPath defines the supported location of authorization policy file
|
||||
AuthorizationPolicyPath = filepath.Join(KubernetesDir, "abac_policy.json")
|
||||
// AuthorizationWebhookConfigPath defines the supported location of webhook config file
|
||||
AuthorizationWebhookConfigPath = filepath.Join(KubernetesDir, "webhook_authz.conf")
|
||||
|
||||
// DefaultTokenUsages specifies the default functions a token will get
|
||||
DefaultTokenUsages = []string{"signing", "authentication"}
|
||||
|
||||
// MasterComponents defines the master component names
|
||||
MasterComponents = []string{KubeAPIServer, KubeControllerManager, KubeScheduler}
|
||||
|
||||
// MinimumControlPlaneVersion specifies the minimum control plane version kubeadm can deploy
|
||||
MinimumControlPlaneVersion = version.MustParseSemantic("v1.8.0")
|
||||
|
||||
// MinimumKubeletVersion specifies the minimum version of kubelet which kubeadm supports
|
||||
MinimumKubeletVersion = version.MustParseSemantic("v1.8.0")
|
||||
|
||||
// MinimumKubeProxyComponentConfigVersion specifies the minimum version for the kubeProxyComponent
|
||||
MinimumKubeProxyComponentConfigVersion = version.MustParseSemantic("v1.9.0-alpha.3")
|
||||
|
||||
// SupportedEtcdVersion lists officially supported etcd versions with corresponding kubernetes releases
|
||||
SupportedEtcdVersion = map[uint8]string{
|
||||
8: "3.0.17",
|
||||
9: "3.1.10",
|
||||
10: "3.1.10",
|
||||
}
|
||||
)
|
||||
|
||||
// EtcdSupportedVersion returns officially supported version of etcd for a specific kubernetes release
|
||||
// if passed version is not listed, the function returns nil and an error
|
||||
func EtcdSupportedVersion(versionString string) (*version.Version, error) {
|
||||
kubernetesVersion, err := version.ParseSemantic(versionString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if etcdStringVersion, ok := SupportedEtcdVersion[uint8(kubernetesVersion.Minor())]; ok {
|
||||
etcdVersion, err := version.ParseSemantic(etcdStringVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return etcdVersion, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Unsupported or unknown kubernetes version")
|
||||
}
|
||||
|
||||
// GetStaticPodDirectory returns the location on the disk where the Static Pod should be present
|
||||
func GetStaticPodDirectory() string {
|
||||
return filepath.Join(KubernetesDir, ManifestsSubDirName)
|
||||
}
|
||||
|
||||
// GetStaticPodFilepath returns the location on the disk where the Static Pod should be present
|
||||
func GetStaticPodFilepath(componentName, manifestsDir string) string {
|
||||
return filepath.Join(manifestsDir, componentName+".yaml")
|
||||
}
|
||||
|
||||
// GetAdminKubeConfigPath returns the location on the disk where admin kubeconfig is located by default
|
||||
func GetAdminKubeConfigPath() string {
|
||||
return filepath.Join(KubernetesDir, AdminKubeConfigFileName)
|
||||
}
|
||||
|
||||
// AddSelfHostedPrefix adds the self-hosted- prefix to the component name
|
||||
func AddSelfHostedPrefix(componentName string) string {
|
||||
return fmt.Sprintf("%s%s", SelfHostingPrefix, componentName)
|
||||
}
|
||||
|
||||
// CreateTempDirForKubeadm is a function that creates a temporary directory under /etc/kubernetes/tmp (not using /tmp as that would potentially be dangerous)
|
||||
func CreateTempDirForKubeadm(dirName string) (string, error) {
|
||||
// creates target folder if not already exists
|
||||
if err := os.MkdirAll(TempDirForKubeadm, 0700); err != nil {
|
||||
return "", fmt.Errorf("failed to create directory %q: %v", TempDirForKubeadm, err)
|
||||
}
|
||||
|
||||
tempDir, err := ioutil.TempDir(TempDirForKubeadm, dirName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("couldn't create a temporary directory: %v", err)
|
||||
}
|
||||
return tempDir, nil
|
||||
}
|
||||
|
||||
// GetDNSIP returns a dnsIP, which is 10th IP in svcSubnet CIDR range
|
||||
func GetDNSIP(svcSubnet string) (net.IP, error) {
|
||||
// Get the service subnet CIDR
|
||||
_, svcSubnetCIDR, err := net.ParseCIDR(svcSubnet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't parse service subnet CIDR %q: %v", svcSubnet, err)
|
||||
}
|
||||
|
||||
// Selects the 10th IP in service subnet CIDR range as dnsIP
|
||||
dnsIP, err := ipallocator.GetIndexedIP(svcSubnetCIDR, 10)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get tenth IP address from service subnet CIDR %s: %v", svcSubnetCIDR.String(), err)
|
||||
}
|
||||
|
||||
return dnsIP, nil
|
||||
}
|
170
vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants_test.go
generated
vendored
Normal file
170
vendor/k8s.io/kubernetes/cmd/kubeadm/app/constants/constants_test.go
generated
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
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 constants
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetStaticPodDirectory(t *testing.T) {
|
||||
expected := "/etc/kubernetes/manifests"
|
||||
actual := GetStaticPodDirectory()
|
||||
|
||||
if actual != expected {
|
||||
t.Errorf(
|
||||
"failed GetStaticPodDirectory:\n\texpected: %s\n\t actual: %s",
|
||||
expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAdminKubeConfigPath(t *testing.T) {
|
||||
expected := "/etc/kubernetes/admin.conf"
|
||||
actual := GetAdminKubeConfigPath()
|
||||
|
||||
if actual != expected {
|
||||
t.Errorf(
|
||||
"failed GetAdminKubeConfigPath:\n\texpected: %s\n\t actual: %s",
|
||||
expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStaticPodFilepath(t *testing.T) {
|
||||
var tests = []struct {
|
||||
componentName, manifestsDir, expected string
|
||||
}{
|
||||
{
|
||||
componentName: "kube-apiserver",
|
||||
manifestsDir: "/etc/kubernetes/manifests",
|
||||
expected: "/etc/kubernetes/manifests/kube-apiserver.yaml",
|
||||
},
|
||||
{
|
||||
componentName: "kube-controller-manager",
|
||||
manifestsDir: "/etc/kubernetes/manifests/",
|
||||
expected: "/etc/kubernetes/manifests/kube-controller-manager.yaml",
|
||||
},
|
||||
{
|
||||
componentName: "foo",
|
||||
manifestsDir: "/etc/bar/",
|
||||
expected: "/etc/bar/foo.yaml",
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := GetStaticPodFilepath(rt.componentName, rt.manifestsDir)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed GetStaticPodFilepath:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddSelfHostedPrefix(t *testing.T) {
|
||||
var tests = []struct {
|
||||
componentName, expected string
|
||||
}{
|
||||
{
|
||||
componentName: "kube-apiserver",
|
||||
expected: "self-hosted-kube-apiserver",
|
||||
},
|
||||
{
|
||||
componentName: "kube-controller-manager",
|
||||
expected: "self-hosted-kube-controller-manager",
|
||||
},
|
||||
{
|
||||
componentName: "kube-scheduler",
|
||||
expected: "self-hosted-kube-scheduler",
|
||||
},
|
||||
{
|
||||
componentName: "foo",
|
||||
expected: "self-hosted-foo",
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := AddSelfHostedPrefix(rt.componentName)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed AddSelfHostedPrefix:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEtcdSupportedVersion(t *testing.T) {
|
||||
var tests = []struct {
|
||||
kubernetesVersion string
|
||||
expectedVersion *version.Version
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
kubernetesVersion: "1.8.0",
|
||||
expectedVersion: version.MustParseSemantic("3.0.17"),
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
kubernetesVersion: "1.80.0",
|
||||
expectedVersion: nil,
|
||||
expectedError: fmt.Errorf("Unsupported or unknown kubernetes version"),
|
||||
},
|
||||
{
|
||||
kubernetesVersion: "1.9.0",
|
||||
expectedVersion: version.MustParseSemantic("3.1.10"),
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
kubernetesVersion: "1.10.0",
|
||||
expectedVersion: version.MustParseSemantic("3.1.10"),
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
kubernetesVersion: "1.8.6",
|
||||
expectedVersion: version.MustParseSemantic("3.0.17"),
|
||||
expectedError: nil,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actualVersion, actualError := EtcdSupportedVersion(rt.kubernetesVersion)
|
||||
if actualError != nil {
|
||||
if actualError.Error() != rt.expectedError.Error() {
|
||||
t.Errorf(
|
||||
"failed EtcdSupportedVersion:\n\texpected error: %v\n\t actual error: %v",
|
||||
rt.expectedError,
|
||||
actualError,
|
||||
)
|
||||
}
|
||||
|
||||
} else {
|
||||
if strings.Compare(actualVersion.String(), rt.expectedVersion.String()) != 0 {
|
||||
t.Errorf(
|
||||
"failed EtcdSupportedVersion:\n\texpected version: %s\n\t actual version: %s",
|
||||
rt.expectedVersion.String(),
|
||||
actualVersion.String(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
47
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/BUILD
generated
vendored
Normal file
47
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/BUILD
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["discovery.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/discovery",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/discovery/file:go_default_library",
|
||||
"//cmd/kubeadm/app/discovery/https:go_default_library",
|
||||
"//cmd/kubeadm/app/discovery/token:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["discovery_test.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/discovery",
|
||||
library = ":go_default_library",
|
||||
deps = ["//cmd/kubeadm/app/apis/kubeadm:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//cmd/kubeadm/app/discovery/file:all-srcs",
|
||||
"//cmd/kubeadm/app/discovery/https:all-srcs",
|
||||
"//cmd/kubeadm/app/discovery/token:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
72
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery.go
generated
vendored
Normal file
72
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
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 discovery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery/file"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery/https"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery/token"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
)
|
||||
|
||||
// TokenUser defines token user
|
||||
const TokenUser = "tls-bootstrap-token-user"
|
||||
|
||||
// For returns a KubeConfig object that can be used for doing the TLS Bootstrap with the right credentials
|
||||
// Also, before returning anything, it makes sure it can trust the API Server
|
||||
func For(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Config, error) {
|
||||
// TODO: Print summary info about the CA certificate, along with the checksum signature
|
||||
// we also need an ability for the user to configure the client to validate received CA cert against a checksum
|
||||
clusterinfo, err := GetValidatedClusterInfoObject(cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't validate the identity of the API Server: %v", err)
|
||||
}
|
||||
|
||||
return kubeconfigutil.CreateWithToken(
|
||||
clusterinfo.Server,
|
||||
"kubernetes",
|
||||
TokenUser,
|
||||
clusterinfo.CertificateAuthorityData,
|
||||
cfg.TLSBootstrapToken,
|
||||
), nil
|
||||
}
|
||||
|
||||
// GetValidatedClusterInfoObject returns a validated Cluster object that specifies where the cluster is and the CA cert to trust
|
||||
func GetValidatedClusterInfoObject(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Cluster, error) {
|
||||
switch {
|
||||
case len(cfg.DiscoveryFile) != 0:
|
||||
if isHTTPSURL(cfg.DiscoveryFile) {
|
||||
return https.RetrieveValidatedClusterInfo(cfg.DiscoveryFile)
|
||||
}
|
||||
return file.RetrieveValidatedClusterInfo(cfg.DiscoveryFile)
|
||||
case len(cfg.DiscoveryToken) != 0:
|
||||
return token.RetrieveValidatedClusterInfo(cfg.DiscoveryToken, cfg.DiscoveryTokenAPIServers, cfg.DiscoveryTokenCACertHashes)
|
||||
default:
|
||||
return nil, fmt.Errorf("couldn't find a valid discovery configuration")
|
||||
}
|
||||
}
|
||||
|
||||
// isHTTPSURL checks whether the string is parsable as an URL and whether the Scheme is https
|
||||
func isHTTPSURL(s string) bool {
|
||||
u, err := url.Parse(s)
|
||||
return err == nil && u.Scheme == "https"
|
||||
}
|
66
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery_test.go
generated
vendored
Normal file
66
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery_test.go
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
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 discovery
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestFor(t *testing.T) {
|
||||
tests := []struct {
|
||||
d kubeadm.NodeConfiguration
|
||||
expect bool
|
||||
}{
|
||||
{d: kubeadm.NodeConfiguration{}, expect: false},
|
||||
{
|
||||
d: kubeadm.NodeConfiguration{
|
||||
DiscoveryFile: "notnil",
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
d: kubeadm.NodeConfiguration{
|
||||
DiscoveryFile: "https://localhost",
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
d: kubeadm.NodeConfiguration{
|
||||
DiscoveryFile: "notnil",
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
d: kubeadm.NodeConfiguration{
|
||||
DiscoveryToken: "foo.bar@foobar",
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
_, actual := For(&rt.d)
|
||||
if (actual == nil) != rt.expect {
|
||||
t.Errorf(
|
||||
"failed For:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expect,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
36
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/BUILD
generated
vendored
Normal file
36
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/BUILD
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["file.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/discovery/file",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//pkg/bootstrap/api: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/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
129
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/file.go
generated
vendored
Normal file
129
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/file.go
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
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 file
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api"
|
||||
)
|
||||
|
||||
// RetrieveValidatedClusterInfo connects to the API Server and makes sure it can talk
|
||||
// securely to the API Server using the provided CA cert and
|
||||
// optionally refreshes the cluster-info information from the cluster-info ConfigMap
|
||||
func RetrieveValidatedClusterInfo(filepath string) (*clientcmdapi.Cluster, error) {
|
||||
clusterinfo, err := clientcmd.LoadFromFile(filepath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ValidateClusterInfo(clusterinfo)
|
||||
}
|
||||
|
||||
// ValidateClusterInfo connects to the API Server and makes sure it can talk
|
||||
// securely to the API Server using the provided CA cert and
|
||||
// optionally refreshes the cluster-info information from the cluster-info ConfigMap
|
||||
func ValidateClusterInfo(clusterinfo *clientcmdapi.Config) (*clientcmdapi.Cluster, error) {
|
||||
err := validateClusterInfoKubeConfig(clusterinfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This is the cluster object we've got from the cluster-info KubeConfig file
|
||||
defaultCluster := kubeconfigutil.GetClusterFromKubeConfig(clusterinfo)
|
||||
|
||||
// Create a new kubeconfig object from the given, just copy over the server and the CA cert
|
||||
// We do this in order to not pick up other possible misconfigurations in the clusterinfo file
|
||||
configFromClusterInfo := kubeconfigutil.CreateBasic(
|
||||
defaultCluster.Server,
|
||||
"kubernetes",
|
||||
"", // no user provided
|
||||
defaultCluster.CertificateAuthorityData,
|
||||
)
|
||||
|
||||
client, err := kubeconfigutil.ToClientSet(configFromClusterInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("[discovery] Created cluster-info discovery client, requesting info from %q\n", defaultCluster.Server)
|
||||
|
||||
var clusterinfoCM *v1.ConfigMap
|
||||
wait.PollInfinite(constants.DiscoveryRetryInterval, func() (bool, error) {
|
||||
var err error
|
||||
clusterinfoCM, err = client.CoreV1().ConfigMaps(metav1.NamespacePublic).Get(bootstrapapi.ConfigMapClusterInfo, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if apierrors.IsForbidden(err) {
|
||||
// If the request is unauthorized, the cluster admin has not granted access to the cluster info configmap for unauthenicated users
|
||||
// In that case, trust the cluster admin and do not refresh the cluster-info credentials
|
||||
fmt.Printf("[discovery] Could not access the %s ConfigMap for refreshing the cluster-info information, but the TLS cert is valid so proceeding...\n", bootstrapapi.ConfigMapClusterInfo)
|
||||
return true, nil
|
||||
}
|
||||
fmt.Printf("[discovery] Failed to validate the API Server's identity, will try again: [%v]\n", err)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
// If we couldn't fetch the cluster-info ConfigMap, just return the cluster-info object the user provided
|
||||
if clusterinfoCM == nil {
|
||||
return defaultCluster, nil
|
||||
}
|
||||
|
||||
// We somehow got hold of the ConfigMap, try to read some data from it. If we can't, fallback on the user-provided file
|
||||
refreshedBaseKubeConfig, err := tryParseClusterInfoFromConfigMap(clusterinfoCM)
|
||||
if err != nil {
|
||||
fmt.Printf("[discovery] The %s ConfigMap isn't set up properly (%v), but the TLS cert is valid so proceeding...\n", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
return defaultCluster, nil
|
||||
}
|
||||
|
||||
fmt.Println("[discovery] Synced cluster-info information from the API Server so we have got the latest information")
|
||||
// In an HA world in the future, this will make more sense, because now we've got new information, possibly about new API Servers to talk to
|
||||
return kubeconfigutil.GetClusterFromKubeConfig(refreshedBaseKubeConfig), nil
|
||||
}
|
||||
|
||||
// tryParseClusterInfoFromConfigMap tries to parse a kubeconfig file from a ConfigMap key
|
||||
func tryParseClusterInfoFromConfigMap(cm *v1.ConfigMap) (*clientcmdapi.Config, error) {
|
||||
kubeConfigString, ok := cm.Data[bootstrapapi.KubeConfigKey]
|
||||
if !ok || len(kubeConfigString) == 0 {
|
||||
return nil, fmt.Errorf("no %s key in ConfigMap", bootstrapapi.KubeConfigKey)
|
||||
}
|
||||
parsedKubeConfig, err := clientcmd.Load([]byte(kubeConfigString))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't parse the kubeconfig file in the %s ConfigMap: %v", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
}
|
||||
return parsedKubeConfig, nil
|
||||
}
|
||||
|
||||
// validateClusterInfoKubeConfig makes sure the user-provided cluster-info KubeConfig file is valid
|
||||
func validateClusterInfoKubeConfig(clusterinfo *clientcmdapi.Config) error {
|
||||
if len(clusterinfo.Clusters) < 1 {
|
||||
return fmt.Errorf("the provided cluster-info KubeConfig file must have at least one Cluster defined")
|
||||
}
|
||||
defaultCluster := kubeconfigutil.GetClusterFromKubeConfig(clusterinfo)
|
||||
if defaultCluster == nil {
|
||||
return fmt.Errorf("the provided cluster-info KubeConfig file must have an unnamed Cluster or a CurrentContext that specifies a non-nil Cluster")
|
||||
}
|
||||
return nil
|
||||
}
|
30
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/BUILD
generated
vendored
Normal file
30
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/BUILD
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["https.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/discovery/https",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/discovery/file:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
48
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/https.go
generated
vendored
Normal file
48
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/https.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
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 https
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery/file"
|
||||
)
|
||||
|
||||
// RetrieveValidatedClusterInfo connects to the API Server and makes sure it can talk
|
||||
// securely to the API Server using the provided CA cert and
|
||||
// optionally refreshes the cluster-info information from the cluster-info ConfigMap
|
||||
func RetrieveValidatedClusterInfo(httpsURL string) (*clientcmdapi.Cluster, error) {
|
||||
response, err := http.Get(httpsURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
kubeconfig, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterinfo, err := clientcmd.Load(kubeconfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return file.ValidateClusterInfo(clusterinfo)
|
||||
}
|
50
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/BUILD
generated
vendored
Normal file
50
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/BUILD
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["token.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/discovery/token",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/util/pubkeypin:go_default_library",
|
||||
"//cmd/kubeadm/app/util/token:go_default_library",
|
||||
"//pkg/bootstrap/api:go_default_library",
|
||||
"//pkg/controller/bootstrap: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/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["token_test.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/discovery/token",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
],
|
||||
)
|
222
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token.go
generated
vendored
Normal file
222
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token.go
generated
vendored
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
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 token
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/pubkeypin"
|
||||
tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token"
|
||||
bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api"
|
||||
"k8s.io/kubernetes/pkg/controller/bootstrap"
|
||||
)
|
||||
|
||||
// BootstrapUser defines bootstrap user name
|
||||
const BootstrapUser = "token-bootstrap-client"
|
||||
|
||||
// RetrieveValidatedClusterInfo connects to the API Server and tries to fetch the cluster-info ConfigMap
|
||||
// It then makes sure it can trust the API Server by looking at the JWS-signed tokens and (if rootCAPubKeys is not empty)
|
||||
// validating the cluster CA against a set of pinned public keys
|
||||
func RetrieveValidatedClusterInfo(discoveryToken string, tokenAPIServers, rootCAPubKeys []string) (*clientcmdapi.Cluster, error) {
|
||||
tokenID, tokenSecret, err := tokenutil.ParseToken(discoveryToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Load the cfg.DiscoveryTokenCACertHashes into a pubkeypin.Set
|
||||
pubKeyPins := pubkeypin.NewSet()
|
||||
err = pubKeyPins.Allow(rootCAPubKeys...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The function below runs for every endpoint, and all endpoints races with each other.
|
||||
// The endpoint that wins the race and completes the task first gets its kubeconfig returned below
|
||||
baseKubeConfig := runForEndpointsAndReturnFirst(tokenAPIServers, func(endpoint string) (*clientcmdapi.Config, error) {
|
||||
|
||||
insecureBootstrapConfig := buildInsecureBootstrapKubeConfig(endpoint)
|
||||
clusterName := insecureBootstrapConfig.Contexts[insecureBootstrapConfig.CurrentContext].Cluster
|
||||
|
||||
insecureClient, err := kubeconfigutil.ToClientSet(insecureBootstrapConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("[discovery] Created cluster-info discovery client, requesting info from %q\n", insecureBootstrapConfig.Clusters[clusterName].Server)
|
||||
|
||||
// Make an initial insecure connection to get the cluster-info ConfigMap
|
||||
var insecureClusterInfo *v1.ConfigMap
|
||||
wait.PollImmediateInfinite(constants.DiscoveryRetryInterval, func() (bool, error) {
|
||||
var err error
|
||||
insecureClusterInfo, err = insecureClient.CoreV1().ConfigMaps(metav1.NamespacePublic).Get(bootstrapapi.ConfigMapClusterInfo, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
fmt.Printf("[discovery] Failed to request cluster info, will try again: [%s]\n", err)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
// Validate the MAC on the kubeconfig from the ConfigMap and load it
|
||||
insecureKubeconfigString, ok := insecureClusterInfo.Data[bootstrapapi.KubeConfigKey]
|
||||
if !ok || len(insecureKubeconfigString) == 0 {
|
||||
return nil, fmt.Errorf("there is no %s key in the %s ConfigMap. This API Server isn't set up for token bootstrapping, can't connect", bootstrapapi.KubeConfigKey, bootstrapapi.ConfigMapClusterInfo)
|
||||
}
|
||||
detachedJWSToken, ok := insecureClusterInfo.Data[bootstrapapi.JWSSignatureKeyPrefix+tokenID]
|
||||
if !ok || len(detachedJWSToken) == 0 {
|
||||
return nil, fmt.Errorf("there is no JWS signed token in the %s ConfigMap. This token id %q is invalid for this cluster, can't connect", bootstrapapi.ConfigMapClusterInfo, tokenID)
|
||||
}
|
||||
if !bootstrap.DetachedTokenIsValid(detachedJWSToken, insecureKubeconfigString, tokenID, tokenSecret) {
|
||||
return nil, fmt.Errorf("failed to verify JWS signature of received cluster info object, can't trust this API Server")
|
||||
}
|
||||
insecureKubeconfigBytes := []byte(insecureKubeconfigString)
|
||||
insecureConfig, err := clientcmd.Load(insecureKubeconfigBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't parse the kubeconfig file in the %s configmap: %v", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
}
|
||||
|
||||
// If no TLS root CA pinning was specified, we're done
|
||||
if pubKeyPins.Empty() {
|
||||
fmt.Printf("[discovery] Cluster info signature and contents are valid and no TLS pinning was specified, will use API Server %q\n", endpoint)
|
||||
return insecureConfig, nil
|
||||
}
|
||||
|
||||
// Load the cluster CA from the Config
|
||||
if len(insecureConfig.Clusters) != 1 {
|
||||
return nil, fmt.Errorf("expected the kubeconfig file in the %s configmap to have a single cluster, but it had %d", bootstrapapi.ConfigMapClusterInfo, len(insecureConfig.Clusters))
|
||||
}
|
||||
var clusterCABytes []byte
|
||||
for _, cluster := range insecureConfig.Clusters {
|
||||
clusterCABytes = cluster.CertificateAuthorityData
|
||||
}
|
||||
clusterCA, err := parsePEMCert(clusterCABytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse cluster CA from the %s configmap: %v", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
|
||||
}
|
||||
|
||||
// Validate the cluster CA public key against the pinned set
|
||||
err = pubKeyPins.Check(clusterCA)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cluster CA found in %s configmap is invalid: %v", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
}
|
||||
|
||||
// Now that we know the proported cluster CA, connect back a second time validating with that CA
|
||||
secureBootstrapConfig := buildSecureBootstrapKubeConfig(endpoint, clusterCABytes)
|
||||
secureClient, err := kubeconfigutil.ToClientSet(secureBootstrapConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("[discovery] Requesting info from %q again to validate TLS against the pinned public key\n", insecureBootstrapConfig.Clusters[clusterName].Server)
|
||||
var secureClusterInfo *v1.ConfigMap
|
||||
wait.PollImmediateInfinite(constants.DiscoveryRetryInterval, func() (bool, error) {
|
||||
var err error
|
||||
secureClusterInfo, err = secureClient.CoreV1().ConfigMaps(metav1.NamespacePublic).Get(bootstrapapi.ConfigMapClusterInfo, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
fmt.Printf("[discovery] Failed to request cluster info, will try again: [%s]\n", err)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
// Pull the kubeconfig from the securely-obtained ConfigMap and validate that it's the same as what we found the first time
|
||||
secureKubeconfigBytes := []byte(secureClusterInfo.Data[bootstrapapi.KubeConfigKey])
|
||||
if !bytes.Equal(secureKubeconfigBytes, insecureKubeconfigBytes) {
|
||||
return nil, fmt.Errorf("the second kubeconfig from the %s configmap (using validated TLS) was different from the first", bootstrapapi.ConfigMapClusterInfo)
|
||||
}
|
||||
|
||||
secureKubeconfig, err := clientcmd.Load(secureKubeconfigBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't parse the kubeconfig file in the %s configmap: %v", bootstrapapi.ConfigMapClusterInfo, err)
|
||||
}
|
||||
|
||||
fmt.Printf("[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server %q\n", endpoint)
|
||||
return secureKubeconfig, nil
|
||||
})
|
||||
|
||||
return kubeconfigutil.GetClusterFromKubeConfig(baseKubeConfig), nil
|
||||
}
|
||||
|
||||
// buildInsecureBootstrapKubeConfig makes a KubeConfig object that connects insecurely to the API Server for bootstrapping purposes
|
||||
func buildInsecureBootstrapKubeConfig(endpoint string) *clientcmdapi.Config {
|
||||
masterEndpoint := fmt.Sprintf("https://%s", endpoint)
|
||||
clusterName := "kubernetes"
|
||||
bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, clusterName, BootstrapUser, []byte{})
|
||||
bootstrapConfig.Clusters[clusterName].InsecureSkipTLSVerify = true
|
||||
return bootstrapConfig
|
||||
}
|
||||
|
||||
// buildSecureBootstrapKubeConfig makes a KubeConfig object that connects securely to the API Server for bootstrapping purposes (validating with the specified CA)
|
||||
func buildSecureBootstrapKubeConfig(endpoint string, caCert []byte) *clientcmdapi.Config {
|
||||
masterEndpoint := fmt.Sprintf("https://%s", endpoint)
|
||||
bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, "kubernetes", BootstrapUser, caCert)
|
||||
return bootstrapConfig
|
||||
}
|
||||
|
||||
// runForEndpointsAndReturnFirst loops the endpoints slice and let's the endpoints race for connecting to the master
|
||||
func runForEndpointsAndReturnFirst(endpoints []string, fetchKubeConfigFunc func(string) (*clientcmdapi.Config, error)) *clientcmdapi.Config {
|
||||
stopChan := make(chan struct{})
|
||||
var resultingKubeConfig *clientcmdapi.Config
|
||||
var once sync.Once
|
||||
var wg sync.WaitGroup
|
||||
for _, endpoint := range endpoints {
|
||||
wg.Add(1)
|
||||
go func(apiEndpoint string) {
|
||||
defer wg.Done()
|
||||
wait.Until(func() {
|
||||
fmt.Printf("[discovery] Trying to connect to API Server %q\n", apiEndpoint)
|
||||
cfg, err := fetchKubeConfigFunc(apiEndpoint)
|
||||
if err != nil {
|
||||
fmt.Printf("[discovery] Failed to connect to API Server %q: %v\n", apiEndpoint, err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("[discovery] Successfully established connection with API Server %q\n", apiEndpoint)
|
||||
|
||||
// connection established, stop all wait threads
|
||||
once.Do(func() {
|
||||
close(stopChan)
|
||||
resultingKubeConfig = cfg
|
||||
})
|
||||
}, constants.DiscoveryRetryInterval, stopChan)
|
||||
}(endpoint)
|
||||
}
|
||||
wg.Wait()
|
||||
return resultingKubeConfig
|
||||
}
|
||||
|
||||
// parsePEMCert decodes a PEM-formatted certificate and returns it as an x509.Certificate
|
||||
func parsePEMCert(certData []byte) (*x509.Certificate, error) {
|
||||
pemBlock, trailingData := pem.Decode(certData)
|
||||
if pemBlock == nil {
|
||||
return nil, fmt.Errorf("invalid PEM data")
|
||||
}
|
||||
if len(trailingData) != 0 {
|
||||
return nil, fmt.Errorf("trailing data after first PEM block")
|
||||
}
|
||||
return x509.ParseCertificate(pemBlock.Bytes)
|
||||
}
|
115
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go
generated
vendored
Normal file
115
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go
generated
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
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 token
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
|
||||
)
|
||||
|
||||
// testCertPEM is a simple self-signed test certificate issued with the openssl CLI:
|
||||
// openssl req -new -newkey rsa:2048 -days 36500 -nodes -x509 -keyout /dev/null -out test.crt
|
||||
const testCertPEM = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDRDCCAiygAwIBAgIJAJgVaCXvC6HkMA0GCSqGSIb3DQEBBQUAMB8xHTAbBgNV
|
||||
BAMTFGt1YmVhZG0ta2V5cGlucy10ZXN0MCAXDTE3MDcwNTE3NDMxMFoYDzIxMTcw
|
||||
NjExMTc0MzEwWjAfMR0wGwYDVQQDExRrdWJlYWRtLWtleXBpbnMtdGVzdDCCASIw
|
||||
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK0ba8mHU9UtYlzM1Own2Fk/XGjR
|
||||
J4uJQvSeGLtz1hID1IA0dLwruvgLCPadXEOw/f/IWIWcmT+ZmvIHZKa/woq2iHi5
|
||||
+HLhXs7aG4tjKGLYhag1hLjBI7icqV7ovkjdGAt9pWkxEzhIYClFMXDjKpMSynu+
|
||||
YX6nZ9tic1cOkHmx2yiZdMkuriRQnpTOa7bb03OC1VfGl7gHlOAIYaj4539WCOr8
|
||||
+ACTUMJUFEHcRZ2o8a/v6F9GMK+7SC8SJUI+GuroXqlMAdhEv4lX5Co52enYaClN
|
||||
+D9FJLRpBv2YfiCQdJRaiTvCBSxEFz6BN+PtP5l2Hs703ZWEkOqCByM6HV8CAwEA
|
||||
AaOBgDB+MB0GA1UdDgQWBBRQgUX8MhK2rWBWQiPHWcKzoWDH5DBPBgNVHSMESDBG
|
||||
gBRQgUX8MhK2rWBWQiPHWcKzoWDH5KEjpCEwHzEdMBsGA1UEAxMUa3ViZWFkbS1r
|
||||
ZXlwaW5zLXRlc3SCCQCYFWgl7wuh5DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEB
|
||||
BQUAA4IBAQCaAUif7Pfx3X0F08cxhx8/Hdx4jcJw6MCq6iq6rsXM32ge43t8OHKC
|
||||
pJW08dk58a3O1YQSMMvD6GJDAiAfXzfwcwY6j258b1ZlI9Ag0VokvhMl/XfdCsdh
|
||||
AWImnL1t4hvU5jLaImUUMlYxMcSfHBGAm7WJIZ2LdEfg6YWfZh+WGbg1W7uxLxk6
|
||||
y4h5rWdNnzBHWAGf7zJ0oEDV6W6RSwNXtC0JNnLaeIUm/6xdSddJlQPwUv8YH4jX
|
||||
c1vuFqTnJBPcb7W//R/GI2Paicm1cmns9NLnPR35exHxFTy+D1yxmGokpoPMdife
|
||||
aH+sfuxT8xeTPb3kjzF9eJTlnEquUDLM
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
func TestRunForEndpointsAndReturnFirst(t *testing.T) {
|
||||
tests := []struct {
|
||||
endpoints []string
|
||||
expectedEndpoint string
|
||||
}{
|
||||
{
|
||||
endpoints: []string{"1", "2", "3"},
|
||||
expectedEndpoint: "1",
|
||||
},
|
||||
{
|
||||
endpoints: []string{"6", "5"},
|
||||
expectedEndpoint: "5",
|
||||
},
|
||||
{
|
||||
endpoints: []string{"10", "4"},
|
||||
expectedEndpoint: "4",
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
returnKubeConfig := runForEndpointsAndReturnFirst(rt.endpoints, func(endpoint string) (*clientcmdapi.Config, error) {
|
||||
timeout, _ := strconv.Atoi(endpoint)
|
||||
time.Sleep(time.Second * time.Duration(timeout))
|
||||
return kubeconfigutil.CreateBasic(endpoint, "foo", "foo", []byte{}), nil
|
||||
})
|
||||
endpoint := returnKubeConfig.Clusters[returnKubeConfig.Contexts[returnKubeConfig.CurrentContext].Cluster].Server
|
||||
if endpoint != rt.expectedEndpoint {
|
||||
t.Errorf(
|
||||
"failed TestRunForEndpointsAndReturnFirst:\n\texpected: %s\n\t actual: %s",
|
||||
endpoint,
|
||||
rt.expectedEndpoint,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePEMCert(t *testing.T) {
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
input []byte
|
||||
expectValid bool
|
||||
}{
|
||||
{"invalid certificate data", []byte{0}, false},
|
||||
{"certificate with junk appended", []byte(testCertPEM + "\nABC"), false},
|
||||
{"multiple certificates", []byte(testCertPEM + "\n" + testCertPEM), false},
|
||||
{"valid", []byte(testCertPEM), true},
|
||||
} {
|
||||
cert, err := parsePEMCert(testCase.input)
|
||||
if testCase.expectValid {
|
||||
if err != nil {
|
||||
t.Errorf("failed TestParsePEMCert(%s): unexpected error %v", testCase.name, err)
|
||||
}
|
||||
if cert == nil {
|
||||
t.Errorf("failed TestParsePEMCert(%s): returned nil", testCase.name)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Errorf("failed TestParsePEMCert(%s): expected an error", testCase.name)
|
||||
}
|
||||
if cert != nil {
|
||||
t.Errorf("failed TestParsePEMCert(%s): expected not to get a certificate back, but got one", testCase.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/BUILD
generated
vendored
Normal file
38
vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/BUILD
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["features.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/features",
|
||||
deps = [
|
||||
"//pkg/util/version:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["features_test.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/features",
|
||||
library = ":go_default_library",
|
||||
deps = ["//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library"],
|
||||
)
|
178
vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features.go
generated
vendored
Normal file
178
vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features.go
generated
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
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 features
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
const (
|
||||
// HighAvailability is alpha in v1.9
|
||||
HighAvailability = "HighAvailability"
|
||||
|
||||
// CoreDNS is alpha in v1.9
|
||||
CoreDNS = "CoreDNS"
|
||||
|
||||
// SelfHosting is alpha in v1.8 and v1.9
|
||||
SelfHosting = "SelfHosting"
|
||||
|
||||
// StoreCertsInSecrets is alpha in v1.8 and v1.9
|
||||
StoreCertsInSecrets = "StoreCertsInSecrets"
|
||||
|
||||
// DynamicKubeletConfig is alpha in v1.9
|
||||
DynamicKubeletConfig = "DynamicKubeletConfig"
|
||||
)
|
||||
|
||||
var v190 = version.MustParseSemantic("v1.9.0-alpha.1")
|
||||
|
||||
// InitFeatureGates are the default feature gates for the init command
|
||||
var InitFeatureGates = FeatureList{
|
||||
SelfHosting: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}},
|
||||
StoreCertsInSecrets: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}},
|
||||
// We don't want to advertise this feature gate exists in v1.9 to avoid confusion as it is not yet working
|
||||
HighAvailability: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}, MinimumVersion: v190, HiddenInHelpText: true},
|
||||
CoreDNS: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}, MinimumVersion: v190},
|
||||
DynamicKubeletConfig: {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Alpha}, MinimumVersion: v190},
|
||||
}
|
||||
|
||||
// Feature represents a feature being gated
|
||||
type Feature struct {
|
||||
utilfeature.FeatureSpec
|
||||
MinimumVersion *version.Version
|
||||
HiddenInHelpText bool
|
||||
}
|
||||
|
||||
// FeatureList represents a list of feature gates
|
||||
type FeatureList map[string]Feature
|
||||
|
||||
// ValidateVersion ensures that a feature gate list is compatible with the chosen kubernetes version
|
||||
func ValidateVersion(allFeatures FeatureList, requestedFeatures map[string]bool, requestedVersion string) error {
|
||||
if requestedVersion == "" {
|
||||
return nil
|
||||
}
|
||||
parsedExpVersion, err := version.ParseSemantic(requestedVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error parsing version %s: %v", requestedVersion, err)
|
||||
}
|
||||
for k := range requestedFeatures {
|
||||
if minVersion := allFeatures[k].MinimumVersion; minVersion != nil {
|
||||
if !parsedExpVersion.AtLeast(minVersion) {
|
||||
return fmt.Errorf(
|
||||
"the requested kubernetes version (%s) is incompatible with the %s feature gate, which needs %s as a minimum",
|
||||
requestedVersion, k, minVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enabled indicates whether a feature name has been enabled
|
||||
func Enabled(featureList map[string]bool, featureName string) bool {
|
||||
return featureList[string(featureName)]
|
||||
}
|
||||
|
||||
// Supports indicates whether a feature name is supported on the given
|
||||
// feature set
|
||||
func Supports(featureList FeatureList, featureName string) bool {
|
||||
for k := range featureList {
|
||||
if featureName == string(k) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Keys returns a slice of feature names for a given feature set
|
||||
func Keys(featureList FeatureList) []string {
|
||||
var list []string
|
||||
for k := range featureList {
|
||||
list = append(list, string(k))
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// KnownFeatures returns a slice of strings describing the FeatureList features.
|
||||
func KnownFeatures(f *FeatureList) []string {
|
||||
var known []string
|
||||
for k, v := range *f {
|
||||
if v.HiddenInHelpText {
|
||||
continue
|
||||
}
|
||||
|
||||
pre := ""
|
||||
if v.PreRelease != utilfeature.GA {
|
||||
pre = fmt.Sprintf("%s - ", v.PreRelease)
|
||||
}
|
||||
known = append(known, fmt.Sprintf("%s=true|false (%sdefault=%t)", k, pre, v.Default))
|
||||
}
|
||||
sort.Strings(known)
|
||||
return known
|
||||
}
|
||||
|
||||
// NewFeatureGate parses a string of the form "key1=value1,key2=value2,..." into a
|
||||
// map[string]bool of known keys or returns an error.
|
||||
func NewFeatureGate(f *FeatureList, value string) (map[string]bool, error) {
|
||||
featureGate := map[string]bool{}
|
||||
for _, s := range strings.Split(value, ",") {
|
||||
if len(s) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
arr := strings.SplitN(s, "=", 2)
|
||||
if len(arr) != 2 {
|
||||
return nil, fmt.Errorf("missing bool value for feature-gate key:%s", s)
|
||||
}
|
||||
|
||||
k := strings.TrimSpace(arr[0])
|
||||
v := strings.TrimSpace(arr[1])
|
||||
|
||||
if !Supports(*f, k) {
|
||||
return nil, fmt.Errorf("unrecognized feature-gate key: %s", k)
|
||||
}
|
||||
|
||||
boolValue, err := strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid value %v for feature-gate key: %s, use true|false instead", v, k)
|
||||
}
|
||||
featureGate[k] = boolValue
|
||||
}
|
||||
|
||||
ResolveFeatureGateDependencies(featureGate)
|
||||
|
||||
return featureGate, nil
|
||||
}
|
||||
|
||||
// ResolveFeatureGateDependencies resolve dependencies between feature gates
|
||||
func ResolveFeatureGateDependencies(featureGate map[string]bool) {
|
||||
|
||||
// if StoreCertsInSecrets enabled, SelfHosting should enabled
|
||||
if Enabled(featureGate, StoreCertsInSecrets) {
|
||||
featureGate[SelfHosting] = true
|
||||
}
|
||||
|
||||
// if HighAvailability enabled, both StoreCertsInSecrets and SelfHosting should enabled
|
||||
if Enabled(featureGate, HighAvailability) && !Enabled(featureGate, StoreCertsInSecrets) {
|
||||
featureGate[SelfHosting] = true
|
||||
featureGate[StoreCertsInSecrets] = true
|
||||
}
|
||||
}
|
191
vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features_test.go
generated
vendored
Normal file
191
vendor/k8s.io/kubernetes/cmd/kubeadm/app/features/features_test.go
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
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 features
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
)
|
||||
|
||||
func TestKnownFeatures(t *testing.T) {
|
||||
var someFeatures = FeatureList{
|
||||
"feature2": {FeatureSpec: utilfeature.FeatureSpec{Default: true, PreRelease: utilfeature.Alpha}},
|
||||
"feature1": {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Beta}},
|
||||
"feature3": {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.GA}},
|
||||
}
|
||||
|
||||
r := KnownFeatures(&someFeatures)
|
||||
|
||||
if len(r) != 3 {
|
||||
t.Errorf("KnownFeatures returned %d values, expected 3", len(r))
|
||||
}
|
||||
|
||||
// check the first value is feature1 (the list should be sorted); prerelease and default should be present
|
||||
f1 := "feature1=true|false (BETA - default=false)"
|
||||
if r[0] != f1 {
|
||||
t.Errorf("KnownFeatures returned %s values, expected %s", r[0], f1)
|
||||
}
|
||||
// check the second value is feature2; prerelease and default should be present
|
||||
f2 := "feature2=true|false (ALPHA - default=true)"
|
||||
if r[1] != f2 {
|
||||
t.Errorf("KnownFeatures returned %s values, expected %s", r[1], f2)
|
||||
}
|
||||
// check the second value is feature3; prerelease should not shown fo GA features; default should be present
|
||||
f3 := "feature3=true|false (default=false)"
|
||||
if r[2] != f3 {
|
||||
t.Errorf("KnownFeatures returned %s values, expected %s", r[2], f3)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFeatureGate(t *testing.T) {
|
||||
var someFeatures = FeatureList{
|
||||
"feature1": {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Beta}},
|
||||
"feature2": {FeatureSpec: utilfeature.FeatureSpec{Default: true, PreRelease: utilfeature.Alpha}},
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
value string
|
||||
expectedError bool
|
||||
expectedFeaturesGate map[string]bool
|
||||
}{
|
||||
{ //invalid value (missing =)
|
||||
value: "invalidValue",
|
||||
expectedError: true,
|
||||
},
|
||||
{ //invalid value (missing =)
|
||||
value: "feature1=true,invalidValue",
|
||||
expectedError: true,
|
||||
},
|
||||
{ //invalid value (not a boolean)
|
||||
value: "feature1=notABoolean",
|
||||
expectedError: true,
|
||||
},
|
||||
{ //invalid value (not a boolean)
|
||||
value: "feature1=true,feature2=notABoolean",
|
||||
expectedError: true,
|
||||
},
|
||||
{ //unrecognized feature-gate key
|
||||
value: "unknownFeature=false",
|
||||
expectedError: true,
|
||||
},
|
||||
{ //unrecognized feature-gate key
|
||||
value: "feature1=true,unknownFeature=false",
|
||||
expectedError: true,
|
||||
},
|
||||
{ //one feature
|
||||
value: "feature1=true",
|
||||
expectedError: false,
|
||||
expectedFeaturesGate: map[string]bool{"feature1": true},
|
||||
},
|
||||
{ //two features
|
||||
value: "feature1=true,feature2=false",
|
||||
expectedError: false,
|
||||
expectedFeaturesGate: map[string]bool{"feature1": true, "feature2": false},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
r, err := NewFeatureGate(&someFeatures, test.value)
|
||||
|
||||
if !test.expectedError && err != nil {
|
||||
t.Errorf("NewFeatureGate failed when not expected: %v", err)
|
||||
continue
|
||||
} else if test.expectedError && err == nil {
|
||||
t.Error("NewFeatureGate didn't failed when expected")
|
||||
continue
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(r, test.expectedFeaturesGate) {
|
||||
t.Errorf("NewFeatureGate returned a unexpected value")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateVersion(t *testing.T) {
|
||||
var someFeatures = FeatureList{
|
||||
"feature1": {FeatureSpec: utilfeature.FeatureSpec{Default: false, PreRelease: utilfeature.Beta}},
|
||||
"feature2": {FeatureSpec: utilfeature.FeatureSpec{Default: true, PreRelease: utilfeature.Alpha}, MinimumVersion: v190},
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
requestedVersion string
|
||||
requestedFeatures map[string]bool
|
||||
expectedError bool
|
||||
}{
|
||||
{ //no min version
|
||||
requestedFeatures: map[string]bool{"feature1": true},
|
||||
expectedError: false,
|
||||
},
|
||||
{ //min version but correct value given
|
||||
requestedFeatures: map[string]bool{"feature2": true},
|
||||
requestedVersion: "v1.9.0",
|
||||
expectedError: false,
|
||||
},
|
||||
{ //min version and incorrect value given
|
||||
requestedFeatures: map[string]bool{"feature2": true},
|
||||
requestedVersion: "v1.8.2",
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
err := ValidateVersion(someFeatures, test.requestedFeatures, test.requestedVersion)
|
||||
if !test.expectedError && err != nil {
|
||||
t.Errorf("ValidateVersion failed when not expected: %v", err)
|
||||
continue
|
||||
} else if test.expectedError && err == nil {
|
||||
t.Error("ValidateVersion didn't failed when expected")
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveFeatureGateDependencies(t *testing.T) {
|
||||
|
||||
var tests = []struct {
|
||||
inputFeatures map[string]bool
|
||||
expectedFeatures map[string]bool
|
||||
}{
|
||||
{ // no flags
|
||||
inputFeatures: map[string]bool{},
|
||||
expectedFeatures: map[string]bool{},
|
||||
},
|
||||
{ // others flags
|
||||
inputFeatures: map[string]bool{"SupportIPVSProxyMode": true},
|
||||
expectedFeatures: map[string]bool{"SupportIPVSProxyMode": true},
|
||||
},
|
||||
{ // just StoreCertsInSecrets flags
|
||||
inputFeatures: map[string]bool{"StoreCertsInSecrets": true},
|
||||
expectedFeatures: map[string]bool{"StoreCertsInSecrets": true, "SelfHosting": true},
|
||||
},
|
||||
{ // just HighAvailability flags
|
||||
inputFeatures: map[string]bool{"HighAvailability": true},
|
||||
expectedFeatures: map[string]bool{"HighAvailability": true, "StoreCertsInSecrets": true, "SelfHosting": true},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
ResolveFeatureGateDependencies(test.inputFeatures)
|
||||
if !reflect.DeepEqual(test.inputFeatures, test.expectedFeatures) {
|
||||
t.Errorf("ResolveFeatureGateDependencies failed, expected: %v, got: %v", test.inputFeatures, test.expectedFeatures)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
38
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/BUILD
generated
vendored
Normal file
38
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/BUILD
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["images.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/images",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["images_test.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/images",
|
||||
library = ":go_default_library",
|
||||
deps = ["//cmd/kubeadm/app/constants:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
44
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images.go
generated
vendored
Normal file
44
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
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 images
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
)
|
||||
|
||||
// GetCoreImage generates and returns the image for the core Kubernetes components or returns overrideImage if specified
|
||||
func GetCoreImage(image, repoPrefix, k8sVersion, overrideImage string) string {
|
||||
if overrideImage != "" {
|
||||
return overrideImage
|
||||
}
|
||||
kubernetesImageTag := kubeadmutil.KubernetesVersionToImageTag(k8sVersion)
|
||||
etcdImageTag := constants.DefaultEtcdVersion
|
||||
etcdImageVersion, err := constants.EtcdSupportedVersion(k8sVersion)
|
||||
if err == nil {
|
||||
etcdImageTag = etcdImageVersion.String()
|
||||
}
|
||||
return map[string]string{
|
||||
constants.Etcd: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "etcd", runtime.GOARCH, etcdImageTag),
|
||||
constants.KubeAPIServer: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-apiserver", runtime.GOARCH, kubernetesImageTag),
|
||||
constants.KubeControllerManager: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-controller-manager", runtime.GOARCH, kubernetesImageTag),
|
||||
constants.KubeScheduler: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-scheduler", runtime.GOARCH, kubernetesImageTag),
|
||||
}[image]
|
||||
}
|
75
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images_test.go
generated
vendored
Normal file
75
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images_test.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
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 images
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
testversion = "v10.1.2-alpha.1.100+0123456789abcdef+SOMETHING"
|
||||
expected = "v10.1.2-alpha.1.100_0123456789abcdef_SOMETHING"
|
||||
gcrPrefix = "gcr.io/google_containers"
|
||||
)
|
||||
|
||||
func TestGetCoreImage(t *testing.T) {
|
||||
var tests = []struct {
|
||||
image, repo, version, override, expected string
|
||||
}{
|
||||
{
|
||||
override: "override",
|
||||
expected: "override",
|
||||
},
|
||||
{
|
||||
image: constants.Etcd,
|
||||
repo: gcrPrefix,
|
||||
expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "etcd", runtime.GOARCH, constants.DefaultEtcdVersion),
|
||||
},
|
||||
{
|
||||
image: constants.KubeAPIServer,
|
||||
repo: gcrPrefix,
|
||||
version: testversion,
|
||||
expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, expected),
|
||||
},
|
||||
{
|
||||
image: constants.KubeControllerManager,
|
||||
repo: gcrPrefix,
|
||||
version: testversion,
|
||||
expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, expected),
|
||||
},
|
||||
{
|
||||
image: constants.KubeScheduler,
|
||||
repo: gcrPrefix,
|
||||
version: testversion,
|
||||
expected: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, expected),
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := GetCoreImage(rt.image, rt.repo, rt.version, rt.override)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed GetCoreImage:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
37
vendor/k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go
generated
vendored
Normal file
37
vendor/k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
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 app
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
_ "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd"
|
||||
)
|
||||
|
||||
// Run creates and executes new kubeadm command
|
||||
func Run() error {
|
||||
// We do not want these flags to show up in --help
|
||||
pflag.CommandLine.MarkHidden("version")
|
||||
pflag.CommandLine.MarkHidden("google-json-key")
|
||||
pflag.CommandLine.MarkHidden("log-flush-frequency")
|
||||
|
||||
cmd := cmd.NewKubeadmCommand(os.Stdin, os.Stdout, os.Stderr)
|
||||
return cmd.Execute()
|
||||
}
|
66
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/BUILD
generated
vendored
Normal file
66
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/BUILD
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"dns_test.go",
|
||||
"versions_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/util/version:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors: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",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"dns.go",
|
||||
"manifests.go",
|
||||
"versions.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns",
|
||||
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/util:go_default_library",
|
||||
"//cmd/kubeadm/app/util/apiclient:go_default_library",
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/util/version:go_default_library",
|
||||
"//vendor/k8s.io/api/apps/v1beta2:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/rbac/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:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
247
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns.go
generated
vendored
Normal file
247
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns.go
generated
vendored
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
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 dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
apps "k8s.io/api/apps/v1beta2"
|
||||
"k8s.io/api/core/v1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kuberuntime "k8s.io/apimachinery/pkg/runtime"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/features"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
const (
|
||||
// KubeDNSServiceAccountName describes the name of the ServiceAccount for the kube-dns addon
|
||||
KubeDNSServiceAccountName = "kube-dns"
|
||||
)
|
||||
|
||||
// EnsureDNSAddon creates the kube-dns or CoreDNS addon
|
||||
func EnsureDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error {
|
||||
k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't parse kubernetes version %q: %v", cfg.KubernetesVersion, err)
|
||||
}
|
||||
if features.Enabled(cfg.FeatureGates, features.CoreDNS) {
|
||||
return coreDNSAddon(cfg, client, k8sVersion)
|
||||
}
|
||||
return kubeDNSAddon(cfg, client, k8sVersion)
|
||||
}
|
||||
|
||||
func kubeDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface, k8sVersion *version.Version) error {
|
||||
if err := CreateServiceAccount(client); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dnsip, err := kubeadmconstants.GetDNSIP(cfg.Networking.ServiceSubnet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var dnsBindAddr, dnsProbeAddr string
|
||||
if dnsip.To4() == nil {
|
||||
dnsBindAddr = "::1"
|
||||
dnsProbeAddr = "[" + dnsBindAddr + "]"
|
||||
} else {
|
||||
dnsBindAddr = "127.0.0.1"
|
||||
dnsProbeAddr = dnsBindAddr
|
||||
}
|
||||
|
||||
// Get the YAML manifest conditionally based on the k8s version
|
||||
kubeDNSDeploymentBytes := GetKubeDNSManifest(k8sVersion)
|
||||
dnsDeploymentBytes, err := kubeadmutil.ParseTemplate(kubeDNSDeploymentBytes,
|
||||
struct{ ImageRepository, Arch, Version, DNSBindAddr, DNSProbeAddr, DNSDomain, DNSProbeType, MasterTaintKey string }{
|
||||
ImageRepository: cfg.ImageRepository,
|
||||
Arch: runtime.GOARCH,
|
||||
// Get the kube-dns version conditionally based on the k8s version
|
||||
Version: GetDNSVersion(k8sVersion, kubeadmconstants.KubeDNS),
|
||||
DNSBindAddr: dnsBindAddr,
|
||||
DNSProbeAddr: dnsProbeAddr,
|
||||
DNSDomain: cfg.Networking.DNSDomain,
|
||||
DNSProbeType: GetKubeDNSProbeType(k8sVersion),
|
||||
MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when parsing kube-dns deployment template: %v", err)
|
||||
}
|
||||
|
||||
dnsServiceBytes, err := kubeadmutil.ParseTemplate(KubeDNSService, struct{ DNSIP string }{
|
||||
DNSIP: dnsip.String(),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when parsing kube-proxy configmap template: %v", err)
|
||||
}
|
||||
|
||||
if err := createKubeDNSAddon(dnsDeploymentBytes, dnsServiceBytes, client); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("[addons] Applied essential addon: kube-dns")
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateServiceAccount creates the necessary serviceaccounts that kubeadm uses/might use, if they don't already exist.
|
||||
func CreateServiceAccount(client clientset.Interface) error {
|
||||
|
||||
return apiclient.CreateOrUpdateServiceAccount(client, &v1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: KubeDNSServiceAccountName,
|
||||
Namespace: metav1.NamespaceSystem,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func createKubeDNSAddon(deploymentBytes, serviceBytes []byte, client clientset.Interface) error {
|
||||
kubednsDeployment := &apps.Deployment{}
|
||||
if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), deploymentBytes, kubednsDeployment); err != nil {
|
||||
return fmt.Errorf("unable to decode kube-dns deployment %v", err)
|
||||
}
|
||||
|
||||
// Create the Deployment for kube-dns or update it in case it already exists
|
||||
if err := apiclient.CreateOrUpdateDeployment(client, kubednsDeployment); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kubednsService := &v1.Service{}
|
||||
return createDNSService(kubednsService, serviceBytes, client)
|
||||
}
|
||||
|
||||
func coreDNSAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface, k8sVersion *version.Version) error {
|
||||
// Get the YAML manifest conditionally based on the k8s version
|
||||
dnsDeploymentBytes := GetCoreDNSManifest(k8sVersion)
|
||||
coreDNSDeploymentBytes, err := kubeadmutil.ParseTemplate(dnsDeploymentBytes, struct{ MasterTaintKey, Version string }{
|
||||
MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster,
|
||||
Version: GetDNSVersion(k8sVersion, kubeadmconstants.CoreDNS),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when parsing CoreDNS deployment template: %v", err)
|
||||
}
|
||||
|
||||
// Get the config file for CoreDNS
|
||||
coreDNSConfigMapBytes, err := kubeadmutil.ParseTemplate(CoreDNSConfigMap, struct{ DNSDomain, ServiceCIDR string }{
|
||||
ServiceCIDR: cfg.Networking.ServiceSubnet,
|
||||
DNSDomain: cfg.Networking.DNSDomain,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when parsing CoreDNS configMap template: %v", err)
|
||||
}
|
||||
|
||||
dnsip, err := kubeadmconstants.GetDNSIP(cfg.Networking.ServiceSubnet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
coreDNSServiceBytes, err := kubeadmutil.ParseTemplate(KubeDNSService, struct{ DNSIP string }{
|
||||
DNSIP: dnsip.String(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when parsing CoreDNS service template: %v", err)
|
||||
}
|
||||
|
||||
if err := createCoreDNSAddon(coreDNSDeploymentBytes, coreDNSServiceBytes, coreDNSConfigMapBytes, client); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("[addons] Applied essential addon: CoreDNS")
|
||||
return nil
|
||||
}
|
||||
|
||||
func createCoreDNSAddon(deploymentBytes, serviceBytes, configBytes []byte, client clientset.Interface) error {
|
||||
coreDNSConfigMap := &v1.ConfigMap{}
|
||||
if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), configBytes, coreDNSConfigMap); err != nil {
|
||||
return fmt.Errorf("unable to decode CoreDNS configmap %v", err)
|
||||
}
|
||||
|
||||
// Create the ConfigMap for CoreDNS or update it in case it already exists
|
||||
if err := apiclient.CreateOrUpdateConfigMap(client, coreDNSConfigMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
coreDNSClusterRoles := &rbac.ClusterRole{}
|
||||
if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), []byte(CoreDNSClusterRole), coreDNSClusterRoles); err != nil {
|
||||
return fmt.Errorf("unable to decode CoreDNS clusterroles %v", err)
|
||||
}
|
||||
|
||||
// Create the Clusterroles for CoreDNS or update it in case it already exists
|
||||
if err := apiclient.CreateOrUpdateClusterRole(client, coreDNSClusterRoles); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
coreDNSClusterRolesBinding := &rbac.ClusterRoleBinding{}
|
||||
if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), []byte(CoreDNSClusterRoleBinding), coreDNSClusterRolesBinding); err != nil {
|
||||
return fmt.Errorf("unable to decode CoreDNS clusterrolebindings %v", err)
|
||||
}
|
||||
|
||||
// Create the Clusterrolebindings for CoreDNS or update it in case it already exists
|
||||
if err := apiclient.CreateOrUpdateClusterRoleBinding(client, coreDNSClusterRolesBinding); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
coreDNSServiceAccount := &v1.ServiceAccount{}
|
||||
if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), []byte(CoreDNSServiceAccount), coreDNSServiceAccount); err != nil {
|
||||
return fmt.Errorf("unable to decode CoreDNS configmap %v", err)
|
||||
}
|
||||
|
||||
// Create the ConfigMap for CoreDNS or update it in case it already exists
|
||||
if err := apiclient.CreateOrUpdateServiceAccount(client, coreDNSServiceAccount); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
coreDNSDeployment := &apps.Deployment{}
|
||||
if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), deploymentBytes, coreDNSDeployment); err != nil {
|
||||
return fmt.Errorf("unable to decode CoreDNS deployment %v", err)
|
||||
}
|
||||
|
||||
// Create the Deployment for CoreDNS or update it in case it already exists
|
||||
if err := apiclient.CreateOrUpdateDeployment(client, coreDNSDeployment); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
coreDNSService := &v1.Service{}
|
||||
return createDNSService(coreDNSService, serviceBytes, client)
|
||||
}
|
||||
|
||||
func createDNSService(dnsService *v1.Service, serviceBytes []byte, client clientset.Interface) error {
|
||||
if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), serviceBytes, dnsService); err != nil {
|
||||
return fmt.Errorf("unable to decode the DNS service %v", err)
|
||||
}
|
||||
|
||||
// Can't use a generic apiclient helper func here as we have to tolerate more than AlreadyExists.
|
||||
if _, err := client.CoreV1().Services(metav1.NamespaceSystem).Create(dnsService); err != nil {
|
||||
// Ignore if the Service is invalid with this error message:
|
||||
// Service "kube-dns" is invalid: spec.clusterIP: Invalid value: "10.96.0.10": provided IP is already allocated
|
||||
|
||||
if !apierrors.IsAlreadyExists(err) && !apierrors.IsInvalid(err) {
|
||||
return fmt.Errorf("unable to create a new DNS service: %v", err)
|
||||
}
|
||||
|
||||
if _, err := client.CoreV1().Services(metav1.NamespaceSystem).Update(dnsService); err != nil {
|
||||
return fmt.Errorf("unable to create/update the DNS service: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
178
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns_test.go
generated
vendored
Normal file
178
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/dns_test.go
generated
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
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 dns
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
clientsetfake "k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
func TestCreateServiceAccount(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
createErr error
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
"error-free case",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"duplication errors should be ignored",
|
||||
apierrors.NewAlreadyExists(api.Resource(""), ""),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"unexpected errors should be returned",
|
||||
apierrors.NewUnauthorized(""),
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
client := clientsetfake.NewSimpleClientset()
|
||||
if tc.createErr != nil {
|
||||
client.PrependReactor("create", "serviceaccounts", func(action core.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, tc.createErr
|
||||
})
|
||||
}
|
||||
|
||||
err := CreateServiceAccount(client)
|
||||
if tc.expectErr {
|
||||
if err == nil {
|
||||
t.Errorf("CreateServiceAccounts(%s) wanted err, got nil", tc.name)
|
||||
}
|
||||
continue
|
||||
} else if !tc.expectErr && err != nil {
|
||||
t.Errorf("CreateServiceAccounts(%s) returned unexpected err: %v", tc.name, err)
|
||||
}
|
||||
|
||||
wantResourcesCreated := 1
|
||||
if len(client.Actions()) != wantResourcesCreated {
|
||||
t.Errorf("CreateServiceAccounts(%s) should have made %d actions, but made %d", tc.name, wantResourcesCreated, len(client.Actions()))
|
||||
}
|
||||
|
||||
for _, action := range client.Actions() {
|
||||
if action.GetVerb() != "create" || action.GetResource().Resource != "serviceaccounts" {
|
||||
t.Errorf("CreateServiceAccounts(%s) called [%v %v], but wanted [create serviceaccounts]",
|
||||
tc.name, action.GetVerb(), action.GetResource().Resource)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompileManifests(t *testing.T) {
|
||||
var tests = []struct {
|
||||
manifest string
|
||||
data interface{}
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
manifest: v180AndAboveKubeDNSDeployment,
|
||||
data: struct{ ImageRepository, Arch, Version, DNSBindAddr, DNSProbeAddr, DNSDomain, DNSProbeType, MasterTaintKey string }{
|
||||
ImageRepository: "foo",
|
||||
Arch: "foo",
|
||||
Version: "foo",
|
||||
DNSBindAddr: "foo",
|
||||
DNSProbeAddr: "foo",
|
||||
DNSDomain: "foo",
|
||||
DNSProbeType: "foo",
|
||||
MasterTaintKey: "foo",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
manifest: KubeDNSService,
|
||||
data: struct{ DNSIP string }{
|
||||
DNSIP: "foo",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
manifest: CoreDNSDeployment,
|
||||
data: struct{ MasterTaintKey, Version string }{
|
||||
MasterTaintKey: "foo",
|
||||
Version: "foo",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
manifest: KubeDNSService,
|
||||
data: struct{ DNSIP string }{
|
||||
DNSIP: "foo",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
manifest: CoreDNSConfigMap,
|
||||
data: struct{ DNSDomain, ServiceCIDR string }{
|
||||
DNSDomain: "foo",
|
||||
ServiceCIDR: "foo",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
_, actual := kubeadmutil.ParseTemplate(rt.manifest, rt.data)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed CompileManifests:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDNSIP(t *testing.T) {
|
||||
var tests = []struct {
|
||||
svcSubnet, expectedDNSIP string
|
||||
}{
|
||||
{
|
||||
svcSubnet: "10.96.0.0/12",
|
||||
expectedDNSIP: "10.96.0.10",
|
||||
},
|
||||
{
|
||||
svcSubnet: "10.87.116.64/26",
|
||||
expectedDNSIP: "10.87.116.74",
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
dnsIP, err := kubeadmconstants.GetDNSIP(rt.svcSubnet)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't get dnsIP : %v", err)
|
||||
}
|
||||
|
||||
actualDNSIP := dnsIP.String()
|
||||
if actualDNSIP != rt.expectedDNSIP {
|
||||
t.Errorf(
|
||||
"failed GetDNSIP\n\texpected: %s\n\t actual: %s",
|
||||
rt.expectedDNSIP,
|
||||
actualDNSIP,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
347
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/manifests.go
generated
vendored
Normal file
347
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/manifests.go
generated
vendored
Normal file
@ -0,0 +1,347 @@
|
||||
/*
|
||||
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 dns
|
||||
|
||||
const (
|
||||
// v180AndAboveKubeDNSDeployment is the kube-dns Deployment manifest for the kube-dns manifest for v1.7+
|
||||
v180AndAboveKubeDNSDeployment = `
|
||||
apiVersion: apps/v1beta2
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kube-dns
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: kube-dns
|
||||
spec:
|
||||
# replicas: not specified here:
|
||||
# 1. In order to make Addon Manager do not reconcile this replicas parameter.
|
||||
# 2. Default is 1.
|
||||
# 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 10%
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: kube-dns
|
||||
spec:
|
||||
volumes:
|
||||
- name: kube-dns-config
|
||||
configMap:
|
||||
name: kube-dns
|
||||
optional: true
|
||||
containers:
|
||||
- name: kubedns
|
||||
image: {{ .ImageRepository }}/k8s-dns-kube-dns-{{ .Arch }}:{{ .Version }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
resources:
|
||||
# TODO: Set memory limits when we've profiled the container for large
|
||||
# clusters, then set request = limit to keep this container in
|
||||
# guaranteed class. Currently, this container falls into the
|
||||
# "burstable" category so the kubelet doesn't backoff from restarting it.
|
||||
limits:
|
||||
memory: 170Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 70Mi
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthcheck/kubedns
|
||||
port: 10054
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 5
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /readiness
|
||||
port: 8081
|
||||
scheme: HTTP
|
||||
# we poll on pod startup for the Kubernetes master service and
|
||||
# only setup the /readiness HTTP server once that's available.
|
||||
initialDelaySeconds: 3
|
||||
timeoutSeconds: 5
|
||||
args:
|
||||
- --domain={{ .DNSDomain }}.
|
||||
- --dns-port=10053
|
||||
- --config-dir=/kube-dns-config
|
||||
- --v=2
|
||||
env:
|
||||
- name: PROMETHEUS_PORT
|
||||
value: "10055"
|
||||
ports:
|
||||
- containerPort: 10053
|
||||
name: dns-local
|
||||
protocol: UDP
|
||||
- containerPort: 10053
|
||||
name: dns-tcp-local
|
||||
protocol: TCP
|
||||
- containerPort: 10055
|
||||
name: metrics
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: kube-dns-config
|
||||
mountPath: /kube-dns-config
|
||||
- name: dnsmasq
|
||||
image: {{ .ImageRepository }}/k8s-dns-dnsmasq-nanny-{{ .Arch }}:{{ .Version }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthcheck/dnsmasq
|
||||
port: 10054
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 5
|
||||
args:
|
||||
- -v=2
|
||||
- -logtostderr
|
||||
- -configDir=/etc/k8s/dns/dnsmasq-nanny
|
||||
- -restartDnsmasq=true
|
||||
- --
|
||||
- -k
|
||||
- --cache-size=1000
|
||||
- --no-negcache
|
||||
- --log-facility=-
|
||||
- --server=/{{ .DNSDomain }}/{{ .DNSBindAddr }}#10053
|
||||
- --server=/in-addr.arpa/{{ .DNSBindAddr }}#10053
|
||||
- --server=/ip6.arpa/{{ .DNSBindAddr }}#10053
|
||||
ports:
|
||||
- containerPort: 53
|
||||
name: dns
|
||||
protocol: UDP
|
||||
- containerPort: 53
|
||||
name: dns-tcp
|
||||
protocol: TCP
|
||||
# see: https://github.com/kubernetes/kubernetes/issues/29055 for details
|
||||
resources:
|
||||
requests:
|
||||
cpu: 150m
|
||||
memory: 20Mi
|
||||
volumeMounts:
|
||||
- name: kube-dns-config
|
||||
mountPath: /etc/k8s/dns/dnsmasq-nanny
|
||||
- name: sidecar
|
||||
image: {{ .ImageRepository }}/k8s-dns-sidecar-{{ .Arch }}:{{ .Version }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /metrics
|
||||
port: 10054
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 5
|
||||
args:
|
||||
- --v=2
|
||||
- --logtostderr
|
||||
- --probe=kubedns,{{ .DNSProbeAddr }}:10053,kubernetes.default.svc.{{ .DNSDomain }},5,{{ .DNSProbeType }}
|
||||
- --probe=dnsmasq,{{ .DNSProbeAddr }}:53,kubernetes.default.svc.{{ .DNSDomain }},5,{{ .DNSProbeType }}
|
||||
ports:
|
||||
- containerPort: 10054
|
||||
name: metrics
|
||||
protocol: TCP
|
||||
resources:
|
||||
requests:
|
||||
memory: 20Mi
|
||||
cpu: 10m
|
||||
dnsPolicy: Default # Don't use cluster DNS.
|
||||
serviceAccountName: kube-dns
|
||||
tolerations:
|
||||
- key: CriticalAddonsOnly
|
||||
operator: Exists
|
||||
- key: {{ .MasterTaintKey }}
|
||||
effect: NoSchedule
|
||||
# TODO: Remove this affinity field as soon as we are using manifest lists
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: beta.kubernetes.io/arch
|
||||
operator: In
|
||||
values:
|
||||
- {{ .Arch }}
|
||||
`
|
||||
|
||||
// KubeDNSService is the kube-dns Service manifest
|
||||
KubeDNSService = `
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: kube-dns
|
||||
kubernetes.io/cluster-service: "true"
|
||||
kubernetes.io/name: "KubeDNS"
|
||||
name: kube-dns
|
||||
namespace: kube-system
|
||||
# Without this resourceVersion value, an update of the Service between versions will yield:
|
||||
# Service "kube-dns" is invalid: metadata.resourceVersion: Invalid value: "": must be specified for an update
|
||||
resourceVersion: "0"
|
||||
spec:
|
||||
clusterIP: {{ .DNSIP }}
|
||||
ports:
|
||||
- name: dns
|
||||
port: 53
|
||||
protocol: UDP
|
||||
targetPort: 53
|
||||
- name: dns-tcp
|
||||
port: 53
|
||||
protocol: TCP
|
||||
targetPort: 53
|
||||
selector:
|
||||
k8s-app: kube-dns
|
||||
`
|
||||
|
||||
// CoreDNSDeployment is the CoreDNS Deployment manifest
|
||||
CoreDNSDeployment = `
|
||||
apiVersion: apps/v1beta2
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: coredns
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: kube-dns
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: kube-dns
|
||||
spec:
|
||||
serviceAccountName: coredns
|
||||
tolerations:
|
||||
- key: CriticalAddonsOnly
|
||||
operator: Exists
|
||||
- key: {{ .MasterTaintKey }}
|
||||
effect: NoSchedule
|
||||
containers:
|
||||
- name: coredns
|
||||
image: coredns/coredns:{{ .Version }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
resources:
|
||||
limits:
|
||||
memory: 170Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 70Mi
|
||||
args: [ "-conf", "/etc/coredns/Corefile" ]
|
||||
volumeMounts:
|
||||
- name: config-volume
|
||||
mountPath: /etc/coredns
|
||||
ports:
|
||||
- containerPort: 53
|
||||
name: dns
|
||||
protocol: UDP
|
||||
- containerPort: 53
|
||||
name: dns-tcp
|
||||
protocol: TCP
|
||||
- containerPort: 9153
|
||||
name: metrics
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health
|
||||
port: 8080
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 5
|
||||
dnsPolicy: Default
|
||||
volumes:
|
||||
- name: config-volume
|
||||
configMap:
|
||||
name: coredns
|
||||
items:
|
||||
- key: Corefile
|
||||
path: Corefile
|
||||
`
|
||||
|
||||
// CoreDNSConfigMap is the CoreDNS ConfigMap manifest
|
||||
CoreDNSConfigMap = `
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: coredns
|
||||
namespace: kube-system
|
||||
data:
|
||||
Corefile: |
|
||||
.:53 {
|
||||
errors
|
||||
log
|
||||
health
|
||||
kubernetes {{ .DNSDomain }} {{ .ServiceCIDR }} {
|
||||
pods insecure
|
||||
}
|
||||
prometheus
|
||||
proxy . /etc/resolv.conf
|
||||
cache 30
|
||||
}
|
||||
`
|
||||
// CoreDNSClusterRole is the CoreDNS ClusterRole manifest
|
||||
CoreDNSClusterRole = `
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: system:coredns
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- endpoints
|
||||
- services
|
||||
- pods
|
||||
- namespaces
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
`
|
||||
// CoreDNSClusterRoleBinding is the CoreDNS Clusterrolebinding manifest
|
||||
CoreDNSClusterRoleBinding = `
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: system:coredns
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:coredns
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: coredns
|
||||
namespace: kube-system
|
||||
`
|
||||
// CoreDNSServiceAccount is the CoreDNS ServiceAccount manifest
|
||||
CoreDNSServiceAccount = `
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: coredns
|
||||
namespace: kube-system
|
||||
`
|
||||
)
|
79
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/versions.go
generated
vendored
Normal file
79
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/versions.go
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
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 dns
|
||||
|
||||
import (
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
const (
|
||||
kubeDNSv180AndAboveVersion = "1.14.5"
|
||||
kubeDNSv190AndAboveVersion = "1.14.7"
|
||||
|
||||
kubeDNSProbeSRV = "SRV"
|
||||
kubeDNSProbeA = "A"
|
||||
coreDNSVersion = "1.0.1"
|
||||
)
|
||||
|
||||
// GetDNSVersion returns the right kube-dns version for a specific k8s version
|
||||
func GetDNSVersion(kubeVersion *version.Version, dns string) string {
|
||||
// v1.8.0+ uses kube-dns 1.14.5
|
||||
// v1.9.0+ uses kube-dns 1.14.7
|
||||
// v1.9.0+ uses CoreDNS 1.0.1
|
||||
|
||||
// In the future when the version is bumped at HEAD; add conditional logic to return the right versions
|
||||
// Also, the version might be bumped for different k8s releases on the same branch
|
||||
switch dns {
|
||||
case kubeadmconstants.KubeDNS:
|
||||
// return the kube-dns version
|
||||
if kubeVersion.Major() == 1 && kubeVersion.Minor() >= 9 {
|
||||
return kubeDNSv190AndAboveVersion
|
||||
}
|
||||
return kubeDNSv180AndAboveVersion
|
||||
case kubeadmconstants.CoreDNS:
|
||||
// return the CoreDNS version
|
||||
return coreDNSVersion
|
||||
default:
|
||||
return kubeDNSv180AndAboveVersion
|
||||
}
|
||||
}
|
||||
|
||||
// GetKubeDNSProbeType returns the right kube-dns probe for a specific k8s version
|
||||
func GetKubeDNSProbeType(kubeVersion *version.Version) string {
|
||||
// v1.8.0+ uses type A, just return that here
|
||||
// In the future when the kube-dns version is bumped at HEAD; add conditional logic to return the right versions
|
||||
// Also, the version might be bumped for different k8s releases on the same branch
|
||||
if kubeVersion.Major() == 1 && kubeVersion.Minor() >= 9 {
|
||||
return kubeDNSProbeSRV
|
||||
}
|
||||
return kubeDNSProbeA
|
||||
}
|
||||
|
||||
// GetKubeDNSManifest returns the right kube-dns YAML manifest for a specific k8s version
|
||||
func GetKubeDNSManifest(kubeVersion *version.Version) string {
|
||||
// v1.8.0+ has only one known YAML manifest spec, just return that here
|
||||
// In the future when the kube-dns version is bumped at HEAD; add conditional logic to return the right manifest
|
||||
return v180AndAboveKubeDNSDeployment
|
||||
}
|
||||
|
||||
// GetCoreDNSManifest returns the right CoreDNS YAML manifest for a specific k8s version
|
||||
func GetCoreDNSManifest(kubeVersion *version.Version) string {
|
||||
// v1.9.0+ has only one known YAML manifest spec, just return that here
|
||||
// In the future when the CoreDNS version is bumped at HEAD; add conditional logic to return the right manifest
|
||||
return CoreDNSDeployment
|
||||
}
|
126
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/versions_test.go
generated
vendored
Normal file
126
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/dns/versions_test.go
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
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 dns
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
func TestGetKubeDNSVersion(t *testing.T) {
|
||||
var tests = []struct {
|
||||
k8sVersion, expected string
|
||||
}{
|
||||
{
|
||||
k8sVersion: "v1.7.0",
|
||||
expected: "1.14.5",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.7.1",
|
||||
expected: "1.14.5",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.7.2",
|
||||
expected: "1.14.5",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.7.3",
|
||||
expected: "1.14.5",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.8.0-alpha.2",
|
||||
expected: "1.14.5",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.8.0",
|
||||
expected: "1.14.5",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.9.0",
|
||||
expected: "1.14.7",
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
|
||||
k8sVersion, err := version.ParseSemantic(rt.k8sVersion)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't parse kubernetes version %q: %v", rt.k8sVersion, err)
|
||||
}
|
||||
|
||||
actualDNSVersion := GetDNSVersion(k8sVersion, kubeadmconstants.KubeDNS)
|
||||
if actualDNSVersion != rt.expected {
|
||||
t.Errorf(
|
||||
"failed GetDNSVersion:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actualDNSVersion,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetKubeDNSProbeType(t *testing.T) {
|
||||
var tests = []struct {
|
||||
k8sVersion, expected string
|
||||
}{
|
||||
{
|
||||
k8sVersion: "v1.7.0",
|
||||
expected: "A",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.7.1",
|
||||
expected: "A",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.7.2",
|
||||
expected: "A",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.7.3",
|
||||
expected: "A",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.8.0-alpha.2",
|
||||
expected: "A",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.8.0",
|
||||
expected: "A",
|
||||
},
|
||||
{
|
||||
k8sVersion: "v1.9.0",
|
||||
expected: "SRV",
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
|
||||
k8sVersion, err := version.ParseSemantic(rt.k8sVersion)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't parse kubernetes version %q: %v", rt.k8sVersion, err)
|
||||
}
|
||||
|
||||
actualDNSProbeType := GetKubeDNSProbeType(k8sVersion)
|
||||
if actualDNSProbeType != rt.expected {
|
||||
t.Errorf(
|
||||
"failed GetKubeDNSProbeType:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actualDNSProbeType,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
66
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/BUILD
generated
vendored
Normal file
66
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/BUILD
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["proxy_test.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//cmd/kubeadm/app/util/config:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
|
||||
"//pkg/util/pointer: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",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"manifests.go",
|
||||
"proxy.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/constants:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//cmd/kubeadm/app/util/apiclient:go_default_library",
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library",
|
||||
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
|
||||
"//pkg/util/version:go_default_library",
|
||||
"//plugin/pkg/scheduler/algorithm:go_default_library",
|
||||
"//vendor/k8s.io/api/apps/v1beta2:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/rbac/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/client-go/kubernetes:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
201
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/manifests.go
generated
vendored
Normal file
201
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/manifests.go
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
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 proxy
|
||||
|
||||
const (
|
||||
// KubeProxyConfigMap18 is the proxy ConfigMap manifest for Kubernetes version 1.8
|
||||
KubeProxyConfigMap18 = `
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kube-proxy
|
||||
namespace: kube-system
|
||||
labels:
|
||||
app: kube-proxy
|
||||
data:
|
||||
kubeconfig.conf: |
|
||||
apiVersion: v1
|
||||
kind: Config
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
server: {{ .MasterEndpoint }}
|
||||
name: default
|
||||
contexts:
|
||||
- context:
|
||||
cluster: default
|
||||
namespace: default
|
||||
user: default
|
||||
name: default
|
||||
current-context: default
|
||||
users:
|
||||
- name: default
|
||||
user:
|
||||
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
`
|
||||
|
||||
// KubeProxyConfigMap19 is the proxy ConfigMap manifest for Kubernetes 1.9 and above
|
||||
KubeProxyConfigMap19 = `
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: kube-proxy
|
||||
namespace: kube-system
|
||||
labels:
|
||||
app: kube-proxy
|
||||
data:
|
||||
kubeconfig.conf: |-
|
||||
apiVersion: v1
|
||||
kind: Config
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
server: {{ .MasterEndpoint }}
|
||||
name: default
|
||||
contexts:
|
||||
- context:
|
||||
cluster: default
|
||||
namespace: default
|
||||
user: default
|
||||
name: default
|
||||
current-context: default
|
||||
users:
|
||||
- name: default
|
||||
user:
|
||||
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
config.conf: |-
|
||||
{{ .ProxyConfig}}
|
||||
`
|
||||
// KubeProxyDaemonSet18 is the proxy DaemonSet manifest for Kubernetes version 1.8
|
||||
KubeProxyDaemonSet18 = `
|
||||
apiVersion: apps/v1beta2
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: kube-proxy
|
||||
name: kube-proxy
|
||||
namespace: kube-system
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: kube-proxy
|
||||
updateStrategy:
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: kube-proxy
|
||||
spec:
|
||||
containers:
|
||||
- name: kube-proxy
|
||||
image: {{ if .ImageOverride }}{{ .ImageOverride }}{{ else }}{{ .ImageRepository }}/kube-proxy-{{ .Arch }}:{{ .Version }}{{ end }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /usr/local/bin/kube-proxy
|
||||
- --kubeconfig=/var/lib/kube-proxy/kubeconfig.conf
|
||||
{{ .ClusterCIDR }}
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/kube-proxy
|
||||
name: kube-proxy
|
||||
- mountPath: /run/xtables.lock
|
||||
name: xtables-lock
|
||||
readOnly: false
|
||||
- mountPath: /lib/modules
|
||||
name: lib-modules
|
||||
readOnly: true
|
||||
hostNetwork: true
|
||||
serviceAccountName: kube-proxy
|
||||
tolerations:
|
||||
- key: {{ .MasterTaintKey }}
|
||||
effect: NoSchedule
|
||||
- key: {{ .CloudTaintKey }}
|
||||
value: "true"
|
||||
effect: NoSchedule
|
||||
volumes:
|
||||
- name: kube-proxy
|
||||
configMap:
|
||||
name: kube-proxy
|
||||
- name: xtables-lock
|
||||
hostPath:
|
||||
path: /run/xtables.lock
|
||||
type: FileOrCreate
|
||||
- name: lib-modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
`
|
||||
|
||||
// KubeProxyDaemonSet19 is the proxy DaemonSet manifest for Kubernetes 1.9 and above
|
||||
KubeProxyDaemonSet19 = `
|
||||
apiVersion: apps/v1beta2
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: kube-proxy
|
||||
name: kube-proxy
|
||||
namespace: kube-system
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: kube-proxy
|
||||
updateStrategy:
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: kube-proxy
|
||||
spec:
|
||||
containers:
|
||||
- name: kube-proxy
|
||||
image: {{ if .ImageOverride }}{{ .ImageOverride }}{{ else }}{{ .ImageRepository }}/kube-proxy-{{ .Arch }}:{{ .Version }}{{ end }}
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /usr/local/bin/kube-proxy
|
||||
- --config=/var/lib/kube-proxy/config.conf
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- mountPath: /var/lib/kube-proxy
|
||||
name: kube-proxy
|
||||
- mountPath: /run/xtables.lock
|
||||
name: xtables-lock
|
||||
readOnly: false
|
||||
- mountPath: /lib/modules
|
||||
name: lib-modules
|
||||
readOnly: true
|
||||
hostNetwork: true
|
||||
serviceAccountName: kube-proxy
|
||||
tolerations:
|
||||
- key: {{ .MasterTaintKey }}
|
||||
effect: NoSchedule
|
||||
- key: {{ .CloudTaintKey }}
|
||||
value: "true"
|
||||
effect: NoSchedule
|
||||
volumes:
|
||||
- name: kube-proxy
|
||||
configMap:
|
||||
name: kube-proxy
|
||||
- name: xtables-lock
|
||||
hostPath:
|
||||
path: /run/xtables.lock
|
||||
type: FileOrCreate
|
||||
- name: lib-modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
`
|
||||
)
|
191
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy.go
generated
vendored
Normal file
191
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy.go
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
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 proxy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
apps "k8s.io/api/apps/v1beta2"
|
||||
"k8s.io/api/core/v1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kuberuntime "k8s.io/apimachinery/pkg/runtime"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
kubeproxyconfigscheme "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/scheme"
|
||||
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
||||
)
|
||||
|
||||
const (
|
||||
// KubeProxyClusterRoleName sets the name for the kube-proxy ClusterRole
|
||||
// TODO: This k8s-generic, well-known constant should be fetchable from another source, not be in this package
|
||||
KubeProxyClusterRoleName = "system:node-proxier"
|
||||
|
||||
// KubeProxyServiceAccountName describes the name of the ServiceAccount for the kube-proxy addon
|
||||
KubeProxyServiceAccountName = "kube-proxy"
|
||||
)
|
||||
|
||||
// EnsureProxyAddon creates the kube-proxy addons
|
||||
func EnsureProxyAddon(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error {
|
||||
if err := CreateServiceAccount(client); err != nil {
|
||||
return fmt.Errorf("error when creating kube-proxy service account: %v", err)
|
||||
}
|
||||
|
||||
// Generate Master Enpoint kubeconfig file
|
||||
masterEndpoint, err := kubeadmutil.GetMasterEndpoint(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
proxyBytes, err := kubeadmutil.MarshalToYamlForCodecsWithShift(cfg.KubeProxy.Config, kubeproxyconfigv1alpha1.SchemeGroupVersion,
|
||||
kubeproxyconfigscheme.Codecs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when marshaling: %v", err)
|
||||
}
|
||||
// Parse the given kubernetes version
|
||||
k8sVersion, err := version.ParseSemantic(cfg.KubernetesVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't parse kubernetes version %q: %v", cfg.KubernetesVersion, err)
|
||||
}
|
||||
var proxyConfigMapBytes, proxyDaemonSetBytes []byte
|
||||
if k8sVersion.AtLeast(kubeadmconstants.MinimumKubeProxyComponentConfigVersion) {
|
||||
proxyConfigMapBytes, err = kubeadmutil.ParseTemplate(KubeProxyConfigMap19,
|
||||
struct {
|
||||
MasterEndpoint string
|
||||
ProxyConfig string
|
||||
}{
|
||||
MasterEndpoint: masterEndpoint,
|
||||
ProxyConfig: proxyBytes,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when parsing kube-proxy configmap template: %v", err)
|
||||
}
|
||||
proxyDaemonSetBytes, err = kubeadmutil.ParseTemplate(KubeProxyDaemonSet19, struct{ ImageRepository, Arch, Version, ImageOverride, ClusterCIDR, MasterTaintKey, CloudTaintKey string }{
|
||||
ImageRepository: cfg.GetControlPlaneImageRepository(),
|
||||
Arch: runtime.GOARCH,
|
||||
Version: kubeadmutil.KubernetesVersionToImageTag(cfg.KubernetesVersion),
|
||||
ImageOverride: cfg.UnifiedControlPlaneImage,
|
||||
MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster,
|
||||
CloudTaintKey: algorithm.TaintExternalCloudProvider,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when parsing kube-proxy daemonset template: %v", err)
|
||||
}
|
||||
} else {
|
||||
proxyConfigMapBytes, err = kubeadmutil.ParseTemplate(KubeProxyConfigMap18,
|
||||
struct {
|
||||
MasterEndpoint string
|
||||
}{
|
||||
MasterEndpoint: masterEndpoint,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when parsing kube-proxy configmap template: %v", err)
|
||||
}
|
||||
|
||||
proxyDaemonSetBytes, err = kubeadmutil.ParseTemplate(KubeProxyDaemonSet18, struct{ ImageRepository, Arch, Version, ImageOverride, ClusterCIDR, MasterTaintKey, CloudTaintKey string }{
|
||||
ImageRepository: cfg.GetControlPlaneImageRepository(),
|
||||
Arch: runtime.GOARCH,
|
||||
Version: kubeadmutil.KubernetesVersionToImageTag(cfg.KubernetesVersion),
|
||||
ImageOverride: cfg.UnifiedControlPlaneImage,
|
||||
ClusterCIDR: getClusterCIDR(cfg.Networking.PodSubnet),
|
||||
MasterTaintKey: kubeadmconstants.LabelNodeRoleMaster,
|
||||
CloudTaintKey: algorithm.TaintExternalCloudProvider,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when parsing kube-proxy daemonset template: %v", err)
|
||||
}
|
||||
}
|
||||
if err := createKubeProxyAddon(proxyConfigMapBytes, proxyDaemonSetBytes, client); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := CreateRBACRules(client); err != nil {
|
||||
return fmt.Errorf("error when creating kube-proxy RBAC rules: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("[addons] Applied essential addon: kube-proxy")
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateServiceAccount creates the necessary serviceaccounts that kubeadm uses/might use, if they don't already exist.
|
||||
func CreateServiceAccount(client clientset.Interface) error {
|
||||
|
||||
return apiclient.CreateOrUpdateServiceAccount(client, &v1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: KubeProxyServiceAccountName,
|
||||
Namespace: metav1.NamespaceSystem,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// CreateRBACRules creates the essential RBAC rules for a minimally set-up cluster
|
||||
func CreateRBACRules(client clientset.Interface) error {
|
||||
return createClusterRoleBindings(client)
|
||||
}
|
||||
|
||||
func createKubeProxyAddon(configMapBytes, daemonSetbytes []byte, client clientset.Interface) error {
|
||||
kubeproxyConfigMap := &v1.ConfigMap{}
|
||||
if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), configMapBytes, kubeproxyConfigMap); err != nil {
|
||||
return fmt.Errorf("unable to decode kube-proxy configmap %v", err)
|
||||
}
|
||||
|
||||
// Create the ConfigMap for kube-proxy or update it in case it already exists
|
||||
if err := apiclient.CreateOrUpdateConfigMap(client, kubeproxyConfigMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kubeproxyDaemonSet := &apps.DaemonSet{}
|
||||
if err := kuberuntime.DecodeInto(legacyscheme.Codecs.UniversalDecoder(), daemonSetbytes, kubeproxyDaemonSet); err != nil {
|
||||
return fmt.Errorf("unable to decode kube-proxy daemonset %v", err)
|
||||
}
|
||||
|
||||
// Create the DaemonSet for kube-proxy or update it in case it already exists
|
||||
return apiclient.CreateOrUpdateDaemonSet(client, kubeproxyDaemonSet)
|
||||
}
|
||||
|
||||
func createClusterRoleBindings(client clientset.Interface) error {
|
||||
return apiclient.CreateOrUpdateClusterRoleBinding(client, &rbac.ClusterRoleBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "kubeadm:node-proxier",
|
||||
},
|
||||
RoleRef: rbac.RoleRef{
|
||||
APIGroup: rbac.GroupName,
|
||||
Kind: "ClusterRole",
|
||||
Name: KubeProxyClusterRoleName,
|
||||
},
|
||||
Subjects: []rbac.Subject{
|
||||
{
|
||||
Kind: rbac.ServiceAccountKind,
|
||||
Name: KubeProxyServiceAccountName,
|
||||
Namespace: metav1.NamespaceSystem,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func getClusterCIDR(podsubnet string) string {
|
||||
if len(podsubnet) == 0 {
|
||||
return ""
|
||||
}
|
||||
return "- --cluster-cidr=" + podsubnet
|
||||
}
|
293
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go
generated
vendored
Normal file
293
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy/proxy_test.go
generated
vendored
Normal file
@ -0,0 +1,293 @@
|
||||
/*
|
||||
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 proxy
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
clientsetfake "k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/util/pointer"
|
||||
)
|
||||
|
||||
func TestCreateServiceAccount(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
createErr error
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
"error-free case",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"duplication errors should be ignored",
|
||||
apierrors.NewAlreadyExists(api.Resource(""), ""),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"unexpected errors should be returned",
|
||||
apierrors.NewUnauthorized(""),
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
client := clientsetfake.NewSimpleClientset()
|
||||
if tc.createErr != nil {
|
||||
client.PrependReactor("create", "serviceaccounts", func(action core.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, tc.createErr
|
||||
})
|
||||
}
|
||||
|
||||
err := CreateServiceAccount(client)
|
||||
if tc.expectErr {
|
||||
if err == nil {
|
||||
t.Errorf("CreateServiceAccounts(%s) wanted err, got nil", tc.name)
|
||||
}
|
||||
continue
|
||||
} else if !tc.expectErr && err != nil {
|
||||
t.Errorf("CreateServiceAccounts(%s) returned unexpected err: %v", tc.name, err)
|
||||
}
|
||||
|
||||
wantResourcesCreated := 1
|
||||
if len(client.Actions()) != wantResourcesCreated {
|
||||
t.Errorf("CreateServiceAccounts(%s) should have made %d actions, but made %d", tc.name, wantResourcesCreated, len(client.Actions()))
|
||||
}
|
||||
|
||||
for _, action := range client.Actions() {
|
||||
if action.GetVerb() != "create" || action.GetResource().Resource != "serviceaccounts" {
|
||||
t.Errorf("CreateServiceAccounts(%s) called [%v %v], but wanted [create serviceaccounts]",
|
||||
tc.name, action.GetVerb(), action.GetResource().Resource)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetClusterCIDR(t *testing.T) {
|
||||
emptyClusterCIDR := getClusterCIDR("")
|
||||
if emptyClusterCIDR != "" {
|
||||
t.Errorf("Invalid format: %s", emptyClusterCIDR)
|
||||
}
|
||||
|
||||
clusterCIDR := getClusterCIDR("10.244.0.0/16")
|
||||
if clusterCIDR != "- --cluster-cidr=10.244.0.0/16" {
|
||||
t.Errorf("Invalid format: %s", clusterCIDR)
|
||||
}
|
||||
|
||||
clusterIPv6CIDR := getClusterCIDR("2001:db8::/64")
|
||||
if clusterIPv6CIDR != "- --cluster-cidr=2001:db8::/64" {
|
||||
t.Errorf("Invalid format: %s", clusterIPv6CIDR)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompileManifests(t *testing.T) {
|
||||
var tests = []struct {
|
||||
manifest string
|
||||
data interface{}
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
manifest: KubeProxyConfigMap18,
|
||||
data: struct {
|
||||
MasterEndpoint, ProxyConfig string
|
||||
}{
|
||||
MasterEndpoint: "foo",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
manifest: KubeProxyConfigMap19,
|
||||
data: struct {
|
||||
MasterEndpoint, ProxyConfig string
|
||||
}{
|
||||
MasterEndpoint: "foo",
|
||||
ProxyConfig: " bindAddress: 0.0.0.0\n clusterCIDR: 192.168.1.1\n enableProfiling: false",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
manifest: KubeProxyDaemonSet18,
|
||||
data: struct{ ImageRepository, Arch, Version, ImageOverride, ClusterCIDR, MasterTaintKey, CloudTaintKey string }{
|
||||
ImageRepository: "foo",
|
||||
Arch: "foo",
|
||||
Version: "foo",
|
||||
ImageOverride: "foo",
|
||||
ClusterCIDR: "foo",
|
||||
MasterTaintKey: "foo",
|
||||
CloudTaintKey: "foo",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
manifest: KubeProxyDaemonSet19,
|
||||
data: struct{ ImageRepository, Arch, Version, ImageOverride, MasterTaintKey, CloudTaintKey string }{
|
||||
ImageRepository: "foo",
|
||||
Arch: "foo",
|
||||
Version: "foo",
|
||||
ImageOverride: "foo",
|
||||
MasterTaintKey: "foo",
|
||||
CloudTaintKey: "foo",
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
_, actual := kubeadmutil.ParseTemplate(rt.manifest, rt.data)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed to compile %s manifest:\n\texpected: %t\n\t actual: %t",
|
||||
rt.manifest,
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureProxyAddon(t *testing.T) {
|
||||
type SimulatedError int
|
||||
const (
|
||||
NoError SimulatedError = iota
|
||||
ServiceAccountError
|
||||
InvalidMasterEndpoint
|
||||
IPv6SetBindAddress
|
||||
)
|
||||
|
||||
var testCases = []struct {
|
||||
name string
|
||||
simError SimulatedError
|
||||
expErrString string
|
||||
expBindAddr string
|
||||
expClusterCIDR string
|
||||
}{
|
||||
{
|
||||
name: "Successful proxy addon",
|
||||
simError: NoError,
|
||||
expErrString: "",
|
||||
expBindAddr: "0.0.0.0",
|
||||
expClusterCIDR: "5.6.7.8/24",
|
||||
}, {
|
||||
name: "Simulated service account error",
|
||||
simError: ServiceAccountError,
|
||||
expErrString: "error when creating kube-proxy service account",
|
||||
expBindAddr: "0.0.0.0",
|
||||
expClusterCIDR: "5.6.7.8/24",
|
||||
}, {
|
||||
name: "IPv6 AdvertiseAddress address",
|
||||
simError: IPv6SetBindAddress,
|
||||
expErrString: "",
|
||||
expBindAddr: "::",
|
||||
expClusterCIDR: "2001:101::/96",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
// Create a fake client and set up default test configuration
|
||||
client := clientsetfake.NewSimpleClientset()
|
||||
|
||||
masterConfig := &kubeadmapiext.MasterConfiguration{
|
||||
API: kubeadmapiext.API{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
BindPort: 1234,
|
||||
},
|
||||
KubeProxy: kubeadmapiext.KubeProxy{
|
||||
Config: &kubeproxyconfigv1alpha1.KubeProxyConfiguration{
|
||||
BindAddress: "",
|
||||
HealthzBindAddress: "0.0.0.0:10256",
|
||||
MetricsBindAddress: "127.0.0.1:10249",
|
||||
Conntrack: kubeproxyconfigv1alpha1.KubeProxyConntrackConfiguration{
|
||||
Max: pointer.Int32Ptr(2),
|
||||
MaxPerCore: pointer.Int32Ptr(1),
|
||||
Min: pointer.Int32Ptr(1),
|
||||
TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
TCPCloseWaitTimeout: &metav1.Duration{Duration: 5 * time.Second},
|
||||
},
|
||||
},
|
||||
},
|
||||
Networking: kubeadmapiext.Networking{
|
||||
PodSubnet: "5.6.7.8/24",
|
||||
},
|
||||
ImageRepository: "someRepo",
|
||||
KubernetesVersion: "v1.9.0",
|
||||
UnifiedControlPlaneImage: "someImage",
|
||||
}
|
||||
|
||||
// Simulate an error if neccessary
|
||||
switch tc.simError {
|
||||
case ServiceAccountError:
|
||||
client.PrependReactor("create", "serviceaccounts", func(action core.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, apierrors.NewUnauthorized("")
|
||||
})
|
||||
case InvalidMasterEndpoint:
|
||||
masterConfig.API.AdvertiseAddress = "1.2.3"
|
||||
case IPv6SetBindAddress:
|
||||
masterConfig.API.AdvertiseAddress = "1:2::3:4"
|
||||
masterConfig.Networking.PodSubnet = "2001:101::/96"
|
||||
}
|
||||
|
||||
kubeadmapiext.SetDefaults_MasterConfiguration(masterConfig)
|
||||
intMaster, err := cmdutil.ConfigFileAndDefaultsToInternalConfig("", masterConfig)
|
||||
if err != nil {
|
||||
t.Errorf(" test failed to convert v1alpha1 to internal version")
|
||||
break
|
||||
}
|
||||
err = EnsureProxyAddon(intMaster, client)
|
||||
|
||||
// Compare actual to expected errors
|
||||
actErr := "No error"
|
||||
if err != nil {
|
||||
actErr = err.Error()
|
||||
}
|
||||
expErr := "No error"
|
||||
if tc.expErrString != "" {
|
||||
expErr = tc.expErrString
|
||||
}
|
||||
if !strings.Contains(actErr, expErr) {
|
||||
t.Errorf(
|
||||
"%s test failed, expected: %s, got: %s",
|
||||
tc.name,
|
||||
expErr,
|
||||
actErr)
|
||||
}
|
||||
if intMaster.KubeProxy.Config.BindAddress != tc.expBindAddr {
|
||||
t.Errorf("%s test failed, expected: %s, got: %s",
|
||||
tc.name,
|
||||
tc.expBindAddr,
|
||||
intMaster.KubeProxy.Config.BindAddress)
|
||||
}
|
||||
if intMaster.KubeProxy.Config.ClusterCIDR != tc.expClusterCIDR {
|
||||
t.Errorf("%s test failed, expected: %s, got: %s",
|
||||
tc.name,
|
||||
tc.expClusterCIDR,
|
||||
intMaster.KubeProxy.Config.ClusterCIDR)
|
||||
}
|
||||
}
|
||||
}
|
52
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/BUILD
generated
vendored
Normal file
52
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/BUILD
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["clusterinfo_test.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors: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",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["clusterinfo.go"],
|
||||
importpath = "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo",
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/util/apiclient:go_default_library",
|
||||
"//pkg/apis/rbac/v1:go_default_library",
|
||||
"//pkg/bootstrap/api:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
105
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go
generated
vendored
Normal file
105
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo.go
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
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 clusterinfo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
|
||||
rbachelper "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||
bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api"
|
||||
)
|
||||
|
||||
const (
|
||||
// BootstrapSignerClusterRoleName sets the name for the ClusterRole that allows access to ConfigMaps in the kube-public ns
|
||||
BootstrapSignerClusterRoleName = "kubeadm:bootstrap-signer-clusterinfo"
|
||||
)
|
||||
|
||||
// CreateBootstrapConfigMapIfNotExists creates the kube-public ConfigMap if it doesn't exist already
|
||||
func CreateBootstrapConfigMapIfNotExists(client clientset.Interface, file string) error {
|
||||
|
||||
fmt.Printf("[bootstraptoken] Creating the %q ConfigMap in the %q namespace\n", bootstrapapi.ConfigMapClusterInfo, metav1.NamespacePublic)
|
||||
|
||||
adminConfig, err := clientcmd.LoadFromFile(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load admin kubeconfig [%v]", err)
|
||||
}
|
||||
|
||||
adminCluster := adminConfig.Contexts[adminConfig.CurrentContext].Cluster
|
||||
// Copy the cluster from admin.conf to the bootstrap kubeconfig, contains the CA cert and the server URL
|
||||
bootstrapConfig := &clientcmdapi.Config{
|
||||
Clusters: map[string]*clientcmdapi.Cluster{
|
||||
"": adminConfig.Clusters[adminCluster],
|
||||
},
|
||||
}
|
||||
bootstrapBytes, err := clientcmd.Write(*bootstrapConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create or update the ConfigMap in the kube-public namespace
|
||||
return apiclient.CreateOrUpdateConfigMap(client, &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: bootstrapapi.ConfigMapClusterInfo,
|
||||
Namespace: metav1.NamespacePublic,
|
||||
},
|
||||
Data: map[string]string{
|
||||
bootstrapapi.KubeConfigKey: string(bootstrapBytes),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// CreateClusterInfoRBACRules creates the RBAC rules for exposing the cluster-info ConfigMap in the kube-public namespace to unauthenticated users
|
||||
func CreateClusterInfoRBACRules(client clientset.Interface) error {
|
||||
err := apiclient.CreateOrUpdateRole(client, &rbac.Role{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: BootstrapSignerClusterRoleName,
|
||||
Namespace: metav1.NamespacePublic,
|
||||
},
|
||||
Rules: []rbac.PolicyRule{
|
||||
rbachelper.NewRule("get").Groups("").Resources("configmaps").Names(bootstrapapi.ConfigMapClusterInfo).RuleOrDie(),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return apiclient.CreateOrUpdateRoleBinding(client, &rbac.RoleBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: BootstrapSignerClusterRoleName,
|
||||
Namespace: metav1.NamespacePublic,
|
||||
},
|
||||
RoleRef: rbac.RoleRef{
|
||||
APIGroup: rbac.GroupName,
|
||||
Kind: "Role",
|
||||
Name: BootstrapSignerClusterRoleName,
|
||||
},
|
||||
Subjects: []rbac.Subject{
|
||||
{
|
||||
Kind: rbac.UserKind,
|
||||
Name: user.Anonymous,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
113
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo_test.go
generated
vendored
Normal file
113
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo/clusterinfo_test.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
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 clusterinfo
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"text/template"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
clientsetfake "k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
var testConfigTempl = template.Must(template.New("test").Parse(`apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
server: {{.Server}}
|
||||
name: kubernetes
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kubernetes
|
||||
user: kubernetes-admin
|
||||
name: kubernetes-admin@kubernetes
|
||||
current-context: kubernetes-admin@kubernetes
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: kubernetes-admin`))
|
||||
|
||||
func TestCreateBootstrapConfigMapIfNotExists(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
createErr error
|
||||
updateErr error
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
"successful case should have no error",
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"if both create and update errors, return error",
|
||||
apierrors.NewAlreadyExists(api.Resource("configmaps"), "test"),
|
||||
apierrors.NewUnauthorized("go away!"),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"unexpected error should be returned",
|
||||
apierrors.NewUnauthorized("go away!"),
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
servers := []struct {
|
||||
Server string
|
||||
}{
|
||||
{Server: "https://10.128.0.6:6443"},
|
||||
{Server: "https://[2001:db8::6]:3446"},
|
||||
}
|
||||
|
||||
for _, server := range servers {
|
||||
file, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("could not create tempfile: %v", err)
|
||||
}
|
||||
defer os.Remove(file.Name())
|
||||
|
||||
if err := testConfigTempl.Execute(file, server); err != nil {
|
||||
t.Fatalf("could not write to tempfile: %v", err)
|
||||
}
|
||||
|
||||
if err := file.Close(); err != nil {
|
||||
t.Fatalf("could not close tempfile: %v", err)
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
client := clientsetfake.NewSimpleClientset()
|
||||
if tc.createErr != nil {
|
||||
client.PrependReactor("create", "configmaps", func(action core.Action) (bool, runtime.Object, error) {
|
||||
return true, nil, tc.createErr
|
||||
})
|
||||
}
|
||||
|
||||
err := CreateBootstrapConfigMapIfNotExists(client, file.Name())
|
||||
if tc.expectErr && err == nil {
|
||||
t.Errorf("CreateBootstrapConfigMapIfNotExists(%s) wanted error, got nil", tc.name)
|
||||
} else if !tc.expectErr && err != nil {
|
||||
t.Errorf("CreateBootstrapConfigMapIfNotExists(%s) returned unexpected error: %v", tc.name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user