Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(cli): improve CLI error handling. Fixes #1935 #13656

Merged
merged 8 commits into from
Oct 4, 2024

Conversation

MasonM
Copy link
Contributor

@MasonM MasonM commented Sep 24, 2024

Fixes #1935

Motivation

It's tricky to write unit tests for the CLI code because it nearly always exits on errors and there's no good way of injecting mocked dependencies. #3917 tried to solve both issues, but it appears to have been abandoned. I thought about trying to revive that PR, but it's been over 4 years and there's certainly going to be a ton of conflicts. I figure it's better to take a more focused, incremental approach.

Modifications

This PR is focused on improving error handling in the following ways:

  1. Do argument validation using cobra validators instead of custom logic in the Run function. Besides being simpler, this leads to better error messages.
  2. Replace all Run functions with RunE, which allows returning errors. This is the same approach that Argo Rollouts is taking (example)
  3. Replace nearly all calls to log.Fatal()/errors.CheckError()/etc with error propagation.

Verification

Ran E2E tests and did some manual testing, e.g.

$ ./dist/argo  delete 
Error: requires either a workflow or other argument
Usage:
  argo delete [--dry-run] [WORKFLOW...|[--all] [--older] [--completed] [--resubmitted] [--prefix PREFIX] [--selector SELECTOR] [--force] [--status STATUS] ] [flags]

Examples:
<SNIP>

It's tricky to write unit tests for the CLI code for three main reasons:
exiting on errors, lack of dependency injection, and insufficient mocks.
argoproj#3917 tried to solve all
of these issues, but appears to have been abandoned. I thought about
trying to revive that PR, but it's been over 4 years and there's
certainly going to be a ton of conflicts. I figure it's better to take a
more focused, incremental approach.

This PR is focused on improving error handling in the following ways:
1. Do argument validation using [cobra
   validators](https://cobra.dev/#positional-and-custom-arguments)
   instead of custom logic in the `Run` function. Besides being
   simpler, this leads to better error messages.
2. Replace all `Run` functions with `RunE`, which allows returning
   errors. This is the same approach that Argo Rollouts is taking
   (example:
   https://github.com/argoproj/argo-rollouts/blob/00e39b114849010dd96221a8db441d58e860d4d0/pkg/kubectl-argo-rollouts/cmd/abort/abort.go#L41)
3. Replace nearly all calls to `log.Fatal()`/`errors.CheckError()`/etc
   with error propagation.

Signed-off-by: Mason Malone <mmalone@adobe.com>
@MasonM MasonM marked this pull request as ready for review September 24, 2024 04:30
@MasonM
Copy link
Contributor Author

MasonM commented Sep 25, 2024

Test failures are unrelated and should go away once #13660 is merged

@blkperl blkperl added the area/cli The `argo` CLI label Sep 30, 2024
Copy link
Member

@isubasinghe isubasinghe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please ensure the arguments to printWorkflow are validated first.

We wouldn't want a non-zero exit code when everything but printing the workflow worked.

cmd/argo/commands/common/wait.go Outdated Show resolved Hide resolved
cmd/argo/commands/cron/get.go Show resolved Hide resolved
cmd/argo/commands/logs.go Outdated Show resolved Hide resolved
cmd/argo/commands/retry.go Show resolved Hide resolved
Signed-off-by: Mason Malone <mmalone@adobe.com>
MasonM added a commit to MasonM/argo-workflows that referenced this pull request Oct 3, 2024
This is a follow-up to
argoproj#13656 (review).
Many of the CLI commands take an `--output` flag, but this wasn't
being validated, and there was a lot of duplication. The duplication has
led to docs getting out-of-date, e.g. `argo cluster-template get --help`
says `Output format. Must be one of: json|yaml|wide`, but it accepts
`name` too.

This introduces a simple `EnumFlagValue` type to represent enum flags
like `--output` and changes all commands with an `--output` flag to use
it. This will cause Cobra to give a helpful error if you pass an invalid
value, e.g.:
```
$ ./dist/argo list -o INVALID
Error: invalid argument "INVALID" for "-o, --output" flag: One of: name|json|yaml|wide
```

Signed-off-by: Mason Malone <mmalone@adobe.com>
Signed-off-by: Mason Malone <mmalone@adobe.com>
@MasonM
Copy link
Contributor Author

MasonM commented Oct 3, 2024

@isubasinghe Thanks for the review!

Please ensure the arguments to printWorkflow are validated first.

We wouldn't want a non-zero exit code when everything but printing the workflow worked.

Okay, I entered #13695 to do that. I'm trying to minimize the chance of bugs by having this PR be almost pure refactoring, without any functional changes. Having the commands exit earlier on a validation error would be a functional change, which is why I split it off to a separate PR.

MasonM added a commit to MasonM/argo-workflows that referenced this pull request Oct 3, 2024
This is a follow-up to
argoproj#13656 (review).
Many of the CLI commands take an `--output` flag, but this wasn't
being validated, and there was a lot of duplication. The duplication has
led to docs getting out-of-date, e.g. `argo cluster-template get --help`
says `Output format. Must be one of: json|yaml|wide`, but it accepts
`name` too.

This introduces a simple `EnumFlagValue` type to represent enum flags
like `--output` and changes all commands with an `--output` flag to use
it. This will cause Cobra to give a helpful error if you pass an invalid
value, e.g.:
```
$ ./dist/argo list -o INVALID
Error: invalid argument "INVALID" for "-o, --output" flag: One of: name|json|yaml|wide
```

Signed-off-by: Mason Malone <mmalone@adobe.com>
Copy link
Member

@isubasinghe isubasinghe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the changes, this looks good to me.

@isubasinghe isubasinghe merged commit 734b5b6 into argoproj:main Oct 4, 2024
27 checks passed
Copy link
Member

@agilgur5 agilgur5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! I looked through most of it, but not all.
Agreed with how things were split as well (functional vs refactor etc)

  1. Do argument validation using cobra validators

Didn't know that was a thing, great!

3. Replace nearly all calls to log.Fatal()/errors.CheckError()/etc with error propagation.

This also has the added benefit of reducing our dependence on argoproj/pkg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/cli The `argo` CLI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CLI: Rework to use RunE
5 participants