From de5e17e6c336aaa23534b3a236c784cbcd9a6ecf Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Thu, 21 Feb 2019 04:15:59 +0200 Subject: [PATCH] kubeadm/phases: use common interfaces for init and join phases The custom sub-set interfaces in init/join phases as a pattern have isolation benefits - e.g. when a consumer imports these but we don't want them to be able to call all methods from the original object that satisfies a complete interface. On the other hand these sub-set interfaces under phases/init and phases/join are private. Expose a couple of new common interfaces: - InitData from phases/init/data.go - JoinData from phases/join/data.go Use these interfaces in init/join phases accordingly instead of the sub-set interfaces. Use compile-time type assertion to verify that these interfaces can be satisfied by init.go's initData and join.go's joinData. Add NO-OP objects called testInitData and joinInitData that can be used for unit testing if embedded. --- cmd/kubeadm/app/cmd/init.go | 5 +- cmd/kubeadm/app/cmd/join.go | 3 ++ cmd/kubeadm/app/cmd/phases/init/BUILD | 8 ++- cmd/kubeadm/app/cmd/phases/init/addons.go | 13 ++--- .../app/cmd/phases/init/bootstraptoken.go | 12 +---- cmd/kubeadm/app/cmd/phases/init/certs.go | 18 ++----- cmd/kubeadm/app/cmd/phases/init/certs_test.go | 1 + .../app/cmd/phases/init/controlplane.go | 11 +---- cmd/kubeadm/app/cmd/phases/init/data.go | 47 ++++++++++++++++++ cmd/kubeadm/app/cmd/phases/init/data_test.go | 49 +++++++++++++++++++ cmd/kubeadm/app/cmd/phases/init/etcd.go | 9 +--- cmd/kubeadm/app/cmd/phases/init/kubeconfig.go | 16 +----- cmd/kubeadm/app/cmd/phases/init/kubelet.go | 12 +---- .../app/cmd/phases/init/markcontrolplane.go | 10 +--- cmd/kubeadm/app/cmd/phases/init/preflight.go | 13 +---- .../app/cmd/phases/init/uploadcerts.go | 12 +---- .../app/cmd/phases/init/uploadconfig.go | 7 +-- .../app/cmd/phases/init/waitcontrolplane.go | 13 +---- cmd/kubeadm/app/cmd/phases/join/BUILD | 15 +++++- cmd/kubeadm/app/cmd/phases/join/checketcd.go | 10 +--- .../app/cmd/phases/join/controlplanejoin.go | 15 ++---- .../cmd/phases/join/controlplaneprepare.go | 12 ++--- cmd/kubeadm/app/cmd/phases/join/data.go | 38 ++++++++++++++ cmd/kubeadm/app/cmd/phases/join/data_test.go | 40 +++++++++++++++ cmd/kubeadm/app/cmd/phases/join/kubelet.go | 12 +---- cmd/kubeadm/app/cmd/phases/join/preflight.go | 9 +--- 26 files changed, 234 insertions(+), 176 deletions(-) create mode 100644 cmd/kubeadm/app/cmd/phases/init/data.go create mode 100644 cmd/kubeadm/app/cmd/phases/init/data_test.go create mode 100644 cmd/kubeadm/app/cmd/phases/join/data.go create mode 100644 cmd/kubeadm/app/cmd/phases/join/data_test.go diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index 2663117104..9c90d3f21f 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -87,7 +87,10 @@ type initOptions struct { uploadCerts bool } -// initData defines all the runtime information used when running the kubeadm init workflow; +// compile-time assert that the local data object satisfies the phases data interface. +var _ phases.InitData = &initData{} + +// initData defines all the runtime information used when running the kubeadm init worklow; // this data is shared across all the phases that are included in the workflow. type initData struct { cfg *kubeadmapi.InitConfiguration diff --git a/cmd/kubeadm/app/cmd/join.go b/cmd/kubeadm/app/cmd/join.go index dd71a8a70b..c4533bb8a4 100644 --- a/cmd/kubeadm/app/cmd/join.go +++ b/cmd/kubeadm/app/cmd/join.go @@ -129,6 +129,9 @@ type joinOptions struct { externalcfg *kubeadmapiv1beta1.JoinConfiguration } +// compile-time assert that the local data object satisfies the phases data interface. +var _ phases.JoinData = &joinData{} + // joinData defines all the runtime information used when running the kubeadm join worklow; // this data is shared across all the phases that are included in the workflow. type joinData struct { diff --git a/cmd/kubeadm/app/cmd/phases/init/BUILD b/cmd/kubeadm/app/cmd/phases/init/BUILD index df4b683d69..22033bbf72 100644 --- a/cmd/kubeadm/app/cmd/phases/init/BUILD +++ b/cmd/kubeadm/app/cmd/phases/init/BUILD @@ -7,6 +7,7 @@ go_library( "bootstraptoken.go", "certs.go", "controlplane.go", + "data.go", "etcd.go", "kubeconfig.go", "kubelet.go", @@ -58,7 +59,10 @@ go_library( go_test( name = "go_default_test", - srcs = ["certs_test.go"], + srcs = [ + "certs_test.go", + "data_test.go", + ], embed = [":go_default_library"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", @@ -67,6 +71,8 @@ go_test( "//cmd/kubeadm/app/util/certs:go_default_library", "//cmd/kubeadm/app/util/pkiutil:go_default_library", "//cmd/kubeadm/test:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", ], ) diff --git a/cmd/kubeadm/app/cmd/phases/init/addons.go b/cmd/kubeadm/app/cmd/phases/init/addons.go index e7c38e4664..7dcdce84ea 100644 --- a/cmd/kubeadm/app/cmd/phases/init/addons.go +++ b/cmd/kubeadm/app/cmd/phases/init/addons.go @@ -40,11 +40,6 @@ var ( `) ) -type addonData interface { - Cfg() *kubeadmapi.InitConfiguration - Client() (clientset.Interface, error) -} - // NewAddonPhase returns the addon Cobra command func NewAddonPhase() workflow.Phase { return workflow.Phase{ @@ -76,8 +71,8 @@ func NewAddonPhase() workflow.Phase { } } -func getAddonData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.Interface, error) { - data, ok := c.(addonData) +func getInitData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.Interface, error) { + data, ok := c.(InitData) if !ok { return nil, nil, errors.New("addon phase invoked with an invalid data struct") } @@ -91,7 +86,7 @@ func getAddonData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset. // runCoreDNSAddon installs CoreDNS addon to a Kubernetes cluster func runCoreDNSAddon(c workflow.RunData) error { - cfg, client, err := getAddonData(c) + cfg, client, err := getInitData(c) if err != nil { return err } @@ -100,7 +95,7 @@ func runCoreDNSAddon(c workflow.RunData) error { // runKubeProxyAddon installs KubeProxy addon to a Kubernetes cluster func runKubeProxyAddon(c workflow.RunData) error { - cfg, client, err := getAddonData(c) + cfg, client, err := getInitData(c) if err != nil { return err } diff --git a/cmd/kubeadm/app/cmd/phases/init/bootstraptoken.go b/cmd/kubeadm/app/cmd/phases/init/bootstraptoken.go index 140fdad680..dc14487a31 100644 --- a/cmd/kubeadm/app/cmd/phases/init/bootstraptoken.go +++ b/cmd/kubeadm/app/cmd/phases/init/bootstraptoken.go @@ -21,8 +21,6 @@ import ( "github.com/pkg/errors" - clientset "k8s.io/client-go/kubernetes" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" clusterinfophase "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo" @@ -46,14 +44,6 @@ var ( `) ) -type bootstrapTokenData interface { - Cfg() *kubeadmapi.InitConfiguration - Client() (clientset.Interface, error) - KubeConfigPath() string - SkipTokenPrint() bool - Tokens() []string -} - // NewBootstrapTokenPhase returns the phase to bootstrapToken func NewBootstrapTokenPhase() workflow.Phase { return workflow.Phase{ @@ -72,7 +62,7 @@ func NewBootstrapTokenPhase() workflow.Phase { } func runBootstrapToken(c workflow.RunData) error { - data, ok := c.(bootstrapTokenData) + data, ok := c.(InitData) if !ok { return errors.New("bootstrap-token phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/init/certs.go b/cmd/kubeadm/app/cmd/phases/init/certs.go index a04be51b73..cfdf7bacbb 100644 --- a/cmd/kubeadm/app/cmd/phases/init/certs.go +++ b/cmd/kubeadm/app/cmd/phases/init/certs.go @@ -54,16 +54,6 @@ var ( csrDir string ) -// certsData defines the behavior that a runtime data struct passed to the certs phase should -// have. Please note that we are using an interface in order to make this phase reusable in different workflows -// (and thus with different runtime data struct, all of them requested to be compliant to this interface) -type certsData interface { - Cfg() *kubeadmapi.InitConfiguration - ExternalCA() bool - CertificateDir() string - CertificateWriteDir() string -} - // NewCertsPhase returns the phase for the certs func NewCertsPhase() workflow.Phase { return workflow.Phase{ @@ -193,7 +183,7 @@ func getSANDescription(certSpec *certsphase.KubeadmCert) string { } func runCertsSa(c workflow.RunData) error { - data, ok := c.(certsData) + data, ok := c.(InitData) if !ok { return errors.New("certs phase invoked with an invalid data struct") } @@ -209,7 +199,7 @@ func runCertsSa(c workflow.RunData) error { } func runCerts(c workflow.RunData) error { - data, ok := c.(certsData) + data, ok := c.(InitData) if !ok { return errors.New("certs phase invoked with an invalid data struct") } @@ -220,7 +210,7 @@ func runCerts(c workflow.RunData) error { func runCAPhase(ca *certsphase.KubeadmCert) func(c workflow.RunData) error { return func(c workflow.RunData) error { - data, ok := c.(certsData) + data, ok := c.(InitData) if !ok { return errors.New("certs phase invoked with an invalid data struct") } @@ -252,7 +242,7 @@ func runCAPhase(ca *certsphase.KubeadmCert) func(c workflow.RunData) error { func runCertPhase(cert *certsphase.KubeadmCert, caCert *certsphase.KubeadmCert) func(c workflow.RunData) error { return func(c workflow.RunData) error { - data, ok := c.(certsData) + data, ok := c.(InitData) if !ok { return errors.New("certs phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/init/certs_test.go b/cmd/kubeadm/app/cmd/phases/init/certs_test.go index dda406b9a2..c28c8945d7 100644 --- a/cmd/kubeadm/app/cmd/phases/init/certs_test.go +++ b/cmd/kubeadm/app/cmd/phases/init/certs_test.go @@ -30,6 +30,7 @@ import ( ) type testCertsData struct { + testInitData cfg *kubeadmapi.InitConfiguration } diff --git a/cmd/kubeadm/app/cmd/phases/init/controlplane.go b/cmd/kubeadm/app/cmd/phases/init/controlplane.go index b5fd2c8ff5..6406f04721 100644 --- a/cmd/kubeadm/app/cmd/phases/init/controlplane.go +++ b/cmd/kubeadm/app/cmd/phases/init/controlplane.go @@ -21,7 +21,6 @@ import ( "github.com/pkg/errors" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" @@ -59,12 +58,6 @@ var ( } ) -type controlPlaneData interface { - Cfg() *kubeadmapi.InitConfiguration - KubeConfigDir() string - ManifestDir() string -} - func getPhaseDescription(component string) string { return fmt.Sprintf("Generates the %s static Pod manifest", component) } @@ -133,7 +126,7 @@ func getControlPlanePhaseFlags(name string) []string { } func runControlPlanePhase(c workflow.RunData) error { - data, ok := c.(controlPlaneData) + data, ok := c.(InitData) if !ok { return errors.New("control-plane phase invoked with an invalid data struct") } @@ -144,7 +137,7 @@ func runControlPlanePhase(c workflow.RunData) error { func runControlPlaneSubphase(component string) func(c workflow.RunData) error { return func(c workflow.RunData) error { - data, ok := c.(controlPlaneData) + data, ok := c.(InitData) if !ok { return errors.New("control-plane phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/init/data.go b/cmd/kubeadm/app/cmd/phases/init/data.go new file mode 100644 index 0000000000..f30a9c3577 --- /dev/null +++ b/cmd/kubeadm/app/cmd/phases/init/data.go @@ -0,0 +1,47 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package phases + +import ( + "io" + + "k8s.io/apimachinery/pkg/util/sets" + clientset "k8s.io/client-go/kubernetes" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" +) + +// InitData is the interface to use for init phases. +// The "initData" type from "cmd/init.go" must satisfy this interface. +type InitData interface { + UploadCerts() bool + CertificateKey() string + SetCertificateKey(key string) + Cfg() *kubeadmapi.InitConfiguration + DryRun() bool + SkipTokenPrint() bool + IgnorePreflightErrors() sets.String + CertificateWriteDir() string + CertificateDir() string + KubeConfigDir() string + KubeConfigPath() string + ManifestDir() string + KubeletDir() string + ExternalCA() bool + OutputWriter() io.Writer + Client() (clientset.Interface, error) + Tokens() []string +} diff --git a/cmd/kubeadm/app/cmd/phases/init/data_test.go b/cmd/kubeadm/app/cmd/phases/init/data_test.go new file mode 100644 index 0000000000..4d51efef76 --- /dev/null +++ b/cmd/kubeadm/app/cmd/phases/init/data_test.go @@ -0,0 +1,49 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package phases + +import ( + "io" + + "k8s.io/apimachinery/pkg/util/sets" + clientset "k8s.io/client-go/kubernetes" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" +) + +// a package local type for testing purposes. +type testInitData struct{} + +// testInitData must satisfy InitData. +var _ InitData = &testInitData{} + +func (t *testInitData) UploadCerts() bool { return false } +func (t *testInitData) CertificateKey() string { return "" } +func (t *testInitData) SetCertificateKey(key string) {} +func (t *testInitData) Cfg() *kubeadmapi.InitConfiguration { return nil } +func (t *testInitData) DryRun() bool { return false } +func (t *testInitData) SkipTokenPrint() bool { return false } +func (t *testInitData) IgnorePreflightErrors() sets.String { return nil } +func (t *testInitData) CertificateWriteDir() string { return "" } +func (t *testInitData) CertificateDir() string { return "" } +func (t *testInitData) KubeConfigDir() string { return "" } +func (t *testInitData) KubeConfigPath() string { return "" } +func (t *testInitData) ManifestDir() string { return "" } +func (t *testInitData) KubeletDir() string { return "" } +func (t *testInitData) ExternalCA() bool { return false } +func (t *testInitData) OutputWriter() io.Writer { return nil } +func (t *testInitData) Client() (clientset.Interface, error) { return nil, nil } +func (t *testInitData) Tokens() []string { return nil } diff --git a/cmd/kubeadm/app/cmd/phases/init/etcd.go b/cmd/kubeadm/app/cmd/phases/init/etcd.go index f531ee9041..0142e46f7c 100644 --- a/cmd/kubeadm/app/cmd/phases/init/etcd.go +++ b/cmd/kubeadm/app/cmd/phases/init/etcd.go @@ -22,7 +22,6 @@ import ( "github.com/pkg/errors" "k8s.io/klog" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" @@ -42,12 +41,6 @@ var ( `) ) -type etcdData interface { - Cfg() *kubeadmapi.InitConfiguration - DryRun() bool - ManifestDir() string -} - // NewEtcdPhase creates a kubeadm workflow phase that implements handling of etcd. func NewEtcdPhase() workflow.Phase { phase := workflow.Phase{ @@ -83,7 +76,7 @@ func getEtcdPhaseFlags() []string { func runEtcdPhaseLocal() func(c workflow.RunData) error { return func(c workflow.RunData) error { - data, ok := c.(etcdData) + data, ok := c.(InitData) if !ok { return errors.New("etcd phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/init/kubeconfig.go b/cmd/kubeadm/app/cmd/phases/init/kubeconfig.go index fef677388a..a6c277c6f9 100644 --- a/cmd/kubeadm/app/cmd/phases/init/kubeconfig.go +++ b/cmd/kubeadm/app/cmd/phases/init/kubeconfig.go @@ -20,7 +20,6 @@ import ( "fmt" "github.com/pkg/errors" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" @@ -62,17 +61,6 @@ var ( } ) -// kubeConfigData defines the behavior that a runtime data struct passed to the kubeconfig phase -// should have. Please note that we are using an interface in order to make this phase reusable in different workflows -// (and thus with different runtime data struct, all of them requested to be compliant to this interface) -type kubeConfigData interface { - Cfg() *kubeadmapi.InitConfiguration - ExternalCA() bool - CertificateDir() string - CertificateWriteDir() string - KubeConfigDir() string -} - // NewKubeConfigPhase creates a kubeadm workflow phase that creates all kubeconfig files necessary to establish the control plane and the admin kubeconfig file. func NewKubeConfigPhase() workflow.Phase { return workflow.Phase{ @@ -123,7 +111,7 @@ func getKubeConfigPhaseFlags(name string) []string { } func runKubeConfig(c workflow.RunData) error { - data, ok := c.(kubeConfigData) + data, ok := c.(InitData) if !ok { return errors.New("kubeconfig phase invoked with an invalid data struct") } @@ -135,7 +123,7 @@ func runKubeConfig(c workflow.RunData) error { // runKubeConfigFile executes kubeconfig creation logic. func runKubeConfigFile(kubeConfigFileName string) func(workflow.RunData) error { return func(c workflow.RunData) error { - data, ok := c.(kubeConfigData) + data, ok := c.(InitData) if !ok { return errors.New("kubeconfig phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/init/kubelet.go b/cmd/kubeadm/app/cmd/phases/init/kubelet.go index b8456a2696..52de91e343 100644 --- a/cmd/kubeadm/app/cmd/phases/init/kubelet.go +++ b/cmd/kubeadm/app/cmd/phases/init/kubelet.go @@ -19,7 +19,6 @@ package phases import ( "github.com/pkg/errors" "k8s.io/klog" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet" @@ -33,15 +32,6 @@ var ( `) ) -// kubeletStartData defines the behavior that a runtime data struct passed to the kubelet start phase -// should have. Please note that we are using an interface in order to make this phase reusable in different workflows -// (and thus with different runtime data struct, all of them requested to be compliant to this interface) -type kubeletStartData interface { - Cfg() *kubeadmapi.InitConfiguration - DryRun() bool - KubeletDir() string -} - // NewKubeletStartPhase creates a kubeadm workflow phase that start kubelet on a node. func NewKubeletStartPhase() workflow.Phase { return workflow.Phase{ @@ -60,7 +50,7 @@ func NewKubeletStartPhase() workflow.Phase { // runKubeletStart executes kubelet start logic. func runKubeletStart(c workflow.RunData) error { - data, ok := c.(kubeletStartData) + data, ok := c.(InitData) if !ok { return errors.New("kubelet-start phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/init/markcontrolplane.go b/cmd/kubeadm/app/cmd/phases/init/markcontrolplane.go index d65187f839..3bf112f94d 100644 --- a/cmd/kubeadm/app/cmd/phases/init/markcontrolplane.go +++ b/cmd/kubeadm/app/cmd/phases/init/markcontrolplane.go @@ -18,8 +18,6 @@ package phases import ( "github.com/pkg/errors" - clientset "k8s.io/client-go/kubernetes" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" markcontrolplanephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markcontrolplane" @@ -36,12 +34,6 @@ var ( `) ) -type markControlPlaneData interface { - Cfg() *kubeadmapi.InitConfiguration - Client() (clientset.Interface, error) - DryRun() bool -} - // NewMarkControlPlanePhase creates a kubeadm workflow phase that implements mark-controlplane checks. func NewMarkControlPlanePhase() workflow.Phase { return workflow.Phase{ @@ -58,7 +50,7 @@ func NewMarkControlPlanePhase() workflow.Phase { // runMarkControlPlane executes mark-control-plane checks logic. func runMarkControlPlane(c workflow.RunData) error { - data, ok := c.(markControlPlaneData) + data, ok := c.(InitData) if !ok { return errors.New("mark-control-plane phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/init/preflight.go b/cmd/kubeadm/app/cmd/phases/init/preflight.go index 12099ced56..4104cc4833 100644 --- a/cmd/kubeadm/app/cmd/phases/init/preflight.go +++ b/cmd/kubeadm/app/cmd/phases/init/preflight.go @@ -20,8 +20,6 @@ import ( "fmt" "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/util/sets" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" "k8s.io/kubernetes/cmd/kubeadm/app/preflight" @@ -36,15 +34,6 @@ var ( `) ) -// preflightData defines the behavior that a runtime data struct passed to the Preflight phase -// should have. Please note that we are using an interface in order to make this phase reusable in different workflows -// (and thus with different runtime data struct, all of them requested to be compliant to this interface) -type preflightData interface { - Cfg() *kubeadmapi.InitConfiguration - DryRun() bool - IgnorePreflightErrors() sets.String -} - // NewPreflightPhase creates a kubeadm workflow phase that implements preflight checks for a new control-plane node. func NewPreflightPhase() workflow.Phase { return workflow.Phase{ @@ -62,7 +51,7 @@ func NewPreflightPhase() workflow.Phase { // runPreflight executes preflight checks logic. func runPreflight(c workflow.RunData) error { - data, ok := c.(preflightData) + data, ok := c.(InitData) if !ok { return errors.New("preflight phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/init/uploadcerts.go b/cmd/kubeadm/app/cmd/phases/init/uploadcerts.go index c9d388e53c..447f56bf2f 100644 --- a/cmd/kubeadm/app/cmd/phases/init/uploadcerts.go +++ b/cmd/kubeadm/app/cmd/phases/init/uploadcerts.go @@ -21,9 +21,7 @@ import ( "github.com/pkg/errors" - clientset "k8s.io/client-go/kubernetes" "k8s.io/klog" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" @@ -31,14 +29,6 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadcerts" ) -type uploadCertsData interface { - Client() (clientset.Interface, error) - UploadCerts() bool - Cfg() *kubeadmapi.InitConfiguration - CertificateKey() string - SetCertificateKey(key string) -} - // NewUploadCertsPhase returns the uploadCerts phase func NewUploadCertsPhase() workflow.Phase { return workflow.Phase{ @@ -54,7 +44,7 @@ func NewUploadCertsPhase() workflow.Phase { } func runUploadCerts(c workflow.RunData) error { - data, ok := c.(uploadCertsData) + data, ok := c.(InitData) if !ok { return errors.New("upload-certs phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/init/uploadconfig.go b/cmd/kubeadm/app/cmd/phases/init/uploadconfig.go index 60481886d7..8d552269db 100644 --- a/cmd/kubeadm/app/cmd/phases/init/uploadconfig.go +++ b/cmd/kubeadm/app/cmd/phases/init/uploadconfig.go @@ -58,11 +58,6 @@ var ( `) ) -type uploadConfigData interface { - Cfg() *kubeadmapi.InitConfiguration - Client() (clientset.Interface, error) -} - // NewUploadConfigPhase returns the phase to uploadConfig func NewUploadConfigPhase() workflow.Phase { return workflow.Phase{ @@ -138,7 +133,7 @@ func runUploadKubeletConfig(c workflow.RunData) error { } func getUploadConfigData(c workflow.RunData) (*kubeadmapi.InitConfiguration, clientset.Interface, error) { - data, ok := c.(uploadConfigData) + data, ok := c.(InitData) if !ok { return nil, nil, errors.New("upload-config phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/init/waitcontrolplane.go b/cmd/kubeadm/app/cmd/phases/init/waitcontrolplane.go index 208dcf8309..544e401a6d 100644 --- a/cmd/kubeadm/app/cmd/phases/init/waitcontrolplane.go +++ b/cmd/kubeadm/app/cmd/phases/init/waitcontrolplane.go @@ -27,7 +27,6 @@ import ( "github.com/pkg/errors" clientset "k8s.io/client-go/kubernetes" "k8s.io/klog" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient" @@ -56,14 +55,6 @@ var ( `))) ) -type waitControlPlaneData interface { - Cfg() *kubeadmapi.InitConfiguration - ManifestDir() string - DryRun() bool - Client() (clientset.Interface, error) - OutputWriter() io.Writer -} - // NewWaitControlPlanePhase is a hidden phase that runs after the control-plane and etcd phases func NewWaitControlPlanePhase() workflow.Phase { phase := workflow.Phase{ @@ -75,7 +66,7 @@ func NewWaitControlPlanePhase() workflow.Phase { } func runWaitControlPlanePhase(c workflow.RunData) error { - data, ok := c.(waitControlPlaneData) + data, ok := c.(InitData) if !ok { return errors.New("wait-control-plane phase invoked with an invalid data struct") } @@ -113,7 +104,7 @@ func runWaitControlPlanePhase(c workflow.RunData) error { } // printFilesIfDryRunning prints the Static Pod manifests to stdout and informs about the temporary directory to go and lookup -func printFilesIfDryRunning(data waitControlPlaneData) error { +func printFilesIfDryRunning(data InitData) error { if !data.DryRun() { return nil } diff --git a/cmd/kubeadm/app/cmd/phases/join/BUILD b/cmd/kubeadm/app/cmd/phases/join/BUILD index 957d1ec4e0..6eb6d73fdb 100644 --- a/cmd/kubeadm/app/cmd/phases/join/BUILD +++ b/cmd/kubeadm/app/cmd/phases/join/BUILD @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -6,6 +6,7 @@ go_library( "checketcd.go", "controlplanejoin.go", "controlplaneprepare.go", + "data.go", "kubelet.go", "preflight.go", ], @@ -54,3 +55,15 @@ filegroup( tags = ["automanaged"], visibility = ["//visibility:public"], ) + +go_test( + name = "go_default_test", + srcs = ["data_test.go"], + embed = [":go_default_library"], + deps = [ + "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//staging/src/k8s.io/client-go/kubernetes:go_default_library", + "//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library", + ], +) diff --git a/cmd/kubeadm/app/cmd/phases/join/checketcd.go b/cmd/kubeadm/app/cmd/phases/join/checketcd.go index b64e831195..ec3153dccb 100644 --- a/cmd/kubeadm/app/cmd/phases/join/checketcd.go +++ b/cmd/kubeadm/app/cmd/phases/join/checketcd.go @@ -20,19 +20,11 @@ import ( "fmt" "github.com/pkg/errors" - clientset "k8s.io/client-go/kubernetes" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" etcdphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/etcd" ) -type checkEtcdData interface { - Cfg() *kubeadmapi.JoinConfiguration - ClientSetFromFile(string) (*clientset.Clientset, error) - InitCfg() (*kubeadmapi.InitConfiguration, error) -} - // NewCheckEtcdPhase is a hidden phase that runs after the control-plane-prepare and // before the bootstrap-kubelet phase that ensures etcd is healthy func NewCheckEtcdPhase() workflow.Phase { @@ -44,7 +36,7 @@ func NewCheckEtcdPhase() workflow.Phase { } func runCheckEtcdPhase(c workflow.RunData) error { - data, ok := c.(checkEtcdData) + data, ok := c.(JoinData) if !ok { return errors.New("check-etcd phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go b/cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go index 69f97efaed..37164a3f78 100644 --- a/cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go +++ b/cmd/kubeadm/app/cmd/phases/join/controlplanejoin.go @@ -20,8 +20,6 @@ import ( "fmt" "github.com/pkg/errors" - clientset "k8s.io/client-go/kubernetes" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" @@ -39,13 +37,6 @@ var ( `) ) -type controlPlaneJoinData interface { - Cfg() *kubeadmapi.JoinConfiguration - ClientSetFromFile(string) (*clientset.Clientset, error) - InitCfg() (*kubeadmapi.InitConfiguration, error) - KubeConfigPath() string -} - func getControlPlaneJoinPhaseFlags() []string { return []string{ options.APIServerAdvertiseAddress, @@ -109,7 +100,7 @@ func newMarkControlPlaneSubphase() workflow.Phase { } func runEtcdPhase(c workflow.RunData) error { - data, ok := c.(controlPlaneJoinData) + data, ok := c.(JoinData) if !ok { return errors.New("control-plane-join phase invoked with an invalid data struct") } @@ -151,7 +142,7 @@ func runEtcdPhase(c workflow.RunData) error { } func runUploadConfigPhase(c workflow.RunData) error { - data, ok := c.(controlPlaneJoinData) + data, ok := c.(JoinData) if !ok { return errors.New("control-plane-join phase invoked with an invalid data struct") } @@ -179,7 +170,7 @@ func runUploadConfigPhase(c workflow.RunData) error { } func runMarkControlPlanePhase(c workflow.RunData) error { - data, ok := c.(controlPlaneJoinData) + data, ok := c.(JoinData) if !ok { return errors.New("control-plane-join phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/join/controlplaneprepare.go b/cmd/kubeadm/app/cmd/phases/join/controlplaneprepare.go index e5a38ea09b..c006df16aa 100644 --- a/cmd/kubeadm/app/cmd/phases/join/controlplaneprepare.go +++ b/cmd/kubeadm/app/cmd/phases/join/controlplaneprepare.go @@ -21,7 +21,6 @@ import ( "github.com/pkg/errors" - kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" @@ -31,11 +30,6 @@ import ( kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig" ) -type controlPlanePrepareData interface { - Cfg() *kubeadmapi.JoinConfiguration - InitCfg() (*kubeadmapi.InitConfiguration, error) -} - // NewControlPlanePreparePhase creates a kubeadm workflow phase that implements the preparation of the node to serve a control plane func NewControlPlanePreparePhase() workflow.Phase { return workflow.Phase{ @@ -97,7 +91,7 @@ func newControlPlanePrepareManifestsSubphases() workflow.Phase { } func runControlPlanePrepareManifestsSubphase(c workflow.RunData) error { - data, ok := c.(controlPlanePrepareData) + data, ok := c.(JoinData) if !ok { return errors.New("control-plane-prepare phase invoked with an invalid data struct") } @@ -117,7 +111,7 @@ func runControlPlanePrepareManifestsSubphase(c workflow.RunData) error { } func runControlPlanePrepareCertsPhaseLocal(c workflow.RunData) error { - data, ok := c.(controlPlanePrepareData) + data, ok := c.(JoinData) if !ok { return errors.New("control-plane-prepare phase invoked with an invalid data struct") } @@ -137,7 +131,7 @@ func runControlPlanePrepareCertsPhaseLocal(c workflow.RunData) error { } func runControlPlanePrepareKubeconfigPhaseLocal(c workflow.RunData) error { - data, ok := c.(controlPlanePrepareData) + data, ok := c.(JoinData) if !ok { return errors.New("control-plane-prepare phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/join/data.go b/cmd/kubeadm/app/cmd/phases/join/data.go new file mode 100644 index 0000000000..1955419a9f --- /dev/null +++ b/cmd/kubeadm/app/cmd/phases/join/data.go @@ -0,0 +1,38 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package phases + +import ( + "io" + + "k8s.io/apimachinery/pkg/util/sets" + clientset "k8s.io/client-go/kubernetes" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" +) + +// JoinData is the interface to use for join phases. +// The "joinData" type from "cmd/join.go" must satisfy this interface. +type JoinData interface { + Cfg() *kubeadmapi.JoinConfiguration + KubeConfigPath() string + TLSBootstrapCfg() (*clientcmdapi.Config, error) + InitCfg() (*kubeadmapi.InitConfiguration, error) + ClientSetFromFile(path string) (*clientset.Clientset, error) + IgnorePreflightErrors() sets.String + OutputWriter() io.Writer +} diff --git a/cmd/kubeadm/app/cmd/phases/join/data_test.go b/cmd/kubeadm/app/cmd/phases/join/data_test.go new file mode 100644 index 0000000000..8de201b393 --- /dev/null +++ b/cmd/kubeadm/app/cmd/phases/join/data_test.go @@ -0,0 +1,40 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package phases + +import ( + "io" + + "k8s.io/apimachinery/pkg/util/sets" + clientset "k8s.io/client-go/kubernetes" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" +) + +// a package local type for testing purposes. +type testJoinData struct{} + +// testJoinData must satisfy JoinData. +var _ JoinData = &testJoinData{} + +func (j *testJoinData) Cfg() *kubeadmapi.JoinConfiguration { return nil } +func (j *testJoinData) KubeConfigPath() string { return "" } +func (j *testJoinData) TLSBootstrapCfg() (*clientcmdapi.Config, error) { return nil, nil } +func (j *testJoinData) InitCfg() (*kubeadmapi.InitConfiguration, error) { return nil, nil } +func (j *testJoinData) ClientSetFromFile(path string) (*clientset.Clientset, error) { return nil, nil } +func (j *testJoinData) IgnorePreflightErrors() sets.String { return nil } +func (j *testJoinData) OutputWriter() io.Writer { return nil } diff --git a/cmd/kubeadm/app/cmd/phases/join/kubelet.go b/cmd/kubeadm/app/cmd/phases/join/kubelet.go index adc2b3edd5..c198b96bfe 100644 --- a/cmd/kubeadm/app/cmd/phases/join/kubelet.go +++ b/cmd/kubeadm/app/cmd/phases/join/kubelet.go @@ -23,7 +23,6 @@ import ( "github.com/lithammer/dedent" "github.com/pkg/errors" "k8s.io/apimachinery/pkg/util/wait" - clientset "k8s.io/client-go/kubernetes" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" certutil "k8s.io/client-go/util/cert" "k8s.io/klog" @@ -54,13 +53,6 @@ var ( `) ) -type kubeletStartData interface { - Cfg() *kubeadmapi.JoinConfiguration - ClientSetFromFile(path string) (*clientset.Clientset, error) - InitCfg() (*kubeadmapi.InitConfiguration, error) - TLSBootstrapCfg() (*clientcmdapi.Config, error) -} - // NewKubeletStartPhase creates a kubeadm workflow phase that start kubelet on a node. func NewKubeletStartPhase() workflow.Phase { return workflow.Phase{ @@ -81,8 +73,8 @@ func NewKubeletStartPhase() workflow.Phase { } } -func getKubeletStartJoinData(c workflow.RunData) (kubeletStartData, *kubeadmapi.JoinConfiguration, *kubeadmapi.InitConfiguration, *clientcmdapi.Config, error) { - data, ok := c.(kubeletStartData) +func getKubeletStartJoinData(c workflow.RunData) (JoinData, *kubeadmapi.JoinConfiguration, *kubeadmapi.InitConfiguration, *clientcmdapi.Config, error) { + data, ok := c.(JoinData) if !ok { return nil, nil, nil, nil, errors.New("kubelet-start phase invoked with an invalid data struct") } diff --git a/cmd/kubeadm/app/cmd/phases/join/preflight.go b/cmd/kubeadm/app/cmd/phases/join/preflight.go index bdf9162a8b..6a4137f097 100644 --- a/cmd/kubeadm/app/cmd/phases/join/preflight.go +++ b/cmd/kubeadm/app/cmd/phases/join/preflight.go @@ -23,7 +23,6 @@ import ( "github.com/lithammer/dedent" "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/util/sets" "k8s.io/klog" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" @@ -52,12 +51,6 @@ var ( `))) ) -type preflightData interface { - Cfg() *kubeadmapi.JoinConfiguration - InitCfg() (*kubeadmapi.InitConfiguration, error) - IgnorePreflightErrors() sets.String -} - // NewPreflightPhase creates a kubeadm workflow phase that implements preflight checks for a new node join func NewPreflightPhase() workflow.Phase { return workflow.Phase{ @@ -86,7 +79,7 @@ func NewPreflightPhase() workflow.Phase { // runPreflight executes preflight checks logic. func runPreflight(c workflow.RunData) error { - j, ok := c.(preflightData) + j, ok := c.(JoinData) if !ok { return errors.New("preflight phase invoked with an invalid data struct") }