2013-07-16 00:08:19 -04:00
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
2013-07-29 19:42:35 -04:00
|
|
|
"fmt"
|
2015-04-05 17:58:48 -04:00
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
2013-07-29 19:42:35 -04:00
|
|
|
"strings"
|
|
|
|
"unicode"
|
2015-05-27 14:35:56 -04:00
|
|
|
|
2015-04-05 17:58:48 -04:00
|
|
|
"github.com/awslabs/aws-sdk-go/aws"
|
2015-05-27 14:35:56 -04:00
|
|
|
"github.com/mitchellh/packer/template/interpolate"
|
2013-07-16 00:08:19 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// AccessConfig is for common configuration related to AWS access
|
|
|
|
type AccessConfig struct {
|
|
|
|
AccessKey string `mapstructure:"access_key"`
|
|
|
|
SecretKey string `mapstructure:"secret_key"`
|
2013-07-29 19:42:35 -04:00
|
|
|
RawRegion string `mapstructure:"region"`
|
2014-09-05 00:19:20 -04:00
|
|
|
Token string `mapstructure:"token"`
|
2013-07-16 00:08:19 -04:00
|
|
|
}
|
|
|
|
|
2015-04-05 17:58:48 -04:00
|
|
|
// Config returns a valid aws.Config object for access to AWS services, or
|
|
|
|
// an error if the authentication and region couldn't be resolved
|
|
|
|
func (c *AccessConfig) Config() (*aws.Config, error) {
|
|
|
|
credsProvider := aws.DetectCreds(c.AccessKey, c.SecretKey, c.Token)
|
|
|
|
|
|
|
|
creds, err := credsProvider.Credentials()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2014-09-05 00:19:20 -04:00
|
|
|
}
|
2015-04-05 17:58:48 -04:00
|
|
|
|
|
|
|
c.AccessKey = creds.AccessKeyID
|
|
|
|
c.SecretKey = creds.SecretAccessKey
|
|
|
|
c.Token = creds.SessionToken
|
|
|
|
|
|
|
|
region, err := c.Region()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2013-09-18 16:59:23 -04:00
|
|
|
}
|
|
|
|
|
2015-04-05 17:58:48 -04:00
|
|
|
return &aws.Config{
|
|
|
|
Region: region,
|
|
|
|
Credentials: credsProvider,
|
|
|
|
}, nil
|
2013-07-16 00:08:19 -04:00
|
|
|
}
|
|
|
|
|
2013-07-29 19:42:35 -04:00
|
|
|
// Region returns the aws.Region object for access to AWS services, requesting
|
|
|
|
// the region from the instance metadata if possible.
|
2015-04-05 17:58:48 -04:00
|
|
|
func (c *AccessConfig) Region() (string, error) {
|
2013-07-29 19:42:35 -04:00
|
|
|
if c.RawRegion != "" {
|
2015-04-05 17:58:48 -04:00
|
|
|
if valid := ValidateRegion(c.RawRegion); valid == false {
|
|
|
|
return "", fmt.Errorf("Not a valid region: %s", c.RawRegion)
|
|
|
|
}
|
|
|
|
return c.RawRegion, nil
|
2013-07-29 19:42:35 -04:00
|
|
|
}
|
|
|
|
|
2015-04-05 17:58:48 -04:00
|
|
|
md, err := GetInstanceMetaData("placement/availability-zone")
|
2013-07-29 19:42:35 -04:00
|
|
|
if err != nil {
|
2015-04-05 17:58:48 -04:00
|
|
|
return "", err
|
2013-07-29 19:42:35 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
region := strings.TrimRightFunc(string(md), unicode.IsLetter)
|
2015-04-05 17:58:48 -04:00
|
|
|
return region, nil
|
2013-07-29 19:42:35 -04:00
|
|
|
}
|
|
|
|
|
2015-05-27 14:35:56 -04:00
|
|
|
func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
|
|
|
var errs []error
|
2013-07-29 19:42:35 -04:00
|
|
|
if c.RawRegion != "" {
|
2015-04-05 17:58:48 -04:00
|
|
|
if valid := ValidateRegion(c.RawRegion); valid == false {
|
2013-08-08 17:29:46 -04:00
|
|
|
errs = append(errs, fmt.Errorf("Unknown region: %s", c.RawRegion))
|
2013-07-29 19:42:35 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-08 17:29:46 -04:00
|
|
|
if len(errs) > 0 {
|
|
|
|
return errs
|
|
|
|
}
|
|
|
|
|
2013-07-16 00:08:19 -04:00
|
|
|
return nil
|
|
|
|
}
|
2015-04-05 17:58:48 -04:00
|
|
|
|
|
|
|
func GetInstanceMetaData(path string) (contents []byte, err error) {
|
|
|
|
url := "http://169.254.169.254/latest/meta-data/" + path
|
|
|
|
|
|
|
|
resp, err := http.Get(url)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
if resp.StatusCode != 200 {
|
|
|
|
err = fmt.Errorf("Code %d returned for url %s", resp.StatusCode, url)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return []byte(body), err
|
|
|
|
}
|