github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/cmd/executor/executor.go (about)

     1  // Copyright 2022 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 executor
    15  
    16  import (
    17  	"context"
    18  	"os"
    19  
    20  	"github.com/gin-gonic/gin"
    21  	"github.com/pingcap/log"
    22  	"github.com/pingcap/tiflow/engine/executor"
    23  	"github.com/pingcap/tiflow/engine/pkg/cmd/util"
    24  	cmdconetxt "github.com/pingcap/tiflow/pkg/cmd/context"
    25  	ticdcutil "github.com/pingcap/tiflow/pkg/cmd/util"
    26  	"github.com/pingcap/tiflow/pkg/errors"
    27  	"github.com/pingcap/tiflow/pkg/logutil"
    28  	"github.com/pingcap/tiflow/pkg/version"
    29  	"github.com/spf13/cobra"
    30  	"github.com/spf13/pflag"
    31  	"go.uber.org/zap"
    32  )
    33  
    34  // options defines flags for the `server` command.
    35  type options struct {
    36  	executorConfig         *executor.Config
    37  	executorConfigFilePath string
    38  }
    39  
    40  // newOptions creates new options for the `server` command.
    41  func newOptions() *options {
    42  	return &options{
    43  		executorConfig: executor.GetDefaultExecutorConfig(),
    44  	}
    45  }
    46  
    47  // addFlags receives a *cobra.Command reference and binds
    48  // flags related to template printing to it.
    49  func (o *options) addFlags(cmd *cobra.Command) {
    50  	cmd.Flags().StringVar(&o.executorConfig.Name, "name", o.executorConfig.Name, "human readable name for executor")
    51  	cmd.Flags().StringVar(&o.executorConfig.Addr, "addr", o.executorConfig.Addr, "Set the listening address for executor")
    52  	cmd.Flags().StringVar(&o.executorConfig.AdvertiseAddr, "advertise-addr", o.executorConfig.AdvertiseAddr, "Set the advertise listening address for client communication")
    53  
    54  	cmd.Flags().StringVar(&o.executorConfig.Join, "join", o.executorConfig.Join, "join to an existing cluster (usage: server masters' address)")
    55  	cmd.Flags().StringToStringVar(&o.executorConfig.Labels, "labels", map[string]string{}, "labels to the executor in key-value pairs")
    56  
    57  	cmd.Flags().StringVar(&o.executorConfigFilePath, "config", "", "Path of the configuration file")
    58  	cmd.Flags().StringVar(&o.executorConfig.LogConf.File, "log-file", o.executorConfig.LogConf.File, "log file path")
    59  	cmd.Flags().StringVar(&o.executorConfig.LogConf.Level, "log-level", o.executorConfig.LogConf.Level, "log level (etc: debug|info|warn|error)")
    60  }
    61  
    62  // run runs the server cmd.
    63  func (o *options) run(cmd *cobra.Command) error {
    64  	err := logutil.InitLogger(&o.executorConfig.LogConf)
    65  	if err != nil {
    66  		return errors.Trace(err)
    67  	}
    68  
    69  	version.LogVersionInfo("TiFlow Executor")
    70  	if os.Getenv(gin.EnvGinMode) == "" {
    71  		gin.SetMode(gin.ReleaseMode)
    72  	}
    73  
    74  	cancel := util.InitCmd(cmd)
    75  	defer cancel()
    76  
    77  	ticdcutil.LogHTTPProxies()
    78  
    79  	server := executor.NewServer(o.executorConfig)
    80  
    81  	err = server.Run(cmdconetxt.GetDefaultContext())
    82  	if err != nil && errors.Cause(err) != context.Canceled {
    83  		log.Error("run dataflow executor with error", zap.Error(err))
    84  		return errors.Trace(err)
    85  	}
    86  	log.Info("dataflow executor exits successfully")
    87  
    88  	return nil
    89  }
    90  
    91  // complete adapts from the command line args and config file to the data required.
    92  func (o *options) complete(cmd *cobra.Command) error {
    93  	cfg := executor.GetDefaultExecutorConfig()
    94  
    95  	if len(o.executorConfigFilePath) > 0 {
    96  		if err := ticdcutil.StrictDecodeFile(
    97  			o.executorConfigFilePath, "dataflow engine executor", cfg); err != nil {
    98  			return err
    99  		}
   100  	}
   101  
   102  	cmd.Flags().Visit(func(flag *pflag.Flag) {
   103  		switch flag.Name {
   104  		case "name":
   105  			cfg.Name = o.executorConfig.Name
   106  		case "addr":
   107  			cfg.Addr = o.executorConfig.Addr
   108  		case "advertise-addr":
   109  			cfg.AdvertiseAddr = o.executorConfig.AdvertiseAddr
   110  		case "join":
   111  			cfg.Join = o.executorConfig.Join
   112  		case "labels":
   113  			cfg.Labels = o.executorConfig.Labels
   114  		case "config":
   115  			// do nothing
   116  		case "log-file":
   117  			cfg.LogConf.File = o.executorConfig.LogConf.File
   118  		case "log-level":
   119  			cfg.LogConf.Level = o.executorConfig.LogConf.Level
   120  		default:
   121  			log.Panic("unknown flag, please report a bug", zap.String("flagName", flag.Name))
   122  		}
   123  	})
   124  
   125  	if err := cfg.Adjust(); err != nil {
   126  		return errors.Trace(err)
   127  	}
   128  
   129  	o.executorConfig = cfg
   130  
   131  	return nil
   132  }
   133  
   134  // NewCmdExecutor creates the `master` command.
   135  func NewCmdExecutor() *cobra.Command {
   136  	o := newOptions()
   137  
   138  	command := &cobra.Command{
   139  		Use:   "executor",
   140  		Short: "Start a dataflow engine executor",
   141  		Args:  cobra.NoArgs,
   142  		RunE: func(cmd *cobra.Command, args []string) error {
   143  			err := o.complete(cmd)
   144  			if err != nil {
   145  				return err
   146  			}
   147  			err = o.run(cmd)
   148  			cobra.CheckErr(err)
   149  			return nil
   150  		},
   151  	}
   152  
   153  	o.addFlags(command)
   154  
   155  	return command
   156  }