github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/ctl/master/start_task.go (about)

     1  // Copyright 2019 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 master
    15  
    16  import (
    17  	"bytes"
    18  	"context"
    19  	"errors"
    20  	"os"
    21  
    22  	"github.com/pingcap/tiflow/dm/checker"
    23  	"github.com/pingcap/tiflow/dm/config"
    24  	"github.com/pingcap/tiflow/dm/ctl/common"
    25  	"github.com/pingcap/tiflow/dm/pb"
    26  	"github.com/pingcap/tiflow/dm/pkg/log"
    27  	"github.com/pingcap/tiflow/dm/pkg/terror"
    28  	"github.com/spf13/cobra"
    29  	"go.uber.org/zap"
    30  )
    31  
    32  // NewStartTaskCmd creates a StartTask command.
    33  func NewStartTaskCmd() *cobra.Command {
    34  	cmd := &cobra.Command{
    35  		Use:   "start-task [-s source ...] [--remove-meta] <config-file>",
    36  		Short: "Starts a task as defined in the configuration file",
    37  		RunE:  startTaskFunc,
    38  	}
    39  	cmd.Flags().BoolP("remove-meta", "", false, "whether to remove task's meta data")
    40  	cmd.Flags().String("start-time", "", "specify the start time of binlog replication, e.g. '2021-10-21 00:01:00' or 2021-10-21T00:01:00")
    41  	return cmd
    42  }
    43  
    44  // startTaskFunc does start task request.
    45  func startTaskFunc(cmd *cobra.Command, _ []string) error {
    46  	if len(cmd.Flags().Args()) != 1 {
    47  		cmd.SetOut(os.Stdout)
    48  		common.PrintCmdUsage(cmd)
    49  		return errors.New("please check output to see error")
    50  	}
    51  	content, err := common.GetFileContent(cmd.Flags().Arg(0))
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	// If task's target db is configured with tls certificate related content
    57  	// the contents of the certificate need to be read and transferred to the dm-master
    58  	task := config.NewTaskConfig()
    59  	yamlErr := task.RawDecode(string(content))
    60  	if yamlErr != nil {
    61  		return yamlErr
    62  	}
    63  	if task.TargetDB != nil && task.TargetDB.Security != nil {
    64  		loadErr := task.TargetDB.Security.LoadTLSContent()
    65  		if loadErr != nil {
    66  			log.L().Warn("load tls content failed", zap.Error(terror.ErrCtlLoadTLSCfg.Generate(loadErr)))
    67  		}
    68  		content = []byte(task.String())
    69  	}
    70  
    71  	lines := bytes.Split(content, []byte("\n"))
    72  	// we check if `is-sharding` is explicitly set, to distinguish between `false` from default value
    73  	isShardingSet := false
    74  	for i := range lines {
    75  		if bytes.HasPrefix(lines[i], []byte("is-sharding")) {
    76  			isShardingSet = true
    77  			break
    78  		}
    79  	}
    80  	// we check if `shard-mode` is explicitly set, to distinguish between "" from default value
    81  	shardModeSet := false
    82  	for i := range lines {
    83  		if bytes.HasPrefix(lines[i], []byte("shard-mode")) {
    84  			shardModeSet = true
    85  			break
    86  		}
    87  	}
    88  
    89  	if isShardingSet && !task.IsSharding && task.ShardMode != "" {
    90  		common.PrintLinesf("The behaviour of `is-sharding` and `shard-mode` is conflicting. `is-sharding` is deprecated, please use `shard-mode` only.")
    91  		return errors.New("please check output to see error")
    92  	}
    93  	if shardModeSet && task.ShardMode == "" && task.IsSharding {
    94  		common.PrintLinesf("The behaviour of `is-sharding` and `shard-mode` is conflicting. `is-sharding` is deprecated, please use `shard-mode` only.")
    95  		return errors.New("please check output to see error")
    96  	}
    97  
    98  	sources, err := common.GetSourceArgs(cmd)
    99  	if err != nil {
   100  		return err
   101  	}
   102  
   103  	removeMeta, err := cmd.Flags().GetBool("remove-meta")
   104  	if err != nil {
   105  		common.PrintLinesf("error in parse `--remove-meta`")
   106  		return err
   107  	}
   108  	startTime, err := cmd.Flags().GetString("start-time")
   109  	if err != nil {
   110  		common.PrintLinesf("error in parse `--start-time`")
   111  		return err
   112  	}
   113  
   114  	ctx, cancel := context.WithCancel(context.Background())
   115  	defer cancel()
   116  
   117  	// start task
   118  	resp := &pb.StartTaskResponse{}
   119  	err = common.SendRequest(
   120  		ctx,
   121  		"StartTask",
   122  		&pb.StartTaskRequest{
   123  			Task:       string(content),
   124  			Sources:    sources,
   125  			RemoveMeta: removeMeta,
   126  			StartTime:  startTime,
   127  		},
   128  		&resp,
   129  	)
   130  
   131  	if err != nil {
   132  		return err
   133  	}
   134  
   135  	if !common.PrettyPrintResponseWithCheckTask(resp, checker.CheckTaskMsgHeader) {
   136  		common.PrettyPrintResponse(resp)
   137  	}
   138  	return nil
   139  }