@@ -42,8 +42,11 @@ import (
42
42
"gopkg.in/gcfg.v1"
43
43
44
44
"k8s.io/api/core/v1"
45
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
45
46
"k8s.io/apimachinery/pkg/types"
46
47
netutil "k8s.io/apimachinery/pkg/util/net"
48
+ "k8s.io/client-go/kubernetes"
49
+ "k8s.io/client-go/tools/clientcmd"
47
50
certutil "k8s.io/client-go/util/cert"
48
51
cloudprovider "k8s.io/cloud-provider"
49
52
nodehelpers "k8s.io/cloud-provider/node/helpers"
@@ -145,17 +148,19 @@ type OpenStack struct {
145
148
// Config is used to read and store information from the cloud configuration file
146
149
type Config struct {
147
150
Global struct {
148
- AuthURL string `gcfg:"auth-url"`
149
- Username string
150
- UserID string `gcfg:"user-id"`
151
- Password string
152
- TenantID string `gcfg:"tenant-id"`
153
- TenantName string `gcfg:"tenant-name"`
154
- TrustID string `gcfg:"trust-id"`
155
- DomainID string `gcfg:"domain-id"`
156
- DomainName string `gcfg:"domain-name"`
157
- Region string
158
- CAFile string `gcfg:"ca-file"`
151
+ AuthURL string `gcfg:"auth-url"`
152
+ Username string
153
+ UserID string `gcfg:"user-id"`
154
+ Password string
155
+ TenantID string `gcfg:"tenant-id"`
156
+ TenantName string `gcfg:"tenant-name"`
157
+ TrustID string `gcfg:"trust-id"`
158
+ DomainID string `gcfg:"domain-id"`
159
+ DomainName string `gcfg:"domain-name"`
160
+ Region string
161
+ CAFile string `gcfg:"ca-file"`
162
+ SecretName string `gcfg:"secret-name"`
163
+ SecretNamespace string `gcfg:"secret-namespace"`
159
164
}
160
165
LoadBalancer LoadBalancerOpts
161
166
BlockStorage BlockStorageOpts
@@ -231,6 +236,9 @@ func configFromEnv() (cfg Config, ok bool) {
231
236
cfg .Global .DomainName = os .Getenv ("OS_USER_DOMAIN_NAME" )
232
237
}
233
238
239
+ cfg .Global .SecretName = os .Getenv ("SECRET_NAME" )
240
+ cfg .Global .SecretNamespace = os .Getenv ("SECRET_NAMESPACE" )
241
+
234
242
ok = cfg .Global .AuthURL != "" &&
235
243
cfg .Global .Username != "" &&
236
244
cfg .Global .Password != "" &&
@@ -245,6 +253,58 @@ func configFromEnv() (cfg Config, ok bool) {
245
253
return
246
254
}
247
255
256
+ func createKubernetesClient () (* kubernetes.Clientset , error ) {
257
+ klog .Info ("Creating kubernetes API client." )
258
+
259
+ // create in-cluster config
260
+ cfg , err := clientcmd .BuildConfigFromFlags ("" , "" )
261
+ if err != nil {
262
+ return nil , err
263
+ }
264
+
265
+ client , err := kubernetes .NewForConfig (cfg )
266
+ if err != nil {
267
+ return nil , err
268
+ }
269
+
270
+ v , err := client .Discovery ().ServerVersion ()
271
+ if err != nil {
272
+ return nil , err
273
+ }
274
+
275
+ klog .Infof ("Kubernetes API client created, server version %s" , fmt .Sprintf ("v%v.%v" , v .Major , v .Minor ))
276
+ return client , nil
277
+ }
278
+
279
+ // setConfigFromSecret allows setting up the config from k8s secret
280
+ func setConfigFromSecret (cfg * Config ) error {
281
+ secretName := cfg .Global .SecretName
282
+ secretNamespace := cfg .Global .SecretNamespace
283
+
284
+ k8sClient , err := createKubernetesClient ()
285
+ if err != nil {
286
+ return fmt .Errorf ("failed to get kubernetes client: %v" , err )
287
+ }
288
+
289
+ secret , err := k8sClient .CoreV1 ().Secrets (secretNamespace ).Get (secretName , metav1.GetOptions {})
290
+ if err != nil {
291
+ klog .Warningf ("Cannot get secret %s in namespace %s. error: %q" , secretName , secretNamespace , err )
292
+ return err
293
+ }
294
+
295
+ if content , ok := secret .Data ["clouds.conf" ]; ok {
296
+ err = gcfg .ReadStringInto (cfg , string (content ))
297
+ if err != nil {
298
+ klog .Errorf ("Cannot parse data from the secret." )
299
+ return fmt .Errorf ("cannot parse data from the secret" )
300
+ }
301
+ return nil
302
+ }
303
+
304
+ klog .Errorf ("Cannot find \" clouds.conf\" key in the secret." )
305
+ return fmt .Errorf ("cannot find \" clouds.conf\" key in the secret" )
306
+ }
307
+
248
308
func readConfig (config io.Reader ) (Config , error ) {
249
309
if config == nil {
250
310
return Config {}, fmt .Errorf ("no OpenStack cloud provider config file given" )
@@ -259,7 +319,19 @@ func readConfig(config io.Reader) (Config, error) {
259
319
cfg .Metadata .SearchOrder = fmt .Sprintf ("%s,%s" , configDriveID , metadataID )
260
320
261
321
err := gcfg .ReadInto (& cfg , config )
262
- return cfg , err
322
+ if err != nil {
323
+ return cfg , err
324
+ }
325
+
326
+ if cfg .Global .SecretName != "" && cfg .Global .SecretNamespace != "" {
327
+ klog .Infof ("Set credentials from secret %s in namespace %s" , cfg .Global .SecretName , cfg .Global .SecretNamespace )
328
+ err = setConfigFromSecret (& cfg )
329
+ if err != nil {
330
+ return cfg , err
331
+ }
332
+ }
333
+
334
+ return cfg , nil
263
335
}
264
336
265
337
// caller is a tiny helper for conditional unwind logic
0 commit comments