[Federation] Implement dry run support in kubefed init

This commit is contained in:
Irfan Ur Rehman 2016-11-10 18:39:47 +05:30
parent 98d55db5ec
commit 0462c656e8

View File

@ -120,6 +120,7 @@ func NewCmdInit(cmdOut io.Writer, config util.AdminConfig) *cobra.Command {
cmd.Flags().String("image", defaultImage, "Image to use for federation API server and controller manager binaries.") cmd.Flags().String("image", defaultImage, "Image to use for federation API server and controller manager binaries.")
cmd.Flags().String("dns-provider", "google-clouddns", "Dns provider to be used for this deployment.") cmd.Flags().String("dns-provider", "google-clouddns", "Dns provider to be used for this deployment.")
cmd.Flags().String("etcd-pv-capacity", "10Gi", "Size of persistent volume claim to be used for etcd.") cmd.Flags().String("etcd-pv-capacity", "10Gi", "Size of persistent volume claim to be used for etcd.")
cmd.Flags().Bool("dry-run", false, "dry run without sending commands to server.")
return cmd return cmd
} }
@ -142,6 +143,7 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman
image := cmdutil.GetFlagString(cmd, "image") image := cmdutil.GetFlagString(cmd, "image")
dnsProvider := cmdutil.GetFlagString(cmd, "dns-provider") dnsProvider := cmdutil.GetFlagString(cmd, "dns-provider")
etcdPVCapacity := cmdutil.GetFlagString(cmd, "etcd-pv-capacity") etcdPVCapacity := cmdutil.GetFlagString(cmd, "etcd-pv-capacity")
dryRun := cmdutil.GetDryRunFlag(cmd)
hostFactory := config.HostFactory(initFlags.Host, initFlags.Kubeconfig) hostFactory := config.HostFactory(initFlags.Host, initFlags.Kubeconfig)
hostClientset, err := hostFactory.ClientSet() hostClientset, err := hostFactory.ClientSet()
@ -155,17 +157,17 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman
cmKubeconfigName := fmt.Sprintf("%s-kubeconfig", cmName) cmKubeconfigName := fmt.Sprintf("%s-kubeconfig", cmName)
// 1. Create a namespace for federation system components // 1. Create a namespace for federation system components
_, err = createNamespace(hostClientset, initFlags.FederationSystemNamespace) _, err = createNamespace(hostClientset, initFlags.FederationSystemNamespace, dryRun)
if err != nil { if err != nil {
return err return err
} }
// 2. Expose a network endpoint for the federation API server // 2. Expose a network endpoint for the federation API server
svc, err := createService(hostClientset, initFlags.FederationSystemNamespace, serverName) svc, err := createService(hostClientset, initFlags.FederationSystemNamespace, serverName, dryRun)
if err != nil { if err != nil {
return err return err
} }
ips, hostnames, err := waitForLoadBalancerAddress(hostClientset, svc) ips, hostnames, err := waitForLoadBalancerAddress(hostClientset, svc, dryRun)
if err != nil { if err != nil {
return err return err
} }
@ -176,13 +178,13 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman
return err return err
} }
_, err = createAPIServerCredentialsSecret(hostClientset, initFlags.FederationSystemNamespace, serverCredName, entKeyPairs) _, err = createAPIServerCredentialsSecret(hostClientset, initFlags.FederationSystemNamespace, serverCredName, entKeyPairs, dryRun)
if err != nil { if err != nil {
return err return err
} }
// 4. Create a kubeconfig secret // 4. Create a kubeconfig secret
_, err = createControllerManagerKubeconfigSecret(hostClientset, initFlags.FederationSystemNamespace, initFlags.Name, svc.Name, cmKubeconfigName, entKeyPairs) _, err = createControllerManagerKubeconfigSecret(hostClientset, initFlags.FederationSystemNamespace, initFlags.Name, svc.Name, cmKubeconfigName, entKeyPairs, dryRun)
if err != nil { if err != nil {
return err return err
} }
@ -190,7 +192,7 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman
// 5. Create a persistent volume and a claim to store the federation // 5. Create a persistent volume and a claim to store the federation
// API server's state. This is where federation API server's etcd // API server's state. This is where federation API server's etcd
// stores its data. // stores its data.
pvc, err := createPVC(hostClientset, initFlags.FederationSystemNamespace, svc.Name, etcdPVCapacity) pvc, err := createPVC(hostClientset, initFlags.FederationSystemNamespace, svc.Name, etcdPVCapacity, dryRun)
if err != nil { if err != nil {
return err return err
} }
@ -208,38 +210,47 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman
} }
// 6. Create federation API server // 6. Create federation API server
_, err = createAPIServer(hostClientset, initFlags.FederationSystemNamespace, serverName, image, serverCredName, pvc.Name, advertiseAddress) _, err = createAPIServer(hostClientset, initFlags.FederationSystemNamespace, serverName, image, serverCredName, pvc.Name, advertiseAddress, dryRun)
if err != nil { if err != nil {
return err return err
} }
// 7. Create federation controller manager // 7. Create federation controller manager
_, err = createControllerManager(hostClientset, initFlags.FederationSystemNamespace, initFlags.Name, svc.Name, cmName, image, cmKubeconfigName, dnsZoneName, dnsProvider) _, err = createControllerManager(hostClientset, initFlags.FederationSystemNamespace, initFlags.Name, svc.Name, cmName, image, cmKubeconfigName, dnsZoneName, dnsProvider, dryRun)
if err != nil { if err != nil {
return err return err
} }
// 8. Write the federation API server endpoint info, credentials // 8. Write the federation API server endpoint info, credentials
// and context to kubeconfig // and context to kubeconfig
err = updateKubeconfig(config, initFlags.Name, endpoint, entKeyPairs) err = updateKubeconfig(config, initFlags.Name, endpoint, entKeyPairs, dryRun)
if err != nil { if err != nil {
return err return err
} }
if !dryRun {
return printSuccess(cmdOut, ips, hostnames) return printSuccess(cmdOut, ips, hostnames)
} else {
_, err := fmt.Fprintf(cmdOut, "Federation control plane runs (dry run)\n")
return err
}
} }
func createNamespace(clientset *client.Clientset, namespace string) (*api.Namespace, error) { func createNamespace(clientset *client.Clientset, namespace string, dryRun bool) (*api.Namespace, error) {
ns := &api.Namespace{ ns := &api.Namespace{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: namespace, Name: namespace,
}, },
} }
if dryRun {
return ns, nil
}
return clientset.Core().Namespaces().Create(ns) return clientset.Core().Namespaces().Create(ns)
} }
func createService(clientset *client.Clientset, namespace, svcName string) (*api.Service, error) { func createService(clientset *client.Clientset, namespace, svcName string, dryRun bool) (*api.Service, error) {
svc := &api.Service{ svc := &api.Service{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: svcName, Name: svcName,
@ -260,13 +271,21 @@ func createService(clientset *client.Clientset, namespace, svcName string) (*api
}, },
} }
if dryRun {
return svc, nil
}
return clientset.Core().Services(namespace).Create(svc) return clientset.Core().Services(namespace).Create(svc)
} }
func waitForLoadBalancerAddress(clientset *client.Clientset, svc *api.Service) ([]string, []string, error) { func waitForLoadBalancerAddress(clientset *client.Clientset, svc *api.Service, dryRun bool) ([]string, []string, error) {
ips := []string{} ips := []string{}
hostnames := []string{} hostnames := []string{}
if dryRun {
return ips, hostnames, nil
}
err := wait.PollImmediateInfinite(lbAddrRetryInterval, func() (bool, error) { err := wait.PollImmediateInfinite(lbAddrRetryInterval, func() (bool, error) {
pollSvc, err := clientset.Core().Services(svc.Namespace).Get(svc.Name) pollSvc, err := clientset.Core().Services(svc.Namespace).Get(svc.Name)
if err != nil { if err != nil {
@ -319,7 +338,7 @@ func genCerts(svcNamespace, name, svcName, localDNSZoneName string, ips, hostnam
}, nil }, nil
} }
func createAPIServerCredentialsSecret(clientset *client.Clientset, namespace, credentialsName string, entKeyPairs *entityKeyPairs) (*api.Secret, error) { func createAPIServerCredentialsSecret(clientset *client.Clientset, namespace, credentialsName string, entKeyPairs *entityKeyPairs, dryRun bool) (*api.Secret, error) {
// Build the secret object with API server credentials. // Build the secret object with API server credentials.
secret := &api.Secret{ secret := &api.Secret{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
@ -333,11 +352,14 @@ func createAPIServerCredentialsSecret(clientset *client.Clientset, namespace, cr
}, },
} }
if dryRun {
return secret, nil
}
// Boilerplate to create the secret in the host cluster. // Boilerplate to create the secret in the host cluster.
return clientset.Core().Secrets(namespace).Create(secret) return clientset.Core().Secrets(namespace).Create(secret)
} }
func createControllerManagerKubeconfigSecret(clientset *client.Clientset, namespace, name, svcName, kubeconfigName string, entKeyPairs *entityKeyPairs) (*api.Secret, error) { func createControllerManagerKubeconfigSecret(clientset *client.Clientset, namespace, name, svcName, kubeconfigName string, entKeyPairs *entityKeyPairs, dryRun bool) (*api.Secret, error) {
basicClientConfig := kubeadmutil.CreateBasicClientConfig( basicClientConfig := kubeadmutil.CreateBasicClientConfig(
name, name,
fmt.Sprintf("https://%s", svcName), fmt.Sprintf("https://%s", svcName),
@ -352,10 +374,13 @@ func createControllerManagerKubeconfigSecret(clientset *client.Clientset, namesp
certutil.EncodeCertPEM(entKeyPairs.controllerManager.Cert), certutil.EncodeCertPEM(entKeyPairs.controllerManager.Cert),
) )
if dryRun {
return nil, nil
}
return util.CreateKubeconfigSecret(clientset, config, namespace, kubeconfigName, false) return util.CreateKubeconfigSecret(clientset, config, namespace, kubeconfigName, false)
} }
func createPVC(clientset *client.Clientset, namespace, svcName, etcdPVCapacity string) (*api.PersistentVolumeClaim, error) { func createPVC(clientset *client.Clientset, namespace, svcName, etcdPVCapacity string, dryRun bool) (*api.PersistentVolumeClaim, error) {
capacity, err := resource.ParseQuantity(etcdPVCapacity) capacity, err := resource.ParseQuantity(etcdPVCapacity)
if err != nil { if err != nil {
return nil, err return nil, err
@ -382,10 +407,14 @@ func createPVC(clientset *client.Clientset, namespace, svcName, etcdPVCapacity s
}, },
} }
if dryRun {
return pvc, nil
}
return clientset.Core().PersistentVolumeClaims(namespace).Create(pvc) return clientset.Core().PersistentVolumeClaims(namespace).Create(pvc)
} }
func createAPIServer(clientset *client.Clientset, namespace, name, image, credentialsName, pvcName, advertiseAddress string) (*extensions.Deployment, error) { func createAPIServer(clientset *client.Clientset, namespace, name, image, credentialsName, pvcName, advertiseAddress string, dryRun bool) (*extensions.Deployment, error) {
command := []string{ command := []string{
"/hyperkube", "/hyperkube",
"federation-apiserver", "federation-apiserver",
@ -480,10 +509,14 @@ func createAPIServer(clientset *client.Clientset, namespace, name, image, creden
}, },
} }
if dryRun {
return dep, nil
}
return clientset.Extensions().Deployments(namespace).Create(dep) return clientset.Extensions().Deployments(namespace).Create(dep)
} }
func createControllerManager(clientset *client.Clientset, namespace, name, svcName, cmName, image, kubeconfigName, dnsZoneName, dnsProvider string) (*extensions.Deployment, error) { func createControllerManager(clientset *client.Clientset, namespace, name, svcName, cmName, image, kubeconfigName, dnsZoneName, dnsProvider string, dryRun bool) (*extensions.Deployment, error) {
dep := &extensions.Deployment{ dep := &extensions.Deployment{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: cmName, Name: cmName,
@ -546,6 +579,9 @@ func createControllerManager(clientset *client.Clientset, namespace, name, svcNa
}, },
} }
if dryRun {
return dep, nil
}
return clientset.Extensions().Deployments(namespace).Create(dep) return clientset.Extensions().Deployments(namespace).Create(dep)
} }
@ -555,7 +591,7 @@ func printSuccess(cmdOut io.Writer, ips, hostnames []string) error {
return err return err
} }
func updateKubeconfig(config util.AdminConfig, name, endpoint string, entKeyPairs *entityKeyPairs) error { func updateKubeconfig(config util.AdminConfig, name, endpoint string, entKeyPairs *entityKeyPairs, dryRun bool) error {
po := config.PathOptions() po := config.PathOptions()
kubeconfig, err := po.GetStartingConfig() kubeconfig, err := po.GetStartingConfig()
if err != nil { if err != nil {
@ -588,10 +624,12 @@ func updateKubeconfig(config util.AdminConfig, name, endpoint string, entKeyPair
kubeconfig.AuthInfos[name] = authInfo kubeconfig.AuthInfos[name] = authInfo
kubeconfig.Contexts[name] = context kubeconfig.Contexts[name] = context
if !dryRun {
// Write the update kubeconfig. // Write the update kubeconfig.
if err := clientcmd.ModifyConfig(po, *kubeconfig, true); err != nil { if err := clientcmd.ModifyConfig(po, *kubeconfig, true); err != nil {
return err return err
} }
}
return nil return nil
} }