github.com/emate/packer@v0.8.1-0.20150625195101-fe0fde195dc6/builder/amazon/common/access_config.go (about)

     1  package common
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"strings"
     8  	"unicode"
     9  
    10  	"github.com/aws/aws-sdk-go/aws"
    11  	"github.com/aws/aws-sdk-go/aws/credentials"
    12  	"github.com/mitchellh/packer/template/interpolate"
    13  )
    14  
    15  // AccessConfig is for common configuration related to AWS access
    16  type AccessConfig struct {
    17  	AccessKey string `mapstructure:"access_key"`
    18  	SecretKey string `mapstructure:"secret_key"`
    19  	RawRegion string `mapstructure:"region"`
    20  	Token     string `mapstructure:"token"`
    21  }
    22  
    23  // Config returns a valid aws.Config object for access to AWS services, or
    24  // an error if the authentication and region couldn't be resolved
    25  func (c *AccessConfig) Config() (*aws.Config, error) {
    26  	creds := credentials.NewChainCredentials([]credentials.Provider{
    27  		&credentials.StaticProvider{Value: credentials.Value{
    28  			AccessKeyID:     c.AccessKey,
    29  			SecretAccessKey: c.SecretKey,
    30  			SessionToken:    c.Token,
    31  		}},
    32  		&credentials.EnvProvider{},
    33  		&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
    34  		&credentials.EC2RoleProvider{},
    35  	})
    36  
    37  	region, err := c.Region()
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	return &aws.Config{
    43  		Region:      region,
    44  		Credentials: creds,
    45  		MaxRetries:  11,
    46  	}, nil
    47  }
    48  
    49  // Region returns the aws.Region object for access to AWS services, requesting
    50  // the region from the instance metadata if possible.
    51  func (c *AccessConfig) Region() (string, error) {
    52  	if c.RawRegion != "" {
    53  		if valid := ValidateRegion(c.RawRegion); valid == false {
    54  			return "", fmt.Errorf("Not a valid region: %s", c.RawRegion)
    55  		}
    56  		return c.RawRegion, nil
    57  	}
    58  
    59  	md, err := GetInstanceMetaData("placement/availability-zone")
    60  	if err != nil {
    61  		return "", err
    62  	}
    63  
    64  	region := strings.TrimRightFunc(string(md), unicode.IsLetter)
    65  	return region, nil
    66  }
    67  
    68  func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
    69  	var errs []error
    70  	if c.RawRegion != "" {
    71  		if valid := ValidateRegion(c.RawRegion); valid == false {
    72  			errs = append(errs, fmt.Errorf("Unknown region: %s", c.RawRegion))
    73  		}
    74  	}
    75  
    76  	if len(errs) > 0 {
    77  		return errs
    78  	}
    79  
    80  	return nil
    81  }
    82  
    83  func GetInstanceMetaData(path string) (contents []byte, err error) {
    84  	url := "http://169.254.169.254/latest/meta-data/" + path
    85  
    86  	resp, err := http.Get(url)
    87  	if err != nil {
    88  		return
    89  	}
    90  	defer resp.Body.Close()
    91  
    92  	if resp.StatusCode != 200 {
    93  		err = fmt.Errorf("Code %d returned for url %s", resp.StatusCode, url)
    94  		return
    95  	}
    96  
    97  	body, err := ioutil.ReadAll(resp.Body)
    98  	if err != nil {
    99  		return
   100  	}
   101  	return []byte(body), err
   102  }