Skip to content

Commit

Permalink
Plumb addon support into clusterctl.
Browse files Browse the repository at this point in the history
  • Loading branch information
roberthbailey committed Jun 21, 2018
1 parent 76577fd commit 094a16b
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 24 deletions.
4 changes: 2 additions & 2 deletions clusterctl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ $ go build
TBD

### Creating a cluster
1. Create a `cluster.yaml`, `machines.yaml` and `provider-components.yaml` files configured for your cluster. See the provider specific templates and generation tools at `$GOPATH/src/sigs.k8s.io/cluster-api/clusterctl/examples/<provider>`.
1. Create the `cluster.yaml`, `machines.yaml`, `provider-components.yaml`, and `addons.yaml` files configured for your cluster. See the provider specific templates and generation tools at `$GOPATH/src/sigs.k8s.io/cluster-api/clusterctl/examples/<provider>`.
2. Create a cluster

```shell
clusterctl create cluster --provider [google/vsphere] -c cluster.yaml -m machines.yaml -p provider-components.yaml
clusterctl create cluster --provider [google/vsphere] -c cluster.yaml -m machines.yaml -p provider-components.yaml -a addons.yaml
```

To choose a specific minikube driver, please use the `--vm-driver` command line parameter. For example to use the kvm2 driver with clusterctl you woud add `--vm-driver kvm2`
Expand Down
29 changes: 15 additions & 14 deletions clusterctl/clusterdeployer/clusterdeployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type ClusterDeployer struct {
clientFactory ClientFactory
provider ProviderDeployer
providerComponents string
addonComponents string
kubeconfigOutput string
cleanupExternalCluster bool
}
Expand All @@ -84,13 +85,15 @@ func New(
clientFactory ClientFactory,
provider ProviderDeployer,
providerComponents string,
addonComponents string,
kubeconfigOutput string,
cleanupExternalCluster bool) *ClusterDeployer {
return &ClusterDeployer{
externalProvisioner: externalProvisioner,
clientFactory: clientFactory,
provider: provider,
providerComponents: providerComponents,
addonComponents: addonComponents,
kubeconfigOutput: kubeconfigOutput,
cleanupExternalCluster: cleanupExternalCluster,
}
Expand All @@ -117,28 +120,24 @@ func (d *ClusterDeployer) Create(cluster *clusterv1.Cluster, machines []*cluster
}()

glog.Info("Applying Cluster API stack to external cluster")
err = d.applyClusterAPIStack(externalClient)
if err != nil {
if err := d.applyClusterAPIStack(externalClient); err != nil {
return fmt.Errorf("unable to apply cluster api stack to external cluster: %v", err)
}

glog.Info("Provisioning internal cluster via external cluster")

glog.Infof("Creating cluster object %v on external cluster", cluster.Name)
err = externalClient.CreateClusterObject(cluster)
if err != nil {
if err := externalClient.CreateClusterObject(cluster); err != nil {
return fmt.Errorf("unable to create cluster object: %v", err)
}

glog.Infof("Creating master %v", master.Name)
err = externalClient.CreateMachineObjects([]*clusterv1.Machine{master})
if err != nil {
if err := externalClient.CreateMachineObjects([]*clusterv1.Machine{master}); err != nil {
return fmt.Errorf("unable to create master machine: %v", err)
}

glog.Infof("Updating external cluster object with master (%s) endpoint", master.Name)
err = d.updateClusterEndpoint(externalClient)
if err != nil {
if err := d.updateClusterEndpoint(externalClient); err != nil {
return fmt.Errorf("unable to update external cluster endpoint: %v", err)
}

Expand All @@ -155,8 +154,7 @@ func (d *ClusterDeployer) Create(cluster *clusterv1.Cluster, machines []*cluster
}()

glog.Info("Applying Cluster API stack to internal cluster")
err = d.applyClusterAPIStackWithPivoting(internalClient, externalClient)
if err != nil {
if err := d.applyClusterAPIStackWithPivoting(internalClient, externalClient); err != nil {
return fmt.Errorf("unable to apply cluster api stack to internal cluster: %v", err)
}

Expand All @@ -169,17 +167,20 @@ func (d *ClusterDeployer) Create(cluster *clusterv1.Cluster, machines []*cluster
// For some reason, endpoint doesn't get updated in external cluster sometimes. So we
// update the internal cluster endpoint as well to be sure.
glog.Infof("Updating internal cluster object with master (%s) endpoint", master.Name)
err = d.updateClusterEndpoint(internalClient)
if err != nil {
if err := d.updateClusterEndpoint(internalClient); err != nil {
return fmt.Errorf("unable to update internal cluster endpoint: %v", err)
}

glog.Info("Creating node machines in internal cluster.")
err = internalClient.CreateMachineObjects(nodes)
if err != nil {
if err := internalClient.CreateMachineObjects(nodes); err != nil {
return fmt.Errorf("unable to create node machines: %v", err)
}

glog.Info("Creating addons in internal cluster.")
if err := internalClient.Apply(d.addonComponents); err != nil {
return fmt.Errorf("unable to apply addons: %v", err)
}

glog.Infof("Done provisioning cluster. You can now access your cluster with kubectl --kubeconfig %v", d.kubeconfigOutput)

return nil
Expand Down
5 changes: 3 additions & 2 deletions clusterctl/clusterdeployer/clusterdeployer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ func TestCreate(t *testing.T) {
inputMachines := generateMachines()
pcStore := mockProviderComponentsStore{}
pcFactory := mockProviderComponentsStoreFactory{NewFromCoreclientsetPCStore: &pcStore}
d := clusterdeployer.New(p, f, pd, "", kubeconfigOut, testcase.cleanupExternal)
d := clusterdeployer.New(p, f, pd, "", "", kubeconfigOut, testcase.cleanupExternal)
err := d.Create(inputCluster, inputMachines, &pcFactory)

// Validate
Expand Down Expand Up @@ -410,7 +410,8 @@ func TestCreateProviderComponentsScenarios(t *testing.T) {
inputMachines := generateMachines()
pcFactory := mockProviderComponentsStoreFactory{NewFromCoreclientsetPCStore: &tc.pcStore}
providerComponentsYaml := "-yaml\ndefinition"
d := clusterdeployer.New(p, f, pd, providerComponentsYaml, kubeconfigOut, false)
addonsYaml := "-yaml\ndefinition"
d := clusterdeployer.New(p, f, pd, providerComponentsYaml, addonsYaml, kubeconfigOut, false)
err := d.Create(inputCluster, inputMachines, &pcFactory)
if err == nil && tc.expectedError != "" {
t.Fatalf("error mismatch: got '%v', want '%v'", err, tc.expectedError)
Expand Down
18 changes: 15 additions & 3 deletions clusterctl/cmd/create_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type CreateOptions struct {
Cluster string
Machine string
ProviderComponents string
AddonComponents string
CleanupExternalCluster bool
VmDriver string
Provider string
Expand All @@ -53,6 +54,12 @@ var createClusterCmd = &cobra.Command{
if co.Machine == "" {
exitWithHelp(cmd, "Please provide yaml file for machine definition.")
}
if co.ProviderComponents == "" {
exitWithHelp(cmd, "Please provide yaml file for provider component definition.")
}
if co.AddonComponents == "" {
exitWithHelp(cmd, "Please provide yaml file for addon component definition.")
}
if err := RunCreate(co); err != nil {
glog.Exit(err)
}
Expand All @@ -78,30 +85,35 @@ func RunCreate(co *CreateOptions) error {
if err != nil {
return err
}
ac, err := ioutil.ReadFile(co.AddonComponents)
if err != nil {
return err
}
pcsFactory := clusterdeployer.NewProviderComponentsStoreFactory()
d := clusterdeployer.New(
mini,
clusterdeployer.NewClientFactory(),
pd,
string(pc),
string(ac),
co.KubeconfigOutput,
co.CleanupExternalCluster)
err = d.Create(c, m, pcsFactory)
return err
return d.Create(c, m, pcsFactory)
}

func init() {
// Required flags
createClusterCmd.Flags().StringVarP(&co.Cluster, "cluster", "c", "", "A yaml file containing cluster object definition")
createClusterCmd.Flags().StringVarP(&co.Machine, "machines", "m", "", "A yaml file containing machine object definition(s)")
createClusterCmd.Flags().StringVarP(&co.ProviderComponents, "provider-components", "p", "", "A yaml file containing cluster api provider controllers and supporting objects")
createClusterCmd.Flags().StringVarP(&co.AddonComponents, "addon-components", "a", "", "A yaml file containing cluster addons to apply to the internal cluster")
// TODO: Remove as soon as code allows https://github.com/kubernetes-sigs/cluster-api/issues/157
createClusterCmd.Flags().StringVarP(&co.Provider, "provider", "", "", "Which provider deployment logic to use (google/vsphere)")

// Optional flags
createClusterCmd.Flags().BoolVarP(&co.CleanupExternalCluster, "cleanup-external-cluster", "", true, "Whether to cleanup the external cluster after bootstrap")
createClusterCmd.Flags().StringVarP(&co.VmDriver, "vm-driver", "", "", "Which vm driver to use for minikube")
createClusterCmd.Flags().StringVarP(&co.KubeconfigOutput, "kubeconfig-out", "", "kubeconfig", "where to output the kubeconfig for the provisioned cluster.")
createClusterCmd.Flags().StringVarP(&co.KubeconfigOutput, "kubeconfig-out", "", "kubeconfig", "Where to output the kubeconfig for the provisioned cluster")

createCmd.AddCommand(createClusterCmd)
}
Expand Down
9 changes: 9 additions & 0 deletions clusterctl/examples/vsphere/addons.yaml.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: standard
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/vsphere-volume
parameters:
datastore: ""
2 changes: 1 addition & 1 deletion clusterctl/examples/vsphere/generate-yaml.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,4 @@ cat $PROVIDERCOMPONENT_TEMPLATE_FILE \
> $PROVIDERCOMPONENT_GENERATED_FILE

echo "Done generating $PROVIDERCOMPONENT_GENERATED_FILE"
echo "You will still need to generate the cluster.yaml and machines.yaml"
echo "You will still need to generate the cluster.yaml, machines.yaml, and addons.yaml configuration files"
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ Usage:
clusterctl create cluster [flags]

Flags:
-a, --addon-components string A yaml file containing cluster addons to apply to the internal cluster
--cleanup-external-cluster Whether to cleanup the external cluster after bootstrap (default true)
-c, --cluster string A yaml file containing cluster object definition
-h, --help help for cluster
--kubeconfig-out string where to output the kubeconfig for the provisioned cluster. (default "kubeconfig")
--kubeconfig-out string Where to output the kubeconfig for the provisioned cluster (default "kubeconfig")
-m, --machines string A yaml file containing machine object definition(s)
--provider string Which provider deployment logic to use (google/vsphere)
-p, --provider-components string A yaml file containing cluster api provider controllers and supporting objects
Expand Down
3 changes: 2 additions & 1 deletion clusterctl/testdata/create-cluster-no-args.golden
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ Usage:
clusterctl create cluster [flags]

Flags:
-a, --addon-components string A yaml file containing cluster addons to apply to the internal cluster
--cleanup-external-cluster Whether to cleanup the external cluster after bootstrap (default true)
-c, --cluster string A yaml file containing cluster object definition
-h, --help help for cluster
--kubeconfig-out string where to output the kubeconfig for the provisioned cluster. (default "kubeconfig")
--kubeconfig-out string Where to output the kubeconfig for the provisioned cluster (default "kubeconfig")
-m, --machines string A yaml file containing machine object definition(s)
--provider string Which provider deployment logic to use (google/vsphere)
-p, --provider-components string A yaml file containing cluster api provider controllers and supporting objects
Expand Down

0 comments on commit 094a16b

Please sign in to comment.