2014-10-29 22:52:36 +01:00
|
|
|
package openstack
|
|
|
|
|
|
|
|
import (
|
2015-04-15 14:58:01 +02:00
|
|
|
"crypto/tls"
|
2016-02-12 07:56:11 +01:00
|
|
|
"crypto/x509"
|
2015-06-07 22:57:55 +02:00
|
|
|
"fmt"
|
2015-04-15 14:58:01 +02:00
|
|
|
"net/http"
|
2017-02-20 13:36:05 +01:00
|
|
|
"os"
|
2015-04-15 14:58:01 +02:00
|
|
|
|
2016-09-03 17:27:45 +02:00
|
|
|
"github.com/gophercloud/gophercloud"
|
|
|
|
"github.com/gophercloud/gophercloud/openstack"
|
2016-11-08 06:30:55 +01:00
|
|
|
"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/swauth"
|
2016-11-21 17:31:25 +01:00
|
|
|
"github.com/hashicorp/terraform/helper/pathorcontents"
|
2017-06-02 06:12:25 +02:00
|
|
|
"github.com/hashicorp/terraform/terraform"
|
2014-10-29 22:52:36 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
type Config struct {
|
2016-02-12 07:56:11 +01:00
|
|
|
CACertFile string
|
2016-04-21 11:39:49 +02:00
|
|
|
ClientCertFile string
|
|
|
|
ClientKeyFile string
|
2016-11-01 14:16:39 +01:00
|
|
|
DomainID string
|
|
|
|
DomainName string
|
|
|
|
EndpointType string
|
|
|
|
IdentityEndpoint string
|
|
|
|
Insecure bool
|
|
|
|
Password string
|
2016-11-08 06:30:55 +01:00
|
|
|
Swauth bool
|
2016-11-01 14:16:39 +01:00
|
|
|
TenantID string
|
|
|
|
TenantName string
|
|
|
|
Token string
|
|
|
|
Username string
|
|
|
|
UserID string
|
2014-10-29 22:52:36 +01:00
|
|
|
|
2015-01-26 05:00:57 +01:00
|
|
|
osClient *gophercloud.ProviderClient
|
2014-10-29 22:52:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Config) loadAndValidate() error {
|
2016-11-01 14:16:39 +01:00
|
|
|
validEndpoint := false
|
|
|
|
validEndpoints := []string{
|
|
|
|
"internal", "internalURL",
|
|
|
|
"admin", "adminURL",
|
|
|
|
"public", "publicURL",
|
|
|
|
"",
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, endpoint := range validEndpoints {
|
|
|
|
if c.EndpointType == endpoint {
|
|
|
|
validEndpoint = true
|
|
|
|
}
|
|
|
|
}
|
2015-06-07 22:57:55 +02:00
|
|
|
|
2016-11-01 14:16:39 +01:00
|
|
|
if !validEndpoint {
|
2015-06-07 22:57:55 +02:00
|
|
|
return fmt.Errorf("Invalid endpoint type provided")
|
|
|
|
}
|
|
|
|
|
2014-10-29 22:52:36 +01:00
|
|
|
ao := gophercloud.AuthOptions{
|
2016-11-01 14:16:39 +01:00
|
|
|
DomainID: c.DomainID,
|
|
|
|
DomainName: c.DomainName,
|
2014-10-29 22:52:36 +01:00
|
|
|
IdentityEndpoint: c.IdentityEndpoint,
|
2016-11-01 14:16:39 +01:00
|
|
|
Password: c.Password,
|
2015-01-26 05:00:57 +01:00
|
|
|
TenantID: c.TenantID,
|
2015-01-10 23:02:19 +01:00
|
|
|
TenantName: c.TenantName,
|
2016-11-01 14:16:39 +01:00
|
|
|
TokenID: c.Token,
|
|
|
|
Username: c.Username,
|
|
|
|
UserID: c.UserID,
|
2014-10-29 22:52:36 +01:00
|
|
|
}
|
|
|
|
|
2015-04-15 14:58:01 +02:00
|
|
|
client, err := openstack.NewClient(ao.IdentityEndpoint)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-06-02 06:12:25 +02:00
|
|
|
// Set UserAgent
|
|
|
|
client.UserAgent.Prepend(terraform.UserAgentString())
|
|
|
|
|
2016-04-21 11:39:49 +02:00
|
|
|
config := &tls.Config{}
|
2016-02-12 07:56:11 +01:00
|
|
|
if c.CACertFile != "" {
|
2016-11-21 17:31:25 +01:00
|
|
|
caCert, _, err := pathorcontents.Read(c.CACertFile)
|
2016-02-12 07:56:11 +01:00
|
|
|
if err != nil {
|
2016-11-21 17:31:25 +01:00
|
|
|
return fmt.Errorf("Error reading CA Cert: %s", err)
|
2016-02-12 07:56:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
caCertPool := x509.NewCertPool()
|
2016-11-21 17:31:25 +01:00
|
|
|
caCertPool.AppendCertsFromPEM([]byte(caCert))
|
2016-04-21 11:39:49 +02:00
|
|
|
config.RootCAs = caCertPool
|
|
|
|
}
|
2016-11-01 14:16:39 +01:00
|
|
|
|
2016-04-21 11:39:49 +02:00
|
|
|
if c.Insecure {
|
|
|
|
config.InsecureSkipVerify = true
|
|
|
|
}
|
2016-02-12 07:56:11 +01:00
|
|
|
|
2016-04-21 11:39:49 +02:00
|
|
|
if c.ClientCertFile != "" && c.ClientKeyFile != "" {
|
2016-11-21 17:31:25 +01:00
|
|
|
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))
|
2016-04-21 11:39:49 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2016-02-12 07:56:11 +01:00
|
|
|
}
|
|
|
|
|
2016-04-21 11:39:49 +02:00
|
|
|
config.Certificates = []tls.Certificate{cert}
|
|
|
|
config.BuildNameToCertificate()
|
2015-04-15 14:58:01 +02:00
|
|
|
}
|
2016-11-01 14:16:39 +01:00
|
|
|
|
2017-02-20 13:36:05 +01:00
|
|
|
// if OS_DEBUG is set, log the requests and responses
|
|
|
|
var osDebug bool
|
|
|
|
if os.Getenv("OS_DEBUG") != "" {
|
|
|
|
osDebug = true
|
|
|
|
}
|
|
|
|
|
2016-09-20 20:53:56 +02:00
|
|
|
transport := &http.Transport{Proxy: http.ProxyFromEnvironment, TLSClientConfig: config}
|
2017-02-20 13:36:05 +01:00
|
|
|
client.HTTPClient = http.Client{
|
|
|
|
Transport: &LogRoundTripper{
|
2017-04-15 16:11:28 +02:00
|
|
|
Rt: transport,
|
|
|
|
OsDebug: osDebug,
|
2017-02-20 13:36:05 +01:00
|
|
|
},
|
|
|
|
}
|
2015-04-15 14:58:01 +02:00
|
|
|
|
2016-11-08 06:30:55 +01:00
|
|
|
// 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
|
|
|
|
}
|
2014-10-29 22:52:36 +01:00
|
|
|
}
|
|
|
|
|
2015-01-26 05:00:57 +01:00
|
|
|
c.osClient = client
|
2014-10-29 22:52:36 +01:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2015-01-31 22:33:54 +01:00
|
|
|
|
2015-02-01 08:34:37 +01:00
|
|
|
func (c *Config) blockStorageV1Client(region string) (*gophercloud.ServiceClient, error) {
|
|
|
|
return openstack.NewBlockStorageV1(c.osClient, gophercloud.EndpointOpts{
|
2015-06-07 22:57:55 +02:00
|
|
|
Region: region,
|
|
|
|
Availability: c.getEndpointType(),
|
2016-05-16 22:37:58 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Config) blockStorageV2Client(region string) (*gophercloud.ServiceClient, error) {
|
|
|
|
return openstack.NewBlockStorageV2(c.osClient, gophercloud.EndpointOpts{
|
|
|
|
Region: region,
|
|
|
|
Availability: c.getEndpointType(),
|
2015-02-01 08:34:37 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-01-31 22:33:54 +01:00
|
|
|
func (c *Config) computeV2Client(region string) (*gophercloud.ServiceClient, error) {
|
|
|
|
return openstack.NewComputeV2(c.osClient, gophercloud.EndpointOpts{
|
2015-06-07 22:57:55 +02:00
|
|
|
Region: region,
|
|
|
|
Availability: c.getEndpointType(),
|
2017-02-16 17:36:54 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-05-18 23:25:28 +02:00
|
|
|
func (c *Config) dnsV2Client(region string) (*gophercloud.ServiceClient, error) {
|
|
|
|
return openstack.NewDNSV2(c.osClient, gophercloud.EndpointOpts{
|
|
|
|
Region: region,
|
|
|
|
Availability: c.getEndpointType(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-02-16 17:36:54 +01:00
|
|
|
func (c *Config) imageV2Client(region string) (*gophercloud.ServiceClient, error) {
|
|
|
|
return openstack.NewImageServiceV2(c.osClient, gophercloud.EndpointOpts{
|
|
|
|
Region: region,
|
|
|
|
Availability: c.getEndpointType(),
|
2015-01-31 22:33:54 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Config) networkingV2Client(region string) (*gophercloud.ServiceClient, error) {
|
|
|
|
return openstack.NewNetworkV2(c.osClient, gophercloud.EndpointOpts{
|
2015-06-07 22:57:55 +02:00
|
|
|
Region: region,
|
|
|
|
Availability: c.getEndpointType(),
|
2015-01-31 22:33:54 +01:00
|
|
|
})
|
|
|
|
}
|
2015-02-01 04:51:50 +01:00
|
|
|
|
|
|
|
func (c *Config) objectStorageV1Client(region string) (*gophercloud.ServiceClient, error) {
|
2016-11-08 06:30:55 +01:00
|
|
|
// 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,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-02-01 04:51:50 +01:00
|
|
|
return openstack.NewObjectStorageV1(c.osClient, gophercloud.EndpointOpts{
|
2015-06-07 22:57:55 +02:00
|
|
|
Region: region,
|
|
|
|
Availability: c.getEndpointType(),
|
2015-02-01 04:51:50 +01:00
|
|
|
})
|
|
|
|
}
|
2015-06-07 22:57:55 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|