github.com/pingcap/tiup@v1.15.1/components/cluster/command/scale_out.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  	"os"
    18  	"path/filepath"
    19  
    20  	"github.com/pingcap/tiup/pkg/cluster/manager"
    21  	operator "github.com/pingcap/tiup/pkg/cluster/operation"
    22  	"github.com/pingcap/tiup/pkg/cluster/spec"
    23  	"github.com/pingcap/tiup/pkg/cluster/task"
    24  	"github.com/pingcap/tiup/pkg/utils"
    25  	"github.com/spf13/cobra"
    26  )
    27  
    28  func newScaleOutCmd() *cobra.Command {
    29  	opt := manager.DeployOptions{
    30  		IdentityFile: filepath.Join(utils.UserHome(), ".ssh", "id_rsa"),
    31  	}
    32  	cmd := &cobra.Command{
    33  		Use:          "scale-out <cluster-name> [topology.yaml]",
    34  		Short:        "Scale out a TiDB cluster",
    35  		SilenceUsage: true,
    36  		RunE: func(cmd *cobra.Command, args []string) error {
    37  			var (
    38  				clusterName string
    39  				topoFile    string
    40  			)
    41  
    42  			// tiup cluster scale-out --stage1 --stage2
    43  			// is equivalent to
    44  			// tiup cluster scale-out
    45  			if opt.Stage1 && opt.Stage2 {
    46  				opt.Stage1 = false
    47  				opt.Stage2 = false
    48  			}
    49  
    50  			if opt.Stage2 && len(args) == 1 {
    51  				clusterName = args[0]
    52  			} else {
    53  				if len(args) != 2 {
    54  					return cmd.Help()
    55  				}
    56  				clusterName = args[0]
    57  				topoFile = args[1]
    58  			}
    59  
    60  			clusterReport.ID = scrubClusterName(clusterName)
    61  			teleCommand = append(teleCommand, scrubClusterName(clusterName))
    62  
    63  			// stage2: topoFile is ""
    64  			if data, err := os.ReadFile(topoFile); err == nil {
    65  				teleTopology = string(data)
    66  			}
    67  
    68  			return cm.ScaleOut(
    69  				clusterName,
    70  				topoFile,
    71  				postScaleOutHook,
    72  				final,
    73  				opt,
    74  				skipConfirm,
    75  				gOpt,
    76  			)
    77  		},
    78  		ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
    79  			switch len(args) {
    80  			case 0:
    81  				return shellCompGetClusterName(cm, toComplete)
    82  			case 1:
    83  				return nil, cobra.ShellCompDirectiveDefault
    84  			default:
    85  				return nil, cobra.ShellCompDirectiveNoFileComp
    86  			}
    87  		},
    88  	}
    89  
    90  	cmd.Flags().StringVarP(&opt.User, "user", "u", utils.CurrentUser(), "The user name to login via SSH. The user must has root (or sudo) privilege.")
    91  	cmd.Flags().BoolVarP(&opt.SkipCreateUser, "skip-create-user", "", false, "(EXPERIMENTAL) Skip creating the user specified in topology.")
    92  	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.")
    93  	cmd.Flags().BoolVarP(&opt.UsePassword, "password", "p", false, "Use password of target hosts. If specified, password authentication will be used.")
    94  	cmd.Flags().BoolVarP(&opt.NoLabels, "no-labels", "", false, "Don't check TiKV labels")
    95  	cmd.Flags().BoolVarP(&opt.Stage1, "stage1", "", false, "Don't start the new instance after scale-out, need to manually execute cluster scale-out --stage2")
    96  	cmd.Flags().BoolVarP(&opt.Stage2, "stage2", "", false, "Start the new instance and init config after scale-out --stage1")
    97  
    98  	return cmd
    99  }
   100  
   101  func final(builder *task.Builder, name string, meta spec.Metadata, gOpt operator.Options) {
   102  	builder.UpdateTopology(name,
   103  		tidbSpec.Path(name),
   104  		meta.(*spec.ClusterMeta),
   105  		nil, /* deleteNodeIds */
   106  	)
   107  }
   108  
   109  func postScaleOutHook(builder *task.Builder, newPart spec.Topology, gOpt operator.Options) {
   110  	postDeployHook(builder, newPart, gOpt)
   111  }