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