Skip to content

Add dynamic resource autocompletion to Velero CLI#9720

Open
Joeavaikath wants to merge 5 commits intovelero-io:mainfrom
Joeavaikath:feature/dynamic-cli-completion
Open

Add dynamic resource autocompletion to Velero CLI#9720
Joeavaikath wants to merge 5 commits intovelero-io:mainfrom
Joeavaikath:feature/dynamic-cli-completion

Conversation

@Joeavaikath
Copy link
Copy Markdown
Contributor

Summary

Adds dynamic shell completion for Velero CLI commands, replacing static
completion with live resource lookups from the cluster.

  • Introduces completion functions that query the Kubernetes API for
    backup, restore, schedule, BSL, VSL, and repository names
  • Wires up ValidArgsFunction on get/describe/delete/logs commands
    and RegisterFlagCompletionFunc on create command flags
    (e.g. --from-schedule, --storage-location, --from-backup)
  • Upgrades bash completion from v1 to v2 (GenBashCompletionV2)
    to support custom completion functions
  • Includes a design document describing the approach

Does your change fix a particular issue?

Please indicate you've done the following:

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 13, 2026

Codecov Report

❌ Patch coverage is 74.57627% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.00%. Comparing base (4d9bd91) to head (c6a8680).

Files with missing lines Patch % Lines
pkg/cmd/cli/completion_functions.go 81.81% 3 Missing and 3 partials ⚠️
pkg/cmd/cli/completion/completion.go 0.00% 1 Missing ⚠️
pkg/cmd/cli/repo/get.go 0.00% 1 Missing ⚠️
pkg/cmd/cli/schedule/delete.go 0.00% 1 Missing ⚠️
pkg/cmd/cli/schedule/describe.go 0.00% 1 Missing ⚠️
pkg/cmd/cli/schedule/get.go 0.00% 1 Missing ⚠️
pkg/cmd/cli/schedule/pause.go 0.00% 1 Missing ⚠️
pkg/cmd/cli/schedule/unpause.go 0.00% 1 Missing ⚠️
pkg/cmd/cli/snapshotlocation/get.go 0.00% 1 Missing ⚠️
pkg/cmd/cli/snapshotlocation/set.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9720      +/-   ##
==========================================
+ Coverage   60.97%   61.00%   +0.02%     
==========================================
  Files         384      385       +1     
  Lines       36609    36667      +58     
==========================================
+ Hits        22322    22368      +46     
- Misses      12678    12688      +10     
- Partials     1609     1611       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Shell completion is a standard UX feature in Kubernetes CLI tooling.
Tools like `kubectl`, `oc`, and `helm` all provide dynamic completions that query the cluster to suggest resource names.
Velero's `velero completion` command generates static completion scripts using cobra's v1 API (`GenBashCompletion`), which only completes command and flag names.
Cobra v1.8.1 (Velero's current version) supports dynamic completion via `ValidArgsFunction` on `cobra.Command` and `RegisterFlagCompletionFunc` for flag values, but Velero does not use either.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
Cobra v1.8.1 (Velero's current version) supports dynamic completion via `ValidArgsFunction` on `cobra.Command` and `RegisterFlagCompletionFunc` for flag values, but Velero does not use either.
Cobra v1.8.1 (Velero's current import) supports dynamic completion via `ValidArgsFunction` on `cobra.Command` and `RegisterFlagCompletionFunc` for flag values, but Velero does not use either.

Comment thread pkg/cmd/cli/completion_functions.go Outdated
return nil, cobra.ShellCompDirectiveNoFileComp
}
backups := new(velerov1api.BackupList)
if err := kbClient.List(context.TODO(), backups, &kbclient.ListOptions{Namespace: f.Namespace()}); err != nil {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

These should be context.WithTimeout or deriving a context from the command's context via cmd.Context() which cobra populates and which typically gets canceled on SIGINT.

Comment thread pkg/cmd/cli/completion_functions.go
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

fyi: optimized the generics further. See how each wrapper return is a single line.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I guess this is using interface func more than generics.. but alas.. less dupe :)

@kaovilai kaovilai self-requested a review April 15, 2026 14:47
@kaovilai kaovilai force-pushed the feature/dynamic-cli-completion branch from c3c92a1 to 95c37d3 Compare April 15, 2026 14:47
Joeavaikath and others added 5 commits April 15, 2026 12:05
Add ValidArgsFunction for 20 commands that take resource names as
positional args (backup, restore, schedule, BSL, VSL, repo) and
RegisterFlagCompletionFunc for 5 flags that reference resources
(--from-backup, --from-schedule, --storage-location, etc).

Completion functions query the cluster via KubebuilderClient and
fail silently if unreachable, matching oc behavior. Switch bash
completion from v1 to v2 (GenBashCompletionV2) which is required
for ValidArgsFunction support.

Signed-off-by: Joseph <jvaikath@redhat.com>
Proposes adding ValidArgsFunction and RegisterFlagCompletionFunc
to all Velero CLI commands that accept existing resource names,
covering 20 commands and 5 flags across 6 resource types.

Signed-off-by: Joseph <jvaikath@redhat.com>
Signed-off-by: Joseph <jvaikath@redhat.com>
Signed-off-by: Joseph <jvaikath@redhat.com>
…dd unit tests for completion logic

Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds dynamic shell autocompletion for Velero CLI resource names by querying the Kubernetes API at completion time (instead of relying solely on static completion scripts), and updates bash completion generation to Cobra’s v2 generator so custom completion callbacks are invoked.

Changes:

  • Introduces reusable completion functions that list Velero resources (backups, restores, schedules, BSL/VSL, repositories) and filter by the typed prefix.
  • Wires these functions into relevant commands via ValidArgsFunction and into selected flags via RegisterFlagCompletionFunc.
  • Switches bash completion generation to GenBashCompletionV2, and adds tests + a design document + changelog entry.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pkg/cmd/cli/snapshotlocation/set.go Adds ValidArgsFunction for VolumeSnapshotLocation name completion.
pkg/cmd/cli/snapshotlocation/get.go Adds ValidArgsFunction for VolumeSnapshotLocation name completion.
pkg/cmd/cli/schedule/unpause.go Adds ValidArgsFunction for Schedule name completion.
pkg/cmd/cli/schedule/pause.go Adds ValidArgsFunction for Schedule name completion.
pkg/cmd/cli/schedule/get.go Adds ValidArgsFunction for Schedule name completion.
pkg/cmd/cli/schedule/describe.go Adds ValidArgsFunction for Schedule name completion.
pkg/cmd/cli/schedule/delete.go Adds ValidArgsFunction for Schedule name completion.
pkg/cmd/cli/restore/logs.go Adds ValidArgsFunction for Restore name completion.
pkg/cmd/cli/restore/get.go Adds ValidArgsFunction for Restore name completion.
pkg/cmd/cli/restore/describe.go Adds ValidArgsFunction for Restore name completion.
pkg/cmd/cli/restore/delete.go Adds ValidArgsFunction for Restore name completion.
pkg/cmd/cli/restore/create.go Adds flag completion for --from-backup and --from-schedule.
pkg/cmd/cli/repo/get.go Adds ValidArgsFunction for BackupRepository name completion.
pkg/cmd/cli/completion_functions_test.go Adds unit tests for the completion helper and wrappers.
pkg/cmd/cli/completion_functions.go New shared implementation for dynamic resource-name completion via controller-runtime client.
pkg/cmd/cli/completion/completion.go Switches bash completion generation to GenBashCompletionV2.
pkg/cmd/cli/backuplocation/set.go Adds ValidArgsFunction for BackupStorageLocation name completion.
pkg/cmd/cli/backuplocation/get.go Adds ValidArgsFunction for BackupStorageLocation name completion.
pkg/cmd/cli/backuplocation/delete.go Adds ValidArgsFunction for BackupStorageLocation name completion.
pkg/cmd/cli/backup/logs.go Adds ValidArgsFunction for Backup name completion.
pkg/cmd/cli/backup/get.go Adds ValidArgsFunction for Backup name completion.
pkg/cmd/cli/backup/download.go Adds ValidArgsFunction for Backup name completion.
pkg/cmd/cli/backup/describe.go Adds ValidArgsFunction for Backup name completion.
pkg/cmd/cli/backup/delete.go Adds ValidArgsFunction for Backup name completion.
pkg/cmd/cli/backup/create.go Adds flag completion for --from-schedule, --storage-location, --volume-snapshot-locations.
design/cli-dynamic-resource-completion_design.md Documents the approach, scope, and Cobra generator implications.
changelogs/unreleased/9720-Joeavaikath Adds an unreleased changelog entry for the feature.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +43 to +45
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
freshList := list.DeepCopyObject().(kbclient.ObjectList)
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

The completion request context is always derived from context.Background(). It would be better to derive from cmd.Context() (when available) so shell completion can be cancelled promptly, and to avoid holding onto work after the caller exits. Also, the type assertion on list.DeepCopyObject() can panic if a non-ObjectList slips in; consider using an ok check and failing silently (nil completions) instead of panicking.

Suggested change
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
freshList := list.DeepCopyObject().(kbclient.ObjectList)
parentCtx := context.Background()
if cmd != nil && cmd.Context() != nil {
parentCtx = cmd.Context()
}
ctx, cancel := context.WithTimeout(parentCtx, 3*time.Second)
defer cancel()
freshObject := list.DeepCopyObject()
freshList, ok := freshObject.(kbclient.ObjectList)
if !ok {
return nil, cobra.ShellCompDirectiveNoFileComp
}

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +64
var filtered []string
for _, item := range items {
accessor, err := meta.Accessor(item)
if err != nil {
continue
}
if name := accessor.GetName(); strings.HasPrefix(name, toComplete) {
filtered = append(filtered, name)
}
}
return filtered, cobra.ShellCompDirectiveNoFileComp
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

The returned completion names are currently in whatever order the API server/client returns list items, which is not guaranteed to be stable. Sorting the filtered slice before returning will make completions deterministic (and typically alphabetical), improving UX and preventing order-dependent tests from becoming flaky.

Copilot uses AI. Check for mistakes.
got, directive := completionFn(&cobra.Command{}, nil, tc.toComplete)

assert.Equal(t, cobra.ShellCompDirectiveNoFileComp, directive)
assert.Equal(t, tc.want, got)
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

This test uses assert.Equal on slices, which makes it order-dependent. Since Kubernetes list ordering isn't guaranteed (and the fake client implementation could change), consider sorting got/want before comparing or using assert.ElementsMatch to avoid flaky tests.

Suggested change
assert.Equal(t, tc.want, got)
assert.ElementsMatch(t, tc.want, got)

Copilot uses AI. Check for mistakes.
Comment on lines +79 to +82
_ = c.RegisterFlagCompletionFunc("from-schedule", cli.CompleteScheduleNames(f))
_ = c.RegisterFlagCompletionFunc("storage-location", cli.CompleteBackupStorageLocationNames(f))
_ = c.RegisterFlagCompletionFunc("volume-snapshot-locations", cli.CompleteVolumeSnapshotLocationNames(f))

Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

volume-snapshot-locations is a StringSlice flag (comma-separated in a single shell word). The current completion function only matches prefixes from the start of toComplete, so completing a second/third value like --volume-snapshot-locations loc1,lo<TAB> will not suggest anything. Consider registering a small wrapper completion function for this flag that splits toComplete on commas, completes only the last segment, and re-attaches the already-typed prefix (optionally also filtering out already-selected locations).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants