From 837cc70c63a2c9021865be93c26f2e22b4c5cd08 Mon Sep 17 00:00:00 2001 From: Chuck Ha Date: Thu, 13 Jun 2019 11:47:31 -0400 Subject: [PATCH] Make the version of the nodes configurable Signed-off-by: Chuck Ha --- README.md | 2 +- capkactuators/machine.go | 6 ++-- cmd/capkctl/main.go | 70 ++++++++++++++++++++++++++-------------- cmd/kind-test/main.go | 10 ++++-- kind/actions/kind.go | 29 +++++++++++++---- 5 files changed, 78 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index ba0ec6a..606acd3 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Requires a google cloud project # Testing out CAPK -⚠️Only tested on linux⚠️ +Tested on: Linux, OS X Start a management kind cluster diff --git a/capkactuators/machine.go b/capkactuators/machine.go index 3d66240..dad25ce 100644 --- a/capkactuators/machine.go +++ b/capkactuators/machine.go @@ -72,7 +72,7 @@ func (m *Machine) Create(ctx context.Context, c *clusterv1.Cluster, machine *clu if setValue == constants.ControlPlaneNodeRoleValue { if len(controlPlanes) > 0 { fmt.Println("Adding a control plane") - controlPlaneNode, err := actions.AddControlPlane(c.Name) + controlPlaneNode, err := actions.AddControlPlane(c.Name, machine.Spec.Versions.ControlPlane) if err != nil { fmt.Printf("%+v", err) return err @@ -92,7 +92,7 @@ func (m *Machine) Create(ctx context.Context, c *clusterv1.Cluster, machine *clu fmt.Printf("%+v\n", err) return err } - controlPlaneNode, err := actions.CreateControlPlane(c.Name, lbip) + controlPlaneNode, err := actions.CreateControlPlane(c.Name, lbip, machine.Spec.Versions.ControlPlane) if err != nil { fmt.Printf("%+v", err) return err @@ -122,7 +122,7 @@ func (m *Machine) Create(ctx context.Context, c *clusterv1.Cluster, machine *clu } fmt.Println("Creating a new worker node") - worker, err := actions.AddWorker(c.Name) + worker, err := actions.AddWorker(c.Name, machine.Spec.Versions.Kubelet) if err != nil { fmt.Printf("%+v", err) return err diff --git a/cmd/capkctl/main.go b/cmd/capkctl/main.go index 945d288..5bf4ef1 100644 --- a/cmd/capkctl/main.go +++ b/cmd/capkctl/main.go @@ -17,16 +17,19 @@ limitations under the License. package main import ( + "encoding/json" "flag" "fmt" "io/ioutil" "os" "gitlab.com/chuckh/cluster-api-provider-kind/execer" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1" ) type machineOptions struct { - name, namespace, clusterName, set *string + name, namespace, clusterName, set, version *string } func (mo *machineOptions) initFlags(fs *flag.FlagSet) { @@ -34,6 +37,7 @@ func (mo *machineOptions) initFlags(fs *flag.FlagSet) { mo.namespace = fs.String("namespace", "my-namespace", "The namespece of the machine") mo.clusterName = fs.String("cluster-name", "my-cluster", "The name of the cluster the machine belongs to") mo.set = fs.String("set", "worker", "The role of the machine. Valid entries ['worker', 'control-plane']") + mo.version = fs.String("version", "v1.14.2", "The Kubernetes version to run") } func main() { @@ -76,15 +80,17 @@ func main() { printClusterAPIPlane(*capkImage, *capiImage) case "control-plane": controlPlane.Parse(os.Args[2:]) - fmt.Fprintf(os.Stdout, machineYAML(*controlPlaneOpts.name, *controlPlaneOpts.namespace, *controlPlaneOpts.clusterName, *controlPlaneOpts.set)) + fmt.Fprintf(os.Stdout, machineYAML(controlPlaneOpts)) case "worker": worker.Parse(os.Args[2:]) - fmt.Fprintf(os.Stdout, machineYAML(*workerOpts.name, *workerOpts.namespace, *workerOpts.clusterName, *workerOpts.set)) + fmt.Fprintf(os.Stdout, machineYAML(workerOpts)) case "cluster": cluster.Parse(os.Args[2:]) fmt.Fprintf(os.Stdout, clusterYAML(*clusterName, *clusterNamespace)) + case "help": + fmt.Println(usage()) default: - fmt.Fprintf(os.Stderr, "unknown command: %q\n", os.Args[1]) + fmt.Println(usage()) os.Exit(1) } } @@ -104,10 +110,10 @@ subcommands are: example: capkctl capk -capk-image gcr.io/kubernetes1-226021/capk-manager:latest -capi-image gcr.io/k8s-cluster-api/cluster-api-controller:0.1.2 | kubeclt apply -f - control-plane - Write a capk control plane machine to stdout - example: capkctl control-plane -name my-control-plane -namespace my-namespace -cluster-name my-cluster | kubectl apply -f - + example: capkctl control-plane -name my-control-plane -namespace my-namespace -cluster-name my-cluster -version v1.14.1 | kubectl apply -f - worker - Write a capk worker machine to stdout - example: capkctl worker -name my-worker -namespace my-namespace -cluster-name my-cluster | kubectl apply -f - + example: capkctl worker -name my-worker -namespace my-namespace -cluster-name my-cluster -version 1.14.2 | kubectl apply -f - cluster - Write a capk cluster object to stdout example: capkctl cluster -cluster-name my-cluster -namespace my-namespace | kubectl apply -f - @@ -131,25 +137,39 @@ spec: providerSpec: {}`, name, namespace) } -func machineYAML(name, namespace, cluster, set string) string { - return fmt.Sprintf(`apiVersion: "cluster.k8s.io/v1alpha1" -kind: MachineList -items: - - apiVersion: "cluster.k8s.io/v1alpha1" - kind: Machine - metadata: - name: %s - namespace: %s - labels: - cluster.k8s.io/cluster-name: %s - annotations: - set: %s - spec: - versions: - kubelet: v1.13.6 - controlPlane: v1.13.6 - providerSpec: {} -`, name, namespace, cluster, set) +func machineYAML(opts *machineOptions) string { + machine := v1alpha1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "Machine", + APIVersion: "cluster.k8s.io/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: *opts.name, + Namespace: *opts.namespace, + Labels: map[string]string{ + "cluster.k8s.io/cluster-name": *opts.clusterName, + }, + Annotations: map[string]string{ + "set": *opts.set, + }, + }, + Spec: v1alpha1.MachineSpec{ + ProviderSpec: v1alpha1.ProviderSpec{}, + }, + } + // TODO: 🤔 + if *opts.set == "control-plane" { + machine.Spec.Versions.ControlPlane = *opts.version + } + if *opts.set == "worker" { + machine.Spec.Versions.Kubelet = *opts.version + } + b, err := json.Marshal(machine) + // TODO don't panic on the error + if err != nil { + panic(err) + } + return string(b) } func makeManagementCluster(clusterName string) { diff --git a/cmd/kind-test/main.go b/cmd/kind-test/main.go index 862e2f3..d6759a1 100644 --- a/cmd/kind-test/main.go +++ b/cmd/kind-test/main.go @@ -31,6 +31,7 @@ func main() { reader := bufio.NewReader(os.Stdin) fmt.Println("Here we go!") clusterName := "my-cluster" + version := "v1.14.2" for { // read input text, _ := reader.ReadString('\n') @@ -47,11 +48,11 @@ func main() { if err != nil { panic(fmt.Sprintf("%+v", err)) } - if _, err := actions.CreateControlPlane(clusterName, ip); err != nil { + if _, err := actions.CreateControlPlane(clusterName, ip, version); err != nil { panic(fmt.Sprintf("%+v", err)) } case "add-worker": - if _, err := actions.AddWorker(clusterName); err != nil { + if _, err := actions.AddWorker(clusterName, version); err != nil { panic(fmt.Sprintf("%+v", err)) } case "delete-node": @@ -64,12 +65,15 @@ func main() { panic(fmt.Sprintf("%+v", err)) } case "add-control-plane": - if _, err := actions.AddControlPlane(clusterName); err != nil { + if _, err := actions.AddControlPlane(clusterName, version); err != nil { panic(fmt.Sprintf("%+v", err)) } case "set-cluster-name": fmt.Println("setting cluster name...") clusterName = inputs[1] + case "set-version": + fmt.Println("setting version") + version = inputs[1] default: fmt.Println("Unknown command") } diff --git a/kind/actions/kind.go b/kind/actions/kind.go index fd31bce..d3a2624 100644 --- a/kind/actions/kind.go +++ b/kind/actions/kind.go @@ -25,9 +25,10 @@ import ( "path/filepath" "regexp" + "sigs.k8s.io/kind/pkg/cluster/config/defaults" + "github.com/pkg/errors" "gitlab.com/chuckh/cluster-api-provider-kind/third_party/forked/loadbalancer" - "sigs.k8s.io/kind/pkg/cluster/config/defaults" "sigs.k8s.io/kind/pkg/cluster/constants" "sigs.k8s.io/kind/pkg/cluster/nodes" "sigs.k8s.io/kind/pkg/container/cri" @@ -42,12 +43,13 @@ func KubeConfigPath(clusterName string) string { } // AddControlPlane adds a control plane to a given cluster -func AddControlPlane(clusterName string) (*nodes.Node, error) { +func AddControlPlane(clusterName, version string) (*nodes.Node, error) { clusterLabel := fmt.Sprintf("%s=%s", constants.ClusterLabelKey, clusterName) + kindImage := image(version) // This function exposes a port (makes sense for kind) that is not needed in capk scenarios. controlPlane, err := nodes.CreateControlPlaneNode( getName(clusterName, constants.ControlPlaneNodeRoleValue), - defaults.Image, + kindImage, clusterLabel, "127.0.0.1", 0, @@ -78,12 +80,13 @@ func SetUpLoadBalancer(clusterName string) (*nodes.Node, error) { } // CreateControlPlane is creating the first control plane and configuring the load balancer. -func CreateControlPlane(clusterName, lbip string) (*nodes.Node, error) { +func CreateControlPlane(clusterName, lbip, version string) (*nodes.Node, error) { fmt.Println("Creating control plane node") clusterLabel := fmt.Sprintf("%s=%s", constants.ClusterLabelKey, clusterName) + kindImage := image(version) controlPlaneNode, err := nodes.CreateControlPlaneNode( getName(clusterName, constants.ControlPlaneNodeRoleValue), - defaults.Image, + kindImage, clusterLabel, "127.0.0.1", 0, @@ -113,11 +116,12 @@ func CreateControlPlane(clusterName, lbip string) (*nodes.Node, error) { } // AddWorker adds a worker to a given cluster. -func AddWorker(clusterName string) (*nodes.Node, error) { +func AddWorker(clusterName, version string) (*nodes.Node, error) { clusterLabel := fmt.Sprintf("%s=%s", constants.ClusterLabelKey, clusterName) + kindImage := image(version) worker, err := nodes.CreateWorkerNode( getName(clusterName, constants.WorkerNodeRoleValue), - defaults.Image, + kindImage, clusterLabel, nil, ) @@ -222,3 +226,14 @@ func getName(clusterName, role string) string { } return fmt.Sprintf("%s-%s%s", clusterName, role, suffix) } + +func image(version string) string { + // valid kindest node versions, but only >= v1.14.0 + switch version { + case "v1.14.2": + case "v1.14.1": + case "v1.14.0": + return fmt.Sprintf("kindest/node:", version) + } + return defaults.Image +}