Skip to content

Commit

Permalink
Allow to use existing k8s cluster instead of minikube (#442)
Browse files Browse the repository at this point in the history
* created external cluster provisioner

* changes made here to support external provisioner that isnt minikube

* added testing to the new external cluster provisioner

* updated golden files to make sure tests run

* pr changes.

* removed unused test function

* comment made to externalboostrapcluster referencing issue that needs to be addressed soon.
  • Loading branch information
alejandroEsc authored and k8s-ci-robot committed Jul 27, 2018
1 parent 2ec8be3 commit f17f564
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 28 deletions.
3 changes: 3 additions & 0 deletions clusterctl/clusterdeployer/clusterdeployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,14 @@ func (d *ClusterDeployer) createExternalCluster() (ClusterClient, func(), error)
if err := d.externalProvisioner.Create(); err != nil {
return nil, cleanupFn, fmt.Errorf("could not create external control plane: %v", err)
}

if d.cleanupExternalCluster {
cleanupFn = func() {
glog.Info("Cleaning up external cluster.")
d.externalProvisioner.Delete()
}
}

externalKubeconfig, err := d.externalProvisioner.GetKubeconfig()
if err != nil {
return nil, cleanupFn, fmt.Errorf("unable to get external cluster kubeconfig: %v", err)
Expand All @@ -243,6 +245,7 @@ func (d *ClusterDeployer) createExternalCluster() (ClusterClient, func(), error)
if err != nil {
return nil, cleanupFn, fmt.Errorf("unable to create external client: %v", err)
}

return externalClient, cleanupFn, nil
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package externalclusterprovisioner

import (
"io/ioutil"
"os"
"fmt"
)

// Represents an actual external cluster being used for bootstrapping, should not be able to
// actually delete or create, but can point to actual kubeconfig file.
type ExternalBootstrapCluster struct {
kubeconfigPath string
kubeconfigFile string
}

// NewExternalCluster creates a new external k8s bootstrap cluster object
// We should clean up any lingering resources when clusterctl is complete.
// TODO https://github.com/kubernetes-sigs/cluster-api/issues/448
func NewExternalCluster(kubeconfigPath string) (*ExternalBootstrapCluster, error) {
if _, err := os.Stat(kubeconfigPath); os.IsNotExist(err) {
return nil, fmt.Errorf("file at %s does not exist", kubeconfigPath)
}

return &ExternalBootstrapCluster{kubeconfigPath:kubeconfigPath}, nil
}

// Create implements clusterdeployer.ClusterProvisioner interface
func (e *ExternalBootstrapCluster) Create() error {
// noop
return nil
}
// Delete implements clusterdeployer.ClusterProvisioner interface
func (e *ExternalBootstrapCluster) Delete() error {
// noop
return nil
}

// GetKubeconfig implements clusterdeployer.ClusterProvisioner interface
func (e *ExternalBootstrapCluster) GetKubeconfig() (string, error) {

if e.kubeconfigFile == "" {
b, err := ioutil.ReadFile(e.kubeconfigPath)
if err != nil {
return "", err
}

e.kubeconfigFile = string(b)
}


return e.kubeconfigFile, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package externalclusterprovisioner

import (
"testing"
"os"
"io/ioutil"
)

func TestGetKubeconfig(t *testing.T) {
const contents = "dfserfafaew"
f, err := createTempFile(contents)
if err != nil {
t.Fatal("Unable to create test file.")
}
defer os.Remove(f)

t.Run("invalid path given", func(t *testing.T){
_, err = NewExternalCluster("")
if err == nil {
t.Fatal("Should not be able create External Cluster Provisioner.")
}
})

t.Run("file exists", func(t *testing.T) {

ec, err := NewExternalCluster(f)
if err != nil {
t.Fatal("Should be able create External Cluster Provisioner.")
}

c, err := ec.GetKubeconfig()
if err != nil {
t.Fatalf("Unexpected err. Got: %v", err)
return
}
if c != contents {
t.Fatalf("Unexpected contents. Got: %v, Want: %v", c, contents)
}
})
}

func createTempFile(contents string) (string, error) {
f, err := ioutil.TempFile("", "")
if err != nil {
return "", err
}
defer f.Close()
f.WriteString(contents)
return f.Name(), nil
}
33 changes: 23 additions & 10 deletions clusterctl/cmd/create_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,22 @@ import (
"github.com/spf13/cobra"
"sigs.k8s.io/cluster-api/clusterctl/clusterdeployer"
"sigs.k8s.io/cluster-api/clusterctl/clusterdeployer/minikube"
"sigs.k8s.io/cluster-api/clusterctl/clusterdeployer/externalclusterprovisioner"
clustercommon "sigs.k8s.io/cluster-api/pkg/apis/cluster/common"
clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1"
"sigs.k8s.io/cluster-api/pkg/util"
)

type CreateOptions struct {
Cluster string
Machine string
ProviderComponents string
AddonComponents string
CleanupExternalCluster bool
VmDriver string
Provider string
KubeconfigOutput string
Cluster string
Machine string
ProviderComponents string
AddonComponents string
CleanupExternalCluster bool
VmDriver string
Provider string
KubeconfigOutput string
ExistingClusterKubeconfigPath string
}

var co = &CreateOptions{}
Expand Down Expand Up @@ -73,7 +75,17 @@ func RunCreate(co *CreateOptions) error {
return err
}

mini := minikube.New(co.VmDriver)
var externalProvider clusterdeployer.ClusterProvisioner
if co.ExistingClusterKubeconfigPath != "" {
externalProvider, err = externalclusterprovisioner.NewExternalCluster(co.ExistingClusterKubeconfigPath)
if err != nil {
return err
}
} else {
externalProvider = minikube.New(co.VmDriver)

}

pd, err := getProvider(co.Provider)
if err != nil {
return err
Expand All @@ -91,7 +103,7 @@ func RunCreate(co *CreateOptions) error {
}
pcsFactory := clusterdeployer.NewProviderComponentsStoreFactory()
d := clusterdeployer.New(
mini,
externalProvider,
clusterdeployer.NewClientFactory(),
string(pc),
string(ac),
Expand All @@ -112,6 +124,7 @@ func init() {
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.ExistingClusterKubeconfigPath, "existing-bootstrap-cluster-kubeconfig", "", "", "Path to an existing cluster's kubeconfig for bootstrapping (intead of using minikube)")

createCmd.AddCommand(createClusterCmd)
}
Expand Down
19 changes: 10 additions & 9 deletions clusterctl/testdata/create-cluster-no-args-invalid-flag.golden
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ 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")
-m, --machines string A yaml file containing machine object definition(s)
--provider string Which provider deployment logic to use (google/vsphere/azure)
-p, --provider-components string A yaml file containing cluster api provider controllers and supporting objects
--vm-driver string Which vm driver to use for minikube
-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
--existing-bootstrap-cluster-kubeconfig string Path to an existing cluster's kubeconfig for bootstrapping (intead of using minikube)
-h, --help help for cluster
--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/azure)
-p, --provider-components string A yaml file containing cluster api provider controllers and supporting objects
--vm-driver string Which vm driver to use for minikube

Global Flags:
--alsologtostderr log to standard error as well as files
Expand Down
19 changes: 10 additions & 9 deletions clusterctl/testdata/create-cluster-no-args.golden
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ 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")
-m, --machines string A yaml file containing machine object definition(s)
--provider string Which provider deployment logic to use (google/vsphere/azure)
-p, --provider-components string A yaml file containing cluster api provider controllers and supporting objects
--vm-driver string Which vm driver to use for minikube
-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
--existing-bootstrap-cluster-kubeconfig string Path to an existing cluster's kubeconfig for bootstrapping (intead of using minikube)
-h, --help help for cluster
--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/azure)
-p, --provider-components string A yaml file containing cluster api provider controllers and supporting objects
--vm-driver string Which vm driver to use for minikube

Global Flags:
--alsologtostderr log to standard error as well as files
Expand Down

0 comments on commit f17f564

Please sign in to comment.