Skip to content

Commit

Permalink
provider/openstack: Security Group Rule fixes
Browse files Browse the repository at this point in the history
This commit fixes an issue with security group rules where the rules
were not being correctly computed due to a typo in the rule map.

Once rules were successfully computed, the rules then needed to be
converted into a Set so they can be correctly ordered.
  • Loading branch information
jtopjian committed Nov 12, 2015
1 parent 9426f6f commit 3db7922
Show file tree
Hide file tree
Showing 2 changed files with 288 additions and 58 deletions.
114 changes: 64 additions & 50 deletions builtin/providers/openstack/resource_openstack_compute_secgroup_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ func resourceComputeSecGroupV2() *schema.Resource {
ForceNew: false,
},
"rule": &schema.Schema{
Type: schema.TypeList,
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": &schema.Schema{
Expand Down Expand Up @@ -79,6 +80,7 @@ func resourceComputeSecGroupV2() *schema.Resource {
},
},
},
Set: secgroupRuleV2Hash,
},
},
}
Expand Down Expand Up @@ -129,13 +131,10 @@ func resourceComputeSecGroupV2Read(d *schema.ResourceData, meta interface{}) err

d.Set("name", sg.Name)
d.Set("description", sg.Description)
rtm := rulesToMap(sg.Rules)
for _, v := range rtm {
if v["group"] == d.Get("name") {
v["self"] = "1"
} else {
v["self"] = "0"
}

rtm, err := rulesToMap(computeClient, d, sg.Rules)
if err != nil {
return err
}
log.Printf("[DEBUG] rulesToMap(sg.Rules): %+v", rtm)
d.Set("rule", rtm)
Expand Down Expand Up @@ -164,14 +163,11 @@ func resourceComputeSecGroupV2Update(d *schema.ResourceData, meta interface{}) e

if d.HasChange("rule") {
oldSGRaw, newSGRaw := d.GetChange("rule")
oldSGRSlice, newSGRSlice := oldSGRaw.([]interface{}), newSGRaw.([]interface{})
oldSGRSet := schema.NewSet(secgroupRuleV2Hash, oldSGRSlice)
newSGRSet := schema.NewSet(secgroupRuleV2Hash, newSGRSlice)
oldSGRSet, newSGRSet := oldSGRaw.(*schema.Set), newSGRaw.(*schema.Set)
secgrouprulesToAdd := newSGRSet.Difference(oldSGRSet)
secgrouprulesToRemove := oldSGRSet.Difference(newSGRSet)

log.Printf("[DEBUG] Security group rules to add: %v", secgrouprulesToAdd)

log.Printf("[DEBUG] Security groups rules to remove: %v", secgrouprulesToRemove)

for _, rawRule := range secgrouprulesToAdd.List() {
Expand Down Expand Up @@ -231,67 +227,83 @@ func resourceComputeSecGroupV2Delete(d *schema.ResourceData, meta interface{}) e
}

func resourceSecGroupRulesV2(d *schema.ResourceData) []secgroups.CreateRuleOpts {
rawRules := d.Get("rule").([]interface{})
rawRules := d.Get("rule").(*schema.Set).List()
createRuleOptsList := make([]secgroups.CreateRuleOpts, len(rawRules))
for i, raw := range rawRules {
rawMap := raw.(map[string]interface{})
groupId := rawMap["from_group_id"].(string)
if rawMap["self"].(bool) {
groupId = d.Id()
}
createRuleOptsList[i] = secgroups.CreateRuleOpts{
ParentGroupID: d.Id(),
FromPort: rawMap["from_port"].(int),
ToPort: rawMap["to_port"].(int),
IPProtocol: rawMap["ip_protocol"].(string),
CIDR: rawMap["cidr"].(string),
FromGroupID: groupId,
}
for i, rawRule := range rawRules {
createRuleOptsList[i] = resourceSecGroupRuleCreateOptsV2(d, rawRule)
}
return createRuleOptsList
}

func resourceSecGroupRuleCreateOptsV2(d *schema.ResourceData, raw interface{}) secgroups.CreateRuleOpts {
rawMap := raw.(map[string]interface{})
groupId := rawMap["from_group_id"].(string)
if rawMap["self"].(bool) {
func resourceSecGroupRuleCreateOptsV2(d *schema.ResourceData, rawRule interface{}) secgroups.CreateRuleOpts {
rawRuleMap := rawRule.(map[string]interface{})
groupId := rawRuleMap["from_group_id"].(string)
if rawRuleMap["self"].(bool) {
groupId = d.Id()
}
return secgroups.CreateRuleOpts{
ParentGroupID: d.Id(),
FromPort: rawMap["from_port"].(int),
ToPort: rawMap["to_port"].(int),
IPProtocol: rawMap["ip_protocol"].(string),
CIDR: rawMap["cidr"].(string),
FromPort: rawRuleMap["from_port"].(int),
ToPort: rawRuleMap["to_port"].(int),
IPProtocol: rawRuleMap["ip_protocol"].(string),
CIDR: rawRuleMap["cidr"].(string),
FromGroupID: groupId,
}
}

func resourceSecGroupRuleV2(d *schema.ResourceData, raw interface{}) secgroups.Rule {
rawMap := raw.(map[string]interface{})
func resourceSecGroupRuleV2(d *schema.ResourceData, rawRule interface{}) secgroups.Rule {
rawRuleMap := rawRule.(map[string]interface{})
return secgroups.Rule{
ID: rawMap["id"].(string),
ID: rawRuleMap["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)},
FromPort: rawRuleMap["from_port"].(int),
ToPort: rawRuleMap["to_port"].(int),
IPProtocol: rawRuleMap["ip_protocol"].(string),
IPRange: secgroups.IPRange{CIDR: rawRuleMap["cidr"].(string)},
}
}

func rulesToMap(sgrs []secgroups.Rule) []map[string]interface{} {
func rulesToMap(computeClient *gophercloud.ServiceClient, d *schema.ResourceData, sgrs []secgroups.Rule) ([]map[string]interface{}, error) {
sgrMap := make([]map[string]interface{}, len(sgrs))
for i, sgr := range sgrs {
groupId := ""
self := false
if sgr.Group.Name != "" {
if sgr.Group.Name == d.Get("name").(string) {
self = true
} else {
// Since Nova only returns the secgroup Name (and not the ID) for the group attribute,
// we need to look up all security groups and match the name.
// Nevermind that Nova wants the ID when setting the Group *and* that multiple groups
// with the same name can exist...
allPages, err := secgroups.List(computeClient).AllPages()
if err != nil {
return nil, err
}
securityGroups, err := secgroups.ExtractSecurityGroups(allPages)
if err != nil {
return nil, err
}

for _, sg := range securityGroups {
if sg.Name == sgr.Group.Name {
groupId = sg.ID
}
}
}
}

sgrMap[i] = map[string]interface{}{
"id": sgr.ID,
"from_port": sgr.FromPort,
"to_port": sgr.ToPort,
"ip_protocol": sgr.IPProtocol,
"cidr": sgr.IPRange.CIDR,
"group": sgr.Group.Name,
"id": sgr.ID,
"from_port": sgr.FromPort,
"to_port": sgr.ToPort,
"ip_protocol": sgr.IPProtocol,
"cidr": sgr.IPRange.CIDR,
"self": self,
"from_group_id": groupId,
}
}
return sgrMap
return sgrMap, nil
}

func secgroupRuleV2Hash(v interface{}) int {
Expand All @@ -301,6 +313,8 @@ func secgroupRuleV2Hash(v interface{}) 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)))
buf.WriteString(fmt.Sprintf("%s-", m["self"].(bool)))

return hashcode.String(buf.String())
}
Expand Down
Loading

0 comments on commit 3db7922

Please sign in to comment.