Refactored the last two resources

This commit is contained in:
Sander van Harmelen 2014-11-24 14:04:48 +01:00
parent eccd5ad308
commit 0725486e89
8 changed files with 256 additions and 164 deletions

View File

@ -3,13 +3,10 @@ package main
import (
"github.com/hashicorp/terraform/builtin/providers/aws"
"github.com/hashicorp/terraform/plugin"
"github.com/hashicorp/terraform/terraform"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: func() terraform.ResourceProvider {
return new(aws.ResourceProvider)
},
ProviderFunc: aws.Provider,
})
}

View File

@ -4,15 +4,11 @@ import (
"os"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
// Provider returns a schema.Provider for AWS.
//
// NOTE: schema.Provider became available long after the AWS provider
// was started, so resources may not be converted to this new structure
// yet. This is a WIP. To assist with the migration, make sure any resources
// you migrate are acceptance tested, then perform the migration.
func Provider() *schema.Provider {
// Provider returns a terraform.ResourceProvider.
func Provider() terraform.ResourceProvider {
// TODO: Move the validation to this, requires conditional schemas
// TODO: Move the configuration to this, requires validation
@ -42,10 +38,10 @@ func Provider() *schema.Provider {
},
ResourcesMap: map[string]*schema.Resource{
"aws_autoscaling_group": resourceAwsAutoscalingGroup(),
//"aws_db_instance": resourceAwsDbInstance(),
"aws_db_parameter_group": resourceAwsDbParameterGroup(),
//"aws_db_security_group": resourceAwsDbSecurityGroup(),
"aws_autoscaling_group": resourceAwsAutoscalingGroup(),
"aws_db_instance": resourceAwsDbInstance(),
"aws_db_parameter_group": resourceAwsDbParameterGroup(),
"aws_db_security_group": resourceAwsDbSecurityGroup(),
"aws_db_subnet_group": resourceAwsDbSubnetGroup(),
"aws_eip": resourceAwsEip(),
"aws_elb": resourceAwsElb(),

View File

@ -13,14 +13,14 @@ var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider
func init() {
testAccProvider = Provider()
testAccProvider = Provider().(*schema.Provider)
testAccProviders = map[string]terraform.ResourceProvider{
"aws": testAccProvider,
}
}
func TestProvider(t *testing.T) {
if err := Provider().InternalValidate(); err != nil {
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
t.Fatalf("err: %s", err)
}
}

View File

@ -1,18 +1,14 @@
package aws
/*
import (
"fmt"
"log"
"strconv"
"strings"
"time"
"github.com/hashicorp/terraform/flatmap"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
"github.com/mitchellh/goamz/rds"
)
@ -36,7 +32,7 @@ func resourceAwsDbInstance() *schema.Resource {
},
"password": &schema.Schema{
Type: schema.TypeInt,
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
@ -70,59 +66,133 @@ func resourceAwsDbInstance() *schema.Resource {
Required: true,
ForceNew: true,
},
// tot hier
"health_check_type": &schema.Schema{
"availability_zone": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"availability_zones": &schema.Schema{
Type: schema.TypeSet,
Required: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: func(v interface{}) int {
return hashcode.String(v.(string))
},
},
"load_balancers": &schema.Schema{
Type: schema.TypeSet,
"backup_retention_period": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"backup_window": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"iops": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"maintenance_window": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"multi_az": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
},
"port": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"publicly_accessible": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
},
"vpc_security_group_ids": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: func(v interface{}) int {
return hashcode.String(v.(string))
},
},
"vpc_zone_identifier": &schema.Schema{
"security_group_names": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: func(v interface{}) int {
return hashcode.String(v.(string))
},
},
"skip_final_snapshot": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
},
"final_snapshot_identifier": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"db_subnet_group_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"parameter_group_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"address": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"endpoint": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"status": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).rdsconn
opts := rds.CreateDBInstance{}
opts.AllocatedStorage = d.Get("allocated_storage").(int)
opts.SetAllocatedStorage = true
if attr, ok := d.GetOk("instance_class"); ok {
opts.DBInstanceClass = attr.(string)
opts := rds.CreateDBInstance{
AllocatedStorage: d.Get("allocated_storage").(int),
SetAllocatedStorage: true,
DBInstanceClass: d.Get("instance_class").(string),
DBInstanceIdentifier: d.Get("identifier").(string),
DBName: d.Get("name").(string),
MasterUsername: d.Get("username").(string),
MasterUserPassword: d.Get("password").(string),
Engine: d.Get("engine").(string),
EngineVersion: d.Get("engine_version").(string),
}
// Special treatment for the password, as we don't want that
// saved into the state file
d.Set("password", "")
if attr, ok := d.GetOk("backup_retention_period"); ok {
opts.BackupRetentionPeriod = attr.(int)
opts.SetBackupRetentionPeriod = true
@ -138,6 +208,10 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
opts.SetPort = true
}
if attr, ok := d.GetOk("multi_az"); ok {
opts.MultiAZ = attr.(bool)
}
if attr, ok := d.GetOk("availability_zone"); ok {
opts.AvailabilityZone = attr.(string)
}
@ -150,10 +224,6 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
opts.PreferredBackupWindow = attr.(string)
}
if attr, ok := d.GetOk("multi_az"); ok {
opts.MultiAZ = attr.(bool)
}
if attr, ok := d.GetOk("publicly_accessible"); ok {
opts.PubliclyAccessible = attr.(bool)
}
@ -166,21 +236,22 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
opts.DBParameterGroupName = attr.(string)
}
if d.Get("vpc_security_group_ids.#").(int) > 0 {
opts.VpcSecurityGroupIds = d.Get("vpc_security_group_ids").([]string)
if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 {
var s []string
for _, v := range attr.List() {
s = append(s, v.(string))
}
opts.VpcSecurityGroupIds = s
}
if d.Get("security_group_names.#").(int) > 0 {
opts.DBSecurityGroupNames = d.Get("security_group_names").([]string)
if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 {
var s []string
for _, v := range attr.List() {
s = append(s, v.(string))
}
opts.DBSecurityGroupNames = s
}
opts.DBInstanceIdentifier = d.Get("identifier").(string)
opts.DBName = d.Get("name").(string)
opts.MasterUsername = d.Get("username").(string)
opts.MasterUserPassword = d.Get("password").(string)
opts.EngineVersion = d.Get("engine_version").(string)
opts.Engine = d.Get("engine").(string)
log.Printf("[DEBUG] DB Instance create configuration: %#v", opts)
_, err := conn.CreateDBInstance(&opts)
if err != nil {
@ -197,7 +268,7 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
stateConf := &resource.StateChangeConf{
Pending: []string{"creating", "backing-up", "modifying"},
Target: "available",
Refresh: resourceAwsDbInstanceStateRefreshFunc(d.Id(), conn),
Refresh: resourceAwsDbInstanceStateRefreshFunc(d, meta),
Timeout: 20 * time.Minute,
MinTimeout: 10 * time.Second,
Delay: 30 * time.Second, // Wait 30 secs before starting
@ -213,40 +284,57 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
}
func resourceAwsDbInstanceRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).rdsconn
v, err := resourceAwsBbInstanceRetrieve(d, meta)
s.Attributes["address"] = v.Address
s.Attributes["allocated_storage"] = strconv.Itoa(v.AllocatedStorage)
s.Attributes["availability_zone"] = v.AvailabilityZone
s.Attributes["backup_retention_period"] = strconv.Itoa(v.BackupRetentionPeriod)
s.Attributes["backup_window"] = v.PreferredBackupWindow
s.Attributes["endpoint"] = fmt.Sprintf("%s:%s", s.Attributes["address"], strconv.Itoa(v.Port))
s.Attributes["engine"] = v.Engine
s.Attributes["engine_version"] = v.EngineVersion
s.Attributes["instance_class"] = v.DBInstanceClass
s.Attributes["maintenance_window"] = v.PreferredMaintenanceWindow
s.Attributes["multi_az"] = strconv.FormatBool(v.MultiAZ)
s.Attributes["name"] = v.DBName
s.Attributes["port"] = strconv.Itoa(v.Port)
s.Attributes["status"] = v.DBInstanceStatus
s.Attributes["username"] = v.MasterUsername
s.Attributes["db_subnet_group_name"] = v.DBSubnetGroup.Name
s.Attributes["parameter_group_name"] = v.DBParameterGroupName
// Flatten our group values
toFlatten := make(map[string]interface{})
if len(v.DBSecurityGroupNames) > 0 && v.DBSecurityGroupNames[0] != "" {
toFlatten["security_group_names"] = v.DBSecurityGroupNames
if err != nil {
return err
}
if len(v.VpcSecurityGroupIds) > 0 && v.VpcSecurityGroupIds[0] != "" {
toFlatten["vpc_security_group_ids"] = v.VpcSecurityGroupIds
}
for k, v := range flatmap.Flatten(toFlatten) {
s.Attributes[k] = v
if v == nil {
d.SetId("")
return nil
}
return s, nil
d.Set("name", v.DBName)
d.Set("username", v.MasterUsername)
d.Set("engine", v.Engine)
d.Set("engine_version", v.EngineVersion)
d.Set("allocated_storage", v.AllocatedStorage)
d.Set("instance_class", v.DBInstanceClass)
d.Set("availability_zone", v.AvailabilityZone)
d.Set("backup_retention_period", v.BackupRetentionPeriod)
d.Set("backup_window", v.PreferredBackupWindow)
d.Set("maintenance_window", v.PreferredMaintenanceWindow)
d.Set("multi_az", v.MultiAZ)
d.Set("port", v.Port)
d.Set("db_subnet_group_name", v.DBSubnetGroup.Name)
d.Set("parameter_group_name", v.DBParameterGroupName)
d.Set("address", v.Address)
d.Set("endpoint", fmt.Sprintf("%s:%d", v.Address, v.Port))
d.Set("status", v.DBInstanceStatus)
// Create an empty schema.Set to hold all vpc security group ids
ids := &schema.Set{
F: func(v interface{}) int {
return hashcode.String(v.(string))
},
}
for _, v := range v.VpcSecurityGroupIds {
ids.Add(v)
}
d.Set("vpc_security_group_ids", ids)
// Create an empty schema.Set to hold all security group names
sgn := &schema.Set{
F: func(v interface{}) int {
return hashcode.String(v.(string))
},
}
for _, v := range v.DBSecurityGroupNames {
sgn.Add(v)
}
d.Set("security_group_names", sgn)
return nil
}
func resourceAwsDbInstanceDelete(d *schema.ResourceData, meta interface{}) error {
@ -256,10 +344,10 @@ func resourceAwsDbInstanceDelete(d *schema.ResourceData, meta interface{}) error
opts := rds.DeleteDBInstance{DBInstanceIdentifier: d.Id()}
if d.Get("skip_final_snapshot").(string) == "true" {
if d.Get("skip_final_snapshot").(bool) {
opts.SkipFinalSnapshot = true
} else {
opts.FinalDBSnapshotIdentifier = s.Attributes["final_snapshot_identifier"]
opts.FinalDBSnapshotIdentifier = d.Get("final_snapshot_identifier").(string)
}
log.Printf("[DEBUG] DB Instance destroy configuration: %v", opts)
@ -273,7 +361,7 @@ func resourceAwsDbInstanceDelete(d *schema.ResourceData, meta interface{}) error
Pending: []string{"creating", "backing-up",
"modifying", "deleting", "available"},
Target: "",
Refresh: resourceAwsDbInstanceStateRefreshFunc(s.ID, conn),
Refresh: resourceAwsDbInstanceStateRefreshFunc(d, meta),
Timeout: 20 * time.Minute,
MinTimeout: 10 * time.Second,
Delay: 30 * time.Second, // Wait 30 secs before starting
@ -285,28 +373,12 @@ func resourceAwsDbInstanceDelete(d *schema.ResourceData, meta interface{}) error
return nil
}
func resource_aws_db_instance_refresh(
s *terraform.InstanceState,
meta interface{}) (*terraform.InstanceState, error) {
p := meta.(*ResourceProvider)
conn := p.rdsconn
func resourceAwsBbInstanceRetrieve(
d *schema.ResourceData, meta interface{}) (*rds.DBInstance, error) {
conn := meta.(*AWSClient).rdsconn
v, err := resource_aws_db_instance_retrieve(s.ID, conn)
if err != nil {
return s, err
}
if v == nil {
s.ID = ""
return s, nil
}
return resource_aws_db_instance_update_state(s, v)
}
func resource_aws_db_instance_retrieve(id string, conn *rds.Rds) (*rds.DBInstance, error) {
opts := rds.DescribeDBInstances{
DBInstanceIdentifier: id,
DBInstanceIdentifier: d.Id(),
}
log.Printf("[DEBUG] DB Instance describe configuration: %#v", opts)
@ -321,7 +393,7 @@ func resource_aws_db_instance_retrieve(id string, conn *rds.Rds) (*rds.DBInstanc
}
if len(resp.DBInstances) != 1 ||
resp.DBInstances[0].DBInstanceIdentifier != id {
resp.DBInstances[0].DBInstanceIdentifier != d.Id() {
if err != nil {
return nil, nil
}
@ -332,9 +404,10 @@ func resource_aws_db_instance_retrieve(id string, conn *rds.Rds) (*rds.DBInstanc
return &v, nil
}
func resourceAwsDbInstanceStateRefreshFunc(id string, conn *rds.Rds) resource.StateRefreshFunc {
func resourceAwsDbInstanceStateRefreshFunc(
d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
v, err := resource_aws_db_instance_retrieve(id, conn)
v, err := resourceAwsBbInstanceRetrieve(d, meta)
if err != nil {
log.Printf("Error on retrieving DB Instance when waiting: %s", err)
@ -348,4 +421,3 @@ func resourceAwsDbInstanceStateRefreshFunc(id string, conn *rds.Rds) resource.St
return v, v.DBInstanceStatus, nil
}
}
*/

View File

@ -1,6 +1,5 @@
package aws
/*
import (
"fmt"
"testing"
@ -166,4 +165,3 @@ resource "aws_db_instance" "bar" {
parameter_group_name = "default.mysql5.6"
}
`
*/

View File

@ -1,12 +1,12 @@
package aws
/*
import (
"bytes"
"fmt"
"log"
"time"
"github.com/hashicorp/terraform/flatmap"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/multierror"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
@ -33,19 +33,20 @@ func resourceAwsDbSecurityGroup() *schema.Resource {
},
"ingress": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Type: schema.TypeSet,
Required: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cidr": &schema.Schema{
Type: schema.TypeString,
Required: true,
Optional: true,
},
"security_group_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Optional: true,
Computed: true,
},
"security_group_id": &schema.Schema{
@ -61,6 +62,7 @@ func resourceAwsDbSecurityGroup() *schema.Resource {
},
},
},
Set: resourceAwsDbSecurityGroupIngressHash,
},
},
}
@ -92,20 +94,17 @@ func resourceAwsDbSecurityGroupCreate(d *schema.ResourceData, meta interface{})
return err
}
rules := d.Get("ingress.#").(int)
if rules > 0 {
for i := 0; i < ssh_keys; i++ {
key := fmt.Sprintf("ingress.%d", i)
err = resourceAwsDbSecurityGroupAuthorizeRule(d.Get(key), sg.Name, conn)
ingresses := d.Get("ingress").(*schema.Set)
for _, ing := range ingresses.List() {
err = resourceAwsDbSecurityGroupAuthorizeRule(ing, sg.Name, conn)
if err != nil {
errs = append(errs, err)
}
if err != nil {
errs = append(errs, err)
}
}
if len(errs) > 0 {
return &multierror.Error{Errors: errs}
}
if len(errs) > 0 {
return &multierror.Error{Errors: errs}
}
log.Println(
@ -114,7 +113,7 @@ func resourceAwsDbSecurityGroupCreate(d *schema.ResourceData, meta interface{})
stateConf := &resource.StateChangeConf{
Pending: []string{"authorizing"},
Target: "authorized",
Refresh: DBSecurityGroupStateRefreshFunc(d.Id(), conn),
Refresh: resourceAwsDbSecurityGroupStateRefreshFunc(d, meta),
Timeout: 10 * time.Minute,
}
@ -128,8 +127,6 @@ func resourceAwsDbSecurityGroupCreate(d *schema.ResourceData, meta interface{})
}
func resourceAwsDbSecurityGroupRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).rdsconn
sg, err := resourceAwsDbSecurityGroupRetrieve(d, meta)
if err != nil {
return err
@ -138,21 +135,27 @@ func resourceAwsDbSecurityGroupRead(d *schema.ResourceData, meta interface{}) er
d.Set("name", sg.Name)
d.Set("description", sg.Description)
// Flatten our group values
toFlatten := make(map[string]interface{})
if len(v.EC2SecurityGroupOwnerIds) > 0 && v.EC2SecurityGroupOwnerIds[0] != "" {
toFlatten["ingress_security_groups"] = v.EC2SecurityGroupOwnerIds
// Create an empty schema.Set to hold all ingress rules
rules := &schema.Set{
F: resourceAwsDbSecurityGroupIngressHash,
}
if len(v.CidrIps) > 0 && v.CidrIps[0] != "" {
toFlatten["ingress_cidr"] = v.CidrIps
for _, v := range sg.CidrIps {
rule := map[string]interface{}{"cidr": v}
rules.Add(rule)
}
for k, v := range flatmap.Flatten(toFlatten) {
s.Attributes[k] = v
for i, _ := range sg.EC2SecurityGroupOwnerIds {
rule := map[string]interface{}{
"security_group_name": sg.EC2SecurityGroupNames[i],
"security_group_id": sg.EC2SecurityGroupIds[i],
"security_group_owner_id": sg.EC2SecurityGroupOwnerIds[i],
}
rules.Add(rule)
}
d.Set("ingress", rules)
return nil
}
@ -212,15 +215,20 @@ func resourceAwsDbSecurityGroupAuthorizeRule(ingress interface{}, dbSecurityGrou
DBSecurityGroupName: dbSecurityGroupName,
}
opts.Cidr = ing["cidr"].(string)
opts.EC2SecurityGroupName = ing["security_group_name"].(string)
if attr, ok := ing["security_group_id"].(string); ok && attr != "" {
opts.EC2SecurityGroupId = attr
if attr, ok := ing["cidr"]; ok && attr != "" {
opts.Cidr = attr.(string)
}
if attr, ok := ing["security_group_owner_id"].(string); ok && attr != "" {
opts.EC2SecurityGroupOwnerId = attr
if attr, ok := ing["security_group_name"]; ok && attr != "" {
opts.EC2SecurityGroupName = attr.(string)
}
if attr, ok := ing["security_group_id"]; ok && attr != "" {
opts.EC2SecurityGroupId = attr.(string)
}
if attr, ok := ing["security_group_owner_id"]; ok && attr != "" {
opts.EC2SecurityGroupOwnerId = attr.(string)
}
log.Printf("[DEBUG] Authorize ingress rule configuration: %#v", opts)
@ -234,9 +242,33 @@ func resourceAwsDbSecurityGroupAuthorizeRule(ingress interface{}, dbSecurityGrou
return nil
}
func resourceAwsDbSecurityGroupStateRefreshFunc(id string, conn *rds.Rds) resource.StateRefreshFunc {
func resourceAwsDbSecurityGroupIngressHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
if v, ok := m["cidr"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}
if v, ok := m["security_group_name"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}
if v, ok := m["security_group_id"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}
if v, ok := m["security_group_owner_id"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}
return hashcode.String(buf.String())
}
func resourceAwsDbSecurityGroupStateRefreshFunc(
d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
v, err := resource_aws_db_security_group_retrieve(id, conn)
v, err := resourceAwsDbSecurityGroupRetrieve(d, meta)
if err != nil {
log.Printf("Error on retrieving DB Security Group when waiting: %s", err)
@ -255,4 +287,3 @@ func resourceAwsDbSecurityGroupStateRefreshFunc(id string, conn *rds.Rds) resour
return v, "authorized", nil
}
}
*/

View File

@ -1,6 +1,5 @@
package aws
/*
import (
"fmt"
"testing"
@ -141,4 +140,3 @@ resource "aws_db_security_group" "bar" {
}
}
`
*/

View File

@ -101,7 +101,7 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error {
return nil
}
rt := rtRaw.(ec2.RouteTable)
rt := rtRaw.(*ec2.RouteTable)
d.Set("vpc_id", rt.VpcId)
// TODO: Add some code to also update the route set