security group rule fix; still not exporting rule ID

This commit is contained in:
Jon Perritt 2015-02-12 17:25:45 -07:00
parent 4df32aebed
commit 633e98dffe
3 changed files with 87 additions and 36 deletions

View File

@ -477,9 +477,18 @@ func resourceComputeInstanceV2Update(d *schema.ResourceData, meta interface{}) e
for _, g := range secgroupsToRemove.List() { for _, g := range secgroupsToRemove.List() {
err := secgroups.RemoveServerFromGroup(computeClient, d.Id(), g.(string)).ExtractErr() err := secgroups.RemoveServerFromGroup(computeClient, d.Id(), g.(string)).ExtractErr()
if err != nil { if err != nil {
return fmt.Errorf("Error removing security group from OpenStack server (%s): %s", d.Id(), err) errCode, ok := err.(*perigee.UnexpectedResponseCodeError)
if !ok {
return fmt.Errorf("Error removing security group from OpenStack server (%s): %s", d.Id(), err)
}
if errCode.Actual == 404 {
continue
} else {
return fmt.Errorf("Error removing security group from OpenStack server (%s): %s", d.Id(), err)
}
} else {
log.Printf("[DEBUG] Removed security group (%s) from instance (%s)", g.(string), d.Id())
} }
log.Printf("[DEBUG] Removed security group (%s) from instance (%s)", g.(string), d.Id())
} }
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/schema"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups" "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
) )
@ -35,38 +36,41 @@ func resourceComputeSecGroupV2() *schema.Resource {
ForceNew: false, ForceNew: false,
}, },
"rule": &schema.Schema{ "rule": &schema.Schema{
Type: schema.TypeSet, Type: schema.TypeList,
Optional: true, Optional: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"from_port": &schema.Schema{ "from_port": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Required: true, Required: true,
ForceNew: true, ForceNew: false,
}, },
"to_port": &schema.Schema{ "to_port": &schema.Schema{
Type: schema.TypeInt, Type: schema.TypeInt,
Required: true, Required: true,
ForceNew: true, ForceNew: false,
}, },
"ip_protocol": &schema.Schema{ "ip_protocol": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: false,
}, },
"cidr": &schema.Schema{ "cidr": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: false,
}, },
"from_group_id": &schema.Schema{ "from_group_id": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: false,
}, },
}, },
}, },
Set: resourceSecGroupRuleV2Hash,
}, },
}, },
} }
@ -117,7 +121,8 @@ func resourceComputeSecGroupV2Read(d *schema.ResourceData, meta interface{}) err
d.Set("region", d.Get("region").(string)) d.Set("region", d.Get("region").(string))
d.Set("name", sg.Name) d.Set("name", sg.Name)
d.Set("description", sg.Description) d.Set("description", sg.Description)
d.Set("rule", sg.Rules) log.Printf("[DEBUG] rulesToMap(sg.Rules): %+v", rulesToMap(sg.Rules))
d.Set("rules", rulesToMap(sg.Rules))
return nil return nil
} }
@ -143,16 +148,18 @@ func resourceComputeSecGroupV2Update(d *schema.ResourceData, meta interface{}) e
if d.HasChange("rule") { if d.HasChange("rule") {
oldSGRaw, newSGRaw := d.GetChange("rule") oldSGRaw, newSGRaw := d.GetChange("rule")
oldSGRSet, newSGRSet := oldSGRaw.(*schema.Set), newSGRaw.(*schema.Set) oldSGRSlice, newSGRSlice := oldSGRaw.([]interface{}), newSGRaw.([]interface{})
oldSGRSet := schema.NewSet(secgroupRuleV2Hash, oldSGRSlice)
newSGRSet := schema.NewSet(secgroupRuleV2Hash, newSGRSlice)
secgrouprulesToAdd := newSGRSet.Difference(oldSGRSet) secgrouprulesToAdd := newSGRSet.Difference(oldSGRSet)
secgrouprulesToRemove := oldSGRSet.Difference(newSGRSet) secgrouprulesToRemove := oldSGRSet.Difference(newSGRSet)
log.Printf("[DEBUG] Security group rules to add: %v", secgrouprulesToAdd) log.Printf("[DEBUG] Security group rules to add: %v", secgrouprulesToAdd)
log.Printf("[DEBUG] Security groups to remove: %v", secgrouprulesToRemove) log.Printf("[DEBUG] Security groups rules to remove: %v", secgrouprulesToRemove)
for _, rawRule := range secgrouprulesToAdd.List() { for _, rawRule := range secgrouprulesToAdd.List() {
createRuleOpts := resourceSecGroupRuleV2(d, rawRule) createRuleOpts := resourceSecGroupRuleCreateOptsV2(d, rawRule)
rule, err := secgroups.CreateRule(computeClient, createRuleOpts).Extract() rule, err := secgroups.CreateRule(computeClient, createRuleOpts).Extract()
if err != nil { if err != nil {
return fmt.Errorf("Error adding rule to OpenStack security group (%s): %s", d.Id(), err) return fmt.Errorf("Error adding rule to OpenStack security group (%s): %s", d.Id(), err)
@ -161,12 +168,21 @@ func resourceComputeSecGroupV2Update(d *schema.ResourceData, meta interface{}) e
} }
for _, r := range secgrouprulesToRemove.List() { for _, r := range secgrouprulesToRemove.List() {
rule := r.(secgroups.Rule) rule := resourceSecGroupRuleV2(d, r)
err := secgroups.DeleteRule(computeClient, "").ExtractErr() err := secgroups.DeleteRule(computeClient, rule.ID).ExtractErr()
if err != nil { if err != nil {
return fmt.Errorf("Error removing rule (%s) from OpenStack security group (%s): %s", rule.ID, d.Id(), err) errCode, ok := err.(*perigee.UnexpectedResponseCodeError)
if !ok {
return fmt.Errorf("Error removing rule (%s) from OpenStack security group (%s): %s", rule.ID, d.Id(), err)
}
if errCode.Actual == 404 {
continue
} else {
return fmt.Errorf("Error removing rule (%s) from OpenStack security group (%s)", rule.ID, d.Id())
}
} else {
log.Printf("[DEBUG] Removed rule (%s) from OpenStack security group (%s): %s", rule.ID, d.Id(), err)
} }
log.Printf("[DEBUG] Removed rule (%s) from OpenStack security group (%s)", rule.ID, d.Id())
} }
} }
@ -188,22 +204,10 @@ func resourceComputeSecGroupV2Delete(d *schema.ResourceData, meta interface{}) e
return nil return nil
} }
func resourceSecGroupRuleV2Hash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%d-", m["from_port"].(int)))
buf.WriteString(fmt.Sprintf("%d-", m["to_port"].(int)))
buf.WriteString(fmt.Sprintf("%s-", m["ip_protocol"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["cidr"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["from_group_id"].(string)))
return hashcode.String(buf.String())
}
func resourceSecGroupRulesV2(d *schema.ResourceData) []secgroups.CreateRuleOpts { func resourceSecGroupRulesV2(d *schema.ResourceData) []secgroups.CreateRuleOpts {
rawRules := (d.Get("rule")).(*schema.Set) rawRules := (d.Get("rule")).([]interface{})
createRuleOptsList := make([]secgroups.CreateRuleOpts, rawRules.Len()) createRuleOptsList := make([]secgroups.CreateRuleOpts, len(rawRules))
for i, raw := range rawRules.List() { for i, raw := range rawRules {
rawMap := raw.(map[string]interface{}) rawMap := raw.(map[string]interface{})
createRuleOptsList[i] = secgroups.CreateRuleOpts{ createRuleOptsList[i] = secgroups.CreateRuleOpts{
ParentGroupID: d.Id(), ParentGroupID: d.Id(),
@ -217,7 +221,7 @@ func resourceSecGroupRulesV2(d *schema.ResourceData) []secgroups.CreateRuleOpts
return createRuleOptsList return createRuleOptsList
} }
func resourceSecGroupRuleV2(d *schema.ResourceData, raw interface{}) secgroups.CreateRuleOpts { func resourceSecGroupRuleCreateOptsV2(d *schema.ResourceData, raw interface{}) secgroups.CreateRuleOpts {
rawMap := raw.(map[string]interface{}) rawMap := raw.(map[string]interface{})
return secgroups.CreateRuleOpts{ return secgroups.CreateRuleOpts{
ParentGroupID: d.Id(), ParentGroupID: d.Id(),
@ -228,3 +232,41 @@ func resourceSecGroupRuleV2(d *schema.ResourceData, raw interface{}) secgroups.C
FromGroupID: rawMap["from_group_id"].(string), FromGroupID: rawMap["from_group_id"].(string),
} }
} }
func resourceSecGroupRuleV2(d *schema.ResourceData, raw interface{}) secgroups.Rule {
rawMap := raw.(map[string]interface{})
return secgroups.Rule{
ID: rawMap["id"].(string),
ParentGroupID: d.Id(),
FromPort: rawMap["from_port"].(int),
ToPort: rawMap["to_port"].(int),
IPProtocol: rawMap["ip_protocol"].(string),
IPRange: secgroups.IPRange{CIDR: rawMap["cidr"].(string)},
}
}
func rulesToMap(sgrs []secgroups.Rule) []map[string]interface{} {
sgrMap := make([]map[string]interface{}, len(sgrs))
for i, sgr := range sgrs {
sgrMap[i] = map[string]interface{}{
"to_port": sgr.ToPort,
"from_port": sgr.FromPort,
"id": sgr.ID,
"ruleID": sgr.ID,
"cidr": sgr.IPRange.CIDR,
"ip_protocol": sgr.IPProtocol,
}
}
return sgrMap
}
func secgroupRuleV2Hash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%d-", m["from_port"].(int)))
buf.WriteString(fmt.Sprintf("%d-", m["to_port"].(int)))
buf.WriteString(fmt.Sprintf("%s-", m["ip_protocol"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["cidr"].(string)))
return hashcode.String(buf.String())
}

View File

@ -9,14 +9,14 @@ import (
// CheckDeleted checks the error to see if it's a 404 (Not Found) and, if so, // CheckDeleted checks the error to see if it's a 404 (Not Found) and, if so,
// sets the resource ID to the empty string instead of throwing an error. // sets the resource ID to the empty string instead of throwing an error.
func CheckDeleted(d *schema.ResourceData, err error, resource string) error { func CheckDeleted(d *schema.ResourceData, err error, msg string) error {
errCode, ok := err.(*perigee.UnexpectedResponseCodeError) errCode, ok := err.(*perigee.UnexpectedResponseCodeError)
if !ok { if !ok {
return fmt.Errorf("Error retrieving OpenStack %s: %s", resource, err) return fmt.Errorf("%s: %s", msg, err)
} }
if errCode.Actual == 404 { if errCode.Actual == 404 {
d.SetId("") d.SetId("")
return nil return nil
} }
return fmt.Errorf("Error retrieving OpenStack %s: %s", resource, err) return fmt.Errorf("%s: %s", msg, err)
} }