2013-08-27 00:57:23 -04:00
|
|
|
package openstack
|
|
|
|
|
|
|
|
import (
|
2014-05-05 12:44:25 -04:00
|
|
|
"crypto/tls"
|
2013-08-27 00:57:23 -04:00
|
|
|
"fmt"
|
2013-11-19 12:03:35 -05:00
|
|
|
"net/http"
|
2013-08-27 00:57:23 -04:00
|
|
|
"os"
|
2014-10-27 19:40:49 -04:00
|
|
|
|
2015-05-27 16:02:57 -04:00
|
|
|
"github.com/mitchellh/packer/template/interpolate"
|
2015-06-12 00:16:43 -04:00
|
|
|
"github.com/rackspace/gophercloud"
|
|
|
|
"github.com/rackspace/gophercloud/openstack"
|
2013-08-27 00:57:23 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// AccessConfig is for common configuration related to openstack access
|
|
|
|
type AccessConfig struct {
|
2015-06-12 00:16:43 -04:00
|
|
|
Username string `mapstructure:"username"`
|
|
|
|
UserID string `mapstructure:"user_id"`
|
|
|
|
Password string `mapstructure:"password"`
|
|
|
|
APIKey string `mapstructure:"api_key"`
|
|
|
|
IdentityEndpoint string `mapstructure:"identity_endpoint"`
|
|
|
|
TenantID string `mapstructure:"tenant_id"`
|
|
|
|
TenantName string `mapstructure:"tenant_name"`
|
|
|
|
DomainID string `mapstructure:"domain_id"`
|
|
|
|
DomainName string `mapstructure:"domain_name"`
|
|
|
|
Insecure bool `mapstructure:"insecure"`
|
|
|
|
Region string `mapstructure:"region"`
|
|
|
|
EndpointType string `mapstructure:"endpoint_type"`
|
|
|
|
|
|
|
|
osClient *gophercloud.ProviderClient
|
2013-08-27 00:57:23 -04:00
|
|
|
}
|
|
|
|
|
2015-06-12 00:16:43 -04:00
|
|
|
func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
|
|
|
if c.EndpointType != "internal" && c.EndpointType != "internalURL" &&
|
|
|
|
c.EndpointType != "admin" && c.EndpointType != "adminURL" &&
|
|
|
|
c.EndpointType != "public" && c.EndpointType != "publicURL" &&
|
|
|
|
c.EndpointType != "" {
|
|
|
|
return []error{fmt.Errorf("Invalid endpoint type provided")}
|
2014-01-06 16:41:30 -05:00
|
|
|
}
|
|
|
|
|
2015-06-12 00:16:43 -04:00
|
|
|
if c.Region == "" {
|
|
|
|
c.Region = os.Getenv("OS_REGION_NAME")
|
2013-09-02 13:22:14 -04:00
|
|
|
}
|
|
|
|
|
2015-06-12 00:33:52 -04:00
|
|
|
// Legacy RackSpace stuff. We're keeping this around to keep things BC.
|
|
|
|
if c.APIKey == "" {
|
|
|
|
c.APIKey = os.Getenv("SDK_API_KEY")
|
|
|
|
}
|
|
|
|
if c.Password == "" {
|
|
|
|
c.Password = os.Getenv("SDK_PASSWORD")
|
|
|
|
}
|
|
|
|
if c.Region == "" {
|
|
|
|
c.Region = os.Getenv("SDK_REGION")
|
|
|
|
}
|
|
|
|
if c.TenantName == "" {
|
|
|
|
c.TenantName = os.Getenv("SDK_PROJECT")
|
|
|
|
}
|
|
|
|
if c.Username == "" {
|
|
|
|
c.Username = os.Getenv("SDK_USERNAME")
|
|
|
|
}
|
|
|
|
|
2015-06-12 00:16:43 -04:00
|
|
|
// Get as much as possible from the end
|
2015-06-12 00:28:38 -04:00
|
|
|
ao, _ := openstack.AuthOptionsFromEnv()
|
2014-05-05 12:44:25 -04:00
|
|
|
|
2016-12-06 20:36:10 -05:00
|
|
|
// Make sure we reauth as needed
|
|
|
|
ao.AllowReauth = true
|
|
|
|
|
2015-06-12 00:16:43 -04:00
|
|
|
// Override values if we have them in our config
|
|
|
|
overrides := []struct {
|
|
|
|
From, To *string
|
|
|
|
}{
|
|
|
|
{&c.Username, &ao.Username},
|
|
|
|
{&c.UserID, &ao.UserID},
|
|
|
|
{&c.Password, &ao.Password},
|
|
|
|
{&c.APIKey, &ao.APIKey},
|
|
|
|
{&c.IdentityEndpoint, &ao.IdentityEndpoint},
|
|
|
|
{&c.TenantID, &ao.TenantID},
|
|
|
|
{&c.TenantName, &ao.TenantName},
|
|
|
|
{&c.DomainID, &ao.DomainID},
|
|
|
|
{&c.DomainName, &ao.DomainName},
|
|
|
|
}
|
|
|
|
for _, s := range overrides {
|
|
|
|
if *s.From != "" {
|
|
|
|
*s.To = *s.From
|
2013-11-19 12:03:35 -05:00
|
|
|
}
|
2015-06-12 00:16:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Build the client itself
|
|
|
|
client, err := openstack.NewClient(ao.IdentityEndpoint)
|
|
|
|
if err != nil {
|
|
|
|
return []error{err}
|
|
|
|
}
|
2013-11-19 12:03:35 -05:00
|
|
|
|
2015-06-12 00:16:43 -04:00
|
|
|
// If we have insecure set, then create a custom HTTP client that
|
|
|
|
// ignores SSL errors.
|
|
|
|
if c.Insecure {
|
|
|
|
config := &tls.Config{InsecureSkipVerify: true}
|
|
|
|
transport := &http.Transport{TLSClientConfig: config}
|
|
|
|
client.HTTPClient.Transport = transport
|
2014-05-05 12:44:25 -04:00
|
|
|
}
|
|
|
|
|
2015-06-12 00:16:43 -04:00
|
|
|
// Auth
|
|
|
|
err = openstack.Authenticate(client, ao)
|
|
|
|
if err != nil {
|
|
|
|
return []error{err}
|
2013-11-19 12:03:35 -05:00
|
|
|
}
|
|
|
|
|
2015-06-12 00:16:43 -04:00
|
|
|
c.osClient = client
|
|
|
|
return nil
|
2013-08-27 00:57:23 -04:00
|
|
|
}
|
|
|
|
|
2015-06-12 00:16:43 -04:00
|
|
|
func (c *AccessConfig) computeV2Client() (*gophercloud.ServiceClient, error) {
|
|
|
|
return openstack.NewComputeV2(c.osClient, gophercloud.EndpointOpts{
|
|
|
|
Region: c.Region,
|
|
|
|
Availability: c.getEndpointType(),
|
|
|
|
})
|
2013-09-01 16:22:22 -04:00
|
|
|
}
|
|
|
|
|
2015-06-12 00:16:43 -04:00
|
|
|
func (c *AccessConfig) getEndpointType() gophercloud.Availability {
|
|
|
|
if c.EndpointType == "internal" || c.EndpointType == "internalURL" {
|
|
|
|
return gophercloud.AvailabilityInternal
|
2014-08-15 14:19:04 -04:00
|
|
|
}
|
2015-06-12 00:16:43 -04:00
|
|
|
if c.EndpointType == "admin" || c.EndpointType == "adminURL" {
|
|
|
|
return gophercloud.AvailabilityAdmin
|
2013-08-27 00:57:23 -04:00
|
|
|
}
|
2015-06-12 00:16:43 -04:00
|
|
|
return gophercloud.AvailabilityPublic
|
2013-08-27 00:57:23 -04:00
|
|
|
}
|