diff --git a/cmd/kubeadm/app/kubeadm.go b/cmd/kubeadm/app/kubeadm.go index 584909353c..239ef35dfb 100644 --- a/cmd/kubeadm/app/kubeadm.go +++ b/cmd/kubeadm/app/kubeadm.go @@ -20,6 +20,7 @@ import ( "fmt" "os" "path" + "runtime" "strings" "github.com/spf13/pflag" @@ -40,13 +41,16 @@ func getEnvParams() map[string]string { } envParams := map[string]string{ - "prefix": globalPrefix, - "host_pki_path": path.Join(globalPrefix, "pki"), - "hyperkube_image": "gcr.io/google_containers/hyperkube:v1.4.0-alpha.3", - "discovery_image": "dgoodwin/kubediscovery:latest", + "prefix": globalPrefix, + "host_pki_path": path.Join(globalPrefix, "pki"), + // TODO find a way to specify image versions for all of these... + "hyperkube_image": fmt.Sprintf("gcr.io/google_containers/hyperkube-%s:%s", runtime.GOARCH, "v1.4.0-alpha.3"), + "discovery_image": "dgoodwin/kubediscovery:latest", + "etcd_image": fmt.Sprintf("gcr.io/google_containers/etcd-%s:%s", runtime.GOARCH, "2.2.5"), + "component_loglevel": "--v=4", } - for k, _ := range envParams { + for k := range envParams { if v := os.Getenv(fmt.Sprintf("KUBE_%s", strings.ToUpper(k))); v != "" { envParams[k] = v } diff --git a/pkg/kubeadm/api/types.go b/pkg/kubeadm/api/types.go index e659162cb0..087a2d315d 100644 --- a/pkg/kubeadm/api/types.go +++ b/pkg/kubeadm/api/types.go @@ -17,8 +17,7 @@ limitations under the License. package kubeadmapi type BootstrapParams struct { - // A struct with methods that implement Discover() - // kubeadm will do the CSR dance + // TODO this is mostly out of date and bloated now, let's revisit this soon Discovery *OutOfBandDiscovery EnvParams map[string]string } diff --git a/pkg/kubeadm/cmd/init.go b/pkg/kubeadm/cmd/init.go index a40f32637a..abfc4647ab 100644 --- a/pkg/kubeadm/cmd/init.go +++ b/pkg/kubeadm/cmd/init.go @@ -91,6 +91,10 @@ func RunInit(out io.Writer, cmd *cobra.Command, args []string, params *kubeadmap return err } + if err := kubemaster.UpdateMasterRoleLabelsAndTaints(client); err != nil { + return err + } + if err := kubemaster.CreateDiscoveryDeploymentAndSecret(params, client, caCert); err != nil { return err } diff --git a/pkg/kubeadm/cmd/manual.go b/pkg/kubeadm/cmd/manual.go index aa617eba9f..491ab06b25 100644 --- a/pkg/kubeadm/cmd/manual.go +++ b/pkg/kubeadm/cmd/manual.go @@ -27,12 +27,12 @@ import ( kubemaster "k8s.io/kubernetes/pkg/kubeadm/master" kubenode "k8s.io/kubernetes/pkg/kubeadm/node" kubeadmutil "k8s.io/kubernetes/pkg/kubeadm/util" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" netutil "k8s.io/kubernetes/pkg/util/net" - // TODO: cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ) var ( - manual_done_msgf = dedent.Dedent(` + manual_init_done_msgf = dedent.Dedent(` Master initialization complete: * Static pods written and kubelet's kubeconfig written. @@ -48,6 +48,14 @@ var ( kubeadm manual bootstrap join-node --ca-cert-file \ --token %s --api-server-urls https://%s:443/ `) + manual_join_done_msgf = dedent.Dedent(` + Node join complete: + * Certificate signing request sent to master and response + received. + * Kubelet informed of new secure connection details. + + Run 'kubectl get nodes' on the master to see this node join. + `) ) // TODO --token here becomes Discovery.BearerToken and not Discovery.GivenToken @@ -92,42 +100,9 @@ func NewCmdManualBootstrapInitMaster(out io.Writer, params *kubeadmapi.Bootstrap Will create TLS certificates and set up static pods for Kubernetes master components. `), - RunE: func(cmd *cobra.Command, args []string) error { - if params.Discovery.ListenIP == "" { - ip, err := netutil.ChooseHostInterface() - if err != nil { - return fmt.Errorf("Unable to autodetect IP address [%s], please specify with --listen-ip", err) - } - params.Discovery.ListenIP = ip.String() - } - if err := kubemaster.CreateTokenAuthFile(params); err != nil { - return err - } - if err := kubemaster.WriteStaticPodManifests(params); err != nil { - return err - } - caKey, caCert, err := kubemaster.CreatePKIAssets(params) - if err != nil { - return err - } - kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(params, []string{"kubelet", "admin"}, caKey, caCert) - if err != nil { - return err - } - for name, kubeconfig := range kubeconfigs { - if err := kubeadmutil.WriteKubeconfigIfNotExists(params, name, kubeconfig); err != nil { - out.Write([]byte(fmt.Sprintf("Unable to write admin for master:\n%s\n", err))) - return nil - } - } - - // TODO use templates to reference struct fields directly as order of args is fragile - fmt.Fprintf(out, manual_done_msgf, - params.Discovery.BearerToken, - params.Discovery.ListenIP, - ) - - return nil + Run: func(cmd *cobra.Command, args []string) { + err := RunManualBootstrapInitMaster(out, cmd, args, params) + cmdutil.CheckErr(err) }, } @@ -143,43 +118,50 @@ func NewCmdManualBootstrapInitMaster(out io.Writer, params *kubeadmapi.Bootstrap return cmd } +func RunManualBootstrapInitMaster(out io.Writer, cmd *cobra.Command, args []string, params *kubeadmapi.BootstrapParams) error { + if params.Discovery.ListenIP == "" { + ip, err := netutil.ChooseHostInterface() + if err != nil { + return fmt.Errorf(" unable to autodetect IP address [%s], please specify with --listen-ip", err) + } + params.Discovery.ListenIP = ip.String() + } + if err := kubemaster.CreateTokenAuthFile(params); err != nil { + return err + } + if err := kubemaster.WriteStaticPodManifests(params); err != nil { + return err + } + caKey, caCert, err := kubemaster.CreatePKIAssets(params) + if err != nil { + return err + } + kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(params, []string{"kubelet", "admin"}, caKey, caCert) + if err != nil { + return err + } + for name, kubeconfig := range kubeconfigs { + if err := kubeadmutil.WriteKubeconfigIfNotExists(params, name, kubeconfig); err != nil { + return err + } + } + + // TODO use templates to reference struct fields directly as order of args is fragile + fmt.Fprintf(out, manual_init_done_msgf, + params.Discovery.BearerToken, + params.Discovery.ListenIP, + ) + return nil +} + func NewCmdManualBootstrapJoinNode(out io.Writer, params *kubeadmapi.BootstrapParams) *cobra.Command { cmd := &cobra.Command{ Use: "join-node", Short: "Manually bootstrap a node 'out-of-band', joining it into a cluster with extant control plane", Run: func(cmd *cobra.Command, args []string) { - if params.Discovery.CaCertFile == "" { - out.Write([]byte(fmt.Sprintf("Must specify --ca-cert-file (see --help)\n"))) - return - } - - if params.Discovery.ApiServerURLs == "" { - out.Write([]byte(fmt.Sprintf("Must specify --api-server-urls (see --help)\n"))) - return - } - - kubeconfig, err := kubenode.PerformTLSBootstrapFromParams(params) - if err != nil { - out.Write([]byte(fmt.Sprintf("Failed to perform TLS bootstrap: %s\n", err))) - return - } - //fmt.Println("recieved signed certificate from the API server, will write `/etc/kubernetes/kubelet.conf`...") - - err = kubeadmutil.WriteKubeconfigIfNotExists(params, "kubelet", kubeconfig) - if err != nil { - out.Write([]byte(fmt.Sprintf("Unable to write config for node:\n%s\n", err))) - return - } - out.Write([]byte(dedent.Dedent(` - Node join complete: - * Certificate signing request sent to master and response - received. - * Kubelet informed of new secure connection details. - - Run 'kubectl get nodes' on the master to see this node join. - - `))) + err := RunManualBootstrapJoinNode(out, cmd, args, params) + cmdutil.CheckErr(err) }, } cmd.PersistentFlags().StringVarP(¶ms.Discovery.CaCertFile, "ca-cert-file", "", "", @@ -193,3 +175,30 @@ func NewCmdManualBootstrapJoinNode(out io.Writer, params *kubeadmapi.BootstrapPa return cmd } + +func RunManualBootstrapJoinNode(out io.Writer, cmd *cobra.Command, args []string, params *kubeadmapi.BootstrapParams) error { + if params.Discovery.CaCertFile == "" { + fmt.Fprintf(out, "Must specify --ca-cert-file (see --help)\n") + return nil + } + + if params.Discovery.ApiServerURLs == "" { + fmt.Fprintf(out, "Must specify --api-server-urls (see --help)\n") + return nil + } + + kubeconfig, err := kubenode.PerformTLSBootstrapFromParams(params) + if err != nil { + fmt.Fprintf(out, "Failed to perform TLS bootstrap: %s\n", err) + return err + } + + err = kubeadmutil.WriteKubeconfigIfNotExists(params, "kubelet", kubeconfig) + if err != nil { + fmt.Fprintf(out, "Unable to write config for node:\n%s\n", err) + return err + } + + fmt.Fprintf(out, manual_join_done_msgf) + return nil +} diff --git a/pkg/kubeadm/master/addons.go b/pkg/kubeadm/master/addons.go index 97911ede83..e56077ceff 100644 --- a/pkg/kubeadm/master/addons.go +++ b/pkg/kubeadm/master/addons.go @@ -13,6 +13,7 @@ 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 kubemaster import ( @@ -35,7 +36,7 @@ func createKubeProxyPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec { "/hyperkube", "proxy", "--kubeconfig=/run/kubeconfig", - COMPONENT_LOGLEVEL, + params.EnvParams["component_loglevel"], }, SecurityContext: &api.SecurityContext{Privileged: &privilegedTrue}, VolumeMounts: []api.VolumeMount{ @@ -80,6 +81,7 @@ func createKubeProxyPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec { func CreateEssentialAddons(params *kubeadmapi.BootstrapParams, client *clientset.Clientset) error { kubeProxyDaemonSet := NewDaemonSet("kube-proxy", createKubeProxyPodSpec(params)) + SetMasterTaintTolerations(&kubeProxyDaemonSet.Spec.Template.ObjectMeta) if _, err := client.Extensions().DaemonSets(api.NamespaceSystem).Create(kubeProxyDaemonSet); err != nil { return fmt.Errorf(" failed creating essential kube-proxy addon [%s]", err) diff --git a/pkg/kubeadm/master/apiclient.go b/pkg/kubeadm/master/apiclient.go index 4a2d404d9b..6c9b19c721 100644 --- a/pkg/kubeadm/master/apiclient.go +++ b/pkg/kubeadm/master/apiclient.go @@ -17,10 +17,12 @@ limitations under the License. package kubemaster import ( + "encoding/json" "fmt" "time" "k8s.io/kubernetes/pkg/api" + apierrs "k8s.io/kubernetes/pkg/api/errors" unversionedapi "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/apis/extensions" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" @@ -53,6 +55,7 @@ func CreateClientAndWaitForAPI(adminConfig *clientcmdapi.Config) (*clientset.Cli if err != nil { return false, nil } + // TODO revisit this when we implement HA if len(cs.Items) < 3 { fmt.Println(" not all control plane components are ready yet") return false, nil @@ -66,11 +69,32 @@ func CreateClientAndWaitForAPI(adminConfig *clientcmdapi.Config) (*clientset.Cli } } - fmt.Printf(" all control plane components are healthy after %s seconds\n", time.Since(start).Seconds()) + fmt.Printf(" all control plane components are healthy after %f seconds\n", time.Since(start).Seconds()) + return true, nil + }) + + fmt.Println(" waiting for at least one node to register and become ready") + start = time.Now() + wait.PollInfinite(500*time.Millisecond, func() (bool, error) { + nodeList, err := client.Nodes().List(api.ListOptions{}) + if err != nil { + fmt.Println(" temporarily unable to list nodes (will retry)") + return false, nil + } + if len(nodeList.Items) < 1 { + //fmt.Printf(" %d nodes have registered so far", len(nodeList.Items)) + return false, nil + } + n := &nodeList.Items[0] + if !api.IsNodeReady(n) { + fmt.Println(" first node has registered, but is not ready yet") + return false, nil + } + + fmt.Printf(" first node is ready after %f seconds\n", time.Since(start).Seconds()) return true, nil }) - // TODO may be also check node status return client, nil } @@ -103,9 +127,72 @@ func NewDeployment(deploymentName string, replicas int32, podSpec api.PodSpec) * } } -func TaintMaster(*clientset.Clientset) error { - // TODO - annotations := make(map[string]string) - annotations[api.TaintsAnnotationKey] = "" +// It's safe to do this for alpha, as we don't have HA and there is no way we can get +// more then one node here (TODO find a way to determine owr own node name) +func findMyself(client *clientset.Clientset) (*api.Node, error) { + nodeList, err := client.Nodes().List(api.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("unable to list nodes [%s]", err) + } + if len(nodeList.Items) < 1 { + return nil, fmt.Errorf("no nodes found") + } + node := &nodeList.Items[0] + return node, nil +} + +func attemptToUpdateMasterRoleLabelsAndTaints(client *clientset.Clientset) error { + n, err := findMyself(client) + if err != nil { + return err + } + + n.ObjectMeta.Labels["kubeadm.alpha.kubernetes.io/role"] = "master" + taintsAnnotation, _ := json.Marshal([]api.Taint{{Key: "dedicated", Value: "master", Effect: "NoSchedule"}}) + n.ObjectMeta.Annotations[api.TaintsAnnotationKey] = string(taintsAnnotation) + + if _, err := client.Nodes().Update(n); err != nil { + if apierrs.IsConflict(err) { + fmt.Println(" temporarily unable to update master node metadata due to conflict (will retry)") + time.Sleep(500 * time.Millisecond) + attemptToUpdateMasterRoleLabelsAndTaints(client) + } else { + return err + } + } + return nil } + +func UpdateMasterRoleLabelsAndTaints(client *clientset.Clientset) error { + err := attemptToUpdateMasterRoleLabelsAndTaints(client) + if err != nil { + return fmt.Errorf(" failed to update master node - %s", err) + } + return nil +} + +func SetMasterTaintTolerations(meta *api.ObjectMeta) { + tolerationsAnnotation, _ := json.Marshal([]api.Toleration{{Key: "dedicated", Value: "master", Effect: "NoSchedule"}}) + if meta.Annotations == nil { + meta.Annotations = map[string]string{} + } + meta.Annotations[api.TolerationsAnnotationKey] = string(tolerationsAnnotation) +} + +func SetMasterNodeAffinity(meta *api.ObjectMeta) { + nodeAffinity := &api.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{ + NodeSelectorTerms: []api.NodeSelectorTerm{{ + MatchExpressions: []api.NodeSelectorRequirement{{ + Key: "kubeadm.alpha.kubernetes.io/role", Operator: api.NodeSelectorOpIn, Values: []string{"master"}, + }}, + }}, + }, + } + affinityAnnotation, _ := json.Marshal(api.Affinity{NodeAffinity: nodeAffinity}) + if meta.Annotations == nil { + meta.Annotations = map[string]string{} + } + meta.Annotations[api.AffinityAnnotationKey] = string(affinityAnnotation) +} diff --git a/pkg/kubeadm/master/discovery.go b/pkg/kubeadm/master/discovery.go index 76caac9009..51fc65bde8 100644 --- a/pkg/kubeadm/master/discovery.go +++ b/pkg/kubeadm/master/discovery.go @@ -13,6 +13,7 @@ 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 kubemaster import ( @@ -61,7 +62,11 @@ func encodeKubeDiscoverySecretData(params *kubeadmapi.BootstrapParams, caCert *x func newKubeDiscoveryPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec { return api.PodSpec{ - SecurityContext: &api.PodSecurityContext{HostNetwork: true}, // TODO we should just use map it to a host port + // We have to use host network namespace, as `HostPort`/`HostIP` are Docker's + // buisness and CNI support isn't quite there yet (except for kubenet) + // (see https://github.com/kubernetes/kubernetes/issues/31307) + // TODO update this when #31307 is resolved + SecurityContext: &api.PodSecurityContext{HostNetwork: true}, Containers: []api.Container{{ Name: kubeDiscoverynName, Image: params.EnvParams["discovery_image"], @@ -71,6 +76,10 @@ func newKubeDiscoveryPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec { MountPath: "/tmp/secret", // TODO use a shared constant ReadOnly: true, }}, + Ports: []api.ContainerPort{ + // TODO when CNI issue (#31307) is resolved, we should add `HostIP: params.Discovery.ListenIP` + {Name: "http", ContainerPort: 9898, HostPort: 9898}, + }, }}, Volumes: []api.Volume{{ Name: kubeDiscoverySecretName, @@ -82,8 +91,7 @@ func newKubeDiscoveryPodSpec(params *kubeadmapi.BootstrapParams) api.PodSpec { } func newKubeDiscovery(params *kubeadmapi.BootstrapParams, caCert *x509.Certificate) kubeDiscovery { - // TODO pin to master - return kubeDiscovery{ + kd := kubeDiscovery{ Deployment: NewDeployment(kubeDiscoverynName, 1, newKubeDiscoveryPodSpec(params)), Secret: &api.Secret{ ObjectMeta: api.ObjectMeta{Name: kubeDiscoverySecretName}, @@ -91,16 +99,21 @@ func newKubeDiscovery(params *kubeadmapi.BootstrapParams, caCert *x509.Certifica Data: encodeKubeDiscoverySecretData(params, caCert), }, } + + SetMasterTaintTolerations(&kd.Deployment.Spec.Template.ObjectMeta) + SetMasterNodeAffinity(&kd.Deployment.Spec.Template.ObjectMeta) + + return kd } func CreateDiscoveryDeploymentAndSecret(params *kubeadmapi.BootstrapParams, client *clientset.Clientset, caCert *x509.Certificate) error { kd := newKubeDiscovery(params, caCert) if _, err := client.Extensions().Deployments(api.NamespaceSystem).Create(kd.Deployment); err != nil { - return fmt.Errorf(" failed to create %q deployment", kubeDiscoverynName) + return fmt.Errorf(" failed to create %q deployment [%s]", kubeDiscoverynName, err) } if _, err := client.Secrets(api.NamespaceSystem).Create(kd.Secret); err != nil { - return fmt.Errorf(" failed to create %q secret", kubeDiscoverySecretName) + return fmt.Errorf(" failed to create %q secret [%s]", kubeDiscoverySecretName, err) } fmt.Println(" created essential addon: kube-discovery") diff --git a/pkg/kubeadm/master/manifests.go b/pkg/kubeadm/master/manifests.go index b8810be2b6..7641ee1066 100644 --- a/pkg/kubeadm/master/manifests.go +++ b/pkg/kubeadm/master/manifests.go @@ -35,7 +35,6 @@ import ( // init master` and `kubeadm manual bootstrap master` can get going. const ( - COMPONENT_LOGLEVEL = "--v=4" SERVICE_CLUSTER_IP_RANGE = "--service-cluster-ip-range=10.16.0.0/12" CLUSTER_NAME = "--cluster-name=kubernetes" MASTER = "--master=127.0.0.1:8080" @@ -55,7 +54,7 @@ func WriteStaticPodManifests(params *kubeadmapi.BootstrapParams) error { "--advertise-client-urls=http://127.0.0.1:2379,http://127.0.0.1:4001", "--data-dir=/var/etcd/data", }, - Image: "gcr.io/google_containers/etcd:2.2.1", // TODO parametrise + Image: params.EnvParams["etcd_image"], LivenessProbe: componentProbe(2379, "/health"), Name: "etcd-server", Resources: componentResources("200m"), @@ -69,7 +68,6 @@ func WriteStaticPodManifests(params *kubeadmapi.BootstrapParams) error { "apiserver", "--address=127.0.0.1", "--etcd-servers=http://127.0.0.1:2379", - "--cloud-provider=fake", // TODO parametrise "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota", SERVICE_CLUSTER_IP_RANGE, "--service-account-key-file=/etc/kubernetes/pki/apiserver-key.pem", @@ -78,7 +76,7 @@ func WriteStaticPodManifests(params *kubeadmapi.BootstrapParams) error { "--tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem", "--secure-port=443", "--allow-privileged", - COMPONENT_LOGLEVEL, + params.EnvParams["component_loglevel"], "--token-auth-file=/etc/kubernetes/pki/tokens.csv", }, VolumeMounts: []api.VolumeMount{pkiVolumeMount()}, @@ -99,7 +97,7 @@ func WriteStaticPodManifests(params *kubeadmapi.BootstrapParams) error { "--cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem", "--cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem", "--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap", - COMPONENT_LOGLEVEL, + params.EnvParams["component_loglevel"], }, VolumeMounts: []api.VolumeMount{pkiVolumeMount()}, LivenessProbe: componentProbe(10252, "/healthz"), @@ -113,7 +111,7 @@ func WriteStaticPodManifests(params *kubeadmapi.BootstrapParams) error { "scheduler", "--leader-elect", MASTER, - COMPONENT_LOGLEVEL, + params.EnvParams["component_loglevel"], }, LivenessProbe: componentProbe(10251, "/healthz"), Resources: componentResources("100m"), diff --git a/pkg/kubeadm/master/pki.go b/pkg/kubeadm/master/pki.go index 6c23c90a5d..d5b2434985 100644 --- a/pkg/kubeadm/master/pki.go +++ b/pkg/kubeadm/master/pki.go @@ -175,6 +175,6 @@ func CreatePKIAssets(params *kubeadmapi.BootstrapParams) (*rsa.PrivateKey, *x509 } // TODO print a summary of SANs used and checksums (signatures) of each of the certiicates - fmt.Println(" created keys and certificates in %q", params.EnvParams["host_pki_path"]) + fmt.Printf(" created keys and certificates in %q\n", params.EnvParams["host_pki_path"]) return caKey, caCert, nil } diff --git a/pkg/kubeadm/master/tokens.go b/pkg/kubeadm/master/tokens.go index 81d899807b..ad184cbbcd 100644 --- a/pkg/kubeadm/master/tokens.go +++ b/pkg/kubeadm/master/tokens.go @@ -13,6 +13,7 @@ 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 kubemaster import ( @@ -38,6 +39,8 @@ func generateTokenIfNeeded(params *kubeadmapi.BootstrapParams) error { return err } fmt.Printf(" generated token: %q\n", params.Discovery.GivenToken) + } else { + fmt.Println(" accepted provided token") } return nil diff --git a/pkg/kubeadm/node/discovery.go b/pkg/kubeadm/node/discovery.go index 9609905b65..beb470e98d 100644 --- a/pkg/kubeadm/node/discovery.go +++ b/pkg/kubeadm/node/discovery.go @@ -13,6 +13,7 @@ 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 kubenode import ( @@ -43,7 +44,7 @@ func RetrieveTrustedClusterInfo(params *kubeadmapi.BootstrapParams) (*clientcmda return nil, fmt.Errorf(" failed to consturct an HTTP request [%s]", err) } - fmt.Println(" created cluster info discovery client, requesting info from %q", requestURL) + fmt.Printf(" created cluster info discovery client, requesting info from %q\n", requestURL) res, err := http.DefaultClient.Do(req) if err != nil { diff --git a/pkg/kubeadm/util/kubeconfig.go b/pkg/kubeadm/util/kubeconfig.go index 9c595d5758..49e27e3f29 100644 --- a/pkg/kubeadm/util/kubeconfig.go +++ b/pkg/kubeadm/util/kubeconfig.go @@ -98,6 +98,6 @@ func WriteKubeconfigIfNotExists(params *kubeadmapi.BootstrapParams, name string, return fmt.Errorf(" failed to write to %q [%s]", filename, err) } - fmt.Println(" created %q", filename) + fmt.Printf(" created %q\n", filename) return nil } diff --git a/pkg/kubeadm/util/tokens.go b/pkg/kubeadm/util/tokens.go index 91f5f78d5f..5d643dcf6e 100644 --- a/pkg/kubeadm/util/tokens.go +++ b/pkg/kubeadm/util/tokens.go @@ -13,6 +13,7 @@ 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 kubeadmutil import ( @@ -61,8 +62,9 @@ func GenerateToken(params *kubeadmapi.BootstrapParams) error { func UseGivenTokenIfValid(params *kubeadmapi.BootstrapParams) (bool, error) { if params.Discovery.GivenToken == "" { - return false, nil + return false, nil // not given } + fmt.Println(" validating provided token") givenToken := strings.Split(strings.ToLower(params.Discovery.GivenToken), ".") // TODO print desired format // TODO could also print more specific messages in each case