Skip to content

Commit b797678

Browse files
Cezarus27Dawid212
authored andcommitted
Feature gap: Add missed enable_flow_logs & state to subnetwork (GoogleCloudPlatform#13093)
Signed-off-by: Cezary Sobczak <[email protected]>
1 parent dfdb6df commit b797678

File tree

7 files changed

+246
-6
lines changed

7 files changed

+246
-6
lines changed

mmv1/products/compute/Subnetwork.yaml

+22
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,14 @@ properties:
349349
isn't supported if the subnet `purpose` field is set to subnetwork is
350350
`REGIONAL_MANAGED_PROXY` or `GLOBAL_MANAGED_PROXY`.
351351
send_empty_value: true
352+
default_from_api: true
352353
update_url: 'projects/{{project}}/regions/{{region}}/subnetworks/{{name}}'
353354
update_verb: 'PATCH'
354355
update_id: 'logConfig'
355356
fingerprint_name: 'fingerprint'
356357
custom_flatten: 'templates/terraform/custom_flatten/subnetwork_log_config.go.tmpl'
357358
custom_expand: 'templates/terraform/custom_expand/subnetwork_log_config.go.tmpl'
359+
diff_suppress_func: 'subnetworkLogConfigDiffSuppress'
358360
properties:
359361
- name: 'aggregationInterval'
360362
type: Enum
@@ -504,3 +506,23 @@ properties:
504506
update_url: 'projects/{{project}}/regions/{{region}}/subnetworks/{{name}}'
505507
update_verb: 'PATCH'
506508
fingerprint_name: 'fingerprint'
509+
- name: 'enableFlowLogs'
510+
type: Boolean
511+
description: |
512+
Whether to enable flow logging for this subnetwork. If this field is not explicitly set,
513+
it will not appear in get listings. If not set the default behavior is determined by the
514+
org policy, if there is no org policy specified, then it will default to disabled.
515+
This field isn't supported if the subnet purpose field is set to REGIONAL_MANAGED_PROXY.
516+
default_from_api: true
517+
send_empty_value: true
518+
update_url: 'projects/{{project}}/regions/{{region}}/subnetworks/{{name}}'
519+
update_verb: 'PATCH'
520+
fingerprint_name: 'fingerprint'
521+
- name: 'state'
522+
type: Enum
523+
description: |
524+
'The state of the subnetwork, which can be one of the following values:
525+
READY: Subnetwork is created and ready to use DRAINING: only applicable to subnetworks that have the purpose
526+
set to INTERNAL_HTTPS_LOAD_BALANCER and indicates that connections to the load balancer are being drained.
527+
A subnetwork that is draining cannot be used or modified until it reaches a status of READY'
528+
output: true

mmv1/templates/terraform/constants/subnetwork.tmpl

+11-1
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,14 @@ func sendSecondaryIpRangeIfEmptyDiff(_ context.Context, diff *schema.ResourceDif
4747
}
4848

4949
return nil
50-
}
50+
}
51+
52+
// DiffSuppressFunc for fields inside `log_config`.
53+
func subnetworkLogConfigDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
54+
// If the enable_flow_logs is not enabled, we don't need to check for differences.
55+
if enable_flow_logs := d.Get("enable_flow_logs"); !enable_flow_logs.(bool) {
56+
return true
57+
}
58+
59+
return false
60+
}

mmv1/templates/terraform/custom_expand/subnetwork_log_config.go.tmpl

+6-4
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ func expand{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d tpgresource.T
1616
if len(l) == 0 || l[0] == nil {
1717
purpose, ok := d.GetOkExists("purpose")
1818

19-
if ok &&(purpose.(string) == "REGIONAL_MANAGED_PROXY" || purpose.(string) == "GLOBAL_MANAGED_PROXY" || purpose.(string) == "INTERNAL_HTTPS_LOAD_BALANCER") {
19+
if ok && (purpose.(string) == "REGIONAL_MANAGED_PROXY" || purpose.(string) == "GLOBAL_MANAGED_PROXY" || purpose.(string) == "INTERNAL_HTTPS_LOAD_BALANCER") {
2020
// Subnetworks for regional L7 ILB/XLB or cross-regional L7 ILB do not accept any values for logConfig
2121
return nil, nil
2222
}
23-
// send enable = false to ensure logging is disabled if there is no config
24-
transformed["enable"] = false
23+
24+
// set enable field basing on the enable_flow_logs field. It's needed for case when enable_flow_logs
25+
// is set to true to avoid conflict with the API. In that case API will return default values for log_config
26+
transformed["enable"] = d.Get("enable_flow_logs")
2527
return transformed, nil
2628
}
2729

@@ -34,7 +36,7 @@ func expand{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d tpgresource.T
3436
transformed["flowSampling"] = original["flow_sampling"]
3537
transformed["metadata"] = original["metadata"]
3638
transformed["filterExpr"] = original["filter_expr"]
37-
39+
3840
// make it JSON marshallable
3941
transformed["metadataFields"] = original["metadata_fields"].(*schema.Set).List()
4042

mmv1/templates/terraform/custom_flatten/subnetwork_log_config.go.tmpl

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ func flatten{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d *schema.Reso
3939
transformed["metadata_fields"] = nil
4040
}
4141
transformed["filter_expr"] = original["filterExpr"]
42-
42+
4343
return []interface{}{transformed}
4444
}

mmv1/third_party/terraform/services/compute/resource_compute_subnetwork_test.go.tmpl

+204
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,66 @@ func TestAccComputeSubnetwork_internal_ipv6(t *testing.T) {
496496
})
497497
}
498498

499+
func TestAccComputeSubnetwork_enableFlowLogs(t *testing.T) {
500+
t.Parallel()
501+
var subnetwork compute.Subnetwork
502+
503+
cnName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10))
504+
subnetworkName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10))
505+
506+
acctest.VcrTest(t, resource.TestCase{
507+
PreCheck: func() { acctest.AccTestPreCheck(t) },
508+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
509+
CheckDestroy: testAccCheckComputeSubnetworkDestroyProducer(t),
510+
Steps: []resource.TestStep{
511+
{
512+
Config: testAccComputeSubnetwork_enableFlowLogs(cnName, subnetworkName, true),
513+
Check: resource.ComposeTestCheckFunc(
514+
testAccCheckComputeSubnetworkExists(t, "google_compute_subnetwork.subnetwork", &subnetwork),
515+
testAccCheckComputeSubnetworkIfLogConfigExists(&subnetwork, "google_compute_subnetwork.subnetwork"),
516+
testAccCheckComputeSubnetworkLogConfig(&subnetwork, "log_config.0.enable", "true"),
517+
resource.TestCheckResourceAttr("google_compute_subnetwork.subnetwork", "enable_flow_logs", "true"),
518+
),
519+
},
520+
{
521+
ResourceName: "google_compute_subnetwork.subnetwork",
522+
ImportState: true,
523+
ImportStateVerify: true,
524+
},
525+
{
526+
Config: testAccComputeSubnetwork_enableFlowLogs_with_logConfig(cnName, subnetworkName, true),
527+
Check: resource.ComposeTestCheckFunc(
528+
testAccCheckComputeSubnetworkExists(t, "google_compute_subnetwork.subnetwork", &subnetwork),
529+
resource.TestCheckResourceAttr("google_compute_subnetwork.subnetwork", "enable_flow_logs", "true"),
530+
testAccCheckComputeSubnetworkLogConfig(&subnetwork, "log_config.0.enable", "true"),
531+
testAccCheckComputeSubnetworkLogConfig(&subnetwork, "log_config.0.aggregation_interval", "INTERVAL_1_MIN"),
532+
testAccCheckComputeSubnetworkLogConfig(&subnetwork, "log_config.0.metadata", "INCLUDE_ALL_METADATA"),
533+
),
534+
},
535+
{
536+
ResourceName: "google_compute_subnetwork.subnetwork",
537+
ImportState: true,
538+
ImportStateVerify: true,
539+
},
540+
{
541+
Config: testAccComputeSubnetwork_enableFlowLogs(cnName, subnetworkName, false),
542+
Check: resource.ComposeTestCheckFunc(
543+
testAccCheckComputeSubnetworkExists(t, "google_compute_subnetwork.subnetwork", &subnetwork),
544+
resource.TestCheckResourceAttr("google_compute_subnetwork.subnetwork", "enable_flow_logs", "false"),
545+
testAccCheckComputeSubnetworkLogConfig(&subnetwork, "log_config.0.enable", "false"),
546+
testAccCheckComputeSubnetworkLogConfig(&subnetwork, "log_config.0.aggregation_interval", "INTERVAL_1_MIN"),
547+
testAccCheckComputeSubnetworkLogConfig(&subnetwork, "log_config.0.metadata", "INCLUDE_ALL_METADATA"),
548+
),
549+
},
550+
{
551+
ResourceName: "google_compute_subnetwork.subnetwork",
552+
ImportState: true,
553+
ImportStateVerify: true,
554+
},
555+
},
556+
})
557+
}
558+
499559
func testAccCheckComputeSubnetworkExists(t *testing.T, n string, subnetwork *compute.Subnetwork) resource.TestCheckFunc {
500560
return func(s *terraform.State) error {
501561
rs, ok := s.RootModule().Resources[n]
@@ -556,6 +616,111 @@ func testAccCheckComputeSubnetworkHasNotSecondaryIpRange(subnetwork *compute.Sub
556616
}
557617
}
558618

619+
func testAccCheckComputeSubnetworkIfLogConfigExists(subnetwork *compute.Subnetwork, resourceName string) resource.TestCheckFunc {
620+
return func(s *terraform.State) error {
621+
// Retrieve the resource state using a fixed resource name
622+
rs, ok := s.RootModule().Resources[resourceName]
623+
if !ok {
624+
return fmt.Errorf("resource google_compute_subnetwork.subnetwork not found in state")
625+
}
626+
627+
if rs.Primary.ID == "" {
628+
return fmt.Errorf("resource ID is not set")
629+
}
630+
631+
// Ensure that the log_config exists in the API response.
632+
if subnetwork.LogConfig == nil {
633+
return fmt.Errorf("no log_config exists in subnetwork")
634+
}
635+
636+
stateAttrs := rs.Primary.Attributes
637+
638+
// Check aggregation_interval.
639+
aggInterval, ok := stateAttrs["log_config.0.aggregation_interval"]
640+
if !ok {
641+
return fmt.Errorf("aggregation_interval not found in state")
642+
}
643+
if subnetwork.LogConfig.AggregationInterval != aggInterval {
644+
return fmt.Errorf("aggregation_interval mismatch: expected %s, got %s", aggInterval, subnetwork.LogConfig.AggregationInterval)
645+
}
646+
647+
// Check flow_sampling.
648+
fsState, ok := stateAttrs["log_config.0.flow_sampling"]
649+
if !ok {
650+
return fmt.Errorf("flow_sampling not found in state")
651+
}
652+
actualFS := fmt.Sprintf("%g", subnetwork.LogConfig.FlowSampling)
653+
if actualFS != fsState {
654+
return fmt.Errorf("flow_sampling mismatch: expected %s, got %s", fsState, actualFS)
655+
}
656+
657+
// Check metadata.
658+
metadata, ok := stateAttrs["log_config.0.metadata"]
659+
if !ok {
660+
return fmt.Errorf("metadata not found in state")
661+
}
662+
if subnetwork.LogConfig.Metadata != metadata {
663+
return fmt.Errorf("metadata mismatch: expected %s, got %s", metadata, subnetwork.LogConfig.Metadata)
664+
}
665+
666+
// Optionally, check filter_expr if it exists.
667+
if subnetwork.LogConfig.FilterExpr != "" {
668+
filterExpr, ok := stateAttrs["log_config.0.filter_expr"]
669+
if !ok {
670+
return fmt.Errorf("filter_expr is set in API but not found in state")
671+
}
672+
if subnetwork.LogConfig.FilterExpr != filterExpr {
673+
return fmt.Errorf("filter_expr mismatch: expected %s, got %s", filterExpr, subnetwork.LogConfig.FilterExpr)
674+
}
675+
}
676+
677+
// Optionally, check metadata_fields if present.
678+
if len(subnetwork.LogConfig.MetadataFields) > 0 {
679+
if _, ok := stateAttrs["log_config.0.metadata_fields"]; !ok {
680+
return fmt.Errorf("metadata_fields are set in API but not found in state")
681+
}
682+
}
683+
684+
return nil
685+
}
686+
}
687+
688+
func testAccCheckComputeSubnetworkLogConfig(subnetwork *compute.Subnetwork, key, value string) resource.TestCheckFunc {
689+
return func(s *terraform.State) error {
690+
if subnetwork.LogConfig == nil {
691+
return fmt.Errorf("no log_config found")
692+
}
693+
694+
switch key {
695+
case "log_config.0.enable":
696+
if subnetwork.LogConfig.Enable != (value == "true") {
697+
return fmt.Errorf("expected %s to be '%s', got '%t'", key, value, subnetwork.LogConfig.Enable)
698+
}
699+
case "log_config.0.aggregation_interval":
700+
if subnetwork.LogConfig.AggregationInterval != value {
701+
return fmt.Errorf("expected %s to be '%s', got '%s'", key, value, subnetwork.LogConfig.AggregationInterval)
702+
}
703+
case "log_config.0.metadata":
704+
if subnetwork.LogConfig.Metadata != value {
705+
return fmt.Errorf("expected %s to be '%s', got '%s'", key, value, subnetwork.LogConfig.Metadata)
706+
}
707+
case "log_config.0.flow_sampling":
708+
flowSamplingStr := fmt.Sprintf("%g", subnetwork.LogConfig.FlowSampling)
709+
if flowSamplingStr != value {
710+
return fmt.Errorf("expected %s to be '%s', got '%s'", key, value, flowSamplingStr)
711+
}
712+
case "log_config.0.filterExpr":
713+
if subnetwork.LogConfig.FilterExpr != value {
714+
return fmt.Errorf("expected %s to be '%s', got '%s'", key, value, subnetwork.LogConfig.FilterExpr)
715+
}
716+
default:
717+
return fmt.Errorf("unknown log_config key: %s", key)
718+
}
719+
720+
return nil
721+
}
722+
}
723+
559724
func testAccComputeSubnetwork_basic(cnName, subnetwork1Name, subnetwork2Name, subnetwork3Name string) string {
560725
return fmt.Sprintf(`
561726
resource "google_compute_network" "custom-test" {
@@ -1033,3 +1198,42 @@ resource "google_compute_subnetwork" "subnetwork" {
10331198
}
10341199
`, cnName, subnetworkName)
10351200
}
1201+
1202+
func testAccComputeSubnetwork_enableFlowLogs(cnName, subnetworkName string, enableFlowLogs bool) string {
1203+
return fmt.Sprintf(`
1204+
resource "google_compute_network" "custom-test" {
1205+
name = "%s"
1206+
auto_create_subnetworks = false
1207+
}
1208+
1209+
resource "google_compute_subnetwork" "subnetwork" {
1210+
name = "%s"
1211+
ip_cidr_range = "10.0.0.0/16"
1212+
region = "us-central1"
1213+
network = google_compute_network.custom-test.self_link
1214+
enable_flow_logs = %t
1215+
}
1216+
`, cnName, subnetworkName, enableFlowLogs)
1217+
}
1218+
1219+
func testAccComputeSubnetwork_enableFlowLogs_with_logConfig(cnName, subnetworkName string, enableFlowLogs bool) string {
1220+
return fmt.Sprintf(`
1221+
resource "google_compute_network" "custom-test" {
1222+
name = "%s"
1223+
auto_create_subnetworks = false
1224+
}
1225+
1226+
resource "google_compute_subnetwork" "subnetwork" {
1227+
name = "%s"
1228+
ip_cidr_range = "10.0.0.0/16"
1229+
region = "us-central1"
1230+
network = google_compute_network.custom-test.self_link
1231+
enable_flow_logs = %t
1232+
1233+
log_config {
1234+
aggregation_interval = "INTERVAL_1_MIN"
1235+
metadata = "INCLUDE_ALL_METADATA"
1236+
}
1237+
}
1238+
`, cnName, subnetworkName, enableFlowLogs)
1239+
}

mmv1/third_party/tgc/tests/data/example_compute_subnetwork.json

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}",
2727
"data": {
2828
"ipCidrRange": "10.0.0.0/24",
29+
"enableFlowLogs": true,
2930
"logConfig": {
3031
"aggregationInterval": "INTERVAL_10_MIN",
3132
"enable": true,

mmv1/third_party/tgc/tests/data/example_compute_subnetwork.tf

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ resource "google_compute_subnetwork" "my-test-subnetwork" {
3838
region = "us-central1"
3939
network = google_compute_network.default.id
4040

41+
enable_flow_logs = true
4142
log_config {
4243
aggregation_interval = "INTERVAL_10_MIN"
4344
flow_sampling = 0.5

0 commit comments

Comments
 (0)