package cmd import ( "encoding/json" "errors" "fmt" "io" "net/url" "os" "strings" "time" "github.com/cozy/cozy-stack/client" "github.com/cozy/cozy-stack/client/request" "github.com/spf13/cobra" ) var flagJobJSONArg string var flagJobPrintLogs bool var flagJobPrintLogsVerbose bool var flagJobWorkers []string var flagJobsPurgeDuration string var jobsCmdGroup = &cobra.Command{ Use: "jobs ", Short: "Launch and manage jobs and workers", } var jobsRunCmd = &cobra.Command{ Use: "run ", Aliases: []string{"launch", "push"}, Example: `$ cozy-stack jobs run service --domain example.mycozy.cloud --json '{"slug": "banks", "name": "onOperationOrBillCreate", "file": "onOperationOrBillCreate.js"}'`, RunE: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return cmd.Help() } if flagDomain == "" { return errMissingDomain } if flagJobJSONArg == "" { return errors.New("The JSON argument is missing") } c := newClient(flagDomain, "io.cozy.jobs", "io.cozy.jobs.logs") o := &client.JobOptions{ Worker: args[0], Arguments: json.RawMessage(flagJobJSONArg), } if flagJobPrintLogs { o.Logs = make(chan *client.JobLog) go func() { for log := range o.Logs { fmt.Fprintf(os.Stdout, "[%s]", log.Level) if flagJobPrintLogsVerbose { fmt.Fprintf(os.Stdout, "[time:%s]", log.Time.Format(time.RFC3339)) for k, v := range log.Data { fmt.Fprintf(os.Stdout, "[%s:%s]", k, v) } } fmt.Fprintf(os.Stdout, " %s\n", log.Message) } }() } j, err := c.JobPush(o) if err != nil { return err } b, err := json.MarshalIndent(j, "", " ") if err != nil { return err } fmt.Println(string(b)) return nil }, } var jobsPurgeCmd = &cobra.Command{ Use: "purge-old-jobs ", Short: `Purge old jobs from an instance`, Example: `$ cozy-stack jobs purge-old-jobs example.mycozy.cloud`, RunE: func(cmd *cobra.Command, args []string) error { if len(args) != 1 { return cmd.Help() } var workers string if flagJobWorkers != nil { workers = strings.Join(flagJobWorkers, ",") } duration := flagJobsPurgeDuration q := url.Values{ "duration": {duration}, "workers": {workers}, } c := newClient(args[0], "io.cozy.jobs:DELETE") res, err := c.Req(&request.Options{ Method: "DELETE", Path: "/jobs/purge", Queries: q, }) if err != nil { return err } resContent, err := io.ReadAll(res.Body) if err != nil { return err } fmt.Println(string(resContent)) return nil }, } func init() { jobsCmdGroup.PersistentFlags().StringVar(&flagDomain, "domain", cozyDomain(), "specify the domain name of the instance") jobsRunCmd.Flags().StringVar(&flagJobJSONArg, "json", "", "specify the job arguments as raw JSON") jobsRunCmd.Flags().BoolVar(&flagJobPrintLogs, "logs", false, "print jobs log in stdout") jobsRunCmd.Flags().BoolVar(&flagJobPrintLogsVerbose, "logs-verbose", false, "verbose logging (with --logs flag)") jobsPurgeCmd.Flags().StringSliceVar(&flagJobWorkers, "workers", nil, "worker types to iterate over (all workers by default)") jobsPurgeCmd.Flags().StringVar(&flagJobsPurgeDuration, "duration", "", "duration to look for (ie. 3D, 2M)") jobsCmdGroup.AddCommand(jobsRunCmd) jobsCmdGroup.AddCommand(jobsPurgeCmd) RootCmd.AddCommand(jobsCmdGroup) }