github.com/oam-dev/kubevela@v1.9.11/references/cli/workflow.go (about) 1 /* 2 Copyright 2021 The KubeVela Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package cli 18 19 import ( 20 "context" 21 "fmt" 22 "io" 23 "os" 24 25 "github.com/AlecAivazis/survey/v2" 26 "github.com/gosuri/uitable" 27 workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1" 28 "github.com/pkg/errors" 29 "github.com/spf13/cobra" 30 "sigs.k8s.io/controller-runtime/pkg/client" 31 32 pkgmulticluster "github.com/kubevela/pkg/multicluster" 33 wfTypes "github.com/kubevela/workflow/pkg/types" 34 wfUtils "github.com/kubevela/workflow/pkg/utils" 35 36 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1" 37 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" 38 "github.com/oam-dev/kubevela/apis/types" 39 "github.com/oam-dev/kubevela/pkg/utils/common" 40 cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" 41 querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" 42 "github.com/oam-dev/kubevela/pkg/workflow/operation" 43 ) 44 45 // NewWorkflowCommand create `workflow` command 46 func NewWorkflowCommand(c common.Args, order string, ioStreams cmdutil.IOStreams) *cobra.Command { 47 cmd := &cobra.Command{ 48 Use: "workflow", 49 Short: "Operate application delivery workflow.", 50 Long: "Operate the Workflow during Application Delivery. Note that workflow command is both valid for Application Workflow and WorkflowRun(expect for [restart, rollout] command, they're only valid for Application Workflow). The command will try to find the Application first, if not found, it will try to find WorkflowRun. You can also specify the resource type by using --type flag.", 51 Annotations: map[string]string{ 52 types.TagCommandType: types.TypeCD, 53 types.TagCommandOrder: order, 54 }, 55 } 56 wargs := &WorkflowArgs{ 57 Args: c, 58 Writer: ioStreams.Out, 59 } 60 cmd.SetOut(ioStreams.Out) 61 cmd.AddCommand( 62 NewWorkflowSuspendCommand(c, ioStreams, wargs), 63 NewWorkflowResumeCommand(c, ioStreams, wargs), 64 NewWorkflowTerminateCommand(c, ioStreams, wargs), 65 NewWorkflowRestartCommand(c, ioStreams, wargs), 66 NewWorkflowRollbackCommand(c, ioStreams, wargs), 67 NewWorkflowLogsCommand(c, ioStreams, wargs), 68 NewWorkflowDebugCommand(c, ioStreams, wargs), 69 NewWorkflowListCommand(c, ioStreams, wargs), 70 ) 71 return cmd 72 } 73 74 // NewWorkflowSuspendCommand create workflow suspend command 75 func NewWorkflowSuspendCommand(_ common.Args, _ cmdutil.IOStreams, wargs *WorkflowArgs) *cobra.Command { 76 cmd := &cobra.Command{ 77 Use: "suspend", 78 Short: "Suspend a workflow.", 79 Long: "Suspend a workflow in cluster.", 80 Example: "vela workflow suspend <workflow-name>", 81 PreRun: wargs.checkWorkflowNotComplete(), 82 RunE: func(cmd *cobra.Command, args []string) error { 83 ctx := context.Background() 84 if err := wargs.getWorkflowInstance(ctx, cmd, args); err != nil { 85 return err 86 } 87 if wargs.StepName != "" { 88 return wargs.StepOperator.Suspend(ctx, wargs.StepName) 89 } 90 return wargs.Operator.Suspend(ctx) 91 }, 92 } 93 addNamespaceAndEnvArg(cmd) 94 cmd.Flags().StringVarP(&wargs.StepName, "step", "s", "", "specify the step name in the workflow") 95 cmd.Flags().StringVarP(&wargs.Type, "type", "t", "", "the type of the resource, support: [app, workflow]") 96 return cmd 97 } 98 99 // NewWorkflowResumeCommand create workflow resume command 100 func NewWorkflowResumeCommand(_ common.Args, _ cmdutil.IOStreams, wargs *WorkflowArgs) *cobra.Command { 101 cmd := &cobra.Command{ 102 Use: "resume", 103 Short: "Resume a suspend workflow.", 104 Long: "Resume a suspend workflow in cluster.", 105 Example: "vela workflow resume <workflow-name>", 106 PreRun: wargs.checkWorkflowNotComplete(), 107 RunE: func(cmd *cobra.Command, args []string) error { 108 ctx := context.Background() 109 if err := wargs.getWorkflowInstance(ctx, cmd, args); err != nil { 110 return err 111 } 112 if wargs.StepName != "" { 113 return wargs.StepOperator.Resume(ctx, wargs.StepName) 114 } 115 return wargs.Operator.Resume(ctx) 116 }, 117 } 118 addNamespaceAndEnvArg(cmd) 119 cmd.Flags().StringVarP(&wargs.StepName, "step", "s", "", "specify the step name in the workflow") 120 cmd.Flags().StringVarP(&wargs.Type, "type", "t", "", "the type of the resource, support: [app, workflow]") 121 return cmd 122 } 123 124 // NewWorkflowTerminateCommand create workflow terminate command 125 func NewWorkflowTerminateCommand(_ common.Args, _ cmdutil.IOStreams, wargs *WorkflowArgs) *cobra.Command { 126 cmd := &cobra.Command{ 127 Use: "terminate", 128 Short: "Terminate a workflow.", 129 Long: "Terminate a workflow in cluster.", 130 Example: "vela workflow terminate <workflow-name>", 131 PreRun: wargs.checkWorkflowNotComplete(), 132 RunE: func(cmd *cobra.Command, args []string) error { 133 ctx := context.Background() 134 if err := wargs.getWorkflowInstance(ctx, cmd, args); err != nil { 135 return err 136 } 137 return wargs.Operator.Terminate(ctx) 138 }, 139 } 140 addNamespaceAndEnvArg(cmd) 141 cmd.Flags().StringVarP(&wargs.Type, "type", "t", "", "the type of the resource, support: [app, workflow]") 142 return cmd 143 } 144 145 // NewWorkflowRestartCommand create workflow restart command 146 func NewWorkflowRestartCommand(_ common.Args, _ cmdutil.IOStreams, wargs *WorkflowArgs) *cobra.Command { 147 cmd := &cobra.Command{ 148 Use: "restart", 149 Short: "Restart a workflow.", 150 Long: "Restart a workflow in cluster.", 151 Example: "vela workflow restart <workflow-name>", 152 RunE: func(cmd *cobra.Command, args []string) error { 153 ctx := context.Background() 154 if err := wargs.getWorkflowInstance(ctx, cmd, args); err != nil { 155 return err 156 } 157 if wargs.StepName != "" { 158 return wargs.StepOperator.Restart(ctx, wargs.StepName) 159 } 160 return wargs.Operator.Restart(ctx) 161 }, 162 } 163 addNamespaceAndEnvArg(cmd) 164 cmd.Flags().StringVarP(&wargs.StepName, "step", "s", "", "specify the step name in the workflow") 165 cmd.Flags().StringVarP(&wargs.Type, "type", "t", "", "the type of the resource, support: [app, workflow]") 166 return cmd 167 } 168 169 // NewWorkflowRollbackCommand create workflow rollback command 170 func NewWorkflowRollbackCommand(_ common.Args, _ cmdutil.IOStreams, wargs *WorkflowArgs) *cobra.Command { 171 cmd := &cobra.Command{ 172 Use: "rollback", 173 Short: "Rollback an application workflow to the latest revision.", 174 Long: "Rollback an application workflow to the latest revision.", 175 Example: "vela workflow rollback <application-name>", 176 RunE: func(cmd *cobra.Command, args []string) error { 177 ctx := context.Background() 178 if err := wargs.getWorkflowInstance(ctx, cmd, args); err != nil { 179 return err 180 } 181 return wargs.Operator.Rollback(ctx) 182 }, 183 } 184 addNamespaceAndEnvArg(cmd) 185 cmd.Flags().StringVarP(&wargs.Type, "type", "t", "", "the type of the resource, support: [app, workflow]") 186 return cmd 187 } 188 189 // NewWorkflowLogsCommand create workflow logs command 190 func NewWorkflowLogsCommand(c common.Args, ioStream cmdutil.IOStreams, wargs *WorkflowArgs) *cobra.Command { 191 cmd := &cobra.Command{ 192 Use: "logs", 193 Short: "Tail logs for workflow steps", 194 Long: "Tail logs for workflow steps, note that you need to use op.#Logs in step definition to set the log config of the step.", 195 Example: "vela workflow logs <workflow-name>", 196 RunE: func(cmd *cobra.Command, args []string) error { 197 cli, err := c.GetClient() 198 if err != nil { 199 return err 200 } 201 ctx := context.Background() 202 if err := wargs.getWorkflowInstance(ctx, cmd, args); err != nil { 203 return err 204 } 205 return wargs.printStepLogs(ctx, cli, ioStream) 206 }, 207 } 208 cmd.Flags().StringVarP(&wargs.StepName, "step", "s", "", "specify the step name in the workflow") 209 cmd.Flags().StringVarP(&wargs.Output, "output", "o", "default", "output format for logs, support: [default, raw, json]") 210 cmd.Flags().StringVarP(&wargs.Type, "type", "t", "", "the type of the resource, support: [app, workflow]") 211 addNamespaceAndEnvArg(cmd) 212 return cmd 213 } 214 215 // NewWorkflowDebugCommand create workflow debug command 216 func NewWorkflowDebugCommand(c common.Args, ioStream cmdutil.IOStreams, wargs *WorkflowArgs) *cobra.Command { 217 dOpts := &debugOpts{ 218 step: wargs.StepName, 219 } 220 cmd := &cobra.Command{ 221 Use: "debug", 222 Short: "Debug workflow steps", 223 Long: "Debug workflow steps", 224 Example: "vela workflow debug <workflow-name>", 225 PreRun: wargs.checkDebugMode(), 226 RunE: func(cmd *cobra.Command, args []string) error { 227 cli, err := c.GetClient() 228 if err != nil { 229 return err 230 } 231 pd, err := c.GetPackageDiscover() 232 if err != nil { 233 return err 234 } 235 ctx := context.Background() 236 if err := wargs.getWorkflowInstance(ctx, cmd, args); err != nil { 237 return err 238 } 239 dOpts.opts = wargs.getWorkflowSteps() 240 dOpts.errMap = wargs.ErrMap 241 return dOpts.debugWorkflow(ctx, wargs, cli, pd, ioStream) 242 }, 243 } 244 cmd.Flags().StringVarP(&wargs.StepName, "step", "s", "", "specify the step name in the workflow") 245 cmd.Flags().StringVarP(&dOpts.focus, "focus", "f", "", "specify the focus value to debug, only valid for application with workflow") 246 cmd.Flags().StringVarP(&wargs.Type, "type", "t", "", "the type of the resource, support: [app, workflow]") 247 addNamespaceAndEnvArg(cmd) 248 return cmd 249 } 250 251 // NewWorkflowListCommand create workflow list command 252 func NewWorkflowListCommand(c common.Args, ioStream cmdutil.IOStreams, _ *WorkflowArgs) *cobra.Command { 253 cmd := &cobra.Command{ 254 Use: "list", 255 Short: "List running workflows", 256 Long: "List running workflows", 257 Example: "vela workflow list", 258 RunE: func(cmd *cobra.Command, args []string) error { 259 cli, err := c.GetClient() 260 if err != nil { 261 return err 262 } 263 namespace, err := GetFlagNamespaceOrEnv(cmd, c) 264 if err != nil { 265 return err 266 } 267 if AllNamespace { 268 namespace = "" 269 } 270 ctx := context.Background() 271 return printWorkflowList(ctx, cli, namespace, ioStream) 272 }, 273 } 274 cmd.Flags().BoolVarP(&AllNamespace, "all-namespaces", "A", false, "If true, check the specified action in all namespaces.") 275 addNamespaceAndEnvArg(cmd) 276 return cmd 277 } 278 279 func printWorkflowList(ctx context.Context, c client.Reader, namespace string, ioStream cmdutil.IOStreams) error { 280 table, err := buildWorkflowListTable(ctx, c, namespace) 281 if err != nil { 282 return err 283 } 284 ioStream.Info(table.String()) 285 return nil 286 } 287 288 func buildWorkflowListTable(ctx context.Context, c client.Reader, namespace string) (*uitable.Table, error) { 289 table := newUITable() 290 header := []interface{}{"NAME", "TYPE", "PHASE", "START-TIME", "END-TIME"} 291 if AllNamespace { 292 header = append([]interface{}{"NAMESPACE"}, header...) 293 } 294 table.AddRow(header...) 295 applist := v1beta1.ApplicationList{} 296 if err := c.List(ctx, &applist, client.InNamespace(namespace)); err != nil { 297 return nil, errors.WithMessage(err, "unable to list application workflows") 298 } 299 300 for _, a := range applist.Items { 301 status := a.Status.Workflow 302 if a.Status.Workflow != nil { 303 if AllNamespace { 304 table.AddRow(a.Namespace, a.Name, "Application", status.Phase, status.StartTime, status.EndTime) 305 } else { 306 table.AddRow(a.Name, "Application", status.Phase, status.StartTime, status.EndTime) 307 } 308 } 309 } 310 311 wrList := workflowv1alpha1.WorkflowRunList{} 312 313 if err := c.List(ctx, &wrList, client.InNamespace(namespace)); err != nil { 314 return nil, errors.WithMessage(err, "unable to list workflowruns") 315 } 316 317 for _, w := range wrList.Items { 318 status := w.Status 319 if status.Phase != "" { 320 if AllNamespace { 321 table.AddRow(w.Namespace, w.Name, "WorkflowRun", status.Phase, status.StartTime, status.EndTime) 322 } else { 323 table.AddRow(w.Name, "WorkflowRun", status.Phase, status.StartTime, status.EndTime) 324 } 325 } 326 } 327 return table, nil 328 } 329 330 // WorkflowArgs is the args for workflow command 331 type WorkflowArgs struct { 332 Type string 333 Output string 334 ControllerLabels map[string]string 335 Operator wfUtils.WorkflowOperator 336 StepOperator wfUtils.WorkflowStepOperator 337 Writer io.Writer 338 Args common.Args 339 StepName string 340 StepID string 341 ErrMap map[string]string 342 App *v1beta1.Application 343 WorkflowRun *workflowv1alpha1.WorkflowRun 344 WorkflowInstance *wfTypes.WorkflowInstance 345 } 346 347 const ( 348 instanceTypeApplication string = "app" 349 instanceTypeWorkflowRun string = "workflow" 350 ) 351 352 func (w *WorkflowArgs) getWorkflowInstance(ctx context.Context, cmd *cobra.Command, args []string) error { 353 if len(args) < 1 { 354 return fmt.Errorf("please specify the name of application/workflow") 355 } 356 name := args[0] 357 namespace, err := GetFlagNamespaceOrEnv(cmd, w.Args) 358 if err != nil { 359 return err 360 } 361 cli, err := w.Args.GetClient() 362 if err != nil { 363 return err 364 } 365 config, err := w.Args.GetConfig() 366 if err != nil { 367 return err 368 } 369 config.Wrap(pkgmulticluster.NewTransportWrapper()) 370 switch w.Type { 371 case "": 372 app := &v1beta1.Application{} 373 if err := cli.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, app); err == nil { 374 w.Type = instanceTypeApplication 375 w.App = app 376 } else { 377 wr := &workflowv1alpha1.WorkflowRun{} 378 if err := cli.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, wr); err == nil { 379 w.Type = instanceTypeWorkflowRun 380 w.WorkflowRun = wr 381 } 382 } 383 if w.Type == "" { 384 return fmt.Errorf("can't find application or workflowrun %s", name) 385 } 386 case instanceTypeApplication: 387 app := &v1beta1.Application{} 388 if err := cli.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, app); err != nil { 389 return err 390 } 391 w.App = app 392 case instanceTypeWorkflowRun: 393 wr := &workflowv1alpha1.WorkflowRun{} 394 if err := cli.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, wr); err != nil { 395 return err 396 } 397 w.WorkflowRun = wr 398 default: 399 } 400 return w.generateWorkflowInstance(ctx, cli) 401 } 402 403 func (w *WorkflowArgs) generateWorkflowInstance(ctx context.Context, cli client.Client) error { 404 debug := false 405 switch w.Type { 406 case instanceTypeApplication: 407 if w.App.Status.Workflow == nil { 408 return fmt.Errorf("the workflow in application %s is not start", w.App.Name) 409 } 410 for _, policy := range w.App.Spec.Policies { 411 if policy.Type == v1alpha1.DebugPolicyType { 412 debug = true 413 break 414 } 415 } 416 status := w.App.Status.Workflow 417 w.WorkflowInstance = &wfTypes.WorkflowInstance{ 418 WorkflowMeta: wfTypes.WorkflowMeta{ 419 Name: w.App.Name, 420 Namespace: w.App.Namespace, 421 UID: w.App.UID, 422 }, 423 Debug: debug, 424 Status: workflowv1alpha1.WorkflowRunStatus{ 425 Phase: status.Phase, 426 Message: status.Message, 427 Suspend: status.Suspend, 428 SuspendState: status.SuspendState, 429 Terminated: status.Terminated, 430 Finished: status.Finished, 431 ContextBackend: status.ContextBackend, 432 Steps: status.Steps, 433 StartTime: status.StartTime, 434 EndTime: status.EndTime, 435 }, 436 } 437 if w.App.Spec.Workflow != nil { 438 w.WorkflowInstance.Steps = w.App.Spec.Workflow.Steps 439 } 440 w.Operator = operation.NewApplicationWorkflowOperator(cli, w.Writer, w.App) 441 w.StepOperator = operation.NewApplicationWorkflowStepOperator(cli, w.Writer, w.App) 442 w.ControllerLabels = map[string]string{"app.kubernetes.io/name": "vela-core"} 443 case instanceTypeWorkflowRun: 444 var steps []workflowv1alpha1.WorkflowStep 445 if w.WorkflowRun.Spec.WorkflowRef != "" { 446 workflow := &workflowv1alpha1.Workflow{} 447 if err := cli.Get(ctx, client.ObjectKey{Namespace: w.WorkflowRun.Namespace, Name: w.WorkflowRun.Spec.WorkflowRef}, workflow); err != nil { 448 return err 449 } 450 steps = workflow.Steps 451 } else { 452 steps = w.WorkflowRun.Spec.WorkflowSpec.Steps 453 } 454 if w.WorkflowRun.Annotations != nil { 455 if d, ok := w.WorkflowRun.Annotations[wfTypes.AnnotationWorkflowRunDebug]; ok && d == "true" { 456 debug = true 457 } 458 } 459 w.WorkflowInstance = &wfTypes.WorkflowInstance{ 460 WorkflowMeta: wfTypes.WorkflowMeta{ 461 Name: w.WorkflowRun.Name, 462 Namespace: w.WorkflowRun.Namespace, 463 UID: w.WorkflowRun.UID, 464 }, 465 Steps: steps, 466 Status: w.WorkflowRun.Status, 467 Debug: debug, 468 } 469 w.Operator = wfUtils.NewWorkflowRunOperator(cli, w.Writer, w.WorkflowRun) 470 w.StepOperator = wfUtils.NewWorkflowRunStepOperator(cli, w.Writer, w.WorkflowRun) 471 w.ControllerLabels = map[string]string{"app.kubernetes.io/name": "vela-workflow"} 472 default: 473 return fmt.Errorf("unknown workflow instance type %s", w.Type) 474 } 475 return nil 476 } 477 478 func (w *WorkflowArgs) printStepLogs(ctx context.Context, cli client.Client, ioStreams cmdutil.IOStreams) error { 479 if w.StepName == "" { 480 if err := w.selectWorkflowStep("Select a step to show logs:"); err != nil { 481 return err 482 } 483 } 484 if w.WorkflowInstance.Status.ContextBackend == nil { 485 return fmt.Errorf("the workflow context backend is not set") 486 } 487 logConfig, err := wfUtils.GetLogConfigFromStep(ctx, cli, w.WorkflowInstance.Status.ContextBackend.Name, w.WorkflowInstance.Name, w.WorkflowInstance.Namespace, w.StepName) 488 if err != nil { 489 return errors.WithMessage(err, fmt.Sprintf("step [%s]", w.StepName)) 490 } 491 if err := selectStepLogSource(logConfig); err != nil { 492 return err 493 } 494 switch { 495 case logConfig.Data: 496 return w.printResourceLogs(ctx, cli, ioStreams, []wfTypes.Resource{{ 497 Namespace: types.DefaultKubeVelaNS, 498 LabelSelector: w.ControllerLabels, 499 }}, []string{fmt.Sprintf(`stepSessionID="%s"`, w.StepID), fmt.Sprintf("%s/%s", w.WorkflowInstance.Namespace, w.WorkflowInstance.Name), "cue logs"}) 500 case logConfig.Source != nil: 501 if len(logConfig.Source.Resources) > 0 { 502 return w.printResourceLogs(ctx, cli, ioStreams, logConfig.Source.Resources, nil) 503 } 504 if logConfig.Source.URL != "" { 505 readCloser, err := wfUtils.GetLogsFromURL(ctx, logConfig.Source.URL) 506 if err != nil { 507 return err 508 } 509 //nolint:errcheck 510 defer readCloser.Close() 511 if _, err := io.Copy(ioStreams.Out, readCloser); err != nil { 512 return err 513 } 514 } 515 } 516 return nil 517 } 518 519 func (w *WorkflowArgs) getWorkflowSteps() []string { 520 if w.ErrMap == nil { 521 w.ErrMap = make(map[string]string) 522 } 523 stepsKey := make([]string, 0) 524 for _, step := range w.WorkflowInstance.Status.Steps { 525 stepsKey = append(stepsKey, wrapStepName(step.StepStatus)) 526 if step.Phase == workflowv1alpha1.WorkflowStepPhaseFailed { 527 w.ErrMap[step.Name] = step.Message 528 } 529 for _, sub := range step.SubStepsStatus { 530 stepsKey = append(stepsKey, fmt.Sprintf(" %s", wrapStepName(sub))) 531 if sub.Phase == workflowv1alpha1.WorkflowStepPhaseFailed { 532 w.ErrMap[step.Name] = sub.Message 533 } 534 } 535 } 536 return stepsKey 537 } 538 539 func (w *WorkflowArgs) selectWorkflowStep(msg string) error { 540 stepsKey := w.getWorkflowSteps() 541 if len(stepsKey) == 0 { 542 return fmt.Errorf("workflow is not start") 543 } 544 545 prompt := &survey.Select{ 546 Message: msg, 547 Options: stepsKey, 548 } 549 var stepName string 550 err := survey.AskOne(prompt, &stepName, survey.WithValidator(survey.Required)) 551 if err != nil { 552 return fmt.Errorf("failed to select step %s: %w", unwrapStepName(w.StepName), err) 553 } 554 w.StepName = unwrapStepName(stepName) 555 w.StepID = unwrapStepID(stepName, w.WorkflowInstance) 556 return nil 557 } 558 559 func selectStepLogSource(logConfig *wfTypes.LogConfig) error { 560 var source string 561 if logConfig.Data && logConfig.Source != nil { 562 prompt := &survey.Select{ 563 Message: "Select logs from data or source", 564 Options: []string{"data", "source"}, 565 } 566 err := survey.AskOne(prompt, &source, survey.WithValidator(survey.Required)) 567 if err != nil { 568 return fmt.Errorf("failed to select %s: %w", source, err) 569 } 570 if source != "data" { 571 logConfig.Data = false 572 } 573 } 574 return nil 575 } 576 577 func (w *WorkflowArgs) printResourceLogs(ctx context.Context, cli client.Client, ioStreams cmdutil.IOStreams, resources []wfTypes.Resource, filters []string) error { 578 pods, err := wfUtils.GetPodListFromResources(ctx, cli, resources) 579 if err != nil { 580 return err 581 } 582 podList := make([]querytypes.PodBase, 0) 583 for _, pod := range pods { 584 podBase := querytypes.PodBase{} 585 podBase.Metadata.Name = pod.Name 586 podBase.Metadata.Namespace = pod.Namespace 587 podList = append(podList, podBase) 588 } 589 if len(pods) == 0 { 590 return errors.New("no pod found") 591 } 592 var selectPod *querytypes.PodBase 593 if len(pods) > 1 { 594 selectPod, err = AskToChooseOnePod(podList) 595 if err != nil { 596 return err 597 } 598 } else { 599 selectPod = &podList[0] 600 } 601 l := Args{ 602 Args: w.Args, 603 Output: w.Output, 604 } 605 return l.printPodLogs(ctx, ioStreams, selectPod, filters) 606 } 607 608 func (w *WorkflowArgs) checkWorkflowNotComplete() func(cmd *cobra.Command, args []string) { 609 return func(cmd *cobra.Command, args []string) { 610 if err := w.getWorkflowInstance(context.Background(), cmd, args); err != nil { 611 return 612 } 613 if w.WorkflowInstance.Status.Phase == workflowv1alpha1.WorkflowStateSucceeded { 614 cmd.Printf("%s workflow not allowed because application %s is running\n", cmd.Use, args[0]) 615 os.Exit(1) 616 } 617 } 618 } 619 620 func (w *WorkflowArgs) checkDebugMode() func(cmd *cobra.Command, args []string) { 621 return func(cmd *cobra.Command, args []string) { 622 if err := w.getWorkflowInstance(context.Background(), cmd, args); err != nil { 623 return 624 } 625 if !w.WorkflowInstance.Debug { 626 msg := "" 627 if w.Type == instanceTypeApplication { 628 msg = "please make sure your application have the debug policy, you can add the debug policy by using `vela up -f <app.yaml> --debug" 629 } else { 630 msg = "please make sure your workflow have the debug annotation [workflowrun.oam.dev/debug:true] then re-run the workflow" 631 } 632 cmd.Printf("workflow %s is not in debug mode, %s", w.WorkflowInstance.Name, msg) 633 os.Exit(1) 634 } 635 } 636 }