-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial version of clusterctl create #219
Initial version of clusterctl create #219
Conversation
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: jessicaochen The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/assign @k4leung4 @mkjelland |
clusterctl/cmd/create_cluster.go
Outdated
VmDriver string | ||
VmDriver string | ||
Provider string | ||
KubeonfigOutput string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
KubeConfigOutput?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -0,0 +1,334 @@ | |||
/* | |||
Copyright 2017 The Kubernetes Authors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2018
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
return string(tmplBuf.Bytes()), nil | ||
} | ||
|
||
const ClusterAPIAPIServerConfigTemplate = ` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider moving the template into a file by itself?
will make it obvious when someone is tweaking the template vs changing code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -0,0 +1,211 @@ | |||
package clusterdeployer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing license
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
func (c *clusterClient) GetClusterObjects() ([]*clusterv1.Cluster, error) { | ||
clusters := []*clusterv1.Cluster{} | ||
// TODO: Iterate over all namespaces where we could have Cluster API Objects | ||
clusterlist, err := c.clientSet.ClusterV1alpha1().Clusters(apiv1.NamespaceDefault).List(metav1.ListOptions{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a apiv1.NamespaceAll if you do want to list all clusters in all namespaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*Acutally punted with issue labeled.
cluster.Status.APIEndpoints = append(cluster.Status.APIEndpoints, | ||
clusterv1.APIEndpoint{ | ||
Host: masterIP, | ||
Port: 443, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider making 443 const
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -0,0 +1,4 @@ | |||
package clusterdeployer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check license for all files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i meant copyright
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
} | ||
}() | ||
|
||
glog.V(2).Info("Applying Cluster API APIServer to external cluster.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while the code in this method is relatively straightforward, there is a lot to keep track of.
does it make sense to add helper methods for creating objects with the external client one for the internal client?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broke it out as much as I could while preserving flow.
} | ||
|
||
for _, cluster := range clusters { | ||
cluster.SetResourceVersion("") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you comment on why it is necessary to set the resource version to an empty string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -4,12 +4,18 @@ import ( | |||
"fmt" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
run gofmt to order imports
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
return nil, err | ||
} | ||
defer f.Close() | ||
f.WriteString(kubeconfig) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing the error check for writing the string to the file on line 31.
Recommend switching from WriteString and using ioutil.WriteFile(...)
There is a subtle bug here where it is possible that the Write on line 31 was not flushed to disk and then on line 32 the contents of the file are being used. If ioutil.WriteFile(...) is used then file handle it opens is guaranteed to be closed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
return certParams, nil | ||
} | ||
|
||
func GetApiServerYaml() (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This public method should have associated test(s).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
glog.V(1).Info("Getting internal cluster kubeconfig.") | ||
internalKubeconfig, err := waitForKubeconfigReady(d.provider, master) | ||
if err != nil { | ||
return fmt.Errorf("unable to get internal cluster kbueconfig: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: kbueconfig -> kubeconfig
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
glog.V(2).Infof("Creating master %v", master.Name) | ||
err = externalClient.CreateMachineObjects([]*clusterv1.Machine{master}) | ||
if err != nil { | ||
return fmt.Errorf("unable to create master machine:%v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: missing space after 'machine:'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
// Fetch freshly created master. | ||
updatedMachines, err := externalClient.GetMachineObjects() | ||
if err != nil { | ||
return fmt.Errorf("unable to fetch machines:%v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: missing space after 'machine:'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
} | ||
master, _, err = splitMachineRoles(updatedMachines) | ||
if err != nil { | ||
return fmt.Errorf("unable to fetch master machine:%v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: missing space after 'machine:'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
|
||
func (d *ClusterDeployer) writeKubeconfig(kubeconfig string) error { | ||
os.Remove(d.kubeconfigOutput) | ||
f, err := os.Create(d.kubeconfigOutput) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function, lines 223 -> 229, can be replaced / simplified with:
return ioutil.WriteFile(d.kubeconfigOutput, []byte(kubeconfig), 0666
which is functionally equivalent (os.Create / ioutil.WriteFile both truncuate).
if err != nil { | ||
return err | ||
} | ||
err = waitForMachineReady(c.clientSet, createdMachine) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be parallelized and It would be faster, if the it were to first create all machine objects. After the creationg loop completed it could then call waitForMachineReady(...) on each object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Punted as a post v0 optimization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a TODO into the code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
3cb2772
to
f8a3d18
Compare
defer func() { | ||
err := externalClient.Close() | ||
if err != nil { | ||
glog.Error("Could not close external client") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add err value to error message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
defer func() { | ||
err := internalClient.Close() | ||
if err != nil { | ||
glog.Error("Could not close internal client") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add err value to error message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
} | ||
|
||
func (d *ClusterDeployer) applyClusterAPIApiserver(client ClusterClient) error { | ||
yaml, err := getApiServerYaml() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I would prefer if this was called getClusterApiServerYaml since it could mean the core api server.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think whether it uses yaml under the covers or something else is a implementation detail. I was hoping the clusterapi + apiserver in the method name would make it clear it is the cluster api apiserver as opposed to the main apiserver. Is this ok or do you have other ideas on how do distinguish between the main apiserver and the clusterapi apiserver for the method name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that makes sense!
CreateClusterObject(*clusterv1.Cluster) error | ||
CreateMachineObjects([]*clusterv1.Machine) error | ||
UpdateClusterObjectEndpoint(string) error | ||
Close() error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eventually, will there be Delete methods for Machine and Cluster? Is that out of scope for clusterctl?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deletion is in scope for clusterctl.
If that ability is added to the ClusterDeployer, it would make sense to extend the ClusterClient interface to handle the needed methods at that point.
f8a3d18
to
2b016a2
Compare
@@ -22,13 +22,10 @@ $ go build | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a TBD here so that it's clear that the limitations section isn't filled out? Right now it is easy to think that Creating a cluster falls in the limitations section.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
"k8s.io/client-go/util/cert/triple" | ||
) | ||
|
||
var apiServerImage = "gcr.io/k8s-cluster-api/cluster-apiserver:0.0.3" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is out of date compared to head. I think the current version is 0.0.5 or so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know. This is snapshot-ed to the version called out in the PR description. My plan is to move roll forward after landing this v0 PR. There is a lot of development in this repo (a good thing :) ) and I think it is better to land something working and improve it than hold off trying to keep up with all the development.
var apiServerImage = "gcr.io/k8s-cluster-api/cluster-apiserver:0.0.3" | ||
|
||
func init() { | ||
if img, ok := os.LookupEnv("CLUSTER_API_SERVER_IMAGE"); ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why an env var instead of a flag?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is what we have been doing so far in this repo. We can change it to a flag post v0 if folks really prefer a flag over a environment variable for a development hook.
api: clusterapi | ||
apiserver: "true" | ||
--- | ||
apiVersion: apps/v1beta1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deployments should use v1
instead of v1beta1
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is snapshot-ed to the version called out in the PR description. I want to check it in with a consistent working snapshot so we know what changes it is caught up with and what changes it has yet to catch up on.
name: default | ||
namespace: default | ||
--- | ||
apiVersion: apps/v1beta1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is snapshot-ed to the version called out in the PR description. I want to check it in with a consistent working snapshot so we know what changes it is caught up with and what changes it has yet to catch up on.
if err != nil { | ||
return err | ||
} | ||
err = waitForMachineReady(c.clientSet, createdMachine) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a TODO into the code?
**NOT YET SUPPORTED!** - Use [provider-specific deployer](../README.md) to create clusters till cluster creation is supported. | ||
|
||
1. Create a `cluster.yaml` and `machines.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 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>`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you intend to include the example provider-components.yaml in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is imminently coming in the next PR.
2b016a2
to
c36f757
Compare
lgtm |
/lgtm |
What this PR does / why we need it:
First version of clusterctl create. There is plenty room to iterate and improve (as indicated by the TODOs). However, I think it is beneficial to get a functional initial version down so iteration and improvement can happen in parallel.
#157
Note that apiserver podspec is captured from commit a1ea634 (#153).
Special notes for your reviewer:
The code for generating the gcp example files for this cluster create command is coming in the next PR.
Release note:
@kubernetes/kube-deploy-reviewers