Ability to specify OS_* variables for OpenStack configuration

When we convert the OpenStack cloud provider to run in an external
process, we should be able to use kubernetes Secrets capability to
inject the OS_* variables. This way we can specify the cloud
configuration as a configmap, specify secrets for the userid/password
information. The configmap can be mounted as a file. the secrets can
be made available as environment variables. the external controller
itself can run as a pod/daemonset.

For backward compat, we preload all the OS_* variables, if anything
is in the config file, then that overrides the environment variables.
pull/6/head
Davanum Srinivas 2018-01-15 11:20:59 -05:00
parent e290741719
commit f8aef8b911
2 changed files with 61 additions and 52 deletions

View File

@ -23,6 +23,7 @@ import (
"io"
"io/ioutil"
"net/http"
"os"
"regexp"
"strings"
"time"
@ -180,12 +181,50 @@ func (cfg Config) toAuth3Options() tokens3.AuthOptions {
}
}
// configFromEnv allows setting up credentials etc using the
// standard OS_* OpenStack client environment variables.
func configFromEnv() (cfg Config, ok bool) {
cfg.Global.AuthUrl = os.Getenv("OS_AUTH_URL")
cfg.Global.Username = os.Getenv("OS_USERNAME")
cfg.Global.Password = os.Getenv("OS_PASSWORD")
cfg.Global.Region = os.Getenv("OS_REGION_NAME")
cfg.Global.TenantId = os.Getenv("OS_TENANT_ID")
if cfg.Global.TenantId == "" {
cfg.Global.TenantId = os.Getenv("OS_PROJECT_ID")
}
cfg.Global.TenantName = os.Getenv("OS_TENANT_NAME")
if cfg.Global.TenantName == "" {
cfg.Global.TenantName = os.Getenv("OS_PROJECT_NAME")
}
cfg.Global.DomainId = os.Getenv("OS_DOMAIN_ID")
if cfg.Global.DomainId == "" {
cfg.Global.DomainId = os.Getenv("OS_USER_DOMAIN_ID")
}
cfg.Global.DomainName = os.Getenv("OS_DOMAIN_NAME")
if cfg.Global.DomainName == "" {
cfg.Global.DomainName = os.Getenv("OS_USER_DOMAIN_NAME")
}
ok = cfg.Global.AuthUrl != "" &&
cfg.Global.Username != "" &&
cfg.Global.Password != "" &&
(cfg.Global.TenantId != "" || cfg.Global.TenantName != "" ||
cfg.Global.DomainId != "" || cfg.Global.DomainName != "")
cfg.Metadata.SearchOrder = fmt.Sprintf("%s,%s", configDriveID, metadataID)
cfg.BlockStorage.BSVersion = "auto"
return
}
func readConfig(config io.Reader) (Config, error) {
if config == nil {
return Config{}, fmt.Errorf("no OpenStack cloud provider config file given")
}
var cfg Config
cfg, _ := configFromEnv()
// Set default values for config params
cfg.BlockStorage.BSVersion = "auto"

View File

@ -90,10 +90,17 @@ func TestReadConfig(t *testing.T) {
t.Errorf("Should fail when no config is provided: %s", err)
}
os.Setenv("OS_PASSWORD", "mypass")
defer os.Unsetenv("OS_PASSWORD")
os.Setenv("OS_TENANT_NAME", "admin")
defer os.Unsetenv("OS_TENANT_NAME")
cfg, err := readConfig(strings.NewReader(`
[Global]
auth-url = http://auth.url
username = user
user-id = user
tenant-name = demo
[LoadBalancer]
create-monitor = yes
monitor-delay = 1m
@ -113,6 +120,19 @@ func TestReadConfig(t *testing.T) {
t.Errorf("incorrect authurl: %s", cfg.Global.AuthUrl)
}
if cfg.Global.UserId != "user" {
t.Errorf("incorrect userid: %s", cfg.Global.UserId)
}
if cfg.Global.Password != "mypass" {
t.Errorf("incorrect password: %s", cfg.Global.Password)
}
// config file wins over environment variable
if cfg.Global.TenantName != "demo" {
t.Errorf("incorrect tenant name: %s", cfg.Global.TenantName)
}
if !cfg.LoadBalancer.CreateMonitor {
t.Errorf("incorrect lb.createmonitor: %t", cfg.LoadBalancer.CreateMonitor)
}
@ -377,56 +397,6 @@ func TestNodeAddresses(t *testing.T) {
}
}
// This allows acceptance testing against an existing OpenStack
// install, using the standard OS_* OpenStack client environment
// variables.
// FIXME: it would be better to hermetically test against canned JSON
// requests/responses.
func configFromEnv() (cfg Config, ok bool) {
cfg.Global.AuthUrl = os.Getenv("OS_AUTH_URL")
cfg.Global.TenantId = os.Getenv("OS_TENANT_ID")
// Rax/nova _insists_ that we don't specify both tenant ID and name
if cfg.Global.TenantId == "" {
cfg.Global.TenantName = os.Getenv("OS_TENANT_NAME")
}
cfg.Global.Username = os.Getenv("OS_USERNAME")
cfg.Global.Password = os.Getenv("OS_PASSWORD")
cfg.Global.Region = os.Getenv("OS_REGION_NAME")
cfg.Global.TenantName = os.Getenv("OS_TENANT_NAME")
if cfg.Global.TenantName == "" {
cfg.Global.TenantName = os.Getenv("OS_PROJECT_NAME")
}
cfg.Global.TenantId = os.Getenv("OS_TENANT_ID")
if cfg.Global.TenantId == "" {
cfg.Global.TenantId = os.Getenv("OS_PROJECT_ID")
}
cfg.Global.DomainId = os.Getenv("OS_DOMAIN_ID")
if cfg.Global.DomainId == "" {
cfg.Global.DomainId = os.Getenv("OS_USER_DOMAIN_ID")
}
cfg.Global.DomainName = os.Getenv("OS_DOMAIN_NAME")
if cfg.Global.DomainName == "" {
cfg.Global.DomainName = os.Getenv("OS_USER_DOMAIN_NAME")
}
ok = (cfg.Global.AuthUrl != "" &&
cfg.Global.Username != "" &&
cfg.Global.Password != "" &&
(cfg.Global.TenantId != "" || cfg.Global.TenantName != "" ||
cfg.Global.DomainId != "" || cfg.Global.DomainName != ""))
cfg.Metadata.SearchOrder = fmt.Sprintf("%s,%s", configDriveID, metadataID)
cfg.BlockStorage.BSVersion = "auto"
return
}
func TestNewOpenStack(t *testing.T) {
cfg, ok := configFromEnv()
if !ok {