in cloudstack/resource_cloudstack_firewall.go [251:383]
func resourceCloudStackFirewallRead(d *schema.ResourceData, meta interface{}) error {
cs := meta.(*cloudstack.CloudStackClient)
// Get all the rules from the running environment
p := cs.Firewall.NewListFirewallRulesParams()
p.SetIpaddressid(d.Id())
p.SetListall(true)
l, err := cs.Firewall.ListFirewallRules(p)
if err != nil {
return err
}
// Make a map of all the rules so we can easily find a rule
ruleMap := make(map[string]*cloudstack.FirewallRule, l.Count)
for _, r := range l.FirewallRules {
ruleMap[r.Id] = r
}
// Create an empty schema.Set to hold all rules
rules := resourceCloudStackFirewall().Schema["rule"].ZeroValue().(*schema.Set)
// Read all rules that are configured
if rs := d.Get("rule").(*schema.Set); rs.Len() > 0 {
for _, rule := range rs.List() {
rule := rule.(map[string]interface{})
uuids := rule["uuids"].(map[string]interface{})
if rule["protocol"].(string) == "icmp" {
id, ok := uuids["icmp"]
if !ok {
continue
}
// Get the rule
r, ok := ruleMap[id.(string)]
if !ok {
delete(uuids, "icmp")
continue
}
// Delete the known rule so only unknown rules remain in the ruleMap
delete(ruleMap, id.(string))
// Create a set with all CIDR's
cidrs := &schema.Set{F: schema.HashString}
for _, cidr := range strings.Split(r.Cidrlist, ",") {
cidrs.Add(cidr)
}
// Update the values
rule["protocol"] = r.Protocol
rule["icmp_type"] = r.Icmptype
rule["icmp_code"] = r.Icmpcode
rule["cidr_list"] = cidrs
rules.Add(rule)
}
// If protocol is not ICMP, loop through all ports
if rule["protocol"].(string) != "icmp" {
if ps := rule["ports"].(*schema.Set); ps.Len() > 0 {
// Create an empty schema.Set to hold all ports
ports := &schema.Set{F: schema.HashString}
// Loop through all ports and retrieve their info
for _, port := range ps.List() {
id, ok := uuids[port.(string)]
if !ok {
continue
}
// Get the rule
r, ok := ruleMap[id.(string)]
if !ok {
delete(uuids, port.(string))
continue
}
// Delete the known rule so only unknown rules remain in the ruleMap
delete(ruleMap, id.(string))
// Create a set with all CIDR's
cidrs := &schema.Set{F: schema.HashString}
for _, cidr := range strings.Split(r.Cidrlist, ",") {
cidrs.Add(cidr)
}
// Update the values
rule["protocol"] = r.Protocol
rule["cidr_list"] = cidrs
ports.Add(port)
}
// If there is at least one port found, add this rule to the rules set
if ports.Len() > 0 {
rule["ports"] = ports
rules.Add(rule)
}
}
}
}
}
// If this is a managed firewall, add all unknown rules into a single dummy rule
managed := d.Get("managed").(bool)
if managed && len(ruleMap) > 0 {
for uuid := range ruleMap {
// We need to create and add a dummy value to a schema.Set as the
// cidr_list is a required field and thus needs a value
cidrs := &schema.Set{F: schema.HashString}
cidrs.Add(uuid)
// Make a dummy rule to hold the unknown UUID
rule := map[string]interface{}{
"cidr_list": cidrs,
"protocol": uuid,
"uuids": map[string]interface{}{uuid: uuid},
}
// Add the dummy rule to the rules set
rules.Add(rule)
}
}
if rules.Len() > 0 {
d.Set("rule", rules)
} else if !managed {
d.SetId("")
}
return nil
}