Skip to content

Commit

Permalink
Merge pull request #16399 from hashicorp/f-network-firewall-vpc-endpo…
Browse files Browse the repository at this point in the history
…ints

resource/networkfirewall_firewall: add vpc endpoint information (FirewallStatus)
  • Loading branch information
anGie44 authored Nov 25, 2020
2 parents d6cbd6b + 754d215 commit 1c5dad9
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 0 deletions.
4 changes: 4 additions & 0 deletions aws/internal/service/networkfirewall/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ func FirewallUpdated(ctx context.Context, conn *networkfirewall.NetworkFirewall,
Target: []string{networkfirewall.FirewallStatusValueReady},
Refresh: FirewallUpdatedStatus(ctx, conn, arn),
Timeout: FirewallTimeout,
// Delay added to account for Associate/DisassociateSubnet calls that return
// a READY status immediately after the method is called instead of immediately
// returning PROVISIONING
Delay: 30 * time.Second,
}

outputRaw, err := stateConf.WaitForState()
Expand Down
86 changes: 86 additions & 0 deletions aws/resource_aws_networkfirewall_firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/aws/aws-sdk-go/service/networkfirewall"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/hashcode"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
Expand All @@ -27,6 +28,12 @@ func resourceAwsNetworkFirewallFirewall() *schema.Resource {
StateContext: schema.ImportStatePassthroughContext,
},

CustomizeDiff: customdiff.Sequence(
customdiff.ComputedIf("firewall_status", func(ctx context.Context, diff *schema.ResourceDiff, meta interface{}) bool {
return diff.HasChange("subnet_mapping")
}),
),

Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Expand All @@ -50,6 +57,42 @@ func resourceAwsNetworkFirewallFirewall() *schema.Resource {
Type: schema.TypeBool,
Optional: true,
},
"firewall_status": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sync_states": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"availability_zone": {
Type: schema.TypeString,
Computed: true,
},
"attachment": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"endpoint_id": {
Type: schema.TypeString,
Computed: true,
},
"subnet_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
},
},
},
},
},
"name": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -162,6 +205,7 @@ func resourceAwsNetworkFirewallFirewallRead(ctx context.Context, d *schema.Resou
d.Set("name", firewall.FirewallName)
d.Set("firewall_policy_arn", firewall.FirewallPolicyArn)
d.Set("firewall_policy_change_protection", firewall.FirewallPolicyChangeProtection)
d.Set("firewall_status", flattenNetworkFirewallFirewallStatus(output.FirewallStatus))
d.Set("subnet_change_protection", firewall.SubnetChangeProtection)
d.Set("update_token", output.UpdateToken)
d.Set("vpc_id", firewall.VpcId)
Expand Down Expand Up @@ -380,6 +424,48 @@ func expandNetworkFirewallSubnetMappingIds(l []interface{}) []string {
return ids
}

func flattenNetworkFirewallFirewallStatus(status *networkfirewall.FirewallStatus) []interface{} {
if status == nil {
return nil
}

m := map[string]interface{}{
"sync_states": flattenNetworkFirewallSyncStates(status.SyncStates),
}

return []interface{}{m}
}

func flattenNetworkFirewallSyncStates(s map[string]*networkfirewall.SyncState) []interface{} {
if s == nil {
return nil
}

syncStates := make([]interface{}, 0, len(s))
for k, v := range s {
m := map[string]interface{}{
"availability_zone": k,
"attachment": flattenNetworkFirewallSyncStateAttachment(v.Attachment),
}
syncStates = append(syncStates, m)
}

return syncStates
}

func flattenNetworkFirewallSyncStateAttachment(a *networkfirewall.Attachment) []interface{} {
if a == nil {
return nil
}

m := map[string]interface{}{
"endpoint_id": aws.StringValue(a.EndpointId),
"subnet_id": aws.StringValue(a.SubnetId),
}

return []interface{}{m}
}

func flattenNetworkFirewallSubnetMappings(sm []*networkfirewall.SubnetMapping) []interface{} {
mappings := make([]interface{}, 0, len(sm))
for _, s := range sm {
Expand Down
29 changes: 29 additions & 0 deletions aws/resource_aws_networkfirewall_firewall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log"
"regexp"
"testing"

"github.com/aws/aws-sdk-go/aws"
Expand Down Expand Up @@ -97,11 +98,19 @@ func TestAccAwsNetworkFirewallFirewall_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "delete_protection", "false"),
resource.TestCheckResourceAttr(resourceName, "description", ""),
resource.TestCheckResourceAttrPair(resourceName, "firewall_policy_arn", policyResourceName, "arn"),
resource.TestCheckResourceAttr(resourceName, "firewall_status.#", "1"),
resource.TestCheckResourceAttr(resourceName, "firewall_status.0.sync_states.#", "1"),
resource.TestCheckTypeSetElemAttrPair(resourceName, "firewall_status.0.sync_states.*.availability_zone", subnetResourceName, "availability_zone"),
resource.TestMatchTypeSetElemNestedAttrs(resourceName, "firewall_status.0.sync_states.*", map[string]*regexp.Regexp{
"attachment.0.endpoint_id": regexp.MustCompile(`vpce-`),
}),
resource.TestCheckTypeSetElemAttrPair(resourceName, "firewall_status.0.sync_states.*.attachment.0.subnet_id", subnetResourceName, "id"),
resource.TestCheckResourceAttr(resourceName, "name", rName),
resource.TestCheckResourceAttrPair(resourceName, "vpc_id", vpcResourceName, "id"),
resource.TestCheckResourceAttr(resourceName, "subnet_mapping.#", "1"),
tfawsresource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_mapping.*.subnet_id", subnetResourceName, "id"),
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
resource.TestCheckResourceAttrSet(resourceName, "update_token"),
),
},
{
Expand Down Expand Up @@ -216,6 +225,13 @@ func TestAccAwsNetworkFirewallFirewall_subnetMappings_updateSubnet(t *testing.T)
Config: testAccNetworkFirewallFirewall_updateSubnet(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsNetworkFirewallFirewallExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "firewall_status.#", "1"),
resource.TestCheckResourceAttr(resourceName, "firewall_status.0.sync_states.#", "1"),
resource.TestCheckTypeSetElemAttrPair(resourceName, "firewall_status.0.sync_states.*.availability_zone", updateSubnetResourceName, "availability_zone"),
resource.TestMatchTypeSetElemNestedAttrs(resourceName, "firewall_status.0.sync_states.*", map[string]*regexp.Regexp{
"attachment.0.endpoint_id": regexp.MustCompile(`vpce-`),
}),
resource.TestCheckTypeSetElemAttrPair(resourceName, "firewall_status.0.sync_states.*.attachment.0.subnet_id", updateSubnetResourceName, "id"),
resource.TestCheckResourceAttr(resourceName, "subnet_mapping.#", "1"),
tfawsresource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_mapping.*.subnet_id", updateSubnetResourceName, "id"),
),
Expand Down Expand Up @@ -252,6 +268,12 @@ func TestAccAwsNetworkFirewallFirewall_subnetMappings_updateMultipleSubnets(t *t
Config: testAccNetworkFirewallFirewall_updateMultipleSubnets(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsNetworkFirewallFirewallExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "firewall_status.#", "1"),
resource.TestCheckResourceAttr(resourceName, "firewall_status.0.sync_states.#", "2"),
resource.TestCheckTypeSetElemAttrPair(resourceName, "firewall_status.0.sync_states.*.availability_zone", subnetResourceName, "availability_zone"),
resource.TestCheckTypeSetElemAttrPair(resourceName, "firewall_status.0.sync_states.*.attachment.0.subnet_id", subnetResourceName, "id"),
resource.TestCheckTypeSetElemAttrPair(resourceName, "firewall_status.0.sync_states.*.availability_zone", updateSubnetResourceName, "availability_zone"),
resource.TestCheckTypeSetElemAttrPair(resourceName, "firewall_status.0.sync_states.*.attachment.0.subnet_id", updateSubnetResourceName, "id"),
resource.TestCheckResourceAttr(resourceName, "subnet_mapping.#", "2"),
tfawsresource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_mapping.*.subnet_id", subnetResourceName, "id"),
tfawsresource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_mapping.*.subnet_id", updateSubnetResourceName, "id"),
Expand All @@ -261,6 +283,13 @@ func TestAccAwsNetworkFirewallFirewall_subnetMappings_updateMultipleSubnets(t *t
Config: testAccNetworkFirewallFirewall_basic(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsNetworkFirewallFirewallExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "firewall_status.#", "1"),
resource.TestCheckResourceAttr(resourceName, "firewall_status.0.sync_states.#", "1"),
resource.TestCheckTypeSetElemAttrPair(resourceName, "firewall_status.0.sync_states.*.availability_zone", subnetResourceName, "availability_zone"),
resource.TestMatchTypeSetElemNestedAttrs(resourceName, "firewall_status.0.sync_states.*", map[string]*regexp.Regexp{
"attachment.0.endpoint_id": regexp.MustCompile(`vpce-`),
}),
resource.TestCheckTypeSetElemAttrPair(resourceName, "firewall_status.0.sync_states.*.attachment.0.subnet_id", subnetResourceName, "id"),
resource.TestCheckResourceAttr(resourceName, "subnet_mapping.#", "1"),
tfawsresource.TestCheckTypeSetElemAttrPair(resourceName, "subnet_mapping.*.subnet_id", subnetResourceName, "id"),
),
Expand Down
7 changes: 7 additions & 0 deletions website/docs/r/networkfirewall_firewall.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ In addition to all arguments above, the following attributes are exported:

* `arn` - The Amazon Resource Name (ARN) that identifies the firewall.

* `firewall_status` - Nested list of information about the current status of the firewall.
* `sync_states` - Set of subnets configured for use by the firewall.
* `attachment` - Nested list describing the attachment status of the firewall's association with a single VPC subnet.
* `endpoint_id` - The identifier of the firewall endpoint that AWS Network Firewall has instantiated in the subnet. You use this to identify the firewall endpoint in the VPC route tables, when you redirect the VPC traffic through the endpoint.
* `subnet_id` - The unique identifier of the subnet that you've specified to be used for a firewall endpoint.
* `availability_zone` - The Availability Zone where the subnet is configured.

* `update_token` - A string token used when updating a firewall.

## Import
Expand Down

0 comments on commit 1c5dad9

Please sign in to comment.