github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/builder/openstack/access_config.go (about)

     1  package openstack
     2  
     3  import (
     4  	"crypto/tls"
     5  	"fmt"
     6  	"github.com/mitchellh/packer/common"
     7  	"github.com/mitchellh/packer/packer"
     8  	"github.com/rackspace/gophercloud"
     9  	"net/http"
    10  	"net/url"
    11  	"os"
    12  	"strings"
    13  )
    14  
    15  // AccessConfig is for common configuration related to openstack access
    16  type AccessConfig struct {
    17  	Username  string `mapstructure:"username"`
    18  	Password  string `mapstructure:"password"`
    19  	ApiKey    string `mapstructure:"api_key"`
    20  	Project   string `mapstructure:"project"`
    21  	Provider  string `mapstructure:"provider"`
    22  	RawRegion string `mapstructure:"region"`
    23  	ProxyUrl  string `mapstructure:"proxy_url"`
    24  	TenantId  string `mapstructure:"tenant_id"`
    25  	Insecure  bool   `mapstructure:"insecure"`
    26  }
    27  
    28  // Auth returns a valid Auth object for access to openstack services, or
    29  // an error if the authentication couldn't be resolved.
    30  func (c *AccessConfig) Auth() (gophercloud.AccessProvider, error) {
    31  	c.Username = common.ChooseString(c.Username, os.Getenv("SDK_USERNAME"), os.Getenv("OS_USERNAME"))
    32  	c.Password = common.ChooseString(c.Password, os.Getenv("SDK_PASSWORD"), os.Getenv("OS_PASSWORD"))
    33  	c.ApiKey = common.ChooseString(c.ApiKey, os.Getenv("SDK_API_KEY"))
    34  	c.Project = common.ChooseString(c.Project, os.Getenv("SDK_PROJECT"), os.Getenv("OS_TENANT_NAME"))
    35  	c.Provider = common.ChooseString(c.Provider, os.Getenv("SDK_PROVIDER"), os.Getenv("OS_AUTH_URL"))
    36  	c.RawRegion = common.ChooseString(c.RawRegion, os.Getenv("SDK_REGION"), os.Getenv("OS_REGION_NAME"))
    37  	c.TenantId = common.ChooseString(c.TenantId, os.Getenv("OS_TENANT_ID"))
    38  
    39  	// OpenStack's auto-generated openrc.sh files do not append the suffix
    40  	// /tokens to the authentication URL. This ensures it is present when
    41  	// specifying the URL.
    42  	if strings.Contains(c.Provider, "://") && !strings.HasSuffix(c.Provider, "/tokens") {
    43  		c.Provider += "/tokens"
    44  	}
    45  
    46  	authoptions := gophercloud.AuthOptions{
    47  		AllowReauth: true,
    48  
    49  		ApiKey:     c.ApiKey,
    50  		TenantId:   c.TenantId,
    51  		TenantName: c.Project,
    52  		Username:   c.Username,
    53  		Password:   c.Password,
    54  	}
    55  
    56  	default_transport := &http.Transport{}
    57  
    58  	if c.Insecure {
    59  		cfg := new(tls.Config)
    60  		cfg.InsecureSkipVerify = true
    61  		default_transport.TLSClientConfig = cfg
    62  	}
    63  
    64  	// For corporate networks it may be the case where we want our API calls
    65  	// to be sent through a separate HTTP proxy than external traffic.
    66  	if c.ProxyUrl != "" {
    67  		url, err := url.Parse(c.ProxyUrl)
    68  		if err != nil {
    69  			return nil, err
    70  		}
    71  
    72  		// The gophercloud.Context has a UseCustomClient method which
    73  		// would allow us to override with a new instance of http.Client.
    74  		default_transport.Proxy = http.ProxyURL(url)
    75  	}
    76  
    77  	if c.Insecure || c.ProxyUrl != "" {
    78  		http.DefaultTransport = default_transport
    79  	}
    80  
    81  	return gophercloud.Authenticate(c.Provider, authoptions)
    82  }
    83  
    84  func (c *AccessConfig) Region() string {
    85  	return common.ChooseString(c.RawRegion, os.Getenv("SDK_REGION"), os.Getenv("OS_REGION_NAME"))
    86  }
    87  
    88  func (c *AccessConfig) Prepare(t *packer.ConfigTemplate) []error {
    89  	if t == nil {
    90  		var err error
    91  		t, err = packer.NewConfigTemplate()
    92  		if err != nil {
    93  			return []error{err}
    94  		}
    95  	}
    96  
    97  	templates := map[string]*string{
    98  		"username":  &c.Username,
    99  		"password":  &c.Password,
   100  		"api_key":   &c.ApiKey,
   101  		"provider":  &c.Provider,
   102  		"project":   &c.Project,
   103  		"tenant_id": &c.TenantId,
   104  		"region":    &c.RawRegion,
   105  		"proxy_url": &c.ProxyUrl,
   106  	}
   107  
   108  	errs := make([]error, 0)
   109  	for n, ptr := range templates {
   110  		var err error
   111  		*ptr, err = t.Process(*ptr, nil)
   112  		if err != nil {
   113  			errs = append(
   114  				errs, fmt.Errorf("Error processing %s: %s", n, err))
   115  		}
   116  	}
   117  
   118  	if strings.HasPrefix(c.Provider, "rackspace") {
   119  		if c.Region() == "" {
   120  			errs = append(errs, fmt.Errorf("region must be specified when using rackspace"))
   121  		}
   122  	}
   123  
   124  	if len(errs) > 0 {
   125  		return errs
   126  	}
   127  
   128  	return nil
   129  }