From 7771b0f0e33507b7625637bbfb8d956c606921eb Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 27 Feb 2026 10:19:57 -0800 Subject: [PATCH 1/6] Add config to set default storage location for non-admin backups Adds a config value to the Velero client config file to set the default storage location for non-admin backups. Adds a command output on NABSL creation to inform the user about the default storage location config. Signed-off-by: Joseph --- cmd/non-admin/backup/create.go | 19 +++++++++++++++++-- cmd/non-admin/bsl/create.go | 3 ++- cmd/shared/factories.go | 14 ++++++++++++-- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/cmd/non-admin/backup/create.go b/cmd/non-admin/backup/create.go index e1c7d8e9..f22bfd05 100644 --- a/cmd/non-admin/backup/create.go +++ b/cmd/non-admin/backup/create.go @@ -61,6 +61,9 @@ func NewCreateCommand(f client.Factory, use string) *cobra.Command { # Create a backup with specific storage location. oc oadp nonadmin backup create backup5 --storage-location my-nabsl + # Set default storage location for all backups. + oc oadp client config set default-nabsl=my-nabsl + # View the YAML for a backup without sending it to the server. oc oadp nonadmin backup create backup6 -o yaml`, } @@ -102,7 +105,7 @@ func (o *CreateOptions) BindFlags(flags *pflag.FlagSet) { // Timing/Storage (MVP) flags.DurationVar(&o.TTL, "ttl", o.TTL, "How long before the backup can be garbage collected.") - flags.StringVar(&o.StorageLocation, "storage-location", "", "Location in which to store the backup.") + flags.StringVar(&o.StorageLocation, "storage-location", "", "Location in which to store the backup. Uses config 'default-nabsl' if not specified.") flags.DurationVar(&o.CSISnapshotTimeout, "csi-snapshot-timeout", o.CSISnapshotTimeout, "How long to wait for CSI snapshot creation before timeout.") flags.DurationVar(&o.ItemOperationTimeout, "item-operation-timeout", o.ItemOperationTimeout, "How long to wait for async plugin operations before timeout.") @@ -132,7 +135,7 @@ func (o *CreateOptions) Validate(c *cobra.Command, args []string, f client.Facto // Storage location validation if o.StorageLocation == "" { - return fmt.Errorf("--storage-location is required") + return fmt.Errorf("--storage-location is required (can be set via flag or config 'default-nabsl')") } return nil @@ -141,6 +144,18 @@ func (o *CreateOptions) Validate(c *cobra.Command, args []string, f client.Facto func (o *CreateOptions) Complete(args []string, f client.Factory) error { o.Name = args[0] + // Load default storage location from config if not provided via flag + if o.StorageLocation == "" { + clientConfig, err := shared.ReadVeleroClientConfig() + if err == nil && clientConfig != nil { + defaultNABSL := clientConfig.GetDefaultNABSL() + if defaultNABSL != "" { + o.StorageLocation = defaultNABSL + } + } + // Silently ignore config read errors - validation will catch missing storage location + } + // Create client with NonAdmin scheme client, err := shared.NewClientWithScheme(f, shared.ClientOptions{ IncludeNonAdminTypes: true, diff --git a/cmd/non-admin/bsl/create.go b/cmd/non-admin/bsl/create.go index 3030f9a1..79d856eb 100644 --- a/cmd/non-admin/bsl/create.go +++ b/cmd/non-admin/bsl/create.go @@ -200,6 +200,7 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { fmt.Printf("NonAdminBackupStorageLocation %q created successfully.\n", nabsl.Name) fmt.Printf("The controller will create a request for admin approval.\n") - fmt.Printf("Use 'oc oadp nonadmin bsl request get' to view auto-created requests.\n") + fmt.Printf("Use 'oc oadp nonadmin bsl request get' to view created requests.\n") + fmt.Printf("Use `oc oadp client config set default-nabsl=%s` to set this BSL as the default to avoid specifying the BSL name each time.\n", nabsl.Name) return nil } diff --git a/cmd/shared/factories.go b/cmd/shared/factories.go index 08af2484..20a6eca7 100644 --- a/cmd/shared/factories.go +++ b/cmd/shared/factories.go @@ -28,8 +28,9 @@ import ( // ClientConfig represents the structure of the Velero client configuration file type ClientConfig struct { - Namespace string `json:"namespace"` - NonAdmin interface{} `json:"nonadmin,omitempty"` + Namespace string `json:"namespace"` + NonAdmin interface{} `json:"nonadmin,omitempty"` + DefaultNABSL string `json:"default-nabsl,omitempty"` } // IsNonAdmin returns true if the nonadmin configuration is enabled. @@ -49,6 +50,15 @@ func (c *ClientConfig) IsNonAdmin() bool { } } +// GetDefaultNABSL returns the default NonAdminBackupStorageLocation if set. +// Returns empty string if not configured. +func (c *ClientConfig) GetDefaultNABSL() string { + if c == nil { + return "" + } + return c.DefaultNABSL +} + // CreateVeleroFactory creates a client factory for Velero operations (admin-scoped) // that uses the client configuration to determine the namespace. // Priority order: From 49a0e95b6cc10d8484a82012e8bc17e18bfba2d0 Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 27 Feb 2026 10:45:56 -0800 Subject: [PATCH 2/6] Display use of config default storage location If default storage location is set in config, display a message that it is being used. Signed-off-by: Joseph --- cmd/non-admin/backup/create.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/cmd/non-admin/backup/create.go b/cmd/non-admin/backup/create.go index f22bfd05..5cb40b9c 100644 --- a/cmd/non-admin/backup/create.go +++ b/cmd/non-admin/backup/create.go @@ -144,16 +144,9 @@ func (o *CreateOptions) Validate(c *cobra.Command, args []string, f client.Facto func (o *CreateOptions) Complete(args []string, f client.Factory) error { o.Name = args[0] - // Load default storage location from config if not provided via flag - if o.StorageLocation == "" { - clientConfig, err := shared.ReadVeleroClientConfig() - if err == nil && clientConfig != nil { - defaultNABSL := clientConfig.GetDefaultNABSL() - if defaultNABSL != "" { - o.StorageLocation = defaultNABSL - } - } - // Silently ignore config read errors - validation will catch missing storage location + defaultNABSL := getNABSLFromConfig() + if defaultNABSL != "" { + o.StorageLocation = defaultNABSL } // Create client with NonAdmin scheme @@ -190,8 +183,12 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { return err } + if defaultNABSL := getNABSLFromConfig(); defaultNABSL != "" { + fmt.Printf("Using default storage location from config: %s\n", defaultNABSL) + } fmt.Printf("NonAdminBackup request %q submitted successfully.\n", nonAdminBackup.Name) fmt.Printf("Run `oc oadp nonadmin backup describe %s` or `oc oadp nonadmin backup logs %s` for more details.\n", nonAdminBackup.Name, nonAdminBackup.Name) + return nil } @@ -252,3 +249,14 @@ func (o *CreateOptions) createNonAdminBackup(namespace string, backupSpec *veler }). Result() } + +func getNABSLFromConfig() string { + clientConfig, err := shared.ReadVeleroClientConfig() + if err == nil && clientConfig != nil { + defaultNABSL := clientConfig.GetDefaultNABSL() + if defaultNABSL != "" { + return defaultNABSL + } + } + return "" +} From ffb64f44fbb49537ba95d5734bd20d5a0828189a Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 27 Feb 2026 11:04:41 -0800 Subject: [PATCH 3/6] Line breaks in create output Add line breaks in create output for non-admin backup and NABSL creation. Signed-off-by: Joseph --- cmd/non-admin/backup/create.go | 2 ++ cmd/non-admin/bsl/create.go | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/non-admin/backup/create.go b/cmd/non-admin/backup/create.go index 5cb40b9c..419a0b47 100644 --- a/cmd/non-admin/backup/create.go +++ b/cmd/non-admin/backup/create.go @@ -186,8 +186,10 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { if defaultNABSL := getNABSLFromConfig(); defaultNABSL != "" { fmt.Printf("Using default storage location from config: %s\n", defaultNABSL) } + fmt.Printf("NonAdminBackup request %q submitted successfully.\n", nonAdminBackup.Name) fmt.Printf("Run `oc oadp nonadmin backup describe %s` or `oc oadp nonadmin backup logs %s` for more details.\n", nonAdminBackup.Name, nonAdminBackup.Name) + fmt.Println() return nil } diff --git a/cmd/non-admin/bsl/create.go b/cmd/non-admin/bsl/create.go index 79d856eb..50eba6ec 100644 --- a/cmd/non-admin/bsl/create.go +++ b/cmd/non-admin/bsl/create.go @@ -199,8 +199,9 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { } fmt.Printf("NonAdminBackupStorageLocation %q created successfully.\n", nabsl.Name) - fmt.Printf("The controller will create a request for admin approval.\n") - fmt.Printf("Use 'oc oadp nonadmin bsl request get' to view created requests.\n") + fmt.Println("The controller will create a request for admin approval.") + fmt.Println("Use 'oc oadp nonadmin bsl request get' to view created requests.") fmt.Printf("Use `oc oadp client config set default-nabsl=%s` to set this BSL as the default to avoid specifying the BSL name each time.\n", nabsl.Name) + fmt.Println() return nil } From d06aba66befe7bbe2680b22d3680602a8378c919 Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 27 Feb 2026 11:15:50 -0800 Subject: [PATCH 4/6] Mention nonadmin Signed-off-by: Joseph --- cmd/non-admin/backup/create.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/non-admin/backup/create.go b/cmd/non-admin/backup/create.go index 419a0b47..f57bd383 100644 --- a/cmd/non-admin/backup/create.go +++ b/cmd/non-admin/backup/create.go @@ -184,7 +184,7 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { } if defaultNABSL := getNABSLFromConfig(); defaultNABSL != "" { - fmt.Printf("Using default storage location from config: %s\n", defaultNABSL) + fmt.Printf("Using default nonadmin backup storage location from config: %s\n", defaultNABSL) } fmt.Printf("NonAdminBackup request %q submitted successfully.\n", nonAdminBackup.Name) From 4deb38e7d048898b7d1962c65168499d891cabf9 Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 27 Feb 2026 11:31:39 -0800 Subject: [PATCH 5/6] Fix bug Signed-off-by: Joseph --- cmd/non-admin/backup/create.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/cmd/non-admin/backup/create.go b/cmd/non-admin/backup/create.go index f57bd383..2f522e46 100644 --- a/cmd/non-admin/backup/create.go +++ b/cmd/non-admin/backup/create.go @@ -79,9 +79,10 @@ type CreateOptions struct { *velerobackup.CreateOptions // Embed Velero's CreateOptions // NAB-specific fields - Name string // The NonAdminBackup resource name (maps to Velero's BackupName) - client kbclient.WithWatch - currentNamespace string + Name string // The NonAdminBackup resource name (maps to Velero's BackupName) + client kbclient.WithWatch + currentNamespace string + storageLocationFromConfig bool // Track if storage location came from config } func NewCreateOptions() *CreateOptions { @@ -144,9 +145,13 @@ func (o *CreateOptions) Validate(c *cobra.Command, args []string, f client.Facto func (o *CreateOptions) Complete(args []string, f client.Factory) error { o.Name = args[0] - defaultNABSL := getNABSLFromConfig() - if defaultNABSL != "" { - o.StorageLocation = defaultNABSL + // Load default NABSL from config if not provided via flag + if o.StorageLocation == "" { + defaultNABSL := getNABSLFromConfig() + if defaultNABSL != "" { + o.StorageLocation = defaultNABSL + o.storageLocationFromConfig = true + } } // Create client with NonAdmin scheme @@ -183,8 +188,8 @@ func (o *CreateOptions) Run(c *cobra.Command, f client.Factory) error { return err } - if defaultNABSL := getNABSLFromConfig(); defaultNABSL != "" { - fmt.Printf("Using default nonadmin backup storage location from config: %s\n", defaultNABSL) + if o.storageLocationFromConfig { + fmt.Printf("Using default nonadmin backup storage location from config: %s\n", o.StorageLocation) } fmt.Printf("NonAdminBackup request %q submitted successfully.\n", nonAdminBackup.Name) From 277ce5fcb2c8b08b20e8ba2d6c401fd24dc6d022 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 2 Mar 2026 11:18:33 -0500 Subject: [PATCH 6/6] Improve error message for default storage location Signed-off-by: Joseph --- cmd/non-admin/backup/create.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/non-admin/backup/create.go b/cmd/non-admin/backup/create.go index 2f522e46..cd182e01 100644 --- a/cmd/non-admin/backup/create.go +++ b/cmd/non-admin/backup/create.go @@ -136,7 +136,9 @@ func (o *CreateOptions) Validate(c *cobra.Command, args []string, f client.Facto // Storage location validation if o.StorageLocation == "" { - return fmt.Errorf("--storage-location is required (can be set via flag or config 'default-nabsl')") + return fmt.Errorf("--storage-location is required\n" + + "To avoid specifying the storage location each time:\n" + + "run `oc oadp client config set default-nabsl=` to set the default storage location") } return nil