Merge pull request #75062 from Fedosin/openstack_config_from_secrets

Allow to read OpenStack config from the secret
k3s-v1.15.3
Kubernetes Prow Robot 2019-03-25 09:01:20 -07:00 committed by GitHub
commit 055061637a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 100 additions and 23 deletions

View File

@ -23,10 +23,13 @@ go_library(
"//pkg/util/mount:go_default_library", "//pkg/util/mount:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
"//staging/src/k8s.io/client-go/util/cert:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/cloud-provider/node/helpers:go_default_library", "//staging/src/k8s.io/cloud-provider/node/helpers:go_default_library",

View File

@ -42,8 +42,11 @@ import (
"gopkg.in/gcfg.v1" "gopkg.in/gcfg.v1"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
netutil "k8s.io/apimachinery/pkg/util/net" netutil "k8s.io/apimachinery/pkg/util/net"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
certutil "k8s.io/client-go/util/cert" certutil "k8s.io/client-go/util/cert"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
nodehelpers "k8s.io/cloud-provider/node/helpers" nodehelpers "k8s.io/cloud-provider/node/helpers"
@ -156,6 +159,8 @@ type Config struct {
DomainName string `gcfg:"domain-name"` DomainName string `gcfg:"domain-name"`
Region string Region string
CAFile string `gcfg:"ca-file"` CAFile string `gcfg:"ca-file"`
SecretName string `gcfg:"secret-name"`
SecretNamespace string `gcfg:"secret-namespace"`
} }
LoadBalancer LoadBalancerOpts LoadBalancer LoadBalancerOpts
BlockStorage BlockStorageOpts BlockStorage BlockStorageOpts
@ -231,6 +236,9 @@ func configFromEnv() (cfg Config, ok bool) {
cfg.Global.DomainName = os.Getenv("OS_USER_DOMAIN_NAME") cfg.Global.DomainName = os.Getenv("OS_USER_DOMAIN_NAME")
} }
cfg.Global.SecretName = os.Getenv("SECRET_NAME")
cfg.Global.SecretNamespace = os.Getenv("SECRET_NAMESPACE")
ok = cfg.Global.AuthURL != "" && ok = cfg.Global.AuthURL != "" &&
cfg.Global.Username != "" && cfg.Global.Username != "" &&
cfg.Global.Password != "" && cfg.Global.Password != "" &&
@ -245,6 +253,58 @@ func configFromEnv() (cfg Config, ok bool) {
return return
} }
func createKubernetesClient() (*kubernetes.Clientset, error) {
klog.Info("Creating kubernetes API client.")
// create in-cluster config
cfg, err := clientcmd.BuildConfigFromFlags("", "")
if err != nil {
return nil, err
}
client, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, err
}
v, err := client.Discovery().ServerVersion()
if err != nil {
return nil, err
}
klog.Infof("Kubernetes API client created, server version %s", fmt.Sprintf("v%v.%v", v.Major, v.Minor))
return client, nil
}
// setConfigFromSecret allows setting up the config from k8s secret
func setConfigFromSecret(cfg *Config) error {
secretName := cfg.Global.SecretName
secretNamespace := cfg.Global.SecretNamespace
k8sClient, err := createKubernetesClient()
if err != nil {
return fmt.Errorf("failed to get kubernetes client: %v", err)
}
secret, err := k8sClient.CoreV1().Secrets(secretNamespace).Get(secretName, metav1.GetOptions{})
if err != nil {
klog.Warningf("Cannot get secret %s in namespace %s. error: %q", secretName, secretNamespace, err)
return err
}
if content, ok := secret.Data["clouds.conf"]; ok {
err = gcfg.ReadStringInto(cfg, string(content))
if err != nil {
klog.Errorf("Cannot parse data from the secret.")
return fmt.Errorf("cannot parse data from the secret")
}
return nil
}
klog.Errorf("Cannot find \"clouds.conf\" key in the secret.")
return fmt.Errorf("cannot find \"clouds.conf\" key in the secret")
}
func readConfig(config io.Reader) (Config, error) { func readConfig(config io.Reader) (Config, error) {
if config == nil { if config == nil {
return Config{}, fmt.Errorf("no OpenStack cloud provider config file given") return Config{}, fmt.Errorf("no OpenStack cloud provider config file given")
@ -259,7 +319,19 @@ func readConfig(config io.Reader) (Config, error) {
cfg.Metadata.SearchOrder = fmt.Sprintf("%s,%s", configDriveID, metadataID) cfg.Metadata.SearchOrder = fmt.Sprintf("%s,%s", configDriveID, metadataID)
err := gcfg.ReadInto(&cfg, config) err := gcfg.ReadInto(&cfg, config)
if err != nil {
return cfg, err return cfg, err
}
if cfg.Global.SecretName != "" && cfg.Global.SecretNamespace != "" {
klog.Infof("Set credentials from secret %s in namespace %s", cfg.Global.SecretName, cfg.Global.SecretNamespace)
err = setConfigFromSecret(&cfg)
if err != nil {
return cfg, err
}
}
return cfg, nil
} }
// caller is a tiny helper for conditional unwind logic // caller is a tiny helper for conditional unwind logic

View File

@ -315,6 +315,8 @@ func getOpenstackConfig() openstack.Config {
DomainName string `gcfg:"domain-name"` DomainName string `gcfg:"domain-name"`
Region string Region string
CAFile string `gcfg:"ca-file"` CAFile string `gcfg:"ca-file"`
SecretName string `gcfg:"secret-name"`
SecretNamespace string `gcfg:"secret-namespace"`
}{ }{
Username: "user", Username: "user",
Password: "pass", Password: "pass",