Add glide.yaml and vendor deps
This commit is contained in:
parent
db918f12ad
commit
5b3d5e81bd
18880 changed files with 5166045 additions and 1 deletions
24
vendor/k8s.io/kubernetes/cmd/kubeadm/app/BUILD
generated
vendored
Normal file
24
vendor/k8s.io/kubernetes/cmd/kubeadm/app/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_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",
|
||||
"//pkg/util/logs:go_default_library",
|
||||
"//vendor:github.com/spf13/pflag",
|
||||
],
|
||||
)
|
||||
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/BUILD
generated
vendored
Normal file
28
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/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_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"env.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//pkg/runtime:go_default_library",
|
||||
"//pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
||||
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"
|
||||
61
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/env.go
generated
vendored
Normal file
61
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/env.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 (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var GlobalEnvParams = SetEnvParams()
|
||||
|
||||
// TODO(phase2) use componentconfig
|
||||
// we need some params for testing etc, let's keep these hidden for now
|
||||
func SetEnvParams() *EnvParams {
|
||||
|
||||
envParams := map[string]string{
|
||||
// TODO(phase1+): Mode prefix and host_pki_path to another place as constants, and use them everywhere
|
||||
// Right now they're used here and there, but not consequently
|
||||
"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": "",
|
||||
"component_loglevel": "--v=2",
|
||||
}
|
||||
|
||||
for k := range envParams {
|
||||
if v := os.Getenv(fmt.Sprintf("KUBE_%s", strings.ToUpper(k))); v != "" {
|
||||
envParams[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return &EnvParams{
|
||||
KubernetesDir: envParams["kubernetes_dir"],
|
||||
HostPKIPath: envParams["host_pki_path"],
|
||||
HostEtcdPath: envParams["host_etcd_path"],
|
||||
HyperkubeImage: envParams["hyperkube_image"],
|
||||
RepositoryPrefix: envParams["repo_prefix"],
|
||||
DiscoveryImage: envParams["discovery_image"],
|
||||
EtcdImage: envParams["etcd_image"],
|
||||
ComponentLoglevel: envParams["component_loglevel"],
|
||||
}
|
||||
}
|
||||
25
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/BUILD
generated
vendored
Normal file
25
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/install/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_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",
|
||||
],
|
||||
)
|
||||
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 (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "kubeadm.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
|
||||
|
||||
var (
|
||||
SchemeBuilder = 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 }
|
||||
91
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/types.go
generated
vendored
Normal file
91
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
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/kubernetes/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type EnvParams struct {
|
||||
KubernetesDir string
|
||||
HostPKIPath string
|
||||
HostEtcdPath string
|
||||
HyperkubeImage string
|
||||
RepositoryPrefix string
|
||||
DiscoveryImage string
|
||||
EtcdImage string
|
||||
ComponentLoglevel string
|
||||
}
|
||||
|
||||
type MasterConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
Secrets Secrets
|
||||
API API
|
||||
Discovery Discovery
|
||||
Etcd Etcd
|
||||
Networking Networking
|
||||
KubernetesVersion string
|
||||
CloudProvider string
|
||||
}
|
||||
|
||||
type API struct {
|
||||
AdvertiseAddresses []string
|
||||
ExternalDNSNames []string
|
||||
BindPort int32
|
||||
}
|
||||
|
||||
type Discovery struct {
|
||||
BindPort int32
|
||||
}
|
||||
|
||||
type Networking struct {
|
||||
ServiceSubnet string
|
||||
PodSubnet string
|
||||
DNSDomain string
|
||||
}
|
||||
|
||||
type Etcd struct {
|
||||
Endpoints []string
|
||||
CAFile string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
}
|
||||
|
||||
type Secrets struct {
|
||||
GivenToken string // dot-separated `<TokenID>.<Token>` set by the user
|
||||
TokenID string // optional on master side, will be generated if not specified
|
||||
Token []byte // optional on master side, will be generated if not specified
|
||||
BearerToken string // set based on Token
|
||||
}
|
||||
|
||||
type NodeConfiguration struct {
|
||||
metav1.TypeMeta
|
||||
|
||||
MasterAddresses []string
|
||||
Secrets Secrets
|
||||
APIPort int32
|
||||
DiscoveryPort int32
|
||||
}
|
||||
|
||||
// ClusterInfo TODO add description
|
||||
type ClusterInfo struct {
|
||||
metav1.TypeMeta
|
||||
// TODO(phase1+) this may become simply `api.Config`
|
||||
CertificateAuthorities []string `json:"certificateAuthorities"`
|
||||
Endpoints []string `json:"endpoints"`
|
||||
}
|
||||
29
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD
generated
vendored
Normal file
29
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_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",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//pkg/runtime:go_default_library",
|
||||
"//pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
||||
70
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go
generated
vendored
Normal file
70
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.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 v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultServiceDNSDomain = "cluster.local"
|
||||
DefaultServicesSubnet = "10.96.0.0/12"
|
||||
DefaultKubernetesVersion = "stable"
|
||||
DefaultKubernetesFallbackVersion = "v1.4.6"
|
||||
DefaultAPIBindPort = 6443
|
||||
DefaultDiscoveryBindPort = 9898
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
RegisterDefaults(scheme)
|
||||
return scheme.AddDefaultingFuncs(
|
||||
SetDefaults_MasterConfiguration,
|
||||
SetDefaults_NodeConfiguration,
|
||||
)
|
||||
}
|
||||
|
||||
func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
|
||||
if obj.KubernetesVersion == "" {
|
||||
obj.KubernetesVersion = DefaultKubernetesVersion
|
||||
}
|
||||
|
||||
if obj.API.BindPort == 0 {
|
||||
obj.API.BindPort = DefaultAPIBindPort
|
||||
}
|
||||
|
||||
if obj.Discovery.BindPort == 0 {
|
||||
obj.Discovery.BindPort = DefaultDiscoveryBindPort
|
||||
}
|
||||
|
||||
if obj.Networking.ServiceSubnet == "" {
|
||||
obj.Networking.ServiceSubnet = DefaultServicesSubnet
|
||||
}
|
||||
|
||||
if obj.Networking.DNSDomain == "" {
|
||||
obj.Networking.DNSDomain = DefaultServiceDNSDomain
|
||||
}
|
||||
}
|
||||
|
||||
func SetDefaults_NodeConfiguration(obj *NodeConfiguration) {
|
||||
if obj.APIPort == 0 {
|
||||
obj.APIPort = DefaultAPIBindPort
|
||||
}
|
||||
|
||||
if obj.DiscoveryPort == 0 {
|
||||
obj.DiscoveryPort = DefaultDiscoveryBindPort
|
||||
}
|
||||
}
|
||||
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 (
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "kubeadm.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
|
||||
|
||||
var (
|
||||
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 }
|
||||
80
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go
generated
vendored
Normal file
80
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
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/kubernetes/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type MasterConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
Secrets Secrets `json:"secrets"`
|
||||
API API `json:"api"`
|
||||
Etcd Etcd `json:"etcd"`
|
||||
Discovery Discovery `json:"discovery"`
|
||||
Networking Networking `json:"networking"`
|
||||
KubernetesVersion string `json:"kubernetesVersion"`
|
||||
CloudProvider string `json:"cloudProvider"`
|
||||
}
|
||||
|
||||
type API struct {
|
||||
AdvertiseAddresses []string `json:"advertiseAddresses"`
|
||||
ExternalDNSNames []string `json:"externalDNSNames"`
|
||||
BindPort int32 `json:"bindPort"`
|
||||
}
|
||||
|
||||
type Discovery struct {
|
||||
BindPort int32 `json:"bindPort"`
|
||||
}
|
||||
|
||||
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 Secrets struct {
|
||||
GivenToken string `json:"givenToken"` // dot-separated `<TokenID>.<Token>` set by the user
|
||||
TokenID string `json:"tokenID"` // optional on master side, will be generated if not specified
|
||||
Token []byte `json:"token"` // optional on master side, will be generated if not specified
|
||||
BearerToken string `json:"bearerToken"` // set based on Token
|
||||
}
|
||||
|
||||
type NodeConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
MasterAddresses []string `json:"masterAddresses"`
|
||||
Secrets Secrets `json:"secrets"`
|
||||
APIPort int32 `json:"apiPort"`
|
||||
DiscoveryPort int32 `json:"discoveryPort"`
|
||||
}
|
||||
|
||||
// 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"`
|
||||
}
|
||||
42
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.defaults.go
generated
vendored
Normal file
42
vendor/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1/zz_generated.defaults.go
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by defaulter-gen. Do not edit it manually!
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/kubernetes/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)) })
|
||||
scheme.AddTypeDefaultingFunc(&NodeConfiguration{}, func(obj interface{}) { SetObjectDefaults_NodeConfiguration(obj.(*NodeConfiguration)) })
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_MasterConfiguration(in *MasterConfiguration) {
|
||||
SetDefaults_MasterConfiguration(in)
|
||||
}
|
||||
|
||||
func SetObjectDefaults_NodeConfiguration(in *NodeConfiguration) {
|
||||
SetDefaults_NodeConfiguration(in)
|
||||
}
|
||||
54
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/BUILD
generated
vendored
Normal file
54
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
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/master:go_default_library",
|
||||
"//cmd/kubeadm/app/node:go_default_library",
|
||||
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||
"//cmd/kubeadm/app/util:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/cloudprovider:go_default_library",
|
||||
"//pkg/cloudprovider/providers:go_default_library",
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
"//pkg/runtime:go_default_library",
|
||||
"//pkg/util/flag:go_default_library",
|
||||
"//pkg/util/initsystem:go_default_library",
|
||||
"//pkg/util/net:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
"//vendor:github.com/renstrom/dedent",
|
||||
"//vendor:github.com/spf13/cobra",
|
||||
],
|
||||
)
|
||||
|
||||
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"],
|
||||
)
|
||||
88
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/cmd.go
generated
vendored
Normal file
88
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/cmd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
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/kubernetes/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 workloads, like pods and replica sets 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
|
||||
// crapy 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(NewCmdToken(out))
|
||||
cmds.AddCommand(NewCmdVersion(out))
|
||||
|
||||
return cmds
|
||||
}
|
||||
296
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go
generated
vendored
Normal file
296
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/init.go
generated
vendored
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
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"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"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"
|
||||
kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
_ "k8s.io/kubernetes/pkg/cloudprovider/providers"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
netutil "k8s.io/kubernetes/pkg/util/net"
|
||||
)
|
||||
|
||||
const (
|
||||
joinArgsTemplateLiteral = `--token={{.Cfg.Secrets.GivenToken -}}
|
||||
{{if ne .Cfg.API.BindPort .DefaultAPIBindPort -}}
|
||||
{{" --api-port="}}{{.Cfg.API.BindPort -}}
|
||||
{{end -}}
|
||||
{{if ne .Cfg.Discovery.BindPort .DefaultDiscoveryBindPort -}}
|
||||
{{" --discovery-port="}}{{.Cfg.Discovery.BindPort -}}
|
||||
{{end -}}
|
||||
{{" "}}{{index .Cfg.API.AdvertiseAddresses 0 -}}
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
initDoneMsgf = dedent.Dedent(`
|
||||
Kubernetes master initialised successfully!
|
||||
|
||||
You can now join any number of machines by running the following on each node:
|
||||
|
||||
kubeadm join %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.Run(out))
|
||||
},
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&cfg.Secrets.GivenToken, "token", cfg.Secrets.GivenToken,
|
||||
"Shared secret used to secure cluster bootstrap; if none is provided, one will be generated for you",
|
||||
)
|
||||
cmd.PersistentFlags().StringSliceVar(
|
||||
&cfg.API.AdvertiseAddresses, "api-advertise-addresses", cfg.API.AdvertiseAddresses,
|
||||
"The IP addresses to advertise, in case autodetection fails",
|
||||
)
|
||||
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().StringVar(
|
||||
&cfg.CloudProvider, "cloud-provider", cfg.CloudProvider,
|
||||
`Enable cloud provider features (external load-balancers, storage, etc), e.g. "gce"`,
|
||||
)
|
||||
|
||||
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")
|
||||
|
||||
// TODO (phase1+) @errordeveloper make the flags below not show up in --help but rather on --advanced-help
|
||||
cmd.PersistentFlags().StringSliceVar(
|
||||
&cfg.Etcd.Endpoints, "external-etcd-endpoints", cfg.Etcd.Endpoints,
|
||||
"etcd endpoints to use, in case you have an external cluster",
|
||||
)
|
||||
cmd.PersistentFlags().MarkDeprecated("external-etcd-endpoints", "this flag will be removed when componentconfig exists")
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&cfg.Etcd.CAFile, "external-etcd-cafile", cfg.Etcd.CAFile,
|
||||
"etcd certificate authority certificate file. Note: The path must be in /etc/ssl/certs",
|
||||
)
|
||||
cmd.PersistentFlags().MarkDeprecated("external-etcd-cafile", "this flag will be removed when componentconfig exists")
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&cfg.Etcd.CertFile, "external-etcd-certfile", cfg.Etcd.CertFile,
|
||||
"etcd client certificate file. Note: The path must be in /etc/ssl/certs",
|
||||
)
|
||||
cmd.PersistentFlags().MarkDeprecated("external-etcd-certfile", "this flag will be removed when componentconfig exists")
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&cfg.Etcd.KeyFile, "external-etcd-keyfile", cfg.Etcd.KeyFile,
|
||||
"etcd client key file. Note: The path must be in /etc/ssl/certs",
|
||||
)
|
||||
cmd.PersistentFlags().MarkDeprecated("external-etcd-keyfile", "this flag will be removed when componentconfig exists")
|
||||
|
||||
cmd.PersistentFlags().BoolVar(
|
||||
&skipPreFlight, "skip-preflight-checks", skipPreFlight,
|
||||
"skip preflight checks normally run before modifying the system",
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().Int32Var(
|
||||
&cfg.API.BindPort, "api-port", cfg.API.BindPort,
|
||||
"Port for API to bind to",
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().Int32Var(
|
||||
&cfg.Discovery.BindPort, "discovery-port", cfg.Discovery.BindPort,
|
||||
"Port for JWS discovery service to bind to",
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type Init struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
}
|
||||
|
||||
func NewInit(cfgPath string, cfg *kubeadmapi.MasterConfiguration, skipPreFlight bool) (*Init, error) {
|
||||
if cfgPath != "" {
|
||||
b, err := ioutil.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
if err := runtime.DecodeInto(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 {
|
||||
// TODO(phase1+) perhaps we could actually grab eth0 and eth1
|
||||
ip, err := netutil.ChooseHostInterface()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.API.AdvertiseAddresses = []string{ip.String()}
|
||||
}
|
||||
|
||||
if !skipPreFlight {
|
||||
fmt.Println("Running pre-flight checks")
|
||||
err := preflight.RunInitMasterChecks(cfg)
|
||||
if err != nil {
|
||||
return nil, &preflight.PreFlightError{Msg: err.Error()}
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Skipping pre-flight checks")
|
||||
}
|
||||
|
||||
// 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("Using Kubernetes version:", ver)
|
||||
|
||||
// TODO(phase1+) create a custom flag
|
||||
if cfg.CloudProvider != "" {
|
||||
if cloudprovider.IsCloudProvider(cfg.CloudProvider) {
|
||||
fmt.Printf("cloud provider %q initialized for the control plane. Remember to set the same cloud provider flag on the kubelet.\n", cfg.CloudProvider)
|
||||
} else {
|
||||
return nil, fmt.Errorf("cloud provider %q is not supported, you can use any of %v, or leave it unset.\n", cfg.CloudProvider, cloudprovider.CloudProviders())
|
||||
}
|
||||
}
|
||||
return &Init{cfg: cfg}, nil
|
||||
}
|
||||
|
||||
// joinArgsData denotes a data object which is needed by function generateJoinArgs to generate kubeadm join arguments.
|
||||
type joinArgsData struct {
|
||||
Cfg *kubeadmapi.MasterConfiguration
|
||||
DefaultAPIBindPort int32
|
||||
DefaultDiscoveryBindPort int32
|
||||
}
|
||||
|
||||
// Run executes master node provisioning, including certificates, needed static pod manifests, etc.
|
||||
func (i *Init) Run(out io.Writer) error {
|
||||
if err := kubemaster.CreateTokenAuthFile(&i.cfg.Secrets); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := kubemaster.WriteStaticPodManifests(i.cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
caKey, caCert, err := kubemaster.CreatePKIAssets(i.cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(i.cfg.API, []string{"kubelet", "admin"}, caKey, caCert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// kubeadm is responsible for writing the following kubeconfig file, which
|
||||
// kubelet should be waiting for. Help user avoid foot-shooting by refusing to
|
||||
// write a file that has already been written (the kubelet will be up and
|
||||
// running in that case - they'd need to stop the kubelet, remove the file, and
|
||||
// start it again in that case).
|
||||
// TODO(phase1+) this is no longer the right place to guard agains foo-shooting,
|
||||
// we need to decide how to handle existing files (it may be handy to support
|
||||
// importing existing files, may be we could even make our command idempotant,
|
||||
// or at least allow for external PKI and stuff)
|
||||
for name, kubeconfig := range kubeconfigs {
|
||||
if err := kubeadmutil.WriteKubeconfigIfNotExists(name, kubeconfig); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
client, err := kubemaster.CreateClientAndWaitForAPI(kubeconfigs["admin"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
schedulePodsOnMaster := false
|
||||
if err := kubemaster.UpdateMasterRoleLabelsAndTaints(client, schedulePodsOnMaster); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := kubemaster.CreateDiscoveryDeploymentAndSecret(i.cfg, client, caCert); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := kubemaster.CreateEssentialAddons(i.cfg, client); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data := joinArgsData{i.cfg, kubeadmapiext.DefaultAPIBindPort, kubeadmapiext.DefaultDiscoveryBindPort}
|
||||
if joinArgs, err := generateJoinArgs(data); err != nil {
|
||||
return err
|
||||
} else {
|
||||
fmt.Fprintf(out, initDoneMsgf, joinArgs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateJoinArgs generates kubeadm join arguments
|
||||
func generateJoinArgs(data joinArgsData) (string, error) {
|
||||
joinArgsTemplate := template.Must(template.New("joinArgsTemplate").Parse(joinArgsTemplateLiteral))
|
||||
var b bytes.Buffer
|
||||
if err := joinArgsTemplate.Execute(&b, data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return b.String(), nil
|
||||
}
|
||||
160
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join.go
generated
vendored
Normal file
160
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/join.go
generated
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"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"
|
||||
kubenode "k8s.io/kubernetes/cmd/kubeadm/app/node"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
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.Run(out))
|
||||
},
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVar(
|
||||
&cfg.Secrets.GivenToken, "token", cfg.Secrets.GivenToken,
|
||||
"(required) Shared secret used to secure bootstrap. Must match the output of 'kubeadm init'",
|
||||
)
|
||||
|
||||
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().Int32Var(
|
||||
&cfg.APIPort, "api-port", cfg.APIPort,
|
||||
"(optional) API server port on the master",
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().Int32Var(
|
||||
&cfg.DiscoveryPort, "discovery-port", cfg.DiscoveryPort,
|
||||
"(optional) Discovery port on the master",
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type Join struct {
|
||||
cfg *kubeadmapi.NodeConfiguration
|
||||
}
|
||||
|
||||
func NewJoin(cfgPath string, args []string, cfg *kubeadmapi.NodeConfiguration, skipPreFlight bool) (*Join, error) {
|
||||
if cfgPath != "" {
|
||||
b, err := ioutil.ReadFile(cfgPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
if err := runtime.DecodeInto(api.Codecs.UniversalDecoder(), b, cfg); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode config from %q [%v]", cfgPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) == 0 && len(cfg.MasterAddresses) == 0 {
|
||||
return nil, fmt.Errorf("must specify master address (see --help)")
|
||||
}
|
||||
cfg.MasterAddresses = append(cfg.MasterAddresses, args...)
|
||||
if len(cfg.MasterAddresses) > 1 {
|
||||
return nil, fmt.Errorf("Must not specify more than one master address (see --help)")
|
||||
}
|
||||
|
||||
if !skipPreFlight {
|
||||
fmt.Println("Running pre-flight checks")
|
||||
err := preflight.RunJoinNodeChecks(cfg)
|
||||
if err != nil {
|
||||
return nil, &preflight.PreFlightError{Msg: err.Error()}
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Skipping pre-flight checks")
|
||||
}
|
||||
|
||||
ok, err := kubeadmutil.UseGivenTokenIfValid(&cfg.Secrets)
|
||||
if !ok {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v (see --help)\n", err)
|
||||
}
|
||||
return nil, fmt.Errorf("Must specify --token (see --help)\n")
|
||||
}
|
||||
|
||||
return &Join{cfg: cfg}, nil
|
||||
}
|
||||
|
||||
// Run executes worked node provisioning and tries to join an existing cluster.
|
||||
func (j *Join) Run(out io.Writer) error {
|
||||
clusterInfo, err := kubenode.RetrieveTrustedClusterInfo(j.cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
connectionDetails, err := kubenode.EstablishMasterConnection(j.cfg, clusterInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kubeconfig, err := kubenode.PerformTLSBootstrap(connectionDetails)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = kubeadmutil.WriteKubeconfigIfNotExists("kubelet", kubeconfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, joinDoneMsgf)
|
||||
return nil
|
||||
}
|
||||
165
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset.go
generated
vendored
Normal file
165
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/reset.go
generated
vendored
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/util/initsystem"
|
||||
)
|
||||
|
||||
// NewCmdReset returns "kubeadm reset" command.
|
||||
func NewCmdReset(out io.Writer) *cobra.Command {
|
||||
var skipPreFlight 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)
|
||||
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",
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type Reset struct{}
|
||||
|
||||
func NewReset(skipPreFlight bool) (*Reset, error) {
|
||||
if !skipPreFlight {
|
||||
fmt.Println("Running pre-flight checks")
|
||||
err := preflight.RunResetCheck()
|
||||
if err != nil {
|
||||
return nil, &preflight.PreFlightError{Msg: err.Error()}
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Skipping pre-flight checks")
|
||||
}
|
||||
|
||||
return &Reset{}, nil
|
||||
}
|
||||
|
||||
// cleanDir removes everything in a directory, but not the directory itself:
|
||||
func cleanDir(path string) {
|
||||
// If the directory doesn't even exist there's nothing to do, and we do
|
||||
// not consider this an error:
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
|
||||
d, err := os.Open(path)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to remove directory: [%v]\n", err)
|
||||
}
|
||||
defer d.Close()
|
||||
names, err := d.Readdirnames(-1)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to remove directory: [%v]\n", err)
|
||||
}
|
||||
for _, name := range names {
|
||||
err = os.RemoveAll(filepath.Join(path, name))
|
||||
if err != nil {
|
||||
fmt.Printf("failed to remove directory: [%v]\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resetConfigDir is used to cleanup the files kubeadm writes in /etc/kubernetes/.
|
||||
func resetConfigDir(configDirPath string) {
|
||||
dirsToClean := []string{
|
||||
filepath.Join(configDirPath, "manifests"),
|
||||
filepath.Join(configDirPath, "pki"),
|
||||
}
|
||||
fmt.Printf("Deleting contents of config directories: %v\n", dirsToClean)
|
||||
for _, dir := range dirsToClean {
|
||||
cleanDir(dir)
|
||||
}
|
||||
|
||||
filesToClean := []string{
|
||||
filepath.Join(configDirPath, "admin.conf"),
|
||||
filepath.Join(configDirPath, "kubelet.conf"),
|
||||
}
|
||||
fmt.Printf("Deleting files: %v\n", filesToClean)
|
||||
for _, path := range filesToClean {
|
||||
err := os.RemoveAll(path)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to remove file: [%v]\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run reverts any changes made to this host by "kubeadm init" or "kubeadm join".
|
||||
func (r *Reset) Run(out io.Writer) error {
|
||||
serviceToStop := "kubelet"
|
||||
initSystem, err := initsystem.GetInitSystem()
|
||||
if err != nil {
|
||||
fmt.Printf("%v", err)
|
||||
} else {
|
||||
fmt.Printf("Stopping the %s service...\n", serviceToStop)
|
||||
if err := initSystem.ServiceStop(serviceToStop); err != nil {
|
||||
fmt.Printf("failed to stop the %s service", serviceToStop)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Unmounting directories in /var/lib/kubelet...\n")
|
||||
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("failed to unmount directories in /var/lib/kubelet, %s", string(umountOutputBytes))
|
||||
}
|
||||
|
||||
dirsToClean := []string{"/var/lib/kubelet"}
|
||||
|
||||
// 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
|
||||
if _, err := os.Stat("/etc/kubernetes/manifests/etcd.json"); os.IsNotExist(err) {
|
||||
dirsToClean = append(dirsToClean, "/var/lib/etcd")
|
||||
}
|
||||
|
||||
resetConfigDir("/etc/kubernetes/")
|
||||
|
||||
fmt.Printf("Deleting contents of stateful directories: %v\n", dirsToClean)
|
||||
for _, dir := range dirsToClean {
|
||||
cleanDir(dir)
|
||||
}
|
||||
|
||||
dockerCheck := preflight.ServiceCheck{Service: "docker"}
|
||||
if warnings, errors := dockerCheck.Check(); len(warnings) == 0 && len(errors) == 0 {
|
||||
fmt.Println("Stopping all running docker containers...")
|
||||
if err := exec.Command("sh", "-c", "docker ps | grep 'k8s_' | awk '{print $1}' | xargs docker rm --force --volumes").Run(); err != nil {
|
||||
fmt.Println("failed to stop the running containers")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("docker doesn't seem to be running, skipping the removal of kubernetes containers")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
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 2014 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.json": {
|
||||
setupDirs: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
},
|
||||
setupFiles: []string{
|
||||
"manifests/etcd.json",
|
||||
"manifests/kube-apiserver.json",
|
||||
"pki/ca.pem",
|
||||
"admin.conf",
|
||||
"kubelet.conf",
|
||||
"cloud-config.json",
|
||||
},
|
||||
verifyExists: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
"cloud-config.json",
|
||||
},
|
||||
},
|
||||
"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.json",
|
||||
".mydir/.myfile",
|
||||
},
|
||||
verifyExists: []string{
|
||||
"manifests",
|
||||
"pki",
|
||||
".cloud-config.json",
|
||||
".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)
|
||||
|
||||
// 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
86
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token.go
generated
vendored
Normal file
86
vendor/k8s.io/kubernetes/cmd/kubeadm/app/cmd/token.go
generated
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"github.com/renstrom/dedent"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
)
|
||||
|
||||
func NewCmdToken(out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "token",
|
||||
Short: "Manage tokens used by init/join",
|
||||
|
||||
// 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])
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(NewCmdTokenGenerate(out))
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewCmdTokenGenerate(out io.Writer) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "Generate and print a token suitable for use with init/join",
|
||||
Long: dedent.Dedent(`
|
||||
This command will print out a randomly-generated token that you can use 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)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func RunGenerateToken(out io.Writer) error {
|
||||
s := &kubeadmapi.Secrets{}
|
||||
err := util.GenerateToken(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(out, s.GivenToken)
|
||||
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 2014 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
|
||||
}
|
||||
26
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/BUILD
generated
vendored
Normal file
26
vendor/k8s.io/kubernetes/cmd/kubeadm/app/images/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
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"],
|
||||
)
|
||||
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 = "kube-dns"
|
||||
KubeDNSmasqImage = "dnsmasq"
|
||||
KubeExechealthzImage = "exechealthz"
|
||||
Pause = "pause"
|
||||
|
||||
gcrPrefix = "gcr.io/google_containers"
|
||||
etcdVersion = "3.0.14-kubeadm"
|
||||
|
||||
kubeDNSVersion = "1.7"
|
||||
dnsmasqVersion = "1.3"
|
||||
exechealthzVersion = "1.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, "kubedns", runtime.GOARCH, kubeDNSVersion),
|
||||
KubeDNSmasqImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "kube-dnsmasq", runtime.GOARCH, dnsmasqVersion),
|
||||
KubeExechealthzImage: fmt.Sprintf("%s/%s-%s:%s", repoPrefix, "exechealthz", runtime.GOARCH, exechealthzVersion),
|
||||
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, "kubedns", runtime.GOARCH, kubeDNSVersion),
|
||||
},
|
||||
{
|
||||
KubeDNSmasqImage,
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-dnsmasq", runtime.GOARCH, dnsmasqVersion),
|
||||
},
|
||||
{
|
||||
KubeExechealthzImage,
|
||||
fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "exechealthz", runtime.GOARCH, exechealthzVersion),
|
||||
},
|
||||
{
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
40
vendor/k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go
generated
vendored
Normal file
40
vendor/k8s.io/kubernetes/cmd/kubeadm/app/kubeadm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
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"
|
||||
"k8s.io/kubernetes/pkg/util/logs"
|
||||
)
|
||||
|
||||
func Run() error {
|
||||
logs.InitLogs()
|
||||
defer logs.FlushLogs()
|
||||
|
||||
// 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()
|
||||
}
|
||||
67
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/BUILD
generated
vendored
Normal file
67
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"addons.go",
|
||||
"apiclient.go",
|
||||
"discovery.go",
|
||||
"kubeconfig.go",
|
||||
"manifests.go",
|
||||
"pki.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/errors:go_default_library",
|
||||
"//pkg/api/resource:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5: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",
|
||||
"//pkg/util/wait:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"addons_test.go",
|
||||
"apiclient_test.go",
|
||||
"discovery_test.go",
|
||||
"kubeconfig_test.go",
|
||||
"manifests_test.go",
|
||||
"pki_test.go",
|
||||
"tokens_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/cert:go_default_library",
|
||||
"//pkg/util/intstr:go_default_library",
|
||||
],
|
||||
)
|
||||
264
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/addons.go
generated
vendored
Normal file
264
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/addons.go
generated
vendored
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package 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"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
ipallocator "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 {
|
||||
|
||||
dnsPodResources := v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("100m"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("170Mi"),
|
||||
}
|
||||
|
||||
healthzPodResources := v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("10m"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("50Mi"),
|
||||
}
|
||||
|
||||
kubeDNSPort := int32(10053)
|
||||
dnsmasqPort := int32(53)
|
||||
|
||||
nslookup := fmt.Sprintf("nslookup kubernetes.default.svc.%s 127.0.0.1", cfg.Networking.DNSDomain)
|
||||
|
||||
nslookup = fmt.Sprintf("-cmd=%s:%d >/dev/null && %s:%d >/dev/null",
|
||||
nslookup, dnsmasqPort,
|
||||
nslookup, kubeDNSPort,
|
||||
)
|
||||
|
||||
return v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
// DNS server
|
||||
{
|
||||
Name: "kube-dns",
|
||||
Image: images.GetAddonImage(images.KubeDNSImage),
|
||||
Resources: v1.ResourceRequirements{
|
||||
Limits: dnsPodResources,
|
||||
Requests: dnsPodResources,
|
||||
},
|
||||
Args: []string{
|
||||
fmt.Sprintf("--domain=%s", cfg.Networking.DNSDomain),
|
||||
fmt.Sprintf("--dns-port=%d", kubeDNSPort),
|
||||
// TODO __PILLAR__FEDERATIONS__DOMAIN__MAP__
|
||||
},
|
||||
LivenessProbe: &v1.Probe{
|
||||
Handler: v1.Handler{
|
||||
HTTPGet: &v1.HTTPGetAction{
|
||||
Path: "/healthz",
|
||||
Port: intstr.FromInt(8080),
|
||||
Scheme: v1.URISchemeHTTP,
|
||||
},
|
||||
},
|
||||
InitialDelaySeconds: 60,
|
||||
TimeoutSeconds: 5,
|
||||
SuccessThreshold: 1,
|
||||
FailureThreshold: 1,
|
||||
},
|
||||
// # 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: 30,
|
||||
TimeoutSeconds: 5,
|
||||
},
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: kubeDNSPort,
|
||||
Name: "dns-local",
|
||||
Protocol: v1.ProtocolUDP,
|
||||
},
|
||||
{
|
||||
ContainerPort: kubeDNSPort,
|
||||
Name: "dns-tcp-local",
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
// dnsmasq
|
||||
{
|
||||
Name: "dnsmasq",
|
||||
Image: images.GetAddonImage(images.KubeDNSmasqImage),
|
||||
Resources: v1.ResourceRequirements{
|
||||
Limits: dnsPodResources,
|
||||
Requests: dnsPodResources,
|
||||
},
|
||||
Args: []string{
|
||||
"--cache-size=1000",
|
||||
"--no-resolv",
|
||||
fmt.Sprintf("--server=127.0.0.1#%d", kubeDNSPort),
|
||||
},
|
||||
Ports: []v1.ContainerPort{
|
||||
{
|
||||
ContainerPort: dnsmasqPort,
|
||||
Name: "dns",
|
||||
Protocol: v1.ProtocolUDP,
|
||||
},
|
||||
{
|
||||
ContainerPort: dnsmasqPort,
|
||||
Name: "dns-tcp",
|
||||
Protocol: v1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
},
|
||||
// healthz
|
||||
{
|
||||
Name: "healthz",
|
||||
Image: images.GetAddonImage(images.KubeExechealthzImage),
|
||||
Resources: v1.ResourceRequirements{
|
||||
Limits: healthzPodResources,
|
||||
Requests: healthzPodResources,
|
||||
},
|
||||
Args: []string{
|
||||
nslookup,
|
||||
"-port=8080",
|
||||
"-quiet",
|
||||
},
|
||||
Ports: []v1.ContainerPort{{
|
||||
ContainerPort: 8080,
|
||||
Protocol: v1.ProtocolTCP,
|
||||
}},
|
||||
},
|
||||
},
|
||||
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)
|
||||
}
|
||||
|
||||
svc := &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(),
|
||||
}
|
||||
|
||||
return svc, 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("<master/addons> failed creating essential kube-proxy addon [%v]", err)
|
||||
}
|
||||
|
||||
fmt.Println("<master/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("<master/addons> failed creating essential kube-dns addon [%v]", err)
|
||||
}
|
||||
|
||||
kubeDNSServiceSpec, err := createKubeDNSServiceSpec(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("<master/addons> failed creating essential kube-dns addon - %v", err)
|
||||
}
|
||||
|
||||
kubeDNSService := NewService("kube-dns", *kubeDNSServiceSpec)
|
||||
if _, err := client.Services(api.NamespaceSystem).Create(kubeDNSService); err != nil {
|
||||
return fmt.Errorf("<master/addons> failed creating essential kube-dns addon [%v]", err)
|
||||
}
|
||||
|
||||
fmt.Println("<master/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),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
279
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/apiclient.go
generated
vendored
Normal file
279
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/apiclient.go
generated
vendored
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
apierrs "k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
)
|
||||
|
||||
const apiCallRetryInterval = 500 * time.Millisecond
|
||||
|
||||
func CreateClientAndWaitForAPI(adminConfig *clientcmdapi.Config) (*clientset.Clientset, error) {
|
||||
adminClientConfig, err := clientcmd.NewDefaultClientConfig(
|
||||
*adminConfig,
|
||||
&clientcmd.ConfigOverrides{},
|
||||
).ClientConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("<master/apiclient> failed to create API client configuration [%v]", err)
|
||||
}
|
||||
|
||||
fmt.Println("<master/apiclient> created API client configuration")
|
||||
|
||||
client, err := clientset.NewForConfig(adminClientConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("<master/apiclient> failed to create API client [%v]", err)
|
||||
}
|
||||
|
||||
fmt.Println("<master/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("<master/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("<master/apiclient> control plane component %q is still unhealthy: %#v\n", item.ObjectMeta.Name, item.Conditions)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("<master/apiclient> all control plane components are healthy after %f seconds\n", time.Since(start).Seconds())
|
||||
return true, nil
|
||||
})
|
||||
|
||||
fmt.Println("<master/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("<master/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("<master/apiclient> first node has registered, but is not ready yet")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
fmt.Printf("<master/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("<master/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("<master/apiclient> 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("<master/apiclient> attempting 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("<master/apiclient> failed to create test deployment [%v] (will retry)", err)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
||||
d, err := client.Extensions().Deployments(api.NamespaceSystem).Get("dummy")
|
||||
if err != nil {
|
||||
fmt.Printf("<master/apiclient> failed to get test deployment [%v] (will retry)", err)
|
||||
return false, nil
|
||||
}
|
||||
if d.Status.AvailableReplicas < 1 {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
fmt.Println("<master/apiclient> test deployment succeeded")
|
||||
|
||||
if err := client.Extensions().Deployments(api.NamespaceSystem).Delete("dummy", &v1.DeleteOptions{}); err != nil {
|
||||
fmt.Printf("<master/apiclient> failed to delete test deployment [%v] (will ignore)", 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"],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
148
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/discovery.go
generated
vendored
Normal file
148
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/discovery.go
generated
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
)
|
||||
|
||||
type kubeDiscovery struct {
|
||||
Deployment *extensions.Deployment
|
||||
Secret *v1.Secret
|
||||
}
|
||||
|
||||
const (
|
||||
kubeDiscoveryName = "kube-discovery"
|
||||
kubeDiscoverySecretName = "clusterinfo"
|
||||
)
|
||||
|
||||
func encodeKubeDiscoverySecretData(cfg *kubeadmapi.MasterConfiguration, caCert *x509.Certificate) map[string][]byte {
|
||||
var (
|
||||
data = map[string][]byte{}
|
||||
endpointList = []string{}
|
||||
tokenMap = map[string]string{}
|
||||
)
|
||||
|
||||
for _, addr := range cfg.API.AdvertiseAddresses {
|
||||
endpointList = append(endpointList, fmt.Sprintf("https://%s:%d", addr, cfg.API.BindPort))
|
||||
}
|
||||
|
||||
tokenMap[cfg.Secrets.TokenID] = cfg.Secrets.BearerToken
|
||||
|
||||
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
|
||||
// buisness 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: cfg.Discovery.BindPort},
|
||||
},
|
||||
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, 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("<master/discovery> failed to create %q deployment [%v]", kubeDiscoveryName, err)
|
||||
}
|
||||
if _, err := client.Secrets(api.NamespaceSystem).Create(kd.Secret); err != nil {
|
||||
return fmt.Errorf("<master/discovery> failed to create %q secret [%v]", kubeDiscoverySecretName, err)
|
||||
}
|
||||
|
||||
fmt.Println("<master/discovery> created essential addon: kube-discovery, waiting for it to become ready")
|
||||
|
||||
start := time.Now()
|
||||
wait.PollInfinite(apiCallRetryInterval, func() (bool, error) {
|
||||
d, err := client.Extensions().Deployments(api.NamespaceSystem).Get(kubeDiscoveryName)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
if d.Status.AvailableReplicas < 1 {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
fmt.Printf("<master/discovery> kube-discovery is ready after %f seconds\n", time.Since(start).Seconds())
|
||||
|
||||
return nil
|
||||
}
|
||||
104
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/discovery_test.go
generated
vendored
Normal file
104
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/discovery_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
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 TestEncodeKubeDiscoverySecretData(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{BindPort: 123, AdvertiseAddresses: []string{"10.0.0.1"}},
|
||||
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/1"},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
caCert := &x509.Certificate{}
|
||||
actual := encodeKubeDiscoverySecretData(rt.cfg, caCert)
|
||||
if (actual != nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed encodeKubeDiscoverySecretData, return map[string][]byte was nil",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewKubeDiscoveryPodSpec(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
p int32
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Discovery: kubeadmapi.Discovery{BindPort: 123},
|
||||
},
|
||||
p: 123,
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Discovery: kubeadmapi.Discovery{BindPort: 456},
|
||||
},
|
||||
p: 456,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := newKubeDiscoveryPodSpec(rt.cfg)
|
||||
if actual.Containers[0].Ports[0].HostPort != rt.p {
|
||||
t.Errorf(
|
||||
"failed newKubeDiscoveryPodSpec:\n\texpected: %d\n\t actual: %d",
|
||||
rt.p,
|
||||
actual.Containers[0].Ports[0].HostPort,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewKubeDiscovery(t *testing.T) {
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
caCert *x509.Certificate
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{BindPort: 123, AdvertiseAddresses: []string{"10.0.0.1"}},
|
||||
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/1"},
|
||||
},
|
||||
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",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
60
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/kubeconfig.go
generated
vendored
Normal file
60
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/kubeconfig.go
generated
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
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/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
|
||||
// TODO: "k8s.io/client-go/client/tools/clientcmd/api"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
)
|
||||
|
||||
func CreateCertsAndConfigForClients(cfg kubeadmapi.API, clientNames []string, caKey *rsa.PrivateKey, caCert *x509.Certificate) (map[string]*clientcmdapi.Config, error) {
|
||||
|
||||
basicClientConfig := kubeadmutil.CreateBasicClientConfig(
|
||||
"kubernetes",
|
||||
// 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
|
||||
fmt.Sprintf("https://%s:%d", cfg.AdvertiseAddresses[0], cfg.BindPort),
|
||||
certutil.EncodeCertPEM(caCert),
|
||||
)
|
||||
|
||||
configs := map[string]*clientcmdapi.Config{}
|
||||
|
||||
for _, client := range clientNames {
|
||||
key, cert, err := newClientKeyAndCert(caCert, caKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("<master/kubeconfig> failure while creating %s client certificate - %v", client, err)
|
||||
}
|
||||
config := kubeadmutil.MakeClientConfigWithCerts(
|
||||
basicClientConfig,
|
||||
"kubernetes",
|
||||
client,
|
||||
certutil.EncodePrivateKeyPEM(key),
|
||||
certutil.EncodeCertPEM(cert),
|
||||
)
|
||||
configs[client] = config
|
||||
}
|
||||
|
||||
return configs, nil
|
||||
}
|
||||
70
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/kubeconfig_test.go
generated
vendored
Normal file
70
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/kubeconfig_test.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 master
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestCreateCertsAndConfigForClients(t *testing.T) {
|
||||
var tests = []struct {
|
||||
a kubeadmapi.API
|
||||
cn []string
|
||||
caKeySize int
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
a: kubeadmapi.API{AdvertiseAddresses: []string{"foo"}},
|
||||
cn: []string{"localhost"},
|
||||
caKeySize: 128,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
a: kubeadmapi.API{AdvertiseAddresses: []string{"foo"}},
|
||||
cn: []string{},
|
||||
caKeySize: 128,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
a: kubeadmapi.API{AdvertiseAddresses: []string{"foo"}},
|
||||
cn: []string{"localhost"},
|
||||
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 := CreateCertsAndConfigForClients(rt.a, rt.cn, caKey, caCert)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed CreateCertsAndConfigForClients:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
316
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/manifests.go
generated
vendored
Normal file
316
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/manifests.go
generated
vendored
Normal file
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
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"
|
||||
metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
)
|
||||
|
||||
// Static pod definitions in golang form are included below so that `kubeadm init` can get going.
|
||||
|
||||
const (
|
||||
DefaultClusterName = "kubernetes"
|
||||
DefaultCloudConfigPath = "/etc/kubernetes/cloud-config.json"
|
||||
|
||||
etcd = "etcd"
|
||||
apiServer = "apiserver"
|
||||
controllerManager = "controller-manager"
|
||||
scheduler = "scheduler"
|
||||
proxy = "proxy"
|
||||
kubeAPIServer = "kube-apiserver"
|
||||
kubeControllerManager = "kube-controller-manager"
|
||||
kubeScheduler = "kube-scheduler"
|
||||
kubeProxy = "kube-proxy"
|
||||
pkiDir = "/etc/kubernetes/pki"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
// 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: []api.VolumeMount{certsVolumeMount(), k8sVolumeMount()},
|
||||
LivenessProbe: componentProbe(8080, "/healthz"),
|
||||
Resources: componentResources("250m"),
|
||||
}, certsVolume(cfg), k8sVolume(cfg)),
|
||||
kubeControllerManager: componentPod(api.Container{
|
||||
Name: kubeControllerManager,
|
||||
Image: images.GetCoreImage(images.KubeControllerManagerImage, cfg, kubeadmapi.GlobalEnvParams.HyperkubeImage),
|
||||
Command: getControllerManagerCommand(cfg),
|
||||
VolumeMounts: []api.VolumeMount{certsVolumeMount(), k8sVolumeMount()},
|
||||
LivenessProbe: componentProbe(10252, "/healthz"),
|
||||
Resources: componentResources("200m"),
|
||||
}, certsVolume(cfg), k8sVolume(cfg)),
|
||||
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"),
|
||||
}),
|
||||
}
|
||||
|
||||
// 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/etcd/data",
|
||||
},
|
||||
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("<master/manifests> 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("<master/manifests> failed to marshall manifest for %q to JSON [%v]", name, err)
|
||||
}
|
||||
if err := cmdutil.DumpReaderToFile(bytes.NewReader(serialized), filename); err != nil {
|
||||
return fmt.Errorf("<master/manifests> 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/etcd",
|
||||
}
|
||||
}
|
||||
|
||||
// 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 k8sVolume(cfg *kubeadmapi.MasterConfiguration) api.Volume {
|
||||
return api.Volume{
|
||||
Name: "pki",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{Path: kubeadmapi.GlobalEnvParams.KubernetesDir},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func k8sVolumeMount() api.VolumeMount {
|
||||
return api.VolumeMount{
|
||||
Name: "pki",
|
||||
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) (command []string) {
|
||||
if kubeadmapi.GlobalEnvParams.HyperkubeImage != "" {
|
||||
command = []string{"/hyperkube", component}
|
||||
} else {
|
||||
command = []string{"kube-" + component}
|
||||
}
|
||||
command = append(command, kubeadmapi.GlobalEnvParams.ComponentLoglevel)
|
||||
return
|
||||
}
|
||||
|
||||
func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) (command []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="+pkiDir+"/apiserver-key.pem",
|
||||
"--client-ca-file="+pkiDir+"/ca.pem",
|
||||
"--tls-cert-file="+pkiDir+"/apiserver.pem",
|
||||
"--tls-private-key-file="+pkiDir+"/apiserver-key.pem",
|
||||
"--token-auth-file="+pkiDir+"/tokens.csv",
|
||||
fmt.Sprintf("--secure-port=%d", cfg.API.BindPort),
|
||||
"--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]))
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration) (command []string) {
|
||||
command = append(getComponentBaseCommand(controllerManager),
|
||||
"--address=127.0.0.1",
|
||||
"--leader-elect",
|
||||
"--master=127.0.0.1:8080",
|
||||
"--cluster-name="+DefaultClusterName,
|
||||
"--root-ca-file="+pkiDir+"/ca.pem",
|
||||
"--service-account-private-key-file="+pkiDir+"/apiserver-key.pem",
|
||||
"--cluster-signing-cert-file="+pkiDir+"/ca.pem",
|
||||
"--cluster-signing-key-file="+pkiDir+"/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
|
||||
// TODO(phase1+) this won't work unless it's in one of the few directories we bind-mount
|
||||
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
|
||||
}
|
||||
|
||||
func getSchedulerCommand(cfg *kubeadmapi.MasterConfiguration) (command []string) {
|
||||
command = append(getComponentBaseCommand(scheduler),
|
||||
"--address=127.0.0.1",
|
||||
"--leader-elect",
|
||||
"--master=127.0.0.1:8080",
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getProxyCommand(cfg *kubeadmapi.MasterConfiguration) (command []string) {
|
||||
command = getComponentBaseCommand(proxy)
|
||||
|
||||
return
|
||||
}
|
||||
577
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/manifests_test.go
generated
vendored
Normal file
577
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/manifests_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
200
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/pki.go
generated
vendored
Normal file
200
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/pki.go
generated
vendored
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
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/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"net"
|
||||
"path"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
ipallocator "k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||
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(cfg *kubeadmapi.MasterConfiguration, 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)
|
||||
}
|
||||
|
||||
internalAPIServerFQDN := []string{
|
||||
"kubernetes",
|
||||
"kubernetes.default",
|
||||
"kubernetes.default.svc",
|
||||
fmt.Sprintf("kubernetes.default.svc.%s", cfg.Networking.DNSDomain),
|
||||
}
|
||||
|
||||
_, n, err := net.ParseCIDR(cfg.Networking.ServiceSubnet)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error parsing CIDR %q: %v", cfg.Networking.ServiceSubnet, err)
|
||||
}
|
||||
internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(n, 1)
|
||||
if err != nil {
|
||||
return nil, 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)
|
||||
altNames.DNSNames = append(altNames.DNSNames, internalAPIServerFQDN...)
|
||||
|
||||
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-admin",
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
||||
func newServiceAccountKey() (*rsa.PrivateKey, error) {
|
||||
key, err := certutil.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// 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) (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||
var (
|
||||
err error
|
||||
altNames certutil.AltNames
|
||||
)
|
||||
|
||||
for _, a := range cfg.API.AdvertiseAddresses {
|
||||
if ip := net.ParseIP(a); ip != nil {
|
||||
altNames.IPs = append(altNames.IPs, ip)
|
||||
} else {
|
||||
return nil, nil, fmt.Errorf("could not parse ip %q", a)
|
||||
}
|
||||
}
|
||||
altNames.DNSNames = append(altNames.DNSNames, cfg.API.ExternalDNSNames...)
|
||||
|
||||
pkiPath := path.Join(kubeadmapi.GlobalEnvParams.HostPKIPath)
|
||||
|
||||
caKey, caCert, err := newCertificateAuthority()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("<master/pki> failure while creating CA keys and certificate - %v", err)
|
||||
}
|
||||
|
||||
if err := writeKeysAndCert(pkiPath, "ca", caKey, caCert); err != nil {
|
||||
return nil, nil, fmt.Errorf("<master/pki> failure while saving CA keys and certificate - %v", err)
|
||||
}
|
||||
fmt.Printf("<master/pki> generated Certificate Authority key and certificate:\n%s\n", certutil.FormatCert(caCert))
|
||||
pub, prv, cert := pathsKeysCerts(pkiPath, "ca")
|
||||
fmt.Printf("Public: %s\nPrivate: %s\nCert: %s\n", pub, prv, cert)
|
||||
|
||||
apiKey, apiCert, err := newServerKeyAndCert(cfg, caCert, caKey, altNames)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("<master/pki> failure while creating API server keys and certificate - %v", err)
|
||||
}
|
||||
|
||||
if err := writeKeysAndCert(pkiPath, "apiserver", apiKey, apiCert); err != nil {
|
||||
return nil, nil, fmt.Errorf("<master/pki> failure while saving API server keys and certificate - %v", err)
|
||||
}
|
||||
fmt.Printf("<master/pki> generated API Server key and certificate:\n%s\n", certutil.FormatCert(apiCert))
|
||||
pub, prv, cert = pathsKeysCerts(pkiPath, "apiserver")
|
||||
fmt.Printf("Public: %s\nPrivate: %s\nCert: %s\n", pub, prv, cert)
|
||||
|
||||
saKey, err := newServiceAccountKey()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("<master/pki> failure while creating service account signing keys [%v]", err)
|
||||
}
|
||||
if err := writeKeysAndCert(pkiPath, "sa", saKey, nil); err != nil {
|
||||
return nil, nil, fmt.Errorf("<master/pki> failure while saving service account signing keys - %v", err)
|
||||
}
|
||||
fmt.Printf("<master/pki> generated Service Account Signing keys:\n")
|
||||
pub, prv, _ = pathsKeysCerts(pkiPath, "sa")
|
||||
fmt.Printf("Public: %s\nPrivate: %s\n", pub, prv)
|
||||
|
||||
fmt.Printf("<master/pki> created keys and certificates in %q\n", pkiPath)
|
||||
return caKey, caCert, nil
|
||||
}
|
||||
258
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/pki_test.go
generated
vendored
Normal file
258
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/pki_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
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/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
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 {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
caKeySize int
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
// given CIDR too small
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/1"},
|
||||
},
|
||||
caKeySize: 2048,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
// bad CIDR
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "foo"},
|
||||
},
|
||||
caKeySize: 2048,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
// RSA key too small
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/24"},
|
||||
},
|
||||
caKeySize: 128,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/24"},
|
||||
},
|
||||
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(rt.cfg, 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],
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewServiceAccountKey(t *testing.T) {
|
||||
r, err := newServiceAccountKey()
|
||||
if r == nil {
|
||||
t.Errorf(
|
||||
"failed newServiceAccountKey, rsa key == nil",
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf(
|
||||
"failed newServiceAccountKey with an error: %v",
|
||||
err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePKIAssets(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.HostPKIPath = fmt.Sprintf("%s/etc/kubernetes/pki", tmpdir)
|
||||
defer func() { kubeadmapi.GlobalEnvParams = oldEnv }()
|
||||
|
||||
var tests = []struct {
|
||||
cfg *kubeadmapi.MasterConfiguration
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadm.API{AdvertiseAddresses: []string{"10.0.0.1"}},
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/1"},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadm.API{AdvertiseAddresses: []string{"10.0.0.1"}},
|
||||
Networking: kubeadm.Networking{ServiceSubnet: "10.0.0.1/24"},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
_, _, actual := CreatePKIAssets(rt.cfg)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed CreatePKIAssets with an error:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
64
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/tokens.go
generated
vendored
Normal file
64
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/tokens.go
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
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"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/util/uuid"
|
||||
)
|
||||
|
||||
func generateTokenIfNeeded(s *kubeadmapi.Secrets) error {
|
||||
ok, err := kubeadmutil.UseGivenTokenIfValid(s)
|
||||
// TODO(phase1+) @krousey: I know it won't happen with the way it is currently implemented, but this doesn't handle case where ok is true and err is non-nil.
|
||||
if !ok {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = kubeadmutil.GenerateToken(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("<master/tokens> generated token: %q\n", s.GivenToken)
|
||||
} else {
|
||||
fmt.Println("<master/tokens> accepted provided token")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateTokenAuthFile(s *kubeadmapi.Secrets) error {
|
||||
tokenAuthFilePath := path.Join(kubeadmapi.GlobalEnvParams.HostPKIPath, "tokens.csv")
|
||||
if err := generateTokenIfNeeded(s); err != nil {
|
||||
return fmt.Errorf("<master/tokens> failed to generate token(s) [%v]", err)
|
||||
}
|
||||
if err := os.MkdirAll(kubeadmapi.GlobalEnvParams.HostPKIPath, 0700); err != nil {
|
||||
return fmt.Errorf("<master/tokens> failed to create directory %q [%v]", kubeadmapi.GlobalEnvParams.HostPKIPath, err)
|
||||
}
|
||||
serialized := []byte(fmt.Sprintf("%s,kubeadm-node-csr,%s,system:kubelet-bootstrap\n", s.BearerToken, uuid.NewUUID()))
|
||||
// DumpReaderToFile create a file with mode 0600
|
||||
if err := cmdutil.DumpReaderToFile(bytes.NewReader(serialized), tokenAuthFilePath); err != nil {
|
||||
return fmt.Errorf("<master/tokens> failed to save token auth file (%q) [%v]", tokenAuthFilePath, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
83
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/tokens_test.go
generated
vendored
Normal file
83
vendor/k8s.io/kubernetes/cmd/kubeadm/app/master/tokens_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package master
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestGenerateTokenIfNeeded(t *testing.T) {
|
||||
var tests = []struct {
|
||||
s kubeadmapi.Secrets
|
||||
expected bool
|
||||
}{
|
||||
{kubeadmapi.Secrets{GivenToken: "noperiod"}, false}, // not 2-part '.' format
|
||||
{kubeadmapi.Secrets{GivenToken: "abcd.a"}, false}, // len(tokenID) != 6
|
||||
{kubeadmapi.Secrets{GivenToken: "abcdef.a"}, true},
|
||||
{kubeadmapi.Secrets{GivenToken: ""}, true},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := generateTokenIfNeeded(&rt.s)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed UseGivenTokenIfValid:\n\texpected: %t\n\t actual: %t\n\t token:%s",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
rt.s.GivenToken,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateTokenAuthFile(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.HostPKIPath = fmt.Sprintf("%s/etc/kubernetes/pki", tmpdir)
|
||||
defer func() { kubeadmapi.GlobalEnvParams = oldEnv }()
|
||||
|
||||
var tests = []struct {
|
||||
s kubeadmapi.Secrets
|
||||
expected bool
|
||||
}{
|
||||
{kubeadmapi.Secrets{GivenToken: "noperiod"}, false}, // not 2-part '.' format
|
||||
{kubeadmapi.Secrets{GivenToken: "abcd.a"}, false}, // len(tokenID) != 6
|
||||
{kubeadmapi.Secrets{GivenToken: "abcdef.a"}, true},
|
||||
{kubeadmapi.Secrets{GivenToken: ""}, true},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := CreateTokenAuthFile(&rt.s)
|
||||
if (actual == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed WriteKubeconfigIfNotExists with an error:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expected,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
55
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/BUILD
generated
vendored
Normal file
55
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
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/util:go_default_library",
|
||||
"//pkg/apis/certificates:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/typed/certificates/v1alpha1: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/types:go_default_library",
|
||||
"//pkg/util/cert:go_default_library",
|
||||
"//pkg/util/wait:go_default_library",
|
||||
"//vendor:github.com/square/go-jose",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"bootstrap_test.go",
|
||||
"csr_test.go",
|
||||
"discovery_test.go",
|
||||
],
|
||||
library = "go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/typed/certificates/v1alpha1:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/client/typed/discovery:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
],
|
||||
)
|
||||
148
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/bootstrap.go
generated
vendored
Normal file
148
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/bootstrap.go
generated
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
certclient "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/certificates/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
)
|
||||
|
||||
// ConnectionDetails represents a master API endpoint connection
|
||||
type ConnectionDetails struct {
|
||||
CertClient *certclient.CertificatesV1alpha1Client
|
||||
Endpoint string
|
||||
CACert []byte
|
||||
NodeName types.NodeName
|
||||
}
|
||||
|
||||
// retryTimeout between the subsequent attempts to connect
|
||||
// to an API endpoint
|
||||
const retryTimeout = 5
|
||||
|
||||
// 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.
|
||||
func EstablishMasterConnection(s *kubeadmapi.NodeConfiguration, clusterInfo *kubeadmapi.ClusterInfo) (*ConnectionDetails, error) {
|
||||
hostName, err := os.Hostname()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("<node/bootstrap> 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{})
|
||||
result := make(chan *ConnectionDetails)
|
||||
var wg sync.WaitGroup
|
||||
for _, endpoint := range endpoints {
|
||||
clientSet, err := createClients(caCert, endpoint, s.Secrets.BearerToken, nodeName)
|
||||
if err != nil {
|
||||
fmt.Printf("<node/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("<node/bootstrap> trying to connect to endpoint %s\n", apiEndpoint)
|
||||
err := checkAPIEndpoint(clientSet, apiEndpoint)
|
||||
if err != nil {
|
||||
fmt.Printf("<node/bootstrap> endpoint check failed [%v]\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("<node/bootstrap> successfully established connection with endpoint %s\n", apiEndpoint)
|
||||
// connection established, stop all wait threads
|
||||
close(stopChan)
|
||||
result <- &ConnectionDetails{
|
||||
CertClient: clientSet.CertificatesV1alpha1Client,
|
||||
Endpoint: apiEndpoint,
|
||||
CACert: caCert,
|
||||
NodeName: nodeName,
|
||||
}
|
||||
}, retryTimeout*time.Second, stopChan)
|
||||
}(endpoint)
|
||||
}
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
// all wait.Until() calls have finished now
|
||||
close(result)
|
||||
}()
|
||||
|
||||
establishedConnection, ok := <-result
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("<node/bootstrap> failed to create bootstrap clients " +
|
||||
"for any of the provided API endpoints")
|
||||
}
|
||||
return establishedConnection, nil
|
||||
}
|
||||
|
||||
// creates a set of clients for this endpoint
|
||||
func createClients(caCert []byte, endpoint, token string, nodeName types.NodeName) (*clientset.Clientset, error) {
|
||||
bareClientConfig := kubeadmutil.CreateBasicClientConfig("kubernetes", endpoint, caCert)
|
||||
bootstrapClientConfig, err := clientcmd.NewDefaultClientConfig(
|
||||
*kubeadmutil.MakeClientConfigWithToken(
|
||||
bareClientConfig, "kubernetes", fmt.Sprintf("kubelet-%s", nodeName), token,
|
||||
),
|
||||
&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 %s [%v]", endpoint, err)
|
||||
}
|
||||
return clientSet, 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 %s [%v]", endpoint, err)
|
||||
}
|
||||
fmt.Printf("<node/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"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
"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.NodeConfiguration{}
|
||||
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),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
57
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/csr.go
generated
vendored
Normal file
57
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/csr.go
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||
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 certificate signing request with the
|
||||
// provided connection details.
|
||||
func PerformTLSBootstrap(connection *ConnectionDetails) (*clientcmdapi.Config, error) {
|
||||
csrClient := connection.CertClient.CertificateSigningRequests()
|
||||
|
||||
fmt.Println("<node/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 nil, fmt.Errorf("<node/csr> failed to generating private key [%v]", err)
|
||||
}
|
||||
cert, err := csr.RequestNodeCertificate(csrClient, key, connection.NodeName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("<node/csr> failed to request signed certificate from the API server [%v]", err)
|
||||
}
|
||||
fmtCert, err := certutil.FormatBytesCert(cert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("<node/csr> failed to format certificate [%v]", err)
|
||||
}
|
||||
fmt.Printf("<node/csr> received signed certificate from the API server:\n%s\n", fmtCert)
|
||||
fmt.Println("<node/csr> generating kubelet configuration")
|
||||
|
||||
bareClientConfig := kubeadmutil.CreateBasicClientConfig("kubernetes", connection.Endpoint, connection.CACert)
|
||||
finalConfig := kubeadmutil.MakeClientConfigWithCerts(
|
||||
bareClientConfig, "kubernetes", fmt.Sprintf("kubelet-%s", connection.NodeName),
|
||||
key, cert,
|
||||
)
|
||||
|
||||
return finalConfig, nil
|
||||
}
|
||||
79
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/csr_test.go
generated
vendored
Normal file
79
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/csr_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
certclient "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/certificates/v1alpha1"
|
||||
restclient "k8s.io/kubernetes/pkg/client/restclient"
|
||||
)
|
||||
|
||||
func TestPerformTLSBootstrap(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
switch req.URL.Path {
|
||||
default:
|
||||
output, err := json.Marshal(nil)
|
||||
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 {
|
||||
h string
|
||||
expect bool
|
||||
}{
|
||||
{
|
||||
h: "",
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
h: "localhost",
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
h: srv.URL,
|
||||
expect: false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
cd := &ConnectionDetails{}
|
||||
r := &restclient.Config{Host: rt.h}
|
||||
tmpConfig, err := certclient.NewForConfig(r)
|
||||
if err != nil {
|
||||
t.Fatalf("encountered an error while trying to get New Cert Client: %v", err)
|
||||
}
|
||||
cd.CertClient = tmpConfig
|
||||
_, actual := PerformTLSBootstrap(cd)
|
||||
if (actual == nil) != rt.expect {
|
||||
t.Errorf(
|
||||
"failed createClients:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expect,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
85
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/discovery.go
generated
vendored
Normal file
85
vendor/k8s.io/kubernetes/cmd/kubeadm/app/node/discovery.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 node
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
jose "github.com/square/go-jose"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
)
|
||||
|
||||
// the amount of time to wait between each request to the discovery API
|
||||
const discoveryRetryTimeout = 5 * time.Second
|
||||
|
||||
func RetrieveTrustedClusterInfo(s *kubeadmapi.NodeConfiguration) (*kubeadmapi.ClusterInfo, error) {
|
||||
host, port := s.MasterAddresses[0], s.DiscoveryPort
|
||||
requestURL := fmt.Sprintf("http://%s:%d/cluster-info/v1/?token-id=%s", host, port, s.Secrets.TokenID)
|
||||
req, err := http.NewRequest("GET", requestURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("<node/discovery> failed to consturct an HTTP request [%v]", err)
|
||||
}
|
||||
|
||||
fmt.Printf("<node/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("<node/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("<node/discovery> failed to parse response as JWS object [%v]", err)
|
||||
}
|
||||
|
||||
fmt.Println("<node/discovery> cluster info object received, verifying signature using given token")
|
||||
|
||||
output, err := object.Verify(s.Secrets.Token)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("<node/discovery> 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("<node/discovery> failed to decode received cluster info object [%v]", err)
|
||||
}
|
||||
|
||||
if len(clusterInfo.CertificateAuthorities) == 0 || len(clusterInfo.Endpoints) == 0 {
|
||||
return nil, fmt.Errorf("<node/discovery> 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("<node/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 int32
|
||||
payload string
|
||||
expect bool
|
||||
}{
|
||||
{
|
||||
h: host,
|
||||
p: int32(iPort),
|
||||
payload: "",
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
h: host,
|
||||
p: int32(iPort),
|
||||
payload: "foo",
|
||||
expect: false,
|
||||
},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
j.Payload = rt.payload
|
||||
nc := &kubeadmapi.NodeConfiguration{MasterAddresses: []string{host}, DiscoveryPort: int32(iPort)}
|
||||
_, actual := RetrieveTrustedClusterInfo(nc)
|
||||
if (actual == nil) != rt.expect {
|
||||
t.Errorf(
|
||||
"failed createClients:\n\texpected: %t\n\t actual: %t",
|
||||
rt.expect,
|
||||
(actual == nil),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
32
vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/BUILD
generated
vendored
Normal file
32
vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
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",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["checks_test.go"],
|
||||
library = "go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [],
|
||||
)
|
||||
359
vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks.go
generated
vendored
Normal file
359
vendor/k8s.io/kubernetes/cmd/kubeadm/app/preflight/checks.go
generated
vendored
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
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"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
type PreFlightError struct {
|
||||
Msg string
|
||||
}
|
||||
|
||||
func (e *PreFlightError) Error() string {
|
||||
return fmt.Sprintf("preflight check errors:\n%s", e.Msg)
|
||||
}
|
||||
|
||||
// PreFlightCheck validates the state of the system to ensure kubeadm will be
|
||||
// successful as often as possilble.
|
||||
type PreFlightCheck 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
|
||||
}
|
||||
|
||||
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 !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 {
|
||||
root bool
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// InPathChecks 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
|
||||
bufw := bufio.NewWriterSize(os.Stdout, 1*1024*1024)
|
||||
|
||||
// Run the system verification check, but write to out buffered writer instead of stdout
|
||||
err := system.Validate(system.DefaultSysSpec, &system.StreamReporter{WriteStream: bufw})
|
||||
if err != nil {
|
||||
// Only print the output from the system verification check if the check failed
|
||||
fmt.Println("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 := []PreFlightCheck{
|
||||
SystemVerificationCheck{},
|
||||
IsRootCheck{root: true},
|
||||
HostnameCheck{},
|
||||
ServiceCheck{Service: "kubelet"},
|
||||
ServiceCheck{Service: "docker"},
|
||||
FirewalldCheck{ports: []int{int(cfg.API.BindPort), int(cfg.Discovery.BindPort), 10250}},
|
||||
PortOpenCheck{port: int(cfg.API.BindPort)},
|
||||
PortOpenCheck{port: 8080},
|
||||
PortOpenCheck{port: int(cfg.Discovery.BindPort)},
|
||||
PortOpenCheck{port: 10250},
|
||||
PortOpenCheck{port: 10251},
|
||||
PortOpenCheck{port: 10252},
|
||||
HttpProxyCheck{Proto: "https", Host: cfg.API.AdvertiseAddresses[0], Port: int(cfg.API.BindPort)},
|
||||
DirAvailableCheck{Path: "/etc/kubernetes/manifests"},
|
||||
DirAvailableCheck{Path: "/etc/kubernetes/pki"},
|
||||
DirAvailableCheck{Path: "/var/lib/kubelet"},
|
||||
FileAvailableCheck{Path: "/etc/kubernetes/admin.conf"},
|
||||
FileAvailableCheck{Path: "/etc/kubernetes/kubelet.conf"},
|
||||
InPathCheck{executable: "ebtables", mandatory: true},
|
||||
InPathCheck{executable: "ethtool", mandatory: true},
|
||||
InPathCheck{executable: "ip", mandatory: true},
|
||||
InPathCheck{executable: "iptables", mandatory: true},
|
||||
InPathCheck{executable: "mount", mandatory: true},
|
||||
InPathCheck{executable: "nsenter", mandatory: true},
|
||||
InPathCheck{executable: "socat", mandatory: true},
|
||||
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 := []PreFlightCheck{
|
||||
SystemVerificationCheck{},
|
||||
IsRootCheck{root: true},
|
||||
HostnameCheck{},
|
||||
ServiceCheck{Service: "docker"},
|
||||
ServiceCheck{Service: "kubelet"},
|
||||
PortOpenCheck{port: 10250},
|
||||
HttpProxyCheck{Proto: "https", Host: cfg.MasterAddresses[0], Port: int(cfg.APIPort)},
|
||||
HttpProxyCheck{Proto: "http", Host: cfg.MasterAddresses[0], Port: int(cfg.DiscoveryPort)},
|
||||
DirAvailableCheck{Path: "/etc/kubernetes/manifests"},
|
||||
DirAvailableCheck{Path: "/var/lib/kubelet"},
|
||||
FileAvailableCheck{Path: "/etc/kubernetes/kubelet.conf"},
|
||||
InPathCheck{executable: "ebtables", mandatory: true},
|
||||
InPathCheck{executable: "ethtool", mandatory: true},
|
||||
InPathCheck{executable: "ip", mandatory: true},
|
||||
InPathCheck{executable: "iptables", mandatory: true},
|
||||
InPathCheck{executable: "mount", mandatory: true},
|
||||
InPathCheck{executable: "nsenter", mandatory: true},
|
||||
InPathCheck{executable: "socat", mandatory: true},
|
||||
InPathCheck{executable: "tc", mandatory: false},
|
||||
InPathCheck{executable: "touch", mandatory: false},
|
||||
}
|
||||
|
||||
return runChecks(checks, os.Stderr)
|
||||
}
|
||||
|
||||
func RunResetCheck() error {
|
||||
checks := []PreFlightCheck{
|
||||
IsRootCheck{root: true},
|
||||
}
|
||||
|
||||
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 []PreFlightCheck, ww io.Writer) error {
|
||||
found := []error{}
|
||||
for _, c := range checks {
|
||||
warnings, errs := c.Check()
|
||||
for _, w := range warnings {
|
||||
io.WriteString(ww, fmt.Sprintf("WARNING: %s\n", w))
|
||||
}
|
||||
for _, e := range errs {
|
||||
found = append(found, e)
|
||||
}
|
||||
}
|
||||
if len(found) > 0 {
|
||||
errs := ""
|
||||
for _, i := range found {
|
||||
errs += "\t" + i.Error() + "\n"
|
||||
}
|
||||
return errors.New(errs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
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 []PreFlightCheck
|
||||
expected bool
|
||||
output string
|
||||
}{
|
||||
{[]PreFlightCheck{}, true, ""},
|
||||
{[]PreFlightCheck{preflightCheckTest{"warning"}}, true, "WARNING: warning\n"}, // should just print warning
|
||||
{[]PreFlightCheck{preflightCheckTest{"error"}}, false, ""},
|
||||
{[]PreFlightCheck{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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
47
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/BUILD
generated
vendored
Normal file
47
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
"go_test",
|
||||
"cgo_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"error.go",
|
||||
"kubeconfig.go",
|
||||
"tokens.go",
|
||||
"version.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||
"//cmd/kubeadm/app/preflight:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:github.com/renstrom/dedent",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"error_test.go",
|
||||
"kubeconfig_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",
|
||||
"//pkg/client/unversioned/clientcmd/api:go_default_library",
|
||||
],
|
||||
)
|
||||
92
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error.go
generated
vendored
Normal file
92
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/error.go
generated
vendored
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
Copyright 2014 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"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/renstrom/dedent"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultErrorExitCode = 1
|
||||
PreFlight = 2
|
||||
)
|
||||
|
||||
var AlphaWarningOnExit = dedent.Dedent(`
|
||||
kubeadm: I am an alpha version, my authors welcome your feedback and bug reports
|
||||
kubeadm: please create an issue using https://github.com/kubernetes/kubernetes/issues/new
|
||||
kubeadm: and make sure to mention @kubernetes/sig-cluster-lifecycle. Thank you!
|
||||
`)
|
||||
|
||||
type debugError interface {
|
||||
DebugError() (msg string, args []interface{})
|
||||
}
|
||||
|
||||
var fatalErrHandler = fatal
|
||||
|
||||
// BehaviorOnFatal allows you to override the default behavior when a fatal
|
||||
// error occurs, which is to call os.Exit(code). You can pass 'panic' as a function
|
||||
// here if you prefer the panic() over os.Exit(1).
|
||||
func BehaviorOnFatal(f func(string, int)) {
|
||||
fatalErrHandler = f
|
||||
}
|
||||
|
||||
// fatal prints the message if set and then exits. If V(2) or greater, glog.Fatal
|
||||
// is invoked for extended information.
|
||||
func fatal(msg string, code int) {
|
||||
if len(msg) > 0 {
|
||||
// add newline if needed
|
||||
if !strings.HasSuffix(msg, "\n") {
|
||||
msg += "\n"
|
||||
}
|
||||
|
||||
if glog.V(2) {
|
||||
glog.FatalDepth(2, msg)
|
||||
}
|
||||
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, fatalErrHandler)
|
||||
}
|
||||
|
||||
// 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.PreFlightError:
|
||||
handleErr(err.Error(), PreFlight)
|
||||
default:
|
||||
fmt.Printf(AlphaWarningOnExit)
|
||||
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.PreFlightError{}, PreFlight},
|
||||
}
|
||||
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
97
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig.go
generated
vendored
Normal file
97
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig.go
generated
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
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"
|
||||
"path"
|
||||
|
||||
// TODO: "k8s.io/client-go/client/tools/clientcmd/api"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
)
|
||||
|
||||
func CreateBasicClientConfig(clusterName string, serverURL string, caCert []byte) *clientcmdapi.Config {
|
||||
cluster := clientcmdapi.NewCluster()
|
||||
cluster.Server = serverURL
|
||||
cluster.CertificateAuthorityData = caCert
|
||||
|
||||
config := clientcmdapi.NewConfig()
|
||||
config.Clusters[clusterName] = cluster
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
func MakeClientConfigWithCerts(config *clientcmdapi.Config, clusterName string, userName string, clientKey []byte, clientCert []byte) *clientcmdapi.Config {
|
||||
newConfig := config
|
||||
name := fmt.Sprintf("%s@%s", userName, clusterName)
|
||||
|
||||
authInfo := clientcmdapi.NewAuthInfo()
|
||||
authInfo.ClientKeyData = clientKey
|
||||
authInfo.ClientCertificateData = clientCert
|
||||
|
||||
context := clientcmdapi.NewContext()
|
||||
context.Cluster = clusterName
|
||||
context.AuthInfo = userName
|
||||
|
||||
newConfig.AuthInfos[userName] = authInfo
|
||||
newConfig.Contexts[name] = context
|
||||
newConfig.CurrentContext = name
|
||||
|
||||
return newConfig
|
||||
}
|
||||
|
||||
func MakeClientConfigWithToken(config *clientcmdapi.Config, clusterName string, userName string, token string) *clientcmdapi.Config {
|
||||
newConfig := config
|
||||
name := fmt.Sprintf("%s@%s", userName, clusterName)
|
||||
|
||||
authInfo := clientcmdapi.NewAuthInfo()
|
||||
authInfo.Token = token
|
||||
|
||||
context := clientcmdapi.NewContext()
|
||||
context.Cluster = clusterName
|
||||
context.AuthInfo = userName
|
||||
|
||||
newConfig.AuthInfos[userName] = authInfo
|
||||
newConfig.Contexts[name] = context
|
||||
newConfig.CurrentContext = name
|
||||
|
||||
return newConfig
|
||||
}
|
||||
|
||||
func WriteKubeconfigIfNotExists(name string, kubeconfig *clientcmdapi.Config) error {
|
||||
if err := os.MkdirAll(kubeadmapi.GlobalEnvParams.KubernetesDir, 0700); err != nil {
|
||||
return fmt.Errorf("<util/kubeconfig> failed to create directory %q [%v]", kubeadmapi.GlobalEnvParams.KubernetesDir, err)
|
||||
}
|
||||
|
||||
filename := path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, fmt.Sprintf("%s.conf", name))
|
||||
// Create and open the file, only if it does not already exist.
|
||||
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("<util/kubeconfig> failed to create %q, it already exists [%v]", filename, err)
|
||||
}
|
||||
f.Close()
|
||||
|
||||
if err := clientcmd.WriteToFile(*kubeconfig, filename); err != nil {
|
||||
return fmt.Errorf("<util/kubeconfig> failed to write to %q [%v]", filename, err)
|
||||
}
|
||||
|
||||
fmt.Printf("<util/kubeconfig> created %q\n", filename)
|
||||
return nil
|
||||
}
|
||||
199
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig_test.go
generated
vendored
Normal file
199
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
|
||||
)
|
||||
|
||||
const (
|
||||
configOut1 = `apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
server: ""
|
||||
name: ""
|
||||
contexts: []
|
||||
current-context: ""
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users: []
|
||||
`
|
||||
configOut2 = `apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
server: ""
|
||||
name: kubernetes
|
||||
contexts: []
|
||||
current-context: ""
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users: []
|
||||
`
|
||||
)
|
||||
|
||||
type configClient struct {
|
||||
c string
|
||||
s string
|
||||
ca []byte
|
||||
}
|
||||
|
||||
type configClientWithCerts struct {
|
||||
c *clientcmdapi.Config
|
||||
clusterName string
|
||||
userName string
|
||||
clientKey []byte
|
||||
clientCert []byte
|
||||
}
|
||||
|
||||
type configClientWithToken struct {
|
||||
c *clientcmdapi.Config
|
||||
clusterName string
|
||||
userName string
|
||||
token string
|
||||
}
|
||||
|
||||
func TestCreateBasicClientConfig(t *testing.T) {
|
||||
var createBasicTest = []struct {
|
||||
cc configClient
|
||||
expected string
|
||||
}{
|
||||
{configClient{}, ""},
|
||||
{configClient{c: "kubernetes"}, ""},
|
||||
}
|
||||
for _, rt := range createBasicTest {
|
||||
c := CreateBasicClientConfig(rt.cc.c, rt.cc.s, rt.cc.ca)
|
||||
if c.Kind != rt.expected {
|
||||
t.Errorf(
|
||||
"failed CreateBasicClientConfig:\n\texpected: %s\n\t actual: %s",
|
||||
c.Kind,
|
||||
rt.expected,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeClientConfigWithCerts(t *testing.T) {
|
||||
var createBasicTest = []struct {
|
||||
cc configClient
|
||||
ccWithCerts configClientWithCerts
|
||||
expected string
|
||||
}{
|
||||
{configClient{}, configClientWithCerts{}, ""},
|
||||
{configClient{c: "kubernetes"}, configClientWithCerts{}, ""},
|
||||
}
|
||||
for _, rt := range createBasicTest {
|
||||
c := CreateBasicClientConfig(rt.cc.c, rt.cc.s, rt.cc.ca)
|
||||
rt.ccWithCerts.c = c
|
||||
cwc := MakeClientConfigWithCerts(
|
||||
rt.ccWithCerts.c,
|
||||
rt.ccWithCerts.clusterName,
|
||||
rt.ccWithCerts.userName,
|
||||
rt.ccWithCerts.clientKey,
|
||||
rt.ccWithCerts.clientCert,
|
||||
)
|
||||
if cwc.Kind != rt.expected {
|
||||
t.Errorf(
|
||||
"failed MakeClientConfigWithCerts:\n\texpected: %s\n\t actual: %s",
|
||||
c.Kind,
|
||||
rt.expected,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeClientConfigWithToken(t *testing.T) {
|
||||
var createBasicTest = []struct {
|
||||
cc configClient
|
||||
ccWithToken configClientWithToken
|
||||
expected string
|
||||
}{
|
||||
{configClient{}, configClientWithToken{}, ""},
|
||||
{configClient{c: "kubernetes"}, configClientWithToken{}, ""},
|
||||
}
|
||||
for _, rt := range createBasicTest {
|
||||
c := CreateBasicClientConfig(rt.cc.c, rt.cc.s, rt.cc.ca)
|
||||
rt.ccWithToken.c = c
|
||||
cwc := MakeClientConfigWithToken(
|
||||
rt.ccWithToken.c,
|
||||
rt.ccWithToken.clusterName,
|
||||
rt.ccWithToken.userName,
|
||||
rt.ccWithToken.token,
|
||||
)
|
||||
if cwc.Kind != rt.expected {
|
||||
t.Errorf(
|
||||
"failed MakeClientConfigWithCerts:\n\texpected: %s\n\t actual: %s",
|
||||
c.Kind,
|
||||
rt.expected,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteKubeconfigIfNotExists(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)
|
||||
kubeadmapi.GlobalEnvParams.HostPKIPath = fmt.Sprintf("%s/etc/kubernetes/pki", tmpdir)
|
||||
kubeadmapi.GlobalEnvParams.HostEtcdPath = fmt.Sprintf("%s/var/lib/etcd", tmpdir)
|
||||
kubeadmapi.GlobalEnvParams.DiscoveryImage = fmt.Sprintf("%s/var/lib/etcd", tmpdir)
|
||||
defer func() { kubeadmapi.GlobalEnvParams = oldEnv }()
|
||||
|
||||
var writeConfig = []struct {
|
||||
name string
|
||||
cc configClient
|
||||
expected error
|
||||
file []byte
|
||||
}{
|
||||
{"test1", configClient{}, nil, []byte(configOut1)},
|
||||
{"test2", configClient{c: "kubernetes"}, nil, []byte(configOut2)},
|
||||
}
|
||||
for _, rt := range writeConfig {
|
||||
c := CreateBasicClientConfig(rt.cc.c, rt.cc.s, rt.cc.ca)
|
||||
err := WriteKubeconfigIfNotExists(rt.name, c)
|
||||
if err != rt.expected {
|
||||
t.Errorf(
|
||||
"failed WriteKubeconfigIfNotExists with an error:\n\texpected: %s\n\t actual: %s",
|
||||
err,
|
||||
rt.expected,
|
||||
)
|
||||
}
|
||||
configPath := filepath.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, fmt.Sprintf("%s.conf", rt.name))
|
||||
newFile, err := ioutil.ReadFile(configPath)
|
||||
if !bytes.Equal(newFile, rt.file) {
|
||||
t.Errorf(
|
||||
"failed WriteKubeconfigIfNotExists config write:\n\texpected: %s\n\t actual: %s",
|
||||
newFile,
|
||||
rt.file,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
84
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/tokens.go
generated
vendored
Normal file
84
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/tokens.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 util
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
const (
|
||||
TokenIDLen = 6
|
||||
TokenBytes = 8
|
||||
)
|
||||
|
||||
func RandBytes(length int) ([]byte, string, error) {
|
||||
b := make([]byte, length)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
// It's only the tokenID that doesn't care about raw byte slice,
|
||||
// so we just encoded it in place and ignore bytes slice where we
|
||||
// do not want it
|
||||
return b, hex.EncodeToString(b), nil
|
||||
}
|
||||
|
||||
func GenerateToken(s *kubeadmapi.Secrets) error {
|
||||
_, tokenID, err := RandBytes(TokenIDLen / 2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tokenBytes, token, err := RandBytes(TokenBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.TokenID = tokenID
|
||||
s.BearerToken = token
|
||||
s.Token = tokenBytes
|
||||
s.GivenToken = fmt.Sprintf("%s.%s", tokenID, token)
|
||||
return nil
|
||||
}
|
||||
|
||||
func UseGivenTokenIfValid(s *kubeadmapi.Secrets) (bool, error) {
|
||||
if s.GivenToken == "" {
|
||||
return false, nil // not given
|
||||
}
|
||||
fmt.Println("<util/tokens> validating provided token")
|
||||
givenToken := strings.Split(strings.ToLower(s.GivenToken), ".")
|
||||
// TODO(phase1+) could also print more specific messages in each case
|
||||
invalidErr := "<util/tokens> provided token does not match expected <6 characters>.<16 characters> format - %s"
|
||||
if len(givenToken) != 2 {
|
||||
return false, fmt.Errorf(invalidErr, "not in 2-part dot-separated format")
|
||||
}
|
||||
if len(givenToken[0]) != TokenIDLen {
|
||||
return false, fmt.Errorf(invalidErr, fmt.Sprintf(
|
||||
"length of first part is incorrect [%d (given) != %d (expected) ]",
|
||||
len(givenToken[0]), TokenIDLen))
|
||||
}
|
||||
tokenBytes := []byte(givenToken[1])
|
||||
s.TokenID = givenToken[0]
|
||||
s.BearerToken = givenToken[1]
|
||||
s.Token = tokenBytes
|
||||
return true, nil // given and valid
|
||||
}
|
||||
201
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/tokens_test.go
generated
vendored
Normal file
201
vendor/k8s.io/kubernetes/cmd/kubeadm/app/util/tokens_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 util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
func TestUsingEmptyTokenFails(t *testing.T) {
|
||||
// Simulates what happens when you omit --token on the CLI
|
||||
s := newSecretsWithToken("")
|
||||
|
||||
given, err := UseGivenTokenIfValid(s)
|
||||
if err != nil {
|
||||
t.Errorf("UseGivenTokenIfValid returned an error when the token was omitted: %v", err)
|
||||
}
|
||||
if given {
|
||||
t.Error("UseGivenTokenIfValid returned given = true when the token was omitted; expected false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenValidationFailures(t *testing.T) {
|
||||
var tests = []struct {
|
||||
t string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
t: "1234567890123456789012",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
t: "12345.1234567890123456",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
t: ".1234567890123456",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
t: "123456.1234567890.123456",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
s := newSecretsWithToken(rt.t)
|
||||
_, err := UseGivenTokenIfValid(s)
|
||||
if (err == nil) != rt.expected {
|
||||
t.Errorf(
|
||||
"failed UseGivenTokenIfValid and did not return an error for this invalid token: [%s]",
|
||||
rt.t,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidTokenPopulatesSecrets(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token string
|
||||
expectedToken []byte
|
||||
expectedTokenID string
|
||||
expectedBearerToken string
|
||||
}{
|
||||
{
|
||||
token: "123456.0123456789AbCdEf",
|
||||
expectedToken: []byte("0123456789abcdef"),
|
||||
expectedTokenID: "123456",
|
||||
expectedBearerToken: "0123456789abcdef",
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
s := newSecretsWithToken(rt.token)
|
||||
|
||||
given, err := UseGivenTokenIfValid(s)
|
||||
if err != nil {
|
||||
t.Errorf("UseGivenTokenIfValid gave an error for a valid token: %v", err)
|
||||
}
|
||||
if !given {
|
||||
t.Error("UseGivenTokenIfValid returned given = false when given a valid token")
|
||||
}
|
||||
if s.TokenID != rt.expectedTokenID {
|
||||
t.Errorf("UseGivenTokenIfValid did not populate the TokenID correctly; expected [%s] but got [%s]", rt.expectedTokenID, s.TokenID)
|
||||
}
|
||||
if s.BearerToken != rt.expectedBearerToken {
|
||||
t.Errorf("UseGivenTokenIfValid did not populate the BearerToken correctly; expected [%s] but got [%s]", rt.expectedBearerToken, s.BearerToken)
|
||||
}
|
||||
if !bytes.Equal(s.Token, rt.expectedToken) {
|
||||
t.Errorf("UseGivenTokenIfValid did not populate the Token correctly; expected %v but got %v", rt.expectedToken, s.Token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newSecretsWithToken(token string) *kubeadmapi.Secrets {
|
||||
s := new(kubeadmapi.Secrets)
|
||||
s.GivenToken = token
|
||||
return s
|
||||
}
|
||||
|
||||
func TestGenerateToken(t *testing.T) {
|
||||
var genTest = []struct {
|
||||
s kubeadmapi.Secrets
|
||||
l int
|
||||
n int
|
||||
}{
|
||||
{kubeadmapi.Secrets{}, 2, 6},
|
||||
}
|
||||
|
||||
for _, rt := range genTest {
|
||||
GenerateToken(&rt.s)
|
||||
givenToken := strings.Split(strings.ToLower(rt.s.GivenToken), ".")
|
||||
if len(givenToken) != rt.l {
|
||||
t.Errorf(
|
||||
"failed GenerateToken num parts:\n\texpected: %d\n\t actual: %d",
|
||||
rt.l,
|
||||
len(givenToken),
|
||||
)
|
||||
}
|
||||
if len(givenToken[0]) != rt.n {
|
||||
t.Errorf(
|
||||
"failed GenerateToken first part length:\n\texpected: %d\n\t actual: %d",
|
||||
rt.l,
|
||||
len(givenToken),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUseGivenTokenIfValid(t *testing.T) {
|
||||
var tokenTest = []struct {
|
||||
s kubeadmapi.Secrets
|
||||
expected bool
|
||||
}{
|
||||
{kubeadmapi.Secrets{GivenToken: ""}, false}, // GivenToken == ""
|
||||
{kubeadmapi.Secrets{GivenToken: "noperiod"}, false}, // not 2-part '.' format
|
||||
{kubeadmapi.Secrets{GivenToken: "abcd.a"}, false}, // len(tokenID) != 6
|
||||
{kubeadmapi.Secrets{GivenToken: "abcdef.a"}, true},
|
||||
}
|
||||
|
||||
for _, rt := range tokenTest {
|
||||
actual, _ := UseGivenTokenIfValid(&rt.s)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed UseGivenTokenIfValid:\n\texpected: %t\n\t actual: %t\n\t token:%s",
|
||||
rt.expected,
|
||||
actual,
|
||||
rt.s.GivenToken,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandBytes(t *testing.T) {
|
||||
var randTest = []struct {
|
||||
r int
|
||||
l int
|
||||
expected error
|
||||
}{
|
||||
{0, 0, nil},
|
||||
{1, 1, nil},
|
||||
{2, 2, nil},
|
||||
{3, 3, nil},
|
||||
{100, 100, nil},
|
||||
}
|
||||
|
||||
for _, rt := range randTest {
|
||||
actual, _, err := RandBytes(rt.r)
|
||||
if err != rt.expected {
|
||||
t.Errorf(
|
||||
"failed RandBytes:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
err,
|
||||
)
|
||||
}
|
||||
if len(actual) != rt.l {
|
||||
t.Errorf(
|
||||
"failed RandBytes:\n\texpected: %d\n\t actual: %d\n",
|
||||
rt.l,
|
||||
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("Error: unable to get URL %q: %s", url, err.Error())
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("Error: unable to fetch release information. URL: %q Status: %v", url, resp.Status)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error: 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("Error: 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 succesfully, 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue