diff --git a/google/resource_compute_firewall.go b/google/resource_compute_firewall.go index 3e91ac3522f..9796083743d 100644 --- a/google/resource_compute_firewall.go +++ b/google/resource_compute_firewall.go @@ -152,6 +152,14 @@ network it is associated with. When set to true, the firewall rule is not enforced and the network behaves as if it did not exist. If this is unspecified, the firewall rule will be enabled.`, }, + "enable_logging": { + Type: schema.TypeBool, + Optional: true, + Description: `This field denotes whether to enable logging for a particular +firewall rule. If logging is enabled, logs will be exported to +Stackdriver.`, + }, + "priority": { Type: schema.TypeInt, Optional: true, @@ -369,6 +377,12 @@ func resourceComputeFirewallCreate(d *schema.ResourceData, meta interface{}) err } else if v, ok := d.GetOkExists("disabled"); ok || !reflect.DeepEqual(v, disabledProp) { obj["disabled"] = disabledProp } + logConfigProp, err := expandComputeFirewallLogConfig(nil, d, config) + if err != nil { + return err + } else if !isEmptyValue(reflect.ValueOf(logConfigProp)) { + obj["logConfig"] = logConfigProp + } nameProp, err := expandComputeFirewallName(d.Get("name"), d, config) if err != nil { return err @@ -497,6 +511,16 @@ func resourceComputeFirewallRead(d *schema.ResourceData, meta interface{}) error if err := d.Set("disabled", flattenComputeFirewallDisabled(res["disabled"], d)); err != nil { return fmt.Errorf("Error reading Firewall: %s", err) } + // Terraform must set the top level schema field, but since this object contains collapsed properties + // it's difficult to know what the top level should be. Instead we just loop over the map returned from flatten. + if flattenedProp := flattenComputeFirewallLogConfig(res["logConfig"], d); flattenedProp != nil { + casted := flattenedProp.([]interface{})[0] + if casted != nil { + for k, v := range casted.(map[string]interface{}) { + d.Set(k, v) + } + } + } if err := d.Set("name", flattenComputeFirewallName(res["name"], d)); err != nil { return fmt.Errorf("Error reading Firewall: %s", err) } @@ -567,6 +591,12 @@ func resourceComputeFirewallUpdate(d *schema.ResourceData, meta interface{}) err } else if v, ok := d.GetOkExists("disabled"); ok || !reflect.DeepEqual(v, disabledProp) { obj["disabled"] = disabledProp } + logConfigProp, err := expandComputeFirewallLogConfig(nil, d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("log_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, logConfigProp)) { + obj["logConfig"] = logConfigProp + } networkProp, err := expandComputeFirewallNetwork(d.Get("network"), d, config) if err != nil { return err @@ -763,6 +793,23 @@ func flattenComputeFirewallDisabled(v interface{}, d *schema.ResourceData) inter return v } +func flattenComputeFirewallLogConfig(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["enable_logging"] = + flattenComputeFirewallLogConfigEnableLogging(original["enable"], d) + return []interface{}{transformed} +} +func flattenComputeFirewallLogConfigEnableLogging(v interface{}, d *schema.ResourceData) interface{} { + return v +} + func flattenComputeFirewallName(v interface{}, d *schema.ResourceData) interface{} { return v } @@ -912,6 +959,22 @@ func expandComputeFirewallDisabled(v interface{}, d TerraformResourceData, confi return v, nil } +func expandComputeFirewallLogConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + transformed := make(map[string]interface{}) + transformedEnableLogging, err := expandComputeFirewallLogConfigEnableLogging(d.Get("enable_logging"), d, config) + if err != nil { + return nil, err + } else { + transformed["enable"] = transformedEnableLogging + } + + return transformed, nil +} + +func expandComputeFirewallLogConfigEnableLogging(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeFirewallName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google/resource_compute_firewall_test.go b/google/resource_compute_firewall_test.go index 7c7588f113c..002432d9e0b 100644 --- a/google/resource_compute_firewall_test.go +++ b/google/resource_compute_firewall_test.go @@ -196,6 +196,45 @@ func TestAccComputeFirewall_disabled(t *testing.T) { }) } +func TestAccComputeFirewall_enableLogging(t *testing.T) { + t.Parallel() + + networkName := fmt.Sprintf("firewall-test-%s", acctest.RandString(10)) + firewallName := fmt.Sprintf("firewall-test-%s", acctest.RandString(10)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeFirewallDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeFirewall_enableLogging(networkName, firewallName, false), + }, + { + ResourceName: "google_compute_firewall.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeFirewall_enableLogging(networkName, firewallName, true), + }, + { + ResourceName: "google_compute_firewall.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeFirewall_enableLogging(networkName, firewallName, false), + }, + { + ResourceName: "google_compute_firewall.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccComputeFirewall_basic(network, firewall string) string { return fmt.Sprintf(` resource "google_compute_network" "foobar" { @@ -372,3 +411,29 @@ resource "google_compute_firewall" "foobar" { } `, network, firewall) } + +func testAccComputeFirewall_enableLogging(network, firewall string, enableLogging bool) string { + enableLoggingCfg := "" + if enableLogging { + enableLoggingCfg = "enable_logging= true" + } + return fmt.Sprintf(` +resource "google_compute_network" "foobar" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_firewall" "foobar" { + name = "%s" + description = "Resource created for Terraform acceptance testing" + network = google_compute_network.foobar.name + source_tags = ["foo"] + + allow { + protocol = "icmp" + } + + %s +} +`, network, firewall, enableLoggingCfg) +} diff --git a/website/docs/r/compute_firewall.html.markdown b/website/docs/r/compute_firewall.html.markdown index 2ab70fc9201..3f6bc72f86d 100644 --- a/website/docs/r/compute_firewall.html.markdown +++ b/website/docs/r/compute_firewall.html.markdown @@ -132,6 +132,12 @@ The following arguments are supported: not enforced and the network behaves as if it did not exist. If this is unspecified, the firewall rule will be enabled. +* `enable_logging` - + (Optional) + This field denotes whether to enable logging for a particular + firewall rule. If logging is enabled, logs will be exported to + Stackdriver. + * `priority` - (Optional) Priority for this rule. This is an integer between 0 and 65535, both