package openstack import ( "crypto/tls" "crypto/x509" "fmt" "net/http" "os" "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack" "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/swauth" "github.com/hashicorp/terraform/helper/pathorcontents" "github.com/hashicorp/terraform/terraform" ) type Config struct { CACertFile string ClientCertFile string ClientKeyFile string DomainID string DomainName string EndpointType string IdentityEndpoint string Insecure bool Password string Swauth bool TenantID string TenantName string Token string Username string UserID string osClient *gophercloud.ProviderClient } func (c *Config) loadAndValidate() error { validEndpoint := false validEndpoints := []string{ "internal", "internalURL", "admin", "adminURL", "public", "publicURL", "", } for _, endpoint := range validEndpoints { if c.EndpointType == endpoint { validEndpoint = true } } if !validEndpoint { return fmt.Errorf("Invalid endpoint type provided") } ao := gophercloud.AuthOptions{ DomainID: c.DomainID, 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) if err != nil { return err } // Set UserAgent client.UserAgent.Prepend(terraform.UserAgentString()) config := &tls.Config{} if c.CACertFile != "" { caCert, _, err := pathorcontents.Read(c.CACertFile) if err != nil { return fmt.Errorf("Error reading CA Cert: %s", err) } caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM([]byte(caCert)) config.RootCAs = caCertPool } if c.Insecure { config.InsecureSkipVerify = true } if c.ClientCertFile != "" && c.ClientKeyFile != "" { clientCert, _, err := pathorcontents.Read(c.ClientCertFile) if err != nil { return fmt.Errorf("Error reading Client Cert: %s", err) } clientKey, _, err := pathorcontents.Read(c.ClientKeyFile) if err != nil { return fmt.Errorf("Error reading Client Key: %s", err) } cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey)) if err != nil { return err } config.Certificates = []tls.Certificate{cert} config.BuildNameToCertificate() } // if OS_DEBUG is set, log the requests and responses var osDebug bool if os.Getenv("OS_DEBUG") != "" { osDebug = true } transport := &http.Transport{Proxy: http.ProxyFromEnvironment, TLSClientConfig: config} client.HTTPClient = http.Client{ Transport: &LogRoundTripper{ Rt: transport, OsDebug: osDebug, }, } // If using Swift Authentication, there's no need to validate authentication normally. if !c.Swauth { err = openstack.Authenticate(client, ao) if err != nil { return err } } c.osClient = client return nil } func (c *Config) blockStorageV1Client(region string) (*gophercloud.ServiceClient, error) { return openstack.NewBlockStorageV1(c.osClient, gophercloud.EndpointOpts{ Region: region, Availability: c.getEndpointType(), }) } func (c *Config) blockStorageV2Client(region string) (*gophercloud.ServiceClient, error) { return openstack.NewBlockStorageV2(c.osClient, gophercloud.EndpointOpts{ Region: region, Availability: c.getEndpointType(), }) } func (c *Config) computeV2Client(region string) (*gophercloud.ServiceClient, error) { return openstack.NewComputeV2(c.osClient, gophercloud.EndpointOpts{ Region: region, Availability: c.getEndpointType(), }) } func (c *Config) dnsV2Client(region string) (*gophercloud.ServiceClient, error) { return openstack.NewDNSV2(c.osClient, gophercloud.EndpointOpts{ Region: region, Availability: c.getEndpointType(), }) } func (c *Config) imageV2Client(region string) (*gophercloud.ServiceClient, error) { return openstack.NewImageServiceV2(c.osClient, gophercloud.EndpointOpts{ Region: region, Availability: c.getEndpointType(), }) } func (c *Config) networkingV2Client(region string) (*gophercloud.ServiceClient, error) { return openstack.NewNetworkV2(c.osClient, gophercloud.EndpointOpts{ Region: region, Availability: c.getEndpointType(), }) } func (c *Config) objectStorageV1Client(region string) (*gophercloud.ServiceClient, error) { // If Swift Authentication is being used, return a swauth client. if c.Swauth { return swauth.NewObjectStorageV1(c.osClient, swauth.AuthOpts{ User: c.Username, Key: c.Password, }) } return openstack.NewObjectStorageV1(c.osClient, gophercloud.EndpointOpts{ Region: region, Availability: c.getEndpointType(), }) } func (c *Config) getEndpointType() gophercloud.Availability { if c.EndpointType == "internal" || c.EndpointType == "internalURL" { return gophercloud.AvailabilityInternal } if c.EndpointType == "admin" || c.EndpointType == "adminURL" { return gophercloud.AvailabilityAdmin } return gophercloud.AvailabilityPublic }