Enhanced Plugin Management — Design Proposal
Status: Draft
Author: Jake Abendroth (abendrothj)
Related issue: https://github.com/vmware-tanzu/velero/issues/3210
Related implementation PR: https://github.com/vmware-tanzu/velero/pull/9352
Target release: v1.19 (note: v1.18 feature freeze is near)
Summary
This proposal improves Velero's CLI/plugin UX by clearly indicating which plugins are built into the Velero server binary and by allowing velero plugin remove <plugin-name> semantics that map user-facing plugin names (e.g., velero.io/aws) to init-container images/names. The changes are intentionally limited to CLI/API metadata and removal UX; they do not change plugin discovery or plugin runtime registration.
The implementation work is in vmware-tanzu/velero#9352 and this design PR is intended to let maintainers review the design independent of the implementation.
Motivation
- Users see plugins via
velero plugin getbut cannot tell which plugins are built-in (and therefore cannot be removed). -
velero plugin removecurrently requires the init container name or image string; users expect to use plugin names shown invelero plugin getinstead. - Provide clearer diagnostics and safer removal workflows.
Goals
- Add plugin metadata indicating built-in status and registering command for diagnostics.
- Display built-in status in CLI output.
- Allow
velero plugin remove <plugin-name>that resolves to an init container image/name and refuses removal of built-in plugins. - Preserve existing
velero plugin remove <image|container>behavior for backwards compatibility.
Non-Goals
- Changing plugin registration/discovery mechanisms.
- Adding package/registry systems for plugins.
- Major runtime or packaging redesign.
Proposed API changes
Modify the ServerStatusRequest API plugin information to carry additional optional fields:
File: pkg/apis/velero/v1/server_status_request_types.go
- Add fields to PluginInfo:
type PluginInfo struct {
Name string `json:"name"`
Kind string `json:"kind"`
// Command is the command/binary that registered the plugin on the server.
// +optional
Command string `json:"command,omitempty"`
// BuiltIn indicates whether the plugin is provided by the Velero server
// binary (i.e. a system plugin that cannot be removed by changing init containers).
// +optional
BuiltIn bool `json:"builtIn,omitempty"`
}
These fields are optional to preserve API compatibility with older clients.
Server-side behavior
File: internal/velero/serverstatusrequest.go
- GetInstalledPluginInfo should set PluginInfo.Command (the registering process/binary) and PluginInfo.BuiltIn.
- Heuristic for BuiltIn: plugin.Command == os.Args[0] OR another reliable indicator that the plugin was registered by the Velero server binary.
CLI output
File: pkg/cmd/util/output/plugin_printer.go
- Add a "BuiltIn" column to the plugin table output. This gives operators a clear, at-a-glance indicator of mandatory built-in plugins vs external ones.
Plugin removal command
File: pkg/cmd/cli/plugin/remove.go
-
Accept plugin names (e.g., velero.io/aws) as input in addition to existing image/container names.
-
Workflow:
- Query server status (ServerStatusRequest) to check whether specified plugin name exists and whether it has BuiltIn==true. If built-in — refuse removal with a clear error message.
- If not built-in, resolve the plugin name to an init container via heuristics:
- Exact init container name match.
- Exact init container image match.
- Sanitized plugin name match (e.g., convert
velero.io/aws->aws) to container name or image substring. - Substring match on init container image or name.
- If zero matches, error with a message listing the available init containers and their images.
- If multiple matches, error asking for disambiguation (or accept a
--image/--containerflag). - If a single match, remove that init container as existing behavior does (patch the Velero Deployment).
-
Maintain backwards compatibility:
velero plugin remove <image|container>remains valid.
Compatibility
- API backward compatible: new PluginInfo fields are optional.
- CLI backward compatible: existing usage of
velero plugin remove <image|container>continues to work. - No changes required to existing Velero deployments.
Security considerations
- Built-in protection prevents accidental removal of mandatory plugins that ship with the Velero server binary.
- The ServerStatusRequest remains a read-only status resource; no elevated privileges are introduced by these read-only fields.
- Removal still requires permissions to patch the Velero Deployment (existing requirement).
Tests
- Unit tests: server-side population of PluginInfo fields; printer output; remove command heuristics and error cases.
- Integration tests:
velero plugin getshows BuiltIn flags;velero plugin remove <plugin-name>resolves correctly and patches Deployment; refusing removal for BuiltIn plugins.
Implementation references
- Implementation PR: https://github.com/vmware-tanzu/velero/pull/9352
- Related issue: https://github.com/vmware-tanzu/velero/issues/3210
- Files touched (main-branch locations):
- pkg/apis/velero/v1/server_status_request_types.go
- internal/velero/serverstatusrequest.go
- pkg/cmd/util/output/plugin_printer.go
- pkg/cmd/cli/plugin/remove.go
might want to rebase. design proposal shouldn't contain .go changes.
We can keep code changes in for now and once design is agreed and if implementation still need enhancement after that we can move implementation out to a follow up pr.