github.com/pingcap/tiup@v1.15.1/components/cluster/command/deploy.go (about)

     1  // Copyright 2020 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package command
    15  
    16  import (
    17  	"context"
    18  	"os"
    19  	"path"
    20  
    21  	"github.com/pingcap/tiup/pkg/cluster/manager"
    22  	operator "github.com/pingcap/tiup/pkg/cluster/operation"
    23  	"github.com/pingcap/tiup/pkg/cluster/spec"
    24  	"github.com/pingcap/tiup/pkg/cluster/task"
    25  	"github.com/pingcap/tiup/pkg/telemetry"
    26  	"github.com/pingcap/tiup/pkg/tui"
    27  	"github.com/pingcap/tiup/pkg/utils"
    28  	"github.com/spf13/cobra"
    29  )
    30  
    31  var (
    32  	errNSDeploy            = errNS.NewSubNamespace("deploy")
    33  	errDeployNameDuplicate = errNSDeploy.NewType("name_dup", utils.ErrTraitPreCheck)
    34  )
    35  
    36  func newDeploy() *cobra.Command {
    37  	opt := manager.DeployOptions{
    38  		IdentityFile: path.Join(utils.UserHome(), ".ssh", "id_rsa"),
    39  	}
    40  	cmd := &cobra.Command{
    41  		Use:          "deploy <cluster-name> <version> <topology.yaml>",
    42  		Short:        "Deploy a cluster for production",
    43  		Long:         "Deploy a cluster for production. SSH connection will be used to deploy files, as well as creating system users for running the service.",
    44  		SilenceUsage: true,
    45  		RunE: func(cmd *cobra.Command, args []string) error {
    46  			shouldContinue, err := tui.CheckCommandArgsAndMayPrintHelp(cmd, args, 3)
    47  			if err != nil {
    48  				return err
    49  			}
    50  			if !shouldContinue {
    51  				return nil
    52  			}
    53  
    54  			clusterName := args[0]
    55  			version, err := utils.FmtVer(args[1])
    56  			if err != nil {
    57  				return err
    58  			}
    59  			clusterReport.ID = scrubClusterName(clusterName)
    60  			teleCommand = append(teleCommand, scrubClusterName(clusterName))
    61  			teleCommand = append(teleCommand, version)
    62  
    63  			topoFile := args[2]
    64  			if data, err := os.ReadFile(topoFile); err == nil {
    65  				teleTopology = string(data)
    66  			}
    67  
    68  			return cm.Deploy(clusterName, version, topoFile, opt, postDeployHook, skipConfirm, gOpt)
    69  		},
    70  		ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
    71  			switch len(args) {
    72  			case 2:
    73  				return nil, cobra.ShellCompDirectiveDefault
    74  			default:
    75  				return nil, cobra.ShellCompDirectiveNoFileComp
    76  			}
    77  		},
    78  	}
    79  
    80  	cmd.Flags().StringVarP(&opt.User, "user", "u", utils.CurrentUser(), "The user name to login via SSH. The user must has root (or sudo) privilege.")
    81  	cmd.Flags().BoolVarP(&opt.SkipCreateUser, "skip-create-user", "", false, "(EXPERIMENTAL) Skip creating the user specified in topology.")
    82  	cmd.Flags().StringVarP(&opt.IdentityFile, "identity_file", "i", opt.IdentityFile, "The path of the SSH identity file. If specified, public key authentication will be used.")
    83  	cmd.Flags().BoolVarP(&opt.UsePassword, "password", "p", false, "Use password of target hosts. If specified, password authentication will be used.")
    84  	cmd.Flags().BoolVarP(&gOpt.IgnoreConfigCheck, "ignore-config-check", "", false, "Ignore the config check result of components")
    85  	cmd.Flags().BoolVarP(&opt.NoLabels, "no-labels", "", false, "Don't check TiKV labels")
    86  
    87  	return cmd
    88  }
    89  
    90  func postDeployHook(builder *task.Builder, topo spec.Topology, gOpt operator.Options) {
    91  	nodeInfoTask := task.NewBuilder(builder.Logger).Func("Check status", func(ctx context.Context) error {
    92  		var err error
    93  		teleNodeInfos, err = operator.GetNodeInfo(ctx, topo)
    94  		_ = err
    95  		// intend to never return error
    96  		return nil
    97  	}).BuildAsStep("Check status").SetHidden(true)
    98  
    99  	if telemetry.Enabled() {
   100  		builder.ParallelStep("+ Check status", false, nodeInfoTask)
   101  	}
   102  
   103  	enableTask := task.NewBuilder(builder.Logger).Func("Setting service auto start on boot", func(ctx context.Context) error {
   104  		return operator.Enable(ctx, topo, operator.Options{}, true)
   105  	}).BuildAsStep("Enable service").SetHidden(true)
   106  
   107  	builder.Parallel(false, enableTask)
   108  }