github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/cmd/cli/cli_job_create.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 cli 15 16 import ( 17 "context" 18 "fmt" 19 "io" 20 "os" 21 22 "github.com/pingcap/log" 23 "github.com/pingcap/tiflow/engine/enginepb" 24 cmdcontext "github.com/pingcap/tiflow/pkg/cmd/context" 25 "github.com/pingcap/tiflow/pkg/errors" 26 "github.com/spf13/cobra" 27 "go.uber.org/zap" 28 ) 29 30 // jobCreateOptions defines flags for job create. 31 type jobCreateOptions struct { 32 generalOpts *jobGeneralOptions 33 34 jobConfigStr string 35 36 jobID string 37 jobType enginepb.Job_Type 38 jobConfig []byte 39 } 40 41 // newJobCreateOptions creates new job options. 42 func newJobCreateOptions(generalOpts *jobGeneralOptions) *jobCreateOptions { 43 return &jobCreateOptions{generalOpts: generalOpts} 44 } 45 46 // addFlags receives a *cobra.Command reference and binds 47 // flags related to template printing to it. 48 func (o *jobCreateOptions) addFlags(cmd *cobra.Command) { 49 if o == nil { 50 return 51 } 52 53 cmd.Flags().Var(newJobTypeValue(enginepb.Job_TypeUnknown, &o.jobType), "job-type", "job type, one of [FakeJob, CVSDemo, DM]") 54 cmd.Flags().StringVar(&o.jobConfigStr, "job-config", "", "path of config file for the job") 55 cmd.Flags().StringVar(&o.jobID, "job-id", "", "job id") 56 57 _ = cmd.MarkFlagRequired("job-type") 58 } 59 60 type jobTypeValue enginepb.Job_Type 61 62 func newJobTypeValue(jobType enginepb.Job_Type, p *enginepb.Job_Type) *jobTypeValue { 63 *p = jobType 64 return (*jobTypeValue)(p) 65 } 66 67 func (v *jobTypeValue) String() string { 68 if enginepb.Job_Type(*v) == enginepb.Job_TypeUnknown { 69 return "" 70 } 71 return enginepb.Job_Type(*v).String() 72 } 73 74 func (v *jobTypeValue) Set(val string) error { 75 switch val { 76 case "FakeJob": 77 *v = jobTypeValue(enginepb.Job_FakeJob) 78 case "CVSDemo": 79 *v = jobTypeValue(enginepb.Job_CVSDemo) 80 case "DM": 81 *v = jobTypeValue(enginepb.Job_DM) 82 default: 83 return fmt.Errorf("job type must be one of [FakeJob, CVSDemo, DM]") 84 } 85 return nil 86 } 87 88 func (v *jobTypeValue) Type() string { 89 return "job-type" 90 } 91 92 // validate checks that the provided job options are valid. 93 func (o *jobCreateOptions) validate(ctx context.Context) error { 94 if err := o.generalOpts.validate(ctx); err != nil { 95 return errors.WrapError(errors.ErrInvalidCliParameter, err) 96 } 97 98 jobConfig, err := openFileAndReadString(o.jobConfigStr) 99 if err != nil { 100 return errors.WrapError(errors.ErrInvalidCliParameter, err) 101 } 102 o.jobConfig = jobConfig 103 104 return nil 105 } 106 107 func openFileAndReadString(path string) (content []byte, err error) { 108 if path == "" { 109 log.Warn("create job with empty config file") 110 return nil, nil 111 } 112 fp, err := os.Open(path) 113 if err != nil { 114 return nil, err 115 } 116 defer fp.Close() 117 return io.ReadAll(fp) 118 } 119 120 // run the `cli job create` command. 121 func (o *jobCreateOptions) run(ctx context.Context) error { 122 job, err := o.generalOpts.jobManagerCli.CreateJob(ctx, &enginepb.CreateJobRequest{ 123 Job: &enginepb.Job{ 124 Type: o.jobType, 125 Config: o.jobConfig, 126 }, 127 TenantId: o.generalOpts.tenant.TenantID(), 128 ProjectId: o.generalOpts.tenant.ProjectID(), 129 }) 130 if err != nil { 131 return err 132 } 133 log.Info("create job successfully", zap.Any("job", job)) 134 return nil 135 } 136 137 // newCmdJobCreate creates the `cli job create` command. 138 func newCmdJobCreate(generalOpts *jobGeneralOptions) *cobra.Command { 139 o := newJobCreateOptions(generalOpts) 140 141 command := &cobra.Command{ 142 Use: "create", 143 Short: "Create a new job", 144 Args: cobra.NoArgs, 145 RunE: func(cmd *cobra.Command, args []string) error { 146 ctx := cmdcontext.GetDefaultContext() 147 if err := o.validate(ctx); err != nil { 148 return err 149 } 150 151 return o.run(ctx) 152 }, 153 } 154 155 o.addFlags(command) 156 157 return command 158 }