Skip to content

Commit

Permalink
Merge branch 'master' into aws-go-route53
Browse files Browse the repository at this point in the history
* master: (38 commits)
  update CHANGELOG
  helper/schema: update test desc
  helper/schema: default the new value to zero only for the decode
  helper/schema: failing test
  update CHANGELOG
  terraform: sort dependencies of resource state [GH-928]
  helper/schema: diff with set going to 0 elements removes it from state
  helper/schema: fix test index
  helper/schema: add test for sets
  helper/schema: diff of zero value in state with lack of value should not diff
  adding documentation
  update CHANGELOG
  update CHANGELOG
  update CHANGELOG
  Update CHANGELOG
  Update CHANGELOG
  Add missing preposition.
  Fill in missing outputs in modules.html.md.
  Make Google Instance disk attribute all ForceNew. Fix #608.
  Revert "Add Azure provider"
  ...
  • Loading branch information
catsby committed Feb 17, 2015
2 parents 1b8aa74 + cc3c03d commit 6e8169a
Show file tree
Hide file tree
Showing 54 changed files with 848 additions and 889 deletions.
27 changes: 17 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
## 0.3.7 (unreleased)

FEATURES:

* **New provider: `azure`** - initially just supporting Linux virtual
machines [GH-899]

IMPROVEMENTS:

* **New resources: `google_compute_forwarding_rule`, `google_compute_http_health_check`,
and `google_compute_target_pool`** - Together these provide network-level
* **New resources: `google_compute_forwarding_rule`, `google_compute_http_health_check`,
and `google_compute_target_pool`** - Together these provide network-level
load balancing. [GH-588]
* **New resource: `aws_main_route_table_association`** - Manage the main routing table
* **New resource: `aws_main_route_table_association`** - Manage the main routing table
of a VPC. [GH-918]
* core: Formalized the syntax of interpolations and documented it
very heavily.
Expand All @@ -22,8 +17,12 @@ IMPROVEMENTS:
* provider/aws: The `aws_db_instance` resource no longer requires both
`final_snapshot_identifier` and `skip_final_snapshot`; the presence or
absence of the former now implies the latter. [GH-874]
* provider/aws: Avoid unecessary update of `aws_subnet` when
* provider/aws: Avoid unecessary update of `aws_subnet` when
`map_public_ip_on_launch` is not specified in config. [GH-898]
* provider/aws: Add `apply_method` to `aws_db_parameter_group` [GH-897]
* provider/aws: Add `storage_type` to `aws_db_instance` [GH-896]
* provider/aws: ELB can update listeners without requiring new. [GH-721]
* provider/aws: Security group support egress rules. [GH-856]
* provider/google: Remove "client secrets file", as it's no longer necessary
for API authentication [GH-884].
* provider/google: Expose `self_link` on `google_compute_instance` [GH-906]
Expand All @@ -37,15 +36,23 @@ BUG FIXES:
* core: Fix crash that could occur when there are exactly zero providers
installed on a system. [GH-786]
* core: JSON TF configurations can configure provisioners. [GH-807]
* core: Sort `depends_on` in state to prevent unnecessary file changes. [GH-928]
* core: State containing the zero value won't cause a diff with the
lack of a value. [GH-952]
* core: If a set type becomes empty, the state will be properly updated
to remove it. [GH-952]
* command/apply: Won't try to initialize modules in some cases when
no arguments are given. [GH-780]
* command/apply: Fix regression where user variables weren't asked [GH-736]
* helper/hashcode: Update `hash.String()` to always return a positive index.
* helper/hashcode: Update `hash.String()` to always return a positive index.
Fixes issue where specific strings would convert to a negative index
and be ommited when creating Route53 records. [GH-967]
* provider/aws: ELB subnet change doesn't force new resource. [GH-804]
* provider/aws: Automatically suffix the Route53 zone name on record names. [GH-312]
* provider/aws: Instance should ignore root EBS devices. [GH-877]
* provider/aws: Fix `aws_db_instance` to not recreate each time. [GH-874]
* provider/aws: ASG termination policies are synced with remote state. [GH-923]
* provider/aws: No read error when subnet is manually deleted. [GH-889]
* provider/google: Fix bug preventing instances with metadata from being
created [GH-884].

Expand Down
12 changes: 0 additions & 12 deletions builtin/bins/provider-azure/main.go

This file was deleted.

1 change: 0 additions & 1 deletion builtin/bins/provider-azure/main_test.go

This file was deleted.

1 change: 1 addition & 0 deletions builtin/providers/aws/resource_aws_autoscaling_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ func resourceAwsAutoscalingGroupRead(d *schema.ResourceData, meta interface{}) e
d.Set("max_size", g.MaxSize)
d.Set("name", g.Name)
d.Set("vpc_zone_identifier", strings.Split(g.VPCZoneIdentifier, ","))
d.Set("termination_policies", g.TerminationPolicies)

return nil
}
Expand Down
12 changes: 12 additions & 0 deletions builtin/providers/aws/resource_aws_db_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ func resourceAwsDbInstance() *schema.Resource {
ForceNew: true,
},

"storage_type": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},

"identifier": &schema.Schema{
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -190,6 +197,10 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
EngineVersion: d.Get("engine_version").(string),
}

if attr, ok := d.GetOk("storage_type"); ok {
opts.StorageType = attr.(string)
}

if attr, ok := d.GetOk("backup_retention_period"); ok {
opts.BackupRetentionPeriod = attr.(int)
opts.SetBackupRetentionPeriod = true
Expand Down Expand Up @@ -296,6 +307,7 @@ func resourceAwsDbInstanceRead(d *schema.ResourceData, meta interface{}) error {
d.Set("engine", v.Engine)
d.Set("engine_version", v.EngineVersion)
d.Set("allocated_storage", v.AllocatedStorage)
d.Set("storage_type", v.StorageType)
d.Set("instance_class", v.DBInstanceClass)
d.Set("availability_zone", v.AvailabilityZone)
d.Set("backup_retention_period", v.BackupRetentionPeriod)
Expand Down
13 changes: 13 additions & 0 deletions builtin/providers/aws/resource_aws_db_parameter_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ func resourceAwsDbParameterGroup() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"apply_method": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: "immediate",
// this parameter is not actually state, but a
// meta-parameter describing how the RDS API call
// to modify the parameter group should be made.
// Future reads of the resource from AWS don't tell
// us what we used for apply_method previously, so
// by squashing state to an empty string we avoid
// needing to do an update for every future run.
StateFunc: func(interface{}) string { return "" },
},
},
},
Set: resourceAwsDbParameterHash,
Expand Down
3 changes: 0 additions & 3 deletions builtin/providers/aws/resource_aws_elb.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,9 @@ func resourceAwsElb() *schema.Resource {
},
},

// TODO: could be not ForceNew
"listener": &schema.Schema{
Type: schema.TypeSet,
Required: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"instance_port": &schema.Schema{
Expand Down Expand Up @@ -115,7 +113,6 @@ func resourceAwsElb() *schema.Resource {
Set: resourceAwsElbListenerHash,
},

// TODO: could be not ForceNew
"health_check": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Expand Down
179 changes: 130 additions & 49 deletions builtin/providers/aws/resource_aws_security_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,52 @@ func resourceAwsSecurityGroup() *schema.Resource {
},
},
},
Set: resourceAwsSecurityGroupIngressHash,
Set: resourceAwsSecurityGroupRuleHash,
},

"egress": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"from_port": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},

"to_port": &schema.Schema{
Type: schema.TypeInt,
Required: true,
},

"protocol": &schema.Schema{
Type: schema.TypeString,
Required: true,
},

"cidr_blocks": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},

"security_groups": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: func(v interface{}) int {
return hashcode.String(v.(string))
},
},

"self": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
},
Set: resourceAwsSecurityGroupRuleHash,
},

"owner_id": &schema.Schema{
Expand Down Expand Up @@ -139,28 +184,14 @@ func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) er
return resourceAwsSecurityGroupUpdate(d, meta)
}

func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) error {
ec2conn := meta.(*AWSClient).ec2conn

sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
if err != nil {
return err
}
if sgRaw == nil {
d.SetId("")
return nil
}

sg := sgRaw.(*ec2.SecurityGroupInfo)

// Gather our ingress rules
ingressMap := make(map[string]map[string]interface{})
for _, perm := range sg.IPPerms {
func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions []ec2.IPPerm) []map[string]interface{} {
ruleMap := make(map[string]map[string]interface{})
for _, perm := range permissions {
k := fmt.Sprintf("%s-%d-%d", perm.Protocol, perm.FromPort, perm.ToPort)
m, ok := ingressMap[k]
m, ok := ruleMap[k]
if !ok {
m = make(map[string]interface{})
ingressMap[k] = m
ruleMap[k] = m
}

m["from_port"] = perm.FromPort
Expand Down Expand Up @@ -200,22 +231,15 @@ func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) erro
m["security_groups"] = list
}
}
ingressRules := make([]map[string]interface{}, 0, len(ingressMap))
for _, m := range ingressMap {
ingressRules = append(ingressRules, m)
rules := make([]map[string]interface{}, 0, len(ruleMap))
for _, m := range ruleMap {
rules = append(rules, m)
}

d.Set("description", sg.Description)
d.Set("name", sg.Name)
d.Set("vpc_id", sg.VpcId)
d.Set("owner_id", sg.OwnerId)
d.Set("ingress", ingressRules)
d.Set("tags", tagsToMap(sg.Tags))

return nil
return rules
}

func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) error {
func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) error {
ec2conn := meta.(*AWSClient).ec2conn

sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
Expand All @@ -226,10 +250,26 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er
d.SetId("")
return nil
}
group := sgRaw.(*ec2.SecurityGroupInfo).SecurityGroup

if d.HasChange("ingress") {
o, n := d.GetChange("ingress")
sg := sgRaw.(*ec2.SecurityGroupInfo)

ingressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPerms)
egressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPermsEgress)

d.Set("description", sg.Description)
d.Set("name", sg.Name)
d.Set("vpc_id", sg.VpcId)
d.Set("owner_id", sg.OwnerId)
d.Set("ingress", ingressRules)
d.Set("egress", egressRules)
d.Set("tags", tagsToMap(sg.Tags))

return nil
}

func resourceAwsSecurityGroupUpdateRules(d *schema.ResourceData, ruleset string, meta interface{}, group ec2.SecurityGroup) error {
if d.HasChange(ruleset) {
o, n := d.GetChange(ruleset)
if o == nil {
o = new(schema.Set)
}
Expand All @@ -252,29 +292,70 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er
// adding is easier here, and Terraform should be fast enough to
// not have service issues.

if len(remove) > 0 {
// Revoke the old rules
_, err = ec2conn.RevokeSecurityGroup(group, remove)
if err != nil {
return fmt.Errorf("Error authorizing security group ingress rules: %s", err)
if len(remove) > 0 || len(add) > 0 {

ec2conn := meta.(*AWSClient).ec2conn

if len(remove) > 0 {
// Revoke the old rules
revoke := ec2conn.RevokeSecurityGroup
if ruleset == "egress" {
revoke = ec2conn.RevokeSecurityGroupEgress
}
_, err := revoke(group, remove)
if err != nil {
return fmt.Errorf("Error revoking security group %s rules: %s", ruleset, err)
}
}
}

if len(add) > 0 {
// Authorize the new rules
_, err := ec2conn.AuthorizeSecurityGroup(group, add)
if err != nil {
return fmt.Errorf("Error authorizing security group ingress rules: %s", err)
if len(add) > 0 {
// Authorize the new rules
authorize := ec2conn.AuthorizeSecurityGroup
if ruleset == "egress" {
authorize = ec2conn.AuthorizeSecurityGroupEgress
}
_, err := authorize(group, add)
if err != nil {
return fmt.Errorf("Error authorizing security group %s rules: %s", ruleset, err)
}
}
}
}

return nil
}

func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) error {
ec2conn := meta.(*AWSClient).ec2conn

sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())()
if err != nil {
return err
}
if sgRaw == nil {
d.SetId("")
return nil
}
group := sgRaw.(*ec2.SecurityGroupInfo).SecurityGroup

err = resourceAwsSecurityGroupUpdateRules(d, "ingress", ec2conn, group)
if err != nil {
return err
}

if d.Get("vpc_id") != nil {
err = resourceAwsSecurityGroupUpdateRules(d, "egress", ec2conn, group)
if err != nil {
return err
}
}

if err := setTags(ec2conn, d); err != nil {
return err
} else {
d.SetPartial("tags")
}

d.SetPartial("tags")

return resourceAwsSecurityGroupRead(d, meta)
}

Expand Down Expand Up @@ -307,7 +388,7 @@ func resourceAwsSecurityGroupDelete(d *schema.ResourceData, meta interface{}) er
})
}

func resourceAwsSecurityGroupIngressHash(v interface{}) int {
func resourceAwsSecurityGroupRuleHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%d-", m["from_port"].(int)))
Expand Down
Loading

0 comments on commit 6e8169a

Please sign in to comment.