providers/aws: start filling out

This commit is contained in:
Mitchell Hashimoto 2014-06-23 19:01:57 -07:00
parent 9b4b89c16c
commit c556e2ad48
7 changed files with 186 additions and 13 deletions

View File

@ -0,0 +1,46 @@
package aws
import (
"strings"
"unicode"
"github.com/mitchellh/goamz/aws"
)
type Config struct {
AccessKey string `mapstructure:"access_key"`
SecretKey string `mapstructure:"secret_key"`
Region string `mapstructure:"region"`
}
// AWSAuth returns a valid aws.Auth object for access to AWS services, or
// an error if the authentication couldn't be resolved.
//
// TODO(mitchellh): Test in some way.
func (c *Config) AWSAuth() (aws.Auth, error) {
auth, err := aws.GetAuth(c.AccessKey, c.SecretKey)
if err == nil {
// Store the accesskey and secret that we got...
c.AccessKey = auth.AccessKey
c.SecretKey = auth.SecretKey
}
return auth, err
}
// AWSRegion returns the configured region.
//
// TODO(mitchellh): Test in some way.
func (c *Config) AWSRegion() (aws.Region, error) {
if c.Region != "" {
return aws.Regions[c.Region], nil
}
md, err := aws.GetMetaData("placement/availability-zone")
if err != nil {
return aws.Region{}, err
}
region := strings.TrimRightFunc(string(md), unicode.IsLetter)
return aws.Regions[region], nil
}

View File

@ -27,7 +27,6 @@ func diffBuilder_aws_instance() *diff.ResourceBuilder {
"ami",
"availability_zone",
"instance_type",
"region",
},
}
}

View File

@ -0,0 +1,31 @@
package aws
import (
"github.com/hashicorp/terraform/terraform"
)
// RefreshFunc is a function that performs a refresh of a specific type
// of resource.
type RefreshFunc func(
*ResourceProvider,
*terraform.ResourceState) (*terraform.ResourceState, error)
// refreshMap keeps track of all the resources that this provider
// can refresh.
var refreshMap map[string]RefreshFunc
func init() {
refreshMap = map[string]RefreshFunc{
"aws_instance": refresh_aws_instance,
}
}
func refresh_aws_instance(
p *ResourceProvider,
s *terraform.ResourceState) (*terraform.ResourceState, error) {
if s.ID != "" {
panic("OH MY WOW")
}
return s, nil
}

View File

@ -2,23 +2,52 @@ package aws
import (
"fmt"
"log"
"github.com/hashicorp/terraform/helper/config"
"github.com/hashicorp/terraform/terraform"
"github.com/mitchellh/goamz/ec2"
)
type ResourceProvider struct {
Config Config
ec2conn *ec2.EC2
}
func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) {
errs := c.CheckSet([]string{
"access_key",
"secret_key",
})
return nil, errs
return nil, nil
}
func (p *ResourceProvider) Configure(*terraform.ResourceConfig) error {
func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error {
if _, err := config.Decode(&p.Config, c.Config); err != nil {
return err
}
// Get the auth and region. This can fail if keys/regions were not
// specified and we're attempting to use the environment.
var errs []error
log.Println("Building AWS auth structure")
auth, err := p.Config.AWSAuth()
if err != nil {
errs = append(errs, err)
}
log.Println("Building AWS region structure")
region, err := p.Config.AWSRegion()
if err != nil {
errs = append(errs, err)
}
if len(errs) == 0 {
log.Println("Initializing EC2 connection")
p.ec2conn = ec2.New(auth, region)
}
if len(errs) > 0 {
return &terraform.MultiError{Errors: errs}
}
return nil
}
@ -50,7 +79,18 @@ func (p *ResourceProvider) Diff(
func (p *ResourceProvider) Refresh(
s *terraform.ResourceState) (*terraform.ResourceState, error) {
return s, nil
// If there isn't an ID previously, then the thing didn't exist,
// so there is nothing to refresh.
if s.ID == "" {
return s, nil
}
f, ok := refreshMap[s.Type]
if !ok {
return s, fmt.Errorf("Unknown resource type: %s", s.Type)
}
return f(p, s)
}
func (p *ResourceProvider) Resources() []terraform.ResourceType {

View File

@ -1,11 +1,43 @@
package aws
import (
"reflect"
"testing"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/terraform"
)
func TestResourceProvider_impl(t *testing.T) {
var _ terraform.ResourceProvider = new(ResourceProvider)
}
func TestResourceProvider_Configure(t *testing.T) {
rp := new(ResourceProvider)
raw := map[string]interface{}{
"access_key": "foo",
"secret_key": "bar",
"region": "us-east",
}
rawConfig, err := config.NewRawConfig(raw)
if err != nil {
t.Fatalf("err: %s", err)
}
err = rp.Configure(terraform.NewResourceConfig(rawConfig))
if err != nil {
t.Fatalf("err: %s", err)
}
expected := Config{
AccessKey: "foo",
SecretKey: "bar",
Region: "us-east",
}
if !reflect.DeepEqual(rp.Config, expected) {
t.Fatalf("bad: %#v", rp.Config)
}
}

28
helper/config/decode.go Normal file
View File

@ -0,0 +1,28 @@
package config
import (
"github.com/mitchellh/mapstructure"
)
func Decode(target interface{}, raws ...interface{}) (*mapstructure.Metadata, error) {
var md mapstructure.Metadata
decoderConfig := &mapstructure.DecoderConfig{
Metadata: &md,
Result: target,
WeaklyTypedInput: true,
}
decoder, err := mapstructure.NewDecoder(decoderConfig)
if err != nil {
return nil, err
}
for _, raw := range raws {
err := decoder.Decode(raw)
if err != nil {
return nil, err
}
}
return &md, nil
}

View File

@ -340,10 +340,7 @@ func (t *terraformProvider) init(vars map[string]string) (err error) {
panic(err)
}
rc = &ResourceConfig{
ComputedKeys: t.Config.RawConfig.UnknownKeys(),
Raw: t.Config.RawConfig.Config(),
}
rc = NewResourceConfig(t.Config.RawConfig)
}
err = t.Provider.Configure(rc)