Switch to github.com/golang/dep for vendoring
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
This commit is contained in:
parent
d6ab91be27
commit
8e5b17cf13
15431 changed files with 3971413 additions and 8881 deletions
39
vendor/k8s.io/kubernetes/cmd/kubeadm/BUILD
generated
vendored
Normal file
39
vendor/k8s.io/kubernetes/cmd/kubeadm/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "kubeadm",
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["kubeadm.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//cmd/kubeadm/app:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//cmd/kubeadm/app:all-srcs",
|
||||
"//cmd/kubeadm/test:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
13
vendor/k8s.io/kubernetes/cmd/kubeadm/OWNERS
generated
vendored
Normal file
13
vendor/k8s.io/kubernetes/cmd/kubeadm/OWNERS
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
approvers:
|
||||
- errordeveloper
|
||||
- jbeda
|
||||
- luxas
|
||||
- mikedanese
|
||||
reviewers:
|
||||
- mikedanese
|
||||
- luxas
|
||||
- justinsb
|
||||
- errordeveloper
|
||||
- pires
|
||||
- lukemarsden
|
||||
- dgoodwin
|
45
vendor/k8s.io/kubernetes/cmd/kubeadm/app/BUILD
generated
vendored
Normal file
45
vendor/k8s.io/kubernetes/cmd/kubeadm/app/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["kubeadm.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/install:go_default_library",
|
||||
"//cmd/kubeadm/app/cmd:go_default_library",
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
"//vendor:github.com/spf13/pflag",
|
||||
],
|
||||
)
|
||||
|
||||
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/discovery:all-srcs",
|
||||
"//cmd/kubeadm/app/images:all-srcs",
|
||||
"//cmd/kubeadm/app/master:all-srcs",
|
||||
"//cmd/kubeadm/app/node:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/certs:all-srcs",
|
||||
"//cmd/kubeadm/app/phases/kubeconfig:all-srcs",
|
||||
"//cmd/kubeadm/app/preflight:all-srcs",
|
||||
"//cmd/kubeadm/app/util:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
43
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/BUILD
generated
vendored
Normal file
43
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"env.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-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"],
|
||||
)
|
18
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/doc.go
generated
vendored
Normal file
18
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// +groupName=kubeadm.k8s.io
|
||||
package kubeadm // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
58
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/env.go
generated
vendored
Normal file
58
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/env.go
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var GlobalEnvParams = SetEnvParams()
|
||||
|
||||
// TODO(phase1+) Move these paramaters to the API group
|
||||
// we need some params for testing etc, let's keep these hidden for now
|
||||
func SetEnvParams() *EnvParams {
|
||||
|
||||
envParams := map[string]string{
|
||||
"kubernetes_dir": "/etc/kubernetes",
|
||||
"host_pki_path": "/etc/kubernetes/pki",
|
||||
"host_etcd_path": "/var/lib/etcd",
|
||||
"hyperkube_image": "",
|
||||
"repo_prefix": "gcr.io/google_containers",
|
||||
"discovery_image": fmt.Sprintf("gcr.io/google_containers/kube-discovery-%s:%s", runtime.GOARCH, "1.0"),
|
||||
"etcd_image": "",
|
||||
}
|
||||
|
||||
for k := range envParams {
|
||||
if v := strings.TrimSpace(os.Getenv(fmt.Sprintf("KUBE_%s", strings.ToUpper(k)))); v != "" {
|
||||
envParams[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return &EnvParams{
|
||||
KubernetesDir: path.Clean(envParams["kubernetes_dir"]),
|
||||
HostPKIPath: path.Clean(envParams["host_pki_path"]),
|
||||
HostEtcdPath: path.Clean(envParams["host_etcd_path"]),
|
||||
HyperkubeImage: envParams["hyperkube_image"],
|
||||
RepositoryPrefix: envParams["repo_prefix"],
|
||||
DiscoveryImage: envParams["discovery_image"],
|
||||
EtcdImage: envParams["etcd_image"],
|
||||
}
|
||||
}
|
35
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/BUILD
generated
vendored
Normal file
35
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"install.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//pkg/apimachinery/announced:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
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"
|
39
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install.go
generated
vendored
Normal file
39
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/install.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
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"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/announced"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := announced.NewGroupMetaFactory(
|
||||
&announced.GroupMetaFactoryArgs{
|
||||
GroupName: kubeadm.GroupName,
|
||||
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
|
||||
ImportPrefix: "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm",
|
||||
AddInternalObjectsToScheme: kubeadm.AddToScheme,
|
||||
},
|
||||
announced.VersionToSchemeFunc{
|
||||
v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme,
|
||||
},
|
||||
).Announce().RegisterAndEnable(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
61
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/register.go
generated
vendored
Normal file
61
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/register.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
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"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// 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 = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
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{},
|
||||
&ClusterInfo{},
|
||||
&api.ListOptions{},
|
||||
&api.DeleteOptions{},
|
||||
&metav1.ExportOptions{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (obj *MasterConfiguration) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *NodeConfiguration) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ClusterInfo) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
|
95
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/types.go
generated
vendored
Normal file
95
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/types.go
generated
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
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"
|
||||
)
|
||||
|
||||
type EnvParams struct {
|
||||
KubernetesDir string
|
||||
HostPKIPath string
|
||||
HostEtcdPath string
|
||||
HyperkubeImage string
|
||||
RepositoryPrefix string
|
||||
DiscoveryImage string
|
||||
EtcdImage string
|
||||
}
|
||||
|
||||
type MasterConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
API API
|
||||
Discovery Discovery
|
||||
Etcd Etcd
|
||||
Networking Networking
|
||||
KubernetesVersion string
|
||||
CloudProvider string
|
||||
}
|
||||
|
||||
type API struct {
|
||||
AdvertiseAddresses []string
|
||||
ExternalDNSNames []string
|
||||
Port int32
|
||||
}
|
||||
|
||||
type Discovery struct {
|
||||
HTTPS *HTTPSDiscovery
|
||||
File *FileDiscovery
|
||||
Token *TokenDiscovery
|
||||
}
|
||||
|
||||
type HTTPSDiscovery struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
type FileDiscovery struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
type TokenDiscovery struct {
|
||||
ID string
|
||||
Secret string
|
||||
Addresses []string
|
||||
}
|
||||
|
||||
type Networking struct {
|
||||
ServiceSubnet string
|
||||
PodSubnet string
|
||||
DNSDomain string
|
||||
}
|
||||
|
||||
type Etcd struct {
|
||||
Endpoints []string
|
||||
CAFile string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
}
|
||||
|
||||
type NodeConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
Discovery Discovery
|
||||
}
|
||||
|
||||
// ClusterInfo TODO add description
|
||||
type ClusterInfo struct {
|
||||
metav1.TypeMeta
|
||||
// TODO(phase1+) this may become simply `api.Config`
|
||||
CertificateAuthorities []string
|
||||
Endpoints []string
|
||||
}
|
39
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD
generated
vendored
Normal file
39
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"defaults.go",
|
||||
"doc.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
"zz_generated.defaults.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
59
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go
generated
vendored
Normal file
59
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
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 (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultServiceDNSDomain = "cluster.local"
|
||||
DefaultServicesSubnet = "10.96.0.0/12"
|
||||
DefaultKubernetesVersion = "stable"
|
||||
DefaultKubernetesFallbackVersion = "v1.5.0"
|
||||
DefaultAPIBindPort = 6443
|
||||
DefaultDiscoveryBindPort = 9898
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
RegisterDefaults(scheme)
|
||||
return scheme.AddDefaultingFuncs(
|
||||
SetDefaults_MasterConfiguration,
|
||||
)
|
||||
}
|
||||
|
||||
func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
|
||||
if obj.KubernetesVersion == "" {
|
||||
obj.KubernetesVersion = DefaultKubernetesVersion
|
||||
}
|
||||
|
||||
if obj.API.Port == 0 {
|
||||
obj.API.Port = DefaultAPIBindPort
|
||||
}
|
||||
|
||||
if obj.Networking.ServiceSubnet == "" {
|
||||
obj.Networking.ServiceSubnet = DefaultServicesSubnet
|
||||
}
|
||||
|
||||
if obj.Networking.DNSDomain == "" {
|
||||
obj.Networking.DNSDomain = DefaultServiceDNSDomain
|
||||
}
|
||||
|
||||
if obj.Discovery.Token == nil && obj.Discovery.File == nil && obj.Discovery.HTTPS == nil {
|
||||
obj.Discovery.Token = &TokenDiscovery{}
|
||||
}
|
||||
}
|
19
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=kubeadm.k8s.io
|
||||
package v1alpha1 // import "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
61
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/register.go
generated
vendored
Normal file
61
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/register.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
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"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
// 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 (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs)
|
||||
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{},
|
||||
&ClusterInfo{},
|
||||
&v1.ListOptions{},
|
||||
&v1.DeleteOptions{},
|
||||
&metav1.ExportOptions{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (obj *MasterConfiguration) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *NodeConfiguration) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ClusterInfo) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
|
85
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go
generated
vendored
Normal file
85
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
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"
|
||||
)
|
||||
|
||||
type MasterConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
API API `json:"api"`
|
||||
Discovery Discovery `json:"discovery"`
|
||||
Etcd Etcd `json:"etcd"`
|
||||
Networking Networking `json:"networking"`
|
||||
KubernetesVersion string `json:"kubernetesVersion"`
|
||||
CloudProvider string `json:"cloudProvider"`
|
||||
}
|
||||
|
||||
type API struct {
|
||||
AdvertiseAddresses []string `json:"advertiseAddresses"`
|
||||
ExternalDNSNames []string `json:"externalDNSNames"`
|
||||
Port int32 `json:"port"`
|
||||
}
|
||||
|
||||
type Discovery struct {
|
||||
HTTPS *HTTPSDiscovery `json:"https"`
|
||||
File *FileDiscovery `json:"file"`
|
||||
Token *TokenDiscovery `json:"token"`
|
||||
}
|
||||
|
||||
type HTTPSDiscovery struct {
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
type FileDiscovery struct {
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
type TokenDiscovery struct {
|
||||
ID string `json:"id"`
|
||||
Secret string `json:"secret"`
|
||||
Addresses []string `json:"addresses"`
|
||||
}
|
||||
|
||||
type Networking struct {
|
||||
ServiceSubnet string `json:"serviceSubnet"`
|
||||
PodSubnet string `json:"podSubnet"`
|
||||
DNSDomain string `json:"dnsDomain"`
|
||||
}
|
||||
|
||||
type Etcd struct {
|
||||
Endpoints []string `json:"endpoints"`
|
||||
CAFile string `json:"caFile"`
|
||||
CertFile string `json:"certFile"`
|
||||
KeyFile string `json:"keyFile"`
|
||||
}
|
||||
|
||||
type NodeConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
Discovery Discovery `json:"discovery"`
|
||||
}
|
||||
|
||||
// ClusterInfo TODO add description
|
||||
type ClusterInfo struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// TODO(phase1+) this may become simply `api.Config`
|
||||
CertificateAuthorities []string `json:"certificateAuthorities"`
|
||||
Endpoints []string `json:"endpoints"`
|
||||
}
|
37
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.defaults.go
generated
vendored
Normal file
37
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.defaults.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by defaulter-gen. Do not edit it manually!
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&MasterConfiguration{}, func(obj interface{}) { SetObjectDefaults_MasterConfiguration(obj.(*MasterConfiguration)) })
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_MasterConfiguration(in *MasterConfiguration) {
|
||||
SetDefaults_MasterConfiguration(in)
|
||||
}
|
31
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/BUILD
generated
vendored
Normal file
31
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["validation.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
70
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation.go
generated
vendored
Normal file
70
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation/validation.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
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 (
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateDiscovery(&c.Discovery, field.NewPath("discovery"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateDiscovery(&c.Discovery, field.NewPath("discovery"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateDiscovery(c *kubeadm.Discovery, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
var count int
|
||||
if c.Token != nil {
|
||||
allErrs = append(allErrs, ValidateTokenDiscovery(c.Token, fldPath)...)
|
||||
count++
|
||||
}
|
||||
if c.File != nil {
|
||||
allErrs = append(allErrs, ValidateFileDiscovery(c.File, fldPath)...)
|
||||
count++
|
||||
}
|
||||
if c.HTTPS != nil {
|
||||
allErrs = append(allErrs, ValidateHTTPSDiscovery(c.HTTPS, fldPath)...)
|
||||
count++
|
||||
}
|
||||
if count != 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, nil, "exactly one discovery strategy can be provided"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateFileDiscovery(c *kubeadm.FileDiscovery, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateHTTPSDiscovery(c *kubeadm.HTTPSDiscovery, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateTokenDiscovery(c *kubeadm.TokenDiscovery, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
return allErrs
|
||||
}
|
74
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/BUILD
generated
vendored
Normal file
74
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cmd.go",
|
||||
"init.go",
|
||||
"join.go",
|
||||
"reset.go",
|
||||
"token.go",
|
||||
"version.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
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/flags:go_default_library",
|
||||
"//cmd/kubeadm/app/discovery:go_default_library",
|
||||
"//cmd/kubeadm/app/master:go_default_library",
|
||||
"//cmd/kubeadm/app/node:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/certs:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/kubectl:go_default_library",
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
"//pkg/util/flag:go_default_library",
|
||||
"//pkg/util/initsystem:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
"//vendor:github.com/renstrom/dedent",
|
||||
"//vendor:github.com/spf13/cobra",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"reset_test.go",
|
||||
"token_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = ["//cmd/kubeadm/app/preflight: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/flags: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"
|
||||
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/util/flag"
|
||||
)
|
||||
|
||||
func NewKubeadmCommand(f cmdutil.Factory, in 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 ALPHA, DO NOT USE IT FOR PRODUCTION CLUSTERS! │
|
||||
│ │
|
||||
│ But, please try it out! Give us feedback at: │
|
||||
│ https://github.com/kubernetes/kubeadm/issues │
|
||||
│ and at-mention @kubernetes/sig-cluster-lifecycle │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
|
||||
Example usage:
|
||||
|
||||
Create a two-machine cluster with one master (which controls the cluster),
|
||||
and one node (where your workloads, like Pods and ReplicaSets run).
|
||||
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ On the first machine │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ master# kubeadm init │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ On the second machine │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ node# kubeadm join --token=<token> <ip-of-master> │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
|
||||
You can then repeat the second step on as many other machines as you like.
|
||||
|
||||
`),
|
||||
}
|
||||
// TODO(phase2+) figure out how to avoid running as root
|
||||
//
|
||||
// TODO(phase2) detect interactive vs non-interactive use and adjust output accordingly
|
||||
// i.e. make it automation friendly
|
||||
//
|
||||
// TODO(phase2) create an abstraction that defines files and the content that needs to
|
||||
// be written to disc and write it all in one go at the end as we have a lot of
|
||||
// crappy little files written from different parts of this code; this could also
|
||||
// be useful for testing by having this model we can allow users to create some files before
|
||||
// `kubeadm init` runs, e.g. PKI assets, we would then be able to look at files users has
|
||||
// given an diff or validate if those are sane, we could also warn if any of the files had been deprecated
|
||||
|
||||
cmds.ResetFlags()
|
||||
cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc)
|
||||
|
||||
cmds.AddCommand(NewCmdInit(out))
|
||||
cmds.AddCommand(NewCmdJoin(out))
|
||||
cmds.AddCommand(NewCmdReset(out))
|
||||
cmds.AddCommand(NewCmdVersion(out))
|
||||
|
||||
// Wrap not yet usable/supported commands in experimental sub-command:
|
||||
experimentalCmd := &cobra.Command{
|
||||
Use: "ex",
|
||||
Short: "Experimental sub-commands not yet fully functional.",
|
||||
}
|
||||
experimentalCmd.AddCommand(NewCmdToken(out, err))
|
||||
cmds.AddCommand(experimentalCmd)
|
||||
|
||||
return cmds
|
||||
}
|
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/flags/BUILD
generated
vendored
Normal file
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/flags/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["cloudprovider.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//vendor:github.com/spf13/pflag"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
70
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/flags/cloudprovider.go
generated
vendored
Normal file
70
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/flags/cloudprovider.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
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 flags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var cloudproviders = []string{
|
||||
"aws",
|
||||
"azure",
|
||||
"cloudstack",
|
||||
"gce",
|
||||
"mesos",
|
||||
"openstack",
|
||||
"ovirt",
|
||||
"photon",
|
||||
"rackspace",
|
||||
"vsphere",
|
||||
}
|
||||
|
||||
func NewCloudProviderFlag(provider *string) pflag.Value {
|
||||
return &cloudProviderValue{provider: provider}
|
||||
}
|
||||
|
||||
type cloudProviderValue struct {
|
||||
provider *string
|
||||
}
|
||||
|
||||
func (c *cloudProviderValue) String() string {
|
||||
return *c.provider
|
||||
}
|
||||
|
||||
func (c *cloudProviderValue) Set(s string) error {
|
||||
if ValidateCloudProvider(s) {
|
||||
*c.provider = s
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("cloud provider %q is not supported, you can use any of %v", s, cloudproviders)
|
||||
}
|
||||
|
||||
func (c *cloudProviderValue) Type() string {
|
||||
return "cloudprovider"
|
||||
}
|
||||
|
||||
func ValidateCloudProvider(provider string) bool {
|
||||
for _, supported := range cloudproviders {
|
||||
if provider == supported {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
276
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go
generated
vendored
Normal file
276
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go
generated
vendored
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
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"
|
||||
"strconv"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"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"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/flags"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
|
||||
kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master"
|
||||
|
||||
certphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
netutil "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
var (
|
||||
initDoneMsgf = dedent.Dedent(`
|
||||
Your Kubernetes master has initialized successfully!
|
||||
|
||||
You should now deploy a pod network to the cluster.
|
||||
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
|
||||
http://kubernetes.io/docs/admin/addons/
|
||||
|
||||
You can now join any number of machines by running the following on each node:
|
||||
|
||||
kubeadm join --discovery %s
|
||||
`)
|
||||
)
|
||||
|
||||
// NewCmdInit returns "kubeadm init" command.
|
||||
func NewCmdInit(out io.Writer) *cobra.Command {
|
||||
versioned := &kubeadmapiext.MasterConfiguration{}
|
||||
api.Scheme.Default(versioned)
|
||||
cfg := kubeadmapi.MasterConfiguration{}
|
||||
api.Scheme.Convert(versioned, &cfg, nil)
|
||||
|
||||
var cfgPath string
|
||||
var skipPreFlight bool
|
||||
cmd := &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Run this in order to set up the Kubernetes master",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
i, err := NewInit(cfgPath, &cfg, skipPreFlight)
|
||||
kubeadmutil.CheckErr(err)
|
||||
kubeadmutil.CheckErr(i.Validate())
|
||||
kubeadmutil.CheckErr(i.Run(out))
|
||||
},
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringSliceVar(
|
||||
&cfg.API.AdvertiseAddresses, "api-advertise-addresses", cfg.API.AdvertiseAddresses,
|
||||
"The IP addresses to advertise, in case autodetection fails",
|
||||
)
|
||||
cmd.PersistentFlags().Int32Var(
|
||||
&cfg.API.Port, "api-port", cfg.API.Port,
|
||||
"Port for API to bind to",
|
||||
)
|
||||
cmd.PersistentFlags().StringSliceVar(
|
||||
&cfg.API.ExternalDNSNames, "api-external-dns-names", cfg.API.ExternalDNSNames,
|
||||
"The DNS names to advertise, in case you have configured them yourself",
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet,
|
||||
"Use alternative range of IP address for service VIPs",
|
||||
)
|
||||
cmd.PersistentFlags().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",
|
||||
)
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&cfg.Networking.DNSDomain, "service-dns-domain", cfg.Networking.DNSDomain,
|
||||
`Use alternative domain for services, e.g. "myorg.internal"`,
|
||||
)
|
||||
cmd.PersistentFlags().Var(
|
||||
flags.NewCloudProviderFlag(&cfg.CloudProvider), "cloud-provider",
|
||||
`Enable cloud provider features (external load-balancers, storage, etc). Note that you have to configure all kubelets manually`,
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&cfg.KubernetesVersion, "use-kubernetes-version", cfg.KubernetesVersion,
|
||||
`Choose a specific Kubernetes version for the control plane`,
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file")
|
||||
|
||||
cmd.PersistentFlags().BoolVar(
|
||||
&skipPreFlight, "skip-preflight-checks", skipPreFlight,
|
||||
"skip preflight checks normally run before modifying the system",
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().Var(
|
||||
discovery.NewDiscoveryValue(&cfg.Discovery), "discovery",
|
||||
"The discovery method kubeadm will use for connecting nodes to the master",
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type Init struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
}
|
||||
|
||||
func NewInit(cfgPath string, cfg *kubeadmapi.MasterConfiguration, skipPreFlight bool) (*Init, error) {
|
||||
|
||||
fmt.Println("[kubeadm] WARNING: kubeadm is in alpha, please do not use it for production clusters.")
|
||||
|
||||
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(api.Codecs.UniversalDecoder(), b, cfg); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-detect the IP
|
||||
if len(cfg.API.AdvertiseAddresses) == 0 {
|
||||
ip, err := netutil.ChooseHostInterface()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.API.AdvertiseAddresses = []string{ip.String()}
|
||||
}
|
||||
|
||||
if !skipPreFlight {
|
||||
fmt.Println("[preflight] Running pre-flight checks")
|
||||
|
||||
// First, check if we're root separately from the other preflight checks and fail fast
|
||||
if err := preflight.RunRootCheckOnly(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Then continue with the others...
|
||||
if err := preflight.RunInitMasterChecks(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
fmt.Println("[preflight] Skipping pre-flight checks")
|
||||
}
|
||||
|
||||
// Try to start the kubelet service in case it's inactive
|
||||
preflight.TryStartKubelet()
|
||||
|
||||
// validate version argument
|
||||
ver, err := kubeadmutil.KubernetesReleaseVersion(cfg.KubernetesVersion)
|
||||
if err != nil {
|
||||
if cfg.KubernetesVersion != kubeadmapiext.DefaultKubernetesVersion {
|
||||
return nil, err
|
||||
} else {
|
||||
ver = kubeadmapiext.DefaultKubernetesFallbackVersion
|
||||
}
|
||||
}
|
||||
cfg.KubernetesVersion = ver
|
||||
fmt.Println("[init] Using Kubernetes version:", ver)
|
||||
|
||||
// Warn about the limitations with the current cloudprovider solution.
|
||||
if cfg.CloudProvider != "" {
|
||||
fmt.Println("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)")
|
||||
}
|
||||
|
||||
return &Init{cfg: cfg}, nil
|
||||
}
|
||||
|
||||
func (i *Init) Validate() error {
|
||||
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 {
|
||||
|
||||
// PHASE 1: Generate certificates
|
||||
caCert, err := certphase.CreatePKIAssets(i.cfg, kubeadmapi.GlobalEnvParams.HostPKIPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Exception:
|
||||
if i.cfg.Discovery.Token != nil {
|
||||
// Validate token
|
||||
if valid, err := kubeadmutil.ValidateToken(i.cfg.Discovery.Token); valid == false {
|
||||
return err
|
||||
}
|
||||
|
||||
// Make sure there is at least one address
|
||||
if len(i.cfg.Discovery.Token.Addresses) == 0 {
|
||||
ip, err := netutil.ChooseHostInterface()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.cfg.Discovery.Token.Addresses = []string{ip.String() + ":" + strconv.Itoa(kubeadmapiext.DefaultDiscoveryBindPort)}
|
||||
}
|
||||
|
||||
if err := kubemaster.CreateTokenAuthFile(kubeadmutil.BearerToken(i.cfg.Discovery.Token)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// PHASE 2: Generate kubeconfig files for the admin and the kubelet
|
||||
|
||||
// TODO this is not great, but there is only one address we can use here
|
||||
// so we'll pick the first one, there is much of chance to have an empty
|
||||
// slice by the time this gets called
|
||||
masterEndpoint := fmt.Sprintf("https://%s:%d", i.cfg.API.AdvertiseAddresses[0], i.cfg.API.Port)
|
||||
err = kubeconfigphase.CreateAdminAndKubeletKubeConfig(masterEndpoint, kubeadmapi.GlobalEnvParams.HostPKIPath, kubeadmapi.GlobalEnvParams.KubernetesDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Phase 3: Bootstrap the control plane
|
||||
if err := kubemaster.WriteStaticPodManifests(i.cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := kubemaster.CreateClientAndWaitForAPI(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfigphase.AdminKubeConfigFileName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := kubemaster.UpdateMasterRoleLabelsAndTaints(client, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if i.cfg.Discovery.Token != nil {
|
||||
fmt.Printf("[token-discovery] Using token: %s\n", kubeadmutil.BearerToken(i.cfg.Discovery.Token))
|
||||
if err := kubemaster.CreateDiscoveryDeploymentAndSecret(i.cfg, client, caCert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := kubeadmutil.UpdateOrCreateToken(client, i.cfg.Discovery.Token, kubeadmutil.DefaultTokenDuration); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := kubemaster.CreateEssentialAddons(i.cfg, client); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, initDoneMsgf, generateJoinArgs(i.cfg))
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateJoinArgs generates kubeadm join arguments
|
||||
func generateJoinArgs(cfg *kubeadmapi.MasterConfiguration) string {
|
||||
return discovery.NewDiscoveryValue(&cfg.Discovery).String()
|
||||
}
|
145
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join.go
generated
vendored
Normal file
145
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join.go
generated
vendored
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
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"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
|
||||
kubenode "k8s.io/kubernetes/cmd/kubeadm/app/node"
|
||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
var (
|
||||
joinDoneMsgf = dedent.Dedent(`
|
||||
Node join complete:
|
||||
* Certificate signing request sent to master and response
|
||||
received.
|
||||
* Kubelet informed of new secure connection details.
|
||||
|
||||
Run 'kubectl get nodes' on the master to see this machine join.
|
||||
`)
|
||||
)
|
||||
|
||||
// NewCmdJoin returns "kubeadm join" command.
|
||||
func NewCmdJoin(out io.Writer) *cobra.Command {
|
||||
versioned := &kubeadmapiext.NodeConfiguration{}
|
||||
api.Scheme.Default(versioned)
|
||||
cfg := kubeadmapi.NodeConfiguration{}
|
||||
api.Scheme.Convert(versioned, &cfg, nil)
|
||||
|
||||
var skipPreFlight bool
|
||||
var cfgPath string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "join <master address>",
|
||||
Short: "Run this on any machine you wish to join an existing cluster",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
j, err := NewJoin(cfgPath, args, &cfg, skipPreFlight)
|
||||
kubeadmutil.CheckErr(err)
|
||||
kubeadmutil.CheckErr(j.Validate())
|
||||
kubeadmutil.CheckErr(j.Run(out))
|
||||
},
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file")
|
||||
|
||||
cmd.PersistentFlags().BoolVar(
|
||||
&skipPreFlight, "skip-preflight-checks", false,
|
||||
"skip preflight checks normally run before modifying the system",
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().Var(
|
||||
discovery.NewDiscoveryValue(&cfg.Discovery), "discovery",
|
||||
"The discovery method kubeadm will use for connecting nodes to the master",
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type Join struct {
|
||||
cfg *kubeadmapi.NodeConfiguration
|
||||
}
|
||||
|
||||
func NewJoin(cfgPath string, args []string, cfg *kubeadmapi.NodeConfiguration, skipPreFlight bool) (*Join, error) {
|
||||
fmt.Println("[kubeadm] WARNING: kubeadm is in alpha, please do not use it for production clusters.")
|
||||
|
||||
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(api.Codecs.UniversalDecoder(), b, cfg); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
if !skipPreFlight {
|
||||
fmt.Println("[preflight] Running pre-flight checks")
|
||||
|
||||
// First, check if we're root separately from the other preflight checks and fail fast
|
||||
if err := preflight.RunRootCheckOnly(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Then continue with the others...
|
||||
if err := preflight.RunJoinNodeChecks(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
fmt.Println("[preflight] Skipping pre-flight checks")
|
||||
}
|
||||
|
||||
// Try to start the kubelet service in case it's inactive
|
||||
preflight.TryStartKubelet()
|
||||
|
||||
return &Join{cfg: cfg}, nil
|
||||
}
|
||||
|
||||
func (j *Join) Validate() error {
|
||||
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.Discovery)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := kubenode.PerformTLSBootstrap(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := kubeconfigphase.WriteKubeconfigToDisk(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfigphase.KubeletKubeConfigFileName), cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, joinDoneMsgf)
|
||||
return nil
|
||||
}
|
232
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset.go
generated
vendored
Normal file
232
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset.go
generated
vendored
Normal file
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
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"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/util/initsystem"
|
||||
)
|
||||
|
||||
// NewCmdReset returns the "kubeadm reset" command
|
||||
func NewCmdReset(out io.Writer) *cobra.Command {
|
||||
var skipPreFlight, removeNode bool
|
||||
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) {
|
||||
r, err := NewReset(skipPreFlight, removeNode)
|
||||
kubeadmutil.CheckErr(err)
|
||||
kubeadmutil.CheckErr(r.Run(out))
|
||||
},
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().BoolVar(
|
||||
&skipPreFlight, "skip-preflight-checks", false,
|
||||
"Skip preflight checks normally run before modifying the system",
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().BoolVar(
|
||||
&removeNode, "remove-node", true,
|
||||
"Remove this node from the pool of nodes in this cluster",
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type Reset struct {
|
||||
removeNode bool
|
||||
}
|
||||
|
||||
func NewReset(skipPreFlight, removeNode bool) (*Reset, error) {
|
||||
if !skipPreFlight {
|
||||
fmt.Println("[preflight] Running pre-flight checks")
|
||||
|
||||
if err := preflight.RunRootCheckOnly(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
fmt.Println("[preflight] Skipping pre-flight checks")
|
||||
}
|
||||
|
||||
return &Reset{
|
||||
removeNode: removeNode,
|
||||
}, 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 drain and remove the node from the cluster
|
||||
err := drainAndRemoveNode(r.removeNode)
|
||||
if err != nil {
|
||||
fmt.Printf("[reset] Failed to cleanup node: [%v]\n", err)
|
||||
}
|
||||
|
||||
// Try to stop the kubelet service
|
||||
initSystem, err := initsystem.GetInitSystem()
|
||||
if err != nil {
|
||||
fmt.Println("[reset] WARNING: The kubelet service couldn't be stopped by kubeadm because no supported init system was detected.")
|
||||
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 couldn't 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 := "cat /proc/mounts | awk '{print $2}' | grep '/var/lib/kubelet' | 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))
|
||||
}
|
||||
|
||||
dockerCheck := preflight.ServiceCheck{Service: "docker"}
|
||||
if warnings, errors := dockerCheck.Check(); len(warnings) == 0 && len(errors) == 0 {
|
||||
fmt.Println("[reset] Removing kubernetes-managed containers")
|
||||
if err := exec.Command("sh", "-c", "docker ps | grep 'k8s_' | awk '{print $1}' | 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")
|
||||
}
|
||||
|
||||
dirsToClean := []string{"/var/lib/kubelet", "/etc/cni/net.d"}
|
||||
|
||||
// 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 := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests/etcd.json")
|
||||
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
|
||||
resetConfigDir(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmapi.GlobalEnvParams.HostPKIPath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func drainAndRemoveNode(removeNode bool) error {
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to detect node hostname")
|
||||
}
|
||||
hostname = strings.ToLower(hostname)
|
||||
|
||||
// TODO: Use the "native" k8s client for this once we're confident the versioned is working
|
||||
kubeConfigPath := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "kubelet.conf")
|
||||
|
||||
getNodesCmd := fmt.Sprintf("kubectl --kubeconfig %s get nodes | grep %s", kubeConfigPath, hostname)
|
||||
output, err := exec.Command("sh", "-c", getNodesCmd).Output()
|
||||
if err != nil || len(output) == 0 {
|
||||
// kubeadm shouldn't drain and/or remove the node when it doesn't exist anymore
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Printf("[reset] Draining node: %q\n", hostname)
|
||||
|
||||
output, err = exec.Command("kubectl", "--kubeconfig", kubeConfigPath, "drain", hostname, "--delete-local-data", "--force", "--ignore-daemonsets").Output()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to drain node %q [%s]", hostname, output)
|
||||
}
|
||||
|
||||
if removeNode {
|
||||
fmt.Printf("[reset] Removing node: %q\n", hostname)
|
||||
|
||||
output, err = exec.Command("kubectl", "--kubeconfig", kubeConfigPath, "delete", "node", hostname).Output()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to remove node %q [%s]", hostname, output)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
err = os.RemoveAll(path.Join(filepath, name))
|
||||
if 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{
|
||||
path.Join(configPathDir, "manifests"),
|
||||
pkiPathDir,
|
||||
}
|
||||
fmt.Printf("[reset] Deleting contents of config directories: %v\n", dirsToClean)
|
||||
for _, dir := range dirsToClean {
|
||||
err := cleanDir(dir)
|
||||
if err != nil {
|
||||
fmt.Printf("[reset] Failed to remove directory: %q [%v]\n", dir, err)
|
||||
}
|
||||
}
|
||||
|
||||
filesToClean := []string{
|
||||
path.Join(configPathDir, "admin.conf"),
|
||||
path.Join(configPathDir, "kubelet.conf"),
|
||||
}
|
||||
fmt.Printf("[reset] Deleting files: %v\n", filesToClean)
|
||||
for _, path := range filesToClean {
|
||||
err := os.RemoveAll(path)
|
||||
if err != nil {
|
||||
fmt.Printf("[reset] Failed to remove file: %q [%v]\n", path, err)
|
||||
}
|
||||
}
|
||||
}
|
182
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset_test.go
generated
vendored
Normal file
182
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset_test.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 cmd
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
)
|
||||
|
||||
func assertExists(t *testing.T, path string) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
t.Errorf("file/dir does not exist error: %s", err)
|
||||
t.Errorf("file/dir 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.json",
|
||||
"manifests/kube-apiserver.json",
|
||||
"pki/ca.pem",
|
||||
"admin.conf",
|
||||
"kubelet.conf",
|
||||
},
|
||||
verifyExists: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
},
|
||||
},
|
||||
"partial reset": {
|
||||
setupDirs: []string{
|
||||
"pki",
|
||||
},
|
||||
setupFiles: []string{
|
||||
"pki/ca.pem",
|
||||
"kubelet.conf",
|
||||
},
|
||||
verifyExists: []string{
|
||||
"pki",
|
||||
},
|
||||
verifyNotExists: []string{
|
||||
"manifests",
|
||||
},
|
||||
},
|
||||
"preserve cloud-config": {
|
||||
setupDirs: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
},
|
||||
setupFiles: []string{
|
||||
"manifests/etcd.json",
|
||||
"manifests/kube-apiserver.json",
|
||||
"pki/ca.pem",
|
||||
"admin.conf",
|
||||
"kubelet.conf",
|
||||
"cloud-config",
|
||||
},
|
||||
verifyExists: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
"cloud-config",
|
||||
},
|
||||
},
|
||||
"preserve hidden files and directories": {
|
||||
setupDirs: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
".mydir",
|
||||
},
|
||||
setupFiles: []string{
|
||||
"manifests/etcd.json",
|
||||
"manifests/kube-apiserver.json",
|
||||
"pki/ca.pem",
|
||||
"admin.conf",
|
||||
"kubelet.conf",
|
||||
".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 temp 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)
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
t.Errorf("Unable to create test file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
resetConfigDir(tmpDir, filepath.Join(tmpDir, "pki"))
|
||||
|
||||
// Verify the files we cleanup implicitly in every test:
|
||||
assertExists(t, tmpDir)
|
||||
assertNotExists(t, filepath.Join(tmpDir, "admin.conf"))
|
||||
assertNotExists(t, filepath.Join(tmpDir, "kubelet.conf"))
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
230
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token.go
generated
vendored
Normal file
230
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token.go
generated
vendored
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
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"
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
)
|
||||
|
||||
func NewCmdToken(out io.Writer, errW io.Writer) *cobra.Command {
|
||||
|
||||
tokenCmd := &cobra.Command{
|
||||
Use: "token",
|
||||
Short: "Manage 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: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return errors.New("missing subcommand; 'token' is not meant to be run on its own")
|
||||
} else {
|
||||
return fmt.Errorf("invalid subcommand: %s", args[0])
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var token string
|
||||
var tokenDuration time.Duration
|
||||
createCmd := &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create bootstrap tokens on the server.",
|
||||
Run: func(tokenCmd *cobra.Command, args []string) {
|
||||
err := RunCreateToken(out, tokenCmd, tokenDuration, token)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
createCmd.PersistentFlags().DurationVar(&tokenDuration,
|
||||
"ttl", kubeadmutil.DefaultTokenDuration, "The duration before the token is automatically deleted.")
|
||||
createCmd.PersistentFlags().StringVar(
|
||||
&token, "token", "",
|
||||
"Shared secret used to secure cluster bootstrap. If none is provided, one will be generated for you.",
|
||||
)
|
||||
tokenCmd.AddCommand(createCmd)
|
||||
|
||||
tokenCmd.AddCommand(NewCmdTokenGenerate(out))
|
||||
|
||||
listCmd := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List bootstrap tokens on the server.",
|
||||
Run: func(tokenCmd *cobra.Command, args []string) {
|
||||
err := RunListTokens(out, errW, tokenCmd)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
tokenCmd.AddCommand(listCmd)
|
||||
|
||||
deleteCmd := &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "Delete bootstrap tokens on the server.",
|
||||
Run: func(tokenCmd *cobra.Command, args []string) {
|
||||
err := RunDeleteToken(out, tokenCmd, args[0])
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
tokenCmd.AddCommand(deleteCmd)
|
||||
|
||||
return tokenCmd
|
||||
}
|
||||
|
||||
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's in the format "<6 characters>:<16 characters>". This
|
||||
command is provided for convenience to generate tokens in that 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, cmd *cobra.Command, tokenDuration time.Duration, token string) error {
|
||||
client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "admin.conf"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parsedID, parsedSecret, err := kubeadmutil.ParseToken(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
td := &kubeadmapi.TokenDiscovery{ID: parsedID, Secret: parsedSecret}
|
||||
|
||||
err = kubeadmutil.UpdateOrCreateToken(client, td, tokenDuration)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(out, kubeadmutil.BearerToken(td))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunGenerateToken(out io.Writer) error {
|
||||
td := &kubeadmapi.TokenDiscovery{}
|
||||
err := kubeadmutil.GenerateToken(td)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(out, kubeadmutil.BearerToken(td))
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunListTokens lists details on all existing bootstrap tokens on the server.
|
||||
func RunListTokens(out io.Writer, errW io.Writer, cmd *cobra.Command) error {
|
||||
client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "admin.conf"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tokenSelector := fields.SelectorFromSet(
|
||||
map[string]string{
|
||||
api.SecretTypeField: string(api.SecretTypeBootstrapToken),
|
||||
},
|
||||
)
|
||||
listOptions := v1.ListOptions{
|
||||
FieldSelector: tokenSelector.String(),
|
||||
}
|
||||
|
||||
results, err := client.Secrets(api.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, "ID\tTOKEN\tTTL")
|
||||
for _, secret := range results.Items {
|
||||
tokenId, ok := secret.Data["token-id"]
|
||||
if !ok {
|
||||
fmt.Fprintf(errW, "[token] bootstrap token has no token-id data: %s\n", secret.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
tokenSecret, ok := secret.Data["token-secret"]
|
||||
if !ok {
|
||||
fmt.Fprintf(errW, "[token] bootstrap token has no token-secret data: %s\n", secret.Name)
|
||||
continue
|
||||
}
|
||||
token := fmt.Sprintf("%s.%s", tokenId, tokenSecret)
|
||||
|
||||
// Expiration time is optional, if not specified this implies the token
|
||||
// never expires.
|
||||
expires := "<never>"
|
||||
secretExpiration, ok := secret.Data["expiration"]
|
||||
if ok {
|
||||
expireTime, err := time.Parse(time.RFC3339, string(secretExpiration))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing expiry time [%v]", err)
|
||||
}
|
||||
expires = kubectl.ShortHumanDuration(expireTime.Sub(time.Now()))
|
||||
}
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\n", tokenId, token, expires)
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunDeleteToken removes a bootstrap token from the server.
|
||||
func RunDeleteToken(out io.Writer, cmd *cobra.Command, tokenId string) error {
|
||||
if err := kubeadmutil.ParseTokenID(tokenId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "admin.conf"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tokenSecretName := fmt.Sprintf("%s%s", kubeadmutil.BootstrapTokenSecretPrefix, tokenId)
|
||||
if err := client.Secrets(api.NamespaceSystem).Delete(tokenSecretName, nil); err != nil {
|
||||
return fmt.Errorf("failed to delete bootstrap token [%v]", err)
|
||||
}
|
||||
fmt.Fprintf(out, "[token] bootstrap token deleted: %s\n", tokenId)
|
||||
|
||||
return 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)
|
||||
}
|
||||
}
|
44
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version.go
generated
vendored
Normal file
44
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/version.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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
)
|
||||
|
||||
func NewCmdVersion(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the version of kubeadm",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunVersion(out, cmd)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunVersion(out io.Writer, cmd *cobra.Command) error {
|
||||
fmt.Fprintf(out, "kubeadm version: %#v\n", version.Get())
|
||||
return nil
|
||||
}
|
58
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/BUILD
generated
vendored
Normal file
58
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"discovery.go",
|
||||
"flags.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
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/node:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
||||
"//vendor:github.com/spf13/pflag",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["flags_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//vendor:github.com/davecgh/go-spew/spew",
|
||||
],
|
||||
)
|
||||
|
||||
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"],
|
||||
)
|
82
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery.go
generated
vendored
Normal file
82
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/discovery.go
generated
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
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"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubenode "k8s.io/kubernetes/cmd/kubeadm/app/node"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
)
|
||||
|
||||
// For identifies and executes the desired discovery mechanism.
|
||||
func For(d kubeadmapi.Discovery) (*clientcmdapi.Config, error) {
|
||||
switch {
|
||||
case d.File != nil:
|
||||
return runFileDiscovery(d.File)
|
||||
case d.HTTPS != nil:
|
||||
return runHTTPSDiscovery(d.HTTPS)
|
||||
case d.Token != nil:
|
||||
return runTokenDiscovery(d.Token)
|
||||
default:
|
||||
return nil, fmt.Errorf("couldn't find a valid discovery configuration.")
|
||||
}
|
||||
}
|
||||
|
||||
// runFileDiscovery executes file-based discovery.
|
||||
func runFileDiscovery(fd *kubeadmapi.FileDiscovery) (*clientcmdapi.Config, error) {
|
||||
return clientcmd.LoadFromFile(fd.Path)
|
||||
}
|
||||
|
||||
// runHTTPSDiscovery executes HTTPS-based discovery.
|
||||
func runHTTPSDiscovery(hd *kubeadmapi.HTTPSDiscovery) (*clientcmdapi.Config, error) {
|
||||
response, err := http.Get(hd.URL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
kubeconfig, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return clientcmd.Load(kubeconfig)
|
||||
}
|
||||
|
||||
// runTokenDiscovery executes token-based discovery.
|
||||
func runTokenDiscovery(td *kubeadmapi.TokenDiscovery) (*clientcmdapi.Config, error) {
|
||||
if valid, err := kubeadmutil.ValidateToken(td); valid == false {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterInfo, err := kubenode.RetrieveTrustedClusterInfo(td)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg, err := kubenode.EstablishMasterConnection(td, clusterInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/BUILD
generated
vendored
Normal file
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["file.go"],
|
||||
tags = ["automanaged"],
|
||||
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"],
|
||||
tags = ["automanaged"],
|
||||
)
|
30
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/file.go
generated
vendored
Normal file
30
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/file/file.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
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 (
|
||||
"net/url"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func Parse(u *url.URL, c *kubeadm.Discovery) error {
|
||||
c.File = &kubeadm.FileDiscovery{
|
||||
Path: u.Path,
|
||||
}
|
||||
return nil
|
||||
}
|
92
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/flags.go
generated
vendored
Normal file
92
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/flags.go
generated
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
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"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
type discoveryValue struct {
|
||||
v *kubeadm.Discovery
|
||||
}
|
||||
|
||||
func NewDiscoveryValue(d *kubeadm.Discovery) pflag.Value {
|
||||
return &discoveryValue{
|
||||
v: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *discoveryValue) String() string {
|
||||
switch {
|
||||
case d.v.HTTPS != nil:
|
||||
return d.v.HTTPS.URL
|
||||
case d.v.File != nil:
|
||||
return "file://" + d.v.File.Path
|
||||
case d.v.Token != nil:
|
||||
return fmt.Sprintf("token://%s:%s@%s", d.v.Token.ID, d.v.Token.Secret, strings.Join(d.v.Token.Addresses, ","))
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (d *discoveryValue) Set(s string) error {
|
||||
var kd kubeadm.Discovery
|
||||
if err := ParseURL(&kd, s); err != nil {
|
||||
return err
|
||||
}
|
||||
*d.v = kd
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *discoveryValue) Type() string {
|
||||
return "discovery"
|
||||
}
|
||||
|
||||
func ParseURL(d *kubeadm.Discovery, s string) error {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch u.Scheme {
|
||||
case "https":
|
||||
return https.Parse(u, d)
|
||||
case "file":
|
||||
return file.Parse(u, d)
|
||||
case "token":
|
||||
// Make sure a valid RFC 3986 URL has been passed and parsed.
|
||||
// See https://github.com/kubernetes/kubeadm/issues/95#issuecomment-270431296 for more details.
|
||||
if !strings.Contains(s, "@") {
|
||||
s := s + "@"
|
||||
u, err = url.Parse(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return token.Parse(u, d)
|
||||
default:
|
||||
return fmt.Errorf("unknown discovery scheme")
|
||||
}
|
||||
}
|
101
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/flags_test.go
generated
vendored
Normal file
101
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/flags_test.go
generated
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
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 (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestParseURL(t *testing.T) {
|
||||
cases := []struct {
|
||||
url string
|
||||
expect kubeadm.Discovery
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
url: "token://",
|
||||
expect: kubeadm.Discovery{
|
||||
Token: &kubeadm.TokenDiscovery{},
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "token://c05de9:ab224260fb3cd718",
|
||||
expect: kubeadm.Discovery{
|
||||
Token: &kubeadm.TokenDiscovery{
|
||||
ID: "c05de9",
|
||||
Secret: "ab224260fb3cd718",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "token://c05de9:ab224260fb3cd718@",
|
||||
expect: kubeadm.Discovery{
|
||||
Token: &kubeadm.TokenDiscovery{
|
||||
ID: "c05de9",
|
||||
Secret: "ab224260fb3cd718",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "token://c05de9:ab224260fb3cd718@192.168.0.1:6555,191.168.0.2:6443",
|
||||
expect: kubeadm.Discovery{
|
||||
Token: &kubeadm.TokenDiscovery{
|
||||
ID: "c05de9",
|
||||
Secret: "ab224260fb3cd718",
|
||||
Addresses: []string{
|
||||
"192.168.0.1:6555",
|
||||
"191.168.0.2:6443",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "file:///foo/bar/baz",
|
||||
expect: kubeadm.Discovery{
|
||||
File: &kubeadm.FileDiscovery{
|
||||
Path: "/foo/bar/baz",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "https://storage.googleapis.com/kubeadm-disco/clusters/217651295213",
|
||||
expect: kubeadm.Discovery{
|
||||
HTTPS: &kubeadm.HTTPSDiscovery{
|
||||
URL: "https://storage.googleapis.com/kubeadm-disco/clusters/217651295213",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
var d kubeadm.Discovery
|
||||
if err := ParseURL(&d, c.url); err != nil {
|
||||
if !c.expectErr {
|
||||
t.Errorf("unexpected error parsing discovery url: %v", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(d, c.expect) {
|
||||
t.Errorf("expected discovery config to be equal but got:\n\tactual: %s\n\texpected: %s", spew.Sdump(d), spew.Sdump(c.expect))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/BUILD
generated
vendored
Normal file
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["https.go"],
|
||||
tags = ["automanaged"],
|
||||
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"],
|
||||
tags = ["automanaged"],
|
||||
)
|
30
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/https.go
generated
vendored
Normal file
30
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/https/https.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
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 (
|
||||
"net/url"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func Parse(u *url.URL, c *kubeadm.Discovery) error {
|
||||
c.HTTPS = &kubeadm.HTTPSDiscovery{
|
||||
URL: u.String(),
|
||||
}
|
||||
return nil
|
||||
}
|
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/BUILD
generated
vendored
Normal file
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["token.go"],
|
||||
tags = ["automanaged"],
|
||||
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"],
|
||||
tags = ["automanaged"],
|
||||
)
|
46
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token.go
generated
vendored
Normal file
46
vendor/k8s.io/kubernetes/cmd/kubeadm/app/discovery/token/token.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 token
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func Parse(u *url.URL, c *kubeadm.Discovery) error {
|
||||
var (
|
||||
hosts []string
|
||||
tokenID, token string
|
||||
)
|
||||
if u.Host != "" {
|
||||
hosts = strings.Split(u.Host, ",")
|
||||
}
|
||||
if u.User != nil {
|
||||
if p, ok := u.User.Password(); ok {
|
||||
tokenID = u.User.Username()
|
||||
token = p
|
||||
}
|
||||
}
|
||||
c.Token = &kubeadm.TokenDiscovery{
|
||||
ID: tokenID,
|
||||
Secret: token,
|
||||
Addresses: hosts,
|
||||
}
|
||||
return nil
|
||||
}
|
37
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/BUILD
generated
vendored
Normal file
37
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["images.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//cmd/kubeadm/app/apis/kubeadm:go_default_library"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["images_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
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"],
|
||||
tags = ["automanaged"],
|
||||
)
|
70
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images.go
generated
vendored
Normal file
70
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
const (
|
||||
KubeEtcdImage = "etcd"
|
||||
|
||||
KubeAPIServerImage = "apiserver"
|
||||
KubeControllerManagerImage = "controller-manager"
|
||||
KubeSchedulerImage = "scheduler"
|
||||
KubeProxyImage = "proxy"
|
||||
|
||||
KubeDNSImage = "k8s-dns-kube-dns"
|
||||
KubeDNSmasqImage = "k8s-dns-dnsmasq"
|
||||
KubeDNSSidecarImage = "k8s-dns-sidecar"
|
||||
Pause = "pause"
|
||||
|
||||
gcrPrefix = "gcr.io/google_containers"
|
||||
etcdVersion = "3.0.14-kubeadm"
|
||||
|
||||
kubeDNSVersion = "1.10.1"
|
||||
dnsmasqVersion = "1.10.1"
|
||||
kubeDNSSidecarVersion = "1.10.1"
|
||||
pauseVersion = "3.0"
|
||||
)
|
||||
|
||||
func GetCoreImage(image string, cfg *kubeadmapi.MasterConfiguration, overrideImage string) string {
|
||||
if overrideImage != "" {
|
||||
return overrideImage
|
||||
}
|
||||
repoPrefix := kubeadmapi.GlobalEnvParams.RepositoryPrefix
|
||||
return map[string]string{
|
||||
KubeEtcdImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "etcd", runtime.GOARCH, etcdVersion),
|
||||
KubeAPIServerImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-apiserver", runtime.GOARCH, cfg.KubernetesVersion),
|
||||
KubeControllerManagerImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-controller-manager", runtime.GOARCH, cfg.KubernetesVersion),
|
||||
KubeSchedulerImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-scheduler", runtime.GOARCH, cfg.KubernetesVersion),
|
||||
KubeProxyImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-proxy", runtime.GOARCH, cfg.KubernetesVersion),
|
||||
}[image]
|
||||
}
|
||||
|
||||
func GetAddonImage(image string) string {
|
||||
repoPrefix := kubeadmapi.GlobalEnvParams.RepositoryPrefix
|
||||
return map[string]string{
|
||||
KubeDNSImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, KubeDNSImage, runtime.GOARCH, kubeDNSVersion),
|
||||
KubeDNSmasqImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, KubeDNSmasqImage, runtime.GOARCH, dnsmasqVersion),
|
||||
KubeDNSSidecarImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, KubeDNSSidecarImage, runtime.GOARCH, kubeDNSSidecarVersion),
|
||||
Pause: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, Pause, runtime.GOARCH, pauseVersion),
|
||||
}[image]
|
||||
}
|
112
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images_test.go
generated
vendored
Normal file
112
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/images_test.go
generated
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
type getCoreImageTest struct {
|
||||
i string
|
||||
c *kubeadmapi.MasterConfiguration
|
||||
o string
|
||||
}
|
||||
|
||||
const testversion = "1"
|
||||
|
||||
func TestGetCoreImage(t *testing.T) {
|
||||
var tokenTest = []struct {
|
||||
t getCoreImageTest
|
||||
expected string
|
||||
}{
|
||||
{getCoreImageTest{o: "override"}, "override"},
|
||||
{getCoreImageTest{
|
||||
i: KubeEtcdImage,
|
||||
c: &kubeadmapi.MasterConfiguration{}},
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "etcd", runtime.GOARCH, etcdVersion),
|
||||
},
|
||||
{getCoreImageTest{
|
||||
i: KubeAPIServerImage,
|
||||
c: &kubeadmapi.MasterConfiguration{KubernetesVersion: testversion}},
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, testversion),
|
||||
},
|
||||
{getCoreImageTest{
|
||||
i: KubeControllerManagerImage,
|
||||
c: &kubeadmapi.MasterConfiguration{KubernetesVersion: testversion}},
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, testversion),
|
||||
},
|
||||
{getCoreImageTest{
|
||||
i: KubeSchedulerImage,
|
||||
c: &kubeadmapi.MasterConfiguration{KubernetesVersion: testversion}},
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, testversion),
|
||||
},
|
||||
{getCoreImageTest{
|
||||
i: KubeProxyImage,
|
||||
c: &kubeadmapi.MasterConfiguration{KubernetesVersion: testversion}},
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-proxy", runtime.GOARCH, testversion),
|
||||
},
|
||||
}
|
||||
for _, rt := range tokenTest {
|
||||
actual := GetCoreImage(rt.t.i, rt.t.c, rt.t.o)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed GetCoreImage:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAddonImage(t *testing.T) {
|
||||
var tokenTest = []struct {
|
||||
t string
|
||||
expected string
|
||||
}{
|
||||
{"matches nothing", ""},
|
||||
{
|
||||
KubeDNSImage,
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, KubeDNSImage, runtime.GOARCH, kubeDNSVersion),
|
||||
},
|
||||
{
|
||||
KubeDNSmasqImage,
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, KubeDNSmasqImage, runtime.GOARCH, dnsmasqVersion),
|
||||
},
|
||||
{
|
||||
KubeDNSSidecarImage,
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, KubeDNSSidecarImage, runtime.GOARCH, kubeDNSSidecarVersion),
|
||||
},
|
||||
{
|
||||
Pause,
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, Pause, runtime.GOARCH, pauseVersion),
|
||||
},
|
||||
}
|
||||
for _, rt := range tokenTest {
|
||||
actual := GetAddonImage(rt.t)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed GetCoreImage:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
36
vendor/k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go
generated
vendored
Normal file
36
vendor/k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
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"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
)
|
||||
|
||||
func Run() error {
|
||||
// We do not want these flags to show up in --help
|
||||
pflag.CommandLine.MarkHidden("google-json-key")
|
||||
pflag.CommandLine.MarkHidden("log-flush-frequency")
|
||||
|
||||
cmd := cmd.NewKubeadmCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr)
|
||||
return cmd.Execute()
|
||||
}
|
73
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/BUILD
generated
vendored
Normal file
73
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"addons.go",
|
||||
"apiclient.go",
|
||||
"discovery.go",
|
||||
"manifests.go",
|
||||
"tokens.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/images:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/resource:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||
"//pkg/util/cert:go_default_library",
|
||||
"//pkg/util/intstr:go_default_library",
|
||||
"//pkg/util/uuid:go_default_library",
|
||||
"//vendor:github.com/blang/semver",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"addons_test.go",
|
||||
"apiclient_test.go",
|
||||
"discovery_test.go",
|
||||
"manifests_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/util/intstr:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
295
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/addons.go
generated
vendored
Normal file
295
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/addons.go
generated
vendored
Normal file
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"path"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
)
|
||||
|
||||
func createKubeProxyPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec {
|
||||
privilegedTrue := true
|
||||
return v1.PodSpec{
|
||||
HostNetwork: true,
|
||||
SecurityContext: &v1.PodSecurityContext{},
|
||||
Containers: []v1.Container{{
|
||||
Name: kubeProxy,
|
||||
Image: images.GetCoreImage(images.KubeProxyImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage),
|
||||
Command: append(getProxyCommand(cfg), "--kubeconfig=/run/kubeconfig"),
|
||||
SecurityContext: &v1.SecurityContext{Privileged: &privilegedTrue},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "dbus",
|
||||
MountPath: "/var/run/dbus",
|
||||
ReadOnly: false,
|
||||
},
|
||||
{
|
||||
// TODO there are handful of clever options to get around this, but it's
|
||||
// easier to just mount kubelet's config here; we should probably just
|
||||
// make sure that proxy reads the token and CA cert from /run/secrets
|
||||
// and accepts `--master` at the same time
|
||||
//
|
||||
// clever options include:
|
||||
// - do CSR dance and create kubeconfig and mount it as a secret
|
||||
// - create a service account with a second secret encoding kubeconfig
|
||||
// - use init container to convert known information to kubeconfig
|
||||
// - ...whatever
|
||||
Name: "kubeconfig",
|
||||
MountPath: "/run/kubeconfig",
|
||||
ReadOnly: false,
|
||||
},
|
||||
},
|
||||
}},
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "kubelet.conf")},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "dbus",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{Path: "/var/run/dbus"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func createKubeDNSPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec {
|
||||
kubeDNSPort := int32(10053)
|
||||
dnsmasqPort := int32(53)
|
||||
|
||||
return v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
// DNS server
|
||||
{
|
||||
Name: "kubedns",
|
||||
Image: images.GetAddonImage(images.KubeDNSImage),
|
||||
Resources: v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("170Mi"),
|
||||
},
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("100m"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("70Mi"),
|
||||
},
|
||||
},
|
||||
LivenessProbe: &v1.Probe{
|
||||
Handler: v1.Handler{
|
||||
HTTPGet: &v1.HTTPGetAction{
|
||||
Path: "/healthcheck/kubedns",
|
||||
Port: intstr.FromInt(10054),
|
||||
Scheme: v1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: 60,
|
||||
TimeoutSeconds: 5,
|
||||
SuccessThreshold: 1,
|
||||
FailureThreshold: 5,
|
||||
},
|
||||
// # we poll on pod startup for the Kubernetes master service and
|
||||
// # only setup the /readiness HTTP server once that's available.
|
||||
ReadinessProbe: &v1.Probe{
|
||||
Handler: v1.Handler{
|
||||
HTTPGet: &v1.HTTPGetAction{
|
||||
Path: "/readiness",
|
||||
Port: intstr.FromInt(8081),
|
||||
Scheme: v1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: 3,
|
||||
TimeoutSeconds: 5,
|
||||
},
|
||||
Args: []string{
|
||||
fmt.Sprintf("--domain=%s", cfg.Networking.DNSDomain),
|
||||
fmt.Sprintf("--dns-port=%d", kubeDNSPort),
|
||||
"--config-map=kube-dns",
|
||||
"--v=2",
|
||||
},
|
||||
Env: []v1.EnvVar{
|
||||
{
|
||||
Name: "PROMETHEUS_PORT",
|
||||
Value: "10055",
|
||||
},
|
||||
},
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: kubeDNSPort,
|
||||
Name: "dns-local",
|
||||
Protocol: v1.ProtocolUDP,
|
||||
},
|
||||
{
|
||||
ContainerPort: kubeDNSPort,
|
||||
Name: "dns-tcp-local",
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 10055,
|
||||
Name: "metrics",
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
// dnsmasq
|
||||
{
|
||||
Name: "dnsmasq",
|
||||
Image: images.GetAddonImage(images.KubeDNSmasqImage),
|
||||
LivenessProbe: &v1.Probe{
|
||||
Handler: v1.Handler{
|
||||
HTTPGet: &v1.HTTPGetAction{
|
||||
Path: "/healthcheck/dnsmasq",
|
||||
Port: intstr.FromInt(10054),
|
||||
Scheme: v1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: 60,
|
||||
TimeoutSeconds: 5,
|
||||
SuccessThreshold: 1,
|
||||
FailureThreshold: 5,
|
||||
},
|
||||
Args: []string{
|
||||
"--cache-size=1000",
|
||||
"--no-resolv",
|
||||
fmt.Sprintf("--server=127.0.0.1#%d", kubeDNSPort),
|
||||
"--log-facility=-",
|
||||
},
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: dnsmasqPort,
|
||||
Name: "dns",
|
||||
Protocol: v1.ProtocolUDP,
|
||||
},
|
||||
{
|
||||
ContainerPort: dnsmasqPort,
|
||||
Name: "dns-tcp",
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("150m"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("10Mi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "sidecar",
|
||||
Image: images.GetAddonImage(images.KubeDNSSidecarImage),
|
||||
LivenessProbe: &v1.Probe{
|
||||
Handler: v1.Handler{
|
||||
HTTPGet: &v1.HTTPGetAction{
|
||||
Path: "/metrics",
|
||||
Port: intstr.FromInt(10054),
|
||||
Scheme: v1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: 60,
|
||||
TimeoutSeconds: 5,
|
||||
SuccessThreshold: 1,
|
||||
FailureThreshold: 5,
|
||||
},
|
||||
Args: []string{
|
||||
"--v=2",
|
||||
"--logtostderr",
|
||||
fmt.Sprintf("--probe=kubedns,127.0.0.1:10053,kubernetes.default.svc.%s,5,A", cfg.Networking.DNSDomain),
|
||||
fmt.Sprintf("--probe=dnsmasq,127.0.0.1:53,kubernetes.default.svc.%s,5,A", cfg.Networking.DNSDomain),
|
||||
},
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: 10054,
|
||||
Name: "metrics",
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("20Mi"),
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("10m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DNSPolicy: v1.DNSDefault,
|
||||
}
|
||||
}
|
||||
|
||||
func createKubeDNSServiceSpec(cfg *kubeadmapi.MasterConfiguration) (*v1.ServiceSpec, error) {
|
||||
_, n, err := net.ParseCIDR(cfg.Networking.ServiceSubnet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse %q: %v", cfg.Networking.ServiceSubnet, err)
|
||||
}
|
||||
ip, err := ipallocator.GetIndexedIP(n, 10)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to allocate IP address for kube-dns addon from the given CIDR %q: [%v]", cfg.Networking.ServiceSubnet, err)
|
||||
}
|
||||
|
||||
return &v1.ServiceSpec{
|
||||
Selector: map[string]string{"name": "kube-dns"},
|
||||
Ports: []v1.ServicePort{
|
||||
{Name: "dns", Port: 53, Protocol: v1.ProtocolUDP},
|
||||
{Name: "dns-tcp", Port: 53, Protocol: v1.ProtocolTCP},
|
||||
},
|
||||
ClusterIP: ip.String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func CreateEssentialAddons(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset) error {
|
||||
kubeProxyDaemonSet := NewDaemonSet(kubeProxy, createKubeProxyPodSpec(cfg))
|
||||
SetMasterTaintTolerations(&kubeProxyDaemonSet.Spec.Template.ObjectMeta)
|
||||
SetNodeAffinity(&kubeProxyDaemonSet.Spec.Template.ObjectMeta, NativeArchitectureNodeAffinity())
|
||||
|
||||
if _, err := client.Extensions().DaemonSets(api.NamespaceSystem).Create(kubeProxyDaemonSet); err != nil {
|
||||
return fmt.Errorf("failed creating essential kube-proxy addon [%v]", err)
|
||||
}
|
||||
|
||||
fmt.Println("[addons] Created essential addon: kube-proxy")
|
||||
|
||||
kubeDNSDeployment := NewDeployment("kube-dns", 1, createKubeDNSPodSpec(cfg))
|
||||
SetMasterTaintTolerations(&kubeDNSDeployment.Spec.Template.ObjectMeta)
|
||||
SetNodeAffinity(&kubeDNSDeployment.Spec.Template.ObjectMeta, NativeArchitectureNodeAffinity())
|
||||
|
||||
if _, err := client.Extensions().Deployments(api.NamespaceSystem).Create(kubeDNSDeployment); err != nil {
|
||||
return fmt.Errorf("failed creating essential kube-dns addon [%v]", err)
|
||||
}
|
||||
|
||||
kubeDNSServiceSpec, err := createKubeDNSServiceSpec(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed creating essential kube-dns addon [%v]", err)
|
||||
}
|
||||
|
||||
kubeDNSService := NewService("kube-dns", *kubeDNSServiceSpec)
|
||||
kubeDNSService.ObjectMeta.Labels["kubernetes.io/name"] = "KubeDNS"
|
||||
if _, err := client.Services(api.NamespaceSystem).Create(kubeDNSService); err != nil {
|
||||
return fmt.Errorf("failed creating essential kube-dns addon [%v]", err)
|
||||
}
|
||||
|
||||
fmt.Println("[addons] Created essential addon: kube-dns")
|
||||
|
||||
return nil
|
||||
}
|
115
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/addons_test.go
generated
vendored
Normal file
115
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/addons_test.go
generated
vendored
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestCreateKubeProxyPodSpec(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := createKubeProxyPodSpec(rt.cfg)
|
||||
if (actual.Containers[0].Name != "") != rt.expected {
|
||||
t.Errorf(
|
||||
"failed createKubeProxyPodSpec:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual.Containers[0].Name != ""),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateKubeDNSPodSpec(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Networking: kubeadm.Networking{DNSDomain: "localhost"},
|
||||
},
|
||||
expected: "--domain=localhost",
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Networking: kubeadm.Networking{DNSDomain: "foo"},
|
||||
},
|
||||
expected: "--domain=foo",
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := createKubeDNSPodSpec(rt.cfg)
|
||||
if actual.Containers[0].Args[0] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed createKubeDNSPodSpec:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual.Containers[0].Args[0],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateKubeDNSServiceSpec(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "foo"},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/1"},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/24"},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
_, actual := createKubeDNSServiceSpec(rt.cfg)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed createKubeDNSServiceSpec:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
293
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/apiclient.go
generated
vendored
Normal file
293
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/apiclient.go
generated
vendored
Normal file
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
)
|
||||
|
||||
const apiCallRetryInterval = 500 * time.Millisecond
|
||||
|
||||
func createAPIClient(adminKubeconfig *clientcmdapi.Config) (*clientset.Clientset, error) {
|
||||
adminClientConfig, err := clientcmd.NewDefaultClientConfig(
|
||||
*adminKubeconfig,
|
||||
&clientcmd.ConfigOverrides{},
|
||||
).ClientConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create API client configuration [%v]", err)
|
||||
}
|
||||
|
||||
client, err := clientset.NewForConfig(adminClientConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create API client [%v]", err)
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func CreateClientFromFile(path string) (*clientset.Clientset, error) {
|
||||
adminKubeconfig, err := clientcmd.LoadFromFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load admin kubeconfig [%v]", err)
|
||||
}
|
||||
return createAPIClient(adminKubeconfig)
|
||||
}
|
||||
|
||||
func CreateClientAndWaitForAPI(file string) (*clientset.Clientset, error) {
|
||||
client, err := CreateClientFromFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println("[apiclient] Created API client, waiting for the control plane to become ready")
|
||||
|
||||
start := time.Now()
|
||||
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
||||
cs, err := client.ComponentStatuses().List(v1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
// TODO(phase2) must revisit this when we implement HA
|
||||
if len(cs.Items) < 3 {
|
||||
fmt.Println("[apiclient] Not all control plane components are ready yet")
|
||||
return false, nil
|
||||
}
|
||||
for _, item := range cs.Items {
|
||||
for _, condition := range item.Conditions {
|
||||
if condition.Type != v1.ComponentHealthy {
|
||||
fmt.Printf("[apiclient] Control plane component %q is still unhealthy: %#v\n", item.ObjectMeta.Name, item.Conditions)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("[apiclient] All control plane components are healthy after %f seconds\n", time.Since(start).Seconds())
|
||||
return true, nil
|
||||
})
|
||||
|
||||
fmt.Println("[apiclient] Waiting for at least one node to register and become ready")
|
||||
start = time.Now()
|
||||
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
||||
nodeList, err := client.Nodes().List(v1.ListOptions{})
|
||||
if err != nil {
|
||||
fmt.Println("[apiclient] Temporarily unable to list nodes (will retry)")
|
||||
return false, nil
|
||||
}
|
||||
if len(nodeList.Items) < 1 {
|
||||
return false, nil
|
||||
}
|
||||
n := &nodeList.Items[0]
|
||||
if !v1.IsNodeReady(n) {
|
||||
fmt.Println("[apiclient] First node has registered, but is not ready yet")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
fmt.Printf("[apiclient] First node is ready after %f seconds\n", time.Since(start).Seconds())
|
||||
return true, nil
|
||||
})
|
||||
|
||||
createDummyDeployment(client)
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func standardLabels(n string) map[string]string {
|
||||
return map[string]string{
|
||||
"component": n, "name": n, "k8s-app": n,
|
||||
"kubernetes.io/cluster-service": "true", "tier": "node",
|
||||
}
|
||||
}
|
||||
|
||||
func NewDaemonSet(daemonName string, podSpec v1.PodSpec) *extensions.DaemonSet {
|
||||
l := standardLabels(daemonName)
|
||||
return &extensions.DaemonSet{
|
||||
ObjectMeta: v1.ObjectMeta{Name: daemonName},
|
||||
Spec: extensions.DaemonSetSpec{
|
||||
Selector: &metav1.LabelSelector{MatchLabels: l},
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: v1.ObjectMeta{Labels: l},
|
||||
Spec: podSpec,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewService(serviceName string, spec v1.ServiceSpec) *v1.Service {
|
||||
l := standardLabels(serviceName)
|
||||
return &v1.Service{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: serviceName,
|
||||
Labels: l,
|
||||
},
|
||||
Spec: spec,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDeployment(deploymentName string, replicas int32, podSpec v1.PodSpec) *extensions.Deployment {
|
||||
l := standardLabels(deploymentName)
|
||||
return &extensions.Deployment{
|
||||
ObjectMeta: v1.ObjectMeta{Name: deploymentName},
|
||||
Spec: extensions.DeploymentSpec{
|
||||
Replicas: &replicas,
|
||||
Selector: &metav1.LabelSelector{MatchLabels: l},
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: v1.ObjectMeta{Labels: l},
|
||||
Spec: podSpec,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// It's safe to do this for alpha, as we don't have HA and there is no way we can get
|
||||
// more then one node here (TODO(phase1+) use os.Hostname)
|
||||
func findMyself(client *clientset.Clientset) (*v1.Node, error) {
|
||||
nodeList, err := client.Nodes().List(v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to list nodes [%v]", err)
|
||||
}
|
||||
if len(nodeList.Items) < 1 {
|
||||
return nil, fmt.Errorf("no nodes found")
|
||||
}
|
||||
node := &nodeList.Items[0]
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func attemptToUpdateMasterRoleLabelsAndTaints(client *clientset.Clientset, schedulable bool) error {
|
||||
n, err := findMyself(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n.ObjectMeta.Labels[metav1.NodeLabelKubeadmAlphaRole] = metav1.NodeLabelRoleMaster
|
||||
|
||||
if !schedulable {
|
||||
taintsAnnotation, _ := json.Marshal([]v1.Taint{{Key: "dedicated", Value: "master", Effect: "NoSchedule"}})
|
||||
n.ObjectMeta.Annotations[v1.TaintsAnnotationKey] = string(taintsAnnotation)
|
||||
}
|
||||
|
||||
if _, err := client.Nodes().Update(n); err != nil {
|
||||
if apierrs.IsConflict(err) {
|
||||
fmt.Println("[apiclient] Temporarily unable to update master node metadata due to conflict (will retry)")
|
||||
time.Sleep(apiCallRetryInterval)
|
||||
attemptToUpdateMasterRoleLabelsAndTaints(client, schedulable)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateMasterRoleLabelsAndTaints(client *clientset.Clientset, schedulable bool) error {
|
||||
// TODO(phase1+) use iterate instead of recursion
|
||||
err := attemptToUpdateMasterRoleLabelsAndTaints(client, schedulable)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update master node - [%v]", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetMasterTaintTolerations(meta *v1.ObjectMeta) {
|
||||
tolerationsAnnotation, _ := json.Marshal([]v1.Toleration{{Key: "dedicated", Value: "master", Effect: "NoSchedule"}})
|
||||
if meta.Annotations == nil {
|
||||
meta.Annotations = map[string]string{}
|
||||
}
|
||||
meta.Annotations[v1.TolerationsAnnotationKey] = string(tolerationsAnnotation)
|
||||
}
|
||||
|
||||
// SetNodeAffinity is a basic helper to set meta.Annotations[v1.AffinityAnnotationKey] for one or more v1.NodeSelectorRequirement(s)
|
||||
func SetNodeAffinity(meta *v1.ObjectMeta, expr ...v1.NodeSelectorRequirement) {
|
||||
nodeAffinity := &v1.NodeAffinity{
|
||||
RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{{MatchExpressions: expr}},
|
||||
},
|
||||
}
|
||||
affinityAnnotation, _ := json.Marshal(v1.Affinity{NodeAffinity: nodeAffinity})
|
||||
if meta.Annotations == nil {
|
||||
meta.Annotations = map[string]string{}
|
||||
}
|
||||
meta.Annotations[v1.AffinityAnnotationKey] = string(affinityAnnotation)
|
||||
}
|
||||
|
||||
// MasterNodeAffinity returns v1.NodeSelectorRequirement to be used with SetNodeAffinity to set affinity to master node
|
||||
func MasterNodeAffinity() v1.NodeSelectorRequirement {
|
||||
return v1.NodeSelectorRequirement{
|
||||
Key: metav1.NodeLabelKubeadmAlphaRole,
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{metav1.NodeLabelRoleMaster},
|
||||
}
|
||||
}
|
||||
|
||||
// NativeArchitectureNodeAffinity returns v1.NodeSelectorRequirement to be used with SetNodeAffinity to nodes with CPU architecture
|
||||
// the same as master node
|
||||
func NativeArchitectureNodeAffinity() v1.NodeSelectorRequirement {
|
||||
return v1.NodeSelectorRequirement{
|
||||
Key: "beta.kubernetes.io/arch", Operator: v1.NodeSelectorOpIn, Values: []string{runtime.GOARCH},
|
||||
}
|
||||
}
|
||||
|
||||
func createDummyDeployment(client *clientset.Clientset) {
|
||||
fmt.Println("[apiclient] Creating a test deployment")
|
||||
dummyDeployment := NewDeployment("dummy", 1, v1.PodSpec{
|
||||
HostNetwork: true,
|
||||
SecurityContext: &v1.PodSecurityContext{},
|
||||
Containers: []v1.Container{{
|
||||
Name: "dummy",
|
||||
Image: images.GetAddonImage("pause"),
|
||||
}},
|
||||
})
|
||||
|
||||
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
||||
// TODO: we should check the error, as some cases may be fatal
|
||||
if _, err := client.Extensions().Deployments(api.NamespaceSystem).Create(dummyDeployment); err != nil {
|
||||
fmt.Printf("[apiclient] Failed to create test deployment [%v] (will retry)\n", err)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
||||
d, err := client.Extensions().Deployments(api.NamespaceSystem).Get("dummy", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
fmt.Printf("[apiclient] Failed to get test deployment [%v] (will retry)\n", err)
|
||||
return false, nil
|
||||
}
|
||||
if d.Status.AvailableReplicas < 1 {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
fmt.Println("[apiclient] Test deployment succeeded")
|
||||
|
||||
// TODO: In the future, make sure the ReplicaSet and Pod are garbage collected
|
||||
if err := client.Extensions().Deployments(api.NamespaceSystem).Delete("dummy", &v1.DeleteOptions{}); err != nil {
|
||||
fmt.Printf("[apiclient] Failed to delete test deployment [%v] (will ignore)\n", err)
|
||||
}
|
||||
}
|
201
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/apiclient_test.go
generated
vendored
Normal file
201
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/apiclient_test.go
generated
vendored
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
func TestCreateClientAndWaitForAPI(t *testing.T) {
|
||||
cfg := &kubeadmapi.MasterConfiguration{
|
||||
Networking: kubeadm.Networking{DNSDomain: "localhost"},
|
||||
}
|
||||
fmt.Println(cfg)
|
||||
|
||||
}
|
||||
|
||||
func TestStandardLabels(t *testing.T) {
|
||||
var tests = []struct {
|
||||
n string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
n: "foo",
|
||||
expected: "foo",
|
||||
},
|
||||
{
|
||||
n: "bar",
|
||||
expected: "bar",
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := standardLabels(rt.n)
|
||||
if actual["component"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed standardLabels:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual["component"],
|
||||
)
|
||||
}
|
||||
if actual["name"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed standardLabels:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual["name"],
|
||||
)
|
||||
}
|
||||
if actual["k8s-app"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed standardLabels:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual["k8s-app"],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDaemonSet(t *testing.T) {
|
||||
var tests = []struct {
|
||||
dn string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
dn: "foo",
|
||||
expected: "foo",
|
||||
},
|
||||
{
|
||||
dn: "bar",
|
||||
expected: "bar",
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
p := apiv1.PodSpec{}
|
||||
actual := NewDaemonSet(rt.dn, p)
|
||||
if actual.Spec.Selector.MatchLabels["k8s-app"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed NewDaemonSet:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual.Spec.Selector.MatchLabels["k8s-app"],
|
||||
)
|
||||
}
|
||||
if actual.Spec.Selector.MatchLabels["component"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed NewDaemonSet:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual.Spec.Selector.MatchLabels["component"],
|
||||
)
|
||||
}
|
||||
if actual.Spec.Selector.MatchLabels["name"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed NewDaemonSet:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual.Spec.Selector.MatchLabels["name"],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewService(t *testing.T) {
|
||||
var tests = []struct {
|
||||
dn string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
dn: "foo",
|
||||
expected: "foo",
|
||||
},
|
||||
{
|
||||
dn: "bar",
|
||||
expected: "bar",
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
p := apiv1.ServiceSpec{}
|
||||
actual := NewService(rt.dn, p)
|
||||
if actual.ObjectMeta.Labels["k8s-app"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed NewService:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual.ObjectMeta.Labels["k8s-app"],
|
||||
)
|
||||
}
|
||||
if actual.ObjectMeta.Labels["component"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed NewService:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual.ObjectMeta.Labels["component"],
|
||||
)
|
||||
}
|
||||
if actual.ObjectMeta.Labels["name"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed NewService:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual.ObjectMeta.Labels["name"],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDeployment(t *testing.T) {
|
||||
var tests = []struct {
|
||||
dn string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
dn: "foo",
|
||||
expected: "foo",
|
||||
},
|
||||
{
|
||||
dn: "bar",
|
||||
expected: "bar",
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
p := apiv1.PodSpec{}
|
||||
actual := NewDeployment(rt.dn, 1, p)
|
||||
if actual.Spec.Selector.MatchLabels["k8s-app"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed NewDeployment:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual.Spec.Selector.MatchLabels["k8s-app"],
|
||||
)
|
||||
}
|
||||
if actual.Spec.Selector.MatchLabels["component"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed NewDeployment:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual.Spec.Selector.MatchLabels["component"],
|
||||
)
|
||||
}
|
||||
if actual.Spec.Selector.MatchLabels["name"] != rt.expected {
|
||||
t.Errorf(
|
||||
"failed NewDeployment:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual.Spec.Selector.MatchLabels["name"],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
150
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/discovery.go
generated
vendored
Normal file
150
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/discovery.go
generated
vendored
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
)
|
||||
|
||||
type kubeDiscovery struct {
|
||||
Deployment *extensions.Deployment
|
||||
Secret *v1.Secret
|
||||
}
|
||||
|
||||
const (
|
||||
kubeDiscoveryName = "kube-discovery"
|
||||
kubeDiscoverySecretName = "clusterinfo"
|
||||
)
|
||||
|
||||
func encodeKubeDiscoverySecretData(dcfg *kubeadmapi.TokenDiscovery, apicfg kubeadmapi.API, caCert *x509.Certificate) map[string][]byte {
|
||||
var (
|
||||
data = map[string][]byte{}
|
||||
endpointList = []string{}
|
||||
tokenMap = map[string]string{}
|
||||
)
|
||||
|
||||
for _, addr := range apicfg.AdvertiseAddresses {
|
||||
endpointList = append(endpointList, fmt.Sprintf("https://%s:%d", addr, apicfg.Port))
|
||||
}
|
||||
|
||||
tokenMap[dcfg.ID] = dcfg.Secret
|
||||
|
||||
data["endpoint-list.json"], _ = json.Marshal(endpointList)
|
||||
data["token-map.json"], _ = json.Marshal(tokenMap)
|
||||
data["ca.pem"] = certutil.EncodeCertPEM(caCert)
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func newKubeDiscoveryPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.PodSpec {
|
||||
return v1.PodSpec{
|
||||
// We have to use host network namespace, as `HostPort`/`HostIP` are Docker's
|
||||
// business and CNI support isn't quite there yet (except for kubenet)
|
||||
// (see https://github.com/kubernetes/kubernetes/issues/31307)
|
||||
// TODO update this when #31307 is resolved
|
||||
HostNetwork: true,
|
||||
SecurityContext: &v1.PodSecurityContext{},
|
||||
Containers: []v1.Container{{
|
||||
Name: kubeDiscoveryName,
|
||||
Image: kubeadmapi.GlobalEnvParams.DiscoveryImage,
|
||||
Command: []string{"/usr/local/bin/kube-discovery"},
|
||||
VolumeMounts: []v1.VolumeMount{{
|
||||
Name: kubeDiscoverySecretName,
|
||||
MountPath: "/tmp/secret", // TODO use a shared constant
|
||||
ReadOnly: true,
|
||||
}},
|
||||
Ports: []v1.ContainerPort{
|
||||
// TODO when CNI issue (#31307) is resolved, we should consider adding
|
||||
// `HostIP: s.API.AdvertiseAddrs[0]`, if there is only one address`
|
||||
{Name: "http", ContainerPort: kubeadmapiext.DefaultDiscoveryBindPort, HostPort: kubeadmutil.DiscoveryPort(cfg.Discovery.Token)},
|
||||
},
|
||||
SecurityContext: &v1.SecurityContext{
|
||||
SELinuxOptions: &v1.SELinuxOptions{
|
||||
// TODO: This implies our discovery container is not being restricted by
|
||||
// SELinux. This is not optimal and would be nice to adjust in future
|
||||
// so it can read /tmp/secret, but for now this avoids recommending
|
||||
// setenforce 0 system-wide.
|
||||
Type: "spc_t",
|
||||
},
|
||||
},
|
||||
}},
|
||||
Volumes: []v1.Volume{{
|
||||
Name: kubeDiscoverySecretName,
|
||||
VolumeSource: v1.VolumeSource{
|
||||
Secret: &v1.SecretVolumeSource{SecretName: kubeDiscoverySecretName},
|
||||
}},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newKubeDiscovery(cfg *kubeadmapi.MasterConfiguration, caCert *x509.Certificate) kubeDiscovery {
|
||||
kd := kubeDiscovery{
|
||||
Deployment: NewDeployment(kubeDiscoveryName, 1, newKubeDiscoveryPodSpec(cfg)),
|
||||
Secret: &v1.Secret{
|
||||
ObjectMeta: v1.ObjectMeta{Name: kubeDiscoverySecretName},
|
||||
Type: v1.SecretTypeOpaque,
|
||||
Data: encodeKubeDiscoverySecretData(cfg.Discovery.Token, cfg.API, caCert),
|
||||
},
|
||||
}
|
||||
|
||||
SetMasterTaintTolerations(&kd.Deployment.Spec.Template.ObjectMeta)
|
||||
SetNodeAffinity(&kd.Deployment.Spec.Template.ObjectMeta, MasterNodeAffinity(), NativeArchitectureNodeAffinity())
|
||||
|
||||
return kd
|
||||
}
|
||||
|
||||
func CreateDiscoveryDeploymentAndSecret(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset, caCert *x509.Certificate) error {
|
||||
kd := newKubeDiscovery(cfg, caCert)
|
||||
|
||||
if _, err := client.Extensions().Deployments(api.NamespaceSystem).Create(kd.Deployment); err != nil {
|
||||
return fmt.Errorf("failed to create %q deployment [%v]", kubeDiscoveryName, err)
|
||||
}
|
||||
if _, err := client.Secrets(api.NamespaceSystem).Create(kd.Secret); err != nil {
|
||||
return fmt.Errorf("failed to create %q secret [%v]", kubeDiscoverySecretName, err)
|
||||
}
|
||||
|
||||
fmt.Println("[token-discovery] Created the kube-discovery deployment, waiting for it to become ready")
|
||||
|
||||
start := time.Now()
|
||||
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
||||
d, err := client.Extensions().Deployments(api.NamespaceSystem).Get(kubeDiscoveryName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
if d.Status.AvailableReplicas < 1 {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
fmt.Printf("[token-discovery] kube-discovery is ready after %f seconds\n", time.Since(start).Seconds())
|
||||
|
||||
return nil
|
||||
}
|
49
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/discovery_test.go
generated
vendored
Normal file
49
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/discovery_test.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestNewKubeDiscovery(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
caCert *x509.Certificate
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{Port: 123, AdvertiseAddresses: []string{"10.0.0.1"}},
|
||||
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/1"},
|
||||
Discovery: kubeadmapi.Discovery{Token: &kubeadmapi.TokenDiscovery{}},
|
||||
},
|
||||
caCert: &x509.Certificate{},
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := newKubeDiscovery(rt.cfg, rt.caCert)
|
||||
if actual.Deployment == nil || actual.Secret == nil {
|
||||
t.Errorf(
|
||||
"failed newKubeDiscovery, kubeDiscovery was nil",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
408
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/manifests.go
generated
vendored
Normal file
408
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/manifests.go
generated
vendored
Normal file
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||
"k8s.io/kubernetes/pkg/api/resource"
|
||||
api "k8s.io/kubernetes/pkg/api/v1"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
|
||||
"github.com/blang/semver"
|
||||
)
|
||||
|
||||
// Static pod definitions in golang form are included below so that `kubeadm init` can get going.
|
||||
const (
|
||||
DefaultClusterName = "kubernetes"
|
||||
DefaultCloudConfigPath = "/etc/kubernetes/cloud-config"
|
||||
|
||||
etcd = "etcd"
|
||||
apiServer = "apiserver"
|
||||
controllerManager = "controller-manager"
|
||||
scheduler = "scheduler"
|
||||
proxy = "proxy"
|
||||
kubeAPIServer = "kube-apiserver"
|
||||
kubeControllerManager = "kube-controller-manager"
|
||||
kubeScheduler = "kube-scheduler"
|
||||
kubeProxy = "kube-proxy"
|
||||
)
|
||||
|
||||
var (
|
||||
// Minimum version of kube-apiserver that supports --kubelet-preferred-address-types
|
||||
preferredAddressAPIServerMinVersion = semver.MustParse("1.5.0")
|
||||
|
||||
// Minimum version of kube-apiserver that has to have --anonymous-auth=false set
|
||||
anonAuthDisableAPIServerMinVersion = semver.MustParse("1.5.0")
|
||||
)
|
||||
|
||||
// WriteStaticPodManifests builds manifest objects based on user provided configuration and then dumps it to disk
|
||||
// where kubelet will pick and schedule them.
|
||||
func WriteStaticPodManifests(cfg *kubeadmapi.MasterConfiguration) error {
|
||||
volumes := []api.Volume{k8sVolume(cfg)}
|
||||
volumeMounts := []api.VolumeMount{k8sVolumeMount()}
|
||||
|
||||
if isCertsVolumeMountNeeded() {
|
||||
volumes = append(volumes, certsVolume(cfg))
|
||||
volumeMounts = append(volumeMounts, certsVolumeMount())
|
||||
}
|
||||
|
||||
if isPkiVolumeMountNeeded() {
|
||||
volumes = append(volumes, pkiVolume(cfg))
|
||||
volumeMounts = append(volumeMounts, pkiVolumeMount())
|
||||
}
|
||||
|
||||
// Prepare static pod specs
|
||||
staticPodSpecs := map[string]api.Pod{
|
||||
kubeAPIServer: componentPod(api.Container{
|
||||
Name: kubeAPIServer,
|
||||
Image: images.GetCoreImage(images.KubeAPIServerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage),
|
||||
Command: getAPIServerCommand(cfg),
|
||||
VolumeMounts: volumeMounts,
|
||||
LivenessProbe: componentProbe(8080, "/healthz"),
|
||||
Resources: componentResources("250m"),
|
||||
Env: getProxyEnvVars(),
|
||||
}, volumes...),
|
||||
kubeControllerManager: componentPod(api.Container{
|
||||
Name: kubeControllerManager,
|
||||
Image: images.GetCoreImage(images.KubeControllerManagerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage),
|
||||
Command: getControllerManagerCommand(cfg),
|
||||
VolumeMounts: volumeMounts,
|
||||
LivenessProbe: componentProbe(10252, "/healthz"),
|
||||
Resources: componentResources("200m"),
|
||||
Env: getProxyEnvVars(),
|
||||
}, volumes...),
|
||||
kubeScheduler: componentPod(api.Container{
|
||||
Name: kubeScheduler,
|
||||
Image: images.GetCoreImage(images.KubeSchedulerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage),
|
||||
Command: getSchedulerCommand(cfg),
|
||||
LivenessProbe: componentProbe(10251, "/healthz"),
|
||||
Resources: componentResources("100m"),
|
||||
Env: getProxyEnvVars(),
|
||||
}),
|
||||
}
|
||||
|
||||
// Add etcd static pod spec only if external etcd is not configured
|
||||
if len(cfg.Etcd.Endpoints) == 0 {
|
||||
staticPodSpecs[etcd] = componentPod(api.Container{
|
||||
Name: etcd,
|
||||
Command: []string{
|
||||
"etcd",
|
||||
"--listen-client-urls=http://127.0.0.1:2379",
|
||||
"--advertise-client-urls=http://127.0.0.1:2379",
|
||||
"--data-dir=/var/lib/etcd",
|
||||
},
|
||||
VolumeMounts: []api.VolumeMount{certsVolumeMount(), etcdVolumeMount(), k8sVolumeMount()},
|
||||
Image: images.GetCoreImage(images.KubeEtcdImage, cfg, kubeadmapi.GlobalEnvParams.EtcdImage),
|
||||
LivenessProbe: componentProbe(2379, "/health"),
|
||||
Resources: componentResources("200m"),
|
||||
SecurityContext: &api.SecurityContext{
|
||||
SELinuxOptions: &api.SELinuxOptions{
|
||||
// TODO: This implies our etcd container is not being restricted by
|
||||
// SELinux. This is not optimal and would be nice to adjust in future
|
||||
// so it can create and write /var/lib/etcd, but for now this avoids
|
||||
// recommending setenforce 0 system-wide.
|
||||
Type: "spc_t",
|
||||
},
|
||||
},
|
||||
}, certsVolume(cfg), etcdVolume(cfg), k8sVolume(cfg))
|
||||
}
|
||||
|
||||
manifestsPath := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests")
|
||||
if err := os.MkdirAll(manifestsPath, 0700); err != nil {
|
||||
return fmt.Errorf("failed to create directory %q [%v]", manifestsPath, err)
|
||||
}
|
||||
for name, spec := range staticPodSpecs {
|
||||
filename := path.Join(manifestsPath, name+".json")
|
||||
serialized, err := json.MarshalIndent(spec, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal manifest for %q to JSON [%v]", name, err)
|
||||
}
|
||||
if err := cmdutil.DumpReaderToFile(bytes.NewReader(serialized), filename); err != nil {
|
||||
return fmt.Errorf("failed to create static pod manifest file for %q (%q) [%v]", name, filename, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// etcdVolume exposes a path on the host in order to guarantee data survival during reboot.
|
||||
func etcdVolume(cfg *kubeadmapi.MasterConfiguration) api.Volume {
|
||||
return api.Volume{
|
||||
Name: "etcd",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{Path: kubeadmapi.GlobalEnvParams.HostEtcdPath},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func etcdVolumeMount() api.VolumeMount {
|
||||
return api.VolumeMount{
|
||||
Name: "etcd",
|
||||
MountPath: "/var/lib/etcd",
|
||||
}
|
||||
}
|
||||
|
||||
func isCertsVolumeMountNeeded() bool {
|
||||
// Always return true for now. We may add conditional logic here for images which do not require host mounting /etc/ssl
|
||||
// hyperkube for example already has valid ca-certificates installed
|
||||
return true
|
||||
}
|
||||
|
||||
// certsVolume exposes host SSL certificates to pod containers.
|
||||
func certsVolume(cfg *kubeadmapi.MasterConfiguration) api.Volume {
|
||||
return api.Volume{
|
||||
Name: "certs",
|
||||
VolumeSource: api.VolumeSource{
|
||||
// TODO(phase1+) make path configurable
|
||||
HostPath: &api.HostPathVolumeSource{Path: "/etc/ssl/certs"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func certsVolumeMount() api.VolumeMount {
|
||||
return api.VolumeMount{
|
||||
Name: "certs",
|
||||
MountPath: "/etc/ssl/certs",
|
||||
}
|
||||
}
|
||||
|
||||
func isPkiVolumeMountNeeded() bool {
|
||||
// On some systems were we host-mount /etc/ssl/certs, it is also required to mount /etc/pki. This is needed
|
||||
// due to symlinks pointing from files in /etc/ssl/certs into /etc/pki/
|
||||
if _, err := os.Stat("/etc/pki"); err == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func pkiVolume(cfg *kubeadmapi.MasterConfiguration) api.Volume {
|
||||
return api.Volume{
|
||||
Name: "pki",
|
||||
VolumeSource: api.VolumeSource{
|
||||
// TODO(phase1+) make path configurable
|
||||
HostPath: &api.HostPathVolumeSource{Path: "/etc/pki"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func pkiVolumeMount() api.VolumeMount {
|
||||
return api.VolumeMount{
|
||||
Name: "pki",
|
||||
MountPath: "/etc/pki",
|
||||
}
|
||||
}
|
||||
|
||||
func k8sVolume(cfg *kubeadmapi.MasterConfiguration) api.Volume {
|
||||
return api.Volume{
|
||||
Name: "k8s",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{Path: kubeadmapi.GlobalEnvParams.KubernetesDir},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func k8sVolumeMount() api.VolumeMount {
|
||||
return api.VolumeMount{
|
||||
Name: "k8s",
|
||||
MountPath: "/etc/kubernetes/",
|
||||
ReadOnly: true,
|
||||
}
|
||||
}
|
||||
|
||||
func componentResources(cpu string) api.ResourceRequirements {
|
||||
return api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse(cpu),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func componentProbe(port int, path string) *api.Probe {
|
||||
return &api.Probe{
|
||||
Handler: api.Handler{
|
||||
HTTPGet: &api.HTTPGetAction{
|
||||
Host: "127.0.0.1",
|
||||
Path: path,
|
||||
Port: intstr.FromInt(port),
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: 15,
|
||||
TimeoutSeconds: 15,
|
||||
FailureThreshold: 8,
|
||||
}
|
||||
}
|
||||
|
||||
func componentPod(container api.Container, volumes ...api.Volume) api.Pod {
|
||||
return api.Pod{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: container.Name,
|
||||
Namespace: "kube-system",
|
||||
Labels: map[string]string{"component": container.Name, "tier": "control-plane"},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{container},
|
||||
HostNetwork: true,
|
||||
Volumes: volumes,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getComponentBaseCommand(component string) []string {
|
||||
if kubeadmapi.GlobalEnvParams.HyperkubeImage != "" {
|
||||
return []string{"/hyperkube", component}
|
||||
}
|
||||
|
||||
return []string{"kube-" + component}
|
||||
}
|
||||
|
||||
func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string {
|
||||
command := append(getComponentBaseCommand(apiServer),
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
|
||||
"--service-cluster-ip-range="+cfg.Networking.ServiceSubnet,
|
||||
"--service-account-key-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/apiserver-key.pem",
|
||||
"--client-ca-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/ca.pem",
|
||||
"--tls-cert-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/apiserver.pem",
|
||||
"--tls-private-key-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/apiserver-key.pem",
|
||||
"--token-auth-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/tokens.csv",
|
||||
fmt.Sprintf("--secure-port=%d", cfg.API.Port),
|
||||
"--allow-privileged",
|
||||
)
|
||||
|
||||
// Use first address we are given
|
||||
if len(cfg.API.AdvertiseAddresses) > 0 {
|
||||
command = append(command, fmt.Sprintf("--advertise-address=%s", cfg.API.AdvertiseAddresses[0]))
|
||||
}
|
||||
|
||||
if len(cfg.KubernetesVersion) != 0 {
|
||||
// If the k8s version is v1.5-something, this argument is set and makes `kubectl logs` and `kubectl exec`
|
||||
// work on bare-metal where hostnames aren't usually resolvable
|
||||
// Omit the "v" in the beginning, otherwise semver will fail
|
||||
k8sVersion, err := semver.Parse(cfg.KubernetesVersion[1:])
|
||||
|
||||
// If the k8s version is greater than this version, it supports telling it which way it should contact kubelets
|
||||
if err == nil && k8sVersion.GTE(preferredAddressAPIServerMinVersion) {
|
||||
command = append(command, "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname")
|
||||
}
|
||||
|
||||
// This is a critical "bugfix". Any version above this is vulnarable unless a RBAC/ABAC-authorizer is provided (which kubeadm doesn't for the time being)
|
||||
if err == nil && k8sVersion.GTE(anonAuthDisableAPIServerMinVersion) {
|
||||
command = append(command, "--anonymous-auth=false")
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the user decided to use an external etcd cluster
|
||||
if len(cfg.Etcd.Endpoints) > 0 {
|
||||
command = append(command, fmt.Sprintf("--etcd-servers=%s", strings.Join(cfg.Etcd.Endpoints, ",")))
|
||||
} else {
|
||||
command = append(command, "--etcd-servers=http://127.0.0.1:2379")
|
||||
}
|
||||
|
||||
// Is etcd secured?
|
||||
if cfg.Etcd.CAFile != "" {
|
||||
command = append(command, fmt.Sprintf("--etcd-cafile=%s", cfg.Etcd.CAFile))
|
||||
}
|
||||
if cfg.Etcd.CertFile != "" && cfg.Etcd.KeyFile != "" {
|
||||
etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", cfg.Etcd.CertFile)
|
||||
etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", cfg.Etcd.KeyFile)
|
||||
command = append(command, etcdClientFileArg, etcdKeyFileArg)
|
||||
}
|
||||
|
||||
if cfg.CloudProvider != "" {
|
||||
command = append(command, "--cloud-provider="+cfg.CloudProvider)
|
||||
|
||||
// Only append the --cloud-config option if there's a such file
|
||||
if _, err := os.Stat(DefaultCloudConfigPath); err == nil {
|
||||
command = append(command, "--cloud-config="+DefaultCloudConfigPath)
|
||||
}
|
||||
}
|
||||
|
||||
return command
|
||||
}
|
||||
|
||||
func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration) []string {
|
||||
command := append(getComponentBaseCommand(controllerManager),
|
||||
"--address=127.0.0.1",
|
||||
"--leader-elect",
|
||||
"--master=127.0.0.1:8080",
|
||||
"--cluster-name="+DefaultClusterName,
|
||||
"--root-ca-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/ca.pem",
|
||||
"--service-account-private-key-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/apiserver-key.pem",
|
||||
"--cluster-signing-cert-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/ca.pem",
|
||||
"--cluster-signing-key-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/ca-key.pem",
|
||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap",
|
||||
)
|
||||
|
||||
if cfg.CloudProvider != "" {
|
||||
command = append(command, "--cloud-provider="+cfg.CloudProvider)
|
||||
|
||||
// Only append the --cloud-config option if there's a such file
|
||||
if _, err := os.Stat(DefaultCloudConfigPath); err == nil {
|
||||
command = append(command, "--cloud-config="+DefaultCloudConfigPath)
|
||||
}
|
||||
}
|
||||
|
||||
// Let the controller-manager allocate Node CIDRs for the Pod network.
|
||||
// Each node will get a subspace of the address CIDR provided with --pod-network-cidr.
|
||||
if cfg.Networking.PodSubnet != "" {
|
||||
command = append(command, "--allocate-node-cidrs=true", "--cluster-cidr="+cfg.Networking.PodSubnet)
|
||||
}
|
||||
return command
|
||||
}
|
||||
|
||||
func getSchedulerCommand(cfg *kubeadmapi.MasterConfiguration) []string {
|
||||
return append(getComponentBaseCommand(scheduler),
|
||||
"--address=127.0.0.1",
|
||||
"--leader-elect",
|
||||
"--master=127.0.0.1:8080",
|
||||
)
|
||||
}
|
||||
|
||||
func getProxyCommand(cfg *kubeadmapi.MasterConfiguration) []string {
|
||||
return getComponentBaseCommand(proxy)
|
||||
}
|
||||
|
||||
func getProxyEnvVars() []api.EnvVar {
|
||||
envs := []api.EnvVar{}
|
||||
for _, env := range os.Environ() {
|
||||
pos := strings.Index(env, "=")
|
||||
if pos == -1 {
|
||||
// malformed environment variable, skip it.
|
||||
continue
|
||||
}
|
||||
name := env[:pos]
|
||||
value := env[pos+1:]
|
||||
if strings.HasSuffix(strings.ToLower(name), "_proxy") && value != "" {
|
||||
envVar := api.EnvVar{Name: name, Value: value}
|
||||
envs = append(envs, envVar)
|
||||
}
|
||||
}
|
||||
return envs
|
||||
}
|
594
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/manifests_test.go
generated
vendored
Normal file
594
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/manifests_test.go
generated
vendored
Normal file
|
@ -0,0 +1,594 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
api "k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
)
|
||||
|
||||
func TestWriteStaticPodManifests(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create tmpdir")
|
||||
}
|
||||
defer os.Remove(tmpdir)
|
||||
|
||||
// set up tmp GlobalEnvParams values for testing
|
||||
oldEnv := kubeadmapi.GlobalEnvParams
|
||||
kubeadmapi.GlobalEnvParams.KubernetesDir = fmt.Sprintf("%s/etc/kubernetes", tmpdir)
|
||||
defer func() { kubeadmapi.GlobalEnvParams = oldEnv }()
|
||||
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := WriteStaticPodManifests(rt.cfg)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed WriteStaticPodManifests with an error:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEtcdVolume(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected api.Volume
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{},
|
||||
expected: api.Volume{
|
||||
Name: "etcd",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{
|
||||
Path: kubeadmapi.GlobalEnvParams.HostEtcdPath},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := etcdVolume(rt.cfg)
|
||||
if actual.Name != rt.expected.Name {
|
||||
t.Errorf(
|
||||
"failed etcdVolume:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.Name,
|
||||
actual.Name,
|
||||
)
|
||||
}
|
||||
if actual.VolumeSource.HostPath.Path != rt.expected.VolumeSource.HostPath.Path {
|
||||
t.Errorf(
|
||||
"failed etcdVolume:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.VolumeSource.HostPath.Path,
|
||||
actual.VolumeSource.HostPath.Path,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEtcdVolumeMount(t *testing.T) {
|
||||
var tests = []struct {
|
||||
expected api.VolumeMount
|
||||
}{
|
||||
{
|
||||
expected: api.VolumeMount{
|
||||
Name: "etcd",
|
||||
MountPath: "/var/lib/etcd",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := etcdVolumeMount()
|
||||
if actual.Name != rt.expected.Name {
|
||||
t.Errorf(
|
||||
"failed etcdVolumeMount:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.Name,
|
||||
actual.Name,
|
||||
)
|
||||
}
|
||||
if actual.MountPath != rt.expected.MountPath {
|
||||
t.Errorf(
|
||||
"failed etcdVolumeMount:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.MountPath,
|
||||
actual.MountPath,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCertsVolume(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected api.Volume
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{},
|
||||
expected: api.Volume{
|
||||
Name: "certs",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{
|
||||
Path: "/etc/ssl/certs"},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := certsVolume(rt.cfg)
|
||||
if actual.Name != rt.expected.Name {
|
||||
t.Errorf(
|
||||
"failed certsVolume:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.Name,
|
||||
actual.Name,
|
||||
)
|
||||
}
|
||||
if actual.VolumeSource.HostPath.Path != rt.expected.VolumeSource.HostPath.Path {
|
||||
t.Errorf(
|
||||
"failed certsVolume:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.VolumeSource.HostPath.Path,
|
||||
actual.VolumeSource.HostPath.Path,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCertsVolumeMount(t *testing.T) {
|
||||
var tests = []struct {
|
||||
expected api.VolumeMount
|
||||
}{
|
||||
{
|
||||
expected: api.VolumeMount{
|
||||
Name: "certs",
|
||||
MountPath: "/etc/ssl/certs",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := certsVolumeMount()
|
||||
if actual.Name != rt.expected.Name {
|
||||
t.Errorf(
|
||||
"failed certsVolumeMount:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.Name,
|
||||
actual.Name,
|
||||
)
|
||||
}
|
||||
if actual.MountPath != rt.expected.MountPath {
|
||||
t.Errorf(
|
||||
"failed certsVolumeMount:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.MountPath,
|
||||
actual.MountPath,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestK8sVolume(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected api.Volume
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{},
|
||||
expected: api.Volume{
|
||||
Name: "k8s",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{
|
||||
Path: kubeadmapi.GlobalEnvParams.KubernetesDir},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := k8sVolume(rt.cfg)
|
||||
if actual.Name != rt.expected.Name {
|
||||
t.Errorf(
|
||||
"failed k8sVolume:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.Name,
|
||||
actual.Name,
|
||||
)
|
||||
}
|
||||
if actual.VolumeSource.HostPath.Path != rt.expected.VolumeSource.HostPath.Path {
|
||||
t.Errorf(
|
||||
"failed k8sVolume:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.VolumeSource.HostPath.Path,
|
||||
actual.VolumeSource.HostPath.Path,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestK8sVolumeMount(t *testing.T) {
|
||||
var tests = []struct {
|
||||
expected api.VolumeMount
|
||||
}{
|
||||
{
|
||||
expected: api.VolumeMount{
|
||||
Name: "k8s",
|
||||
MountPath: "/etc/kubernetes/",
|
||||
ReadOnly: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := k8sVolumeMount()
|
||||
if actual.Name != rt.expected.Name {
|
||||
t.Errorf(
|
||||
"failed k8sVolumeMount:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.Name,
|
||||
actual.Name,
|
||||
)
|
||||
}
|
||||
if actual.MountPath != rt.expected.MountPath {
|
||||
t.Errorf(
|
||||
"failed k8sVolumeMount:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected.MountPath,
|
||||
actual.MountPath,
|
||||
)
|
||||
}
|
||||
if actual.ReadOnly != rt.expected.ReadOnly {
|
||||
t.Errorf(
|
||||
"failed k8sVolumeMount:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected.ReadOnly,
|
||||
actual.ReadOnly,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestComponentResources(t *testing.T) {
|
||||
a := componentResources("250m")
|
||||
if a.Requests == nil {
|
||||
t.Errorf(
|
||||
"failed componentResources, return value was nil",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComponentProbe(t *testing.T) {
|
||||
var tests = []struct {
|
||||
port int
|
||||
path string
|
||||
}{
|
||||
{
|
||||
port: 1,
|
||||
path: "foo",
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := componentProbe(rt.port, rt.path)
|
||||
if actual.Handler.HTTPGet.Port != intstr.FromInt(rt.port) {
|
||||
t.Errorf(
|
||||
"failed componentProbe:\n\texpected: %v\n\t actual: %v",
|
||||
rt.port,
|
||||
actual.Handler.HTTPGet.Port,
|
||||
)
|
||||
}
|
||||
if actual.Handler.HTTPGet.Path != rt.path {
|
||||
t.Errorf(
|
||||
"failed componentProbe:\n\texpected: %s\n\t actual: %s",
|
||||
rt.path,
|
||||
actual.Handler.HTTPGet.Path,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestComponentPod(t *testing.T) {
|
||||
var tests = []struct {
|
||||
n string
|
||||
}{
|
||||
{
|
||||
n: "foo",
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
c := api.Container{Name: rt.n}
|
||||
v := api.Volume{}
|
||||
actual := componentPod(c, v)
|
||||
if actual.ObjectMeta.Name != rt.n {
|
||||
t.Errorf(
|
||||
"failed componentPod:\n\texpected: %s\n\t actual: %s",
|
||||
rt.n,
|
||||
actual.ObjectMeta.Name,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetComponentBaseCommand(t *testing.T) {
|
||||
var tests = []struct {
|
||||
c string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
c: "foo",
|
||||
expected: []string{"kube-foo", "--v=2"},
|
||||
},
|
||||
{
|
||||
c: "bar",
|
||||
expected: []string{"kube-bar", "--v=2"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := getComponentBaseCommand(rt.c)
|
||||
for i := range actual {
|
||||
if actual[i] != rt.expected[i] {
|
||||
t.Errorf(
|
||||
"failed getComponentBaseCommand:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected[i],
|
||||
actual[i],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAPIServerCommand(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadm.API{Port: 123},
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "bar"},
|
||||
},
|
||||
expected: []string{
|
||||
"kube-apiserver",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
|
||||
"--service-cluster-ip-range=bar",
|
||||
"--service-account-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||
"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.pem",
|
||||
"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv",
|
||||
fmt.Sprintf("--secure-port=%d", 123),
|
||||
"--allow-privileged",
|
||||
"--etcd-servers=http://127.0.0.1:2379",
|
||||
},
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadm.API{Port: 123, AdvertiseAddresses: []string{"foo"}},
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "bar"},
|
||||
},
|
||||
expected: []string{
|
||||
"kube-apiserver",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
|
||||
"--service-cluster-ip-range=bar",
|
||||
"--service-account-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||
"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.pem",
|
||||
"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv",
|
||||
fmt.Sprintf("--secure-port=%d", 123),
|
||||
"--allow-privileged",
|
||||
"--advertise-address=foo",
|
||||
"--etcd-servers=http://127.0.0.1:2379",
|
||||
},
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadm.API{Port: 123},
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "bar"},
|
||||
Etcd: kubeadm.Etcd{CertFile: "fiz", KeyFile: "faz"},
|
||||
},
|
||||
expected: []string{
|
||||
"kube-apiserver",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
|
||||
"--service-cluster-ip-range=bar",
|
||||
"--service-account-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||
"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.pem",
|
||||
"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv",
|
||||
fmt.Sprintf("--secure-port=%d", 123),
|
||||
"--allow-privileged",
|
||||
"--etcd-servers=http://127.0.0.1:2379",
|
||||
"--etcd-certfile=fiz",
|
||||
"--etcd-keyfile=faz",
|
||||
},
|
||||
},
|
||||
// Make sure --kubelet-preferred-address-types
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadm.API{Port: 123, AdvertiseAddresses: []string{"foo"}},
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "bar"},
|
||||
KubernetesVersion: "v1.5.3",
|
||||
},
|
||||
expected: []string{
|
||||
"kube-apiserver",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
|
||||
"--service-cluster-ip-range=bar",
|
||||
"--service-account-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||
"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.pem",
|
||||
"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv",
|
||||
fmt.Sprintf("--secure-port=%d", 123),
|
||||
"--allow-privileged",
|
||||
"--advertise-address=foo",
|
||||
"--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname",
|
||||
"--anonymous-auth=false",
|
||||
"--etcd-servers=http://127.0.0.1:2379",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := getAPIServerCommand(rt.cfg)
|
||||
for i := range actual {
|
||||
if actual[i] != rt.expected[i] {
|
||||
t.Errorf(
|
||||
"failed getAPIServerCommand:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected[i],
|
||||
actual[i],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetControllerManagerCommand(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{},
|
||||
expected: []string{
|
||||
"kube-controller-manager",
|
||||
"--address=127.0.0.1",
|
||||
"--leader-elect",
|
||||
"--master=127.0.0.1:8080",
|
||||
"--cluster-name=" + DefaultClusterName,
|
||||
"--root-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca-key.pem",
|
||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap",
|
||||
},
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{CloudProvider: "foo"},
|
||||
expected: []string{
|
||||
"kube-controller-manager",
|
||||
"--address=127.0.0.1",
|
||||
"--leader-elect",
|
||||
"--master=127.0.0.1:8080",
|
||||
"--cluster-name=" + DefaultClusterName,
|
||||
"--root-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca-key.pem",
|
||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap",
|
||||
"--cloud-provider=foo",
|
||||
},
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{Networking: kubeadm.Networking{PodSubnet: "bar"}},
|
||||
expected: []string{
|
||||
"kube-controller-manager",
|
||||
"--address=127.0.0.1",
|
||||
"--leader-elect",
|
||||
"--master=127.0.0.1:8080",
|
||||
"--cluster-name=" + DefaultClusterName,
|
||||
"--root-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-key.pem",
|
||||
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.pem",
|
||||
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca-key.pem",
|
||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap",
|
||||
"--allocate-node-cidrs=true",
|
||||
"--cluster-cidr=bar",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := getControllerManagerCommand(rt.cfg)
|
||||
for i := range actual {
|
||||
if actual[i] != rt.expected[i] {
|
||||
t.Errorf(
|
||||
"failed getControllerManagerCommand:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected[i],
|
||||
actual[i],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSchedulerCommand(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{},
|
||||
expected: []string{
|
||||
"kube-scheduler",
|
||||
"--address=127.0.0.1",
|
||||
"--leader-elect",
|
||||
"--master=127.0.0.1:8080",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := getSchedulerCommand(rt.cfg)
|
||||
for i := range actual {
|
||||
if actual[i] != rt.expected[i] {
|
||||
t.Errorf(
|
||||
"failed getSchedulerCommand:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected[i],
|
||||
actual[i],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetProxyCommand(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{},
|
||||
expected: []string{
|
||||
"kube-proxy",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := getProxyCommand(rt.cfg)
|
||||
for i := range actual {
|
||||
if actual[i] != rt.expected[i] {
|
||||
t.Errorf(
|
||||
"failed getProxyCommand:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected[i],
|
||||
actual[i],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/tokens.go
generated
vendored
Normal file
41
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/tokens.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/util/uuid"
|
||||
)
|
||||
|
||||
func CreateTokenAuthFile(bt string) error {
|
||||
tokenAuthFilePath := path.Join(kubeadmapi.GlobalEnvParams.HostPKIPath, "tokens.csv")
|
||||
if err := os.MkdirAll(kubeadmapi.GlobalEnvParams.HostPKIPath, 0700); err != nil {
|
||||
return fmt.Errorf("failed to create directory %q [%v]", kubeadmapi.GlobalEnvParams.HostPKIPath, err)
|
||||
}
|
||||
serialized := []byte(fmt.Sprintf("%s,kubeadm-node-csr,%s,system:kubelet-bootstrap\n", bt, uuid.NewUUID()))
|
||||
// DumpReaderToFile create a file with mode 0600
|
||||
if err := cmdutil.DumpReaderToFile(bytes.NewReader(serialized), tokenAuthFilePath); err != nil {
|
||||
return fmt.Errorf("failed to save token auth file (%q) [%v]", tokenAuthFilePath, err)
|
||||
}
|
||||
return nil
|
||||
}
|
65
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/BUILD
generated
vendored
Normal file
65
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bootstrap.go",
|
||||
"csr.go",
|
||||
"discovery.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/certificates:go_default_library",
|
||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
||||
"//pkg/kubelet/util/csr:go_default_library",
|
||||
"//pkg/util/cert:go_default_library",
|
||||
"//vendor:github.com/square/go-jose",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"bootstrap_test.go",
|
||||
"discovery_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/client/typed/discovery:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
164
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/bootstrap.go
generated
vendored
Normal file
164
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/bootstrap.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 node
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
)
|
||||
|
||||
// retryTimeout between the subsequent attempts to connect
|
||||
// to an API endpoint
|
||||
const retryTimeout = 5
|
||||
|
||||
type apiClient struct {
|
||||
clientSet *clientset.Clientset
|
||||
clientConfig *clientcmdapi.Config
|
||||
}
|
||||
|
||||
// EstablishMasterConnection establishes a connection with exactly one of the provided API endpoints.
|
||||
// The function builds a client for every endpoint and concurrently keeps trying to connect to any one
|
||||
// of the provided endpoints. Blocks until at least one connection is established, then it stops the
|
||||
// connection attempts for other endpoints and returns the valid client configuration, if any.
|
||||
func EstablishMasterConnection(c *kubeadmapi.TokenDiscovery, clusterInfo *kubeadmapi.ClusterInfo) (*clientcmdapi.Config, error) {
|
||||
hostName, err := os.Hostname()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get node hostname [%v]", err)
|
||||
}
|
||||
// TODO(phase1+) https://github.com/kubernetes/kubernetes/issues/33641
|
||||
nodeName := types.NodeName(hostName)
|
||||
|
||||
endpoints := clusterInfo.Endpoints
|
||||
caCert := []byte(clusterInfo.CertificateAuthorities[0])
|
||||
|
||||
stopChan := make(chan struct{})
|
||||
var clientConfig *clientcmdapi.Config
|
||||
var once sync.Once
|
||||
var wg sync.WaitGroup
|
||||
for _, endpoint := range endpoints {
|
||||
ac, err := createClients(caCert, endpoint, kubeadmutil.BearerToken(c), nodeName)
|
||||
if err != nil {
|
||||
fmt.Printf("[bootstrap] Warning: %s. Skipping endpoint %s\n", err, endpoint)
|
||||
continue
|
||||
}
|
||||
wg.Add(1)
|
||||
go func(apiEndpoint string) {
|
||||
defer wg.Done()
|
||||
wait.Until(func() {
|
||||
fmt.Printf("[bootstrap] Trying to connect to endpoint %s\n", apiEndpoint)
|
||||
err := checkAPIEndpoint(ac.clientSet, apiEndpoint)
|
||||
if err != nil {
|
||||
fmt.Printf("[bootstrap] Endpoint check failed [%v]\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("[bootstrap] Successfully established connection with endpoint %q\n", apiEndpoint)
|
||||
// connection established, stop all wait threads
|
||||
close(stopChan)
|
||||
once.Do(func() {
|
||||
clientConfig = ac.clientConfig
|
||||
})
|
||||
}, retryTimeout*time.Second, stopChan)
|
||||
}(endpoint)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
if clientConfig == nil {
|
||||
return nil, fmt.Errorf("failed to create bootstrap clients for any of the provided API endpoints")
|
||||
}
|
||||
|
||||
return clientConfig, nil
|
||||
}
|
||||
|
||||
// creates a set of clients for this endpoint
|
||||
func createClients(caCert []byte, endpoint, token string, nodeName types.NodeName) (*apiClient, error) {
|
||||
clientConfig := kubeconfigphase.MakeClientConfigWithToken(
|
||||
endpoint,
|
||||
"kubernetes",
|
||||
fmt.Sprintf("kubelet-%s", nodeName),
|
||||
caCert,
|
||||
token,
|
||||
)
|
||||
|
||||
bootstrapClientConfig, err := clientcmd.NewDefaultClientConfig(*clientConfig, &clientcmd.ConfigOverrides{}).ClientConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create API client configuration [%v]", err)
|
||||
}
|
||||
clientSet, err := clientset.NewForConfig(bootstrapClientConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create clients for the API endpoint %q: [%v]", endpoint, err)
|
||||
}
|
||||
|
||||
ac := &apiClient{
|
||||
clientSet: clientSet,
|
||||
clientConfig: clientConfig,
|
||||
}
|
||||
return ac, nil
|
||||
}
|
||||
|
||||
// checkForNodeNameDuplicates checks whether there are other nodes in the cluster with identical node names.
|
||||
func checkForNodeNameDuplicates(clientSet *clientset.Clientset) error {
|
||||
hostName, err := os.Hostname()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to get node hostname [%v]", err)
|
||||
}
|
||||
nodeList, err := clientSet.Nodes().List(v1.ListOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to list the nodes in the cluster: [%v]\n", err)
|
||||
}
|
||||
for _, node := range nodeList.Items {
|
||||
if hostName == node.Name {
|
||||
return fmt.Errorf("Node with name [%q] already exists.", node.Name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checks the connection requirements for a specific API endpoint
|
||||
func checkAPIEndpoint(clientSet *clientset.Clientset, endpoint string) error {
|
||||
// check general connectivity
|
||||
version, err := clientSet.DiscoveryClient.ServerVersion()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to %q [%v]", endpoint, err)
|
||||
}
|
||||
fmt.Printf("[bootstrap] Detected server version: %s\n", version.String())
|
||||
|
||||
// check certificates API
|
||||
serverGroups, err := clientSet.DiscoveryClient.ServerGroups()
|
||||
if err != nil {
|
||||
return fmt.Errorf("certificate API check failed: failed to retrieve a list of supported API objects [%v]", err)
|
||||
}
|
||||
for _, group := range serverGroups.Groups {
|
||||
if group.Name == certificates.GroupName {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("certificate API check failed: API version %s does not support certificates API, use v1.4.0 or newer",
|
||||
version.String())
|
||||
}
|
262
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/bootstrap_test.go
generated
vendored
Normal file
262
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/bootstrap_test.go
generated
vendored
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
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 node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
)
|
||||
|
||||
func TestEstablishMasterConnection(t *testing.T) {
|
||||
expect := version.Info{
|
||||
Major: "foo",
|
||||
Minor: "bar",
|
||||
GitCommit: "baz",
|
||||
}
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
var obj interface{}
|
||||
switch req.URL.Path {
|
||||
case "/api":
|
||||
obj = &metav1.APIVersions{
|
||||
Versions: []string{
|
||||
"v1.4",
|
||||
},
|
||||
}
|
||||
output, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected encoding error: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(output)
|
||||
case "/apis":
|
||||
obj = &metav1.APIGroupList{
|
||||
Groups: []metav1.APIGroup{
|
||||
{
|
||||
Name: "certificates.k8s.io",
|
||||
Versions: []metav1.GroupVersionForDiscovery{
|
||||
{GroupVersion: "extensions/v1beta1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
output, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected encoding error: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(output)
|
||||
default:
|
||||
output, err := json.Marshal(expect)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected encoding error: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(output)
|
||||
}
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
tests := []struct {
|
||||
c string
|
||||
e string
|
||||
expect bool
|
||||
}{
|
||||
{
|
||||
c: "",
|
||||
e: "",
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
c: "",
|
||||
e: srv.URL,
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
c: "foo",
|
||||
e: srv.URL,
|
||||
expect: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
s := &kubeadmapi.TokenDiscovery{}
|
||||
c := &kubeadmapi.ClusterInfo{Endpoints: []string{rt.e}, CertificateAuthorities: []string{rt.c}}
|
||||
_, actual := EstablishMasterConnection(s, c)
|
||||
if (actual == nil) != rt.expect {
|
||||
t.Errorf(
|
||||
"failed EstablishMasterConnection:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expect,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateClients(t *testing.T) {
|
||||
tests := []struct {
|
||||
e string
|
||||
expect bool
|
||||
}{
|
||||
{
|
||||
e: "",
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
e: "foo",
|
||||
expect: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
_, actual := createClients(nil, rt.e, "", "")
|
||||
if (actual == nil) != rt.expect {
|
||||
t.Errorf(
|
||||
"failed createClients:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expect,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckAPIEndpoint(t *testing.T) {
|
||||
expect := version.Info{
|
||||
Major: "foo",
|
||||
Minor: "bar",
|
||||
GitCommit: "baz",
|
||||
}
|
||||
tests := []struct {
|
||||
s *httptest.Server
|
||||
expect bool
|
||||
}{
|
||||
{
|
||||
s: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {})),
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
s: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
var obj interface{}
|
||||
switch req.URL.Path {
|
||||
case "/api":
|
||||
obj = &metav1.APIVersions{
|
||||
Versions: []string{
|
||||
"v1.4",
|
||||
},
|
||||
}
|
||||
output, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected encoding error: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(output)
|
||||
default:
|
||||
output, err := json.Marshal(expect)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected encoding error: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(output)
|
||||
}
|
||||
})),
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
s: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
var obj interface{}
|
||||
switch req.URL.Path {
|
||||
case "/api":
|
||||
obj = &metav1.APIVersions{
|
||||
Versions: []string{
|
||||
"v1.4",
|
||||
},
|
||||
}
|
||||
output, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected encoding error: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(output)
|
||||
case "/apis":
|
||||
obj = &metav1.APIGroupList{
|
||||
Groups: []metav1.APIGroup{
|
||||
{
|
||||
Name: "certificates.k8s.io",
|
||||
Versions: []metav1.GroupVersionForDiscovery{
|
||||
{GroupVersion: "extensions/v1beta1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
output, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected encoding error: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(output)
|
||||
default:
|
||||
output, err := json.Marshal(expect)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected encoding error: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(output)
|
||||
}
|
||||
})),
|
||||
expect: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
defer rt.s.Close()
|
||||
rc := &restclient.Config{Host: rt.s.URL}
|
||||
c, err := discovery.NewDiscoveryClientForConfig(rc)
|
||||
if err != nil {
|
||||
t.Fatalf("encountered an error while trying to get New Discovery Client: %v", err)
|
||||
}
|
||||
cs := &clientset.Clientset{DiscoveryClient: c}
|
||||
actual := checkAPIEndpoint(cs, "")
|
||||
if (actual == nil) != rt.expect {
|
||||
t.Errorf(
|
||||
"failed runChecks:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expect,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
76
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/csr.go
generated
vendored
Normal file
76
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/csr.go
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
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 node
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/csr"
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
)
|
||||
|
||||
// PerformTLSBootstrap executes a node certificate signing request.
|
||||
func PerformTLSBootstrap(cfg *clientcmdapi.Config) error {
|
||||
hostName, err := os.Hostname()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
name := types.NodeName(hostName)
|
||||
|
||||
rc, err := clientcmd.NewDefaultClientConfig(*cfg, &clientcmd.ConfigOverrides{}).ClientConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c, err := clientset.NewForConfig(rc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("[csr] Created API client to obtain unique certificate for this node, generating keys and certificate signing request")
|
||||
|
||||
key, err := certutil.MakeEllipticPrivateKeyPEM()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate private key [%v]", err)
|
||||
}
|
||||
|
||||
// Make sure there are no other nodes in the cluster with identical node name.
|
||||
if err := checkForNodeNameDuplicates(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cert, err := csr.RequestNodeCertificate(c.Certificates().CertificateSigningRequests(), key, name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to request signed certificate from the API server [%v]", err)
|
||||
}
|
||||
fmt.Printf("[csr] Received signed certificate from the API server")
|
||||
fmt.Println("[csr] Generating kubelet configuration")
|
||||
|
||||
cfg.AuthInfos["kubelet"] = &clientcmdapi.AuthInfo{
|
||||
ClientKeyData: key,
|
||||
ClientCertificateData: cert,
|
||||
}
|
||||
cfg.Contexts["kubelet"] = &clientcmdapi.Context{
|
||||
AuthInfo: "kubelet",
|
||||
Cluster: cfg.Contexts[cfg.CurrentContext].Cluster,
|
||||
}
|
||||
cfg.CurrentContext = "kubelet"
|
||||
return nil
|
||||
}
|
84
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/discovery.go
generated
vendored
Normal file
84
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/discovery.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
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 node
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
jose "github.com/square/go-jose"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
// the amount of time to wait between each request to the discovery API
|
||||
const discoveryRetryTimeout = 5 * time.Second
|
||||
|
||||
func RetrieveTrustedClusterInfo(d *kubeadmapi.TokenDiscovery) (*kubeadmapi.ClusterInfo, error) {
|
||||
requestURL := fmt.Sprintf("http://%s/cluster-info/v1/?token-id=%s", d.Addresses[0], d.ID)
|
||||
req, err := http.NewRequest("GET", requestURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to consturct an HTTP request [%v]", err)
|
||||
}
|
||||
|
||||
fmt.Printf("[discovery] Created cluster info discovery client, requesting info from %q\n", requestURL)
|
||||
|
||||
var res *http.Response
|
||||
wait.PollInfinite(discoveryRetryTimeout, func() (bool, error) {
|
||||
res, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
fmt.Printf("[discovery] Failed to request cluster info, will try again: [%s]\n", err)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
io.Copy(buf, res.Body)
|
||||
res.Body.Close()
|
||||
|
||||
object, err := jose.ParseSigned(buf.String())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse response as JWS object [%v]", err)
|
||||
}
|
||||
|
||||
fmt.Println("[discovery] Cluster info object received, verifying signature using given token")
|
||||
|
||||
output, err := object.Verify([]byte(d.Secret))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to verify JWS signature of received cluster info object [%v]", err)
|
||||
}
|
||||
|
||||
clusterInfo := kubeadmapi.ClusterInfo{}
|
||||
|
||||
if err := json.Unmarshal(output, &clusterInfo); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode received cluster info object [%v]", err)
|
||||
}
|
||||
|
||||
if len(clusterInfo.CertificateAuthorities) == 0 || len(clusterInfo.Endpoints) == 0 {
|
||||
return nil, fmt.Errorf("cluster info object is invalid - no endpoint(s) and/or root CA certificate(s) found")
|
||||
}
|
||||
|
||||
// TODO(phase1+) print summary info about the CA certificate, along with the the checksum signature
|
||||
// we also need an ability for the user to configure the client to validate received CA cert against a checksum
|
||||
fmt.Printf("[discovery] Cluster info signature and contents are valid, will use API endpoints %v\n", clusterInfo.Endpoints)
|
||||
return &clusterInfo, nil
|
||||
}
|
99
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/discovery_test.go
generated
vendored
Normal file
99
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/discovery_test.go
generated
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
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 node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
type rawJsonWebSignatureFake struct {
|
||||
Payload string `json:"payload,omitempty"`
|
||||
Signatures string `json:"signatures,omitempty"`
|
||||
Protected string `json:"protected,omitempty"`
|
||||
Header string `json:"header,omitempty"`
|
||||
Signature string `json:"signature,omitempty"`
|
||||
}
|
||||
|
||||
func TestRetrieveTrustedClusterInfo(t *testing.T) {
|
||||
j := rawJsonWebSignatureFake{}
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
switch req.URL.Path {
|
||||
default:
|
||||
output, err := json.Marshal(j)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected encoding error: %v", err)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(output)
|
||||
}
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
pURL, err := url.Parse(srv.URL)
|
||||
if err != nil {
|
||||
t.Fatalf("encountered an error while trying to parse httptest server url: %v", err)
|
||||
}
|
||||
host, port, err := net.SplitHostPort(pURL.Host)
|
||||
if err != nil {
|
||||
t.Fatalf("encountered an error while trying to split host and port info from httptest server: %v", err)
|
||||
}
|
||||
iPort, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
t.Fatalf("encountered an error while trying to convert string to int (httptest server port): %v", err)
|
||||
}
|
||||
tests := []struct {
|
||||
h string
|
||||
p int
|
||||
payload string
|
||||
expect bool
|
||||
}{
|
||||
{
|
||||
h: host,
|
||||
p: iPort,
|
||||
payload: "",
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
h: host,
|
||||
p: iPort,
|
||||
payload: "foo",
|
||||
expect: false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
j.Payload = rt.payload
|
||||
nc := &kubeadmapi.TokenDiscovery{Addresses: []string{rt.h + ":" + strconv.Itoa(rt.p)}}
|
||||
_, actual := RetrieveTrustedClusterInfo(nc)
|
||||
if (actual == nil) != rt.expect {
|
||||
t.Errorf(
|
||||
"failed createClients:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expect,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
51
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/BUILD
generated
vendored
Normal file
51
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"certs_test.go",
|
||||
"pki_helpers_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//pkg/util/cert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"certs.go",
|
||||
"doc.go",
|
||||
"pki_helpers.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||
"//pkg/util/cert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
102
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs.go
generated
vendored
Normal file
102
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs.go
generated
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
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 certs
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
)
|
||||
|
||||
// CreatePKIAssets will create and write to disk all PKI assets necessary to establish the control plane.
|
||||
// It first generates a self-signed CA certificate, a server certificate (signed by the CA) and a key for
|
||||
// signing service account tokens. It returns CA key and certificate, which is convenient for use with
|
||||
// client config funcs.
|
||||
func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration, pkiPath string) (*x509.Certificate, error) {
|
||||
altNames := certutil.AltNames{}
|
||||
|
||||
// First, define all domains this cert should be signed for
|
||||
internalAPIServerFQDN := []string{
|
||||
"kubernetes",
|
||||
"kubernetes.default",
|
||||
"kubernetes.default.svc",
|
||||
fmt.Sprintf("kubernetes.default.svc.%s", cfg.Networking.DNSDomain),
|
||||
}
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't get the hostname: %v", err)
|
||||
}
|
||||
altNames.DNSNames = append(cfg.API.ExternalDNSNames, hostname)
|
||||
altNames.DNSNames = append(altNames.DNSNames, internalAPIServerFQDN...)
|
||||
|
||||
// then, add all IP addresses we're bound to
|
||||
for _, a := range cfg.API.AdvertiseAddresses {
|
||||
if ip := net.ParseIP(a); ip != nil {
|
||||
altNames.IPs = append(altNames.IPs, ip)
|
||||
} else {
|
||||
return nil, fmt.Errorf("could not parse ip %q", a)
|
||||
}
|
||||
}
|
||||
// and lastly, extract the internal IP address for the API server
|
||||
_, n, err := net.ParseCIDR(cfg.Networking.ServiceSubnet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing CIDR %q: %v", cfg.Networking.ServiceSubnet, err)
|
||||
}
|
||||
internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(n, 1)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to allocate IP address for the API server from the given CIDR (%q) [%v]", &cfg.Networking.ServiceSubnet, err)
|
||||
}
|
||||
|
||||
altNames.IPs = append(altNames.IPs, internalAPIServerVirtualIP)
|
||||
|
||||
caKey, caCert, err := newCertificateAuthority()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failure while creating CA keys and certificate [%v]", err)
|
||||
}
|
||||
|
||||
if err := writeKeysAndCert(pkiPath, "ca", caKey, caCert); err != nil {
|
||||
return nil, fmt.Errorf("failure while saving CA keys and certificate [%v]", err)
|
||||
}
|
||||
fmt.Println("[certificates] Generated Certificate Authority key and certificate.")
|
||||
|
||||
apiKey, apiCert, err := newServerKeyAndCert(caCert, caKey, altNames)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failure while creating API server keys and certificate [%v]", err)
|
||||
}
|
||||
|
||||
if err := writeKeysAndCert(pkiPath, "apiserver", apiKey, apiCert); err != nil {
|
||||
return nil, fmt.Errorf("failure while saving API server keys and certificate [%v]", err)
|
||||
}
|
||||
fmt.Println("[certificates] Generated API Server key and certificate")
|
||||
|
||||
// Generate a private key for service accounts
|
||||
saKey, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failure while creating service account signing keys [%v]", err)
|
||||
}
|
||||
if err := writeKeysAndCert(pkiPath, "sa", saKey, nil); err != nil {
|
||||
return nil, fmt.Errorf("failure while saving service account signing keys [%v]", err)
|
||||
}
|
||||
fmt.Println("[certificates] Generated Service Account signing keys")
|
||||
fmt.Printf("[certificates] Created keys and certificates in %q\n", pkiPath)
|
||||
return caCert, nil
|
||||
}
|
77
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs_test.go
generated
vendored
Normal file
77
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/certs_test.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
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 certs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestCreatePKIAssets(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create tmpdir")
|
||||
}
|
||||
defer os.Remove(tmpdir)
|
||||
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
// CIDR too small
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{AdvertiseAddresses: []string{"10.0.0.1"}},
|
||||
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/1"},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
// CIDR invalid
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{AdvertiseAddresses: []string{"10.0.0.1"}},
|
||||
Networking: kubeadmapi.Networking{ServiceSubnet: "invalid"},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{AdvertiseAddresses: []string{"10.0.0.1"}},
|
||||
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/24"},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
_, actual := CreatePKIAssets(rt.cfg, fmt.Sprintf("%s/etc/kubernetes/pki", tmpdir))
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed CreatePKIAssets with an error:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
41
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/doc.go
generated
vendored
Normal file
41
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
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 certs
|
||||
|
||||
/*
|
||||
|
||||
PHASE: CERTIFICATES
|
||||
|
||||
INPUTS:
|
||||
From MasterConfiguration
|
||||
.API.AdvertiseAddresses is needed for knowing which IPs the certs should be signed for
|
||||
.API.ExternalDNSNames is needed for knowing which DNS names the certs should be signed for
|
||||
.Networking.DNSDomain is needed for knowing which DNS name the internal kubernetes service has
|
||||
.Networking.ServiceSubnet is needed for knowing which IP the internal kubernetes service is going to point to
|
||||
The PKIPath is required for knowing where all certificates should be stored
|
||||
|
||||
OUTPUTS:
|
||||
Files to PKIPath (default /etc/kubernetes/pki):
|
||||
- apiserver-key.pem
|
||||
- apiserver-pub.pem
|
||||
- apiserver.pem
|
||||
- ca-key.pem
|
||||
- ca-pub.pem
|
||||
- ca.pem
|
||||
- sa-key.pem
|
||||
- sa-pub.pem
|
||||
*/
|
110
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pki_helpers.go
generated
vendored
Normal file
110
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pki_helpers.go
generated
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
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 certs
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
)
|
||||
|
||||
func newCertificateAuthority() (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||
key, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to create private key [%v]", err)
|
||||
}
|
||||
|
||||
config := certutil.Config{
|
||||
CommonName: "kubernetes",
|
||||
}
|
||||
|
||||
cert, err := certutil.NewSelfSignedCACert(config, key)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to create self-signed certificate [%v]", err)
|
||||
}
|
||||
|
||||
return key, cert, nil
|
||||
}
|
||||
|
||||
func newServerKeyAndCert(caCert *x509.Certificate, caKey *rsa.PrivateKey, altNames certutil.AltNames) (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||
key, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to create private key [%v]", err)
|
||||
}
|
||||
|
||||
config := certutil.Config{
|
||||
CommonName: "kube-apiserver",
|
||||
AltNames: altNames,
|
||||
}
|
||||
cert, err := certutil.NewSignedCert(config, key, caCert, caKey)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to sign certificate [%v]", err)
|
||||
}
|
||||
|
||||
return key, cert, nil
|
||||
}
|
||||
|
||||
func NewClientKeyAndCert(caCert *x509.Certificate, caKey *rsa.PrivateKey) (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||
key, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to create private key [%v]", err)
|
||||
}
|
||||
|
||||
config := certutil.Config{
|
||||
CommonName: "kubernetes-client",
|
||||
}
|
||||
cert, err := certutil.NewSignedCert(config, key, caCert, caKey)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to sign certificate [%v]", err)
|
||||
}
|
||||
|
||||
return key, cert, nil
|
||||
}
|
||||
|
||||
func writeKeysAndCert(pkiPath string, name string, key *rsa.PrivateKey, cert *x509.Certificate) error {
|
||||
publicKeyPath, privateKeyPath, certificatePath := pathsKeysCerts(pkiPath, name)
|
||||
|
||||
if key != nil {
|
||||
if err := certutil.WriteKey(privateKeyPath, certutil.EncodePrivateKeyPEM(key)); err != nil {
|
||||
return fmt.Errorf("unable to write private key file (%q) [%v]", privateKeyPath, err)
|
||||
}
|
||||
if pubKey, err := certutil.EncodePublicKeyPEM(&key.PublicKey); err == nil {
|
||||
if err := certutil.WriteKey(publicKeyPath, pubKey); err != nil {
|
||||
return fmt.Errorf("unable to write public key file (%q) [%v]", publicKeyPath, err)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("unable to encode public key to PEM [%v]", err)
|
||||
}
|
||||
}
|
||||
|
||||
if cert != nil {
|
||||
if err := certutil.WriteCert(certificatePath, certutil.EncodeCertPEM(cert)); err != nil {
|
||||
return fmt.Errorf("unable to write certificate file (%q) [%v]", certificatePath, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func pathsKeysCerts(pkiPath, name string) (string, string, string) {
|
||||
return path.Join(pkiPath, fmt.Sprintf("%s-pub.pem", name)),
|
||||
path.Join(pkiPath, fmt.Sprintf("%s-key.pem", name)),
|
||||
path.Join(pkiPath, fmt.Sprintf("%s.pem", name))
|
||||
}
|
171
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pki_helpers_test.go
generated
vendored
Normal file
171
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/certs/pki_helpers_test.go
generated
vendored
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
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 certs
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
)
|
||||
|
||||
func TestNewCertificateAuthority(t *testing.T) {
|
||||
r, x, err := newCertificateAuthority()
|
||||
|
||||
if r == nil {
|
||||
t.Errorf(
|
||||
"failed newCertificateAuthority, rsa key == nil",
|
||||
)
|
||||
}
|
||||
if x == nil {
|
||||
t.Errorf(
|
||||
"failed newCertificateAuthority, x509 cert == nil",
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf(
|
||||
"failed newCertificateAuthority with an error: %v",
|
||||
err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewServerKeyAndCert(t *testing.T) {
|
||||
var tests = []struct {
|
||||
caKeySize int
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
// RSA key too small
|
||||
caKeySize: 128,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
// Should succeed
|
||||
caKeySize: 2048,
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
caKey, err := rsa.GenerateKey(rand.Reader, rt.caKeySize)
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create rsa Private Key")
|
||||
}
|
||||
caCert := &x509.Certificate{}
|
||||
altNames := certutil.AltNames{}
|
||||
_, _, actual := newServerKeyAndCert(caCert, caKey, altNames)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed newServerKeyAndCert:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewClientKeyAndCert(t *testing.T) {
|
||||
var tests = []struct {
|
||||
caKeySize int
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
// RSA key too small
|
||||
caKeySize: 128,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
caKeySize: 2048,
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
caKey, err := rsa.GenerateKey(rand.Reader, rt.caKeySize)
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create rsa Private Key")
|
||||
}
|
||||
caCert := &x509.Certificate{}
|
||||
_, _, actual := NewClientKeyAndCert(caCert, caKey)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed NewClientKeyAndCert:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteKeysAndCert(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create tmpdir")
|
||||
}
|
||||
defer os.Remove(tmpdir)
|
||||
|
||||
caKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create rsa Private Key")
|
||||
}
|
||||
caCert := &x509.Certificate{}
|
||||
actual := writeKeysAndCert(tmpdir, "foo", caKey, caCert)
|
||||
if actual != nil {
|
||||
t.Errorf(
|
||||
"failed writeKeysAndCert with an error: %v",
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathsKeysCerts(t *testing.T) {
|
||||
var tests = []struct {
|
||||
pkiPath string
|
||||
name string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
pkiPath: "foo",
|
||||
name: "bar",
|
||||
expected: []string{"foo/bar-pub.pem", "foo/bar-key.pem", "foo/bar.pem"},
|
||||
},
|
||||
{
|
||||
pkiPath: "bar",
|
||||
name: "foo",
|
||||
expected: []string{"bar/foo-pub.pem", "bar/foo-key.pem", "bar/foo.pem"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
a, b, c := pathsKeysCerts(rt.pkiPath, rt.name)
|
||||
all := []string{a, b, c}
|
||||
for i := range all {
|
||||
if all[i] != rt.expected[i] {
|
||||
t.Errorf(
|
||||
"failed pathsKeysCerts:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected[i],
|
||||
all[i],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig/BUILD
generated
vendored
Normal file
45
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["kubeconfig_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = ["//cmd/kubeadm/app/apis/kubeadm:go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"kubeconfig.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/phases/certs:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
||||
"//pkg/util/cert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
33
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig/doc.go
generated
vendored
Normal file
33
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
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 kubeconfig
|
||||
|
||||
/*
|
||||
|
||||
PHASE: KUBECONFIG
|
||||
|
||||
INPUTS:
|
||||
From MasterConfiguration
|
||||
(.API.AdvertiseAddresses is currently needed for knowing the) MasterAPIEndpoint is required so the KubeConfig file knows where to find the master
|
||||
The KubernetesDir path is required for knowing where to put the KubeConfig files
|
||||
The PKIPath is required for knowing where all certificates should be stored
|
||||
|
||||
OUTPUTS:
|
||||
Files to KubernetesDir (default /etc/kubernetes):
|
||||
- admin.conf
|
||||
- kubelet.conf
|
||||
*/
|
164
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go
generated
vendored
Normal file
164
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.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 kubeconfig
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
certphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
)
|
||||
|
||||
const (
|
||||
KubernetesDirPermissions = 0700
|
||||
AdminKubeConfigFileName = "admin.conf"
|
||||
KubeletKubeConfigFileName = "kubelet.conf"
|
||||
)
|
||||
|
||||
// This function is called from the main init and does the work for the default phase behaviour
|
||||
// TODO: Make an integration test for this function that runs after the certificates phase
|
||||
// and makes sure that those two phases work well together...
|
||||
func CreateAdminAndKubeletKubeConfig(masterEndpoint, pkiDir, outDir string) error {
|
||||
// Parse the certificate from a file
|
||||
caCertPath := path.Join(pkiDir, "ca.pem")
|
||||
caCerts, err := certutil.CertsFromFile(caCertPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't load the CA cert file %s: %v", caCertPath, err)
|
||||
}
|
||||
// We are only putting one certificate in the CA certificate pem file, so it's safe to just use the first one
|
||||
caCert := caCerts[0]
|
||||
|
||||
// Parse the rsa private key from a file
|
||||
caKeyPath := path.Join(pkiDir, "ca-key.pem")
|
||||
priv, err := certutil.PrivateKeyFromFile(caKeyPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't load the CA private key file %s: %v", caKeyPath, err)
|
||||
}
|
||||
var caKey *rsa.PrivateKey
|
||||
switch k := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
caKey = k
|
||||
case *ecdsa.PrivateKey:
|
||||
// TODO: Abstract rsa.PrivateKey away and make certutil.NewSignedCert accept a ecdsa.PrivateKey as well
|
||||
// After that, we can support generating kubeconfig files from ecdsa private keys as well
|
||||
return fmt.Errorf("the CA private key file %s isn't in RSA format", caKeyPath)
|
||||
default:
|
||||
return fmt.Errorf("the CA private key file %s isn't in RSA format", caKeyPath)
|
||||
}
|
||||
|
||||
// User admin should have full access to the cluster
|
||||
if err := createKubeConfigFileForClient(masterEndpoint, "admin", outDir, caCert, caKey); err != nil {
|
||||
return fmt.Errorf("couldn't create a kubeconfig file for admin: %v", err)
|
||||
}
|
||||
|
||||
// TODO: The kubelet should have limited access to the cluster
|
||||
if err := createKubeConfigFileForClient(masterEndpoint, "kubelet", outDir, caCert, caKey); err != nil {
|
||||
return fmt.Errorf("couldn't create a kubeconfig file for kubelet: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createKubeConfigFileForClient(masterEndpoint, client, outDir string, caCert *x509.Certificate, caKey *rsa.PrivateKey) error {
|
||||
key, cert, err := certphase.NewClientKeyAndCert(caCert, caKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failure while creating %s client certificate [%v]", client, err)
|
||||
}
|
||||
|
||||
config := MakeClientConfigWithCerts(
|
||||
masterEndpoint,
|
||||
"kubernetes",
|
||||
client,
|
||||
certutil.EncodeCertPEM(caCert),
|
||||
certutil.EncodePrivateKeyPEM(key),
|
||||
certutil.EncodeCertPEM(cert),
|
||||
)
|
||||
|
||||
// Write it now to a file
|
||||
filepath := path.Join(outDir, fmt.Sprintf("%s.conf", client))
|
||||
return WriteKubeconfigToDisk(filepath, config)
|
||||
}
|
||||
|
||||
func WriteKubeconfigToDisk(filepath string, kubeconfig *clientcmdapi.Config) error {
|
||||
// Make sure the dir exists or can be created
|
||||
if err := os.MkdirAll(path.Dir(filepath), KubernetesDirPermissions); err != nil {
|
||||
return fmt.Errorf("failed to create directory %q [%v]", path.Dir(filepath), err)
|
||||
}
|
||||
|
||||
// If err == nil, the file exists. Oops, we don't allow the file to exist already, fail.
|
||||
if _, err := os.Stat(filepath); err == nil {
|
||||
return fmt.Errorf("kubeconfig file %s already exists, but must not exist.", filepath)
|
||||
}
|
||||
|
||||
if err := clientcmd.WriteToFile(*kubeconfig, filepath); err != nil {
|
||||
return fmt.Errorf("failed to write to %q [%v]", filepath, err)
|
||||
}
|
||||
|
||||
fmt.Printf("[kubeconfig] Wrote KubeConfig file to disk: %q\n", filepath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func createBasicClientConfig(serverURL string, clusterName string, userName string, caCert []byte) *clientcmdapi.Config {
|
||||
config := clientcmdapi.NewConfig()
|
||||
|
||||
// Make a new cluster, specify the endpoint we'd like to talk to and the ca cert we're gonna use
|
||||
cluster := clientcmdapi.NewCluster()
|
||||
cluster.Server = serverURL
|
||||
cluster.CertificateAuthorityData = caCert
|
||||
|
||||
// Specify a context where we're using that cluster and the username as the auth information
|
||||
contextName := fmt.Sprintf("%s@%s", userName, clusterName)
|
||||
context := clientcmdapi.NewContext()
|
||||
context.Cluster = clusterName
|
||||
context.AuthInfo = userName
|
||||
|
||||
// Lastly, apply the created objects above to the config
|
||||
config.Clusters[clusterName] = cluster
|
||||
config.Contexts[contextName] = context
|
||||
config.CurrentContext = contextName
|
||||
return config
|
||||
}
|
||||
|
||||
// Creates a clientcmdapi.Config object with access to the API server with client certificates
|
||||
func MakeClientConfigWithCerts(serverURL, clusterName, userName string, caCert []byte, clientKey []byte, clientCert []byte) *clientcmdapi.Config {
|
||||
config := createBasicClientConfig(serverURL, clusterName, userName, caCert)
|
||||
|
||||
authInfo := clientcmdapi.NewAuthInfo()
|
||||
authInfo.ClientKeyData = clientKey
|
||||
authInfo.ClientCertificateData = clientCert
|
||||
|
||||
config.AuthInfos[userName] = authInfo
|
||||
return config
|
||||
}
|
||||
|
||||
// Creates a clientcmdapi.Config object with access to the API server with a token
|
||||
func MakeClientConfigWithToken(serverURL, clusterName, userName string, caCert []byte, token string) *clientcmdapi.Config {
|
||||
config := createBasicClientConfig(serverURL, clusterName, userName, caCert)
|
||||
|
||||
authInfo := clientcmdapi.NewAuthInfo()
|
||||
authInfo.Token = token
|
||||
|
||||
config.AuthInfos[userName] = authInfo
|
||||
return config
|
||||
}
|
189
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go
generated
vendored
Normal file
189
vendor/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go
generated
vendored
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
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 kubeconfig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
const (
|
||||
configOut1 = `apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
server: ""
|
||||
name: k8s
|
||||
contexts:
|
||||
- context:
|
||||
cluster: k8s
|
||||
user: user1
|
||||
name: user1@k8s
|
||||
current-context: user1@k8s
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: user1
|
||||
user:
|
||||
token: abc
|
||||
`
|
||||
configOut2 = `apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
server: localhost:8080
|
||||
name: kubernetes
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kubernetes
|
||||
user: user2
|
||||
name: user2@kubernetes
|
||||
current-context: user2@kubernetes
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: user2
|
||||
user:
|
||||
token: cba
|
||||
`
|
||||
)
|
||||
|
||||
type configClient struct {
|
||||
clusterName string
|
||||
userName string
|
||||
serverURL string
|
||||
caCert []byte
|
||||
}
|
||||
|
||||
type configClientWithCerts struct {
|
||||
clientKey []byte
|
||||
clientCert []byte
|
||||
}
|
||||
|
||||
type configClientWithToken struct {
|
||||
token string
|
||||
}
|
||||
|
||||
func TestMakeClientConfigWithCerts(t *testing.T) {
|
||||
var createBasicTest = []struct {
|
||||
cc configClient
|
||||
ccWithCerts configClientWithCerts
|
||||
expected string
|
||||
}{
|
||||
{configClient{}, configClientWithCerts{}, ""},
|
||||
{configClient{clusterName: "kubernetes"}, configClientWithCerts{}, ""},
|
||||
}
|
||||
for _, rt := range createBasicTest {
|
||||
cwc := MakeClientConfigWithCerts(
|
||||
rt.cc.serverURL,
|
||||
rt.cc.clusterName,
|
||||
rt.cc.userName,
|
||||
rt.cc.caCert,
|
||||
rt.ccWithCerts.clientKey,
|
||||
rt.ccWithCerts.clientCert,
|
||||
)
|
||||
if cwc.Kind != rt.expected {
|
||||
t.Errorf(
|
||||
"failed MakeClientConfigWithCerts:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
cwc.Kind,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeClientConfigWithToken(t *testing.T) {
|
||||
var createBasicTest = []struct {
|
||||
cc configClient
|
||||
ccWithToken configClientWithToken
|
||||
expected string
|
||||
}{
|
||||
{configClient{}, configClientWithToken{}, ""},
|
||||
{configClient{clusterName: "kubernetes"}, configClientWithToken{}, ""},
|
||||
}
|
||||
for _, rt := range createBasicTest {
|
||||
cwc := MakeClientConfigWithToken(
|
||||
rt.cc.serverURL,
|
||||
rt.cc.clusterName,
|
||||
rt.cc.userName,
|
||||
rt.cc.caCert,
|
||||
rt.ccWithToken.token,
|
||||
)
|
||||
if cwc.Kind != rt.expected {
|
||||
t.Errorf(
|
||||
"failed MakeClientConfigWithCerts:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
cwc.Kind,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteKubeconfigToDisk(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't create tmpdir")
|
||||
}
|
||||
defer os.Remove(tmpdir)
|
||||
|
||||
// set up tmp GlobalEnvParams values for testing
|
||||
oldEnv := kubeadmapi.GlobalEnvParams
|
||||
kubeadmapi.GlobalEnvParams = kubeadmapi.SetEnvParams()
|
||||
kubeadmapi.GlobalEnvParams.KubernetesDir = fmt.Sprintf("%s/etc/kubernetes", tmpdir)
|
||||
defer func() { kubeadmapi.GlobalEnvParams = oldEnv }()
|
||||
|
||||
var writeConfig = []struct {
|
||||
name string
|
||||
cc configClient
|
||||
ccWithToken configClientWithToken
|
||||
expected error
|
||||
file []byte
|
||||
}{
|
||||
{"test1", configClient{clusterName: "k8s", userName: "user1"}, configClientWithToken{token: "abc"}, nil, []byte(configOut1)},
|
||||
{"test2", configClient{clusterName: "kubernetes", userName: "user2", serverURL: "localhost:8080"}, configClientWithToken{token: "cba"}, nil, []byte(configOut2)},
|
||||
}
|
||||
for _, rt := range writeConfig {
|
||||
c := MakeClientConfigWithToken(
|
||||
rt.cc.serverURL,
|
||||
rt.cc.clusterName,
|
||||
rt.cc.userName,
|
||||
rt.cc.caCert,
|
||||
rt.ccWithToken.token,
|
||||
)
|
||||
configPath := filepath.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, fmt.Sprintf("%s.conf", rt.name))
|
||||
err := WriteKubeconfigToDisk(configPath, c)
|
||||
if err != rt.expected {
|
||||
t.Errorf(
|
||||
"failed WriteKubeconfigToDisk with an error:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
err,
|
||||
)
|
||||
}
|
||||
newFile, err := ioutil.ReadFile(configPath)
|
||||
if !bytes.Equal(newFile, rt.file) {
|
||||
t.Errorf(
|
||||
"failed WriteKubeconfigToDisk config write:\n\texpected: %s\n\t actual: %s",
|
||||
rt.file,
|
||||
newFile,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
43
vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/BUILD
generated
vendored
Normal file
43
vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["checks.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//pkg/api/validation:go_default_library",
|
||||
"//pkg/util/initsystem:go_default_library",
|
||||
"//pkg/util/node:go_default_library",
|
||||
"//test/e2e_node/system:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/errors",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["checks_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
416
vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks.go
generated
vendored
Normal file
416
vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks.go
generated
vendored
Normal file
|
@ -0,0 +1,416 @@
|
|||
/*
|
||||
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 preflight
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/util/initsystem"
|
||||
"k8s.io/kubernetes/pkg/util/node"
|
||||
"k8s.io/kubernetes/test/e2e_node/system"
|
||||
)
|
||||
|
||||
const bridgenf string = "/proc/sys/net/bridge/bridge-nf-call-iptables"
|
||||
|
||||
type Error struct {
|
||||
Msg string
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("[preflight] Some fatal errors occurred:\n%s%s", e.Msg, "[preflight] If you know what you are doing, you can skip pre-flight checks with `--skip-preflight-checks`")
|
||||
}
|
||||
|
||||
// Checker validates the state of the system to ensure kubeadm will be
|
||||
// successful as often as possilble.
|
||||
type Checker interface {
|
||||
Check() (warnings, errors []error)
|
||||
}
|
||||
|
||||
// ServiceCheck verifies that the given service is enabled and active. If we do not
|
||||
// detect a supported init system however, all checks are skipped and a warning is
|
||||
// returned.
|
||||
type ServiceCheck struct {
|
||||
Service string
|
||||
CheckIfActive bool
|
||||
}
|
||||
|
||||
func (sc ServiceCheck) Check() (warnings, errors []error) {
|
||||
initSystem, err := initsystem.GetInitSystem()
|
||||
if err != nil {
|
||||
return []error{err}, nil
|
||||
}
|
||||
|
||||
warnings = []error{}
|
||||
|
||||
if !initSystem.ServiceExists(sc.Service) {
|
||||
warnings = append(warnings, fmt.Errorf("%s service does not exist", sc.Service))
|
||||
return warnings, nil
|
||||
}
|
||||
|
||||
if !initSystem.ServiceIsEnabled(sc.Service) {
|
||||
warnings = append(warnings,
|
||||
fmt.Errorf("%s service is not enabled, please run 'systemctl enable %s.service'",
|
||||
sc.Service, sc.Service))
|
||||
}
|
||||
|
||||
if sc.CheckIfActive && !initSystem.ServiceIsActive(sc.Service) {
|
||||
errors = append(errors,
|
||||
fmt.Errorf("%s service is not active, please run 'systemctl start %s.service'",
|
||||
sc.Service, sc.Service))
|
||||
}
|
||||
|
||||
return warnings, errors
|
||||
}
|
||||
|
||||
// FirewalldCheck checks if firewalld is enabled or active, and if so outputs a warning.
|
||||
type FirewalldCheck struct {
|
||||
ports []int
|
||||
}
|
||||
|
||||
func (fc FirewalldCheck) Check() (warnings, errors []error) {
|
||||
initSystem, err := initsystem.GetInitSystem()
|
||||
if err != nil {
|
||||
return []error{err}, nil
|
||||
}
|
||||
|
||||
warnings = []error{}
|
||||
|
||||
if !initSystem.ServiceExists("firewalld") {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if initSystem.ServiceIsActive("firewalld") {
|
||||
warnings = append(warnings,
|
||||
fmt.Errorf("firewalld is active, please ensure ports %v are open or your cluster may not function correctly",
|
||||
fc.ports))
|
||||
}
|
||||
|
||||
return warnings, errors
|
||||
}
|
||||
|
||||
// PortOpenCheck ensures the given port is available for use.
|
||||
type PortOpenCheck struct {
|
||||
port int
|
||||
}
|
||||
|
||||
func (poc PortOpenCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
// TODO: Get IP from KubeadmConfig
|
||||
ln, err := net.Listen("tcp", fmt.Sprintf(":%d", poc.port))
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf("Port %d is in use", poc.port))
|
||||
}
|
||||
if ln != nil {
|
||||
ln.Close()
|
||||
}
|
||||
|
||||
return nil, errors
|
||||
}
|
||||
|
||||
// IsRootCheck verifies user is root
|
||||
type IsRootCheck struct{}
|
||||
|
||||
func (irc IsRootCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
if os.Getuid() != 0 {
|
||||
errors = append(errors, fmt.Errorf("user is not running as root"))
|
||||
}
|
||||
|
||||
return nil, errors
|
||||
}
|
||||
|
||||
// DirAvailableCheck checks if the given directory either does not exist, or is empty.
|
||||
type DirAvailableCheck struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
func (dac DirAvailableCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
// If it doesn't exist we are good:
|
||||
if _, err := os.Stat(dac.Path); os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
f, err := os.Open(dac.Path)
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf("unable to check if %s is empty: %s", dac.Path, err))
|
||||
return nil, errors
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
_, err = f.Readdirnames(1)
|
||||
if err != io.EOF {
|
||||
errors = append(errors, fmt.Errorf("%s is not empty", dac.Path))
|
||||
}
|
||||
|
||||
return nil, errors
|
||||
}
|
||||
|
||||
// FileAvailableCheck checks that the given file does not already exist.
|
||||
type FileAvailableCheck struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
func (fac FileAvailableCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
if _, err := os.Stat(fac.Path); err == nil {
|
||||
errors = append(errors, fmt.Errorf("%s already exists", fac.Path))
|
||||
}
|
||||
return nil, errors
|
||||
}
|
||||
|
||||
// FileContentCheck checks that the given file contains the string Content.
|
||||
type FileContentCheck struct {
|
||||
Path string
|
||||
Content []byte
|
||||
}
|
||||
|
||||
func (fcc FileContentCheck) Check() (warnings, errors []error) {
|
||||
f, err := os.Open(fcc.Path)
|
||||
if err != nil {
|
||||
return nil, []error{fmt.Errorf("%s does not exist", fcc.Path)}
|
||||
}
|
||||
|
||||
lr := io.LimitReader(f, int64(len(fcc.Content)))
|
||||
defer f.Close()
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
_, err = io.Copy(buf, lr)
|
||||
if err != nil {
|
||||
return nil, []error{fmt.Errorf("%s could not be read", fcc.Path)}
|
||||
}
|
||||
|
||||
if !bytes.Equal(buf.Bytes(), fcc.Content) {
|
||||
return nil, []error{fmt.Errorf("%s contents are not set to %s", fcc.Path, fcc.Content)}
|
||||
}
|
||||
return nil, []error{}
|
||||
|
||||
}
|
||||
|
||||
// InPathCheck checks if the given executable is present in the path.
|
||||
type InPathCheck struct {
|
||||
executable string
|
||||
mandatory bool
|
||||
}
|
||||
|
||||
func (ipc InPathCheck) Check() (warnings, errors []error) {
|
||||
_, err := exec.LookPath(ipc.executable)
|
||||
if err != nil {
|
||||
if ipc.mandatory {
|
||||
// Return as an error:
|
||||
return nil, []error{fmt.Errorf("%s not found in system path", ipc.executable)}
|
||||
}
|
||||
// Return as a warning:
|
||||
return []error{fmt.Errorf("%s not found in system path", ipc.executable)}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// HostnameCheck checks if hostname match dns sub domain regex.
|
||||
// If hostname doesn't match this regex, kubelet will not launch static pods like kube-apiserver/kube-controller-manager and so on.
|
||||
type HostnameCheck struct{}
|
||||
|
||||
func (hc HostnameCheck) Check() (warnings, errors []error) {
|
||||
errors = []error{}
|
||||
hostname := node.GetHostname("")
|
||||
for _, msg := range validation.ValidateNodeName(hostname, false) {
|
||||
errors = append(errors, fmt.Errorf("hostname \"%s\" %s", hostname, msg))
|
||||
}
|
||||
return nil, errors
|
||||
}
|
||||
|
||||
// HTTPProxyCheck checks if https connection to specific host is going
|
||||
// to be done directly or over proxy. If proxy detected, it will return warning.
|
||||
type HTTPProxyCheck struct {
|
||||
Proto string
|
||||
Host string
|
||||
Port int
|
||||
}
|
||||
|
||||
func (hst HTTPProxyCheck) Check() (warnings, errors []error) {
|
||||
|
||||
url := fmt.Sprintf("%s://%s:%d", hst.Proto, hst.Host, hst.Port)
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, []error{err}
|
||||
}
|
||||
|
||||
proxy, err := http.DefaultTransport.(*http.Transport).Proxy(req)
|
||||
if err != nil {
|
||||
return nil, []error{err}
|
||||
}
|
||||
if proxy != nil {
|
||||
return []error{fmt.Errorf("Connection to %q uses proxy %q. If that is not intended, adjust your proxy settings", url, proxy)}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type SystemVerificationCheck struct{}
|
||||
|
||||
func (sysver SystemVerificationCheck) Check() (warnings, errors []error) {
|
||||
// Create a buffered writer and choose a quite large value (1M) and suppose the output from the system verification test won't exceed the limit
|
||||
// Run the system verification check, but write to out buffered writer instead of stdout
|
||||
bufw := bufio.NewWriterSize(os.Stdout, 1*1024*1024)
|
||||
reporter := &system.StreamReporter{WriteStream: bufw}
|
||||
|
||||
var errs []error
|
||||
// All the validators we'd like to run:
|
||||
var validators = []system.Validator{
|
||||
&system.OSValidator{Reporter: reporter},
|
||||
&system.KernelValidator{Reporter: reporter},
|
||||
&system.CgroupsValidator{Reporter: reporter},
|
||||
&system.DockerValidator{Reporter: reporter},
|
||||
}
|
||||
|
||||
// Run all validators
|
||||
for _, v := range validators {
|
||||
errs = append(errs, v.Validate(system.DefaultSysSpec))
|
||||
}
|
||||
|
||||
err := utilerrors.NewAggregate(errs)
|
||||
if err != nil {
|
||||
// Only print the output from the system verification check if the check failed
|
||||
fmt.Println("[preflight] The system verification failed. Printing the output from the verification:")
|
||||
bufw.Flush()
|
||||
return nil, []error{err}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error {
|
||||
checks := []Checker{
|
||||
SystemVerificationCheck{},
|
||||
IsRootCheck{},
|
||||
HostnameCheck{},
|
||||
ServiceCheck{Service: "kubelet", CheckIfActive: false},
|
||||
ServiceCheck{Service: "docker", CheckIfActive: true},
|
||||
FirewalldCheck{ports: []int{int(cfg.API.Port), 10250}},
|
||||
PortOpenCheck{port: int(cfg.API.Port)},
|
||||
PortOpenCheck{port: 8080},
|
||||
PortOpenCheck{port: 10250},
|
||||
PortOpenCheck{port: 10251},
|
||||
PortOpenCheck{port: 10252},
|
||||
HTTPProxyCheck{Proto: "https", Host: cfg.API.AdvertiseAddresses[0], Port: int(cfg.API.Port)},
|
||||
DirAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests")},
|
||||
DirAvailableCheck{Path: kubeadmapi.GlobalEnvParams.HostPKIPath},
|
||||
DirAvailableCheck{Path: "/var/lib/kubelet"},
|
||||
FileAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "admin.conf")},
|
||||
FileAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "kubelet.conf")},
|
||||
FileContentCheck{Path: bridgenf, Content: []byte{'1'}},
|
||||
InPathCheck{executable: "ip", mandatory: true},
|
||||
InPathCheck{executable: "iptables", mandatory: true},
|
||||
InPathCheck{executable: "mount", mandatory: true},
|
||||
InPathCheck{executable: "nsenter", mandatory: true},
|
||||
InPathCheck{executable: "ebtables", mandatory: false},
|
||||
InPathCheck{executable: "ethtool", mandatory: false},
|
||||
InPathCheck{executable: "socat", mandatory: false},
|
||||
InPathCheck{executable: "tc", mandatory: false},
|
||||
InPathCheck{executable: "touch", mandatory: false},
|
||||
}
|
||||
|
||||
if len(cfg.Etcd.Endpoints) == 0 {
|
||||
// Only do etcd related checks when no external endpoints were specified
|
||||
checks = append(checks,
|
||||
PortOpenCheck{port: 2379},
|
||||
DirAvailableCheck{Path: "/var/lib/etcd"},
|
||||
)
|
||||
}
|
||||
|
||||
return RunChecks(checks, os.Stderr)
|
||||
}
|
||||
|
||||
func RunJoinNodeChecks(cfg *kubeadmapi.NodeConfiguration) error {
|
||||
checks := []Checker{
|
||||
SystemVerificationCheck{},
|
||||
IsRootCheck{},
|
||||
HostnameCheck{},
|
||||
ServiceCheck{Service: "kubelet", CheckIfActive: false},
|
||||
ServiceCheck{Service: "docker", CheckIfActive: true},
|
||||
PortOpenCheck{port: 10250},
|
||||
DirAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests")},
|
||||
DirAvailableCheck{Path: "/var/lib/kubelet"},
|
||||
FileAvailableCheck{Path: path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "kubelet.conf")},
|
||||
FileContentCheck{Path: bridgenf, Content: []byte{'1'}},
|
||||
InPathCheck{executable: "ip", mandatory: true},
|
||||
InPathCheck{executable: "iptables", mandatory: true},
|
||||
InPathCheck{executable: "mount", mandatory: true},
|
||||
InPathCheck{executable: "nsenter", mandatory: true},
|
||||
InPathCheck{executable: "ebtables", mandatory: false},
|
||||
InPathCheck{executable: "ethtool", mandatory: false},
|
||||
InPathCheck{executable: "socat", mandatory: false},
|
||||
InPathCheck{executable: "tc", mandatory: false},
|
||||
InPathCheck{executable: "touch", mandatory: false},
|
||||
}
|
||||
|
||||
return RunChecks(checks, os.Stderr)
|
||||
}
|
||||
|
||||
func RunRootCheckOnly() error {
|
||||
checks := []Checker{
|
||||
IsRootCheck{},
|
||||
}
|
||||
|
||||
return RunChecks(checks, os.Stderr)
|
||||
}
|
||||
|
||||
// RunChecks runs each check, displays it's warnings/errors, and once all
|
||||
// are processed will exit if any errors occurred.
|
||||
func RunChecks(checks []Checker, ww io.Writer) error {
|
||||
found := []error{}
|
||||
for _, c := range checks {
|
||||
warnings, errs := c.Check()
|
||||
for _, w := range warnings {
|
||||
io.WriteString(ww, fmt.Sprintf("[preflight] WARNING: %s\n", w))
|
||||
}
|
||||
found = append(found, errs...)
|
||||
}
|
||||
if len(found) > 0 {
|
||||
var errs bytes.Buffer
|
||||
for _, i := range found {
|
||||
errs.WriteString("\t" + i.Error() + "\n")
|
||||
}
|
||||
return &Error{Msg: errs.String()}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TryStartKubelet() {
|
||||
// If we notice that the kubelet service is inactive, try to start it
|
||||
initSystem, err := initsystem.GetInitSystem()
|
||||
if err != nil {
|
||||
fmt.Println("[preflight] No supported init system detected, won't ensure kubelet is running.")
|
||||
} else if initSystem.ServiceExists("kubelet") && !initSystem.ServiceIsActive("kubelet") {
|
||||
|
||||
fmt.Println("[preflight] Starting the kubelet service")
|
||||
if err := initSystem.ServiceStart("kubelet"); err != nil {
|
||||
fmt.Printf("[preflight] WARNING: Unable to start the kubelet service: [%v]\n", err)
|
||||
fmt.Println("[preflight] WARNING: Please ensure kubelet is running manually.")
|
||||
}
|
||||
}
|
||||
}
|
68
vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks_test.go
generated
vendored
Normal file
68
vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks_test.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
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 preflight
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type preflightCheckTest struct {
|
||||
msg string
|
||||
}
|
||||
|
||||
func (pfct preflightCheckTest) Check() (warning, errors []error) {
|
||||
if pfct.msg == "warning" {
|
||||
return []error{fmt.Errorf("warning")}, nil
|
||||
}
|
||||
if pfct.msg != "" {
|
||||
return nil, []error{fmt.Errorf("fake error")}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestRunChecks(t *testing.T) {
|
||||
var tokenTest = []struct {
|
||||
p []Checker
|
||||
expected bool
|
||||
output string
|
||||
}{
|
||||
{[]Checker{}, true, ""},
|
||||
{[]Checker{preflightCheckTest{"warning"}}, true, "[preflight] WARNING: warning\n"}, // should just print warning
|
||||
{[]Checker{preflightCheckTest{"error"}}, false, ""},
|
||||
{[]Checker{preflightCheckTest{"test"}}, false, ""},
|
||||
}
|
||||
for _, rt := range tokenTest {
|
||||
buf := new(bytes.Buffer)
|
||||
actual := RunChecks(rt.p, buf)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed RunChecks:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
if buf.String() != rt.output {
|
||||
t.Errorf(
|
||||
"failed RunChecks:\n\texpected: %s\n\t actual: %s",
|
||||
rt.output,
|
||||
buf.String(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
57
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/BUILD
generated
vendored
Normal file
57
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"error.go",
|
||||
"tokens.go",
|
||||
"version.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"error_test.go",
|
||||
"tokens_test.go",
|
||||
"version_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
69
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error.go
generated
vendored
Normal file
69
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error.go
generated
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultErrorExitCode = 1
|
||||
PreFlightExitCode = 2
|
||||
)
|
||||
|
||||
type debugError interface {
|
||||
DebugError() (msg string, args []interface{})
|
||||
}
|
||||
|
||||
// fatal prints the message if set and then exits.
|
||||
func fatal(msg string, code int) {
|
||||
if len(msg) > 0 {
|
||||
// add newline if needed
|
||||
if !strings.HasSuffix(msg, "\n") {
|
||||
msg += "\n"
|
||||
}
|
||||
|
||||
fmt.Fprint(os.Stderr, msg)
|
||||
}
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
// CheckErr prints a user friendly error to STDERR and exits with a non-zero
|
||||
// exit code. Unrecognized errors will be printed with an "error: " prefix.
|
||||
//
|
||||
// This method is generic to the command in use and may be used by non-Kubectl
|
||||
// commands.
|
||||
func CheckErr(err error) {
|
||||
checkErr("", err, fatal)
|
||||
}
|
||||
|
||||
// checkErr formats a given error as a string and calls the passed handleErr
|
||||
// func with that string and an kubectl exit code.
|
||||
func checkErr(prefix string, err error, handleErr func(string, int)) {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
return
|
||||
case *preflight.Error:
|
||||
handleErr(err.Error(), PreFlightExitCode)
|
||||
default:
|
||||
handleErr(err.Error(), DefaultErrorExitCode)
|
||||
}
|
||||
}
|
52
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error_test.go
generated
vendored
Normal file
52
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error_test.go
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
)
|
||||
|
||||
func TestCheckErr(t *testing.T) {
|
||||
var codeReturned int
|
||||
errHandle := func(err string, code int) {
|
||||
codeReturned = code
|
||||
}
|
||||
|
||||
var tokenTest = []struct {
|
||||
e error
|
||||
expected int
|
||||
}{
|
||||
{nil, 0},
|
||||
{fmt.Errorf(""), DefaultErrorExitCode},
|
||||
{&preflight.Error{}, PreFlightExitCode},
|
||||
}
|
||||
|
||||
for _, rt := range tokenTest {
|
||||
codeReturned = 0
|
||||
checkErr("", rt.e, errHandle)
|
||||
if codeReturned != rt.expected {
|
||||
t.Errorf(
|
||||
"failed checkErr:\n\texpected: %d\n\t actual: %d",
|
||||
rt.expected,
|
||||
codeReturned,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
194
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/tokens.go
generated
vendored
Normal file
194
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/tokens.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 util
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
)
|
||||
|
||||
const (
|
||||
TokenIDBytes = 3
|
||||
TokenSecretBytes = 8
|
||||
BootstrapTokenSecretPrefix = "bootstrap-token-"
|
||||
DefaultTokenDuration = time.Duration(8) * time.Hour
|
||||
tokenCreateRetries = 5
|
||||
)
|
||||
|
||||
var (
|
||||
tokenIDRegexpString = "^([a-z0-9]{6})$"
|
||||
tokenIDRegexp = regexp.MustCompile(tokenIDRegexpString)
|
||||
tokenRegexpString = "^([a-z0-9]{6})\\:([a-z0-9]{16})$"
|
||||
tokenRegexp = regexp.MustCompile(tokenRegexpString)
|
||||
)
|
||||
|
||||
func randBytes(length int) (string, error) {
|
||||
b := make([]byte, length)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hex.EncodeToString(b), nil
|
||||
}
|
||||
|
||||
// GenerateToken generates a new token with a token ID that is valid as a
|
||||
// Kubernetes DNS label.
|
||||
// For more info, see kubernetes/pkg/util/validation/validation.go.
|
||||
func GenerateToken(d *kubeadmapi.TokenDiscovery) error {
|
||||
tokenID, err := randBytes(TokenIDBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
token, err := randBytes(TokenSecretBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.ID = strings.ToLower(tokenID)
|
||||
d.Secret = strings.ToLower(token)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseTokenID tries and parse a valid token ID from a string.
|
||||
// An error is returned in case of failure.
|
||||
func ParseTokenID(s string) error {
|
||||
if !tokenIDRegexp.MatchString(s) {
|
||||
return fmt.Errorf("token ID [%q] was not of form [%q]", s, tokenIDRegexpString)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// ParseToken tries and parse a valid token from a string.
|
||||
// A token ID and token secret are returned in case of success, an error otherwise.
|
||||
func ParseToken(s string) (string, string, error) {
|
||||
split := tokenRegexp.FindStringSubmatch(s)
|
||||
if len(split) != 3 {
|
||||
return "", "", fmt.Errorf("token [%q] was not of form [%q]", s, tokenRegexpString)
|
||||
}
|
||||
return split[1], split[2], nil
|
||||
|
||||
}
|
||||
|
||||
// BearerToken returns a string representation of the passed token.
|
||||
func BearerToken(d *kubeadmapi.TokenDiscovery) string {
|
||||
return fmt.Sprintf("%s:%s", d.ID, d.Secret)
|
||||
}
|
||||
|
||||
// ValidateToken validates whether a token is well-formed.
|
||||
// In case it's not, the corresponding error is returned as well.
|
||||
func ValidateToken(d *kubeadmapi.TokenDiscovery) (bool, error) {
|
||||
if _, _, err := ParseToken(d.ID + ":" + d.Secret); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func DiscoveryPort(d *kubeadmapi.TokenDiscovery) int32 {
|
||||
if len(d.Addresses) == 0 {
|
||||
return kubeadmapiext.DefaultDiscoveryBindPort
|
||||
}
|
||||
split := strings.Split(d.Addresses[0], ":")
|
||||
if len(split) == 1 {
|
||||
return kubeadmapiext.DefaultDiscoveryBindPort
|
||||
}
|
||||
if i, err := strconv.Atoi(split[1]); err != nil {
|
||||
return int32(i)
|
||||
}
|
||||
return kubeadmapiext.DefaultDiscoveryBindPort
|
||||
}
|
||||
|
||||
// UpdateOrCreateToken attempts to update a token with the given ID, or create if it does
|
||||
// not already exist.
|
||||
func UpdateOrCreateToken(client *clientset.Clientset, d *kubeadmapi.TokenDiscovery, tokenDuration time.Duration) error {
|
||||
// Let's make sure
|
||||
if valid, err := ValidateToken(d); !valid {
|
||||
return err
|
||||
}
|
||||
secretName := fmt.Sprintf("%s%s", BootstrapTokenSecretPrefix, d.ID)
|
||||
var lastErr error
|
||||
for i := 0; i < tokenCreateRetries; i++ {
|
||||
secret, err := client.Secrets(api.NamespaceSystem).Get(secretName, metav1.GetOptions{})
|
||||
if err == nil {
|
||||
// Secret with this ID already exists, update it:
|
||||
secret.Data = encodeTokenSecretData(d, tokenDuration)
|
||||
if _, err := client.Secrets(api.NamespaceSystem).Update(secret); err == nil {
|
||||
return nil
|
||||
} else {
|
||||
lastErr = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Secret does not already exist:
|
||||
if apierrors.IsNotFound(err) {
|
||||
secret = &v1.Secret{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: secretName,
|
||||
},
|
||||
Type: api.SecretTypeBootstrapToken,
|
||||
Data: encodeTokenSecretData(d, tokenDuration),
|
||||
}
|
||||
if _, err := client.Secrets(api.NamespaceSystem).Create(secret); err == nil {
|
||||
return nil
|
||||
} else {
|
||||
lastErr = err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
return fmt.Errorf(
|
||||
"unable to create bootstrap token after %d attempts [%v]",
|
||||
tokenCreateRetries,
|
||||
lastErr,
|
||||
)
|
||||
}
|
||||
|
||||
func encodeTokenSecretData(d *kubeadmapi.TokenDiscovery, duration time.Duration) map[string][]byte {
|
||||
var (
|
||||
data = map[string][]byte{}
|
||||
)
|
||||
|
||||
data["token-id"] = []byte(d.ID)
|
||||
data["token-secret"] = []byte(d.Secret)
|
||||
|
||||
data["usage-bootstrap-signing"] = []byte("true")
|
||||
|
||||
if duration > 0 {
|
||||
t := time.Now()
|
||||
t = t.Add(duration)
|
||||
data["expiration"] = []byte(t.Format(time.RFC3339))
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
143
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/tokens_test.go
generated
vendored
Normal file
143
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/tokens_test.go
generated
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestTokenParse(t *testing.T) {
|
||||
invalidTokens := []string{
|
||||
// invalid parcel size
|
||||
"1234567890123456789012",
|
||||
"12345:1234567890123456",
|
||||
".1234567890123456",
|
||||
// invalid separation
|
||||
"123456:1234567890.123456",
|
||||
"abcdef.1234567890123456",
|
||||
// invalid token id
|
||||
"Abcdef:1234567890123456",
|
||||
// invalid token secret
|
||||
"123456:AABBCCDDEEFFGGHH",
|
||||
}
|
||||
|
||||
for _, token := range invalidTokens {
|
||||
if _, _, err := ParseToken(token); err == nil {
|
||||
t.Errorf("ParseToken did not return an error for this invalid token: [%s]", token)
|
||||
}
|
||||
}
|
||||
|
||||
validTokens := []string{
|
||||
"abcdef:1234567890123456",
|
||||
"123456:aabbccddeeffgghh",
|
||||
}
|
||||
|
||||
for _, token := range validTokens {
|
||||
if _, _, err := ParseToken(token); err != nil {
|
||||
t.Errorf("ParseToken returned an error for this valid token: [%s]", token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTokenID(t *testing.T) {
|
||||
invalidTokenIDs := []string{
|
||||
"",
|
||||
"1234567890123456789012",
|
||||
"12345",
|
||||
"Abcdef",
|
||||
}
|
||||
|
||||
for _, tokenID := range invalidTokenIDs {
|
||||
if err := ParseTokenID(tokenID); err == nil {
|
||||
t.Errorf("ParseTokenID did not return an error for this invalid token ID: [%q]", tokenID)
|
||||
}
|
||||
}
|
||||
|
||||
validTokens := []string{
|
||||
"abcdef",
|
||||
"123456",
|
||||
}
|
||||
|
||||
for _, tokenID := range validTokens {
|
||||
if err := ParseTokenID(tokenID); err != nil {
|
||||
t.Errorf("ParseTokenID failed for a valid token ID [%q], err: %+v", tokenID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateToken(t *testing.T) {
|
||||
invalidTokens := []*kubeadmapi.TokenDiscovery{
|
||||
{ID: "", Secret: ""},
|
||||
{ID: "1234567890123456789012", Secret: ""},
|
||||
{ID: "", Secret: "1234567890123456789012"},
|
||||
{ID: "12345", Secret: "1234567890123456"},
|
||||
{ID: "Abcdef", Secret: "1234567890123456"},
|
||||
{ID: "123456", Secret: "AABBCCDDEEFFGGHH"},
|
||||
}
|
||||
|
||||
for _, token := range invalidTokens {
|
||||
if valid, err := ValidateToken(token); valid == true || err == nil {
|
||||
t.Errorf("ValidateToken did not return an error for this invalid token: [%s]", token)
|
||||
}
|
||||
}
|
||||
|
||||
validTokens := []*kubeadmapi.TokenDiscovery{
|
||||
{ID: "abcdef", Secret: "1234567890123456"},
|
||||
{ID: "123456", Secret: "aabbccddeeffgghh"},
|
||||
}
|
||||
|
||||
for _, token := range validTokens {
|
||||
if valid, err := ValidateToken(token); valid == false || err != nil {
|
||||
t.Errorf("ValidateToken failed for a valid token [%s], valid: %t, err: %+v", token, valid, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateToken(t *testing.T) {
|
||||
td := &kubeadmapi.TokenDiscovery{}
|
||||
if err := GenerateToken(td); err != nil {
|
||||
t.Fatalf("GenerateToken returned an unexpected error: %+v", err)
|
||||
}
|
||||
if len(td.ID) != 6 {
|
||||
t.Errorf("failed GenerateToken first part length:\n\texpected: 6\n\t actual: %d", len(td.ID))
|
||||
}
|
||||
if len(td.Secret) != 16 {
|
||||
t.Errorf("failed GenerateToken second part length:\n\texpected: 16\n\t actual: %d", len(td.Secret))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandBytes(t *testing.T) {
|
||||
var randTest = []int{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
100,
|
||||
}
|
||||
|
||||
for _, rt := range randTest {
|
||||
actual, err := randBytes(rt)
|
||||
if err != nil {
|
||||
t.Errorf("failed randBytes: %v", err)
|
||||
}
|
||||
if len(actual) != rt*2 {
|
||||
t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt*2, len(actual))
|
||||
}
|
||||
}
|
||||
}
|
71
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/version.go
generated
vendored
Normal file
71
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/version.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
kubeReleaseBucketURL = "https://storage.googleapis.com/kubernetes-release/release"
|
||||
kubeReleaseRegex = regexp.MustCompile(`^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)([-0-9a-zA-Z_\.+]*)?$`)
|
||||
kubeReleaseLabelRegex = regexp.MustCompile(`^[[:lower:]]+(-[-\w_\.]+)?$`)
|
||||
)
|
||||
|
||||
// KubernetesReleaseVersion is helper function that can fetch
|
||||
// available version information from release servers based on
|
||||
// label names, like "stable" or "latest".
|
||||
//
|
||||
// If argument is already semantic version string, it
|
||||
// will return same string.
|
||||
//
|
||||
// In case of labels, it tries to fetch from release
|
||||
// servers and then return actual semantic version.
|
||||
//
|
||||
// Available names on release servers:
|
||||
// stable (latest stable release)
|
||||
// stable-1 (latest stable release in 1.x)
|
||||
// stable-1.0 (and similarly 1.1, 1.2, 1.3, ...)
|
||||
// latest (latest release, including alpha/beta)
|
||||
// latest-1 (latest release in 1.x, including alpha/beta)
|
||||
// latest-1.0 (and similarly 1.1, 1.2, 1.3, ...)
|
||||
func KubernetesReleaseVersion(version string) (string, error) {
|
||||
if kubeReleaseRegex.MatchString(version) {
|
||||
return version, nil
|
||||
} else if kubeReleaseLabelRegex.MatchString(version) {
|
||||
url := fmt.Sprintf("%s/%s.txt", kubeReleaseBucketURL, version)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to get URL %q: %s", url, err.Error())
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("unable to fetch release information. URL: %q Status: %v", url, resp.Status)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to read content of URL %q: %s", url, err.Error())
|
||||
}
|
||||
// Re-validate received version and return.
|
||||
return KubernetesReleaseVersion(strings.Trim(string(body), " \t\n"))
|
||||
}
|
||||
return "", fmt.Errorf("version %q doesn't match patterns for neither semantic version nor labels (stable, latest, ...)", version)
|
||||
}
|
122
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/version_test.go
generated
vendored
Normal file
122
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/version_test.go
generated
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEmptyVersion(t *testing.T) {
|
||||
|
||||
ver, err := KubernetesReleaseVersion("")
|
||||
if err == nil {
|
||||
t.Error("KubernetesReleaseVersion returned successfully, but error expected")
|
||||
}
|
||||
if ver != "" {
|
||||
t.Error("KubernetesReleaseVersion returned value, expected only error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidVersion(t *testing.T) {
|
||||
validVersions := []string{
|
||||
"v1.3.0",
|
||||
"v1.4.0-alpha.0",
|
||||
"v1.4.5",
|
||||
"v1.4.0-beta.0",
|
||||
"v2.0.0",
|
||||
"v1.6.0-alpha.0.536+d60d9f3269288f",
|
||||
"v1.5.0-alpha.0.1078+1044b6822497da-pull",
|
||||
"v1.5.0-alpha.1.822+49b9e32fad9f32-pull-gke-gci",
|
||||
}
|
||||
for _, s := range validVersions {
|
||||
ver, err := KubernetesReleaseVersion(s)
|
||||
t.Log("Valid: ", s, ver, err)
|
||||
if err != nil {
|
||||
t.Errorf("KubernetesReleaseVersion unexpected error for version %q: %v", s, err)
|
||||
}
|
||||
if ver != s {
|
||||
t.Errorf("KubernetesReleaseVersion should return same valid version string. %q != %q", s, ver)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidVersion(t *testing.T) {
|
||||
invalidVersions := []string{
|
||||
"v1.3",
|
||||
"1.4.0",
|
||||
"1.4.5+git",
|
||||
"something1.2",
|
||||
}
|
||||
for _, s := range invalidVersions {
|
||||
ver, err := KubernetesReleaseVersion(s)
|
||||
t.Log("Invalid: ", s, ver, err)
|
||||
if err == nil {
|
||||
t.Errorf("KubernetesReleaseVersion error expected for version %q, but returned succesfully", s)
|
||||
}
|
||||
if ver != "" {
|
||||
t.Errorf("KubernetesReleaseVersion should return empty string in case of error. Returned %q for version %q", ver, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionFromNetwork(t *testing.T) {
|
||||
type T struct {
|
||||
Content string
|
||||
Status int
|
||||
Expected string
|
||||
ErrorExpected bool
|
||||
}
|
||||
cases := map[string]T{
|
||||
"stable": {"stable-1", http.StatusOK, "v1.4.6", false}, // recursive pointer to stable-1
|
||||
"stable-1": {"v1.4.6", http.StatusOK, "v1.4.6", false},
|
||||
"stable-1.3": {"v1.3.10", http.StatusOK, "v1.3.10", false},
|
||||
"latest": {"v1.6.0-alpha.0", http.StatusOK, "v1.6.0-alpha.0", false},
|
||||
"latest-1.3": {"v1.3.11-beta.0", http.StatusOK, "v1.3.11-beta.0", false},
|
||||
"empty": {"", http.StatusOK, "", true},
|
||||
"garbage": {"<?xml version='1.0'?><Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message></Error>", http.StatusOK, "", true},
|
||||
"unknown": {"The requested URL was not found on this server.", http.StatusNotFound, "", true},
|
||||
}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
key := strings.TrimSuffix(path.Base(r.URL.Path), ".txt")
|
||||
res, found := cases[key]
|
||||
if found {
|
||||
http.Error(w, res.Content, res.Status)
|
||||
} else {
|
||||
http.Error(w, "Unknown test case key!", http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
kubeReleaseBucketURL = server.URL
|
||||
|
||||
for k, v := range cases {
|
||||
ver, err := KubernetesReleaseVersion(k)
|
||||
t.Logf("Key: %q. Result: %q, Error: %v", k, ver, err)
|
||||
switch {
|
||||
case err != nil && !v.ErrorExpected:
|
||||
t.Errorf("KubernetesReleaseVersion: unexpected error for %q. Error: %v", k, err)
|
||||
case err == nil && v.ErrorExpected:
|
||||
t.Errorf("KubernetesReleaseVersion: error expected for key %q, but result is %q", k, ver)
|
||||
case ver != v.Expected:
|
||||
t.Errorf("KubernetesReleaseVersion: unexpected result for key %q. Expected: %q Actual: %q", k, v.Expected, ver)
|
||||
}
|
||||
}
|
||||
}
|
30
vendor/k8s.io/kubernetes/cmd/kubeadm/kubeadm.go
generated
vendored
Normal file
30
vendor/k8s.io/kubernetes/cmd/kubeadm/kubeadm.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
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 main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := app.Run(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
41
vendor/k8s.io/kubernetes/cmd/kubeadm/test/BUILD
generated
vendored
Normal file
41
vendor/k8s.io/kubernetes/cmd/kubeadm/test/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["util.go"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["token_test.go"],
|
||||
args = ["--kubeadm-path=../kubeadm"],
|
||||
data = ["//cmd/kubeadm"],
|
||||
library = ":go_default_library",
|
||||
tags = [
|
||||
"automanaged",
|
||||
"integration",
|
||||
"skip",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
67
vendor/k8s.io/kubernetes/cmd/kubeadm/test/token_test.go
generated
vendored
Normal file
67
vendor/k8s.io/kubernetes/cmd/kubeadm/test/token_test.go
generated
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
TokenExpectedRegex = "^\\S{6}\\:\\S{16}\n$"
|
||||
)
|
||||
|
||||
var kubeadmPath string
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&kubeadmPath, "kubeadm-path", filepath.Join(os.Getenv("KUBE_ROOT"), "cluster/kubeadm.sh"), "Location of kubeadm")
|
||||
}
|
||||
|
||||
func TestCmdTokenGenerate(t *testing.T) {
|
||||
stdout, _, err := RunCmd(kubeadmPath, "ex", "token", "generate")
|
||||
if err != nil {
|
||||
t.Fatalf("'kubeadm ex token generate' exited uncleanly: %v", err)
|
||||
}
|
||||
|
||||
matched, err := regexp.MatchString(TokenExpectedRegex, stdout)
|
||||
if err != nil {
|
||||
t.Fatalf("encountered an error while trying to match 'kubeadm ex token generate' stdout: %v", err)
|
||||
}
|
||||
if !matched {
|
||||
t.Errorf("'kubeadm ex token generate' stdout did not match expected regex; wanted: [%q], got: [%s]", TokenExpectedRegex, stdout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCmdTokenGenerateTypoError(t *testing.T) {
|
||||
/*
|
||||
Since we expect users to do things like this:
|
||||
|
||||
$ TOKEN=$(kubeadm ex token generate)
|
||||
|
||||
we want to make sure that if they have a typo in their command, we exit
|
||||
with a non-zero status code after showing the command's usage, so that
|
||||
the usage itself isn't captured as a token without the user noticing.
|
||||
*/
|
||||
|
||||
_, _, err := RunCmd(kubeadmPath, "ex", "token", "genorate") // subtle typo
|
||||
if err == nil {
|
||||
t.Error("'kubeadm ex token genorate' (a deliberate typo) exited without an error when we expected non-zero exit status")
|
||||
}
|
||||
}
|
41
vendor/k8s.io/kubernetes/cmd/kubeadm/test/util.go
generated
vendored
Normal file
41
vendor/k8s.io/kubernetes/cmd/kubeadm/test/util.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// Forked from test/e2e/framework because the e2e framework is quite bloated
|
||||
// for our purposes here, and modified to remove undesired logging.
|
||||
func RunCmd(command string, args ...string) (string, string, error) {
|
||||
var bout, berr bytes.Buffer
|
||||
cmd := exec.Command(command, args...)
|
||||
cmd.Stdout = io.MultiWriter(os.Stdout, &bout)
|
||||
cmd.Stderr = io.MultiWriter(os.Stderr, &berr)
|
||||
err := cmd.Run()
|
||||
stdout, stderr := bout.String(), berr.String()
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("error running %s %v; got error %v, stdout %q, stderr %q",
|
||||
command, args, err, stdout, stderr)
|
||||
}
|
||||
return stdout, stderr, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue