diff --git a/hack/update-generated.sh b/hack/update-generated.sh index c10d17e2dd..22c72dbac0 100755 --- a/hack/update-generated.sh +++ b/hack/update-generated.sh @@ -39,13 +39,13 @@ go generate ./... deepcopy-gen -i ./pkg/cluster/config/ -O zz_generated.deepcopy --go-header-file hack/boilerplate.go.txt defaulter-gen -i ./pkg/cluster/config/ -O zz_generated.default --go-header-file hack/boilerplate.go.txt -deepcopy-gen -i ./pkg/cluster/config/v1alpha1 -O zz_generated.deepcopy --go-header-file hack/boilerplate.go.txt -defaulter-gen -i ./pkg/cluster/config/v1alpha1 -O zz_generated.default --go-header-file hack/boilerplate.go.txt -conversion-gen -i ./pkg/cluster/config/v1alpha1 -O zz_generated.conversion --go-header-file hack/boilerplate.go.txt - deepcopy-gen -i ./pkg/cluster/config/v1alpha2 -O zz_generated.deepcopy --go-header-file hack/boilerplate.go.txt defaulter-gen -i ./pkg/cluster/config/v1alpha2 -O zz_generated.default --go-header-file hack/boilerplate.go.txt conversion-gen -i ./pkg/cluster/config/v1alpha2 -O zz_generated.conversion --go-header-file hack/boilerplate.go.txt +deepcopy-gen -i ./pkg/cluster/config/v1alpha3 -O zz_generated.deepcopy --go-header-file hack/boilerplate.go.txt +defaulter-gen -i ./pkg/cluster/config/v1alpha3 -O zz_generated.default --go-header-file hack/boilerplate.go.txt +conversion-gen -i ./pkg/cluster/config/v1alpha3 -O zz_generated.conversion --go-header-file hack/boilerplate.go.txt + # gofmt the tree find . -path "./vendor" -prune -o -name "*.go" -type f -print0 | xargs -0 gofmt -s -w diff --git a/hack/verify-golint.sh b/hack/verify-golint.sh index 3b3a5aec36..6d3c589fb5 100755 --- a/hack/verify-golint.sh +++ b/hack/verify-golint.sh @@ -37,7 +37,7 @@ get_golint() { GOLINT="${GOLINT:-$(get_golint)}" # we need to do this because golint ./... matches vendor... -# we also further filter out generated k8s api code in the config v1alpha1 package +# we also further filter out generated k8s api code in the config packages # which unfortunately fails lint due to apimachinery conventions ... # TODO(fabrizio pandini): makes this smarter (skip only one file) # TODO(bentheelder): we also have to skip hack/tools for now because this is just @@ -45,7 +45,7 @@ GOLINT="${GOLINT:-$(get_golint)}" # TODO(bentheelder): find a solution that does not depend on GO111MODULE="off" GO111MODULE="off" go list ./... | \ grep -v '^hack/tools$' |\ - grep -v '^sigs.k8s.io/kind/pkg/cluster/config/v1alpha1$' | \ grep -v '^sigs.k8s.io/kind/pkg/cluster/config/v1alpha2$' | \ + grep -v '^sigs.k8s.io/kind/pkg/cluster/config/v1alpha3$' | \ grep -v '^sigs.k8s.io/kind/pkg/cluster/config$' | \ xargs -L1 "${GOLINT}" -set_exit_status diff --git a/pkg/cluster/config/default.go b/pkg/cluster/config/default.go index 5d04789f20..2e4e34d650 100644 --- a/pkg/cluster/config/default.go +++ b/pkg/cluster/config/default.go @@ -26,8 +26,8 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { return RegisterDefaults(scheme) } -// SetDefaults_Config sets uninitialized fields to their default value. -func SetDefaults_Config(obj *Config) { +// SetDefaults_Cluster sets uninitialized fields to their default value. +func SetDefaults_Cluster(obj *Cluster) { if len(obj.Nodes) == 0 { obj.Nodes = []Node{ { diff --git a/pkg/cluster/config/encoding/scheme.go b/pkg/cluster/config/encoding/scheme.go index a9be462ecd..910ea134f2 100644 --- a/pkg/cluster/config/encoding/scheme.go +++ b/pkg/cluster/config/encoding/scheme.go @@ -26,8 +26,8 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" "sigs.k8s.io/kind/pkg/cluster/config" - "sigs.k8s.io/kind/pkg/cluster/config/v1alpha1" "sigs.k8s.io/kind/pkg/cluster/config/v1alpha2" + "sigs.k8s.io/kind/pkg/cluster/config/v1alpha3" ) // Scheme is the runtime.Scheme to which all `kind` config API versions and types are registered. @@ -43,16 +43,16 @@ func init() { // AddToScheme builds the scheme using all known `kind` API versions. func AddToScheme(scheme *runtime.Scheme) { utilruntime.Must(config.AddToScheme(scheme)) - utilruntime.Must(v1alpha1.AddToScheme(scheme)) + utilruntime.Must(v1alpha3.AddToScheme(scheme)) utilruntime.Must(v1alpha2.AddToScheme(scheme)) - utilruntime.Must(scheme.SetVersionPriority(v1alpha2.SchemeGroupVersion)) + utilruntime.Must(scheme.SetVersionPriority(v1alpha3.SchemeGroupVersion)) } // Load reads the file at path and attempts to convert into a `kind` Config; the file // can be one of the different API versions defined in scheme. // If path == "" then the default config is returned -func Load(path string) (*config.Config, error) { - var latestPublicConfig = &v1alpha2.Config{} +func Load(path string) (*config.Cluster, error) { + var latestPublicConfig = &v1alpha3.Cluster{} if path != "" { // read in file @@ -63,7 +63,7 @@ func Load(path string) (*config.Config, error) { // decode data into a internal api Config object because // to leverage on conversion functions for all the api versions - var cfg = &config.Config{} + var cfg = &config.Cluster{} err = runtime.DecodeInto(Codecs.UniversalDecoder(), contents, cfg) if err != nil { return nil, errors.Wrap(err, "decoding failure") @@ -77,7 +77,7 @@ func Load(path string) (*config.Config, error) { Scheme.Default(latestPublicConfig) // converts to internal config - var cfg = &config.Config{} + var cfg = &config.Cluster{} Scheme.Convert(latestPublicConfig, cfg, nil) // unmarshal the file content into a `kind` Config diff --git a/pkg/cluster/config/encoding/scheme_test.go b/pkg/cluster/config/encoding/scheme_test.go index 3d8ef75ef6..a832dbfa87 100644 --- a/pkg/cluster/config/encoding/scheme_test.go +++ b/pkg/cluster/config/encoding/scheme_test.go @@ -33,18 +33,6 @@ func TestLoadCurrent(t *testing.T) { ExpectReplicas: []string{"control-plane"}, // no config (empty config path) should return a single node cluster ExpectError: false, }, - { - TestName: "v1alpha1 minimal", - Path: "./testdata/v1alpha1/valid-minimal.yaml", - ExpectReplicas: []string{"control-plane"}, - ExpectError: false, - }, - { - TestName: "v1alpha1 with lifecyclehooks", - Path: "./testdata/v1alpha1/valid-with-lifecyclehooks.yaml", - ExpectReplicas: []string{"control-plane"}, - ExpectError: false, - }, { TestName: "v1alpha2 minimal", Path: "./testdata/v1alpha2/valid-minimal.yaml", diff --git a/pkg/cluster/config/encoding/testdata/v1alpha1/valid-minimal.yaml b/pkg/cluster/config/encoding/testdata/v1alpha1/valid-minimal.yaml deleted file mode 100644 index b92ad3c077..0000000000 --- a/pkg/cluster/config/encoding/testdata/v1alpha1/valid-minimal.yaml +++ /dev/null @@ -1,3 +0,0 @@ -# technically valid, minimal config file -kind: Config -apiVersion: kind.sigs.k8s.io/v1alpha1 diff --git a/pkg/cluster/config/encoding/testdata/v1alpha1/valid-with-lifecyclehooks.yaml b/pkg/cluster/config/encoding/testdata/v1alpha1/valid-with-lifecyclehooks.yaml deleted file mode 100644 index aa63d33270..0000000000 --- a/pkg/cluster/config/encoding/testdata/v1alpha1/valid-with-lifecyclehooks.yaml +++ /dev/null @@ -1,9 +0,0 @@ -kind: Config -apiVersion: kind.sigs.k8s.io/v1alpha1 -ControlPlane: - nodeLifecycle: - preKubeadm: - - name: "pull an image" - command: [ "docker", "pull", "ubuntu" ] - - name: "pull another image" - command: [ "docker", "pull", "debian" ] \ No newline at end of file diff --git a/pkg/cluster/config/fuzzer/fuzzer.go b/pkg/cluster/config/fuzzer/fuzzer.go index 825717d259..63cf7150ac 100644 --- a/pkg/cluster/config/fuzzer/fuzzer.go +++ b/pkg/cluster/config/fuzzer/fuzzer.go @@ -31,7 +31,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { } } -func fuzzConfig(obj *config.Config, c fuzz.Continue) { +func fuzzConfig(obj *config.Cluster, c fuzz.Continue) { c.FuzzNoCustom(obj) // Pinning values for fields that get defaults if fuzz value is empty string or nil diff --git a/pkg/cluster/config/register.go b/pkg/cluster/config/register.go index fef52b593f..3474f6e346 100644 --- a/pkg/cluster/config/register.go +++ b/pkg/cluster/config/register.go @@ -40,12 +40,12 @@ func init() { // We only register manually written functions here. The registration of the // generated functions takes place in the generated files. The separation // makes the code compile even when the generated files are missing. - localSchemeBuilder.Register(addKnownTypes) + localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs) } func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, - &Config{}, + &Cluster{}, ) return nil diff --git a/pkg/cluster/config/types.go b/pkg/cluster/config/types.go index bf178d4a68..48dc10936e 100644 --- a/pkg/cluster/config/types.go +++ b/pkg/cluster/config/types.go @@ -25,58 +25,60 @@ import ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Config groups all nodes in the `kind` Config. -type Config struct { +// Cluster contains kind cluster configuration +type Cluster struct { // TypeMeta representing the type of the object and its API schema version. metav1.TypeMeta - // Nodes contains the list of nodes defined in the `kind` Config - Nodes []Node `json:"nodes,"` -} + // Nodes contains the list of nodes defined in the `kind` Cluster + // If unset this will default to a single control-plane node + // Note that if more than one control plane is specified, an external + // control plane load balancer will be provisioned implicitly + Nodes []Node + + /* Advanced fields */ -// Node contains settings for a node in the `kind` Config. -// A node in kind config represent a container that will be provisioned with all the components -// required for the assigned role in the Kubernetes cluster. -// If replicas is set, the desired node replica number will be generated. -type Node struct { - // Replicas is the number of desired node replicas. - // Defaults to 1 - Replicas *int32 - // Role defines the role of the node in the in the Kubernetes cluster managed by `kind` - // Defaults to "control-plane" - Role NodeRole - // Image is the node image to use when running the cluster - // TODO(bentheelder): split this into image and tag? - Image string // KubeadmConfigPatches are applied to the generated kubeadm config as // strategic merge patches to `kustomize build` internally // https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md // This should be an inline yaml blob-string KubeadmConfigPatches []string + // KubeadmConfigPatchesJSON6902 are applied to the generated kubeadm config // as patchesJson6902 to `kustomize build` KubeadmConfigPatchesJSON6902 []kustomize.PatchJSON6902 +} + +// Node contains settings for a node in the `kind` Cluster. +// A node in kind config represent a container that will be provisioned with all the components +// required for the assigned role in the Kubernetes cluster +type Node struct { + // Role defines the role of the node in the in the Kubernetes cluster + // created by kind + // + // Defaults to "control-plane" + Role NodeRole + + // Image is the node image to use when creating this node + // If unset a default image will be used, see defaults.Image + Image string + + /* Advanced fields */ + // ExtraMounts describes additional mount points for the node container - // These may be used to bind a hostpath - ExtraMounts []cri.Mount `json:"extraMounts,omitempty"` + // These may be used to bind a hostPath + ExtraMounts []cri.Mount } // NodeRole defines possible role for nodes in a Kubernetes cluster managed by `kind` type NodeRole string const ( - // ControlPlaneRole identifies a node that hosts a Kubernetes control-plane - // NB. in single node clusters, control-plane nodes act also as a worker nodes + // ControlPlaneRole identifies a node that hosts a Kubernetes control-plane. + // NOTE: in single node clusters, control-plane nodes act also as a worker + // nodes, in which case the taint will be removed. see: + // https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#control-plane-node-isolation ControlPlaneRole NodeRole = "control-plane" // WorkerRole identifies a node that hosts a Kubernetes worker WorkerRole NodeRole = "worker" - // ExternalEtcdRole identifies a node that hosts an external-etcd instance. - // WARNING: this node type is not yet implemented! - // Please note that `kind` nodes hosting external etcd are not kubernetes nodes - ExternalEtcdRole NodeRole = "external-etcd" - // ExternalLoadBalancerRole identifies a node that hosts an external load balancer for API server - // in HA configurations. - // WARNING: this node type is not yet implemented! - // Please note that `kind` nodes hosting external load balancer are not kubernetes nodes - ExternalLoadBalancerRole NodeRole = "external-load-balancer" ) diff --git a/pkg/cluster/config/v1alpha1/conversion.go b/pkg/cluster/config/v1alpha1/conversion.go deleted file mode 100644 index 27f885d3bb..0000000000 --- a/pkg/cluster/config/v1alpha1/conversion.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - unsafe "unsafe" - - "github.com/pkg/errors" - conversion "k8s.io/apimachinery/pkg/conversion" - "sigs.k8s.io/kind/pkg/cluster/config" - kustomize "sigs.k8s.io/kind/pkg/kustomize" -) - -func Convert_v1alpha1_Config_To_config_Config(in *Config, out *config.Config, s conversion.Scope) error { - if err := autoConvert_v1alpha1_Config_To_config_Config(in, out, s); err != nil { - return err - } - - // converts v1alpha1 Config into an internal config with a single control-plane node - var node config.Node - - node.Role = config.ControlPlaneRole - node.Image = in.Image - node.KubeadmConfigPatches = *(*[]string)(unsafe.Pointer(&in.KubeadmConfigPatches)) - node.KubeadmConfigPatchesJSON6902 = *(*[]kustomize.PatchJSON6902)(unsafe.Pointer(&in.KubeadmConfigPatchesJSON6902)) - - out.Nodes = []config.Node{node} - - return nil -} - -func Convert_config_Config_To_v1alpha1_Config(in *config.Config, out *Config, s conversion.Scope) error { - if err := autoConvert_config_Config_To_v1alpha1_Config(in, out, s); err != nil { - return err - } - - // conversion from internal config to v1alpha1 Config is used only by the fuzzer roundtrip test; - // the fuzzer is configured in order to enforce the number and type of nodes to get always the - // following condition pass - - if len(in.Nodes) > 1 { - return errors.New("invalid conversion. `kind` config with more than one Node cannot be converted to v1alpha1 config format") - } - - var node = in.Nodes[0] - - if node.Role != config.ControlPlaneRole { - return errors.Errorf("invalid conversion. `kind` config without a control-plane Node cannot be converted to v1alpha1 config format %v", node) - } - - out.Image = node.Image - out.KubeadmConfigPatches = *(*[]string)(unsafe.Pointer(&node.KubeadmConfigPatches)) - out.KubeadmConfigPatchesJSON6902 = *(*[]kustomize.PatchJSON6902)(unsafe.Pointer(&node.KubeadmConfigPatchesJSON6902)) - - return nil -} diff --git a/pkg/cluster/config/v1alpha1/types.go b/pkg/cluster/config/v1alpha1/types.go deleted file mode 100644 index 64e0f3c003..0000000000 --- a/pkg/cluster/config/v1alpha1/types.go +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/kind/pkg/kustomize" -) - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// Config contains cluster creation config -// This is the current internal config type used by cluster -type Config struct { - metav1.TypeMeta - - // Image is the node image to use when running the cluster - // TODO(bentheelder): split this into image and tag? - Image string `json:"image,omitempty"` - // KubeadmConfigPatches are applied to the generated kubeadm config as - // strategic merge patches to `kustomize build` internally - // https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md - // This should be an inline yaml blob-string - KubeadmConfigPatches []string `json:"kubeadmConfigPatches,omitempty"` - // KubeadmConfigPatchesJSON6902 are applied to the generated kubeadm config - // as patchesJson6902 to `kustomize build` - KubeadmConfigPatchesJSON6902 []kustomize.PatchJSON6902 `json:"kubeadmConfigPatchesJson6902,omitempty"` - // NOTE: this field is no longer supported (!) - // ControlPlane holds config for the control plane node - ControlPlane *ControlPlane `json:"controlPlane,omitempty"` -} - -// ControlPlane holds configurations specific to the control plane nodes -// (currently the only node). -type ControlPlane struct { - // NodeLifecycle contains LifecycleHooks for phases of node provisioning - NodeLifecycle *NodeLifecycle `json:"nodeLifecycle,omitempty"` -} - -// NodeLifecycle contains LifecycleHooks for phases of node provisioning -// Within each phase these hooks run in the order specified -type NodeLifecycle struct { - // NOTE: this field is no longer supported (!) - // PreBoot hooks run before starting systemd - PreBoot []LifecycleHook `json:"preBoot,omitempty"` - // NOTE: this field is no longer supported (!) - // PreKubeadm hooks run immediately before `kubeadm` - PreKubeadm []LifecycleHook `json:"preKubeadm,omitempty"` - // NOTE: this field is no longer supported (!) - // PostKubeadm hooks run immediately after `kubeadm` - PostKubeadm []LifecycleHook `json:"postKubeadm,omitempty"` - // NOTE: this field is no longer supported (!) - // PostSetup hooks run after any standard `kind` setup on the node - PostSetup []LifecycleHook `json:"postSetup,omitempty"` -} - -// LifecycleHook represents a command to run at points in the node lifecycle -type LifecycleHook struct { - // Name is used to improve logging (optional) - Name string `json:"name,omitempty"` - // Command is the command to run on the node - Command []string `json:"command"` - // MustSucceed - if true then the hook / command failing will cause - // cluster creation to fail, otherwise the error will just be logged and - // the boot process will continue - MustSucceed bool `json:"mustSucceed,omitempty"` -} diff --git a/pkg/cluster/config/v1alpha1/zz_generated.conversion.go b/pkg/cluster/config/v1alpha1/zz_generated.conversion.go deleted file mode 100644 index e5f2945699..0000000000 --- a/pkg/cluster/config/v1alpha1/zz_generated.conversion.go +++ /dev/null @@ -1,70 +0,0 @@ -// +build !ignore_autogenerated - -/* -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. -*/ - -// Code generated by conversion-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - conversion "k8s.io/apimachinery/pkg/conversion" - runtime "k8s.io/apimachinery/pkg/runtime" - config "sigs.k8s.io/kind/pkg/cluster/config" -) - -func init() { - localSchemeBuilder.Register(RegisterConversions) -} - -// RegisterConversions adds conversion functions to the given scheme. -// Public to allow building arbitrary schemes. -func RegisterConversions(s *runtime.Scheme) error { - if err := s.AddGeneratedConversionFunc((*Config)(nil), (*config.Config)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha1_Config_To_config_Config(a.(*Config), b.(*config.Config), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*config.Config)(nil), (*Config)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_config_Config_To_v1alpha1_Config(a.(*config.Config), b.(*Config), scope) - }); err != nil { - return err - } - if err := s.AddConversionFunc((*config.Config)(nil), (*Config)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_config_Config_To_v1alpha1_Config(a.(*config.Config), b.(*Config), scope) - }); err != nil { - return err - } - if err := s.AddConversionFunc((*Config)(nil), (*config.Config)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha1_Config_To_config_Config(a.(*Config), b.(*config.Config), scope) - }); err != nil { - return err - } - return nil -} - -func autoConvert_v1alpha1_Config_To_config_Config(in *Config, out *config.Config, s conversion.Scope) error { - // WARNING: in.Image requires manual conversion: does not exist in peer-type - // WARNING: in.KubeadmConfigPatches requires manual conversion: does not exist in peer-type - // WARNING: in.KubeadmConfigPatchesJSON6902 requires manual conversion: does not exist in peer-type - // WARNING: in.ControlPlane requires manual conversion: does not exist in peer-type - return nil -} - -func autoConvert_config_Config_To_v1alpha1_Config(in *config.Config, out *Config, s conversion.Scope) error { - // WARNING: in.Nodes requires manual conversion: does not exist in peer-type - return nil -} diff --git a/pkg/cluster/config/v1alpha1/zz_generated.deepcopy.go b/pkg/cluster/config/v1alpha1/zz_generated.deepcopy.go deleted file mode 100644 index 85b9cd8809..0000000000 --- a/pkg/cluster/config/v1alpha1/zz_generated.deepcopy.go +++ /dev/null @@ -1,152 +0,0 @@ -// +build !ignore_autogenerated - -/* -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. -*/ - -// Code generated by deepcopy-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" - kustomize "sigs.k8s.io/kind/pkg/kustomize" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { - *out = *in - out.TypeMeta = in.TypeMeta - if in.KubeadmConfigPatches != nil { - in, out := &in.KubeadmConfigPatches, &out.KubeadmConfigPatches - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.KubeadmConfigPatchesJSON6902 != nil { - in, out := &in.KubeadmConfigPatchesJSON6902, &out.KubeadmConfigPatchesJSON6902 - *out = make([]kustomize.PatchJSON6902, len(*in)) - copy(*out, *in) - } - if in.ControlPlane != nil { - in, out := &in.ControlPlane, &out.ControlPlane - *out = new(ControlPlane) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { - if in == nil { - return nil - } - out := new(Config) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ControlPlane) DeepCopyInto(out *ControlPlane) { - *out = *in - if in.NodeLifecycle != nil { - in, out := &in.NodeLifecycle, &out.NodeLifecycle - *out = new(NodeLifecycle) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlane. -func (in *ControlPlane) DeepCopy() *ControlPlane { - if in == nil { - return nil - } - out := new(ControlPlane) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LifecycleHook) DeepCopyInto(out *LifecycleHook) { - *out = *in - if in.Command != nil { - in, out := &in.Command, &out.Command - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LifecycleHook. -func (in *LifecycleHook) DeepCopy() *LifecycleHook { - if in == nil { - return nil - } - out := new(LifecycleHook) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NodeLifecycle) DeepCopyInto(out *NodeLifecycle) { - *out = *in - if in.PreBoot != nil { - in, out := &in.PreBoot, &out.PreBoot - *out = make([]LifecycleHook, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.PreKubeadm != nil { - in, out := &in.PreKubeadm, &out.PreKubeadm - *out = make([]LifecycleHook, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.PostKubeadm != nil { - in, out := &in.PostKubeadm, &out.PostKubeadm - *out = make([]LifecycleHook, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.PostSetup != nil { - in, out := &in.PostSetup, &out.PostSetup - *out = make([]LifecycleHook, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeLifecycle. -func (in *NodeLifecycle) DeepCopy() *NodeLifecycle { - if in == nil { - return nil - } - out := new(NodeLifecycle) - in.DeepCopyInto(out) - return out -} diff --git a/pkg/cluster/config/v1alpha2/conversion.go b/pkg/cluster/config/v1alpha2/conversion.go new file mode 100644 index 0000000000..92aae0b363 --- /dev/null +++ b/pkg/cluster/config/v1alpha2/conversion.go @@ -0,0 +1,81 @@ +/* +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. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + conversion "k8s.io/apimachinery/pkg/conversion" + config "sigs.k8s.io/kind/pkg/cluster/config" +) + +func Convert_v1alpha2_Config_To_config_Cluster(in *Config, out *config.Cluster, s conversion.Scope) error { + for _, node := range in.Nodes { + // TODO(bentheelder): if v1alpha3 does re-gain per-node patches, drop + // this snippet + // Copy config patches from nodes to the cluster level, since we only + // generate a cluster-wide config anyhow + for _, patch := range node.KubeadmConfigPatches { + out.KubeadmConfigPatches = append(out.KubeadmConfigPatches, patch) + } + for _, patch := range node.KubeadmConfigPatchesJSON6902 { + out.KubeadmConfigPatchesJSON6902 = append(out.KubeadmConfigPatchesJSON6902, patch) + } + + // skip now-implicit external load balancers + if node.Role == ExternalLoadBalancerRole { + continue + } + + // always convert the node + convertedNode := config.Node{} + if err := Convert_v1alpha2_Node_To_config_Node(&node, &convertedNode, s); err != nil { + return err + } + out.Nodes = append(out.Nodes, convertedNode) + + // handle additional replicas if any + if node.Replicas != nil && *node.Replicas > 1 { + for i := int32(1); i < *node.Replicas; i++ { + out.Nodes = append(out.Nodes, *convertedNode.DeepCopy()) + } + } + } + return nil +} + +func Convert_v1alpha2_Node_To_config_Node(in *Node, out *config.Node, s conversion.Scope) error { + return autoConvert_v1alpha2_Node_To_config_Node(in, out, s) +} + +func Convert_config_Cluster_To_v1alpha2_Config(in *config.Cluster, out *Config, s conversion.Scope) error { + // TODO(bentheelder): try to convert kubeadm config patches? + // Not sure if that makes sense since these aren't cluster wide, and we don't + // actually roundtrip anywho? :thinking: + for _, node := range in.Nodes { + convertedNode := Node{} + if err := Convert_config_Node_To_v1alpha2_Node(&node, &convertedNode, s); err != nil { + return err + } + out.Nodes = append(out.Nodes, convertedNode) + } + return nil +} + +func Convert_config_Node_To_v1alpha2_Node(in *config.Node, out *Node, s conversion.Scope) error { + return autoConvert_config_Node_To_v1alpha2_Node(in, out, s) +} diff --git a/pkg/cluster/config/v1alpha2/types.go b/pkg/cluster/config/v1alpha2/types.go index 68482cee4a..3b4dabe1a3 100644 --- a/pkg/cluster/config/v1alpha2/types.go +++ b/pkg/cluster/config/v1alpha2/types.go @@ -31,6 +31,9 @@ type Config struct { metav1.TypeMeta `json:",inline"` // nodes contains the list of nodes defined in the `kind` Config + // If unset this will default to a single control-plane node + // Note that if more than one control plane is specified, an external + // control plane load balancer will be provisioned implicitly Nodes []Node `json:"nodes"` } @@ -45,7 +48,7 @@ type Node struct { // Defaults to "control-plane" Role NodeRole `json:"role,omitempty"` // Image is the node image to use when running the cluster - // TODO(bentheelder): split this into image and tag? + // If unset a default image will be used, see defaults.Image Image string `json:"image,omitempty"` // KubeadmConfigPatches are applied to the generated kubeadm config as // strategic merge patches to `kustomize build` internally @@ -65,14 +68,12 @@ type NodeRole string const ( // ControlPlaneRole identifies a node that hosts a Kubernetes control-plane. - // NB. in single node clusters, control-plane nodes act also as a worker nodes + // NOTE: in single node clusters, control-plane nodes act also as a worker + // nodes, in which case the taint will be removed. see: + // https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#control-plane-node-isolation ControlPlaneRole NodeRole = "control-plane" // WorkerRole identifies a node that hosts a Kubernetes worker WorkerRole NodeRole = "worker" - // ExternalEtcdRole identifies a node that hosts an external-etcd instance. - // WARNING: this node type is not yet implemented! - // Please note that `kind` nodes hosting external etcd are not kubernetes nodes - ExternalEtcdRole NodeRole = "external-etcd" // ExternalLoadBalancerRole identifies a node that hosts an external load balancer for API server // in HA configurations. // WARNING: this node type is not yet implemented! diff --git a/pkg/cluster/config/v1alpha2/zz_generated.conversion.go b/pkg/cluster/config/v1alpha2/zz_generated.conversion.go index 9136db32a6..30c4ce4e4b 100644 --- a/pkg/cluster/config/v1alpha2/zz_generated.conversion.go +++ b/pkg/cluster/config/v1alpha2/zz_generated.conversion.go @@ -27,7 +27,6 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" config "sigs.k8s.io/kind/pkg/cluster/config" cri "sigs.k8s.io/kind/pkg/container/cri" - kustomize "sigs.k8s.io/kind/pkg/kustomize" ) func init() { @@ -37,75 +36,52 @@ func init() { // RegisterConversions adds conversion functions to the given scheme. // Public to allow building arbitrary schemes. func RegisterConversions(s *runtime.Scheme) error { - if err := s.AddGeneratedConversionFunc((*Config)(nil), (*config.Config)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha2_Config_To_config_Config(a.(*Config), b.(*config.Config), scope) + if err := s.AddGeneratedConversionFunc((*Node)(nil), (*config.Node)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Node_To_config_Node(a.(*Node), b.(*config.Node), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*config.Config)(nil), (*Config)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_config_Config_To_v1alpha2_Config(a.(*config.Config), b.(*Config), scope) + if err := s.AddGeneratedConversionFunc((*config.Node)(nil), (*Node)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_Node_To_v1alpha2_Node(a.(*config.Node), b.(*Node), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*Node)(nil), (*config.Node)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha2_Node_To_config_Node(a.(*Node), b.(*config.Node), scope) + if err := s.AddConversionFunc((*config.Cluster)(nil), (*Config)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_Cluster_To_v1alpha2_Config(a.(*config.Cluster), b.(*Config), scope) }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*config.Node)(nil), (*Node)(nil), func(a, b interface{}, scope conversion.Scope) error { + if err := s.AddConversionFunc((*config.Node)(nil), (*Node)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_config_Node_To_v1alpha2_Node(a.(*config.Node), b.(*Node), scope) }); err != nil { return err } + if err := s.AddConversionFunc((*Config)(nil), (*config.Cluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Config_To_config_Cluster(a.(*Config), b.(*config.Cluster), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*Node)(nil), (*config.Node)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_Node_To_config_Node(a.(*Node), b.(*config.Node), scope) + }); err != nil { + return err + } return nil } -func autoConvert_v1alpha2_Config_To_config_Config(in *Config, out *config.Config, s conversion.Scope) error { - out.Nodes = *(*[]config.Node)(unsafe.Pointer(&in.Nodes)) - return nil -} - -// Convert_v1alpha2_Config_To_config_Config is an autogenerated conversion function. -func Convert_v1alpha2_Config_To_config_Config(in *Config, out *config.Config, s conversion.Scope) error { - return autoConvert_v1alpha2_Config_To_config_Config(in, out, s) -} - -func autoConvert_config_Config_To_v1alpha2_Config(in *config.Config, out *Config, s conversion.Scope) error { - out.Nodes = *(*[]Node)(unsafe.Pointer(&in.Nodes)) - return nil -} - -// Convert_config_Config_To_v1alpha2_Config is an autogenerated conversion function. -func Convert_config_Config_To_v1alpha2_Config(in *config.Config, out *Config, s conversion.Scope) error { - return autoConvert_config_Config_To_v1alpha2_Config(in, out, s) -} - func autoConvert_v1alpha2_Node_To_config_Node(in *Node, out *config.Node, s conversion.Scope) error { - out.Replicas = (*int32)(unsafe.Pointer(in.Replicas)) + // WARNING: in.Replicas requires manual conversion: does not exist in peer-type out.Role = config.NodeRole(in.Role) out.Image = in.Image - out.KubeadmConfigPatches = *(*[]string)(unsafe.Pointer(&in.KubeadmConfigPatches)) - out.KubeadmConfigPatchesJSON6902 = *(*[]kustomize.PatchJSON6902)(unsafe.Pointer(&in.KubeadmConfigPatchesJSON6902)) + // WARNING: in.KubeadmConfigPatches requires manual conversion: does not exist in peer-type + // WARNING: in.KubeadmConfigPatchesJSON6902 requires manual conversion: does not exist in peer-type out.ExtraMounts = *(*[]cri.Mount)(unsafe.Pointer(&in.ExtraMounts)) return nil } -// Convert_v1alpha2_Node_To_config_Node is an autogenerated conversion function. -func Convert_v1alpha2_Node_To_config_Node(in *Node, out *config.Node, s conversion.Scope) error { - return autoConvert_v1alpha2_Node_To_config_Node(in, out, s) -} - func autoConvert_config_Node_To_v1alpha2_Node(in *config.Node, out *Node, s conversion.Scope) error { - out.Replicas = (*int32)(unsafe.Pointer(in.Replicas)) out.Role = NodeRole(in.Role) out.Image = in.Image - out.KubeadmConfigPatches = *(*[]string)(unsafe.Pointer(&in.KubeadmConfigPatches)) - out.KubeadmConfigPatchesJSON6902 = *(*[]kustomize.PatchJSON6902)(unsafe.Pointer(&in.KubeadmConfigPatchesJSON6902)) out.ExtraMounts = *(*[]cri.Mount)(unsafe.Pointer(&in.ExtraMounts)) return nil } - -// Convert_config_Node_To_v1alpha2_Node is an autogenerated conversion function. -func Convert_config_Node_To_v1alpha2_Node(in *config.Node, out *Node, s conversion.Scope) error { - return autoConvert_config_Node_To_v1alpha2_Node(in, out, s) -} diff --git a/pkg/cluster/config/v1alpha1/default.go b/pkg/cluster/config/v1alpha3/default.go similarity index 63% rename from pkg/cluster/config/v1alpha1/default.go rename to pkg/cluster/config/v1alpha3/default.go index f044a42868..c74ccb1310 100644 --- a/pkg/cluster/config/v1alpha1/default.go +++ b/pkg/cluster/config/v1alpha3/default.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha1 +package v1alpha3 import ( "k8s.io/apimachinery/pkg/runtime" @@ -26,9 +26,25 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { return RegisterDefaults(scheme) } -// SetDefaults_Config sets uninitialized fields to their default value. -func SetDefaults_Config(obj *Config) { +// SetDefaults_Cluster sets uninitialized fields to their default value. +func SetDefaults_Cluster(obj *Cluster) { + if len(obj.Nodes) == 0 { + obj.Nodes = []Node{ + { + Image: defaults.Image, + Role: ControlPlaneRole, + }, + } + } +} + +// SetDefaults_Node sets uninitialized fields to their default value. +func SetDefaults_Node(obj *Node) { if obj.Image == "" { obj.Image = defaults.Image } + + if obj.Role == "" { + obj.Role = ControlPlaneRole + } } diff --git a/pkg/cluster/config/v1alpha1/doc.go b/pkg/cluster/config/v1alpha3/doc.go similarity index 81% rename from pkg/cluster/config/v1alpha1/doc.go rename to pkg/cluster/config/v1alpha3/doc.go index e5810c210b..afd2b5c32d 100644 --- a/pkg/cluster/config/v1alpha1/doc.go +++ b/pkg/cluster/config/v1alpha3/doc.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -14,9 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package v1alpha1 implements the v1alpha1 apiVersion of the `kind` Config +// Package v1alpha3 implements the v1alpha3 apiVersion of kind's cluster +// configuration // // +k8s:deepcopy-gen=package // +k8s:conversion-gen=sigs.k8s.io/kind/pkg/cluster/config // +k8s:defaulter-gen=TypeMeta -package v1alpha1 +package v1alpha3 diff --git a/pkg/cluster/config/v1alpha1/register.go b/pkg/cluster/config/v1alpha3/register.go similarity index 94% rename from pkg/cluster/config/v1alpha1/register.go rename to pkg/cluster/config/v1alpha3/register.go index 01b71cf72f..e7a4e322f2 100644 --- a/pkg/cluster/config/v1alpha1/register.go +++ b/pkg/cluster/config/v1alpha3/register.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1alpha1 +package v1alpha3 import ( "k8s.io/apimachinery/pkg/runtime" @@ -26,7 +26,7 @@ const GroupName = "kind.sigs.k8s.io" var ( // SchemeGroupVersion is group version used to register these objects. - SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha3"} // SchemeBuilder is a type to collect functions that add data to an API // object through a scheme. SchemeBuilder runtime.SchemeBuilder @@ -45,7 +45,7 @@ func init() { func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, - &Config{}, + &Cluster{}, ) return nil diff --git a/pkg/cluster/config/v1alpha3/types.go b/pkg/cluster/config/v1alpha3/types.go new file mode 100644 index 0000000000..783e2af74b --- /dev/null +++ b/pkg/cluster/config/v1alpha3/types.go @@ -0,0 +1,84 @@ +/* +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 v1alpha3 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "sigs.k8s.io/kind/pkg/container/cri" + "sigs.k8s.io/kind/pkg/kustomize" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Cluster contains kind cluster configuration +type Cluster struct { + // TypeMeta representing the type of the object and its API schema version. + metav1.TypeMeta `json:",inline"` + + // Nodes contains the list of nodes defined in the `kind` Cluster + // If unset this will default to a single control-plane node + // Note that if more than one control plane is specified, an external + // control plane load balancer will be provisioned implicitly + Nodes []Node `json:"nodes"` + + /* Advanced fields */ + + // KubeadmConfigPatches are applied to the generated kubeadm config as + // strategic merge patches to `kustomize build` internally + // https://github.com/kubernetes/community/blob/master/contributors/devel/strategic-merge-patch.md + // This should be an inline yaml blob-string + KubeadmConfigPatches []string `json:"kubeadmConfigPatches,omitempty"` + + // KubeadmConfigPatchesJSON6902 are applied to the generated kubeadm config + // as patchesJson6902 to `kustomize build` + KubeadmConfigPatchesJSON6902 []kustomize.PatchJSON6902 `json:"kubeadmConfigPatchesJson6902,omitempty"` +} + +// Node contains settings for a node in the `kind` Cluster. +// A node in kind config represent a container that will be provisioned with all the components +// required for the assigned role in the Kubernetes cluster +type Node struct { + // Role defines the role of the node in the in the Kubernetes cluster + // created by kind + // + // Defaults to "control-plane" + Role NodeRole `json:"role,omitempty"` + + // Image is the node image to use when creating this node + // If unset a default image will be used, see defaults.Image + Image string `json:"image,omitempty"` + + /* Advanced fields */ + + // ExtraMounts describes additional mount points for the node container + // These may be used to bind a hostPath + ExtraMounts []cri.Mount `json:"extraMounts,omitempty"` +} + +// NodeRole defines possible role for nodes in a Kubernetes cluster managed by `kind` +type NodeRole string + +const ( + // ControlPlaneRole identifies a node that hosts a Kubernetes control-plane. + // NOTE: in single node clusters, control-plane nodes act also as a worker + // nodes, in which case the taint will be removed. see: + // https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#control-plane-node-isolation + ControlPlaneRole NodeRole = "control-plane" + // WorkerRole identifies a node that hosts a Kubernetes worker + WorkerRole NodeRole = "worker" +) diff --git a/pkg/cluster/config/v1alpha3/zz_generated.conversion.go b/pkg/cluster/config/v1alpha3/zz_generated.conversion.go new file mode 100644 index 0000000000..b136c8af6e --- /dev/null +++ b/pkg/cluster/config/v1alpha3/zz_generated.conversion.go @@ -0,0 +1,109 @@ +// +build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + unsafe "unsafe" + + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + config "sigs.k8s.io/kind/pkg/cluster/config" + cri "sigs.k8s.io/kind/pkg/container/cri" + kustomize "sigs.k8s.io/kind/pkg/kustomize" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*Cluster)(nil), (*config.Cluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_Cluster_To_config_Cluster(a.(*Cluster), b.(*config.Cluster), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.Cluster)(nil), (*Cluster)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_Cluster_To_v1alpha3_Cluster(a.(*config.Cluster), b.(*Cluster), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*Node)(nil), (*config.Node)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_Node_To_config_Node(a.(*Node), b.(*config.Node), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*config.Node)(nil), (*Node)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_config_Node_To_v1alpha3_Node(a.(*config.Node), b.(*Node), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1alpha3_Cluster_To_config_Cluster(in *Cluster, out *config.Cluster, s conversion.Scope) error { + out.Nodes = *(*[]config.Node)(unsafe.Pointer(&in.Nodes)) + out.KubeadmConfigPatches = *(*[]string)(unsafe.Pointer(&in.KubeadmConfigPatches)) + out.KubeadmConfigPatchesJSON6902 = *(*[]kustomize.PatchJSON6902)(unsafe.Pointer(&in.KubeadmConfigPatchesJSON6902)) + return nil +} + +// Convert_v1alpha3_Cluster_To_config_Cluster is an autogenerated conversion function. +func Convert_v1alpha3_Cluster_To_config_Cluster(in *Cluster, out *config.Cluster, s conversion.Scope) error { + return autoConvert_v1alpha3_Cluster_To_config_Cluster(in, out, s) +} + +func autoConvert_config_Cluster_To_v1alpha3_Cluster(in *config.Cluster, out *Cluster, s conversion.Scope) error { + out.Nodes = *(*[]Node)(unsafe.Pointer(&in.Nodes)) + out.KubeadmConfigPatches = *(*[]string)(unsafe.Pointer(&in.KubeadmConfigPatches)) + out.KubeadmConfigPatchesJSON6902 = *(*[]kustomize.PatchJSON6902)(unsafe.Pointer(&in.KubeadmConfigPatchesJSON6902)) + return nil +} + +// Convert_config_Cluster_To_v1alpha3_Cluster is an autogenerated conversion function. +func Convert_config_Cluster_To_v1alpha3_Cluster(in *config.Cluster, out *Cluster, s conversion.Scope) error { + return autoConvert_config_Cluster_To_v1alpha3_Cluster(in, out, s) +} + +func autoConvert_v1alpha3_Node_To_config_Node(in *Node, out *config.Node, s conversion.Scope) error { + out.Role = config.NodeRole(in.Role) + out.Image = in.Image + out.ExtraMounts = *(*[]cri.Mount)(unsafe.Pointer(&in.ExtraMounts)) + return nil +} + +// Convert_v1alpha3_Node_To_config_Node is an autogenerated conversion function. +func Convert_v1alpha3_Node_To_config_Node(in *Node, out *config.Node, s conversion.Scope) error { + return autoConvert_v1alpha3_Node_To_config_Node(in, out, s) +} + +func autoConvert_config_Node_To_v1alpha3_Node(in *config.Node, out *Node, s conversion.Scope) error { + out.Role = NodeRole(in.Role) + out.Image = in.Image + out.ExtraMounts = *(*[]cri.Mount)(unsafe.Pointer(&in.ExtraMounts)) + return nil +} + +// Convert_config_Node_To_v1alpha3_Node is an autogenerated conversion function. +func Convert_config_Node_To_v1alpha3_Node(in *config.Node, out *Node, s conversion.Scope) error { + return autoConvert_config_Node_To_v1alpha3_Node(in, out, s) +} diff --git a/pkg/cluster/config/v1alpha3/zz_generated.deepcopy.go b/pkg/cluster/config/v1alpha3/zz_generated.deepcopy.go new file mode 100644 index 0000000000..f213e50811 --- /dev/null +++ b/pkg/cluster/config/v1alpha3/zz_generated.deepcopy.go @@ -0,0 +1,90 @@ +// +build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha3 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + cri "sigs.k8s.io/kind/pkg/container/cri" + kustomize "sigs.k8s.io/kind/pkg/kustomize" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Cluster) DeepCopyInto(out *Cluster) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.Nodes != nil { + in, out := &in.Nodes, &out.Nodes + *out = make([]Node, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.KubeadmConfigPatches != nil { + in, out := &in.KubeadmConfigPatches, &out.KubeadmConfigPatches + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.KubeadmConfigPatchesJSON6902 != nil { + in, out := &in.KubeadmConfigPatchesJSON6902, &out.KubeadmConfigPatchesJSON6902 + *out = make([]kustomize.PatchJSON6902, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Cluster. +func (in *Cluster) DeepCopy() *Cluster { + if in == nil { + return nil + } + out := new(Cluster) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Cluster) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Node) DeepCopyInto(out *Node) { + *out = *in + if in.ExtraMounts != nil { + in, out := &in.ExtraMounts, &out.ExtraMounts + *out = make([]cri.Mount, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Node. +func (in *Node) DeepCopy() *Node { + if in == nil { + return nil + } + out := new(Node) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/cluster/config/v1alpha1/zz_generated.default.go b/pkg/cluster/config/v1alpha3/zz_generated.default.go similarity index 78% rename from pkg/cluster/config/v1alpha1/zz_generated.default.go rename to pkg/cluster/config/v1alpha3/zz_generated.default.go index b4e44773db..5c91b177be 100644 --- a/pkg/cluster/config/v1alpha1/zz_generated.default.go +++ b/pkg/cluster/config/v1alpha3/zz_generated.default.go @@ -18,7 +18,7 @@ limitations under the License. // Code generated by defaulter-gen. DO NOT EDIT. -package v1alpha1 +package v1alpha3 import ( runtime "k8s.io/apimachinery/pkg/runtime" @@ -28,10 +28,14 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&Config{}, func(obj interface{}) { SetObjectDefaults_Config(obj.(*Config)) }) + scheme.AddTypeDefaultingFunc(&Cluster{}, func(obj interface{}) { SetObjectDefaults_Cluster(obj.(*Cluster)) }) return nil } -func SetObjectDefaults_Config(in *Config) { - SetDefaults_Config(in) +func SetObjectDefaults_Cluster(in *Cluster) { + SetDefaults_Cluster(in) + for i := range in.Nodes { + a := &in.Nodes[i] + SetDefaults_Node(a) + } } diff --git a/pkg/cluster/config/validate.go b/pkg/cluster/config/validate.go index 9c3d49eb3b..c2a93506d1 100644 --- a/pkg/cluster/config/validate.go +++ b/pkg/cluster/config/validate.go @@ -24,7 +24,7 @@ import ( // Validate returns a ConfigErrors with an entry for each problem // with the config, or nil if there are none -func (c *Config) Validate() error { +func (c *Cluster) Validate() error { errs := []error{} numByRole := make(map[NodeRole]int32) @@ -35,14 +35,10 @@ func (c *Config) Validate() error { errs = append(errs, errors.Errorf("invalid configuration for node %d: %v", i, err)) } // update role count - replicas := int32(1) - if n.Replicas != nil { - replicas = *n.Replicas - } if num, ok := numByRole[n.Role]; ok { - numByRole[n.Role] = replicas + num + numByRole[n.Role] = 1 + num } else { - numByRole[n.Role] = replicas + numByRole[n.Role] = 1 } } @@ -52,23 +48,6 @@ func (c *Config) Validate() error { errs = append(errs, errors.Errorf("must have at least one %s node", string(ControlPlaneRole))) } - // there may not be more than one load balancer - numLoadBlancer, _ := numByRole[ExternalLoadBalancerRole] - if numLoadBlancer > 1 { - errs = append(errs, errors.Errorf("only one %s node is supported", string(ExternalLoadBalancerRole))) - } - - // there must be a load balancer if there are multiple control planes - if numControlPlane > 1 && numLoadBlancer != 1 { - errs = append(errs, errors.Errorf("%d > 1 %s nodes requires a %s node", numControlPlane, string(ControlPlaneRole), string(ExternalLoadBalancerRole))) - } - - // external-etcd is not actually supported yet - numExternalEtcd, _ := numByRole[ExternalEtcdRole] - if numExternalEtcd > 0 { - errs = append(errs, errors.Errorf("multi node support is still a work in progress, currently %s node is not supported", string(ExternalEtcdRole))) - } - if len(errs) > 0 { return util.NewErrors(errs) } @@ -83,9 +62,7 @@ func (n *Node) Validate() error { // validate node role should be one of the expected values switch n.Role { case ControlPlaneRole, - WorkerRole, - ExternalEtcdRole, - ExternalLoadBalancerRole: + WorkerRole: default: errs = append(errs, errors.Errorf("%q is not a valid node role", n.Role)) } @@ -95,11 +72,6 @@ func (n *Node) Validate() error { errs = append(errs, errors.New("image is a required field")) } - // replicas >= 0 - if n.Replicas != nil && int32(*n.Replicas) < 0 { - errs = append(errs, errors.New("replicas number should not be a negative number")) - } - if len(errs) > 0 { return util.NewErrors(errs) } diff --git a/pkg/cluster/config/zz_generated.deepcopy.go b/pkg/cluster/config/zz_generated.deepcopy.go index 61e53d3b3d..9db23d90f1 100644 --- a/pkg/cluster/config/zz_generated.deepcopy.go +++ b/pkg/cluster/config/zz_generated.deepcopy.go @@ -27,7 +27,7 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Config) DeepCopyInto(out *Config) { +func (in *Cluster) DeepCopyInto(out *Cluster) { *out = *in out.TypeMeta = in.TypeMeta if in.Nodes != nil { @@ -37,21 +37,31 @@ func (in *Config) DeepCopyInto(out *Config) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.KubeadmConfigPatches != nil { + in, out := &in.KubeadmConfigPatches, &out.KubeadmConfigPatches + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.KubeadmConfigPatchesJSON6902 != nil { + in, out := &in.KubeadmConfigPatchesJSON6902, &out.KubeadmConfigPatchesJSON6902 + *out = make([]kustomize.PatchJSON6902, len(*in)) + copy(*out, *in) + } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config. -func (in *Config) DeepCopy() *Config { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Cluster. +func (in *Cluster) DeepCopy() *Cluster { if in == nil { return nil } - out := new(Config) + out := new(Cluster) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Config) DeepCopyObject() runtime.Object { +func (in *Cluster) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -61,21 +71,6 @@ func (in *Config) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Node) DeepCopyInto(out *Node) { *out = *in - if in.Replicas != nil { - in, out := &in.Replicas, &out.Replicas - *out = new(int32) - **out = **in - } - if in.KubeadmConfigPatches != nil { - in, out := &in.KubeadmConfigPatches, &out.KubeadmConfigPatches - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.KubeadmConfigPatchesJSON6902 != nil { - in, out := &in.KubeadmConfigPatchesJSON6902, &out.KubeadmConfigPatchesJSON6902 - *out = make([]kustomize.PatchJSON6902, len(*in)) - copy(*out, *in) - } if in.ExtraMounts != nil { in, out := &in.ExtraMounts, &out.ExtraMounts *out = make([]cri.Mount, len(*in)) diff --git a/pkg/cluster/config/zz_generated.default.go b/pkg/cluster/config/zz_generated.default.go index a3d34f360e..8172293afb 100644 --- a/pkg/cluster/config/zz_generated.default.go +++ b/pkg/cluster/config/zz_generated.default.go @@ -28,12 +28,12 @@ import ( // Public to allow building arbitrary schemes. // All generated defaulters are covering - they call all nested defaulters. func RegisterDefaults(scheme *runtime.Scheme) error { - scheme.AddTypeDefaultingFunc(&Config{}, func(obj interface{}) { SetObjectDefaults_Config(obj.(*Config)) }) + scheme.AddTypeDefaultingFunc(&Cluster{}, func(obj interface{}) { SetObjectDefaults_Cluster(obj.(*Cluster)) }) return nil } -func SetObjectDefaults_Config(in *Config) { - SetDefaults_Config(in) +func SetObjectDefaults_Cluster(in *Cluster) { + SetDefaults_Cluster(in) for i := range in.Nodes { a := &in.Nodes[i] SetDefaults_Node(a) diff --git a/pkg/cluster/context.go b/pkg/cluster/context.go index 569958d857..d41dd03f0f 100644 --- a/pkg/cluster/context.go +++ b/pkg/cluster/context.go @@ -70,7 +70,7 @@ func (c *Context) KubeConfigPath() string { } // Create provisions and starts a kubernetes-in-docker cluster -func (c *Context) Create(cfg *config.Config, options ...create.ClusterOption) error { +func (c *Context) Create(cfg *config.Cluster, options ...create.ClusterOption) error { // apply create options opts := &internalcreate.Options{} for _, option := range options { diff --git a/pkg/cluster/internal/create/actions/action.go b/pkg/cluster/internal/create/actions/action.go index aa6874d9f7..29fb76b549 100644 --- a/pkg/cluster/internal/create/actions/action.go +++ b/pkg/cluster/internal/create/actions/action.go @@ -34,14 +34,14 @@ type Action interface { // ActionContext is data supplied to all actions type ActionContext struct { Status *logutil.Status - Config *config.Config + Config *config.Cluster ClusterContext *context.Context cache *cachedData } // NewActionContext returns a new ActionContext func NewActionContext( - cfg *config.Config, + cfg *config.Cluster, ctx *context.Context, status *logutil.Status, ) *ActionContext { diff --git a/pkg/cluster/internal/create/actions/config/config.go b/pkg/cluster/internal/create/actions/config/config.go index 04b66b41ef..b4200ce4f0 100644 --- a/pkg/cluster/internal/create/actions/config/config.go +++ b/pkg/cluster/internal/create/actions/config/config.go @@ -98,7 +98,7 @@ func (a *Action) Execute(ctx *actions.ActionContext) error { // getKubeadmConfig generates the kubeadm config contents for the cluster // by running data through the template. -func getKubeadmConfig(cfg *config.Config, data kubeadm.ConfigData) (path string, err error) { +func getKubeadmConfig(cfg *config.Cluster, data kubeadm.ConfigData) (path string, err error) { // generate the config contents config, err := kubeadm.Config(data) if err != nil { @@ -114,12 +114,8 @@ func getKubeadmConfig(cfg *config.Config, data kubeadm.ConfigData) (path string, return kustomize.Build([]string{config}, patches, jsonPatches) } -func allPatchesFromConfig(cfg *config.Config) (patches []string, jsonPatches []kustomize.PatchJSON6902) { - for _, node := range cfg.Nodes { - patches = append(patches, node.KubeadmConfigPatches...) - jsonPatches = append(jsonPatches, node.KubeadmConfigPatchesJSON6902...) - } - return patches, jsonPatches +func allPatchesFromConfig(cfg *config.Cluster) (patches []string, jsonPatches []kustomize.PatchJSON6902) { + return cfg.KubeadmConfigPatches, cfg.KubeadmConfigPatchesJSON6902 } // setPatchNames sets the targeted object name on every patch to be the fixed diff --git a/pkg/cluster/internal/create/create.go b/pkg/cluster/internal/create/create.go index 8483db78eb..d6bc402435 100644 --- a/pkg/cluster/internal/create/create.go +++ b/pkg/cluster/internal/create/create.go @@ -47,7 +47,7 @@ type Options struct { } // Cluster creates a cluster -func Cluster(ctx *context.Context, cfg *config.Config, opts *Options) error { +func Cluster(ctx *context.Context, cfg *config.Cluster, opts *Options) error { // default config fields (important for usage as a library, where the config // may be constructed in memory rather than from disk) encoding.Scheme.Default(cfg) diff --git a/pkg/cluster/internal/create/images.go b/pkg/cluster/internal/create/images.go index e2e624c33e..071607d55c 100644 --- a/pkg/cluster/internal/create/images.go +++ b/pkg/cluster/internal/create/images.go @@ -29,7 +29,7 @@ import ( // ensureNodeImages ensures that the node images used by the create // configuration are present -func ensureNodeImages(status *logutil.Status, cfg *config.Config) { +func ensureNodeImages(status *logutil.Status, cfg *config.Cluster) { // pull each required image for _, image := range requiredImages(cfg).List() { // prints user friendly message @@ -45,7 +45,7 @@ func ensureNodeImages(status *logutil.Status, cfg *config.Config) { } // requiredImages returns the set of images specified by the config -func requiredImages(cfg *config.Config) sets.String { +func requiredImages(cfg *config.Cluster) sets.String { images := sets.NewString() for _, node := range cfg.Nodes { images.Insert(node.Image) diff --git a/pkg/cluster/internal/create/nodes.go b/pkg/cluster/internal/create/nodes.go index 7808ee9e4b..acd097a78c 100644 --- a/pkg/cluster/internal/create/nodes.go +++ b/pkg/cluster/internal/create/nodes.go @@ -63,19 +63,11 @@ func makeRoleToOrder(roleOrder []string) func(string) int { } } -// TODO(bentheelder): eliminate this when we have v1alpha3 -func convertReplicas(nodes []config.Node) []config.Node { - out := []config.Node{} - for _, node := range nodes { - replicas := int32(1) - if node.Replicas != nil { - replicas = *node.Replicas - } - for i := int32(0); i < replicas; i++ { - outNode := node.DeepCopy() - outNode.Replicas = nil - out = append(out, *outNode) - } +// returns a deep copy of a slice of config nodes +func copyConfigNodes(toCopy []config.Node) []config.Node { + out := make([]config.Node, len(toCopy)) + for i, node := range toCopy { + out[i] = *node.DeepCopy() } return out } @@ -83,7 +75,7 @@ func convertReplicas(nodes []config.Node) []config.Node { // provisionNodes takes care of creating all the containers // that will host `kind` nodes func provisionNodes( - status *logutil.Status, cfg *config.Config, clusterName, clusterLabel string, + status *logutil.Status, cfg *config.Cluster, clusterName, clusterLabel string, ) error { defer status.End(false) @@ -97,7 +89,7 @@ func provisionNodes( } func createNodeContainers( - status *logutil.Status, cfg *config.Config, clusterName, clusterLabel string, + status *logutil.Status, cfg *config.Cluster, clusterName, clusterLabel string, ) ([]nodes.Node, error) { defer status.End(false) @@ -186,21 +178,34 @@ type nodeSpec struct { ExtraMounts []cri.Mount } -func nodesToCreate(cfg *config.Config, clusterName string) []nodeSpec { +func nodesToCreate(cfg *config.Cluster, clusterName string) []nodeSpec { desiredNodes := []nodeSpec{} // nodes are named based on the cluster name and their role, with a counter nameNode := makeNodeNamer(clusterName) - // convert replicas to normal nodes - // TODO(bentheelder): eliminate this when we have v1alpha3 ? - configNodes := convertReplicas(cfg.Nodes) - + // copy and sort config nodes // TODO(bentheelder): allow overriding defaultRoleOrder + configNodes := copyConfigNodes(cfg.Nodes) sortNodes(configNodes, defaultRoleOrder) + // we will use these two values to determine if / how to setup the + // external control plane load balancer + controlPlanes := 0 + controlPlaneImage := "" + // add all of the config nodes as desired nodes for _, configNode := range configNodes { role := string(configNode.Role) + // keep track of control planes for the load balancer + if role == constants.ControlPlaneNodeRoleValue { + controlPlanes++ + // TODO(bentheelder): instead of keeping the first image, we + // should have a config field that controls this image, and use + // that with defaulting + if controlPlaneImage == "" { + controlPlaneImage = configNode.Image + } + } desiredNodes = append(desiredNodes, nodeSpec{ Name: nameNode(role), Image: configNode.Image, @@ -209,7 +214,16 @@ func nodesToCreate(cfg *config.Config, clusterName string) []nodeSpec { }) } - // TODO(bentheelder): handle implicit nodes as well + // add an external load balancer if there are multiple control planes + if controlPlanes > 1 { + role := constants.ExternalLoadBalancerNodeRoleValue + desiredNodes = append(desiredNodes, nodeSpec{ + Name: nameNode(role), + Image: controlPlaneImage, // TODO(bentheelder): get from config instead + Role: role, + ExtraMounts: []cri.Mount{}, + }) + } return desiredNodes } diff --git a/pkg/cluster/nodes/create.go b/pkg/cluster/nodes/create.go index 797114ac2d..6c748e782a 100644 --- a/pkg/cluster/nodes/create.go +++ b/pkg/cluster/nodes/create.go @@ -22,7 +22,6 @@ import ( "os" "github.com/pkg/errors" - "sigs.k8s.io/kind/pkg/cluster/config" "sigs.k8s.io/kind/pkg/cluster/constants" "sigs.k8s.io/kind/pkg/cluster/internal/haproxy" "sigs.k8s.io/kind/pkg/cluster/internal/kubeadm" @@ -59,7 +58,7 @@ func CreateControlPlaneNode(name, image, clusterLabel string, mounts []cri.Mount } node, err = createNode( - name, image, clusterLabel, config.ControlPlaneRole, mounts, + name, image, clusterLabel, constants.ControlPlaneNodeRoleValue, mounts, // publish selected port for the API server "--expose", fmt.Sprintf("%d", port), "-p", fmt.Sprintf("%d:%d", port, kubeadm.APIServerPort), @@ -85,7 +84,7 @@ func CreateExternalLoadBalancerNode(name, image, clusterLabel string) (node *Nod return nil, errors.Wrap(err, "failed to get port for control-plane load balancer") } - node, err = createNode(name, image, clusterLabel, config.ExternalLoadBalancerRole, + node, err = createNode(name, image, clusterLabel, constants.ExternalLoadBalancerNodeRoleValue, nil, // publish selected port for the control plane "--expose", fmt.Sprintf("%d", port), @@ -105,7 +104,7 @@ func CreateExternalLoadBalancerNode(name, image, clusterLabel string) (node *Nod // CreateWorkerNode creates a worker node func CreateWorkerNode(name, image, clusterLabel string, mounts []cri.Mount) (node *Node, err error) { - node, err = createNode(name, image, clusterLabel, config.WorkerRole, mounts) + node, err = createNode(name, image, clusterLabel, constants.WorkerNodeRoleValue, mounts) if err != nil { return node, err } @@ -116,7 +115,7 @@ func CreateWorkerNode(name, image, clusterLabel string, mounts []cri.Mount) (nod // createNode `docker run`s the node image, note that due to // images/node/entrypoint being the entrypoint, this container will // effectively be paused until we call actuallyStartNode(...) -func createNode(name, image, clusterLabel string, role config.NodeRole, mounts []cri.Mount, extraArgs ...string) (handle *Node, err error) { +func createNode(name, image, clusterLabel, role string, mounts []cri.Mount, extraArgs ...string) (handle *Node, err error) { runArgs := []string{ "-d", // run the container detached // running containers in a container requires privileged