diff --git a/digitalocean/import_digitalocean_firewall_test.go b/digitalocean/import_digitalocean_firewall_test.go deleted file mode 100644 index f82f1317..00000000 --- a/digitalocean/import_digitalocean_firewall_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package digitalocean - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" -) - -func TestAccDigitalOceanFirewall_importBasic(t *testing.T) { - tests := []struct { - description string - firewallName string - config string - }{ - { - description: "only allow inbound SSH(TCP/22)", - firewallName: fmt.Sprintf("foobar-test-terraform-firewall-%s", acctest.RandString(10)), - config: ` - resource "digitalocean_firewall" "foobar" { - name = "%s" - inbound_rules = [ - { - protocol = "tcp" - port_range = "22" - source_addresses = ["0.0.0.0/0", "::/0"] - }, - ] - }`, - }, - { - description: "only allow outbound SSH(TCP/22)", - firewallName: fmt.Sprintf("foobar-test-terraform-firewall-%s", acctest.RandString(10)), - config: ` - resource "digitalocean_firewall" "foobar" { - name = "%s" - outbound_rules = [ - { - protocol = "tcp" - port_range = "22" - destination_addresses = ["0.0.0.0/0", "::/0"] - }, - ] - }`, - }, - { - description: "only allow inbound SSH(TCP/22) and HTTP(TCP/80)", - firewallName: fmt.Sprintf("foobar-test-terraform-firewall-%s", acctest.RandString(10)), - config: ` - resource "digitalocean_firewall" "foobar" { - name = "%s" - inbound_rules = [ - { - protocol = "tcp" - port_range = "22" - source_addresses = ["0.0.0.0/0", "::/0"] - }, - { - protocol = "tcp" - port_range = "80" - source_addresses = ["1.2.3.0/24", "2002::/16"] - }, - ] - }`, - }, - { - description: "only allow outbound SSH(TCP/22) and DNS(UDP/53)", - firewallName: fmt.Sprintf("foobar-test-terraform-firewall-%s", acctest.RandString(10)), - config: ` - resource "digitalocean_firewall" "foobar" { - name = "%s" - outbound_rules = [ - { - protocol = "tcp" - port_range = "22" - destination_addresses = ["192.168.1.0/24", "2002:1001::/48"] - }, - { - protocol = "udp" - port_range = "53" - destination_addresses = ["1.2.3.0/24", "2002::/16"] - }, - ] - }`, - }, - { - description: "allow inbound and outbound HTTPS(TCP/443), inbound SSH(TCP/22), and outbound DNS(UDP/53)", - firewallName: fmt.Sprintf("foobar-test-terraform-firewall-%s", acctest.RandString(10)), - config: ` - resource "digitalocean_firewall" "foobar" { - name = "%s" - inbound_rules = [ - { - protocol = "tcp" - port_range = "443" - source_addresses = ["192.168.1.0/24", "2002:1001:1:2::/64"] - }, - { - protocol = "tcp" - port_range = "22" - source_addresses = ["0.0.0.0/0", "::/0"] - }, - ] - outbound_rules = [ - { - protocol = "tcp" - port_range = "443" - destination_addresses = ["192.168.1.0/24", "2002:1001:1:2::/64"] - }, - { - protocol = "udp" - port_range = "53" - destination_addresses = ["0.0.0.0/0", "::/0"] - }, - ] - }`, - }, - } - - for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - config := fmt.Sprintf(tt.config, tt.firewallName) - resourceName := fmt.Sprintf("digitalocean_firewall.%s", tt.firewallName) - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckDigitalOceanFirewallDestroy, - Steps: []resource.TestStep{ - { - Config: config, - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) - }) - } -} diff --git a/digitalocean/resource_digitalocean_firewall.go b/digitalocean/resource_digitalocean_firewall.go index 4061a9c6..890c763b 100644 --- a/digitalocean/resource_digitalocean_firewall.go +++ b/digitalocean/resource_digitalocean_firewall.go @@ -73,7 +73,7 @@ func resourceDigitalOceanFirewall() *schema.Resource { Optional: true, }, - "inbound_rules": { + "inbound_rule": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -110,7 +110,7 @@ func resourceDigitalOceanFirewall() *schema.Resource { }, }, - "outbound_rules": { + "outbound_rule": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -195,8 +195,14 @@ func resourceDigitalOceanFirewallRead(d *schema.ResourceData, meta interface{}) d.Set("name", firewall.Name) d.Set("droplet_ids", firewall.DropletIDs) d.Set("tags", firewall.Tags) - d.Set("inbound_rules", matchFirewallInboundRules(d, firewall)) - d.Set("outbound_rules", matchFirewallOutboundRules(d, firewall)) + + if err := d.Set("inbound_rule", flattenFirewallInboundRules(d, firewall.InboundRules)); err != nil { + return fmt.Errorf("[DEBUG] Error setting Firewall inbound_rule error: %#v", err) + } + + if err := d.Set("outbound_rule", flattenFirewallOutboundRules(d, firewall.OutboundRules)); err != nil { + return fmt.Errorf("[DEBUG] Error setting Firewall outbound_rule error: %#v", err) + } return nil } @@ -287,44 +293,41 @@ func firewallRequest(d *schema.ResourceData, client *godo.Client) (*godo.Firewal } // Get inbound_rules - opts.InboundRules = firewallInboundRules(d) + opts.InboundRules = expandFirewallInboundRules(d) // Get outbound_rules - opts.OutboundRules = firewallOutboundRules(d) + opts.OutboundRules = expandFirewallOutboundRules(d) return opts, nil } -func firewallInboundRules(d *schema.ResourceData) []godo.InboundRule { - rules := make([]godo.InboundRule, 0, len(d.Get("inbound_rules").([]interface{}))) - for i, rawRule := range d.Get("inbound_rules").([]interface{}) { +func expandFirewallInboundRules(d *schema.ResourceData) []godo.InboundRule { + rules := make([]godo.InboundRule, 0, len(d.Get("inbound_rule").([]interface{}))) + for _, rawRule := range d.Get("inbound_rule").([]interface{}) { var src godo.Sources rule := rawRule.(map[string]interface{}) - key := fmt.Sprintf("inbound_rules.%d.source_addresses", i) - if vv, ok := d.GetOk(key); ok { - for _, v := range vv.([]interface{}) { - src.Addresses = append(src.Addresses, v.(string)) - } + + sourceAddresses := rule["source_addresses"].([]interface{}) + for _, address := range sourceAddresses { + src.Addresses = append(src.Addresses, address.(string)) } - key = fmt.Sprintf("inbound_rules.%d.source_tags", i) - if vv, ok := d.GetOk(key); ok { - for _, v := range vv.([]interface{}) { - src.Tags = append(src.Tags, v.(string)) - } + + sourceTags := rule["source_tags"].([]interface{}) + for _, tag := range sourceTags { + src.Tags = append(src.Tags, tag.(string)) } - key = fmt.Sprintf("inbound_rules.%d.source_droplet_ids", i) - if vv, ok := d.GetOk(key); ok { - for _, v := range vv.([]interface{}) { - src.DropletIDs = append(src.DropletIDs, v.(int)) - } + + dropletIds := rule["source_droplet_ids"].([]interface{}) + for _, dropletId := range dropletIds { + src.DropletIDs = append(src.DropletIDs, dropletId.(int)) } - key = fmt.Sprintf("inbound_rules.%d.source_load_balancer_uids", i) - if vv, ok := d.GetOk(key); ok { - for _, v := range vv.([]interface{}) { - src.LoadBalancerUIDs = append(src.LoadBalancerUIDs, v.(string)) - } + + lbIds := rule["source_load_balancer_uids"].([]interface{}) + for _, lbId := range lbIds { + src.LoadBalancerUIDs = append(src.LoadBalancerUIDs, lbId.(string)) } + r := godo.InboundRule{ Protocol: rule["protocol"].(string), PortRange: rule["port_range"].(string), @@ -335,36 +338,33 @@ func firewallInboundRules(d *schema.ResourceData) []godo.InboundRule { return rules } -func firewallOutboundRules(d *schema.ResourceData) []godo.OutboundRule { - rules := make([]godo.OutboundRule, 0, len(d.Get("outbound_rules").([]interface{}))) - for i, rawRule := range d.Get("outbound_rules").([]interface{}) { +func expandFirewallOutboundRules(d *schema.ResourceData) []godo.OutboundRule { + rules := make([]godo.OutboundRule, 0, len(d.Get("outbound_rule").([]interface{}))) + for _, rawRule := range d.Get("outbound_rule").([]interface{}) { var dest godo.Destinations rule := rawRule.(map[string]interface{}) - key := fmt.Sprintf("outbound_rules.%d.destination_addresses", i) - if vv, ok := d.GetOk(key); ok { - for _, v := range vv.([]interface{}) { - dest.Addresses = append(dest.Addresses, v.(string)) - } + + destinationAddresses := rule["destination_addresses"].([]interface{}) + for _, address := range destinationAddresses { + dest.Addresses = append(dest.Addresses, address.(string)) } - key = fmt.Sprintf("outbound_rules.%d.destination_tags", i) - if vv, ok := d.GetOk(key); ok { - for _, v := range vv.([]interface{}) { - dest.Tags = append(dest.Tags, v.(string)) - } + + destinationTags := rule["destination_tags"].([]interface{}) + for _, tag := range destinationTags { + dest.Addresses = append(dest.Tags, tag.(string)) } - key = fmt.Sprintf("outbound_rules.%d.destination_droplet_ids", i) - if vv, ok := d.GetOk(key); ok { - for _, v := range vv.([]interface{}) { - dest.DropletIDs = append(dest.DropletIDs, v.(int)) - } + + dropletIds := rule["destination_droplet_ids"].([]interface{}) + for _, dropletId := range dropletIds { + dest.DropletIDs = append(dest.DropletIDs, dropletId.(int)) } - key = fmt.Sprintf("outbound_rules.%d.destination_load_balancer_uids", i) - if vv, ok := d.GetOk(key); ok { - for _, v := range vv.([]interface{}) { - dest.LoadBalancerUIDs = append(dest.LoadBalancerUIDs, v.(string)) - } + + lbIds := rule["destination_load_balancer_uids"].([]interface{}) + for _, lbId := range lbIds { + dest.LoadBalancerUIDs = append(dest.LoadBalancerUIDs, lbId.(string)) } + r := godo.OutboundRule{ Protocol: rule["protocol"].(string), PortRange: rule["port_range"].(string), @@ -388,12 +388,16 @@ func firewallPendingChanges(d *schema.ResourceData, firewall *godo.Firewall) []i return remote } -func matchFirewallInboundRules(d *schema.ResourceData, firewall *godo.Firewall) []interface{} { +func flattenFirewallInboundRules(d *schema.ResourceData, rules []godo.InboundRule) []interface{} { + if rules == nil { + return nil + } + // Prepare the data. - local := d.Get("inbound_rules").([]interface{}) - remote := make([]interface{}, 0, len(firewall.InboundRules)) + local := d.Get("inbound_rule").([]interface{}) + remote := make([]interface{}, 0, len(rules)) remoteMap := make(map[int]map[string]interface{}) - for _, rule := range firewall.InboundRules { + for _, rule := range rules { rawRule := map[string]interface{}{ "protocol": rule.Protocol, "port_range": rule.PortRange, @@ -414,7 +418,7 @@ func matchFirewallInboundRules(d *schema.ResourceData, firewall *godo.Firewall) // Update the local rules to only contains rules match // to the remote rules. - match := make([]interface{}, 0, len(firewall.InboundRules)) + match := make([]interface{}, 0, len(rules)) for _, rawRule := range local { local := rawRule.(map[string]interface{}) protocol := local["protocol"].(string) @@ -450,12 +454,12 @@ func matchFirewallInboundRules(d *schema.ResourceData, firewall *godo.Firewall) return match } -func matchFirewallOutboundRules(d *schema.ResourceData, firewall *godo.Firewall) []interface{} { +func flattenFirewallOutboundRules(d *schema.ResourceData, rules []godo.OutboundRule) []interface{} { // Prepare the data. - local := d.Get("outbound_rules").([]interface{}) - remote := make([]interface{}, 0, len(firewall.OutboundRules)) + local := d.Get("outbound_rule").([]interface{}) + remote := make([]interface{}, 0, len(rules)) remoteMap := make(map[int]map[string]interface{}) - for _, rule := range firewall.OutboundRules { + for _, rule := range rules { rawRule := map[string]interface{}{ "protocol": rule.Protocol, "port_range": rule.PortRange, @@ -476,7 +480,7 @@ func matchFirewallOutboundRules(d *schema.ResourceData, firewall *godo.Firewall) // Update the local rules to only contains rules match // to the remote rules. - match := make([]interface{}, 0, len(firewall.OutboundRules)) + match := make([]interface{}, 0, len(rules)) for _, rawRule := range local { local := rawRule.(map[string]interface{}) protocol := local["protocol"].(string) diff --git a/digitalocean/resource_digitalocean_firewall_test.go b/digitalocean/resource_digitalocean_firewall_test.go index b1e7b5ad..86942ae3 100644 --- a/digitalocean/resource_digitalocean_firewall_test.go +++ b/digitalocean/resource_digitalocean_firewall_test.go @@ -11,204 +11,271 @@ import ( "github.com/hashicorp/terraform/terraform" ) -func TestAccDigitalOceanFirewall_Basic(t *testing.T) { - tests := []struct { - description string - firewallName string - config string - checkers []resource.TestCheckFunc - }{ - { - description: "only allow inbound SSH(TCP/22)", - firewallName: fmt.Sprintf("foobar-test-terraform-firewall-%s", acctest.RandString(10)), - config: ` - resource "digitalocean_firewall" "foobar" { +func TestAccDigitalOceanFirewall_AllowOnlyInbound(t *testing.T) { + rName := acctest.RandString(10) + var firewall godo.Firewall + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDigitalOceanFirewallDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDigitalOceanFirewallConfig_OnlyInbound(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDigitalOceanFirewallExists("digitalocean_firewall.foobar", &firewall), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.#", "1"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.port_range", "22"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.protocol", "tcp"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.source_addresses.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.source_addresses.0", "0.0.0.0/0"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.source_addresses.1", "::/0"), + ), + }, + }, + }) +} + +func TestAccDigitalOceanFirewall_AllowMultipleInbound(t *testing.T) { + rName := acctest.RandString(10) + var firewall godo.Firewall + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDigitalOceanFirewallDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDigitalOceanFirewallConfig_OnlyMultipleInbound(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDigitalOceanFirewallExists("digitalocean_firewall.foobar", &firewall), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.port_range", "22"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.protocol", "tcp"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.source_addresses.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.source_addresses.0", "0.0.0.0/0"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.source_addresses.1", "::/0"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.1.port_range", "80"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.1.protocol", "tcp"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.1.source_addresses.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.1.source_addresses.0", "1.2.3.0/24"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.1.source_addresses.1", "2002::/16"), + ), + }, + }, + }) +} + +func TestAccDigitalOceanFirewall_AllowOnlyOutbound(t *testing.T) { + rName := acctest.RandString(10) + var firewall godo.Firewall + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDigitalOceanFirewallDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDigitalOceanFirewallConfig_OnlyOutbound(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDigitalOceanFirewallExists("digitalocean_firewall.foobar", &firewall), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.#", "1"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.port_range", "22"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.protocol", "tcp"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.destination_addresses.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.destination_addresses.0", "0.0.0.0/0"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.destination_addresses.1", "::/0"), + ), + }, + }, + }) +} + +func TestAccDigitalOceanFirewall_AllowMultipleOutbound(t *testing.T) { + rName := acctest.RandString(10) + var firewall godo.Firewall + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDigitalOceanFirewallDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDigitalOceanFirewallConfig_OnlyMultipleOutbound(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDigitalOceanFirewallExists("digitalocean_firewall.foobar", &firewall), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.port_range", "22"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.protocol", "tcp"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.destination_addresses.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.destination_addresses.0", "192.168.1.0/24"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.destination_addresses.1", "2002:1001::/48"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.1.port_range", "53"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.1.protocol", "udp"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.1.destination_addresses.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.1.destination_addresses.0", "1.2.3.0/24"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.1.destination_addresses.1", "2002::/16"), + ), + }, + }, + }) +} + +func TestAccDigitalOceanFirewall_MultipleInboundAndOutbound(t *testing.T) { + rName := acctest.RandString(10) + var firewall godo.Firewall + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDigitalOceanFirewallDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDigitalOceanFirewallConfig_MultipleInboundAndOutbound(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckDigitalOceanFirewallExists("digitalocean_firewall.foobar", &firewall), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.1.port_range", "443"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.1.protocol", "tcp"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.1.source_addresses.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.1.source_addresses.0", "192.168.1.0/24"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.1.source_addresses.1", "2002:1001:1:2::/64"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.port_range", "22"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.protocol", "tcp"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.source_addresses.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.source_addresses.0", "0.0.0.0/0"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rule.0.source_addresses.1", "::/0"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.port_range", "443"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.protocol", "tcp"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.destination_addresses.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.destination_addresses.0", "192.168.1.0/24"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.0.destination_addresses.1", "2002:1001:1:2::/64"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.1.port_range", "53"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.1.protocol", "udp"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.1.destination_addresses.#", "2"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.1.destination_addresses.0", "0.0.0.0/0"), + resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rule.1.destination_addresses.1", "::/0"), + ), + }, + }, + }) +} + +func TestAccDigitalOceanFirewall_ImportMultipleRules(t *testing.T) { + resourceName := "digitalocean_firewall.foobar" + rName := acctest.RandString(10) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDigitalOceanFirewallDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDigitalOceanFirewallConfig_MultipleInboundAndOutbound(rName), + }, + + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccDigitalOceanFirewallConfig_OnlyInbound(rName string) string { + return fmt.Sprintf(` + resource "digitalocean_firewall" "foobar" { name = "%s" - inbound_rules = [ - { + inbound_rule { protocol = "tcp" port_range = "22" source_addresses = ["0.0.0.0/0", "::/0"] - }, - ] - }`, - checkers: []resource.TestCheckFunc{ - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.#", "1"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.port_range", "22"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.protocol", "tcp"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.source_addresses.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.source_addresses.0", "0.0.0.0/0"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.source_addresses.1", "::/0"), - }, - }, - { - description: "only allow outbound SSH(TCP/22)", - firewallName: fmt.Sprintf("foobar-test-terraform-firewall-%s", acctest.RandString(10)), - config: ` - resource "digitalocean_firewall" "foobar" { + } + + } + `, rName) +} + +func testAccDigitalOceanFirewallConfig_OnlyOutbound(rName string) string { + return fmt.Sprintf(` + resource "digitalocean_firewall" "foobar" { name = "%s" - outbound_rules = [ - { + outbound_rule { protocol = "tcp" port_range = "22" destination_addresses = ["0.0.0.0/0", "::/0"] - }, - ] - }`, - checkers: []resource.TestCheckFunc{ - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.#", "1"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.port_range", "22"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.protocol", "tcp"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.destination_addresses.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.destination_addresses.0", "0.0.0.0/0"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.destination_addresses.1", "::/0"), - }, - }, - { - description: "only allow inbound SSH(TCP/22) and HTTP(TCP/80)", - firewallName: fmt.Sprintf("foobar-test-terraform-firewall-%s", acctest.RandString(10)), - config: ` - resource "digitalocean_firewall" "foobar" { + } + + } + `, rName) +} + +func testAccDigitalOceanFirewallConfig_OnlyMultipleInbound(rName string) string { + return fmt.Sprintf(` + resource "digitalocean_firewall" "foobar" { name = "%s" - inbound_rules = [ - { + inbound_rule { protocol = "tcp" port_range = "22" source_addresses = ["0.0.0.0/0", "::/0"] - }, - { + } + inbound_rule { protocol = "tcp" port_range = "80" source_addresses = ["1.2.3.0/24", "2002::/16"] - }, - ] - }`, - checkers: []resource.TestCheckFunc{ - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.port_range", "22"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.protocol", "tcp"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.source_addresses.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.source_addresses.0", "0.0.0.0/0"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.source_addresses.1", "::/0"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.1.port_range", "80"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.1.protocol", "tcp"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.1.source_addresses.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.1.source_addresses.0", "1.2.3.0/24"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.1.source_addresses.1", "2002::/16"), - }, - }, - { - description: "only allow outbound SSH(TCP/22) and DNS(UDP/53)", - firewallName: fmt.Sprintf("foobar-test-terraform-firewall-%s", acctest.RandString(10)), - config: ` - resource "digitalocean_firewall" "foobar" { + } + + } + `, rName) +} + +func testAccDigitalOceanFirewallConfig_OnlyMultipleOutbound(rName string) string { + return fmt.Sprintf(` + resource "digitalocean_firewall" "foobar" { name = "%s" - outbound_rules = [ - { + outbound_rule { protocol = "tcp" port_range = "22" destination_addresses = ["192.168.1.0/24", "2002:1001::/48"] - }, - { + } + outbound_rule { protocol = "udp" port_range = "53" destination_addresses = ["1.2.3.0/24", "2002::/16"] - }, - ] - }`, - checkers: []resource.TestCheckFunc{ - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.port_range", "22"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.protocol", "tcp"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.destination_addresses.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.destination_addresses.0", "192.168.1.0/24"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.destination_addresses.1", "2002:1001::/48"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.1.port_range", "53"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.1.protocol", "udp"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.1.destination_addresses.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.1.destination_addresses.0", "1.2.3.0/24"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.1.destination_addresses.1", "2002::/16"), - }, - }, - { - description: "allow inbound and outbound HTTPS(TCP/443), inbound SSH(TCP/22), and outbound DNS(UDP/53)", - firewallName: fmt.Sprintf("foobar-test-terraform-firewall-%s", acctest.RandString(10)), - config: ` - resource "digitalocean_firewall" "foobar" { + } + + } + `, rName) +} + +func testAccDigitalOceanFirewallConfig_MultipleInboundAndOutbound(rName string) string { + return fmt.Sprintf(` + resource "digitalocean_firewall" "foobar" { name = "%s" - inbound_rules = [ - { - protocol = "tcp" - port_range = "443" - source_addresses = ["192.168.1.0/24", "2002:1001:1:2::/64"] - }, - { + inbound_rule { protocol = "tcp" port_range = "22" source_addresses = ["0.0.0.0/0", "::/0"] - }, - ] - outbound_rules = [ - { + } + inbound_rule { + protocol = "tcp" + port_range = "443" + source_addresses = ["192.168.1.0/24", "2002:1001:1:2::/64"] + } + outbound_rule { protocol = "tcp" port_range = "443" destination_addresses = ["192.168.1.0/24", "2002:1001:1:2::/64"] - }, - { + } + outbound_rule { protocol = "udp" port_range = "53" destination_addresses = ["0.0.0.0/0", "::/0"] - }, - ] - }`, - checkers: []resource.TestCheckFunc{ - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.port_range", "443"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.protocol", "tcp"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.source_addresses.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.source_addresses.0", "192.168.1.0/24"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.0.source_addresses.1", "2002:1001:1:2::/64"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.1.port_range", "22"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.1.protocol", "tcp"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.1.source_addresses.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.1.source_addresses.0", "0.0.0.0/0"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "inbound_rules.1.source_addresses.1", "::/0"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.port_range", "443"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.protocol", "tcp"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.destination_addresses.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.destination_addresses.0", "192.168.1.0/24"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.0.destination_addresses.1", "2002:1001:1:2::/64"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.1.port_range", "53"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.1.protocol", "udp"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.1.destination_addresses.#", "2"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.1.destination_addresses.0", "0.0.0.0/0"), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "outbound_rules.1.destination_addresses.1", "::/0"), - }, - }, - } + } - var firewall godo.Firewall - for _, tt := range tests { - t.Run(tt.description, func(t *testing.T) { - checkers := []resource.TestCheckFunc{ - testAccCheckDigitalOceanFirewallExists("digitalocean_firewall.foobar", &firewall), - resource.TestCheckResourceAttr("digitalocean_firewall.foobar", "name", tt.firewallName), } - checkers = append(checkers, tt.checkers...) - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckDigitalOceanFirewallDestroy, - Steps: []resource.TestStep{ - { - Config: fmt.Sprintf(tt.config, tt.firewallName), - Check: resource.ComposeTestCheckFunc(checkers...), - }, - }, - }) - }) - } + `, rName) } func testAccCheckDigitalOceanFirewallDestroy(s *terraform.State) error {