github.com/jlmeeker/kismatic@v1.10.1-0.20180612190640-57f9005a1f1a/pkg/cli/apply.go (about)

     1  package cli
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  
     8  	"github.com/apprenda/kismatic/pkg/install"
     9  	"github.com/apprenda/kismatic/pkg/util"
    10  	"github.com/spf13/cobra"
    11  )
    12  
    13  type applyCmd struct {
    14  	out                io.Writer
    15  	planner            install.Planner
    16  	executor           install.Executor
    17  	planFile           string
    18  	generatedAssetsDir string
    19  	verbose            bool
    20  	outputFormat       string
    21  	skipPreFlight      bool
    22  	restartServices    bool
    23  	limit              []string
    24  }
    25  
    26  type applyOpts struct {
    27  	generatedAssetsDir string
    28  	restartServices    bool
    29  	verbose            bool
    30  	outputFormat       string
    31  	skipPreFlight      bool
    32  	limit              []string
    33  }
    34  
    35  // NewCmdApply creates a cluter using the plan file
    36  func NewCmdApply(out io.Writer, installOpts *installOpts) *cobra.Command {
    37  	applyOpts := applyOpts{}
    38  	cmd := &cobra.Command{
    39  		Use:   "apply",
    40  		Short: "apply your plan file to create a Kubernetes cluster",
    41  		RunE: func(cmd *cobra.Command, args []string) error {
    42  			if len(args) != 0 {
    43  				return fmt.Errorf("Unexpected args: %v", args)
    44  			}
    45  			planner := &install.FilePlanner{File: installOpts.planFilename}
    46  			executorOpts := install.ExecutorOptions{
    47  				GeneratedAssetsDirectory: applyOpts.generatedAssetsDir,
    48  				OutputFormat:             applyOpts.outputFormat,
    49  				Verbose:                  applyOpts.verbose,
    50  			}
    51  			executor, err := install.NewExecutor(out, os.Stderr, executorOpts)
    52  			if err != nil {
    53  				return err
    54  			}
    55  
    56  			applyCmd := &applyCmd{
    57  				out:                out,
    58  				planner:            planner,
    59  				executor:           executor,
    60  				planFile:           installOpts.planFilename,
    61  				generatedAssetsDir: applyOpts.generatedAssetsDir,
    62  				verbose:            applyOpts.verbose,
    63  				outputFormat:       applyOpts.outputFormat,
    64  				skipPreFlight:      applyOpts.skipPreFlight,
    65  				restartServices:    applyOpts.restartServices,
    66  				limit:              applyOpts.limit,
    67  			}
    68  			return applyCmd.run()
    69  		},
    70  	}
    71  
    72  	// Flags
    73  	cmd.Flags().StringSliceVar(&applyOpts.limit, "limit", []string{}, "comma-separated list of hostnames to limit the execution to a subset of nodes")
    74  	cmd.Flags().StringVar(&applyOpts.generatedAssetsDir, "generated-assets-dir", "generated", "path to the directory where assets generated during the installation process will be stored")
    75  	cmd.Flags().BoolVar(&applyOpts.restartServices, "restart-services", false, "force restart cluster services (Use with care)")
    76  	cmd.Flags().BoolVar(&applyOpts.verbose, "verbose", false, "enable verbose logging from the installation")
    77  	cmd.Flags().StringVarP(&applyOpts.outputFormat, "output", "o", "simple", "installation output format (options \"simple\"|\"raw\")")
    78  	cmd.Flags().BoolVar(&applyOpts.skipPreFlight, "skip-preflight", false, "skip pre-flight checks, useful when rerunning kismatic")
    79  
    80  	return cmd
    81  }
    82  
    83  func (c *applyCmd) run() error {
    84  	// Validate and run pre-flight
    85  	opts := &validateOpts{
    86  		planFile:           c.planFile,
    87  		verbose:            c.verbose,
    88  		outputFormat:       c.outputFormat,
    89  		skipPreFlight:      c.skipPreFlight,
    90  		generatedAssetsDir: c.generatedAssetsDir,
    91  		limit:              c.limit,
    92  	}
    93  	err := doValidate(c.out, c.planner, opts)
    94  	if err != nil {
    95  		return fmt.Errorf("error validating plan: %v", err)
    96  	}
    97  	plan, err := c.planner.Read()
    98  	if err != nil {
    99  		return fmt.Errorf("error reading plan file: %v", err)
   100  	}
   101  
   102  	// Generate certificates
   103  	if err := c.executor.GenerateCertificates(plan, false); err != nil {
   104  		return fmt.Errorf("error installing: %v", err)
   105  	}
   106  
   107  	// Generate kubeconfig
   108  	util.PrintHeader(c.out, "Generating Kubeconfig File", '=')
   109  	err = install.GenerateKubeconfig(plan, c.generatedAssetsDir)
   110  	if err != nil {
   111  		return fmt.Errorf("error generating kubeconfig file: %v", err)
   112  	}
   113  	util.PrettyPrintOk(c.out, "Generated kubeconfig file in the %q directory", c.generatedAssetsDir)
   114  
   115  	// Perform the installation
   116  	if err := c.executor.Install(plan, c.restartServices, c.limit...); err != nil {
   117  		return fmt.Errorf("error installing: %v", err)
   118  	}
   119  
   120  	// Run smoketest
   121  	// Don't run
   122  	if plan.NetworkConfigured() {
   123  		if err := c.executor.RunSmokeTest(plan); err != nil {
   124  			return fmt.Errorf("error running smoke test: %v", err)
   125  		}
   126  	}
   127  
   128  	util.PrintColor(c.out, util.Green, "\nThe cluster was installed successfully!\n")
   129  	fmt.Fprintln(c.out)
   130  
   131  	msg := "- To use the generated kubeconfig file with kubectl:" +
   132  		"\n    * use \"./kubectl --kubeconfig %s/kubeconfig\"" +
   133  		"\n    * or copy the config file \"cp %[1]s/kubeconfig ~/.kube/config\"\n"
   134  	util.PrintColor(c.out, util.Blue, msg, c.generatedAssetsDir)
   135  	util.PrintColor(c.out, util.Blue, "- To view the Kubernetes dashboard: \"./kismatic dashboard\"\n")
   136  	util.PrintColor(c.out, util.Blue, "- To SSH into a cluster node: \"./kismatic ssh etcd|master|worker|storage|$node.host\"\n")
   137  	fmt.Fprintln(c.out)
   138  
   139  	return nil
   140  }