Merge pull request #823 from svanharmelen/f-provider/cloudstack-managed-fw

provider/cloudstack: managed fw and adding/updating docs
This commit is contained in:
Sander van Harmelen 2015-01-16 17:53:42 +01:00
commit 8e7ffc24a5
8 changed files with 169 additions and 36 deletions

View File

@ -35,7 +35,7 @@ func resourceCloudStackEgressFirewall() *schema.Resource {
"rule": &schema.Schema{ "rule": &schema.Schema{
Type: schema.TypeSet, Type: schema.TypeSet,
Required: true, Optional: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"source_cidr": &schema.Schema{ "source_cidr": &schema.Schema{
@ -84,6 +84,11 @@ func resourceCloudStackEgressFirewall() *schema.Resource {
func resourceCloudStackEgressFirewallCreate(d *schema.ResourceData, meta interface{}) error { func resourceCloudStackEgressFirewallCreate(d *schema.ResourceData, meta interface{}) error {
cs := meta.(*cloudstack.CloudStackClient) cs := meta.(*cloudstack.CloudStackClient)
// Make sure all required parameters are there
if err := verifyEgressFirewallParams(d); err != nil {
return err
}
// Retrieve the network UUID // Retrieve the network UUID
networkid, e := retrieveUUID(cs, "network", d.Get("network").(string)) networkid, e := retrieveUUID(cs, "network", d.Get("network").(string))
if e != nil { if e != nil {
@ -203,10 +208,6 @@ func resourceCloudStackEgressFirewallRead(d *schema.ResourceData, meta interface
F: resourceCloudStackEgressFirewallRuleHash, F: resourceCloudStackEgressFirewallRuleHash,
} }
if d.Get("managed").(bool) {
// Read all rules...
}
// Read all rules that are configured // Read all rules that are configured
if rs := d.Get("rule").(*schema.Set); rs.Len() > 0 { if rs := d.Get("rule").(*schema.Set); rs.Len() > 0 {
for _, rule := range rs.List() { for _, rule := range rs.List() {
@ -285,7 +286,8 @@ func resourceCloudStackEgressFirewallRead(d *schema.ResourceData, meta interface
} }
// If this is a managed firewall, add all unknown rules into a single dummy rule // If this is a managed firewall, add all unknown rules into a single dummy rule
if d.Get("managed").(bool) { managed := d.Get("managed").(bool)
if managed {
// Get all the rules from the running environment // Get all the rules from the running environment
p := cs.Firewall.NewListEgressFirewallRulesParams() p := cs.Firewall.NewListEgressFirewallRulesParams()
p.SetNetworkid(d.Id()) p.SetNetworkid(d.Id())
@ -297,7 +299,7 @@ func resourceCloudStackEgressFirewallRead(d *schema.ResourceData, meta interface
} }
// Add all UUIDs to the uuids map // Add all UUIDs to the uuids map
uuids := make(map[string]interface{}) uuids := make(map[string]interface{}, len(r.EgressFirewallRules))
for _, r := range r.EgressFirewallRules { for _, r := range r.EgressFirewallRules {
uuids[r.Id] = r.Id uuids[r.Id] = r.Id
} }
@ -326,7 +328,7 @@ func resourceCloudStackEgressFirewallRead(d *schema.ResourceData, meta interface
if rules.Len() > 0 { if rules.Len() > 0 {
d.Set("rule", rules) d.Set("rule", rules)
} else { } else if !managed {
d.SetId("") d.SetId("")
} }
@ -334,6 +336,11 @@ func resourceCloudStackEgressFirewallRead(d *schema.ResourceData, meta interface
} }
func resourceCloudStackEgressFirewallUpdate(d *schema.ResourceData, meta interface{}) error { func resourceCloudStackEgressFirewallUpdate(d *schema.ResourceData, meta interface{}) error {
// Make sure all required parameters are there
if err := verifyEgressFirewallParams(d); err != nil {
return err
}
// Check if the rule set as a whole has changed // Check if the rule set as a whole has changed
if d.HasChange("rule") { if d.HasChange("rule") {
o, n := d.GetChange("rule") o, n := d.GetChange("rule")
@ -462,6 +469,18 @@ func resourceCloudStackEgressFirewallRuleHash(v interface{}) int {
return hashcode.String(buf.String()) return hashcode.String(buf.String())
} }
func verifyEgressFirewallParams(d *schema.ResourceData) error {
managed := d.Get("managed").(bool)
_, rules := d.GetOk("rule")
if !rules && !managed {
return fmt.Errorf(
"You must supply at least one 'rule' when not using the 'managed' firewall feature")
}
return nil
}
func verifyEgressFirewallRuleParams(d *schema.ResourceData, rule map[string]interface{}) error { func verifyEgressFirewallRuleParams(d *schema.ResourceData, rule map[string]interface{}) error {
protocol := rule["protocol"].(string) protocol := rule["protocol"].(string)
if protocol != "tcp" && protocol != "udp" && protocol != "icmp" { if protocol != "tcp" && protocol != "udp" && protocol != "icmp" {

View File

@ -35,7 +35,7 @@ func resourceCloudStackFirewall() *schema.Resource {
"rule": &schema.Schema{ "rule": &schema.Schema{
Type: schema.TypeSet, Type: schema.TypeSet,
Required: true, Optional: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"source_cidr": &schema.Schema{ "source_cidr": &schema.Schema{
@ -84,6 +84,11 @@ func resourceCloudStackFirewall() *schema.Resource {
func resourceCloudStackFirewallCreate(d *schema.ResourceData, meta interface{}) error { func resourceCloudStackFirewallCreate(d *schema.ResourceData, meta interface{}) error {
cs := meta.(*cloudstack.CloudStackClient) cs := meta.(*cloudstack.CloudStackClient)
// Make sure all required parameters are there
if err := verifyFirewallParams(d); err != nil {
return err
}
// Retrieve the ipaddress UUID // Retrieve the ipaddress UUID
ipaddressid, e := retrieveUUID(cs, "ipaddress", d.Get("ipaddress").(string)) ipaddressid, e := retrieveUUID(cs, "ipaddress", d.Get("ipaddress").(string))
if e != nil { if e != nil {
@ -281,7 +286,8 @@ func resourceCloudStackFirewallRead(d *schema.ResourceData, meta interface{}) er
} }
// If this is a managed firewall, add all unknown rules into a single dummy rule // If this is a managed firewall, add all unknown rules into a single dummy rule
if d.Get("managed").(bool) { managed := d.Get("managed").(bool)
if managed {
// Get all the rules from the running environment // Get all the rules from the running environment
p := cs.Firewall.NewListFirewallRulesParams() p := cs.Firewall.NewListFirewallRulesParams()
p.SetIpaddressid(d.Id()) p.SetIpaddressid(d.Id())
@ -293,7 +299,7 @@ func resourceCloudStackFirewallRead(d *schema.ResourceData, meta interface{}) er
} }
// Add all UUIDs to the uuids map // Add all UUIDs to the uuids map
uuids := make(map[string]interface{}) uuids := make(map[string]interface{}, len(r.FirewallRules))
for _, r := range r.FirewallRules { for _, r := range r.FirewallRules {
uuids[r.Id] = r.Id uuids[r.Id] = r.Id
} }
@ -322,7 +328,7 @@ func resourceCloudStackFirewallRead(d *schema.ResourceData, meta interface{}) er
if rules.Len() > 0 { if rules.Len() > 0 {
d.Set("rule", rules) d.Set("rule", rules)
} else { } else if !managed {
d.SetId("") d.SetId("")
} }
@ -330,6 +336,11 @@ func resourceCloudStackFirewallRead(d *schema.ResourceData, meta interface{}) er
} }
func resourceCloudStackFirewallUpdate(d *schema.ResourceData, meta interface{}) error { func resourceCloudStackFirewallUpdate(d *schema.ResourceData, meta interface{}) error {
// Make sure all required parameters are there
if err := verifyFirewallParams(d); err != nil {
return err
}
// Check if the rule set as a whole has changed // Check if the rule set as a whole has changed
if d.HasChange("rule") { if d.HasChange("rule") {
o, n := d.GetChange("rule") o, n := d.GetChange("rule")
@ -458,6 +469,18 @@ func resourceCloudStackFirewallRuleHash(v interface{}) int {
return hashcode.String(buf.String()) return hashcode.String(buf.String())
} }
func verifyFirewallParams(d *schema.ResourceData) error {
managed := d.Get("managed").(bool)
_, rules := d.GetOk("rule")
if !rules && !managed {
return fmt.Errorf(
"You must supply at least one 'rule' when not using the 'managed' firewall feature")
}
return nil
}
func verifyFirewallRuleParams(d *schema.ResourceData, rule map[string]interface{}) error { func verifyFirewallRuleParams(d *schema.ResourceData, rule map[string]interface{}) error {
protocol := rule["protocol"].(string) protocol := rule["protocol"].(string)
if protocol != "tcp" && protocol != "udp" && protocol != "icmp" { if protocol != "tcp" && protocol != "udp" && protocol != "icmp" {

View File

@ -35,7 +35,7 @@ func resourceCloudStackNetworkACLRule() *schema.Resource {
"rule": &schema.Schema{ "rule": &schema.Schema{
Type: schema.TypeSet, Type: schema.TypeSet,
Required: true, Optional: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"action": &schema.Schema{ "action": &schema.Schema{
@ -94,11 +94,13 @@ func resourceCloudStackNetworkACLRule() *schema.Resource {
} }
func resourceCloudStackNetworkACLRuleCreate(d *schema.ResourceData, meta interface{}) error { func resourceCloudStackNetworkACLRuleCreate(d *schema.ResourceData, meta interface{}) error {
// Get the acl UUID // Make sure all required parameters are there
aclid := d.Get("aclid").(string) if err := verifyNetworkACLParams(d); err != nil {
return err
}
// We need to set this upfront in order to be able to save a partial state // We need to set this upfront in order to be able to save a partial state
d.SetId(aclid) d.SetId(d.Get("aclid").(string))
// Create all rules that are configured // Create all rules that are configured
if rs := d.Get("rule").(*schema.Set); rs.Len() > 0 { if rs := d.Get("rule").(*schema.Set); rs.Len() > 0 {
@ -110,8 +112,7 @@ func resourceCloudStackNetworkACLRuleCreate(d *schema.ResourceData, meta interfa
for _, rule := range rs.List() { for _, rule := range rs.List() {
// Create a single rule // Create a single rule
err := resourceCloudStackNetworkACLRuleCreateRule( err := resourceCloudStackNetworkACLRuleCreateRule(d, meta, rule.(map[string]interface{}))
d, meta, aclid, rule.(map[string]interface{}))
// We need to update this first to preserve the correct state // We need to update this first to preserve the correct state
rules.Add(rule) rules.Add(rule)
@ -127,7 +128,7 @@ func resourceCloudStackNetworkACLRuleCreate(d *schema.ResourceData, meta interfa
} }
func resourceCloudStackNetworkACLRuleCreateRule( func resourceCloudStackNetworkACLRuleCreateRule(
d *schema.ResourceData, meta interface{}, aclid string, rule map[string]interface{}) error { d *schema.ResourceData, meta interface{}, rule map[string]interface{}) error {
cs := meta.(*cloudstack.CloudStackClient) cs := meta.(*cloudstack.CloudStackClient)
uuids := rule["uuids"].(map[string]interface{}) uuids := rule["uuids"].(map[string]interface{})
@ -140,7 +141,7 @@ func resourceCloudStackNetworkACLRuleCreateRule(
p := cs.NetworkACL.NewCreateNetworkACLParams(rule["protocol"].(string)) p := cs.NetworkACL.NewCreateNetworkACLParams(rule["protocol"].(string))
// Set the acl ID // Set the acl ID
p.SetAclid(aclid) p.SetAclid(d.Id())
// Set the action // Set the action
p.SetAction(rule["action"].(string)) p.SetAction(rule["action"].(string))
@ -302,7 +303,8 @@ func resourceCloudStackNetworkACLRuleRead(d *schema.ResourceData, meta interface
} }
// If this is a managed firewall, add all unknown rules into a single dummy rule // If this is a managed firewall, add all unknown rules into a single dummy rule
if d.Get("managed").(bool) { managed := d.Get("managed").(bool)
if managed {
// Get all the rules from the running environment // Get all the rules from the running environment
p := cs.NetworkACL.NewListNetworkACLsParams() p := cs.NetworkACL.NewListNetworkACLsParams()
p.SetAclid(d.Id()) p.SetAclid(d.Id())
@ -314,7 +316,7 @@ func resourceCloudStackNetworkACLRuleRead(d *schema.ResourceData, meta interface
} }
// Add all UUIDs to the uuids map // Add all UUIDs to the uuids map
uuids := make(map[string]interface{}) uuids := make(map[string]interface{}, len(r.NetworkACLs))
for _, r := range r.NetworkACLs { for _, r := range r.NetworkACLs {
uuids[r.Id] = r.Id uuids[r.Id] = r.Id
} }
@ -343,7 +345,7 @@ func resourceCloudStackNetworkACLRuleRead(d *schema.ResourceData, meta interface
if rules.Len() > 0 { if rules.Len() > 0 {
d.Set("rule", rules) d.Set("rule", rules)
} else { } else if !managed {
d.SetId("") d.SetId("")
} }
@ -351,8 +353,10 @@ func resourceCloudStackNetworkACLRuleRead(d *schema.ResourceData, meta interface
} }
func resourceCloudStackNetworkACLRuleUpdate(d *schema.ResourceData, meta interface{}) error { func resourceCloudStackNetworkACLRuleUpdate(d *schema.ResourceData, meta interface{}) error {
// Get the acl UUID // Make sure all required parameters are there
aclid := d.Get("aclid").(string) if err := verifyNetworkACLParams(d); err != nil {
return err
}
// Check if the rule set as a whole has changed // Check if the rule set as a whole has changed
if d.HasChange("rule") { if d.HasChange("rule") {
@ -376,8 +380,7 @@ func resourceCloudStackNetworkACLRuleUpdate(d *schema.ResourceData, meta interfa
// Then loop through al the currently configured rules and create the new ones // Then loop through al the currently configured rules and create the new ones
for _, rule := range nrs.List() { for _, rule := range nrs.List() {
// When succesfully deleted, re-create it again if it still exists // When succesfully deleted, re-create it again if it still exists
err := resourceCloudStackNetworkACLRuleCreateRule( err := resourceCloudStackNetworkACLRuleCreateRule(d, meta, rule.(map[string]interface{}))
d, meta, aclid, rule.(map[string]interface{}))
// We need to update this first to preserve the correct state // We need to update this first to preserve the correct state
rules.Add(rule) rules.Add(rule)
@ -486,6 +489,18 @@ func resourceCloudStackNetworkACLRuleHash(v interface{}) int {
return hashcode.String(buf.String()) return hashcode.String(buf.String())
} }
func verifyNetworkACLParams(d *schema.ResourceData) error {
managed := d.Get("managed").(bool)
_, rules := d.GetOk("rule")
if !rules && !managed {
return fmt.Errorf(
"You must supply at least one 'rule' when not using the 'managed' firewall feature")
}
return nil
}
func verifyNetworkACLRuleParams(d *schema.ResourceData, rule map[string]interface{}) error { func verifyNetworkACLRuleParams(d *schema.ResourceData, rule map[string]interface{}) error {
action := rule["action"].(string) action := rule["action"].(string)
if action != "allow" && action != "deny" { if action != "allow" && action != "deny" {

View File

@ -0,0 +1,61 @@
---
layout: "cloudstack"
page_title: "CloudStack: cloudstack_egress_firewall"
sidebar_current: "docs-cloudstack-resource-egress-firewall"
description: |-
Creates egress firewall rules for a given network.
---
# cloudstack\_egress\_firewall
Creates egress firewall rules for a given network.
## Example Usage
```
resource "cloudstack_egress_firewall" "default" {
network = "test-network"
rule {
source_cidr = "10.0.0.0/8"
protocol = "tcp"
ports = ["80", "1000-2000"]
}
}
```
## Argument Reference
The following arguments are supported:
* `network` - (Required) The network for which to create the egress firewall
rules. Changing this forces a new resource to be created.
* `managed` - (Optional) USE WITH CAUTION! If enabled all the egress firewall
rules for this network will be managed by this resource. This means it will
delete all firewall rules that are not in your config! (defaults false)
* `rule` - (Optional) Can be specified multiple times. Each rule block supports
fields documented below. If `managed = false` at least one rule is required!
The `rule` block supports:
* `source_cidr` - (Required) The source CIDR to allow access to the given ports.
* `protocol` - (Required) The name of the protocol to allow. Valid options are:
`tcp`, `udp` and `icmp`.
* `icmp_type` - (Optional) The ICMP type to allow. This can only be specified if
the protocol is ICMP.
* `icmp_code` - (Optional) The ICMP code to allow. This can only be specified if
the protocol is ICMP.
* `ports` - (Optional) List of ports and/or port ranges to allow. This can only
be specified if the protocol is TCP or UDP.
## Attributes Reference
The following attributes are exported:
* `ID` - The network ID for which the egress firewall rules are created.

View File

@ -31,8 +31,12 @@ The following arguments are supported:
* `ipaddress` - (Required) The IP address for which to create the firewall rules. * `ipaddress` - (Required) The IP address for which to create the firewall rules.
Changing this forces a new resource to be created. Changing this forces a new resource to be created.
* `rule` - (Required) Can be specified multiple times. Each rule block supports * `managed` - (Optional) USE WITH CAUTION! If enabled all the firewall rules for
fields documented below. this IP address will be managed by this resource. This means it will delete
all firewall rules that are not in your config! (defaults false)
* `rule` - (Optional) Can be specified multiple times. Each rule block supports
fields documented below. If `managed = false` at least one rule is required!
The `rule` block supports: The `rule` block supports:
@ -54,4 +58,4 @@ The `rule` block supports:
The following attributes are exported: The following attributes are exported:
* `ipaddress` - The IP address for which the firewall rules are created. * `ID` - The IP address ID for which the firewall rules are created.

View File

@ -23,9 +23,12 @@ resource "cloudstack_network_acl" "default" {
The following arguments are supported: The following arguments are supported:
* `name` - (Required) The name of the ACL. Changing this forces a new resource to be created. * `name` - (Required) The name of the ACL. Changing this forces a new resource
* `description` - (Optional) The description of the ACL. Changing this forces a new resource to be created. to be created.
* `vpc` - (Required) The name of the VPC to create this ACL for. Changing this forces a new resource to be created. * `description` - (Optional) The description of the ACL. Changing this forces a
new resource to be created.
* `vpc` - (Required) The name of the VPC to create this ACL for. Changing this
forces a new resource to be created.
## Attributes Reference ## Attributes Reference

View File

@ -33,8 +33,12 @@ The following arguments are supported:
* `aclid` - (Required) The network ACL ID for which to create the rules. * `aclid` - (Required) The network ACL ID for which to create the rules.
Changing this forces a new resource to be created. Changing this forces a new resource to be created.
* `rule` - (Required) Can be specified multiple times. Each rule block supports * `managed` - (Optional) USE WITH CAUTION! If enabled all the firewall rules for
fields documented below. this network ACL will be managed by this resource. This means it will delete
all firewall rules that are not in your config! (defaults false)
* `rule` - (Optional) Can be specified multiple times. Each rule block supports
fields documented below. If `managed = false` at least one rule is required!
The `rule` block supports: The `rule` block supports:
@ -62,4 +66,4 @@ The `rule` block supports:
The following attributes are exported: The following attributes are exported:
* `aclid` - The ACL ID for which the rules are created. * `ID` - The ACL ID for which the rules are created.

View File

@ -17,6 +17,10 @@
<a href="/docs/providers/cloudstack/r/disk.html">cloudstack_disk</a> <a href="/docs/providers/cloudstack/r/disk.html">cloudstack_disk</a>
</li> </li>
<li<%= sidebar_current("docs-cloudstack-resource-egress-firewall") %>>
<a href="/docs/providers/cloudstack/r/egress_firewall.html">cloudstack_egress_firewall</a>
</li>
<li<%= sidebar_current("docs-cloudstack-resource-firewall") %>> <li<%= sidebar_current("docs-cloudstack-resource-firewall") %>>
<a href="/docs/providers/cloudstack/r/firewall.html">cloudstack_firewall</a> <a href="/docs/providers/cloudstack/r/firewall.html">cloudstack_firewall</a>
</li> </li>