@@ -30,32 +30,44 @@ import (
3030 "github.com/vmware-tanzu/velero/pkg/client"
3131 "github.com/vmware-tanzu/velero/pkg/cmd"
3232 "github.com/vmware-tanzu/velero/pkg/cmd/util/output"
33+ corev1 "k8s.io/api/core/v1"
3334 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3435)
3536
36- func NewCreateCommand (f client.Factory , use string ) * cobra.Command {
37+ func NewCreateCommand (f client.Factory ) * cobra.Command {
3738 o := NewCreateOptions ()
3839
3940 c := & cobra.Command {
40- Use : use + " NAME" ,
41+ Use : "create NAME" ,
4142 Short : "Create a non-admin backup storage location" ,
4243 Args : cobra .ExactArgs (1 ),
4344 Run : func (c * cobra.Command , args []string ) {
4445 cmd .CheckError (o .Complete (args , f ))
4546 cmd .CheckError (o .Validate (c , args , f ))
4647 cmd .CheckError (o .Run (c , f ))
4748 },
48- Example : ` # Create a non-admin backup storage location
49- kubectl oadp nonadmin bsl create my-bsl --backup-storage-location default
50-
51- # Create a non-admin backup storage location with specific namespace
52- kubectl oadp nonadmin bsl create my-bsl --backup-storage-location aws-bsl --namespace my-namespace
53-
54- # Create with custom BSL namespace (if OADP operator is not in openshift-adp)
55- kubectl oadp nonadmin bsl create my-bsl --backup-storage-location default --bsl-namespace velero
56-
57- # View the YAML for a non-admin backup storage location without sending it to the server
58- kubectl oadp nonadmin bsl create my-bsl --backup-storage-location default -o yaml` ,
49+ Example : ` # Create a non-admin backup storage location for AWS
50+ kubectl oadp nonadmin bsl create my-storage \
51+ --provider aws \
52+ --bucket my-velero-bucket \
53+ --credential-name cloud-credentials \
54+ --region us-east-1
55+
56+ # Create with prefix for organizing backups
57+ kubectl oadp nonadmin bsl create my-storage \
58+ --provider aws \
59+ --bucket my-velero-bucket \
60+ --prefix velero-backups \
61+ --credential-name cloud-credentials \
62+ --region us-east-1
63+
64+ # View the YAML without creating the resource
65+ kubectl oadp nonadmin bsl create my-storage \
66+ --provider aws \
67+ --bucket my-bucket \
68+ --credential-name cloud-credentials \
69+ --region us-east-1 \
70+ -o yaml` ,
5971 }
6072
6173 o .BindFlags (c .Flags ())
@@ -66,89 +78,115 @@ func NewCreateCommand(f client.Factory, use string) *cobra.Command {
6678}
6779
6880type CreateOptions struct {
69- Name string
70- BackupStorageLocation string
71- NonAdminNamespace string
72- BSLNamespace string
73- client kbclient.WithWatch
81+ Name string
82+ Namespace string
83+ Provider string
84+ Bucket string
85+ Prefix string
86+ CredentialName string
87+ Region string
88+ Config map [string ]string
89+ client kbclient.WithWatch
7490}
7591
7692func NewCreateOptions () * CreateOptions {
7793 return & CreateOptions {
78- BSLNamespace : "openshift-adp" , // Default OADP operator namespace
94+ Config : make ( map [ string ] string ),
7995 }
8096}
8197
8298func (o * CreateOptions ) BindFlags (flags * pflag.FlagSet ) {
83- flags .StringVar (& o .BackupStorageLocation , "backup-storage-location" , "" , "Name of the BackupStorageLocation to reference." )
84- flags .StringVar (& o .NonAdminNamespace , "namespace" , "" , "Namespace for the NonAdminBackupStorageLocation (defaults to current context namespace)." )
85- flags .StringVar (& o .BSLNamespace , "bsl-namespace" , "openshift-adp" , "Namespace where the BackupStorageLocation exists." )
99+ flags .StringVar (& o .Provider , "provider" , "" , "Storage provider (required). Examples: aws, azure, gcp" )
100+ flags .StringVar (& o .Bucket , "bucket" , "" , "Object storage bucket name (required)" )
101+ flags .StringVar (& o .Prefix , "prefix" , "" , "Prefix for backup objects in the bucket" )
102+ flags .StringVar (& o .CredentialName , "credential-name" , "" , "Name of the credential secret (required)" )
103+ flags .StringVar (& o .Region , "region" , "" , "Storage region (required for some providers like AWS)" )
104+ flags .StringToStringVar (& o .Config , "config" , nil , "Additional provider-specific configuration (key=value pairs)" )
86105}
87106
88107func (o * CreateOptions ) Complete (args []string , f client.Factory ) error {
89108 o .Name = args [0 ]
90109
91- // Create client with Velero scheme for BackupStorageLocation access
92- client , err := shared .NewClientWithScheme (f , shared.ClientOptions {
93- IncludeVeleroTypes : true ,
94- })
110+ // Create client with full scheme including NonAdmin and Velero types
111+ client , err := shared .NewClientWithFullScheme (f )
95112 if err != nil {
96113 return err
97114 }
98115
99116 o .client = client
100117
101- if o .NonAdminNamespace == "" {
102- namespace := f .Namespace ()
103- o .NonAdminNamespace = namespace
118+ // Get the current namespace
119+ currentNS , err := shared .GetCurrentNamespace ()
120+ if err != nil {
121+ return fmt .Errorf ("failed to determine current namespace: %w" , err )
104122 }
123+ o .Namespace = currentNS
105124
106125 return nil
107126}
108127
109128func (o * CreateOptions ) Validate (c * cobra.Command , args []string , f client.Factory ) error {
110- if o .BackupStorageLocation == "" {
111- return fmt .Errorf ("--backup-storage-location is required" )
129+ if o .Provider == "" {
130+ return fmt .Errorf ("--provider is required" )
131+ }
132+ if o .Bucket == "" {
133+ return fmt .Errorf ("--bucket is required" )
134+ }
135+ if o .CredentialName == "" {
136+ return fmt .Errorf ("--credential-name is required" )
112137 }
113138
114139 return nil
115140}
116141
117142func (o * CreateOptions ) Run (c * cobra.Command , f client.Factory ) error {
118- // If we have a BackupStorageLocation name, we need to fetch its spec
119- var bslSpec * velerov1.BackupStorageLocationSpec
120- if o .BackupStorageLocation != "" {
121- // Get the existing BackupStorageLocation to copy its spec
122- existingBSL := & velerov1.BackupStorageLocation {}
123- err := o .client .Get (context .Background (), kbclient.ObjectKey {
124- Name : o .BackupStorageLocation ,
125- Namespace : o .BSLNamespace , // Use the BSLNamespace flag
126- }, existingBSL )
127- if err != nil {
128- return fmt .Errorf ("failed to get BackupStorageLocation %q: %w" , o .BackupStorageLocation , err )
129- }
130- bslSpec = & existingBSL .Spec
143+ // Build config map
144+ config := make (map [string ]string )
145+ if o .Region != "" {
146+ config ["region" ] = o .Region
147+ }
148+ // Add any additional config provided via --config flag
149+ for k , v := range o .Config {
150+ config [k ] = v
131151 }
132152
133- bsl := & nacv1alpha1.NonAdminBackupStorageLocation {
153+ // Create the NABSL
154+ nabsl := & nacv1alpha1.NonAdminBackupStorageLocation {
134155 ObjectMeta : metav1.ObjectMeta {
135156 Name : o .Name ,
136- Namespace : o .NonAdminNamespace ,
157+ Namespace : o .Namespace ,
137158 },
138159 Spec : nacv1alpha1.NonAdminBackupStorageLocationSpec {
139- BackupStorageLocationSpec : bslSpec ,
160+ BackupStorageLocationSpec : & velerov1.BackupStorageLocationSpec {
161+ Provider : o .Provider ,
162+ Config : config ,
163+ Credential : & corev1.SecretKeySelector {
164+ LocalObjectReference : corev1.LocalObjectReference {
165+ Name : o .CredentialName ,
166+ },
167+ Key : "cloud" , // Standard key name for cloud credentials
168+ },
169+ StorageType : velerov1.StorageType {
170+ ObjectStorage : & velerov1.ObjectStorageLocation {
171+ Bucket : o .Bucket ,
172+ Prefix : o .Prefix ,
173+ },
174+ },
175+ },
140176 },
141177 }
142178
143- if printed , err := output .PrintWithFormat (c , bsl ); printed || err != nil {
179+ if printed , err := output .PrintWithFormat (c , nabsl ); printed || err != nil {
144180 return err
145181 }
146182
147- err := o .client .Create (context .Background (), bsl )
183+ err := o .client .Create (context .Background (), nabsl )
148184 if err != nil {
149185 return err
150186 }
151187
152- fmt .Printf ("NonAdminBackupStorageLocation %q created successfully.\n " , bsl .Name )
188+ fmt .Printf ("NonAdminBackupStorageLocation %q created successfully.\n " , nabsl .Name )
189+ fmt .Printf ("The controller will create a request for admin approval.\n " )
190+ fmt .Printf ("Use 'kubectl oadp nonadmin bsl request get' to view auto-created requests.\n " )
153191 return nil
154192}
0 commit comments