@@ -18,6 +18,8 @@ package controller
1818
1919import  (
2020	"fmt" 
21+ 	"strings" 
22+ 
2123	"github.com/golang/glog" 
2224	crdv1 "github.com/kubernetes-csi/external-snapshotter/pkg/apis/volumesnapshot/v1alpha1" 
2325	"k8s.io/api/core/v1" 
@@ -37,12 +39,41 @@ var (
3739	keyFunc  =  cache .DeletionHandlingMetaNamespaceKeyFunc 
3840)
3941
40- const  snapshotterSecretNameKey  =  "csiSnapshotterSecretName" 
41- const  snapshotterSecretNamespaceKey  =  "csiSnapshotterSecretNamespace" 
42+ type  deprecatedSecretParamsMap  struct  {
43+ 	name                          string 
44+ 	deprecatedSecretNameKey       string 
45+ 	deprecatedSecretNamespaceKey  string 
46+ 	secretNameKey                 string 
47+ 	secretNamespaceKey            string 
48+ }
49+ 
50+ const  (
51+ 	// CSI Parameters prefixed with csiParameterPrefix are not passed through 
52+ 	// to the driver on CreateSnapshotRequest calls. Instead they are intended 
53+ 	// to be used by the CSI external-snapshotter and maybe used to populate 
54+ 	// fields in subsequent CSI calls or Kubernetes API objects. 
55+ 	csiParameterPrefix  =  "csi.storage.k8s.io/" 
56+ 
57+ 	prefixedSnapshotterSecretNameKey       =  csiParameterPrefix  +  "snapshotter-secret-name" 
58+ 	prefixedSnapshotterSecretNamespaceKey  =  csiParameterPrefix  +  "snapshotter-secret-namespace" 
4259
43- // Name of finalizer on VolumeSnapshotContents that are bound by VolumeSnapshots 
44- const  VolumeSnapshotContentFinalizer  =  "snapshot.storage.kubernetes.io/volumesnapshotcontent-protection" 
45- const  VolumeSnapshotFinalizer  =  "snapshot.storage.kubernetes.io/volumesnapshot-protection" 
60+ 	// [Deprecated] CSI Parameters that are put into fields but 
61+ 	// NOT stripped from the parameters passed to CreateSnapshot 
62+ 	snapshotterSecretNameKey       =  "csiSnapshotterSecretName" 
63+ 	snapshotterSecretNamespaceKey  =  "csiSnapshotterSecretNamespace" 
64+ 
65+ 	// Name of finalizer on VolumeSnapshotContents that are bound by VolumeSnapshots 
66+ 	VolumeSnapshotContentFinalizer  =  "snapshot.storage.kubernetes.io/volumesnapshotcontent-protection" 
67+ 	VolumeSnapshotFinalizer         =  "snapshot.storage.kubernetes.io/volumesnapshot-protection" 
68+ )
69+ 
70+ var  snapshotterSecretParams  =  deprecatedSecretParamsMap {
71+ 	name : "Snapshotter" ,
72+ 	deprecatedSecretNameKey :      snapshotterSecretNameKey ,
73+ 	deprecatedSecretNamespaceKey : snapshotterSecretNamespaceKey ,
74+ 	secretNameKey :                prefixedSnapshotterSecretNameKey ,
75+ 	secretNamespaceKey :           prefixedSnapshotterSecretNamespaceKey ,
76+ }
4677
4778func  snapshotKey (vs  * crdv1.VolumeSnapshot ) string  {
4879	return  fmt .Sprintf ("%s/%s" , vs .Namespace , vs .Name )
@@ -130,9 +161,54 @@ func IsDefaultAnnotation(obj metav1.ObjectMeta) bool {
130161	return  false 
131162}
132163
133- // GetSecretReference returns a reference to the secret specified in the given nameKey and namespaceKey parameters, or an error if the parameters are not specified correctly. 
134- // if neither the name or namespace parameter are set, a nil reference and no error is returned. 
135- // no lookup of the referenced secret is performed, and the secret may or may not exist. 
164+ // verifyAndGetSecretNameAndNamespaceTemplate gets the values (templates) associated 
165+ // with the parameters specified in "secret" and verifies that they are specified correctly. 
166+ func  verifyAndGetSecretNameAndNamespaceTemplate (secret  deprecatedSecretParamsMap , snapshotClassParams  map [string ]string ) (nameTemplate , namespaceTemplate  string , err  error ) {
167+ 	numName  :=  0 
168+ 	numNamespace  :=  0 
169+ 	if  t , ok  :=  snapshotClassParams [secret .deprecatedSecretNameKey ]; ok  {
170+ 		nameTemplate  =  t 
171+ 		numName  +=  1 
172+ 		glog .Warning (deprecationWarning (secret .deprecatedSecretNameKey , secret .secretNameKey , "" ))
173+ 	}
174+ 	if  t , ok  :=  snapshotClassParams [secret .deprecatedSecretNamespaceKey ]; ok  {
175+ 		namespaceTemplate  =  t 
176+ 		numNamespace  +=  1 
177+ 		glog .Warning (deprecationWarning (secret .deprecatedSecretNamespaceKey , secret .secretNamespaceKey , "" ))
178+ 	}
179+ 	if  t , ok  :=  snapshotClassParams [secret .secretNameKey ]; ok  {
180+ 		nameTemplate  =  t 
181+ 		numName  +=  1 
182+ 	}
183+ 	if  t , ok  :=  snapshotClassParams [secret .secretNamespaceKey ]; ok  {
184+ 		namespaceTemplate  =  t 
185+ 		numNamespace  +=  1 
186+ 	}
187+ 
188+ 	if  numName  >  1  ||  numNamespace  >  1  {
189+ 		// Double specified error 
190+ 		return  "" , "" , fmt .Errorf ("%s secrets specified in paramaters with both \" csi\"  and \" %s\"  keys" , secret .name , csiParameterPrefix )
191+ 	} else  if  numName  !=  numNamespace  {
192+ 		// Not both 0 or both 1 
193+ 		return  "" , "" , fmt .Errorf ("either name and namespace for %s secrets specified, Both must be specified" , secret .name )
194+ 	} else  if  numName  ==  1  {
195+ 		// Case where we've found a name and a namespace template 
196+ 		if  nameTemplate  ==  ""  ||  namespaceTemplate  ==  ""  {
197+ 			return  "" , "" , fmt .Errorf ("%s secrets specified in parameters but value of either namespace or name is empty" , secret .name )
198+ 		}
199+ 		return  nameTemplate , namespaceTemplate , nil 
200+ 	} else  if  numName  ==  0  {
201+ 		// No secrets specified 
202+ 		return  "" , "" , nil 
203+ 	} else  {
204+ 		// THIS IS NOT A VALID CASE 
205+ 		return  "" , "" , fmt .Errorf ("unknown error with getting secret name and namespace templates" )
206+ 	}
207+ }
208+ 
209+ // getSecretReference returns a reference to the secret specified in the given nameTemplate 
210+ //  and namespaceTemplate, or an error if the templates are not specified correctly. 
211+ // No lookup of the referenced secret is performed, and the secret may or may not exist. 
136212// 
137213// supported tokens for name resolution: 
138214// - ${volumesnapshotcontent.name} 
@@ -145,20 +221,17 @@ func IsDefaultAnnotation(obj metav1.ObjectMeta) bool {
145221// - ${volumesnapshot.namespace} 
146222// 
147223// an error is returned in the following situations: 
148- // - only one of name or namespace is provided 
149- // - the name or namespace parameter contains a token that cannot be resolved 
224+ // - the nameTemplate or namespaceTemplate contains a token that cannot be resolved 
150225// - the resolved name is not a valid secret name 
151226// - the resolved namespace is not a valid namespace name 
152- func  GetSecretReference (snapshotClassParams  map [string ]string , snapContentName  string , snapshot  * crdv1.VolumeSnapshot ) (* v1.SecretReference , error ) {
153- 	nameTemplate , hasName  :=  snapshotClassParams [snapshotterSecretNameKey ]
154- 	namespaceTemplate , hasNamespace  :=  snapshotClassParams [snapshotterSecretNamespaceKey ]
155- 
156- 	if  ! hasName  &&  ! hasNamespace  {
157- 		return  nil , nil 
227+ func  getSecretReference (snapshotClassParams  map [string ]string , snapContentName  string , snapshot  * crdv1.VolumeSnapshot ) (* v1.SecretReference , error ) {
228+ 	nameTemplate , namespaceTemplate , err  :=  verifyAndGetSecretNameAndNamespaceTemplate (snapshotterSecretParams , snapshotClassParams )
229+ 	if  err  !=  nil  {
230+ 		return  nil , fmt .Errorf ("failed to get name and namespace template from params: %v" , err )
158231	}
159232
160- 	if  len ( nameTemplate )  ==  0   ||   len ( namespaceTemplate )  ==  0  {
161- 		return  nil , fmt . Errorf ( "%s and %s parameters must be specified together" ,  snapshotterSecretNameKey ,  snapshotterSecretNamespaceKey ) 
233+ 	if  nameTemplate  ==  ""   &&   namespaceTemplate  ==  ""  {
234+ 		return  nil , nil 
162235	}
163236
164237	ref  :=  & v1.SecretReference {}
@@ -174,15 +247,15 @@ func GetSecretReference(snapshotClassParams map[string]string, snapContentName s
174247
175248	resolvedNamespace , err  :=  resolveTemplate (namespaceTemplate , namespaceParams )
176249	if  err  !=  nil  {
177- 		return  nil , fmt .Errorf ("error resolving %s  value %q: %v" ,  snapshotterSecretNamespaceKey , namespaceTemplate , err )
250+ 		return  nil , fmt .Errorf ("error resolving value %q: %v" , namespaceTemplate , err )
178251	}
179252	glog .V (4 ).Infof ("GetSecretReference namespaceTemplate %s, namespaceParams: %+v, resolved %s" , namespaceTemplate , namespaceParams , resolvedNamespace )
180253
181254	if  len (validation .IsDNS1123Label (resolvedNamespace )) >  0  {
182255		if  namespaceTemplate  !=  resolvedNamespace  {
183- 			return  nil , fmt .Errorf ("%s parameter % q resolved to %q which is not a valid namespace name" ,  snapshotterSecretNamespaceKey , namespaceTemplate , resolvedNamespace )
256+ 			return  nil , fmt .Errorf ("%q resolved to %q which is not a valid namespace name" , namespaceTemplate , resolvedNamespace )
184257		}
185- 		return  nil , fmt .Errorf ("%s parameter % q is not a valid namespace name" ,  snapshotterSecretNamespaceKey , namespaceTemplate )
258+ 		return  nil , fmt .Errorf ("%q is not a valid namespace name" , namespaceTemplate )
186259	}
187260	ref .Namespace  =  resolvedNamespace 
188261
@@ -199,13 +272,13 @@ func GetSecretReference(snapshotClassParams map[string]string, snapContentName s
199272	}
200273	resolvedName , err  :=  resolveTemplate (nameTemplate , nameParams )
201274	if  err  !=  nil  {
202- 		return  nil , fmt .Errorf ("error resolving %s  value %q: %v" ,  snapshotterSecretNameKey , nameTemplate , err )
275+ 		return  nil , fmt .Errorf ("error resolving value %q: %v" , nameTemplate , err )
203276	}
204277	if  len (validation .IsDNS1123Subdomain (resolvedName )) >  0  {
205278		if  nameTemplate  !=  resolvedName  {
206- 			return  nil , fmt .Errorf ("%s parameter % q resolved to %q which is not a valid secret name" ,  snapshotterSecretNameKey , nameTemplate , resolvedName )
279+ 			return  nil , fmt .Errorf ("%q resolved to %q which is not a valid secret name" , nameTemplate , resolvedName )
207280		}
208- 		return  nil , fmt .Errorf ("%s parameter % q is not a valid secret name" ,  snapshotterSecretNameKey , nameTemplate )
281+ 		return  nil , fmt .Errorf ("%q is not a valid secret name" , nameTemplate )
209282	}
210283	ref .Name  =  resolvedName 
211284
@@ -229,8 +302,8 @@ func resolveTemplate(template string, params map[string]string) (string, error)
229302	return  resolved , nil 
230303}
231304
232- // GetCredentials  retrieves credentials stored in v1.SecretReference 
233- func  GetCredentials (k8s  kubernetes.Interface , ref  * v1.SecretReference ) (map [string ]string , error ) {
305+ // getCredentials  retrieves credentials stored in v1.SecretReference 
306+ func  getCredentials (k8s  kubernetes.Interface , ref  * v1.SecretReference ) (map [string ]string , error ) {
234307	if  ref  ==  nil  {
235308		return  nil , nil 
236309	}
@@ -271,3 +344,34 @@ func isSnapshotDeletionCandidate(snapshot *crdv1.VolumeSnapshot) bool {
271344func  needToAddSnapshotFinalizer (snapshot  * crdv1.VolumeSnapshot ) bool  {
272345	return  snapshot .ObjectMeta .DeletionTimestamp  ==  nil  &&  ! slice .ContainsString (snapshot .ObjectMeta .Finalizers , VolumeSnapshotFinalizer , nil )
273346}
347+ 
348+ func  deprecationWarning (deprecatedParam , newParam , removalVersion  string ) string  {
349+ 	if  removalVersion  ==  ""  {
350+ 		removalVersion  =  "a future release" 
351+ 	}
352+ 	newParamPhrase  :=  "" 
353+ 	if  len (newParam ) !=  0  {
354+ 		newParamPhrase  =  fmt .Sprintf (", please use \" %s\"  instead" , newParam )
355+ 	}
356+ 	return  fmt .Sprintf ("\" %s\"  is deprecated and will be removed in %s%s" , deprecatedParam , removalVersion , newParamPhrase )
357+ }
358+ 
359+ func  removePrefixedParameters (param  map [string ]string ) (map [string ]string , error ) {
360+ 	newParam  :=  map [string ]string {}
361+ 	for  k , v  :=  range  param  {
362+ 		if  strings .HasPrefix (k , csiParameterPrefix ) {
363+ 			// Check if its well known 
364+ 			switch  k  {
365+ 			case  prefixedSnapshotterSecretNameKey :
366+ 			case  prefixedSnapshotterSecretNamespaceKey :
367+ 			default :
368+ 				return  map [string ]string {}, fmt .Errorf ("found unknown parameter key \" %s\"  with reserved namespace %s" , k , csiParameterPrefix )
369+ 			}
370+ 		} else  {
371+ 			// Don't strip, add this key-value to new map 
372+ 			// Deprecated parameters prefixed with "csi" are not stripped to preserve backwards compatibility 
373+ 			newParam [k ] =  v 
374+ 		}
375+ 	}
376+ 	return  newParam , nil 
377+ }
0 commit comments