diff --git a/Gopkg.lock b/Gopkg.lock index 1aa25c4221..57e0fe4ddb 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -697,14 +697,6 @@ pruneopts = "NUT" revision = "3a9b63ab1e397dc12a9764df998f99bc59dfd9ae" -[[projects]] - branch = "master" - digest = "1:ff54706d46de40c865b5fcfc4bde1087c02510cd12e0150de8e405ab427d9907" - name = "k8s.io/utils" - packages = ["pointer"] - pruneopts = "NUT" - revision = "0d26856f57b32ec3398579285e5c8a2bfe8c5243" - [[projects]] branch = "master" digest = "1:9dbda414956b2af5c2e24cbc54074ed7158902912bde8c0a0ec7f7344a309720" @@ -773,7 +765,6 @@ "k8s.io/code-generator/cmd/conversion-gen", "k8s.io/code-generator/cmd/deepcopy-gen", "k8s.io/code-generator/cmd/defaulter-gen", - "k8s.io/utils/pointer", "sigs.k8s.io/kustomize/k8sdeps", "sigs.k8s.io/kustomize/pkg/commands/build", "sigs.k8s.io/kustomize/pkg/fs", diff --git a/Gopkg.toml b/Gopkg.toml index 319d882178..c1d3fb5374 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -52,7 +52,3 @@ required = [ name = "k8s.io/code-generator" branch = "master" - -[[constraint]] - branch = "master" - name = "k8s.io/utils" diff --git a/cmd/kind/create/cluster/createcluster.go b/cmd/kind/create/cluster/createcluster.go index 2817ea8972..8769595c48 100644 --- a/cmd/kind/create/cluster/createcluster.go +++ b/cmd/kind/create/cluster/createcluster.go @@ -74,18 +74,10 @@ func runE(flags *flagpole, cmd *cobra.Command, args []string) error { return fmt.Errorf("aborting due to invalid configuration") } - // TODO(fabrizio pandini): this check is temporary / WIP - // kind v1alpha2 config fully supports multi nodes, but the cluster creation logic implemented in - // pkg/cluster/contex.go does not (yet). - // As soon a multi node support is implemented in pkg/cluster/contex.go, this should go away - if len(cfg.AllReplicas()) > 1 { - return fmt.Errorf("multi node support is still a work in progress, currently only single node cluster are supported") - } - // create a cluster context and create the cluster ctx := cluster.NewContext(flags.Name) if flags.ImageName != "" { - cfg.BootStrapControlPlane().Image = flags.ImageName + cfg.Image = flags.ImageName err := cfg.Validate() if err != nil { log.Errorf("Invalid flags, configuration failed validation: %v", err) diff --git a/pkg/cluster/config/encoding/scheme.go b/pkg/cluster/config/encoding/scheme.go index 3d8ff2acd3..ec4f58fa03 100644 --- a/pkg/cluster/config/encoding/scheme.go +++ b/pkg/cluster/config/encoding/scheme.go @@ -48,42 +48,56 @@ func AddToScheme(scheme *runtime.Scheme) { utilruntime.Must(scheme.SetVersionPriority(v1alpha2.SchemeGroupVersion)) } +// newDefaultedConfig creates a new, defaulted `kind` Config +// Defaulting uses Scheme registered defaulting functions +func newDefaultedConfig() *config.Config { + var cfg = &v1alpha2.Config{} + + // apply defaults + Scheme.Default(cfg) + + // converts to internal cfg + var internalCfg = &config.Config{} + Scheme.Convert(cfg, internalCfg, nil) + + return internalCfg +} + +// unmarshalConfig attempt to decode data into a `kind` Config; data can be +// one of the different API versions defined in the Scheme. +func unmarshalConfig(data []byte) (*config.Config, error) { + var cfg = &v1alpha2.Config{} + + // decode data into a config object + _, _, err := Codecs.UniversalDecoder().Decode(data, nil, cfg) + if err != nil { + return nil, errors.Wrap(err, "decoding failure") + } + + // apply defaults + Scheme.Default(cfg) + + // converts to internal cfg + var internalCfg = &config.Config{} + Scheme.Convert(cfg, internalCfg, nil) + + return internalCfg, nil +} + // 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{} - - if path != "" { - // read in file - contents, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - - // decode data into a internal api Config object because - // to leverage on conversion functions for all the api versions - var cfg = &config.Config{} - err = runtime.DecodeInto(Codecs.UniversalDecoder(), contents, cfg) - if err != nil { - return nil, errors.Wrap(err, "decoding failure") - } - - // converts back to the latest API version to apply defaults - Scheme.Convert(cfg, latestPublicConfig, nil) + if path == "" { + return newDefaultedConfig(), nil } - // apply defaults - Scheme.Default(latestPublicConfig) - - // converts to internal config - var cfg = &config.Config{} - Scheme.Convert(latestPublicConfig, cfg, nil) - - if err := cfg.DeriveInfo(); err != nil { + // read in file + contents, err := ioutil.ReadFile(path) + if err != nil { return nil, err } // unmarshal the file content into a `kind` Config - return cfg, nil + return unmarshalConfig(contents) } diff --git a/pkg/cluster/config/encoding/scheme_test.go b/pkg/cluster/config/encoding/scheme_test.go index 6d98e2fd6e..c3c8f4d68d 100644 --- a/pkg/cluster/config/encoding/scheme_test.go +++ b/pkg/cluster/config/encoding/scheme_test.go @@ -17,108 +17,76 @@ limitations under the License. package encoding import ( + "reflect" "testing" ) +// TODO(fabrizio pandini): once we have multiple config API versions we +// will need more tests + func TestLoadCurrent(t *testing.T) { cases := []struct { - TestName string - Path string - ExpectReplicas []string - ExpectError bool + Name string + Path string + ExpectError bool }{ { - TestName: "no config", - Path: "", - 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", - ExpectReplicas: []string{"control-plane"}, - ExpectError: false, + Name: "v1alpha1 valid minimal", + Path: "./testdata/v1alpha1/valid-minimal.yaml", + ExpectError: false, }, { - TestName: "v1alpha2 lifecyclehooks", - Path: "./testdata/v1alpha2/valid-with-lifecyclehooks.yaml", - ExpectReplicas: []string{"control-plane"}, - ExpectError: false, + Name: "v1alpha1 valid with lifecyclehooks", + Path: "./testdata/v1alpha1/valid-with-lifecyclehooks.yaml", + ExpectError: false, }, { - TestName: "v1alpha2 config with 2 nodes", - Path: "./testdata/v1alpha2/valid-minimal-two-nodes.yaml", - ExpectReplicas: []string{"control-plane", "worker"}, - ExpectError: false, + Name: "v1alpha2 valid minimal", + Path: "./testdata/v1alpha2/valid-minimal.yaml", + ExpectError: false, }, { - TestName: "v1alpha2 full HA", - Path: "./testdata/v1alpha2/valid-full-ha.yaml", - ExpectReplicas: []string{"etcd", "lb", "control-plane1", "control-plane2", "control-plane3", "worker1", "worker2"}, - ExpectError: false, + Name: "v1alpha2 valid with lifecyclehooks", + Path: "./testdata/v1alpha2/valid-with-lifecyclehooks.yaml", + ExpectError: false, }, { - TestName: "invalid path", + Name: "invalid path", Path: "./testdata/not-a-file.bogus", ExpectError: true, }, { - TestName: "Invalid apiversion", + Name: "invalid apiVersion", Path: "./testdata/invalid-apiversion.yaml", ExpectError: true, }, { - TestName: "Invalid kind", - Path: "./testdata/invalid-kind.yaml", - ExpectError: true, - }, - { - TestName: "Invalid yaml", + Name: "invalid yaml", Path: "./testdata/invalid-yaml.yaml", ExpectError: true, }, } - for _, c := range cases { - t.Run(c.TestName, func(t2 *testing.T) { - // Loading config and deriving infos - cfg, err := Load(c.Path) - - // the error can be: - // - nil, in which case we should expect no errors or fail - if err != nil { - if !c.ExpectError { - t2.Fatalf("unexpected error while Loading config: %v", err) - } - return - } - // - not nil, in which case we should expect errors or fail - if err == nil { - if c.ExpectError { - t2.Fatalf("unexpected lack or error while Loading config") - } - } - - if len(cfg.AllReplicas()) != len(c.ExpectReplicas) { - t2.Fatalf("expected %d replicas, saw %d", len(c.ExpectReplicas), len(cfg.AllReplicas())) - } + for _, tc := range cases { + _, err := Load(tc.Path) + if err != nil && !tc.ExpectError { + t.Errorf("case: '%s' got error loading and expected none: %v", tc.Name, err) + } else if err == nil && tc.ExpectError { + t.Errorf("case: '%s' got no error loading but expected one", tc.Name) + } + } +} - for i, name := range c.ExpectReplicas { - if cfg.AllReplicas()[i].Name != name { - t2.Errorf("expected %q node at position %d, saw %q", name, i, cfg.AllReplicas()[i].Name) - } - } - }) +func TestLoadDefault(t *testing.T) { + cfg, err := Load("") + if err != nil { + t.Errorf("got error loading default config but expected none: %v", err) + t.FailNow() + } + defaultConfig := newDefaultedConfig() + if !reflect.DeepEqual(cfg, defaultConfig) { + t.Errorf( + "Load(\"\") should match config.New() but does not: %v != %v", + cfg, defaultConfig, + ) } } diff --git a/pkg/cluster/config/encoding/testdata/invalid-apiversion.yaml b/pkg/cluster/config/encoding/testdata/invalid-apiversion.yaml index b5f797a633..9f08271ed8 100644 --- a/pkg/cluster/config/encoding/testdata/invalid-apiversion.yaml +++ b/pkg/cluster/config/encoding/testdata/invalid-apiversion.yaml @@ -1,3 +1,3 @@ # this file contains an invalid config api version for testing -kind: Node +kind: Config apiVersion: not-valid diff --git a/pkg/cluster/config/encoding/testdata/invalid-kind.yaml b/pkg/cluster/config/encoding/testdata/invalid-kind.yaml deleted file mode 100644 index 6f58a2c941..0000000000 --- a/pkg/cluster/config/encoding/testdata/invalid-kind.yaml +++ /dev/null @@ -1,3 +0,0 @@ -# this file contains an invalid config kind for testing -kind: not-valid -apiVersion: kind.sigs.k8s.io/v1alpha2 \ No newline at end of file diff --git a/pkg/cluster/config/encoding/testdata/v1alpha2/valid-full-ha.yaml b/pkg/cluster/config/encoding/testdata/v1alpha2/valid-full-ha.yaml deleted file mode 100644 index 38507f7b77..0000000000 --- a/pkg/cluster/config/encoding/testdata/v1alpha2/valid-full-ha.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# technically valid, config file with a full ha cluster -kind: Config -apiVersion: kind.sigs.k8s.io/v1alpha2 -nodes: -- role: control-plane - replicas: 3 -- role: worker - replicas: 2 -- role: external-etcd -- role: external-load-balancer diff --git a/pkg/cluster/config/encoding/testdata/v1alpha2/valid-minimal-two-nodes.yaml b/pkg/cluster/config/encoding/testdata/v1alpha2/valid-minimal-two-nodes.yaml deleted file mode 100644 index 44704c330e..0000000000 --- a/pkg/cluster/config/encoding/testdata/v1alpha2/valid-minimal-two-nodes.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# technically valid, minimal config file with two nodes -kind: Config -apiVersion: kind.sigs.k8s.io/v1alpha2 -nodes: -- role: control-plane -- role: worker \ No newline at end of file diff --git a/pkg/cluster/config/encoding/testdata/v1alpha2/valid-with-lifecyclehooks.yaml b/pkg/cluster/config/encoding/testdata/v1alpha2/valid-with-lifecyclehooks.yaml index 13ed32c209..5b1521ddbf 100644 --- a/pkg/cluster/config/encoding/testdata/v1alpha2/valid-with-lifecyclehooks.yaml +++ b/pkg/cluster/config/encoding/testdata/v1alpha2/valid-with-lifecyclehooks.yaml @@ -1,9 +1,8 @@ kind: Config apiVersion: kind.sigs.k8s.io/v1alpha2 -nodes: -- nodeLifecycle: - preKubeadm: - - name: "pull an image" - command: [ "docker", "pull", "ubuntu" ] - - name: "pull another image" - command: [ "docker", "pull", "debian" ] \ No newline at end of file +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 c31a243bbb..4eae9a09f8 100644 --- a/pkg/cluster/config/fuzzer/fuzzer.go +++ b/pkg/cluster/config/fuzzer/fuzzer.go @@ -28,24 +28,12 @@ import ( func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { return []interface{}{ fuzzConfig, - //fuzzNode, } } func fuzzConfig(obj *config.Config, c fuzz.Continue) { c.FuzzNoCustom(obj) - // Pinning values for fields that get defaults if fuzz value is empty string or nil - obj.Nodes = []config.Node{{ - Image: "foo:bar", - Role: config.ControlPlaneRole, - }} -} - -func fuzzNode(obj *config.Node, c fuzz.Continue) { - c.FuzzNoCustom(obj) - - // Pinning values for fields that get defaults if fuzz value is empty string or nil - obj.Image = "foo:bar" - obj.Role = config.ControlPlaneRole + // Pinning values for fields that get defaults if fuzz value is empty string or nil (thus making the round trip test fail) + obj.Image = "fuzzimage:latest" } diff --git a/pkg/cluster/config/helpers.go b/pkg/cluster/config/helpers.go deleted file mode 100644 index 1849227c7e..0000000000 --- a/pkg/cluster/config/helpers.go +++ /dev/null @@ -1,229 +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 config - -import ( - "fmt" - "sort" - - "github.com/pkg/errors" -) - -// IsControlPlane returns true if the node hosts a control plane instance -// NB. in single node clusters, control-plane nodes act also as a worker nodes -func (n *Node) IsControlPlane() bool { - return n.Role == ControlPlaneRole -} - -// IsWorker returns true if the node hosts a worker instance -func (n *Node) IsWorker() bool { - return n.Role == WorkerRole -} - -// IsExternalEtcd returns true if the node hosts an external etcd member -func (n *Node) IsExternalEtcd() bool { - return n.Role == ExternalEtcdRole -} - -// IsExternalLoadBalancer returns true if the node hosts an external load balancer -func (n *Node) IsExternalLoadBalancer() bool { - return n.Role == ExternalLoadBalancerRole -} - -// ProvisioningOrder returns the provisioning order for nodes, that -// should be defined according to the assigned NodeRole -func (n *Node) ProvisioningOrder() int { - switch n.Role { - // External dependencies should be provisioned first; we are defining an arbitrary - // precedence between etcd and load balancer in order to get predictable/repeatable results - case ExternalEtcdRole: - return 1 - case ExternalLoadBalancerRole: - return 2 - // Then control plane nodes - case ControlPlaneRole: - return 3 - // Finally workers - case WorkerRole: - return 4 - default: - return 99 - } -} - -// Len of the NodeList. -// It is required for making NodeList sortable. -func (t ReplicaList) Len() int { - return len(t) -} - -// Less return the lower between two elements of the NodeList, where the -// lower element should be provisioned before the other. -// It is required for making NodeList sortable. -func (t ReplicaList) Less(i, j int) bool { - return t[i].ProvisioningOrder() < t[j].ProvisioningOrder() || - // In case of same provisioning order, the name is used to get predictable/repeatable results - (t[i].ProvisioningOrder() == t[j].ProvisioningOrder() && t[i].Name < t[j].Name) -} - -// Swap two elements of the NodeList. -// It is required for making NodeList sortable. -func (t ReplicaList) Swap(i, j int) { - t[i], t[j] = t[j], t[i] -} - -// DeriveInfo populates DerivedConfig info starting -// from the current list on Nodes -func (c *Config) DeriveInfo() error { - for _, n := range c.Nodes { - if err := c.Add(&n); err != nil { - return err - } - } - return nil -} - -// Add a Node to the `kind` cluster, generating requested node replicas -// and assigning a unique node name to each replica. -func (c *Config) Add(node *Node) error { - - // Creates the list of node replicas - expectedReplicas := 1 - if node.Replicas != nil { - expectedReplicas = int(*node.Replicas) - } - - replicas := ReplicaList{} - for i := 1; i <= expectedReplicas; i++ { - replica := &NodeReplica{ - Node: *node.DeepCopy(), - } - replica.Replicas = nil // resetting the replicas number for each replica to default (1) - - replicas = append(replicas, replica) - } - - // adds replica to the config unpdating derivedConfigData - for _, replica := range replicas { - - // adds the replica to the list of nodes - c.allReplicas = append(c.allReplicas, replica) - - // list of nodes with control plane role - if replica.IsControlPlane() { - // assign selected name for control plane node - replica.Name = "control-plane" - // stores the node in derivedConfigData - c.controlPlanes = append(c.controlPlanes, replica) - } - - // list of nodes with worker role - if replica.IsWorker() { - // assign selected name for worker node - replica.Name = "worker" - // stores the node in derivedConfigData - c.workers = append(c.workers, replica) - } - - // node with external etcd role - if replica.IsExternalEtcd() { - if c.externalEtcd != nil { - return errors.Errorf("invalid config. there are two nodes with role %q", ExternalEtcdRole) - } - // assign selected name for etcd node - replica.Name = "etcd" - // stores the node in derivedConfigData - c.externalEtcd = replica - } - - // node with external load balancer role - if replica.IsExternalLoadBalancer() { - if c.externalLoadBalancer != nil { - return errors.Errorf("invalid config. there are two nodes with role %q", ExternalLoadBalancerRole) - } - // assign selected name for load balancer node - replica.Name = "lb" - // stores the node in derivedConfigData - c.externalLoadBalancer = replica - } - - } - - // if more than one control plane node exists, fixes names to get a progressive index - if len(c.controlPlanes) > 1 { - for i, n := range c.controlPlanes { - n.Name = fmt.Sprintf("%s%d", "control-plane", i+1) - } - } - - // if more than one worker node exists, fixes names to get a progressive index - if len(c.workers) > 1 { - for i, n := range c.workers { - n.Name = fmt.Sprintf("%s%d", "worker", i+1) - } - } - - // ensure the list of nodes is ordered. - // the ordering is key for getting a consistent and predictable behaviour - // when provisioning nodes and when executing actions on nodes - sort.Sort(c.allReplicas) - - return nil -} - -// AllReplicas returns all the node replicas defined in the `kind` Config. -func (c *Config) AllReplicas() ReplicaList { - return c.allReplicas -} - -// ControlPlanes returns all the nodes with control-plane role -func (c *Config) ControlPlanes() ReplicaList { - return c.controlPlanes -} - -// BootStrapControlPlane returns the first node with control-plane role -// This is the node where kubeadm init will be executed. -func (c *Config) BootStrapControlPlane() *NodeReplica { - if len(c.controlPlanes) == 0 { - return nil - } - return c.controlPlanes[0] -} - -// SecondaryControlPlanes returns all the nodes with control-plane role -// except the BootStrapControlPlane node, if any, -func (c *Config) SecondaryControlPlanes() ReplicaList { - if len(c.controlPlanes) <= 1 { - return nil - } - return c.controlPlanes[1:] -} - -// Workers returns all the nodes with Worker role, if any -func (c *Config) Workers() ReplicaList { - return c.workers -} - -// ExternalEtcd returns the node with external-etcd role, if defined -func (c *Config) ExternalEtcd() *NodeReplica { - return c.externalEtcd -} - -// ExternalLoadBalancer returns the node with external-load-balancer role, if defined -func (c *Config) ExternalLoadBalancer() *NodeReplica { - return c.externalLoadBalancer -} diff --git a/pkg/cluster/config/helpers_test.go b/pkg/cluster/config/helpers_test.go deleted file mode 100644 index 0f1b5d17ac..0000000000 --- a/pkg/cluster/config/helpers_test.go +++ /dev/null @@ -1,185 +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 config - -import ( - "testing" - - utilpointer "k8s.io/utils/pointer" -) - -func TestDeriveInfo(t *testing.T) { - cases := []struct { - TestName string - Nodes []Node - ExpectReplicas []string - ExpectControlPlanes []string - ExpectBootStrapControlPlane *string - ExpectSecondaryControlPlanes []string - ExpectWorkers []string - ExpectEtcd *string - ExpectLoadBalancer *string - ExpectError bool - }{ - { - TestName: "Defaults/Empty config should give empty replicas", - ExpectReplicas: nil, - ExpectControlPlanes: nil, - ExpectBootStrapControlPlane: nil, - ExpectSecondaryControlPlanes: nil, - ExpectWorkers: nil, - ExpectEtcd: nil, - ExpectLoadBalancer: nil, - ExpectError: false, - }, - { - TestName: "Single control plane Node get properly assigned to bootstrap control-plane", - Nodes: []Node{ - {Role: ControlPlaneRole}, - }, - ExpectReplicas: []string{"control-plane"}, - ExpectControlPlanes: []string{"control-plane"}, - ExpectBootStrapControlPlane: utilpointer.StringPtr("control-plane"), - ExpectSecondaryControlPlanes: nil, - ExpectError: false, - }, - { - TestName: "Control planes Nodes get properly splitted between bootstrap and secondary control-planes", - Nodes: []Node{ - {Role: ControlPlaneRole, Replicas: utilpointer.Int32Ptr(3)}, - }, - ExpectReplicas: []string{"control-plane1", "control-plane2", "control-plane3"}, - ExpectControlPlanes: []string{"control-plane1", "control-plane2", "control-plane3"}, - ExpectBootStrapControlPlane: utilpointer.StringPtr("control-plane1"), - ExpectSecondaryControlPlanes: []string{"control-plane2", "control-plane3"}, - ExpectError: false, - }, - { - TestName: "Full HA cluster", // NB. This test case test that provisioning order is applied to all the node lists as well - Nodes: []Node{ - {Role: WorkerRole}, - {Role: ControlPlaneRole}, - {Role: ExternalEtcdRole}, - {Role: ControlPlaneRole}, - {Role: WorkerRole}, - {Role: ControlPlaneRole}, - {Role: ExternalLoadBalancerRole}, - }, - ExpectReplicas: []string{"etcd", "lb", "control-plane1", "control-plane2", "control-plane3", "worker1", "worker2"}, - ExpectControlPlanes: []string{"control-plane1", "control-plane2", "control-plane3"}, - ExpectBootStrapControlPlane: utilpointer.StringPtr("control-plane1"), - ExpectSecondaryControlPlanes: []string{"control-plane2", "control-plane3"}, - ExpectWorkers: []string{"worker1", "worker2"}, - ExpectEtcd: utilpointer.StringPtr("etcd"), - ExpectLoadBalancer: utilpointer.StringPtr("lb"), - ExpectError: false, - }, - { - TestName: "Full HA cluster with replicas", - Nodes: []Node{ - {Role: WorkerRole, Replicas: utilpointer.Int32Ptr(2)}, - {Role: ControlPlaneRole, Replicas: utilpointer.Int32Ptr(3)}, - {Role: ExternalEtcdRole}, - {Role: ExternalLoadBalancerRole}, - }, - ExpectReplicas: []string{"etcd", "lb", "control-plane1", "control-plane2", "control-plane3", "worker1", "worker2"}, - ExpectControlPlanes: []string{"control-plane1", "control-plane2", "control-plane3"}, - ExpectBootStrapControlPlane: utilpointer.StringPtr("control-plane1"), - ExpectSecondaryControlPlanes: []string{"control-plane2", "control-plane3"}, - ExpectWorkers: []string{"worker1", "worker2"}, - ExpectEtcd: utilpointer.StringPtr("etcd"), - ExpectLoadBalancer: utilpointer.StringPtr("lb"), - ExpectError: false, - }, - { - TestName: "Fails because two etcds Nodes are added", - Nodes: []Node{ - {Role: ExternalEtcdRole}, - {Role: ExternalEtcdRole}, - }, - ExpectError: true, - }, - { - TestName: "Fails because two load balancer Nodes are added", - Nodes: []Node{ - {Role: ExternalLoadBalancerRole}, - {Role: ExternalLoadBalancerRole}, - }, - ExpectError: true, - }, - } - - for _, c := range cases { - t.Run(c.TestName, func(t2 *testing.T) { - // Adding Nodes to the config and deriving infos - var cfg = Config{Nodes: c.Nodes} - err := cfg.DeriveInfo() - // the error can be: - // - nil, in which case we should expect no errors or fail - if err != nil { - if !c.ExpectError { - t2.Fatalf("unexpected error while Deriving infos: %v", err) - } - return - } - // - not nil, in which case we should expect errors or fail - if err == nil { - if c.ExpectError { - t2.Fatalf("unexpected lack or error while Deriving infos") - } - } - - // Fail if Nodes does not match - checkReplicaList(t2, cfg.AllReplicas(), c.ExpectReplicas) - - // Fail if fields derived from Nodes does not match - checkReplicaList(t2, cfg.ControlPlanes(), c.ExpectControlPlanes) - checkNode(t2, cfg.BootStrapControlPlane(), c.ExpectBootStrapControlPlane) - checkReplicaList(t2, cfg.SecondaryControlPlanes(), c.ExpectSecondaryControlPlanes) - checkReplicaList(t2, cfg.Workers(), c.ExpectWorkers) - checkNode(t2, cfg.ExternalEtcd(), c.ExpectEtcd) - checkNode(t2, cfg.ExternalLoadBalancer(), c.ExpectLoadBalancer) - }) - } -} - -func checkNode(t *testing.T, n *NodeReplica, name *string) { - if (n == nil) != (name == nil) { - t.Errorf("expected %v node, saw %v", name, n) - } - - if n == nil { - return - } - - if n.Name != *name { - t.Errorf("expected %v node, saw %v", name, n.Name) - } -} - -func checkReplicaList(t *testing.T, list ReplicaList, names []string) { - if len(list) != len(names) { - t.Errorf("expected %d nodes, saw %d", len(names), len(list)) - return - } - - for i, name := range names { - if list[i].Name != name { - t.Errorf("expected %q node at position %d, saw %q", name, i, list[i].Name) - } - } -} diff --git a/pkg/cluster/config/register.go b/pkg/cluster/config/register.go index fef52b593f..bb1cb78497 100644 --- a/pkg/cluster/config/register.go +++ b/pkg/cluster/config/register.go @@ -36,6 +36,16 @@ var ( AddToScheme = localSchemeBuilder.AddToScheme ) +// Kind takes an unqualified kind and returns a Group qualified GroupKind. +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + func init() { // We only register manually written functions here. The registration of the // generated functions takes place in the generated files. The separation diff --git a/pkg/cluster/config/types.go b/pkg/cluster/config/types.go index 096e302c11..f0a7113c53 100644 --- a/pkg/cluster/config/types.go +++ b/pkg/cluster/config/types.go @@ -23,36 +23,12 @@ import ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Config groups all nodes in the `kind` Config. +// Config contains cluster creation config +// This is the current internal config type used by cluster +// Other API versions can be converted to this struct with Convert() type Config struct { - // TypeMeta representing the type of the object and its API schema version. metav1.TypeMeta - // Nodes constains the list of nodes defined in the `kind` Config - Nodes []Node `json:"nodes,"` - - // DerivedConfigData is struct populated starting from the node list. - // It contains a set of "materialized views" generated starting from nodes - // and designed to make easy operating nodes in the rest of the code base. - // This attribute exists only in the internal config version and is meant - // to simplify the usage of the config in the code base. - // TODO(fabrizio pandini): as soon as possible this should became an - // internal of the kind library and be removed from the config - // +k8s:conversion-gen=false - DerivedConfigData -} - -// 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 nodw 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 @@ -68,24 +44,6 @@ type Node struct { ControlPlane *ControlPlane } -// 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 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. - // 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. - // Please note that `kind` nodes hosting external load balancer are not kubernetes nodes - ExternalLoadBalancerRole NodeRole = "external-load-balancer" -) - // ControlPlane holds configurations specific to the control plane nodes // (currently the only node). type ControlPlane struct { @@ -117,46 +75,3 @@ type LifecycleHook struct { // the boot process will continue MustSucceed bool } - -// +k8s:conversion-gen=false - -// NodeReplica defines a `kind` config Node that is geneated by creating a replicas for a node -// This attribute exists only in the internal config version and is meant -// to simplify the usage of the config in the code base. -type NodeReplica struct { - // Node contains settings for the node in the `kind` Config. - // please note that the Replicas number is alway set to nil. - Node - - // Name contains the unique name assigned to the node while generating the replica - Name string -} - -// +k8s:conversion-gen=false - -// ReplicaList defines a list of NodeReplicas in the `kind` Config -// This attribute exists only in the internal config version and is meant -// to simplify the usage of the config in the code base. -type ReplicaList []*NodeReplica - -// +k8s:conversion-gen=false - -// DerivedConfigData is a struct populated starting from the nodes list. -// All the field of this type are intentionally defined a private fields, thus ensuring -// that derivedConfigData will have a predictable behaviour for the code built on top. -// This attribute exists only in the internal config version and is meant -// to simplify the usage of the config in the code base. -type DerivedConfigData struct { - // allReplicas constains the list of node replicas defined in the `kind` Config - allReplicas ReplicaList - // controlPlanes contains the subset of node replicas with control-plane role - controlPlanes ReplicaList - // workers contains the subset of node replicas with worker role, if any - workers ReplicaList - // externalEtcd contains the node replica with external-etcd role, if defined - // TODO(fabriziopandini): eventually in future we would like to support - // external etcd clusters with more than one member - externalEtcd *NodeReplica - // externalLoadBalancer contains the node replica with external-load-balancer role, if defined - externalLoadBalancer *NodeReplica -} diff --git a/pkg/cluster/config/v1alpha1/conversion.go b/pkg/cluster/config/v1alpha1/conversion.go deleted file mode 100644 index cea60b9cee..0000000000 --- a/pkg/cluster/config/v1alpha1/conversion.go +++ /dev/null @@ -1,72 +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 ( - "fmt" - unsafe "unsafe" - - 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)) - node.ControlPlane = (*config.ControlPlane)(unsafe.Pointer(in.ControlPlane)) - - 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 - } - - // convertion 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 fmt.Errorf("invalid conversion. `kind` config with more than one Node cannot be converted to v1alpha1 config format") - } - - var node = in.Nodes[0] - - if !node.IsControlPlane() { - return fmt.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)) - out.ControlPlane = (*ControlPlane)(unsafe.Pointer(node.ControlPlane)) - - return nil -} diff --git a/pkg/cluster/config/v1alpha1/register.go b/pkg/cluster/config/v1alpha1/register.go index 01b71cf72f..caabb403ab 100644 --- a/pkg/cluster/config/v1alpha1/register.go +++ b/pkg/cluster/config/v1alpha1/register.go @@ -36,6 +36,16 @@ var ( AddToScheme = localSchemeBuilder.AddToScheme ) +// Kind takes an unqualified kind and returns a Group qualified GroupKind. +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + func init() { // We only register manually written functions here. The registration of the // generated functions takes place in the generated files. The separation diff --git a/pkg/cluster/config/v1alpha1/zz_generated.conversion.go b/pkg/cluster/config/v1alpha1/zz_generated.conversion.go index dff2e73a5c..f2b35f698a 100644 --- a/pkg/cluster/config/v1alpha1/zz_generated.conversion.go +++ b/pkg/cluster/config/v1alpha1/zz_generated.conversion.go @@ -26,6 +26,7 @@ import ( conversion "k8s.io/apimachinery/pkg/conversion" runtime "k8s.io/apimachinery/pkg/runtime" config "sigs.k8s.io/kind/pkg/cluster/config" + kustomize "sigs.k8s.io/kind/pkg/kustomize" ) func init() { @@ -75,33 +76,35 @@ func RegisterConversions(s *runtime.Scheme) error { }); 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 + out.Image = in.Image + out.KubeadmConfigPatches = *(*[]string)(unsafe.Pointer(&in.KubeadmConfigPatches)) + out.KubeadmConfigPatchesJSON6902 = *(*[]kustomize.PatchJSON6902)(unsafe.Pointer(&in.KubeadmConfigPatchesJSON6902)) + out.ControlPlane = (*config.ControlPlane)(unsafe.Pointer(in.ControlPlane)) return nil } +// Convert_v1alpha1_Config_To_config_Config is an autogenerated conversion function. +func Convert_v1alpha1_Config_To_config_Config(in *Config, out *config.Config, s conversion.Scope) error { + return autoConvert_v1alpha1_Config_To_config_Config(in, out, s) +} + 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 - // INFO: in.DerivedConfigData opted out of conversion generation + out.Image = in.Image + out.KubeadmConfigPatches = *(*[]string)(unsafe.Pointer(&in.KubeadmConfigPatches)) + out.KubeadmConfigPatchesJSON6902 = *(*[]kustomize.PatchJSON6902)(unsafe.Pointer(&in.KubeadmConfigPatchesJSON6902)) + out.ControlPlane = (*ControlPlane)(unsafe.Pointer(in.ControlPlane)) return nil } +// Convert_config_Config_To_v1alpha1_Config is an autogenerated conversion function. +func Convert_config_Config_To_v1alpha1_Config(in *config.Config, out *Config, s conversion.Scope) error { + return autoConvert_config_Config_To_v1alpha1_Config(in, out, s) +} + func autoConvert_v1alpha1_ControlPlane_To_config_ControlPlane(in *ControlPlane, out *config.ControlPlane, s conversion.Scope) error { out.NodeLifecycle = (*config.NodeLifecycle)(unsafe.Pointer(in.NodeLifecycle)) return nil diff --git a/pkg/cluster/config/v1alpha2/default.go b/pkg/cluster/config/v1alpha2/default.go index b969166664..d41d7c0a00 100644 --- a/pkg/cluster/config/v1alpha2/default.go +++ b/pkg/cluster/config/v1alpha2/default.go @@ -30,23 +30,7 @@ func addDefaultingFuncs(scheme *runtime.Scheme) error { // SetDefaults_Config sets uninitialized fields to their default value. func SetDefaults_Config(obj *Config) { - if len(obj.Nodes) == 0 { - obj.Nodes = []Node{ - { - Image: DefaultImage, - Role: ControlPlaneRole, - }, - } - } -} - -// SetDefaults_Node sets uninitialized fields to their default value. -func SetDefaults_Node(obj *Node) { if obj.Image == "" { obj.Image = DefaultImage } - - if obj.Role == "" { - obj.Role = ControlPlaneRole - } } diff --git a/pkg/cluster/config/v1alpha2/register.go b/pkg/cluster/config/v1alpha2/register.go index dbab5a1ab6..b985435d5d 100644 --- a/pkg/cluster/config/v1alpha2/register.go +++ b/pkg/cluster/config/v1alpha2/register.go @@ -36,6 +36,16 @@ var ( AddToScheme = localSchemeBuilder.AddToScheme ) +// Kind takes an unqualified kind and returns a Group qualified GroupKind. +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + func init() { // We only register manually written functions here. The registration of the // generated functions takes place in the generated files. The separation diff --git a/pkg/cluster/config/v1alpha2/types.go b/pkg/cluster/config/v1alpha2/types.go index 0bf6d0e919..be5937f60d 100644 --- a/pkg/cluster/config/v1alpha2/types.go +++ b/pkg/cluster/config/v1alpha2/types.go @@ -23,25 +23,11 @@ import ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// Config groups all nodes in the `kind` Config. +// Config contains cluster creation config +// This is the current internal config type used by cluster type Config struct { - // TypeMeta representing the type of the object and its API schema version. - metav1.TypeMeta `json:",inline"` + metav1.TypeMeta - // nodes constains the list of nodes defined in the `kind` Config - Nodes []Node `json:"nodes"` -} - -// 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 -type Node struct { - // Replicas is the number of desired node replicas. - // Defaults to 1 - Replicas *int32 `json:"replicas,omitempty"` - // Role defines the role of the nodw in the in the Kubernetes cluster managed by `kind` - // 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? Image string `json:"image,omitempty"` @@ -57,24 +43,6 @@ type Node struct { ControlPlane *ControlPlane `json:"ControlPlane,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. - // NB. in single node clusters, control-plane nodes act also as a worker nodes - 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. - // 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. - // Please note that `kind` nodes hosting external load balancer are not kubernetes nodes - ExternalLoadBalancerRole NodeRole = "external-load-balancer" -) - // ControlPlane holds configurations specific to the control plane nodes // (currently the only node). type ControlPlane struct { diff --git a/pkg/cluster/config/v1alpha2/zz_generated.conversion.go b/pkg/cluster/config/v1alpha2/zz_generated.conversion.go index b30b5515fb..ab004cf311 100644 --- a/pkg/cluster/config/v1alpha2/zz_generated.conversion.go +++ b/pkg/cluster/config/v1alpha2/zz_generated.conversion.go @@ -66,16 +66,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); 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) - }); 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_v1alpha2_Node(a.(*config.Node), b.(*Node), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*NodeLifecycle)(nil), (*config.NodeLifecycle)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha2_NodeLifecycle_To_config_NodeLifecycle(a.(*NodeLifecycle), b.(*config.NodeLifecycle), scope) }); err != nil { @@ -90,7 +80,10 @@ func RegisterConversions(s *runtime.Scheme) error { } func autoConvert_v1alpha2_Config_To_config_Config(in *Config, out *config.Config, s conversion.Scope) error { - out.Nodes = *(*[]config.Node)(unsafe.Pointer(&in.Nodes)) + out.Image = in.Image + out.KubeadmConfigPatches = *(*[]string)(unsafe.Pointer(&in.KubeadmConfigPatches)) + out.KubeadmConfigPatchesJSON6902 = *(*[]kustomize.PatchJSON6902)(unsafe.Pointer(&in.KubeadmConfigPatchesJSON6902)) + out.ControlPlane = (*config.ControlPlane)(unsafe.Pointer(in.ControlPlane)) return nil } @@ -100,8 +93,10 @@ func Convert_v1alpha2_Config_To_config_Config(in *Config, out *config.Config, s } func autoConvert_config_Config_To_v1alpha2_Config(in *config.Config, out *Config, s conversion.Scope) error { - out.Nodes = *(*[]Node)(unsafe.Pointer(&in.Nodes)) - // INFO: in.DerivedConfigData opted out of conversion generation + out.Image = in.Image + out.KubeadmConfigPatches = *(*[]string)(unsafe.Pointer(&in.KubeadmConfigPatches)) + out.KubeadmConfigPatchesJSON6902 = *(*[]kustomize.PatchJSON6902)(unsafe.Pointer(&in.KubeadmConfigPatchesJSON6902)) + out.ControlPlane = (*ControlPlane)(unsafe.Pointer(in.ControlPlane)) return nil } @@ -154,36 +149,6 @@ func Convert_config_LifecycleHook_To_v1alpha2_LifecycleHook(in *config.Lifecycle return autoConvert_config_LifecycleHook_To_v1alpha2_LifecycleHook(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)) - 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)) - out.ControlPlane = (*config.ControlPlane)(unsafe.Pointer(in.ControlPlane)) - 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.ControlPlane = (*ControlPlane)(unsafe.Pointer(in.ControlPlane)) - 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) -} - func autoConvert_v1alpha2_NodeLifecycle_To_config_NodeLifecycle(in *NodeLifecycle, out *config.NodeLifecycle, s conversion.Scope) error { out.PreBoot = *(*[]config.LifecycleHook)(unsafe.Pointer(&in.PreBoot)) out.PreKubeadm = *(*[]config.LifecycleHook)(unsafe.Pointer(&in.PreKubeadm)) diff --git a/pkg/cluster/config/v1alpha2/zz_generated.deepcopy.go b/pkg/cluster/config/v1alpha2/zz_generated.deepcopy.go index 5d41f916eb..08cc10d471 100644 --- a/pkg/cluster/config/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/cluster/config/v1alpha2/zz_generated.deepcopy.go @@ -29,12 +29,20 @@ import ( func (in *Config) DeepCopyInto(out *Config) { *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) + } + if in.ControlPlane != nil { + in, out := &in.ControlPlane, &out.ControlPlane + *out = new(ControlPlane) + (*in).DeepCopyInto(*out) } return } @@ -99,42 +107,6 @@ func (in *LifecycleHook) DeepCopy() *LifecycleHook { return out } -// 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.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 Node. -func (in *Node) DeepCopy() *Node { - if in == nil { - return nil - } - out := new(Node) - 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 diff --git a/pkg/cluster/config/v1alpha2/zz_generated.default.go b/pkg/cluster/config/v1alpha2/zz_generated.default.go index 175007271e..54567365ae 100644 --- a/pkg/cluster/config/v1alpha2/zz_generated.default.go +++ b/pkg/cluster/config/v1alpha2/zz_generated.default.go @@ -34,8 +34,4 @@ func RegisterDefaults(scheme *runtime.Scheme) error { func SetObjectDefaults_Config(in *Config) { SetDefaults_Config(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 93cdd84a02..87773a5e5d 100644 --- a/pkg/cluster/config/validate.go +++ b/pkg/cluster/config/validate.go @@ -26,58 +26,12 @@ import ( // with the config, or nil if there are none func (c *Config) Validate() error { errs := []error{} - - // All nodes in the config should be valid - for i, n := range c.Nodes { - if err := n.Validate(); err != nil { - errs = append(errs, fmt.Errorf("please fix invalid configuration for node %d: \n%v", i, err)) - } - } - - // There should be at least one control plane - if c.BootStrapControlPlane() == nil { - errs = append(errs, fmt.Errorf("please add at least one node with role %q", ControlPlaneRole)) - } - // There should be one load balancer if more than one control plane exists in the cluster - if len(c.ControlPlanes()) > 1 && c.ExternalLoadBalancer() == nil { - errs = append(errs, fmt.Errorf("please add a node with role %s because in the cluster there are more than one node with role %s", ExternalLoadBalancerRole, ControlPlaneRole)) - } - - if len(errs) > 0 { - return util.NewErrors(errs) - } - return nil -} - -// Validate returns a ConfigErrors with an entry for each problem -// with the Node, or nil if there are none -func (n *Node) Validate() error { - errs := []error{} - - // validate node role should be one of the expected values - switch n.Role { - case ControlPlaneRole, - WorkerRole, - ExternalEtcdRole, - ExternalLoadBalancerRole: - default: - errs = append(errs, fmt.Errorf("role is a required field")) - } - - // image should be defined - if n.Image == "" { + if c.Image == "" { errs = append(errs, fmt.Errorf("image is a required field")) } - - // replicas >= 0 - if n.Replicas != nil && int32(*n.Replicas) < 0 { - errs = append(errs, fmt.Errorf("replicas number should not be a negative number")) - } - - // validate NodeLifecycle - if n.ControlPlane != nil { - if n.ControlPlane.NodeLifecycle != nil { - for _, hook := range n.ControlPlane.NodeLifecycle.PreBoot { + if c.ControlPlane != nil { + if c.ControlPlane.NodeLifecycle != nil { + for _, hook := range c.ControlPlane.NodeLifecycle.PreBoot { if len(hook.Command) == 0 { errs = append(errs, fmt.Errorf( "preBoot hooks must set command to a non-empty value", @@ -87,7 +41,7 @@ func (n *Node) Validate() error { break } } - for _, hook := range n.ControlPlane.NodeLifecycle.PreKubeadm { + for _, hook := range c.ControlPlane.NodeLifecycle.PreKubeadm { if len(hook.Command) == 0 { errs = append(errs, fmt.Errorf( "preKubeadm hooks must set command to a non-empty value", @@ -97,7 +51,7 @@ func (n *Node) Validate() error { break } } - for _, hook := range n.ControlPlane.NodeLifecycle.PostKubeadm { + for _, hook := range c.ControlPlane.NodeLifecycle.PostKubeadm { if len(hook.Command) == 0 { errs = append(errs, fmt.Errorf( "postKubeadm hooks must set command to a non-empty value", @@ -107,7 +61,7 @@ func (n *Node) Validate() error { break } } - for _, hook := range n.ControlPlane.NodeLifecycle.PostSetup { + for _, hook := range c.ControlPlane.NodeLifecycle.PostSetup { if len(hook.Command) == 0 { errs = append(errs, fmt.Errorf( "postKubeadm hooks must set command to a non-empty value", @@ -122,6 +76,5 @@ func (n *Node) Validate() error { if len(errs) > 0 { return util.NewErrors(errs) } - return nil } diff --git a/pkg/cluster/config/validate_test.go b/pkg/cluster/config/validate_test.go index e0c92f55fc..5d359fd7d0 100644 --- a/pkg/cluster/config/validate_test.go +++ b/pkg/cluster/config/validate_test.go @@ -23,29 +23,29 @@ import ( ) // TODO(fabriziopandini): ideally this should use scheme.Default, but this creates a circular dependency -// So the current solution is to mimic defaulting for the validation test -func newDefaultedNode(role NodeRole) Node { - return Node{ - Role: role, +// So the current solution is to mimic defaulting for the validation test, but probably there should be a better solution here +func newDefaultedConfig() *Config { + cfg := &Config{ Image: "myImage:latest", } + return cfg } -func TestNodeValidate(t *testing.T) { +func TestConfigValidate(t *testing.T) { cases := []struct { - TestName string - Node Node - ExpectErrors int + TestName string + Config *Config + ExpectedErrors int }{ { - TestName: "Canonical node", - Node: newDefaultedNode(ControlPlaneRole), - ExpectErrors: 0, + TestName: "Canonical config", + Config: newDefaultedConfig(), + ExpectedErrors: 0, }, { TestName: "Invalid PreBoot hook", - Node: func() Node { - cfg := newDefaultedNode(ControlPlaneRole) + Config: func() *Config { + cfg := newDefaultedConfig() cfg.ControlPlane = &ControlPlane{ NodeLifecycle: &NodeLifecycle{ PreBoot: []LifecycleHook{ @@ -57,12 +57,12 @@ func TestNodeValidate(t *testing.T) { } return cfg }(), - ExpectErrors: 1, + ExpectedErrors: 1, }, { TestName: "Invalid PreKubeadm hook", - Node: func() Node { - cfg := newDefaultedNode(ControlPlaneRole) + Config: func() *Config { + cfg := newDefaultedConfig() cfg.ControlPlane = &ControlPlane{ NodeLifecycle: &NodeLifecycle{ PreKubeadm: []LifecycleHook{ @@ -75,12 +75,12 @@ func TestNodeValidate(t *testing.T) { } return cfg }(), - ExpectErrors: 1, + ExpectedErrors: 1, }, { TestName: "Invalid PostKubeadm hook", - Node: func() Node { - cfg := newDefaultedNode(ControlPlaneRole) + Config: func() *Config { + cfg := newDefaultedConfig() cfg.ControlPlane = &ControlPlane{ NodeLifecycle: &NodeLifecycle{ PostKubeadm: []LifecycleHook{ @@ -93,134 +93,39 @@ func TestNodeValidate(t *testing.T) { } return cfg }(), - ExpectErrors: 1, + ExpectedErrors: 1, }, { TestName: "Empty image field", - Node: func() Node { - cfg := newDefaultedNode(ControlPlaneRole) + Config: func() *Config { + cfg := newDefaultedConfig() cfg.Image = "" return cfg }(), - ExpectErrors: 1, - }, - { - TestName: "Empty role field", - Node: func() Node { - cfg := newDefaultedNode(ControlPlaneRole) - cfg.Role = "" - return cfg - }(), - ExpectErrors: 1, - }, - { - TestName: "Unknows role field", - Node: func() Node { - cfg := newDefaultedNode(ControlPlaneRole) - cfg.Role = "ssss" - return cfg - }(), - ExpectErrors: 1, - }, - } - - for _, tc := range cases { - t.Run(tc.TestName, func(t2 *testing.T) { - err := tc.Node.Validate() - // the error can be: - // - nil, in which case we should expect no errors or fail - if err == nil { - if tc.ExpectErrors != 0 { - t2.Error("received no errors but expected errors for case") - } - return - } - // - not castable to *Errors, in which case we have the wrong error type ... - configErrors, ok := err.(util.Errors) - if !ok { - t2.Errorf("config.Validate should only return nil or ConfigErrors{...}, got: %v", err) - return - } - // - ConfigErrors, in which case expect a certain number of errors - errors := configErrors.Errors() - if len(errors) != tc.ExpectErrors { - t2.Errorf("expected %d errors but got len(%v) = %d", tc.ExpectErrors, errors, len(errors)) - } - }) - } -} - -func TestConfigValidate(t *testing.T) { - cases := []struct { - TestName string - Nodes []Node - ExpectErrors int - }{ - { - TestName: "Canonical config", - Nodes: []Node{ - newDefaultedNode(ControlPlaneRole), - }, - }, - { - TestName: "Fail without at least one control plane", - ExpectErrors: 1, - }, - { - TestName: "Fail without at load balancer and more than one control plane", - Nodes: []Node{ - newDefaultedNode(ControlPlaneRole), - newDefaultedNode(ControlPlaneRole), - }, - ExpectErrors: 1, - }, - { - TestName: "Fail with not valid nodes", - Nodes: []Node{ - func() Node { - cfg := newDefaultedNode(ControlPlaneRole) - cfg.Image = "" - return cfg - }(), - func() Node { - cfg := newDefaultedNode(ControlPlaneRole) - cfg.Role = "" - return cfg - }(), - }, - ExpectErrors: 2, + ExpectedErrors: 1, }, } for _, tc := range cases { - t.Run(tc.TestName, func(t2 *testing.T) { - var c = Config{Nodes: tc.Nodes} - if err := c.DeriveInfo(); err != nil { - t.Fatalf("unexpected error while adding nodes: %v", err) - } - - // validating config - err := c.Validate() - - // the error can be: - // - nil, in which case we should expect no errors or fail - if err == nil { - if tc.ExpectErrors != 0 { - t2.Error("received no errors but expected errors") - } - return - } - // - not castable to *Errors, in which case we have the wrong error type ... - configErrors, ok := err.(util.Errors) - if !ok { - t2.Errorf("config.Validate should only return nil or ConfigErrors{...}, got: %v", err) - return - } - // - ConfigErrors, in which case expect a certain number of errors - errors := configErrors.Errors() - if len(errors) != tc.ExpectErrors { - t2.Errorf("expected %d errors but got len(%v) = %d", tc.ExpectErrors, errors, len(errors)) + err := tc.Config.Validate() + // the error can be: + // - nil, in which case we should expect no errors or fail + if err == nil { + if tc.ExpectedErrors != 0 { + t.Errorf("received no errors but expected errors for case %s", tc.TestName) } - }) + continue + } + // - not castable to *Errors, in which case we have the wrong error type ... + configErrors, ok := err.(*util.Errors) + if !ok { + t.Errorf("config.Validate should only return nil or ConfigErrors{...}, got: %v for case: %s", err, tc.TestName) + continue + } + // - ConfigErrors, in which case expect a certain number of errors + errors := configErrors.Errors() + if len(errors) != tc.ExpectedErrors { + t.Errorf("expected %d errors but got len(%v) = %d for case: %s", tc.ExpectedErrors, errors, len(errors), tc.TestName) + } } } diff --git a/pkg/cluster/config/zz_generated.deepcopy.go b/pkg/cluster/config/zz_generated.deepcopy.go index bb06f85865..17bec49089 100644 --- a/pkg/cluster/config/zz_generated.deepcopy.go +++ b/pkg/cluster/config/zz_generated.deepcopy.go @@ -29,14 +29,21 @@ import ( func (in *Config) DeepCopyInto(out *Config) { *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) + } + if in.ControlPlane != nil { + in, out := &in.ControlPlane, &out.ControlPlane + *out = new(ControlPlane) + (*in).DeepCopyInto(*out) } - in.DerivedConfigData.DeepCopyInto(&out.DerivedConfigData) return } @@ -79,65 +86,6 @@ func (in *ControlPlane) DeepCopy() *ControlPlane { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DerivedConfigData) DeepCopyInto(out *DerivedConfigData) { - *out = *in - if in.allReplicas != nil { - in, out := &in.allReplicas, &out.allReplicas - *out = make(ReplicaList, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(NodeReplica) - (*in).DeepCopyInto(*out) - } - } - } - if in.controlPlanes != nil { - in, out := &in.controlPlanes, &out.controlPlanes - *out = make(ReplicaList, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(NodeReplica) - (*in).DeepCopyInto(*out) - } - } - } - if in.workers != nil { - in, out := &in.workers, &out.workers - *out = make(ReplicaList, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(NodeReplica) - (*in).DeepCopyInto(*out) - } - } - } - if in.externalEtcd != nil { - in, out := &in.externalEtcd, &out.externalEtcd - *out = new(NodeReplica) - (*in).DeepCopyInto(*out) - } - if in.externalLoadBalancer != nil { - in, out := &in.externalLoadBalancer, &out.externalLoadBalancer - *out = new(NodeReplica) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DerivedConfigData. -func (in *DerivedConfigData) DeepCopy() *DerivedConfigData { - if in == nil { - return nil - } - out := new(DerivedConfigData) - 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 @@ -159,42 +107,6 @@ func (in *LifecycleHook) DeepCopy() *LifecycleHook { return out } -// 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.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 Node. -func (in *Node) DeepCopy() *Node { - if in == nil { - return nil - } - out := new(Node) - 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 @@ -238,46 +150,3 @@ func (in *NodeLifecycle) DeepCopy() *NodeLifecycle { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NodeReplica) DeepCopyInto(out *NodeReplica) { - *out = *in - in.Node.DeepCopyInto(&out.Node) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeReplica. -func (in *NodeReplica) DeepCopy() *NodeReplica { - if in == nil { - return nil - } - out := new(NodeReplica) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in ReplicaList) DeepCopyInto(out *ReplicaList) { - { - in := &in - *out = make(ReplicaList, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(NodeReplica) - (*in).DeepCopyInto(*out) - } - } - return - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicaList. -func (in ReplicaList) DeepCopy() ReplicaList { - if in == nil { - return nil - } - out := new(ReplicaList) - in.DeepCopyInto(out) - return *out -} diff --git a/pkg/cluster/context.go b/pkg/cluster/context.go index df6e5a28d1..e92f53a3ee 100644 --- a/pkg/cluster/context.go +++ b/pkg/cluster/context.go @@ -142,11 +142,7 @@ func (c *Context) Create(cfg *config.Config, retain bool, wait time.Duration) er cc.status.MaybeWrapLogrus(log.StandardLogger()) defer cc.status.End(false) - - // TODO(fabrizio pandini): usage of BootStrapControlPlane() in this file is temporary / WIP - // kind v1alpha2 config fully supports multi nodes, but the cluster creation logic implemented in - // in this file does not (yet). - image := cfg.BootStrapControlPlane().Image + image := cfg.Image if strings.Contains(image, "@sha256:") { image = strings.Split(image, "@sha256:")[0] } @@ -154,7 +150,7 @@ func (c *Context) Create(cfg *config.Config, retain bool, wait time.Duration) er // attempt to explicitly pull the image if it doesn't exist locally // we don't care if this errors, we'll still try to run which also pulls - _, _ = docker.PullIfNotPresent(cfg.BootStrapControlPlane().Image, 4) + _, _ = docker.PullIfNotPresent(cfg.Image, 4) // TODO(bentheelder): multiple nodes ... kubeadmConfig, err := cc.provisionControlPlane( @@ -215,7 +211,7 @@ func (cc *createContext) provisionControlPlane( ) (kubeadmConfigPath string, err error) { cc.status.Start(fmt.Sprintf("[%s] Creating node container 📦", nodeName)) // create the "node" container (docker run, but it is paused, see createNode) - node, port, err := nodes.CreateControlPlaneNode(nodeName, cc.config.BootStrapControlPlane().Image, cc.ClusterLabel()) + node, port, err := nodes.CreateControlPlaneNode(nodeName, cc.config.Image, cc.ClusterLabel()) if err != nil { return "", err } @@ -238,8 +234,8 @@ func (cc *createContext) provisionControlPlane( } // run any pre-boot hooks - if cc.config.BootStrapControlPlane().ControlPlane != nil && cc.config.BootStrapControlPlane().ControlPlane.NodeLifecycle != nil { - for _, hook := range cc.config.BootStrapControlPlane().ControlPlane.NodeLifecycle.PreBoot { + if cc.config.ControlPlane != nil && cc.config.ControlPlane.NodeLifecycle != nil { + for _, hook := range cc.config.ControlPlane.NodeLifecycle.PreBoot { if err := runHook(node, &hook, "preBoot"); err != nil { return "", err } @@ -305,8 +301,8 @@ func (cc *createContext) provisionControlPlane( } // run any pre-kubeadm hooks - if cc.config.BootStrapControlPlane().ControlPlane != nil && cc.config.BootStrapControlPlane().ControlPlane.NodeLifecycle != nil { - for _, hook := range cc.config.BootStrapControlPlane().ControlPlane.NodeLifecycle.PreKubeadm { + if cc.config.ControlPlane != nil && cc.config.ControlPlane.NodeLifecycle != nil { + for _, hook := range cc.config.ControlPlane.NodeLifecycle.PreKubeadm { if err := runHook(node, &hook, "preKubeadm"); err != nil { return kubeadmConfig, err } @@ -334,8 +330,8 @@ func (cc *createContext) provisionControlPlane( } // run any post-kubeadm hooks - if cc.config.BootStrapControlPlane().ControlPlane != nil && cc.config.BootStrapControlPlane().ControlPlane.NodeLifecycle != nil { - for _, hook := range cc.config.BootStrapControlPlane().ControlPlane.NodeLifecycle.PostKubeadm { + if cc.config.ControlPlane != nil && cc.config.ControlPlane.NodeLifecycle != nil { + for _, hook := range cc.config.ControlPlane.NodeLifecycle.PostKubeadm { if err := runHook(node, &hook, "postKubeadm"); err != nil { return kubeadmConfig, err } @@ -376,8 +372,8 @@ func (cc *createContext) provisionControlPlane( } // run any post-overlay hooks - if cc.config.BootStrapControlPlane().ControlPlane != nil && cc.config.BootStrapControlPlane().ControlPlane.NodeLifecycle != nil { - for _, hook := range cc.config.BootStrapControlPlane().ControlPlane.NodeLifecycle.PostSetup { + if cc.config.ControlPlane != nil && cc.config.ControlPlane.NodeLifecycle != nil { + for _, hook := range cc.config.ControlPlane.NodeLifecycle.PostSetup { if err := runHook(node, &hook, "postSetup"); err != nil { return kubeadmConfig, err } @@ -446,8 +442,8 @@ func (c *Context) createKubeadmConfig(cfg *config.Config, data kubeadm.ConfigDat // apply patches patchedConfig, err := kustomize.Build( []string{config}, - cfg.BootStrapControlPlane().KubeadmConfigPatches, - cfg.BootStrapControlPlane().KubeadmConfigPatchesJSON6902, + cfg.KubeadmConfigPatches, + cfg.KubeadmConfigPatchesJSON6902, ) if err != nil { os.Remove(path) diff --git a/vendor/k8s.io/utils/LICENSE b/vendor/k8s.io/utils/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/vendor/k8s.io/utils/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/vendor/k8s.io/utils/pointer/pointer.go b/vendor/k8s.io/utils/pointer/pointer.go deleted file mode 100644 index a11a540f46..0000000000 --- a/vendor/k8s.io/utils/pointer/pointer.go +++ /dev/null @@ -1,86 +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 pointer - -import ( - "fmt" - "reflect" -) - -// AllPtrFieldsNil tests whether all pointer fields in a struct are nil. This is useful when, -// for example, an API struct is handled by plugins which need to distinguish -// "no plugin accepted this spec" from "this spec is empty". -// -// This function is only valid for structs and pointers to structs. Any other -// type will cause a panic. Passing a typed nil pointer will return true. -func AllPtrFieldsNil(obj interface{}) bool { - v := reflect.ValueOf(obj) - if !v.IsValid() { - panic(fmt.Sprintf("reflect.ValueOf() produced a non-valid Value for %#v", obj)) - } - if v.Kind() == reflect.Ptr { - if v.IsNil() { - return true - } - v = v.Elem() - } - for i := 0; i < v.NumField(); i++ { - if v.Field(i).Kind() == reflect.Ptr && !v.Field(i).IsNil() { - return false - } - } - return true -} - -// Int32Ptr returns a pointer to an int32 -func Int32Ptr(i int32) *int32 { - return &i -} - -// Int64Ptr returns a pointer to an int64 -func Int64Ptr(i int64) *int64 { - return &i -} - -// Int32PtrDerefOr dereference the int32 ptr and returns it i not nil, -// else returns def. -func Int32PtrDerefOr(ptr *int32, def int32) int32 { - if ptr != nil { - return *ptr - } - return def -} - -// BoolPtr returns a pointer to a bool -func BoolPtr(b bool) *bool { - return &b -} - -// StringPtr returns a pointer to the passed string. -func StringPtr(s string) *string { - return &s -} - -// Float32Ptr returns a pointer to the passed float32. -func Float32Ptr(i float32) *float32 { - return &i -} - -// Float64Ptr returns a pointer to the passed float64. -func Float64Ptr(i float64) *float64 { - return &i -}