provider/openstack: Openstack Provider Updates (#9725)

* provider/openstack: Adding Identity v3 compatible environment variables

* provider/openstack: Adding missing environment variables

* provider/openstack: line spacing for provider options

* provider/openstack: Making password sensitive

* provider/openstack: Adding descriptions to provider options

* provider/openstack: Clean up provider documentation

* provider/openstack: clean up EndpointType check
This commit is contained in:
Joe Topjian 2016-11-01 07:16:39 -06:00 committed by Paul Stack
parent 9b2b21b583
commit 266b5ab598
3 changed files with 174 additions and 79 deletions

View File

@ -12,43 +12,53 @@ import (
) )
type Config struct { type Config struct {
Username string
UserID string
Password string
Token string
IdentityEndpoint string
TenantID string
TenantName string
DomainID string
DomainName string
Insecure bool
EndpointType string
CACertFile string CACertFile string
ClientCertFile string ClientCertFile string
ClientKeyFile string ClientKeyFile string
DomainID string
DomainName string
EndpointType string
IdentityEndpoint string
Insecure bool
Password string
TenantID string
TenantName string
Token string
Username string
UserID string
osClient *gophercloud.ProviderClient osClient *gophercloud.ProviderClient
} }
func (c *Config) loadAndValidate() error { func (c *Config) loadAndValidate() error {
validEndpoint := false
validEndpoints := []string{
"internal", "internalURL",
"admin", "adminURL",
"public", "publicURL",
"",
}
if c.EndpointType != "internal" && c.EndpointType != "internalURL" && for _, endpoint := range validEndpoints {
c.EndpointType != "admin" && c.EndpointType != "adminURL" && if c.EndpointType == endpoint {
c.EndpointType != "public" && c.EndpointType != "publicURL" && validEndpoint = true
c.EndpointType != "" { }
}
if !validEndpoint {
return fmt.Errorf("Invalid endpoint type provided") return fmt.Errorf("Invalid endpoint type provided")
} }
ao := gophercloud.AuthOptions{ ao := gophercloud.AuthOptions{
Username: c.Username,
UserID: c.UserID,
Password: c.Password,
TokenID: c.Token,
IdentityEndpoint: c.IdentityEndpoint,
TenantID: c.TenantID,
TenantName: c.TenantName,
DomainID: c.DomainID, DomainID: c.DomainID,
DomainName: c.DomainName, DomainName: c.DomainName,
IdentityEndpoint: c.IdentityEndpoint,
Password: c.Password,
TenantID: c.TenantID,
TenantName: c.TenantName,
TokenID: c.Token,
Username: c.Username,
UserID: c.UserID,
} }
client, err := openstack.NewClient(ao.IdentityEndpoint) client, err := openstack.NewClient(ao.IdentityEndpoint)
@ -58,7 +68,6 @@ func (c *Config) loadAndValidate() error {
config := &tls.Config{} config := &tls.Config{}
if c.CACertFile != "" { if c.CACertFile != "" {
caCert, err := ioutil.ReadFile(c.CACertFile) caCert, err := ioutil.ReadFile(c.CACertFile)
if err != nil { if err != nil {
return err return err
@ -68,6 +77,7 @@ func (c *Config) loadAndValidate() error {
caCertPool.AppendCertsFromPEM(caCert) caCertPool.AppendCertsFromPEM(caCert)
config.RootCAs = caCertPool config.RootCAs = caCertPool
} }
if c.Insecure { if c.Insecure {
config.InsecureSkipVerify = true config.InsecureSkipVerify = true
} }
@ -81,6 +91,7 @@ func (c *Config) loadAndValidate() error {
config.Certificates = []tls.Certificate{cert} config.Certificates = []tls.Certificate{cert}
config.BuildNameToCertificate() config.BuildNameToCertificate()
} }
transport := &http.Transport{Proxy: http.ProxyFromEnvironment, TLSClientConfig: config} transport := &http.Transport{Proxy: http.ProxyFromEnvironment, TLSClientConfig: config}
client.HTTPClient.Transport = transport client.HTTPClient.Transport = transport

View File

@ -17,71 +17,113 @@ func Provider() terraform.ResourceProvider {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
DefaultFunc: schema.EnvDefaultFunc("OS_AUTH_URL", nil), DefaultFunc: schema.EnvDefaultFunc("OS_AUTH_URL", nil),
Description: descriptions["auth_url"],
}, },
"user_name": &schema.Schema{ "user_name": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
DefaultFunc: schema.EnvDefaultFunc("OS_USERNAME", ""), DefaultFunc: schema.EnvDefaultFunc("OS_USERNAME", ""),
Description: descriptions["user_name"],
}, },
"user_id": &schema.Schema{ "user_id": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Default: "", DefaultFunc: schema.EnvDefaultFunc("OS_USER_ID", ""),
Description: descriptions["user_name"],
}, },
"tenant_id": &schema.Schema{ "tenant_id": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Default: "", DefaultFunc: schema.MultiEnvDefaultFunc([]string{
"OS_TENANT_ID",
"OS_PROJECT_ID",
}, ""),
Description: descriptions["tenant_id"],
}, },
"tenant_name": &schema.Schema{ "tenant_name": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
DefaultFunc: schema.EnvDefaultFunc("OS_TENANT_NAME", nil), DefaultFunc: schema.MultiEnvDefaultFunc([]string{
"OS_TENANT_NAME",
"OS_PROJECT_NAME",
}, ""),
Description: descriptions["tenant_name"],
}, },
"password": &schema.Schema{ "password": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Sensitive: true,
DefaultFunc: schema.EnvDefaultFunc("OS_PASSWORD", ""), DefaultFunc: schema.EnvDefaultFunc("OS_PASSWORD", ""),
Description: descriptions["password"],
}, },
"token": &schema.Schema{ "token": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
DefaultFunc: schema.EnvDefaultFunc("OS_AUTH_TOKEN", ""), DefaultFunc: schema.EnvDefaultFunc("OS_AUTH_TOKEN", ""),
Description: descriptions["token"],
}, },
"domain_id": &schema.Schema{ "domain_id": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("OS_DOMAIN_ID", ""),
},
"domain_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("OS_DOMAIN_NAME", ""),
},
"insecure": &schema.Schema{
Type: schema.TypeBool,
Optional: true, Optional: true,
Default: false, DefaultFunc: schema.MultiEnvDefaultFunc([]string{
"OS_USER_DOMAIN_ID",
"OS_PROJECT_DOMAIN_ID",
"OS_DOMAIN_ID",
}, ""),
Description: descriptions["domain_id"],
}, },
"domain_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.MultiEnvDefaultFunc([]string{
"OS_USER_DOMAIN_NAME",
"OS_PROJECT_DOMAIN_NAME",
"OS_DOMAIN_NAME",
"OS_DEFAULT_DOMAIN",
}, ""),
Description: descriptions["domain_name"],
},
"insecure": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("OS_INSECURE", ""),
Description: descriptions["insecure"],
},
"endpoint_type": &schema.Schema{ "endpoint_type": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
DefaultFunc: schema.EnvDefaultFunc("OS_ENDPOINT_TYPE", ""), DefaultFunc: schema.EnvDefaultFunc("OS_ENDPOINT_TYPE", ""),
}, },
"cacert_file": &schema.Schema{ "cacert_file": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
DefaultFunc: schema.EnvDefaultFunc("OS_CACERT", ""), DefaultFunc: schema.EnvDefaultFunc("OS_CACERT", ""),
Description: descriptions["cacert_file"],
}, },
"cert": &schema.Schema{ "cert": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
DefaultFunc: schema.EnvDefaultFunc("OS_CERT", ""), DefaultFunc: schema.EnvDefaultFunc("OS_CERT", ""),
Description: descriptions["cert"],
}, },
"key": &schema.Schema{ "key": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
DefaultFunc: schema.EnvDefaultFunc("OS_KEY", ""), DefaultFunc: schema.EnvDefaultFunc("OS_KEY", ""),
Description: descriptions["key"],
}, },
}, },
@ -121,22 +163,58 @@ func Provider() terraform.ResourceProvider {
} }
} }
var descriptions map[string]string
func init() {
descriptions = map[string]string{
"auth_url": "The Identity authentication URL.",
"user_name": "Username to login with.",
"user_id": "User ID to login with.",
"tenant_id": "The ID of the Tenant (Identity v2) or Project (Identity v3)\n" +
"to login with.",
"tenant_name": "The name of the Tenant (Identity v2) or Project (Identity v3)\n" +
"to login with.",
"password": "Password to login with.",
"token": "Authentication token to use as an alternative to username/password.",
"domain_id": "The ID of the Domain to scope to (Identity v3).",
"domain_name": "The name of the Domain to scope to (Identity v3).",
"insecure": "Trust self-signed certificates.",
"cacert_file": "A Custom CA certificate.",
"endpoint_type": "The catalog endpoint type to use.",
"cert": "A client certificate to authenticate with.",
"key": "A client private key to authenticate with.",
}
}
func configureProvider(d *schema.ResourceData) (interface{}, error) { func configureProvider(d *schema.ResourceData) (interface{}, error) {
config := Config{ config := Config{
CACertFile: d.Get("cacert_file").(string),
ClientCertFile: d.Get("cert").(string),
ClientKeyFile: d.Get("key").(string),
DomainID: d.Get("domain_id").(string),
DomainName: d.Get("domain_name").(string),
EndpointType: d.Get("endpoint_type").(string),
IdentityEndpoint: d.Get("auth_url").(string), IdentityEndpoint: d.Get("auth_url").(string),
Username: d.Get("user_name").(string), Insecure: d.Get("insecure").(bool),
UserID: d.Get("user_id").(string),
Password: d.Get("password").(string), Password: d.Get("password").(string),
Token: d.Get("token").(string), Token: d.Get("token").(string),
TenantID: d.Get("tenant_id").(string), TenantID: d.Get("tenant_id").(string),
TenantName: d.Get("tenant_name").(string), TenantName: d.Get("tenant_name").(string),
DomainID: d.Get("domain_id").(string), Username: d.Get("user_name").(string),
DomainName: d.Get("domain_name").(string), UserID: d.Get("user_id").(string),
Insecure: d.Get("insecure").(bool),
EndpointType: d.Get("endpoint_type").(string),
CACertFile: d.Get("cacert_file").(string),
ClientCertFile: d.Get("cert").(string),
ClientKeyFile: d.Get("key").(string),
} }
if err := config.loadAndValidate(); err != nil { if err := config.loadAndValidate(); err != nil {

View File

@ -35,50 +35,56 @@ resource "openstack_compute_instance_v2" "test-server" {
The following arguments are supported: The following arguments are supported:
* `auth_url` - (Required) If omitted, the `OS_AUTH_URL` environment * `auth_url` - (Required) The Identity authentication URL. If omitted, the
variable is used. `OS_AUTH_URL` environment variable is used.
* `user_name` - (Optional; Required for Identity V2) If omitted, the * `user_name` - (Optional) The Username to login with. If omitted, the
`OS_USERNAME` environment variable is used. `OS_USERNAME` environment variable is used.
* `user_id` - (Optional) * `user_id` - (Optional) The User ID to login with. If omitted, the
`OS_USER_ID` environment variable is used.
* `password` - (Optional; Required if not using `api_key`) If omitted, the * `tenant_id` - (Optional) The ID of the Tenant (Identity v2) or Project
`OS_PASSWORD` environment variable is used. (Identity v3) to login with. If omitted, the `OS_TENANT_ID` or
`OS_PROJECT_ID` environment variables are used.
* `tenant_name` - (Optional) The Name of the Tenant (Identity v2) or Project
(Identity v3) to login with. If omitted, the `OS_TENANT_NAME` or
`OS_PROJECT_NAME` environment variable are used.
* `password` - (Optional) The Password to login with. If omitted, the
`OS_PASSWORD` environment variable is used.
* `token` - (Optional; Required if not using `user_name` and `password`) * `token` - (Optional; Required if not using `user_name` and `password`)
A token is an expiring, temporary means of access issued via the A token is an expiring, temporary means of access issued via the Keystone
Keystone service. By specifying a token, you do not have to service. By specifying a token, you do not have to specify a username/password
specify a username/password combination, since the token was combination, since the token was already created by a username/password out of
already created by a username/password out of band of Terraform. band of Terraform. If omitted, the `OS_AUTH_TOKEN` environment variable is used.
If omitted, the `OS_AUTH_TOKEN` environment variable is used.
* `domain_id` - (Optional) If omitted, the `OS_DOMAIN_ID` environment * `domain_id` - (Optional) The ID of the Domain to scope to (Identity v3). If
variable is used. If omitted, the following environment variables are checked (in this order):
`OS_USER_DOMAIN_ID`, `OS_PROJECT_DOMAIN_ID`, `OS_DOMAIN_ID`.
* `domain_name` - (Optional) If omitted, the `OS_DOMAIN_NAME` * `domain_name` - (Optional) The Name of the Domain to scope to (Identity v3).
environment variable is used. If omitted, the following environment variables are checked (in this order):
`OS_USER_DOMAIN_NAME`, `OS_PROJECT_DOMAIN_NAME`, `OS_DOMAIN_NAME`,
`DEFAULT_DOMAIN`.
* `tenant_id` - (Optional) * `insecure` - (Optional) Trust self-signed SSL certificates. If omitted, the
`OS_INSECURE` environment variable is used.
* `tenant_name` - (Optional) If omitted, the `OS_TENANT_NAME` environment
variable is used.
* `insecure` - (Optional) Explicitly allow the provider to perform
"insecure" SSL requests. If omitted, default value is `false`
* `cacert_file` - (Optional) Specify a custom CA certificate when communicating * `cacert_file` - (Optional) Specify a custom CA certificate when communicating
over SSL. If omitted, the `OS_CACERT` environment variable is used. over SSL. If omitted, the `OS_CACERT` environment variable is used.
* `cert` - (Optional) Specify client certificate file for SSL client * `cert` - (Optional) Specify client certificate file for SSL client
authentication. If omitted the `OS_CERT` environment variable is used. authentication. If omitted the `OS_CERT` environment variable is used.
* `key` - (Optional) Specify client private key file for SSL client * `key` - (Optional) Specify client private key file for SSL client
authentication. If omitted the `OS_KEY` environment variable is used. authentication. If omitted the `OS_KEY` environment variable is used.
* `endpoint_type` - (Optional) Specify which type of endpoint to use from the * `endpoint_type` - (Optional) Specify which type of endpoint to use from the
service catalog. It can be set using the OS_ENDPOINT_TYPE environment service catalog. It can be set using the OS_ENDPOINT_TYPE environment
variable. If not set, public endpoints is used. variable. If not set, public endpoints is used.
## Rackspace Compatibility ## Rackspace Compatibility