[Federation] Improve the logging and user feedback in 'kubefed init'.

This commit is contained in:
Jonathan MacMillan 2017-02-28 17:57:48 -08:00
parent 76889118d7
commit 0f851bfa2e

View File

@ -284,20 +284,25 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
} }
} }
fmt.Fprint(cmdOut, "Creating a namespace for federation system components") fmt.Fprintf(cmdOut, "Creating a namespace %s for federation system components...", i.commonOptions.FederationSystemNamespace)
glog.V(4).Infof("Creating a namespace %s for federation system components", i.commonOptions.FederationSystemNamespace)
_, err = createNamespace(hostClientset, i.commonOptions.Name, i.commonOptions.FederationSystemNamespace, i.options.dryRun) _, err = createNamespace(hostClientset, i.commonOptions.Name, i.commonOptions.FederationSystemNamespace, i.options.dryRun)
if err != nil { if err != nil {
return err return err
} }
fmt.Fprint(cmdOut, " done\n")
fmt.Fprint(cmdOut, "Creating federation control plane objects (service, credentials, persistent volume claim)") fmt.Fprintln(cmdOut, " done")
svc, ips, hostnames, err := createService(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.commonOptions.Name, i.options.apiServerAdvertiseAddress, i.options.apiServerServiceType, i.options.dryRun)
fmt.Fprint(cmdOut, "Creating federation control plane service...")
glog.V(4).Info("Creating federation control plane service")
svc, ips, hostnames, err := createService(cmdOut, hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.commonOptions.Name, i.options.apiServerAdvertiseAddress, i.options.apiServerServiceType, i.options.dryRun)
if err != nil { if err != nil {
return err return err
} }
fmt.Fprintln(cmdOut, " done")
glog.V(4).Infof("Created service named %s with IP addresses %v, hostnames %v", svc.Name, ips, hostnames) glog.V(4).Infof("Created service named %s with IP addresses %v, hostnames %v", svc.Name, ips, hostnames)
fmt.Fprint(cmdOut, "Creating federation control plane objects (credentials, persistent volume claim)...")
glog.V(4).Info("Generating TLS certificates and credentials for communicating with the federation API server") glog.V(4).Info("Generating TLS certificates and credentials for communicating with the federation API server")
credentials, err := generateCredentials(i.commonOptions.FederationSystemNamespace, i.commonOptions.Name, svc.Name, HostClusterLocalDNSZoneName, serverCredName, ips, hostnames, i.options.apiServerEnableHTTPBasicAuth, i.options.apiServerEnableTokenAuth, i.options.dryRun) credentials, err := generateCredentials(i.commonOptions.FederationSystemNamespace, i.commonOptions.Name, svc.Name, HostClusterLocalDNSZoneName, serverCredName, ips, hostnames, i.options.apiServerEnableHTTPBasicAuth, i.options.apiServerEnableTokenAuth, i.options.dryRun)
if err != nil { if err != nil {
@ -316,7 +321,7 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
if err != nil { if err != nil {
return err return err
} }
glog.V(4).Info("kubeconfig successfully updated") glog.V(4).Info("Credentials secret successfully created")
glog.V(4).Info("Creating a persistent volume and a claim to store the federation API server's state, including etcd data") glog.V(4).Info("Creating a persistent volume and a claim to store the federation API server's state, including etcd data")
var pvc *api.PersistentVolumeClaim var pvc *api.PersistentVolumeClaim
@ -327,7 +332,7 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
} }
} }
glog.V(4).Info("Persistent volume and claim created") glog.V(4).Info("Persistent volume and claim created")
fmt.Fprint(cmdOut, " done\n") fmt.Fprintln(cmdOut, " done")
// Since only one IP address can be specified as advertise address, // Since only one IP address can be specified as advertise address,
// we arbitrarily pick the first available IP address // we arbitrarily pick the first available IP address
@ -337,7 +342,8 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
advertiseAddress = ips[0] advertiseAddress = ips[0]
} }
fmt.Fprint(cmdOut, "Creating federation component deployments") fmt.Fprint(cmdOut, "Creating federation component deployments...")
glog.V(4).Info("Creating federation control plane components")
_, err = createAPIServer(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.commonOptions.Name, i.options.image, advertiseAddress, serverCredName, i.options.apiServerEnableHTTPBasicAuth, i.options.apiServerEnableTokenAuth, i.options.apiServerOverrides, pvc, i.options.dryRun) _, err = createAPIServer(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.commonOptions.Name, i.options.image, advertiseAddress, serverCredName, i.options.apiServerEnableHTTPBasicAuth, i.options.apiServerEnableTokenAuth, i.options.apiServerOverrides, pvc, i.options.dryRun)
if err != nil { if err != nil {
return err return err
@ -378,9 +384,10 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
return err return err
} }
glog.V(4).Info("Successfully created federation controller manager deployment") glog.V(4).Info("Successfully created federation controller manager deployment")
fmt.Fprint(cmdOut, " done\n") fmt.Println(cmdOut, " done")
fmt.Fprint(cmdOut, "Updating kubeconfig ") fmt.Fprint(cmdOut, "Updating kubeconfig...")
glog.V(4).Info("Updating kubeconfig")
// Pick the first ip/hostname to update the api server endpoint in kubeconfig and also to give information to user // Pick the first ip/hostname to update the api server endpoint in kubeconfig and also to give information to user
// In case of NodePort Service for api server, ips are node external ips. // In case of NodePort Service for api server, ips are node external ips.
endpoint := "" endpoint := ""
@ -396,25 +403,30 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
err = updateKubeconfig(config, i.commonOptions.Name, endpoint, i.commonOptions.Kubeconfig, credentials, i.options.dryRun) err = updateKubeconfig(config, i.commonOptions.Name, endpoint, i.commonOptions.Kubeconfig, credentials, i.options.dryRun)
if err != nil { if err != nil {
glog.V(4).Infof("Failed to update kubeconfig: %v", err)
return err return err
} }
fmt.Fprint(cmdOut, " done\n") fmt.Fprintln(cmdOut, " done")
glog.V(4).Info("Successfully updated kubeconfig")
if !i.options.dryRun { if !i.options.dryRun {
fmt.Fprint(cmdOut, "Waiting for federation control plane to come up ") fmt.Fprint(cmdOut, "Waiting for federation control plane to come up...")
glog.V(4).Info("Waiting for federation control plane to come up")
fedPods := []string{serverName, cmName} fedPods := []string{serverName, cmName}
err = waitForPods(hostClientset, fedPods, i.commonOptions.FederationSystemNamespace) err = waitForPods(cmdOut, hostClientset, fedPods, i.commonOptions.FederationSystemNamespace)
if err != nil { if err != nil {
return err return err
} }
err = waitSrvHealthy(config, i.commonOptions.Name, i.commonOptions.Kubeconfig) err = waitSrvHealthy(cmdOut, config, i.commonOptions.Name, i.commonOptions.Kubeconfig)
fmt.Fprint(cmdOut, " done\n")
if err != nil { if err != nil {
return err return err
} }
glog.V(4).Info("Federation control plane running")
fmt.Fprintln(cmdOut, " done")
return printSuccess(cmdOut, ips, hostnames, svc) return printSuccess(cmdOut, ips, hostnames, svc)
} }
_, err = fmt.Fprintf(cmdOut, "Federation control plane runs (dry run)\n") _, err = fmt.Fprintln(cmdOut, "Federation control plane runs (dry run)")
glog.V(4).Info("Federation control plane runs (dry run)")
return err return err
} }
@ -433,7 +445,7 @@ func createNamespace(clientset client.Interface, federationName, namespace strin
return clientset.Core().Namespaces().Create(ns) return clientset.Core().Namespaces().Create(ns)
} }
func createService(clientset client.Interface, namespace, svcName, federationName, apiserverAdvertiseAddress string, apiserverServiceType v1.ServiceType, dryRun bool) (*api.Service, []string, []string, error) { func createService(cmdOut io.Writer, clientset client.Interface, namespace, svcName, federationName, apiserverAdvertiseAddress string, apiserverServiceType v1.ServiceType, dryRun bool) (*api.Service, []string, []string, error) {
svc := &api.Service{ svc := &api.Service{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: svcName, Name: svcName,
@ -465,7 +477,7 @@ func createService(clientset client.Interface, namespace, svcName, federationNam
ips := []string{} ips := []string{}
hostnames := []string{} hostnames := []string{}
if apiserverServiceType == v1.ServiceTypeLoadBalancer { if apiserverServiceType == v1.ServiceTypeLoadBalancer {
ips, hostnames, err = waitForLoadBalancerAddress(clientset, svc, dryRun) ips, hostnames, err = waitForLoadBalancerAddress(cmdOut, clientset, svc, dryRun)
} else { } else {
if apiserverAdvertiseAddress != "" { if apiserverAdvertiseAddress != "" {
ips = append(ips, apiserverAdvertiseAddress) ips = append(ips, apiserverAdvertiseAddress)
@ -504,7 +516,7 @@ func getClusterNodeIPs(clientset client.Interface) ([]string, error) {
return nodeAddresses, nil return nodeAddresses, nil
} }
func waitForLoadBalancerAddress(clientset client.Interface, svc *api.Service, dryRun bool) ([]string, []string, error) { func waitForLoadBalancerAddress(cmdOut io.Writer, clientset client.Interface, svc *api.Service, dryRun bool) ([]string, []string, error) {
ips := []string{} ips := []string{}
hostnames := []string{} hostnames := []string{}
@ -513,6 +525,7 @@ func waitForLoadBalancerAddress(clientset client.Interface, svc *api.Service, dr
} }
err := wait.PollImmediateInfinite(lbAddrRetryInterval, func() (bool, error) { err := wait.PollImmediateInfinite(lbAddrRetryInterval, func() (bool, error) {
fmt.Fprint(cmdOut, ".")
pollSvc, err := clientset.Core().Services(svc.Namespace).Get(svc.Name, metav1.GetOptions{}) pollSvc, err := clientset.Core().Services(svc.Namespace).Get(svc.Name, metav1.GetOptions{})
if err != nil { if err != nil {
return false, nil return false, nil
@ -968,8 +981,9 @@ func argMapsToArgStrings(argsMap, overrides map[string]string) []string {
return args return args
} }
func waitForPods(clientset client.Interface, fedPods []string, namespace string) error { func waitForPods(cmdOut io.Writer, clientset client.Interface, fedPods []string, namespace string) error {
err := wait.PollInfinite(podWaitInterval, func() (bool, error) { err := wait.PollInfinite(podWaitInterval, func() (bool, error) {
fmt.Fprint(cmdOut, ".")
podCheck := len(fedPods) podCheck := len(fedPods)
podList, err := clientset.Core().Pods(namespace).List(metav1.ListOptions{}) podList, err := clientset.Core().Pods(namespace).List(metav1.ListOptions{})
if err != nil { if err != nil {
@ -991,13 +1005,14 @@ func waitForPods(clientset client.Interface, fedPods []string, namespace string)
return err return err
} }
func waitSrvHealthy(config util.AdminConfig, context, kubeconfig string) error { func waitSrvHealthy(cmdOut io.Writer, config util.AdminConfig, context, kubeconfig string) error {
fedClientSet, err := config.FederationClientset(context, kubeconfig) fedClientSet, err := config.FederationClientset(context, kubeconfig)
if err != nil { if err != nil {
return err return err
} }
fedDiscoveryClient := fedClientSet.Discovery() fedDiscoveryClient := fedClientSet.Discovery()
err = wait.PollInfinite(podWaitInterval, func() (bool, error) { err = wait.PollInfinite(podWaitInterval, func() (bool, error) {
fmt.Fprint(cmdOut, ".")
body, err := fedDiscoveryClient.RESTClient().Get().AbsPath("/healthz").Do().Raw() body, err := fedDiscoveryClient.RESTClient().Get().AbsPath("/healthz").Do().Raw()
if err != nil { if err != nil {
return false, nil return false, nil