Repository: GoogleCloudPlatform/terraform-validator
Pull request #96 (2019-11-09 01:17:49)

support google_container_cluster and google_container_node_pool


Patch:
diff --git a/README.md b/README.md
index 07c02214..64aff732 100644
--- a/README.md
+++ b/README.md
@@ -74,6 +74,8 @@ The follow Terraform resources are supported for running validation checks:
 - `google_compute_disk`
 - `google_compute_instance`
 - `google_compute_firewall`
+- `google_container_cluster`
+- `google_container_node_pool`
 - `google_storage_bucket`
 - `google_storage_bucket_iam_policy`
 - `google_storage_bucket_iam_binding`
diff --git a/converters/google/mappers.go b/converters/google/mappers.go
index 11147e0c..efb1934d 100644
--- a/converters/google/mappers.go
+++ b/converters/google/mappers.go
@@ -51,6 +51,8 @@ func mappers() map[string][]mapper {
 		"google_compute_instance":      {{convert: converter.GetComputeInstanceCaiObject}},
 		"google_storage_bucket":        {{convert: converter.GetStorageBucketCaiObject}},
 		"google_sql_database_instance": {{convert: converter.GetSQLDatabaseInstanceCaiObject}},
+		"google_container_cluster":     {{convert: converter.GetContainerClusterCaiObject}},
+		"google_container_node_pool":   {{convert: converter.GetContainerNodePoolCaiObject}},
 
 		// Terraform resources of type "google_project" have a 1:N relationship with CAI assets.
 		"google_project": {
diff --git a/go.mod b/go.mod
index 3d64a796..b5baa2d7 100644
--- a/go.mod
+++ b/go.mod
@@ -1,7 +1,7 @@
 module github.com/GoogleCloudPlatform/terraform-validator
 
 require (
-	github.com/GoogleCloudPlatform/terraform-google-conversion v0.0.0-20191024191752-54004ba54ac1
+	github.com/GoogleCloudPlatform/terraform-google-conversion v0.0.0-20191108204708-1cb5102f41ee
 	github.com/forseti-security/config-validator v0.0.0-20190619160113-b8fae8e864e3
 	github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
 	github.com/golang/protobuf v1.3.2
diff --git a/go.sum b/go.sum
index 67e04149..be4c8fd8 100644
--- a/go.sum
+++ b/go.sum
@@ -33,6 +33,8 @@ github.com/GoogleCloudPlatform/terraform-google-conversion v0.0.0-20190826162802
 github.com/GoogleCloudPlatform/terraform-google-conversion v0.0.0-20190826162802-791ccb94729b/go.mod h1:wa21h3G8M+QlqhWtwmocZxAWebpML3UWiRt0sTjpMOA=
 github.com/GoogleCloudPlatform/terraform-google-conversion v0.0.0-20191024191752-54004ba54ac1 h1:AzsrON1bzlhjGKg4Fyintmo7nlKCIU7iQu7F1bkEIzI=
 github.com/GoogleCloudPlatform/terraform-google-conversion v0.0.0-20191024191752-54004ba54ac1/go.mod h1:lR1nvDFcZgNcytKbe1fjtB6hITjoIUaP9YAItnaueB4=
+github.com/GoogleCloudPlatform/terraform-google-conversion v0.0.0-20191108204708-1cb5102f41ee h1:4iG9FL9nZ8Hsw5sF/arOInjC0gAZ4fl4QPOo9oL/NcQ=
+github.com/GoogleCloudPlatform/terraform-google-conversion v0.0.0-20191108204708-1cb5102f41ee/go.mod h1:lR1nvDFcZgNcytKbe1fjtB6hITjoIUaP9YAItnaueB4=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI=
 github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
diff --git a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/cloudbuild_trigger.go b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/cloudbuild_trigger.go
index 7be35faf..092893c2 100644
--- a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/cloudbuild_trigger.go
+++ b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/cloudbuild_trigger.go
@@ -39,6 +39,12 @@ func GetCloudBuildTriggerCaiObject(d TerraformResourceData, config *Config) (Ass
 
 func GetCloudBuildTriggerApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
 	obj := make(map[string]interface{})
+	nameProp, err := expandCloudBuildTriggerName(d.Get("name"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
+		obj["name"] = nameProp
+	}
 	descriptionProp, err := expandCloudBuildTriggerDescription(d.Get("description"), d, config)
 	if err != nil {
 		return nil, err
@@ -91,6 +97,10 @@ func GetCloudBuildTriggerApiObject(d TerraformResourceData, config *Config) (map
 	return obj, nil
 }
 
+func expandCloudBuildTriggerName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
 func expandCloudBuildTriggerDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
 	return v, nil
 }
diff --git a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_instance_helpers.go b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_instance_helpers.go
index 927fb8a4..abe36265 100644
--- a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_instance_helpers.go
+++ b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_instance_helpers.go
@@ -329,3 +329,21 @@ func flattenShieldedVmConfig(shieldedVmConfig *computeBeta.ShieldedVmConfig) []m
 		"enable_integrity_monitoring": shieldedVmConfig.EnableIntegrityMonitoring,
 	}}
 }
+
+func expandDisplayDevice(d *schema.ResourceData) *computeBeta.DisplayDevice {
+	if _, ok := d.GetOk("enable_display"); !ok {
+		return nil
+	}
+	return &computeBeta.DisplayDevice{
+		EnableDisplay:   d.Get("enable_display").(bool),
+		ForceSendFields: []string{"EnableDisplay"},
+	}
+}
+
+func flattenEnableDisplay(displayDevice *computeBeta.DisplayDevice) interface{} {
+	if displayDevice == nil {
+		return nil
+	}
+
+	return displayDevice.EnableDisplay
+}
diff --git a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_region_backend_service.go b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_region_backend_service.go
index b4d75d36..ca9012cf 100644
--- a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_region_backend_service.go
+++ b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_region_backend_service.go
@@ -49,24 +49,18 @@ func GetComputeRegionBackendServiceCaiObject(d TerraformResourceData, config *Co
 
 func GetComputeRegionBackendServiceApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
 	obj := make(map[string]interface{})
-	nameProp, err := expandComputeRegionBackendServiceName(d.Get("name"), d, config)
-	if err != nil {
-		return nil, err
-	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
-		obj["name"] = nameProp
-	}
-	healthChecksProp, err := expandComputeRegionBackendServiceHealthChecks(d.Get("health_checks"), d, config)
-	if err != nil {
-		return nil, err
-	} else if v, ok := d.GetOkExists("health_checks"); !isEmptyValue(reflect.ValueOf(healthChecksProp)) && (ok || !reflect.DeepEqual(v, healthChecksProp)) {
-		obj["healthChecks"] = healthChecksProp
-	}
 	backendsProp, err := expandComputeRegionBackendServiceBackend(d.Get("backend"), d, config)
 	if err != nil {
 		return nil, err
 	} else if v, ok := d.GetOkExists("backend"); !isEmptyValue(reflect.ValueOf(backendsProp)) && (ok || !reflect.DeepEqual(v, backendsProp)) {
 		obj["backends"] = backendsProp
 	}
+	connectionDrainingProp, err := expandComputeRegionBackendServiceConnectionDraining(nil, d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("connection_draining"); !isEmptyValue(reflect.ValueOf(connectionDrainingProp)) && (ok || !reflect.DeepEqual(v, connectionDrainingProp)) {
+		obj["connectionDraining"] = connectionDrainingProp
+	}
 	descriptionProp, err := expandComputeRegionBackendServiceDescription(d.Get("description"), d, config)
 	if err != nil {
 		return nil, err
@@ -79,6 +73,24 @@ func GetComputeRegionBackendServiceApiObject(d TerraformResourceData, config *Co
 	} else if v, ok := d.GetOkExists("fingerprint"); !isEmptyValue(reflect.ValueOf(fingerprintProp)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) {
 		obj["fingerprint"] = fingerprintProp
 	}
+	healthChecksProp, err := expandComputeRegionBackendServiceHealthChecks(d.Get("health_checks"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("health_checks"); !isEmptyValue(reflect.ValueOf(healthChecksProp)) && (ok || !reflect.DeepEqual(v, healthChecksProp)) {
+		obj["healthChecks"] = healthChecksProp
+	}
+	loadBalancingSchemeProp, err := expandComputeRegionBackendServiceLoadBalancingScheme(d.Get("load_balancing_scheme"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("load_balancing_scheme"); !isEmptyValue(reflect.ValueOf(loadBalancingSchemeProp)) && (ok || !reflect.DeepEqual(v, loadBalancingSchemeProp)) {
+		obj["loadBalancingScheme"] = loadBalancingSchemeProp
+	}
+	nameProp, err := expandComputeRegionBackendServiceName(d.Get("name"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
+		obj["name"] = nameProp
+	}
 	protocolProp, err := expandComputeRegionBackendServiceProtocol(d.Get("protocol"), d, config)
 	if err != nil {
 		return nil, err
@@ -91,43 +103,22 @@ func GetComputeRegionBackendServiceApiObject(d TerraformResourceData, config *Co
 	} else if v, ok := d.GetOkExists("session_affinity"); !isEmptyValue(reflect.ValueOf(sessionAffinityProp)) && (ok || !reflect.DeepEqual(v, sessionAffinityProp)) {
 		obj["sessionAffinity"] = sessionAffinityProp
 	}
-	regionProp, err := expandComputeRegionBackendServiceRegion(d.Get("region"), d, config)
-	if err != nil {
-		return nil, err
-	} else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(regionProp)) && (ok || !reflect.DeepEqual(v, regionProp)) {
-		obj["region"] = regionProp
-	}
 	timeoutSecProp, err := expandComputeRegionBackendServiceTimeoutSec(d.Get("timeout_sec"), d, config)
 	if err != nil {
 		return nil, err
 	} else if v, ok := d.GetOkExists("timeout_sec"); !isEmptyValue(reflect.ValueOf(timeoutSecProp)) && (ok || !reflect.DeepEqual(v, timeoutSecProp)) {
 		obj["timeoutSec"] = timeoutSecProp
 	}
-	connectionDrainingProp, err := expandComputeRegionBackendServiceConnectionDraining(nil, d, config)
-	if err != nil {
-		return nil, err
-	} else if v, ok := d.GetOkExists("connection_draining"); !isEmptyValue(reflect.ValueOf(connectionDrainingProp)) && (ok || !reflect.DeepEqual(v, connectionDrainingProp)) {
-		obj["connectionDraining"] = connectionDrainingProp
-	}
-	loadBalancingSchemeProp, err := expandComputeRegionBackendServiceLoadBalancingScheme(d.Get("load_balancing_scheme"), d, config)
+	regionProp, err := expandComputeRegionBackendServiceRegion(d.Get("region"), d, config)
 	if err != nil {
 		return nil, err
-	} else if v, ok := d.GetOkExists("load_balancing_scheme"); !isEmptyValue(reflect.ValueOf(loadBalancingSchemeProp)) && (ok || !reflect.DeepEqual(v, loadBalancingSchemeProp)) {
-		obj["loadBalancingScheme"] = loadBalancingSchemeProp
+	} else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(regionProp)) && (ok || !reflect.DeepEqual(v, regionProp)) {
+		obj["region"] = regionProp
 	}
 
 	return obj, nil
 }
 
-func expandComputeRegionBackendServiceName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
-	return v, nil
-}
-
-func expandComputeRegionBackendServiceHealthChecks(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
-	v = v.(*schema.Set).List()
-	return v, nil
-}
-
 func expandComputeRegionBackendServiceBackend(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
 	v = v.(*schema.Set).List()
 	l := v.([]interface{})
@@ -139,6 +130,20 @@ func expandComputeRegionBackendServiceBackend(v interface{}, d TerraformResource
 		original := raw.(map[string]interface{})
 		transformed := make(map[string]interface{})
 
+		transformedBalancingMode, err := expandComputeRegionBackendServiceBackendBalancingMode(original["balancing_mode"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedBalancingMode); val.IsValid() && !isEmptyValue(val) {
+			transformed["balancingMode"] = transformedBalancingMode
+		}
+
+		transformedCapacityScaler, err := expandComputeRegionBackendServiceBackendCapacityScaler(original["capacity_scaler"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedCapacityScaler); val.IsValid() && !isEmptyValue(val) {
+			transformed["capacityScaler"] = transformedCapacityScaler
+		}
+
 		transformedDescription, err := expandComputeRegionBackendServiceBackendDescription(original["description"], d, config)
 		if err != nil {
 			return nil, err
@@ -153,11 +158,68 @@ func expandComputeRegionBackendServiceBackend(v interface{}, d TerraformResource
 			transformed["group"] = transformedGroup
 		}
 
+		transformedMaxConnections, err := expandComputeRegionBackendServiceBackendMaxConnections(original["max_connections"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedMaxConnections); val.IsValid() && !isEmptyValue(val) {
+			transformed["maxConnections"] = transformedMaxConnections
+		}
+
+		transformedMaxConnectionsPerInstance, err := expandComputeRegionBackendServiceBackendMaxConnectionsPerInstance(original["max_connections_per_instance"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedMaxConnectionsPerInstance); val.IsValid() && !isEmptyValue(val) {
+			transformed["maxConnectionsPerInstance"] = transformedMaxConnectionsPerInstance
+		}
+
+		transformedMaxConnectionsPerEndpoint, err := expandComputeRegionBackendServiceBackendMaxConnectionsPerEndpoint(original["max_connections_per_endpoint"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedMaxConnectionsPerEndpoint); val.IsValid() && !isEmptyValue(val) {
+			transformed["maxConnectionsPerEndpoint"] = transformedMaxConnectionsPerEndpoint
+		}
+
+		transformedMaxRate, err := expandComputeRegionBackendServiceBackendMaxRate(original["max_rate"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedMaxRate); val.IsValid() && !isEmptyValue(val) {
+			transformed["maxRate"] = transformedMaxRate
+		}
+
+		transformedMaxRatePerInstance, err := expandComputeRegionBackendServiceBackendMaxRatePerInstance(original["max_rate_per_instance"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedMaxRatePerInstance); val.IsValid() && !isEmptyValue(val) {
+			transformed["maxRatePerInstance"] = transformedMaxRatePerInstance
+		}
+
+		transformedMaxRatePerEndpoint, err := expandComputeRegionBackendServiceBackendMaxRatePerEndpoint(original["max_rate_per_endpoint"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedMaxRatePerEndpoint); val.IsValid() && !isEmptyValue(val) {
+			transformed["maxRatePerEndpoint"] = transformedMaxRatePerEndpoint
+		}
+
+		transformedMaxUtilization, err := expandComputeRegionBackendServiceBackendMaxUtilization(original["max_utilization"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedMaxUtilization); val.IsValid() && !isEmptyValue(val) {
+			transformed["maxUtilization"] = transformedMaxUtilization
+		}
+
 		req = append(req, transformed)
 	}
 	return req, nil
 }
 
+func expandComputeRegionBackendServiceBackendBalancingMode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandComputeRegionBackendServiceBackendCapacityScaler(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
 func expandComputeRegionBackendServiceBackendDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
 	return v, nil
 }
@@ -166,31 +228,31 @@ func expandComputeRegionBackendServiceBackendGroup(v interface{}, d TerraformRes
 	return v, nil
 }
 
-func expandComputeRegionBackendServiceDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+func expandComputeRegionBackendServiceBackendMaxConnections(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
 	return v, nil
 }
 
-func expandComputeRegionBackendServiceFingerprint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+func expandComputeRegionBackendServiceBackendMaxConnectionsPerInstance(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
 	return v, nil
 }
 
-func expandComputeRegionBackendServiceProtocol(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+func expandComputeRegionBackendServiceBackendMaxConnectionsPerEndpoint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
 	return v, nil
 }
 
-func expandComputeRegionBackendServiceSessionAffinity(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+func expandComputeRegionBackendServiceBackendMaxRate(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
 	return v, nil
 }
 
-func expandComputeRegionBackendServiceRegion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
-	f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true)
-	if err != nil {
-		return nil, fmt.Errorf("Invalid value for region: %s", err)
-	}
-	return f.RelativeLink(), nil
+func expandComputeRegionBackendServiceBackendMaxRatePerInstance(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
 }
 
-func expandComputeRegionBackendServiceTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+func expandComputeRegionBackendServiceBackendMaxRatePerEndpoint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandComputeRegionBackendServiceBackendMaxUtilization(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
 	return v, nil
 }
 
@@ -210,6 +272,43 @@ func expandComputeRegionBackendServiceConnectionDrainingConnectionDrainingTimeou
 	return v, nil
 }
 
+func expandComputeRegionBackendServiceDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandComputeRegionBackendServiceFingerprint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandComputeRegionBackendServiceHealthChecks(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	v = v.(*schema.Set).List()
+	return v, nil
+}
+
 func expandComputeRegionBackendServiceLoadBalancingScheme(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
 	return v, nil
 }
+
+func expandComputeRegionBackendServiceName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandComputeRegionBackendServiceProtocol(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandComputeRegionBackendServiceSessionAffinity(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandComputeRegionBackendServiceTimeoutSec(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandComputeRegionBackendServiceRegion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true)
+	if err != nil {
+		return nil, fmt.Errorf("Invalid value for region: %s", err)
+	}
+	return f.RelativeLink(), nil
+}
diff --git a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_subnetwork.go b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_subnetwork.go
index 9868eff2..dc4c7187 100644
--- a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_subnetwork.go
+++ b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/compute_subnetwork.go
@@ -127,6 +127,12 @@ func GetComputeSubnetworkApiObject(d TerraformResourceData, config *Config) (map
 	} else if v, ok := d.GetOkExists("region"); !isEmptyValue(reflect.ValueOf(regionProp)) && (ok || !reflect.DeepEqual(v, regionProp)) {
 		obj["region"] = regionProp
 	}
+	logConfigProp, err := expandComputeSubnetworkLogConfig(d.Get("log_config"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("log_config"); !isEmptyValue(reflect.ValueOf(logConfigProp)) && (ok || !reflect.DeepEqual(v, logConfigProp)) {
+		obj["logConfig"] = logConfigProp
+	}
 
 	return obj, nil
 }
@@ -207,3 +213,24 @@ func expandComputeSubnetworkRegion(v interface{}, d TerraformResourceData, confi
 	}
 	return f.RelativeLink(), nil
 }
+
+func expandComputeSubnetworkLogConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+
+	v, ok := d.GetOkExists("enable_flow_logs")
+
+	transformed := make(map[string]interface{})
+	if !ok || v.(bool) {
+		transformed["enable"] = true
+		transformed["aggregationInterval"] = original["aggregation_interval"]
+		transformed["flowSampling"] = original["flow_sampling"]
+		transformed["metadata"] = original["metadata"]
+	}
+
+	return transformed, nil
+}
diff --git a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/container.go b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/container.go
new file mode 100644
index 00000000..94312387
--- /dev/null
+++ b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/container.go
@@ -0,0 +1,1609 @@
+// This file is written manually and is not based from terraform-provider-google. 
+// There is a huge potential for drift. The longer term plan is to have this 
+// file generated from the logic in terraform-provider-google. Please 
+// see https://github.com/GoogleCloudPlatform/magic-modules/pull/2485#issuecomment-545680059 
+// for the discussion.
+
+package google
+
+import (
+  "fmt"
+	"reflect"
+
+	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
+)
+
+func expandContainerEnabledObject(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	if val := reflect.ValueOf(v); !val.IsValid() || isEmptyValue(val) {
+		return nil, nil
+	}
+	transformed := map[string]interface{}{
+		"enabled": v,
+	}
+	return transformed, nil
+}
+
+func expandContainerClusterEnableLegacyAbac(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return expandContainerEnabledObject(v, d, config)
+}
+
+func expandContainerClusterEnableBinaryAuthorization(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return expandContainerEnabledObject(v, d, config)
+}
+
+func expandContainerMaxPodsConstraint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	if val := reflect.ValueOf(v); !val.IsValid() || isEmptyValue(val) {
+		return nil, nil
+	}
+	transformed := map[string]interface{}{
+		"maxPodsPerNode": v,
+	}
+	return transformed, nil
+}
+
+func expandContainerClusterDefaultMaxPodsPerNode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return expandContainerMaxPodsConstraint(v, d, config)
+}
+
+func expandContainerNodePoolMaxPodsPerNode(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return expandContainerMaxPodsConstraint(v, d, config)
+}
+
+func expandContainerClusterNetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	fv, err := ParseNetworkFieldValue(v.(string), d, config)
+	if err != nil {
+		return nil, err
+	}
+	return fv.RelativeLink(), nil
+}
+
+func expandContainerClusterSubnetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	fv, err := ParseNetworkFieldValue(v.(string), d, config)
+	if err != nil {
+		return nil, err
+	}
+	return fv.RelativeLink(), nil
+}
+
+func canonicalizeServiceScopesFromSet(scopesSet *schema.Set) (interface{}, error) {
+	scopes := make([]string, scopesSet.Len())
+	for i, scope := range scopesSet.List() {
+		scopes[i] = canonicalizeServiceScope(scope.(string))
+	}
+	return scopes, nil
+}
+
+func expandContainerClusterNodeConfigOauthScopes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	scopesSet := v.(*schema.Set)
+	return canonicalizeServiceScopesFromSet(scopesSet)
+}
+
+func expandContainerNodePoolNodeConfigOauthScopes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	scopesSet := v.(*schema.Set)
+	return canonicalizeServiceScopesFromSet(scopesSet)
+}
+
+func GetContainerClusterCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
+	name, err := assetName(d, config, "//container.googleapis.com/projects/{{project}}/locations/{{location}}/clusters/{{name}}")
+	if err != nil {
+		return Asset{}, err
+	}
+	if obj, err := GetContainerClusterApiObject(d, config); err == nil {
+		return Asset{
+			Name: name,
+			Type: "container.googleapis.com/Cluster",
+			Resource: &AssetResource{
+				Version:              "v1",
+				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/container/v1/rest",
+				DiscoveryName:        "Cluster",
+				Data:                 obj,
+			},
+		}, nil
+	} else {
+		return Asset{}, err
+	}
+}
+
+func GetContainerClusterApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
+	obj := make(map[string]interface{})
+	binaryAuthorizationProp, err := expandContainerClusterEnableBinaryAuthorization(d.Get("enable_binary_authorization"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("enable_binary_authorization"); !isEmptyValue(reflect.ValueOf(binaryAuthorizationProp)) && (ok || !reflect.DeepEqual(v, binaryAuthorizationProp)) {
+		obj["binaryAuthorization"] = binaryAuthorizationProp
+	}
+	enableKubernetesAlphaProp, err := expandContainerClusterEnableKubernetesAlpha(d.Get("enable_kubernetes_alpha"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("enable_kubernetes_alpha"); !isEmptyValue(reflect.ValueOf(enableKubernetesAlphaProp)) && (ok || !reflect.DeepEqual(v, enableKubernetesAlphaProp)) {
+		obj["enableKubernetesAlpha"] = enableKubernetesAlphaProp
+	}
+	podSecurityPolicyConfigProp, err := expandContainerClusterPodSecurityPolicyConfig(d.Get("pod_security_policy_config"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("pod_security_policy_config"); !isEmptyValue(reflect.ValueOf(podSecurityPolicyConfigProp)) && (ok || !reflect.DeepEqual(v, podSecurityPolicyConfigProp)) {
+		obj["podSecurityPolicyConfig"] = podSecurityPolicyConfigProp
+	}
+	nameProp, err := expandContainerClusterName(d.Get("name"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
+		obj["name"] = nameProp
+	}
+	descriptionProp, err := expandContainerClusterDescription(d.Get("description"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
+		obj["description"] = descriptionProp
+	}
+	initialNodeCountProp, err := expandContainerClusterInitialNodeCount(d.Get("initial_node_count"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("initial_node_count"); !isEmptyValue(reflect.ValueOf(initialNodeCountProp)) && (ok || !reflect.DeepEqual(v, initialNodeCountProp)) {
+		obj["initialNodeCount"] = initialNodeCountProp
+	}
+	nodeConfigProp, err := expandContainerClusterNodeConfig(d.Get("node_config"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("node_config"); !isEmptyValue(reflect.ValueOf(nodeConfigProp)) && (ok || !reflect.DeepEqual(v, nodeConfigProp)) {
+		obj["nodeConfig"] = nodeConfigProp
+	}
+	masterAuthProp, err := expandContainerClusterMasterAuth(d.Get("master_auth"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("master_auth"); !isEmptyValue(reflect.ValueOf(masterAuthProp)) && (ok || !reflect.DeepEqual(v, masterAuthProp)) {
+		obj["masterAuth"] = masterAuthProp
+	}
+	loggingServiceProp, err := expandContainerClusterLoggingService(d.Get("logging_service"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("logging_service"); !isEmptyValue(reflect.ValueOf(loggingServiceProp)) && (ok || !reflect.DeepEqual(v, loggingServiceProp)) {
+		obj["loggingService"] = loggingServiceProp
+	}
+	monitoringServiceProp, err := expandContainerClusterMonitoringService(d.Get("monitoring_service"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("monitoring_service"); !isEmptyValue(reflect.ValueOf(monitoringServiceProp)) && (ok || !reflect.DeepEqual(v, monitoringServiceProp)) {
+		obj["monitoringService"] = monitoringServiceProp
+	}
+	networkProp, err := expandContainerClusterNetwork(d.Get("network"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("network"); !isEmptyValue(reflect.ValueOf(networkProp)) && (ok || !reflect.DeepEqual(v, networkProp)) {
+		obj["network"] = networkProp
+	}
+	privateClusterConfigProp, err := expandContainerClusterPrivateClusterConfig(d.Get("private_cluster_config"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("private_cluster_config"); !isEmptyValue(reflect.ValueOf(privateClusterConfigProp)) && (ok || !reflect.DeepEqual(v, privateClusterConfigProp)) {
+		obj["privateClusterConfig"] = privateClusterConfigProp
+	}
+	clusterIpv4CidrProp, err := expandContainerClusterClusterIpv4Cidr(d.Get("cluster_ipv4_cidr"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("cluster_ipv4_cidr"); !isEmptyValue(reflect.ValueOf(clusterIpv4CidrProp)) && (ok || !reflect.DeepEqual(v, clusterIpv4CidrProp)) {
+		obj["clusterIpv4Cidr"] = clusterIpv4CidrProp
+	}
+	addonsConfigProp, err := expandContainerClusterAddonsConfig(d.Get("addons_config"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("addons_config"); !isEmptyValue(reflect.ValueOf(addonsConfigProp)) && (ok || !reflect.DeepEqual(v, addonsConfigProp)) {
+		obj["addonsConfig"] = addonsConfigProp
+	}
+	subnetworkProp, err := expandContainerClusterSubnetwork(d.Get("subnetwork"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("subnetwork"); !isEmptyValue(reflect.ValueOf(subnetworkProp)) && (ok || !reflect.DeepEqual(v, subnetworkProp)) {
+		obj["subnetwork"] = subnetworkProp
+	}
+	locationsProp, err := expandContainerClusterNodeLocations(d.Get("node_locations"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("node_locations"); !isEmptyValue(reflect.ValueOf(locationsProp)) && (ok || !reflect.DeepEqual(v, locationsProp)) {
+		obj["locations"] = locationsProp
+	}
+	resourceLabelsProp, err := expandContainerClusterResourceLabels(d.Get("resource_labels"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("resource_labels"); !isEmptyValue(reflect.ValueOf(resourceLabelsProp)) && (ok || !reflect.DeepEqual(v, resourceLabelsProp)) {
+		obj["resourceLabels"] = resourceLabelsProp
+	}
+	labelFingerprintProp, err := expandContainerClusterLabelFingerprint(d.Get("label_fingerprint"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
+		obj["labelFingerprint"] = labelFingerprintProp
+	}
+	legacyAbacProp, err := expandContainerClusterEnableLegacyAbac(d.Get("enable_legacy_abac"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("enable_legacy_abac"); !isEmptyValue(reflect.ValueOf(legacyAbacProp)) && (ok || !reflect.DeepEqual(v, legacyAbacProp)) {
+		obj["legacyAbac"] = legacyAbacProp
+	}
+	networkPolicyProp, err := expandContainerClusterNetworkPolicy(d.Get("network_policy"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("network_policy"); !isEmptyValue(reflect.ValueOf(networkPolicyProp)) && (ok || !reflect.DeepEqual(v, networkPolicyProp)) {
+		obj["networkPolicy"] = networkPolicyProp
+	}
+	defaultMaxPodsConstraintProp, err := expandContainerClusterDefaultMaxPodsPerNode(d.Get("default_max_pods_per_node"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("default_max_pods_per_node"); !isEmptyValue(reflect.ValueOf(defaultMaxPodsConstraintProp)) && (ok || !reflect.DeepEqual(v, defaultMaxPodsConstraintProp)) {
+		obj["defaultMaxPodsConstraint"] = defaultMaxPodsConstraintProp
+	}
+	ipAllocationPolicyProp, err := expandContainerClusterIpAllocationPolicy(d.Get("ip_allocation_policy"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("ip_allocation_policy"); !isEmptyValue(reflect.ValueOf(ipAllocationPolicyProp)) && (ok || !reflect.DeepEqual(v, ipAllocationPolicyProp)) {
+		obj["ipAllocationPolicy"] = ipAllocationPolicyProp
+	}
+	initialClusterVersionProp, err := expandContainerClusterMinMasterVersion(d.Get("min_master_version"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("min_master_version"); !isEmptyValue(reflect.ValueOf(initialClusterVersionProp)) && (ok || !reflect.DeepEqual(v, initialClusterVersionProp)) {
+		obj["initialClusterVersion"] = initialClusterVersionProp
+	}
+	enableTpuProp, err := expandContainerClusterEnableTpu(d.Get("enable_tpu"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("enable_tpu"); !isEmptyValue(reflect.ValueOf(enableTpuProp)) && (ok || !reflect.DeepEqual(v, enableTpuProp)) {
+		obj["enableTpu"] = enableTpuProp
+	}
+	tpuIpv4CidrBlockProp, err := expandContainerClusterTPUIpv4CidrBlock(d.Get("tpu_ipv4_cidr_block"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("tpu_ipv4_cidr_block"); !isEmptyValue(reflect.ValueOf(tpuIpv4CidrBlockProp)) && (ok || !reflect.DeepEqual(v, tpuIpv4CidrBlockProp)) {
+		obj["tpuIpv4CidrBlock"] = tpuIpv4CidrBlockProp
+	}
+	masterAuthorizedNetworksConfigProp, err := expandContainerClusterMasterAuthorizedNetworksConfig(d.Get("master_authorized_networks_config"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("master_authorized_networks_config"); !isEmptyValue(reflect.ValueOf(masterAuthorizedNetworksConfigProp)) && (ok || !reflect.DeepEqual(v, masterAuthorizedNetworksConfigProp)) {
+		obj["masterAuthorizedNetworksConfig"] = masterAuthorizedNetworksConfigProp
+	}
+	locationProp, err := expandContainerClusterLocation(d.Get("location"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("location"); !isEmptyValue(reflect.ValueOf(locationProp)) && (ok || !reflect.DeepEqual(v, locationProp)) {
+		obj["location"] = locationProp
+	}
+	kubectlPathProp, err := expandContainerClusterKubectlPath(d.Get("kubectl_path"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("kubectl_path"); !isEmptyValue(reflect.ValueOf(kubectlPathProp)) && (ok || !reflect.DeepEqual(v, kubectlPathProp)) {
+		obj["kubectlPath"] = kubectlPathProp
+	}
+	kubectlContextProp, err := expandContainerClusterKubectlContext(d.Get("kubectl_context"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("kubectl_context"); !isEmptyValue(reflect.ValueOf(kubectlContextProp)) && (ok || !reflect.DeepEqual(v, kubectlContextProp)) {
+		obj["kubectlContext"] = kubectlContextProp
+	}
+
+	return obj, nil
+}
+
+func expandContainerClusterEnableKubernetesAlpha(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterPodSecurityPolicyConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedEnabled, err := expandContainerClusterPodSecurityPolicyConfigEnabled(original["enabled"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !isEmptyValue(val) {
+		transformed["enabled"] = transformedEnabled
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterPodSecurityPolicyConfigEnabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterInitialNodeCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedWorkloadMetadataConfig, err := expandContainerClusterNodeConfigWorkloadMetadataConfig(original["workload_metadata_config"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedWorkloadMetadataConfig); val.IsValid() && !isEmptyValue(val) {
+		transformed["workloadMetadataConfig"] = transformedWorkloadMetadataConfig
+	}
+
+	transformedMachineType, err := expandContainerClusterNodeConfigMachineType(original["machine_type"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedMachineType); val.IsValid() && !isEmptyValue(val) {
+		transformed["machineType"] = transformedMachineType
+	}
+
+	transformedDiskSizeGb, err := expandContainerClusterNodeConfigDiskSizeGb(original["disk_size_gb"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedDiskSizeGb); val.IsValid() && !isEmptyValue(val) {
+		transformed["diskSizeGb"] = transformedDiskSizeGb
+	}
+
+	transformedOauthScopes, err := expandContainerClusterNodeConfigOauthScopes(original["oauth_scopes"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedOauthScopes); val.IsValid() && !isEmptyValue(val) {
+		transformed["oauthScopes"] = transformedOauthScopes
+	}
+
+	transformedServiceAccount, err := expandContainerClusterNodeConfigServiceAccount(original["service_account"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedServiceAccount); val.IsValid() && !isEmptyValue(val) {
+		transformed["serviceAccount"] = transformedServiceAccount
+	}
+
+	transformedMetadata, err := expandContainerClusterNodeConfigMetadata(original["metadata"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedMetadata); val.IsValid() && !isEmptyValue(val) {
+		transformed["metadata"] = transformedMetadata
+	}
+
+	transformedImageType, err := expandContainerClusterNodeConfigImageType(original["image_type"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedImageType); val.IsValid() && !isEmptyValue(val) {
+		transformed["imageType"] = transformedImageType
+	}
+
+	transformedLabels, err := expandContainerClusterNodeConfigLabels(original["labels"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedLabels); val.IsValid() && !isEmptyValue(val) {
+		transformed["labels"] = transformedLabels
+	}
+
+	transformedLocalSsdCount, err := expandContainerClusterNodeConfigLocalSsdCount(original["local_ssd_count"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedLocalSsdCount); val.IsValid() && !isEmptyValue(val) {
+		transformed["localSsdCount"] = transformedLocalSsdCount
+	}
+
+	transformedTags, err := expandContainerClusterNodeConfigTags(original["tags"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedTags); val.IsValid() && !isEmptyValue(val) {
+		transformed["tags"] = transformedTags
+	}
+
+	transformedPreemptible, err := expandContainerClusterNodeConfigPreemptible(original["preemptible"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedPreemptible); val.IsValid() && !isEmptyValue(val) {
+		transformed["preemptible"] = transformedPreemptible
+	}
+
+	transformedGuestAccelerator, err := expandContainerClusterNodeConfigGuestAccelerator(original["guest_accelerator"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedGuestAccelerator); val.IsValid() && !isEmptyValue(val) {
+		transformed["accelerators"] = transformedGuestAccelerator
+	}
+
+	transformedDiskType, err := expandContainerClusterNodeConfigDiskType(original["disk_type"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedDiskType); val.IsValid() && !isEmptyValue(val) {
+		transformed["diskType"] = transformedDiskType
+	}
+
+	transformedMinCpuPlatform, err := expandContainerClusterNodeConfigMinCpuPlatform(original["min_cpu_platform"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedMinCpuPlatform); val.IsValid() && !isEmptyValue(val) {
+		transformed["minCpuPlatform"] = transformedMinCpuPlatform
+	}
+
+	transformedTaint, err := expandContainerClusterNodeConfigTaint(original["taint"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedTaint); val.IsValid() && !isEmptyValue(val) {
+		transformed["taints"] = transformedTaint
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterNodeConfigWorkloadMetadataConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedNodeMetadata, err := expandContainerClusterNodeConfigWorkloadMetadataConfigNodeMetadata(original["node_metadata"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedNodeMetadata); val.IsValid() && !isEmptyValue(val) {
+		transformed["nodeMetadata"] = transformedNodeMetadata
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterNodeConfigWorkloadMetadataConfigNodeMetadata(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigMachineType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigDiskSizeGb(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigServiceAccount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigMetadata(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
+	if v == nil {
+		return map[string]string{}, nil
+	}
+	m := make(map[string]string)
+	for k, val := range v.(map[string]interface{}) {
+		m[k] = val.(string)
+	}
+	return m, nil
+}
+
+func expandContainerClusterNodeConfigImageType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigLabels(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
+	if v == nil {
+		return map[string]string{}, nil
+	}
+	m := make(map[string]string)
+	for k, val := range v.(map[string]interface{}) {
+		m[k] = val.(string)
+	}
+	return m, nil
+}
+
+func expandContainerClusterNodeConfigLocalSsdCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigTags(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigPreemptible(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigGuestAccelerator(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	req := make([]interface{}, 0, len(l))
+	for _, raw := range l {
+		if raw == nil {
+			continue
+		}
+		original := raw.(map[string]interface{})
+		transformed := make(map[string]interface{})
+
+		transformedCount, err := expandContainerClusterNodeConfigGuestAcceleratorCount(original["count"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedCount); val.IsValid() && !isEmptyValue(val) {
+			transformed["acceleratorCount"] = transformedCount
+		}
+
+		transformedType, err := expandContainerClusterNodeConfigGuestAcceleratorType(original["type"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedType); val.IsValid() && !isEmptyValue(val) {
+			transformed["acceleratorType"] = transformedType
+		}
+
+		req = append(req, transformed)
+	}
+	return req, nil
+}
+
+func expandContainerClusterNodeConfigGuestAcceleratorCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigGuestAcceleratorType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigDiskType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigMinCpuPlatform(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigTaint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	req := make([]interface{}, 0, len(l))
+	for _, raw := range l {
+		if raw == nil {
+			continue
+		}
+		original := raw.(map[string]interface{})
+		transformed := make(map[string]interface{})
+
+		transformedKey, err := expandContainerClusterNodeConfigTaintKey(original["key"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedKey); val.IsValid() && !isEmptyValue(val) {
+			transformed["key"] = transformedKey
+		}
+
+		transformedValue, err := expandContainerClusterNodeConfigTaintValue(original["value"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedValue); val.IsValid() && !isEmptyValue(val) {
+			transformed["value"] = transformedValue
+		}
+
+		transformedEffect, err := expandContainerClusterNodeConfigTaintEffect(original["effect"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedEffect); val.IsValid() && !isEmptyValue(val) {
+			transformed["effect"] = transformedEffect
+		}
+
+		req = append(req, transformed)
+	}
+	return req, nil
+}
+
+func expandContainerClusterNodeConfigTaintKey(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigTaintValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeConfigTaintEffect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMasterAuth(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedUsername, err := expandContainerClusterMasterAuthUsername(original["username"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedUsername); val.IsValid() && !isEmptyValue(val) {
+		transformed["username"] = transformedUsername
+	}
+
+	transformedPassword, err := expandContainerClusterMasterAuthPassword(original["password"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedPassword); val.IsValid() && !isEmptyValue(val) {
+		transformed["password"] = transformedPassword
+	}
+
+	transformedClientCertificateConfig, err := expandContainerClusterMasterAuthClientCertificateConfig(original["client_certificate_config"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedClientCertificateConfig); val.IsValid() && !isEmptyValue(val) {
+		transformed["clientCertificateConfig"] = transformedClientCertificateConfig
+	}
+
+	transformedClusterCaCertificate, err := expandContainerClusterMasterAuthClusterCaCertificate(original["cluster_ca_certificate"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedClusterCaCertificate); val.IsValid() && !isEmptyValue(val) {
+		transformed["clusterCaCertificate"] = transformedClusterCaCertificate
+	}
+
+	transformedClientCertificate, err := expandContainerClusterMasterAuthClientCertificate(original["client_certificate"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedClientCertificate); val.IsValid() && !isEmptyValue(val) {
+		transformed["clientCertificate"] = transformedClientCertificate
+	}
+
+	transformedClientKey, err := expandContainerClusterMasterAuthClientKey(original["client_key"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedClientKey); val.IsValid() && !isEmptyValue(val) {
+		transformed["clientKey"] = transformedClientKey
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterMasterAuthUsername(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMasterAuthPassword(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMasterAuthClientCertificateConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedIssueClientCertificate, err := expandContainerClusterMasterAuthClientCertificateConfigIssueClientCertificate(original["issue_client_certificate"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedIssueClientCertificate); val.IsValid() && !isEmptyValue(val) {
+		transformed["issueClientCertificate"] = transformedIssueClientCertificate
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterMasterAuthClientCertificateConfigIssueClientCertificate(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMasterAuthClusterCaCertificate(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMasterAuthClientCertificate(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMasterAuthClientKey(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterLoggingService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMonitoringService(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterPrivateClusterConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedEnablePrivateNodes, err := expandContainerClusterPrivateClusterConfigEnablePrivateNodes(original["enable_private_nodes"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedEnablePrivateNodes); val.IsValid() && !isEmptyValue(val) {
+		transformed["enablePrivateNodes"] = transformedEnablePrivateNodes
+	}
+
+	transformedEnablePrivateEndpoint, err := expandContainerClusterPrivateClusterConfigEnablePrivateEndpoint(original["enable_private_endpoint"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedEnablePrivateEndpoint); val.IsValid() && !isEmptyValue(val) {
+		transformed["enablePrivateEndpoint"] = transformedEnablePrivateEndpoint
+	}
+
+	transformedMasterIpv4CidrBlock, err := expandContainerClusterPrivateClusterConfigMasterIpv4CidrBlock(original["master_ipv4_cidr_block"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedMasterIpv4CidrBlock); val.IsValid() && !isEmptyValue(val) {
+		transformed["masterIpv4CidrBlock"] = transformedMasterIpv4CidrBlock
+	}
+
+	transformedPrivateEndpoint, err := expandContainerClusterPrivateClusterConfigPrivateEndpoint(original["private_endpoint"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedPrivateEndpoint); val.IsValid() && !isEmptyValue(val) {
+		transformed["privateEndpoint"] = transformedPrivateEndpoint
+	}
+
+	transformedPublicEndpoint, err := expandContainerClusterPrivateClusterConfigPublicEndpoint(original["public_endpoint"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedPublicEndpoint); val.IsValid() && !isEmptyValue(val) {
+		transformed["publicEndpoint"] = transformedPublicEndpoint
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterPrivateClusterConfigEnablePrivateNodes(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterPrivateClusterConfigEnablePrivateEndpoint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterPrivateClusterConfigMasterIpv4CidrBlock(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterPrivateClusterConfigPrivateEndpoint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterPrivateClusterConfigPublicEndpoint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterClusterIpv4Cidr(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterAddonsConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedHttpLoadBalancing, err := expandContainerClusterAddonsConfigHttpLoadBalancing(original["http_load_balancing"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedHttpLoadBalancing); val.IsValid() && !isEmptyValue(val) {
+		transformed["httpLoadBalancing"] = transformedHttpLoadBalancing
+	}
+
+	transformedHorizontalPodAutoscaling, err := expandContainerClusterAddonsConfigHorizontalPodAutoscaling(original["horizontal_pod_autoscaling"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedHorizontalPodAutoscaling); val.IsValid() && !isEmptyValue(val) {
+		transformed["horizontalPodAutoscaling"] = transformedHorizontalPodAutoscaling
+	}
+
+	transformedKubernetesDashboard, err := expandContainerClusterAddonsConfigKubernetesDashboard(original["kubernetes_dashboard"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedKubernetesDashboard); val.IsValid() && !isEmptyValue(val) {
+		transformed["kubernetesDashboard"] = transformedKubernetesDashboard
+	}
+
+	transformedNetworkPolicyConfig, err := expandContainerClusterAddonsConfigNetworkPolicyConfig(original["network_policy_config"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedNetworkPolicyConfig); val.IsValid() && !isEmptyValue(val) {
+		transformed["networkPolicyConfig"] = transformedNetworkPolicyConfig
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterAddonsConfigHttpLoadBalancing(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedDisabled, err := expandContainerClusterAddonsConfigHttpLoadBalancingDisabled(original["disabled"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedDisabled); val.IsValid() && !isEmptyValue(val) {
+		transformed["disabled"] = transformedDisabled
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterAddonsConfigHttpLoadBalancingDisabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterAddonsConfigHorizontalPodAutoscaling(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedDisabled, err := expandContainerClusterAddonsConfigHorizontalPodAutoscalingDisabled(original["disabled"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedDisabled); val.IsValid() && !isEmptyValue(val) {
+		transformed["disabled"] = transformedDisabled
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterAddonsConfigHorizontalPodAutoscalingDisabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterAddonsConfigKubernetesDashboard(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedDisabled, err := expandContainerClusterAddonsConfigKubernetesDashboardDisabled(original["disabled"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedDisabled); val.IsValid() && !isEmptyValue(val) {
+		transformed["disabled"] = transformedDisabled
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterAddonsConfigKubernetesDashboardDisabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterAddonsConfigNetworkPolicyConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedDisabled, err := expandContainerClusterAddonsConfigNetworkPolicyConfigDisabled(original["disabled"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedDisabled); val.IsValid() && !isEmptyValue(val) {
+		transformed["disabled"] = transformedDisabled
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterAddonsConfigNetworkPolicyConfigDisabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNodeLocations(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	v = v.(*schema.Set).List()
+	return v, nil
+}
+
+func expandContainerClusterResourceLabels(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
+	if v == nil {
+		return map[string]string{}, nil
+	}
+	m := make(map[string]string)
+	for k, val := range v.(map[string]interface{}) {
+		m[k] = val.(string)
+	}
+	return m, nil
+}
+
+func expandContainerClusterLabelFingerprint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNetworkPolicy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedProvider, err := expandContainerClusterNetworkPolicyProvider(original["provider"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedProvider); val.IsValid() && !isEmptyValue(val) {
+		transformed["provider"] = transformedProvider
+	}
+
+	transformedEnabled, err := expandContainerClusterNetworkPolicyEnabled(original["enabled"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !isEmptyValue(val) {
+		transformed["enabled"] = transformedEnabled
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterNetworkPolicyProvider(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterNetworkPolicyEnabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterIpAllocationPolicy(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedUseIpAliases, err := expandContainerClusterIpAllocationPolicyUseIpAliases(original["use_ip_aliases"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedUseIpAliases); val.IsValid() && !isEmptyValue(val) {
+		transformed["useIpAliases"] = transformedUseIpAliases
+	}
+
+	transformedCreateSubnetwork, err := expandContainerClusterIpAllocationPolicyCreateSubnetwork(original["create_subnetwork"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedCreateSubnetwork); val.IsValid() && !isEmptyValue(val) {
+		transformed["createSubnetwork"] = transformedCreateSubnetwork
+	}
+
+	transformedSubnetworkName, err := expandContainerClusterIpAllocationPolicySubnetworkName(original["subnetwork_name"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedSubnetworkName); val.IsValid() && !isEmptyValue(val) {
+		transformed["subnetworkName"] = transformedSubnetworkName
+	}
+
+	transformedClusterSecondaryRangeName, err := expandContainerClusterIpAllocationPolicyClusterSecondaryRangeName(original["cluster_secondary_range_name"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedClusterSecondaryRangeName); val.IsValid() && !isEmptyValue(val) {
+		transformed["clusterSecondaryRangeName"] = transformedClusterSecondaryRangeName
+	}
+
+	transformedServicesSecondaryRangeName, err := expandContainerClusterIpAllocationPolicyServicesSecondaryRangeName(original["services_secondary_range_name"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedServicesSecondaryRangeName); val.IsValid() && !isEmptyValue(val) {
+		transformed["servicesSecondaryRangeName"] = transformedServicesSecondaryRangeName
+	}
+
+	transformedClusterIpv4CidrBlock, err := expandContainerClusterIpAllocationPolicyClusterIpv4CidrBlock(original["cluster_ipv4_cidr_block"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedClusterIpv4CidrBlock); val.IsValid() && !isEmptyValue(val) {
+		transformed["clusterIpv4CidrBlock"] = transformedClusterIpv4CidrBlock
+	}
+
+	transformedNodeIpv4CidrBlock, err := expandContainerClusterIpAllocationPolicyNodeIpv4CidrBlock(original["node_ipv4_cidr_block"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedNodeIpv4CidrBlock); val.IsValid() && !isEmptyValue(val) {
+		transformed["nodeIpv4CidrBlock"] = transformedNodeIpv4CidrBlock
+	}
+
+	transformedServicesIpv4CidrBlock, err := expandContainerClusterIpAllocationPolicyServicesIpv4CidrBlock(original["services_ipv4_cidr_block"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedServicesIpv4CidrBlock); val.IsValid() && !isEmptyValue(val) {
+		transformed["servicesIpv4CidrBlock"] = transformedServicesIpv4CidrBlock
+	}
+
+	transformedTPUIpv4CidrBlock, err := expandContainerClusterIpAllocationPolicyTPUIpv4CidrBlock(original["tpu_ipv4_cidr_block"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedTPUIpv4CidrBlock); val.IsValid() && !isEmptyValue(val) {
+		transformed["tpuIpv4CidrBlock"] = transformedTPUIpv4CidrBlock
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterIpAllocationPolicyUseIpAliases(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterIpAllocationPolicyCreateSubnetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterIpAllocationPolicySubnetworkName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterIpAllocationPolicyClusterSecondaryRangeName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterIpAllocationPolicyServicesSecondaryRangeName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterIpAllocationPolicyClusterIpv4CidrBlock(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterIpAllocationPolicyNodeIpv4CidrBlock(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterIpAllocationPolicyServicesIpv4CidrBlock(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterIpAllocationPolicyTPUIpv4CidrBlock(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMinMasterVersion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterEnableTpu(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterTPUIpv4CidrBlock(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMasterAuthorizedNetworksConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedEnabled, err := expandContainerClusterMasterAuthorizedNetworksConfigEnabled(original["enabled"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !isEmptyValue(val) {
+		transformed["enabled"] = transformedEnabled
+	}
+
+	transformedCidrBlocks, err := expandContainerClusterMasterAuthorizedNetworksConfigCidrBlocks(original["cidr_blocks"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedCidrBlocks); val.IsValid() && !isEmptyValue(val) {
+		transformed["cidrBlocks"] = transformedCidrBlocks
+	}
+
+	return transformed, nil
+}
+
+func expandContainerClusterMasterAuthorizedNetworksConfigEnabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMasterAuthorizedNetworksConfigCidrBlocks(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	v = v.(*schema.Set).List()
+	l := v.([]interface{})
+	req := make([]interface{}, 0, len(l))
+	for _, raw := range l {
+		if raw == nil {
+			continue
+		}
+		original := raw.(map[string]interface{})
+		transformed := make(map[string]interface{})
+
+		transformedDisplayName, err := expandContainerClusterMasterAuthorizedNetworksConfigCidrBlocksDisplayName(original["display_name"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedDisplayName); val.IsValid() && !isEmptyValue(val) {
+			transformed["displayName"] = transformedDisplayName
+		}
+
+		transformedCidrBlock, err := expandContainerClusterMasterAuthorizedNetworksConfigCidrBlocksCidrBlock(original["cidr_block"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedCidrBlock); val.IsValid() && !isEmptyValue(val) {
+			transformed["cidrBlock"] = transformedCidrBlock
+		}
+
+		req = append(req, transformed)
+	}
+	return req, nil
+}
+
+func expandContainerClusterMasterAuthorizedNetworksConfigCidrBlocksDisplayName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterMasterAuthorizedNetworksConfigCidrBlocksCidrBlock(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterLocation(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterKubectlPath(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerClusterKubectlContext(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func GetContainerNodePoolCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
+	name, err := assetName(d, config, "//container.googleapis.com/projects/{{project}}/locations/{{location}}/clusters/{{cluster}}/nodePools/{{name}}")
+	if err != nil {
+		return Asset{}, err
+	}
+	if obj, err := GetContainerNodePoolApiObject(d, config); err == nil {
+		return Asset{
+			Name: name,
+			Type: "container.googleapis.com/NodePool",
+			Resource: &AssetResource{
+				Version:              "v1",
+				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/container/v1/rest",
+				DiscoveryName:        "NodePool",
+				Data:                 obj,
+			},
+		}, nil
+	} else {
+		return Asset{}, err
+	}
+}
+
+func GetContainerNodePoolApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
+	obj := make(map[string]interface{})
+	nameProp, err := expandContainerNodePoolName(d.Get("name"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) {
+		obj["name"] = nameProp
+	}
+	configProp, err := expandContainerNodePoolNodeConfig(d.Get("node_config"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("node_config"); !isEmptyValue(reflect.ValueOf(configProp)) && (ok || !reflect.DeepEqual(v, configProp)) {
+		obj["config"] = configProp
+	}
+	initialNodeCountProp, err := expandContainerNodePoolInitialNodeCount(d.Get("initial_node_count"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("initial_node_count"); !isEmptyValue(reflect.ValueOf(initialNodeCountProp)) && (ok || !reflect.DeepEqual(v, initialNodeCountProp)) {
+		obj["initialNodeCount"] = initialNodeCountProp
+	}
+	versionProp, err := expandContainerNodePoolVersion(d.Get("version"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("version"); !isEmptyValue(reflect.ValueOf(versionProp)) && (ok || !reflect.DeepEqual(v, versionProp)) {
+		obj["version"] = versionProp
+	}
+	autoscalingProp, err := expandContainerNodePoolAutoscaling(d.Get("autoscaling"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("autoscaling"); !isEmptyValue(reflect.ValueOf(autoscalingProp)) && (ok || !reflect.DeepEqual(v, autoscalingProp)) {
+		obj["autoscaling"] = autoscalingProp
+	}
+	managementProp, err := expandContainerNodePoolManagement(d.Get("management"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("management"); !isEmptyValue(reflect.ValueOf(managementProp)) && (ok || !reflect.DeepEqual(v, managementProp)) {
+		obj["management"] = managementProp
+	}
+	maxPodsConstraintProp, err := expandContainerNodePoolMaxPodsPerNode(d.Get("max_pods_per_node"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("max_pods_per_node"); !isEmptyValue(reflect.ValueOf(maxPodsConstraintProp)) && (ok || !reflect.DeepEqual(v, maxPodsConstraintProp)) {
+		obj["maxPodsConstraint"] = maxPodsConstraintProp
+	}
+	clusterProp, err := expandContainerNodePoolCluster(d.Get("cluster"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("cluster"); !isEmptyValue(reflect.ValueOf(clusterProp)) && (ok || !reflect.DeepEqual(v, clusterProp)) {
+		obj["cluster"] = clusterProp
+	}
+	locationProp, err := expandContainerNodePoolLocation(d.Get("location"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("location"); !isEmptyValue(reflect.ValueOf(locationProp)) && (ok || !reflect.DeepEqual(v, locationProp)) {
+		obj["location"] = locationProp
+	}
+
+	return obj, nil
+}
+
+func expandContainerNodePoolName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfig(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedMachineType, err := expandContainerNodePoolNodeConfigMachineType(original["machine_type"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedMachineType); val.IsValid() && !isEmptyValue(val) {
+		transformed["machineType"] = transformedMachineType
+	}
+
+	transformedDiskSizeGb, err := expandContainerNodePoolNodeConfigDiskSizeGb(original["disk_size_gb"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedDiskSizeGb); val.IsValid() && !isEmptyValue(val) {
+		transformed["diskSizeGb"] = transformedDiskSizeGb
+	}
+
+	transformedOauthScopes, err := expandContainerNodePoolNodeConfigOauthScopes(original["oauth_scopes"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedOauthScopes); val.IsValid() && !isEmptyValue(val) {
+		transformed["oauthScopes"] = transformedOauthScopes
+	}
+
+	transformedServiceAccount, err := expandContainerNodePoolNodeConfigServiceAccount(original["service_account"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedServiceAccount); val.IsValid() && !isEmptyValue(val) {
+		transformed["serviceAccount"] = transformedServiceAccount
+	}
+
+	transformedMetadata, err := expandContainerNodePoolNodeConfigMetadata(original["metadata"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedMetadata); val.IsValid() && !isEmptyValue(val) {
+		transformed["metadata"] = transformedMetadata
+	}
+
+	transformedImageType, err := expandContainerNodePoolNodeConfigImageType(original["image_type"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedImageType); val.IsValid() && !isEmptyValue(val) {
+		transformed["imageType"] = transformedImageType
+	}
+
+	transformedLabels, err := expandContainerNodePoolNodeConfigLabels(original["labels"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedLabels); val.IsValid() && !isEmptyValue(val) {
+		transformed["labels"] = transformedLabels
+	}
+
+	transformedLocalSsdCount, err := expandContainerNodePoolNodeConfigLocalSsdCount(original["local_ssd_count"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedLocalSsdCount); val.IsValid() && !isEmptyValue(val) {
+		transformed["localSsdCount"] = transformedLocalSsdCount
+	}
+
+	transformedTags, err := expandContainerNodePoolNodeConfigTags(original["tags"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedTags); val.IsValid() && !isEmptyValue(val) {
+		transformed["tags"] = transformedTags
+	}
+
+	transformedPreemptible, err := expandContainerNodePoolNodeConfigPreemptible(original["preemptible"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedPreemptible); val.IsValid() && !isEmptyValue(val) {
+		transformed["preemptible"] = transformedPreemptible
+	}
+
+	transformedGuestAccelerator, err := expandContainerNodePoolNodeConfigGuestAccelerator(original["guest_accelerator"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedGuestAccelerator); val.IsValid() && !isEmptyValue(val) {
+		transformed["accelerators"] = transformedGuestAccelerator
+	}
+
+	transformedDiskType, err := expandContainerNodePoolNodeConfigDiskType(original["disk_type"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedDiskType); val.IsValid() && !isEmptyValue(val) {
+		transformed["diskType"] = transformedDiskType
+	}
+
+	transformedMinCpuPlatform, err := expandContainerNodePoolNodeConfigMinCpuPlatform(original["min_cpu_platform"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedMinCpuPlatform); val.IsValid() && !isEmptyValue(val) {
+		transformed["minCpuPlatform"] = transformedMinCpuPlatform
+	}
+
+	transformedTaint, err := expandContainerNodePoolNodeConfigTaint(original["taint"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedTaint); val.IsValid() && !isEmptyValue(val) {
+		transformed["taints"] = transformedTaint
+	}
+
+	return transformed, nil
+}
+
+func expandContainerNodePoolNodeConfigMachineType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigDiskSizeGb(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigServiceAccount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigMetadata(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
+	if v == nil {
+		return map[string]string{}, nil
+	}
+	m := make(map[string]string)
+	for k, val := range v.(map[string]interface{}) {
+		m[k] = val.(string)
+	}
+	return m, nil
+}
+
+func expandContainerNodePoolNodeConfigImageType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigLabels(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
+	if v == nil {
+		return map[string]string{}, nil
+	}
+	m := make(map[string]string)
+	for k, val := range v.(map[string]interface{}) {
+		m[k] = val.(string)
+	}
+	return m, nil
+}
+
+func expandContainerNodePoolNodeConfigLocalSsdCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigTags(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigPreemptible(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigGuestAccelerator(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	req := make([]interface{}, 0, len(l))
+	for _, raw := range l {
+		if raw == nil {
+			continue
+		}
+		original := raw.(map[string]interface{})
+		transformed := make(map[string]interface{})
+
+		transformedCount, err := expandContainerNodePoolNodeConfigGuestAcceleratorCount(original["count"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedCount); val.IsValid() && !isEmptyValue(val) {
+			transformed["acceleratorCount"] = transformedCount
+		}
+
+		transformedType, err := expandContainerNodePoolNodeConfigGuestAcceleratorType(original["type"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedType); val.IsValid() && !isEmptyValue(val) {
+			transformed["acceleratorType"] = transformedType
+		}
+
+		req = append(req, transformed)
+	}
+	return req, nil
+}
+
+func expandContainerNodePoolNodeConfigGuestAcceleratorCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigGuestAcceleratorType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigDiskType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigMinCpuPlatform(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigTaint(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	req := make([]interface{}, 0, len(l))
+	for _, raw := range l {
+		if raw == nil {
+			continue
+		}
+		original := raw.(map[string]interface{})
+		transformed := make(map[string]interface{})
+
+		transformedKey, err := expandContainerNodePoolNodeConfigTaintKey(original["key"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedKey); val.IsValid() && !isEmptyValue(val) {
+			transformed["key"] = transformedKey
+		}
+
+		transformedValue, err := expandContainerNodePoolNodeConfigTaintValue(original["value"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedValue); val.IsValid() && !isEmptyValue(val) {
+			transformed["value"] = transformedValue
+		}
+
+		transformedEffect, err := expandContainerNodePoolNodeConfigTaintEffect(original["effect"], d, config)
+		if err != nil {
+			return nil, err
+		} else if val := reflect.ValueOf(transformedEffect); val.IsValid() && !isEmptyValue(val) {
+			transformed["effect"] = transformedEffect
+		}
+
+		req = append(req, transformed)
+	}
+	return req, nil
+}
+
+func expandContainerNodePoolNodeConfigTaintKey(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigTaintValue(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolNodeConfigTaintEffect(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolInitialNodeCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolVersion(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolAutoscaling(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedEnabled, err := expandContainerNodePoolAutoscalingEnabled(original["enabled"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !isEmptyValue(val) {
+		transformed["enabled"] = transformedEnabled
+	}
+
+	transformedMinNodeCount, err := expandContainerNodePoolAutoscalingMinNodeCount(original["min_node_count"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedMinNodeCount); val.IsValid() && !isEmptyValue(val) {
+		transformed["minNodeCount"] = transformedMinNodeCount
+	}
+
+	transformedMaxNodeCount, err := expandContainerNodePoolAutoscalingMaxNodeCount(original["max_node_count"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedMaxNodeCount); val.IsValid() && !isEmptyValue(val) {
+		transformed["maxNodeCount"] = transformedMaxNodeCount
+	}
+
+	return transformed, nil
+}
+
+func expandContainerNodePoolAutoscalingEnabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolAutoscalingMinNodeCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolAutoscalingMaxNodeCount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolManagement(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedAutoUpgrade, err := expandContainerNodePoolManagementAutoUpgrade(original["auto_upgrade"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedAutoUpgrade); val.IsValid() && !isEmptyValue(val) {
+		transformed["autoUpgrade"] = transformedAutoUpgrade
+	}
+
+	transformedAutoRepair, err := expandContainerNodePoolManagementAutoRepair(original["auto_repair"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedAutoRepair); val.IsValid() && !isEmptyValue(val) {
+		transformed["autoRepair"] = transformedAutoRepair
+	}
+
+	return transformed, nil
+}
+
+func expandContainerNodePoolManagementAutoUpgrade(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolManagementAutoRepair(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandContainerNodePoolCluster(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	f, err := parseGlobalFieldValue("clusters", v.(string), "project", d, config, true)
+	if err != nil {
+		return nil, fmt.Errorf("Invalid value for cluster: %s", err)
+	}
+	return f.RelativeLink(), nil
+}
+
+func expandContainerNodePoolLocation(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
diff --git a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/logging_metric.go b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/logging_metric.go
index 52fd142c..f2514247 100644
--- a/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/logging_metric.go
+++ b/vendor/github.com/GoogleCloudPlatform/terraform-google-conversion/google/logging_metric.go
@@ -134,6 +134,13 @@ func expandLoggingMetricMetricDescriptor(v interface{}, d TerraformResourceData,
 		transformed["labels"] = transformedLabels
 	}
 
+	transformedDisplayName, err := expandLoggingMetricMetricDescriptorDisplayName(original["display_name"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedDisplayName); val.IsValid() && !isEmptyValue(val) {
+		transformed["displayName"] = transformedDisplayName
+	}
+
 	return transformed, nil
 }
 
@@ -197,6 +204,10 @@ func expandLoggingMetricMetricDescriptorLabelsValueType(v interface{}, d Terrafo
 	return v, nil
 }
 
+func expandLoggingMetricMetricDescriptorDisplayName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
 func expandLoggingMetricLabelExtractors(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
 	if v == nil {
 		return map[string]string{}, nil
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go
new file mode 100644
index 00000000..41bbddc6
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go
@@ -0,0 +1,89 @@
+// Copyright 2017, The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE.md file.
+
+// Package cmpopts provides common options for the cmp package.
+package cmpopts
+
+import (
+	"math"
+	"reflect"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func equateAlways(_, _ interface{}) bool { return true }
+
+// EquateEmpty returns a Comparer option that determines all maps and slices
+// with a length of zero to be equal, regardless of whether they are nil.
+//
+// EquateEmpty can be used in conjunction with SortSlices and SortMaps.
+func EquateEmpty() cmp.Option {
+	return cmp.FilterValues(isEmpty, cmp.Comparer(equateAlways))
+}
+
+func isEmpty(x, y interface{}) bool {
+	vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
+	return (x != nil && y != nil && vx.Type() == vy.Type()) &&
+		(vx.Kind() == reflect.Slice || vx.Kind() == reflect.Map) &&
+		(vx.Len() == 0 && vy.Len() == 0)
+}
+
+// EquateApprox returns a Comparer option that determines float32 or float64
+// values to be equal if they are within a relative fraction or absolute margin.
+// This option is not used when either x or y is NaN or infinite.
+//
+// The fraction determines that the difference of two values must be within the
+// smaller fraction of the two values, while the margin determines that the two
+// values must be within some absolute margin.
+// To express only a fraction or only a margin, use 0 for the other parameter.
+// The fraction and margin must be non-negative.
+//
+// The mathematical expression used is equivalent to:
+//	|x-y| ≤ max(fraction*min(|x|, |y|), margin)
+//
+// EquateApprox can be used in conjunction with EquateNaNs.
+func EquateApprox(fraction, margin float64) cmp.Option {
+	if margin < 0 || fraction < 0 || math.IsNaN(margin) || math.IsNaN(fraction) {
+		panic("margin or fraction must be a non-negative number")
+	}
+	a := approximator{fraction, margin}
+	return cmp.Options{
+		cmp.FilterValues(areRealF64s, cmp.Comparer(a.compareF64)),
+		cmp.FilterValues(areRealF32s, cmp.Comparer(a.compareF32)),
+	}
+}
+
+type approximator struct{ frac, marg float64 }
+
+func areRealF64s(x, y float64) bool {
+	return !math.IsNaN(x) && !math.IsNaN(y) && !math.IsInf(x, 0) && !math.IsInf(y, 0)
+}
+func areRealF32s(x, y float32) bool {
+	return areRealF64s(float64(x), float64(y))
+}
+func (a approximator) compareF64(x, y float64) bool {
+	relMarg := a.frac * math.Min(math.Abs(x), math.Abs(y))
+	return math.Abs(x-y) <= math.Max(a.marg, relMarg)
+}
+func (a approximator) compareF32(x, y float32) bool {
+	return a.compareF64(float64(x), float64(y))
+}
+
+// EquateNaNs returns a Comparer option that determines float32 and float64
+// NaN values to be equal.
+//
+// EquateNaNs can be used in conjunction with EquateApprox.
+func EquateNaNs() cmp.Option {
+	return cmp.Options{
+		cmp.FilterValues(areNaNsF64s, cmp.Comparer(equateAlways)),
+		cmp.FilterValues(areNaNsF32s, cmp.Comparer(equateAlways)),
+	}
+}
+
+func areNaNsF64s(x, y float64) bool {
+	return math.IsNaN(x) && math.IsNaN(y)
+}
+func areNaNsF32s(x, y float32) bool {
+	return areNaNsF64s(float64(x), float64(y))
+}
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go
new file mode 100644
index 00000000..ff8e785d
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go
@@ -0,0 +1,207 @@
+// Copyright 2017, The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE.md file.
+
+package cmpopts
+
+import (
+	"fmt"
+	"reflect"
+	"unicode"
+	"unicode/utf8"
+
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/internal/function"
+)
+
+// IgnoreFields returns an Option that ignores exported fields of the
+// given names on a single struct type.
+// The struct type is specified by passing in a value of that type.
+//
+// The name may be a dot-delimited string (e.g., "Foo.Bar") to ignore a
+// specific sub-field that is embedded or nested within the parent struct.
+//
+// This does not handle unexported fields; use IgnoreUnexported instead.
+func IgnoreFields(typ interface{}, names ...string) cmp.Option {
+	sf := newStructFilter(typ, names...)
+	return cmp.FilterPath(sf.filter, cmp.Ignore())
+}
+
+// IgnoreTypes returns an Option that ignores all values assignable to
+// certain types, which are specified by passing in a value of each type.
+func IgnoreTypes(typs ...interface{}) cmp.Option {
+	tf := newTypeFilter(typs...)
+	return cmp.FilterPath(tf.filter, cmp.Ignore())
+}
+
+type typeFilter []reflect.Type
+
+func newTypeFilter(typs ...interface{}) (tf typeFilter) {
+	for _, typ := range typs {
+		t := reflect.TypeOf(typ)
+		if t == nil {
+			// This occurs if someone tries to pass in sync.Locker(nil)
+			panic("cannot determine type; consider using IgnoreInterfaces")
+		}
+		tf = append(tf, t)
+	}
+	return tf
+}
+func (tf typeFilter) filter(p cmp.Path) bool {
+	if len(p) < 1 {
+		return false
+	}
+	t := p.Last().Type()
+	for _, ti := range tf {
+		if t.AssignableTo(ti) {
+			return true
+		}
+	}
+	return false
+}
+
+// IgnoreInterfaces returns an Option that ignores all values or references of
+// values assignable to certain interface types. These interfaces are specified
+// by passing in an anonymous struct with the interface types embedded in it.
+// For example, to ignore sync.Locker, pass in struct{sync.Locker}{}.
+func IgnoreInterfaces(ifaces interface{}) cmp.Option {
+	tf := newIfaceFilter(ifaces)
+	return cmp.FilterPath(tf.filter, cmp.Ignore())
+}
+
+type ifaceFilter []reflect.Type
+
+func newIfaceFilter(ifaces interface{}) (tf ifaceFilter) {
+	t := reflect.TypeOf(ifaces)
+	if ifaces == nil || t.Name() != "" || t.Kind() != reflect.Struct {
+		panic("input must be an anonymous struct")
+	}
+	for i := 0; i < t.NumField(); i++ {
+		fi := t.Field(i)
+		switch {
+		case !fi.Anonymous:
+			panic("struct cannot have named fields")
+		case fi.Type.Kind() != reflect.Interface:
+			panic("embedded field must be an interface type")
+		case fi.Type.NumMethod() == 0:
+			// This matches everything; why would you ever want this?
+			panic("cannot ignore empty interface")
+		default:
+			tf = append(tf, fi.Type)
+		}
+	}
+	return tf
+}
+func (tf ifaceFilter) filter(p cmp.Path) bool {
+	if len(p) < 1 {
+		return false
+	}
+	t := p.Last().Type()
+	for _, ti := range tf {
+		if t.AssignableTo(ti) {
+			return true
+		}
+		if t.Kind() != reflect.Ptr && reflect.PtrTo(t).AssignableTo(ti) {
+			return true
+		}
+	}
+	return false
+}
+
+// IgnoreUnexported returns an Option that only ignores the immediate unexported
+// fields of a struct, including anonymous fields of unexported types.
+// In particular, unexported fields within the struct's exported fields
+// of struct types, including anonymous fields, will not be ignored unless the
+// type of the field itself is also passed to IgnoreUnexported.
+//
+// Avoid ignoring unexported fields of a type which you do not control (i.e. a
+// type from another repository), as changes to the implementation of such types
+// may change how the comparison behaves. Prefer a custom Comparer instead.
+func IgnoreUnexported(typs ...interface{}) cmp.Option {
+	ux := newUnexportedFilter(typs...)
+	return cmp.FilterPath(ux.filter, cmp.Ignore())
+}
+
+type unexportedFilter struct{ m map[reflect.Type]bool }
+
+func newUnexportedFilter(typs ...interface{}) unexportedFilter {
+	ux := unexportedFilter{m: make(map[reflect.Type]bool)}
+	for _, typ := range typs {
+		t := reflect.TypeOf(typ)
+		if t == nil || t.Kind() != reflect.Struct {
+			panic(fmt.Sprintf("invalid struct type: %T", typ))
+		}
+		ux.m[t] = true
+	}
+	return ux
+}
+func (xf unexportedFilter) filter(p cmp.Path) bool {
+	sf, ok := p.Index(-1).(cmp.StructField)
+	if !ok {
+		return false
+	}
+	return xf.m[p.Index(-2).Type()] && !isExported(sf.Name())
+}
+
+// isExported reports whether the identifier is exported.
+func isExported(id string) bool {
+	r, _ := utf8.DecodeRuneInString(id)
+	return unicode.IsUpper(r)
+}
+
+// IgnoreSliceElements returns an Option that ignores elements of []V.
+// The discard function must be of the form "func(T) bool" which is used to
+// ignore slice elements of type V, where V is assignable to T.
+// Elements are ignored if the function reports true.
+func IgnoreSliceElements(discardFunc interface{}) cmp.Option {
+	vf := reflect.ValueOf(discardFunc)
+	if !function.IsType(vf.Type(), function.ValuePredicate) || vf.IsNil() {
+		panic(fmt.Sprintf("invalid discard function: %T", discardFunc))
+	}
+	return cmp.FilterPath(func(p cmp.Path) bool {
+		si, ok := p.Index(-1).(cmp.SliceIndex)
+		if !ok {
+			return false
+		}
+		if !si.Type().AssignableTo(vf.Type().In(0)) {
+			return false
+		}
+		vx, vy := si.Values()
+		if vx.IsValid() && vf.Call([]reflect.Value{vx})[0].Bool() {
+			return true
+		}
+		if vy.IsValid() && vf.Call([]reflect.Value{vy})[0].Bool() {
+			return true
+		}
+		return false
+	}, cmp.Ignore())
+}
+
+// IgnoreMapEntries returns an Option that ignores entries of map[K]V.
+// The discard function must be of the form "func(T, R) bool" which is used to
+// ignore map entries of type K and V, where K and V are assignable to T and R.
+// Entries are ignored if the function reports true.
+func IgnoreMapEntries(discardFunc interface{}) cmp.Option {
+	vf := reflect.ValueOf(discardFunc)
+	if !function.IsType(vf.Type(), function.KeyValuePredicate) || vf.IsNil() {
+		panic(fmt.Sprintf("invalid discard function: %T", discardFunc))
+	}
+	return cmp.FilterPath(func(p cmp.Path) bool {
+		mi, ok := p.Index(-1).(cmp.MapIndex)
+		if !ok {
+			return false
+		}
+		if !mi.Key().Type().AssignableTo(vf.Type().In(0)) || !mi.Type().AssignableTo(vf.Type().In(1)) {
+			return false
+		}
+		k := mi.Key()
+		vx, vy := mi.Values()
+		if vx.IsValid() && vf.Call([]reflect.Value{k, vx})[0].Bool() {
+			return true
+		}
+		if vy.IsValid() && vf.Call([]reflect.Value{k, vy})[0].Bool() {
+			return true
+		}
+		return false
+	}, cmp.Ignore())
+}
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go
new file mode 100644
index 00000000..3a480462
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go
@@ -0,0 +1,147 @@
+// Copyright 2017, The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE.md file.
+
+package cmpopts
+
+import (
+	"fmt"
+	"reflect"
+	"sort"
+
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/internal/function"
+)
+
+// SortSlices returns a Transformer option that sorts all []V.
+// The less function must be of the form "func(T, T) bool" which is used to
+// sort any slice with element type V that is assignable to T.
+//
+// The less function must be:
+//	• Deterministic: less(x, y) == less(x, y)
+//	• Irreflexive: !less(x, x)
+//	• Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
+//
+// The less function does not have to be "total". That is, if !less(x, y) and
+// !less(y, x) for two elements x and y, their relative order is maintained.
+//
+// SortSlices can be used in conjunction with EquateEmpty.
+func SortSlices(lessFunc interface{}) cmp.Option {
+	vf := reflect.ValueOf(lessFunc)
+	if !function.IsType(vf.Type(), function.Less) || vf.IsNil() {
+		panic(fmt.Sprintf("invalid less function: %T", lessFunc))
+	}
+	ss := sliceSorter{vf.Type().In(0), vf}
+	return cmp.FilterValues(ss.filter, cmp.Transformer("cmpopts.SortSlices", ss.sort))
+}
+
+type sliceSorter struct {
+	in  reflect.Type  // T
+	fnc reflect.Value // func(T, T) bool
+}
+
+func (ss sliceSorter) filter(x, y interface{}) bool {
+	vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
+	if !(x != nil && y != nil && vx.Type() == vy.Type()) ||
+		!(vx.Kind() == reflect.Slice && vx.Type().Elem().AssignableTo(ss.in)) ||
+		(vx.Len() <= 1 && vy.Len() <= 1) {
+		return false
+	}
+	// Check whether the slices are already sorted to avoid an infinite
+	// recursion cycle applying the same transform to itself.
+	ok1 := sort.SliceIsSorted(x, func(i, j int) bool { return ss.less(vx, i, j) })
+	ok2 := sort.SliceIsSorted(y, func(i, j int) bool { return ss.less(vy, i, j) })
+	return !ok1 || !ok2
+}
+func (ss sliceSorter) sort(x interface{}) interface{} {
+	src := reflect.ValueOf(x)
+	dst := reflect.MakeSlice(src.Type(), src.Len(), src.Len())
+	for i := 0; i < src.Len(); i++ {
+		dst.Index(i).Set(src.Index(i))
+	}
+	sort.SliceStable(dst.Interface(), func(i, j int) bool { return ss.less(dst, i, j) })
+	ss.checkSort(dst)
+	return dst.Interface()
+}
+func (ss sliceSorter) checkSort(v reflect.Value) {
+	start := -1 // Start of a sequence of equal elements.
+	for i := 1; i < v.Len(); i++ {
+		if ss.less(v, i-1, i) {
+			// Check that first and last elements in v[start:i] are equal.
+			if start >= 0 && (ss.less(v, start, i-1) || ss.less(v, i-1, start)) {
+				panic(fmt.Sprintf("incomparable values detected: want equal elements: %v", v.Slice(start, i)))
+			}
+			start = -1
+		} else if start == -1 {
+			start = i
+		}
+	}
+}
+func (ss sliceSorter) less(v reflect.Value, i, j int) bool {
+	vx, vy := v.Index(i), v.Index(j)
+	return ss.fnc.Call([]reflect.Value{vx, vy})[0].Bool()
+}
+
+// SortMaps returns a Transformer option that flattens map[K]V types to be a
+// sorted []struct{K, V}. The less function must be of the form
+// "func(T, T) bool" which is used to sort any map with key K that is
+// assignable to T.
+//
+// Flattening the map into a slice has the property that cmp.Equal is able to
+// use Comparers on K or the K.Equal method if it exists.
+//
+// The less function must be:
+//	• Deterministic: less(x, y) == less(x, y)
+//	• Irreflexive: !less(x, x)
+//	• Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
+//	• Total: if x != y, then either less(x, y) or less(y, x)
+//
+// SortMaps can be used in conjunction with EquateEmpty.
+func SortMaps(lessFunc interface{}) cmp.Option {
+	vf := reflect.ValueOf(lessFunc)
+	if !function.IsType(vf.Type(), function.Less) || vf.IsNil() {
+		panic(fmt.Sprintf("invalid less function: %T", lessFunc))
+	}
+	ms := mapSorter{vf.Type().In(0), vf}
+	return cmp.FilterValues(ms.filter, cmp.Transformer("cmpopts.SortMaps", ms.sort))
+}
+
+type mapSorter struct {
+	in  reflect.Type  // T
+	fnc reflect.Value // func(T, T) bool
+}
+
+func (ms mapSorter) filter(x, y interface{}) bool {
+	vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
+	return (x != nil && y != nil && vx.Type() == vy.Type()) &&
+		(vx.Kind() == reflect.Map && vx.Type().Key().AssignableTo(ms.in)) &&
+		(vx.Len() != 0 || vy.Len() != 0)
+}
+func (ms mapSorter) sort(x interface{}) interface{} {
+	src := reflect.ValueOf(x)
+	outType := reflect.StructOf([]reflect.StructField{
+		{Name: "K", Type: src.Type().Key()},
+		{Name: "V", Type: src.Type().Elem()},
+	})
+	dst := reflect.MakeSlice(reflect.SliceOf(outType), src.Len(), src.Len())
+	for i, k := range src.MapKeys() {
+		v := reflect.New(outType).Elem()
+		v.Field(0).Set(k)
+		v.Field(1).Set(src.MapIndex(k))
+		dst.Index(i).Set(v)
+	}
+	sort.Slice(dst.Interface(), func(i, j int) bool { return ms.less(dst, i, j) })
+	ms.checkSort(dst)
+	return dst.Interface()
+}
+func (ms mapSorter) checkSort(v reflect.Value) {
+	for i := 1; i < v.Len(); i++ {
+		if !ms.less(v, i-1, i) {
+			panic(fmt.Sprintf("partial order detected: want %v < %v", v.Index(i-1), v.Index(i)))
+		}
+	}
+}
+func (ms mapSorter) less(v reflect.Value, i, j int) bool {
+	vx, vy := v.Index(i).Field(0), v.Index(j).Field(0)
+	return ms.fnc.Call([]reflect.Value{vx, vy})[0].Bool()
+}
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/struct_filter.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/struct_filter.go
new file mode 100644
index 00000000..97f70798
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/cmpopts/struct_filter.go
@@ -0,0 +1,182 @@
+// Copyright 2017, The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE.md file.
+
+package cmpopts
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+// filterField returns a new Option where opt is only evaluated on paths that
+// include a specific exported field on a single struct type.
+// The struct type is specified by passing in a value of that type.
+//
+// The name may be a dot-delimited string (e.g., "Foo.Bar") to select a
+// specific sub-field that is embedded or nested within the parent struct.
+func filterField(typ interface{}, name string, opt cmp.Option) cmp.Option {
+	// TODO: This is currently unexported over concerns of how helper filters
+	// can be composed together easily.
+	// TODO: Add tests for FilterField.
+
+	sf := newStructFilter(typ, name)
+	return cmp.FilterPath(sf.filter, opt)
+}
+
+type structFilter struct {
+	t  reflect.Type // The root struct type to match on
+	ft fieldTree    // Tree of fields to match on
+}
+
+func newStructFilter(typ interface{}, names ...string) structFilter {
+	// TODO: Perhaps allow * as a special identifier to allow ignoring any
+	// number of path steps until the next field match?
+	// This could be useful when a concrete struct gets transformed into
+	// an anonymous struct where it is not possible to specify that by type,
+	// but the transformer happens to provide guarantees about the names of
+	// the transformed fields.
+
+	t := reflect.TypeOf(typ)
+	if t == nil || t.Kind() != reflect.Struct {
+		panic(fmt.Sprintf("%T must be a struct", typ))
+	}
+	var ft fieldTree
+	for _, name := range names {
+		cname, err := canonicalName(t, name)
+		if err != nil {
+			panic(fmt.Sprintf("%s: %v", strings.Join(cname, "."), err))
+		}
+		ft.insert(cname)
+	}
+	return structFilter{t, ft}
+}
+
+func (sf structFilter) filter(p cmp.Path) bool {
+	for i, ps := range p {
+		if ps.Type().AssignableTo(sf.t) && sf.ft.matchPrefix(p[i+1:]) {
+			return true
+		}
+	}
+	return false
+}
+
+// fieldTree represents a set of dot-separated identifiers.
+//
+// For example, inserting the following selectors:
+//	Foo
+//	Foo.Bar.Baz
+//	Foo.Buzz
+//	Nuka.Cola.Quantum
+//
+// Results in a tree of the form:
+//	{sub: {
+//		"Foo": {ok: true, sub: {
+//			"Bar": {sub: {
+//				"Baz": {ok: true},
+//			}},
+//			"Buzz": {ok: true},
+//		}},
+//		"Nuka": {sub: {
+//			"Cola": {sub: {
+//				"Quantum": {ok: true},
+//			}},
+//		}},
+//	}}
+type fieldTree struct {
+	ok  bool                 // Whether this is a specified node
+	sub map[string]fieldTree // The sub-tree of fields under this node
+}
+
+// insert inserts a sequence of field accesses into the tree.
+func (ft *fieldTree) insert(cname []string) {
+	if ft.sub == nil {
+		ft.sub = make(map[string]fieldTree)
+	}
+	if len(cname) == 0 {
+		ft.ok = true
+		return
+	}
+	sub := ft.sub[cname[0]]
+	sub.insert(cname[1:])
+	ft.sub[cname[0]] = sub
+}
+
+// matchPrefix reports whether any selector in the fieldTree matches
+// the start of path p.
+func (ft fieldTree) matchPrefix(p cmp.Path) bool {
+	for _, ps := range p {
+		switch ps := ps.(type) {
+		case cmp.StructField:
+			ft = ft.sub[ps.Name()]
+			if ft.ok {
+				return true
+			}
+			if len(ft.sub) == 0 {
+				return false
+			}
+		case cmp.Indirect:
+		default:
+			return false
+		}
+	}
+	return false
+}
+
+// canonicalName returns a list of identifiers where any struct field access
+// through an embedded field is expanded to include the names of the embedded
+// types themselves.
+//
+// For example, suppose field "Foo" is not directly in the parent struct,
+// but actually from an embedded struct of type "Bar". Then, the canonical name
+// of "Foo" is actually "Bar.Foo".
+//
+// Suppose field "Foo" is not directly in the parent struct, but actually
+// a field in two different embedded structs of types "Bar" and "Baz".
+// Then the selector "Foo" causes a panic since it is ambiguous which one it
+// refers to. The user must specify either "Bar.Foo" or "Baz.Foo".
+func canonicalName(t reflect.Type, sel string) ([]string, error) {
+	var name string
+	sel = strings.TrimPrefix(sel, ".")
+	if sel == "" {
+		return nil, fmt.Errorf("name must not be empty")
+	}
+	if i := strings.IndexByte(sel, '.'); i < 0 {
+		name, sel = sel, ""
+	} else {
+		name, sel = sel[:i], sel[i:]
+	}
+
+	// Type must be a struct or pointer to struct.
+	if t.Kind() == reflect.Ptr {
+		t = t.Elem()
+	}
+	if t.Kind() != reflect.Struct {
+		return nil, fmt.Errorf("%v must be a struct", t)
+	}
+
+	// Find the canonical name for this current field name.
+	// If the field exists in an embedded struct, then it will be expanded.
+	if !isExported(name) {
+		// Disallow unexported fields:
+		//	* To discourage people from actually touching unexported fields
+		//	* FieldByName is buggy (https://golang.org/issue/4876)
+		return []string{name}, fmt.Errorf("name must be exported")
+	}
+	sf, ok := t.FieldByName(name)
+	if !ok {
+		return []string{name}, fmt.Errorf("does not exist")
+	}
+	var ss []string
+	for i := range sf.Index {
+		ss = append(ss, t.FieldByIndex(sf.Index[:i+1]).Name)
+	}
+	if sel == "" {
+		return ss, nil
+	}
+	ssPost, err := canonicalName(sf.Type, sel)
+	return append(ss, ssPost...), err
+}
diff --git a/vendor/github.com/google/go-cmp/cmp/cmpopts/xform.go b/vendor/github.com/google/go-cmp/cmp/cmpopts/xform.go
new file mode 100644
index 00000000..9d651553
--- /dev/null
+++ b/vendor/github.com/google/go-cmp/cmp/cmpopts/xform.go
@@ -0,0 +1,35 @@
+// Copyright 2018, The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE.md file.
+
+package cmpopts
+
+import (
+	"github.com/google/go-cmp/cmp"
+)
+
+type xformFilter struct{ xform cmp.Option }
+
+func (xf xformFilter) filter(p cmp.Path) bool {
+	for _, ps := range p {
+		if t, ok := ps.(cmp.Transform); ok && t.Option() == xf.xform {
+			return false
+		}
+	}
+	return true
+}
+
+// AcyclicTransformer returns a Transformer with a filter applied that ensures
+// that the transformer cannot be recursively applied upon its own output.
+//
+// An example use case is a transformer that splits a string by lines:
+//	AcyclicTransformer("SplitLines", func(s string) []string{
+//		return strings.Split(s, "\n")
+//	})
+//
+// Had this been an unfiltered Transformer instead, this would result in an
+// infinite cycle converting a string to []string to [][]string and so on.
+func AcyclicTransformer(name string, xformFunc interface{}) cmp.Option {
+	xf := xformFilter{cmp.Transformer(name, xformFunc)}
+	return cmp.FilterPath(xf.filter, xf.xform)
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 26d7645e..8094db3f 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -14,7 +14,7 @@ cloud.google.com/go/bigtable
 cloud.google.com/go/bigtable/internal/option
 # github.com/BurntSushi/toml v0.3.1
 github.com/BurntSushi/toml
-# github.com/GoogleCloudPlatform/terraform-google-conversion v0.0.0-20191024191752-54004ba54ac1
+# github.com/GoogleCloudPlatform/terraform-google-conversion v0.0.0-20191108204708-1cb5102f41ee
 github.com/GoogleCloudPlatform/terraform-google-conversion/google
 # github.com/OneOfOne/xxhash v1.2.5
 github.com/OneOfOne/xxhash
@@ -113,6 +113,7 @@ github.com/golang/protobuf/ptypes/wrappers
 github.com/golang/snappy
 # github.com/google/go-cmp v0.3.0
 github.com/google/go-cmp/cmp
+github.com/google/go-cmp/cmp/cmpopts
 github.com/google/go-cmp/cmp/internal/diff
 github.com/google/go-cmp/cmp/internal/flags
 github.com/google/go-cmp/cmp/internal/function


Test patch:
diff --git a/tfgcv/planned_assets_test.go b/tfgcv/planned_assets_test.go
index 47dd52ea..3cf712ec 100644
--- a/tfgcv/planned_assets_test.go
+++ b/tfgcv/planned_assets_test.go
@@ -14,12 +14,11 @@ import (
 )
 
 const (
-	testDataDir = "../test/read_planned_assets"
-	testProjectName = "gl-akopachevskyy-sql-db"
+	testDataDir      = "../test/read_planned_assets"
+	testProjectName  = "gl-akopachevskyy-sql-db"
 	testAncestryName = "ancestry"
 )
 
-
 func TestReadPlannedAssets(t *testing.T) {
 	type args struct {
 		file     string
@@ -107,11 +106,12 @@ func TestReadPlannedAssetsCoverage(t *testing.T) {
 	defaultProject := "foobar"
 	defaultAncestry := "organization/12345/folder/67890"
 	cases := []struct {
-		name     string
+		name string
 	}{
 		{name: "example_compute_disk"},
 		{name: "example_compute_firewall"},
 		{name: "example_compute_instance"},
+		{name: "example_container_cluster"},
 		{name: "example_organization_iam_binding"},
 		{name: "example_organization_iam_member"},
 		{name: "example_organization_iam_policy"},
@@ -121,6 +121,8 @@ func TestReadPlannedAssetsCoverage(t *testing.T) {
 		{name: "example_project_iam_policy"},
 		{name: "example_sql_database_instance"},
 		{name: "example_storage_bucket"},
+		{name: "full_container_cluster"},
+		{name: "full_container_node_pool"},
 	}
 	for _, c := range cases {
 		t.Run(c.name, func(t *testing.T) {
@@ -166,4 +168,3 @@ func remarshal(t *testing.T, assets []google.Asset) []google.Asset {
 	}
 	return got
 }
-
diff --git a/tfgcv/testdata/example_container_cluster.tf b/tfgcv/testdata/example_container_cluster.tf
new file mode 100644
index 00000000..1dad79e9
--- /dev/null
+++ b/tfgcv/testdata/example_container_cluster.tf
@@ -0,0 +1,41 @@
+resource "google_container_cluster" "primary" {
+  name     = "my-gke-cluster"
+  location = "us-central1"
+
+  # We can't create a cluster with no node pool defined, but we want to only use
+  # separately managed node pools. So we create the smallest possible default
+  # node pool and immediately delete it.
+  remove_default_node_pool = true
+  initial_node_count = 1
+
+  master_auth {
+    username = ""
+    password = ""
+
+    client_certificate_config {
+      issue_client_certificate = false
+    }
+  }
+}
+
+resource "google_container_node_pool" "primary_preemptible_nodes" {
+  name       = "my-node-pool"
+  location   = "us-central1"
+  cluster    = "${google_container_cluster.primary.name}"
+  node_count = 1
+
+  node_config {
+    preemptible  = true
+    machine_type = "n1-standard-1"
+
+    metadata = {
+      disable-legacy-endpoints = "true"
+    }
+
+    oauth_scopes = [
+      "https://www.googleapis.com/auth/logging.write",
+      "https://www.googleapis.com/auth/monitoring",
+    ]
+  }
+}
+
diff --git a/tfgcv/testdata/example_container_cluster_assets.json b/tfgcv/testdata/example_container_cluster_assets.json
new file mode 100644
index 00000000..81d226a9
--- /dev/null
+++ b/tfgcv/testdata/example_container_cluster_assets.json
@@ -0,0 +1,58 @@
+[
+  {
+    "name": "//container.googleapis.com/projects/foobar/locations/us-central1/clusters/my-gke-cluster",
+    "asset_type": "container.googleapis.com/Cluster",
+    "ancestry_path": "organization/12345/folder/67890/project/foobar",
+    "resource": {
+      "version": "v1",
+      "discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/container/v1/rest",
+      "discovery_name": "Cluster",
+      "parent": "//cloudresourcemanager.googleapis.com/projects/foobar",
+      "data": {
+        "addonsConfig": null,
+        "binaryAuthorization": null,
+        "initialNodeCount": 1,
+        "ipAllocationPolicy": null,
+        "legacyAbac": null,
+        "location": "us-central1",
+        "masterAuthorizedNetworksConfig": null,
+        "name": "my-gke-cluster",
+        "network": "projects/foobar/global/networks/default",
+        "networkPolicy": null,
+        "nodeConfig": null,
+        "podSecurityPolicyConfig": null,
+        "privateClusterConfig": null
+      }
+    }
+  },
+  {
+    "name": "//container.googleapis.com/projects/foobar/locations/us-central1/clusters/my-gke-cluster/nodePools/my-node-pool",
+    "asset_type": "container.googleapis.com/NodePool",
+    "ancestry_path": "organization/12345/folder/67890/project/foobar",
+    "resource": {
+      "version": "v1",
+      "discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/container/v1/rest",
+      "discovery_name": "NodePool",
+      "parent": "//cloudresourcemanager.googleapis.com/projects/foobar",
+      "data": {
+        "autoscaling": null,
+        "cluster": "projects/foobar/global/clusters/my-gke-cluster",
+        "config": {
+          "machineType": "n1-standard-1",
+          "metadata": {
+            "disable-legacy-endpoints": "true"
+          },
+          "oauthScopes": [
+            "https://www.googleapis.com/auth/monitoring",
+            "https://www.googleapis.com/auth/logging.write"
+          ],
+          "preemptible": true
+        },
+        "location": "us-central1",
+        "management": null,
+        "maxPodsConstraint": null,
+        "name": "my-node-pool"
+      }
+    }
+  }
+]
diff --git a/tfgcv/testdata/example_container_cluster_tfplan.json b/tfgcv/testdata/example_container_cluster_tfplan.json
new file mode 100644
index 00000000..fe8ba4e5
--- /dev/null
+++ b/tfgcv/testdata/example_container_cluster_tfplan.json
@@ -0,0 +1,327 @@
+{
+  "format_version": "0.1",
+  "terraform_version": "0.12.13",
+  "planned_values": {
+    "root_module": {
+      "resources": [
+        {
+          "address": "google_container_cluster.primary",
+          "mode": "managed",
+          "type": "google_container_cluster",
+          "name": "primary",
+          "provider_name": "google",
+          "schema_version": 1,
+          "values": {
+            "description": null,
+            "enable_intranode_visibility": null,
+            "enable_kubernetes_alpha": false,
+            "enable_legacy_abac": false,
+            "initial_node_count": 1,
+            "location": "us-central1",
+            "maintenance_policy": [],
+            "master_auth": [
+              {
+                "client_certificate_config": [
+                  {
+                    "issue_client_certificate": false
+                  }
+                ],
+                "password": "",
+                "username": ""
+              }
+            ],
+            "master_authorized_networks_config": [],
+            "min_master_version": null,
+            "name": "my-gke-cluster",
+            "network": "default",
+            "pod_security_policy_config": [],
+            "private_cluster_config": [],
+            "remove_default_node_pool": true,
+            "resource_labels": null,
+            "timeouts": null
+          }
+        },
+        {
+          "address": "google_container_node_pool.primary_preemptible_nodes",
+          "mode": "managed",
+          "type": "google_container_node_pool",
+          "name": "primary_preemptible_nodes",
+          "provider_name": "google",
+          "schema_version": 1,
+          "values": {
+            "autoscaling": [],
+            "cluster": "my-gke-cluster",
+            "location": "us-central1",
+            "name": "my-node-pool",
+            "node_config": [
+              {
+                "machine_type": "n1-standard-1",
+                "metadata": {
+                  "disable-legacy-endpoints": "true"
+                },
+                "min_cpu_platform": null,
+                "oauth_scopes": [
+                  "https://www.googleapis.com/auth/logging.write",
+                  "https://www.googleapis.com/auth/monitoring"
+                ],
+                "preemptible": true,
+                "sandbox_config": [],
+                "tags": null,
+                "taint": [],
+                "workload_metadata_config": []
+              }
+            ],
+            "node_count": 1,
+            "timeouts": null
+          }
+        }
+      ]
+    }
+  },
+  "resource_changes": [
+    {
+      "address": "google_container_cluster.primary",
+      "mode": "managed",
+      "type": "google_container_cluster",
+      "name": "primary",
+      "provider_name": "google",
+      "change": {
+        "actions": [
+          "create"
+        ],
+        "before": null,
+        "after": {
+          "description": null,
+          "enable_intranode_visibility": null,
+          "enable_kubernetes_alpha": false,
+          "enable_legacy_abac": false,
+          "initial_node_count": 1,
+          "location": "us-central1",
+          "maintenance_policy": [],
+          "master_auth": [
+            {
+              "client_certificate_config": [
+                {
+                  "issue_client_certificate": false
+                }
+              ],
+              "password": "",
+              "username": ""
+            }
+          ],
+          "master_authorized_networks_config": [],
+          "min_master_version": null,
+          "name": "my-gke-cluster",
+          "network": "default",
+          "pod_security_policy_config": [],
+          "private_cluster_config": [],
+          "remove_default_node_pool": true,
+          "resource_labels": null,
+          "timeouts": null
+        },
+        "after_unknown": {
+          "additional_zones": true,
+          "addons_config": true,
+          "cluster_autoscaling": true,
+          "cluster_ipv4_cidr": true,
+          "default_max_pods_per_node": true,
+          "enable_binary_authorization": true,
+          "enable_tpu": true,
+          "endpoint": true,
+          "id": true,
+          "instance_group_urls": true,
+          "ip_allocation_policy": true,
+          "logging_service": true,
+          "maintenance_policy": [],
+          "master_auth": [
+            {
+              "client_certificate": true,
+              "client_certificate_config": [
+                {}
+              ],
+              "client_key": true,
+              "cluster_ca_certificate": true
+            }
+          ],
+          "master_authorized_networks_config": [],
+          "master_version": true,
+          "monitoring_service": true,
+          "network_policy": true,
+          "node_config": true,
+          "node_locations": true,
+          "node_pool": true,
+          "node_version": true,
+          "pod_security_policy_config": [],
+          "private_cluster_config": [],
+          "project": true,
+          "region": true,
+          "services_ipv4_cidr": true,
+          "subnetwork": true,
+          "zone": true
+        }
+      }
+    },
+    {
+      "address": "google_container_node_pool.primary_preemptible_nodes",
+      "mode": "managed",
+      "type": "google_container_node_pool",
+      "name": "primary_preemptible_nodes",
+      "provider_name": "google",
+      "change": {
+        "actions": [
+          "create"
+        ],
+        "before": null,
+        "after": {
+          "autoscaling": [],
+          "cluster": "my-gke-cluster",
+          "location": "us-central1",
+          "name": "my-node-pool",
+          "node_config": [
+            {
+              "machine_type": "n1-standard-1",
+              "metadata": {
+                "disable-legacy-endpoints": "true"
+              },
+              "min_cpu_platform": null,
+              "oauth_scopes": [
+                "https://www.googleapis.com/auth/logging.write",
+                "https://www.googleapis.com/auth/monitoring"
+              ],
+              "preemptible": true,
+              "sandbox_config": [],
+              "tags": null,
+              "taint": [],
+              "workload_metadata_config": []
+            }
+          ],
+          "node_count": 1,
+          "timeouts": null
+        },
+        "after_unknown": {
+          "autoscaling": [],
+          "id": true,
+          "initial_node_count": true,
+          "instance_group_urls": true,
+          "management": true,
+          "max_pods_per_node": true,
+          "name_prefix": true,
+          "node_config": [
+            {
+              "disk_size_gb": true,
+              "disk_type": true,
+              "guest_accelerator": true,
+              "image_type": true,
+              "labels": true,
+              "local_ssd_count": true,
+              "metadata": {},
+              "oauth_scopes": [
+                false,
+                false
+              ],
+              "sandbox_config": [],
+              "service_account": true,
+              "shielded_instance_config": true,
+              "taint": [],
+              "workload_metadata_config": []
+            }
+          ],
+          "project": true,
+          "region": true,
+          "version": true,
+          "zone": true
+        }
+      }
+    }
+  ],
+  "configuration": {
+    "root_module": {
+      "resources": [
+        {
+          "address": "google_container_cluster.primary",
+          "mode": "managed",
+          "type": "google_container_cluster",
+          "name": "primary",
+          "provider_config_key": "google",
+          "expressions": {
+            "initial_node_count": {
+              "constant_value": 1
+            },
+            "location": {
+              "constant_value": "us-central1"
+            },
+            "master_auth": [
+              {
+                "client_certificate_config": [
+                  {
+                    "issue_client_certificate": {
+                      "constant_value": false
+                    }
+                  }
+                ],
+                "password": {
+                  "constant_value": ""
+                },
+                "username": {
+                  "constant_value": ""
+                }
+              }
+            ],
+            "name": {
+              "constant_value": "my-gke-cluster"
+            },
+            "remove_default_node_pool": {
+              "constant_value": true
+            }
+          },
+          "schema_version": 1
+        },
+        {
+          "address": "google_container_node_pool.primary_preemptible_nodes",
+          "mode": "managed",
+          "type": "google_container_node_pool",
+          "name": "primary_preemptible_nodes",
+          "provider_config_key": "google",
+          "expressions": {
+            "cluster": {
+              "references": [
+                "google_container_cluster.primary"
+              ]
+            },
+            "location": {
+              "constant_value": "us-central1"
+            },
+            "name": {
+              "constant_value": "my-node-pool"
+            },
+            "node_config": [
+              {
+                "machine_type": {
+                  "constant_value": "n1-standard-1"
+                },
+                "metadata": {
+                  "constant_value": {
+                    "disable-legacy-endpoints": "true"
+                  }
+                },
+                "oauth_scopes": {
+                  "constant_value": [
+                    "https://www.googleapis.com/auth/logging.write",
+                    "https://www.googleapis.com/auth/monitoring"
+                  ]
+                },
+                "preemptible": {
+                  "constant_value": true
+                }
+              }
+            ],
+            "node_count": {
+              "constant_value": 1
+            }
+          },
+          "schema_version": 1
+        }
+      ]
+    }
+  }
+}
diff --git a/tfgcv/testdata/full_container_cluster.tf b/tfgcv/testdata/full_container_cluster.tf
new file mode 100644
index 00000000..e7243b5a
--- /dev/null
+++ b/tfgcv/testdata/full_container_cluster.tf
@@ -0,0 +1,133 @@
+resource "google_container_cluster" "full_list_default_1" {
+  # TODO: test beta fields.
+  # addons_config.cloudrun_config
+  # addons_config.cloudrun_config
+  # addons_config.cloudrun_config
+  # addons_config.istio_config
+  # authenticator_groups_config
+  # cluster_autoscaling
+  # database_encryption
+  # enable_binary_authorization
+  # enable_intranode_visibility
+  # enable_shielded_nodes
+  # enable_tpu
+  # node_config.workload_metadata_config
+  # node_config.sandbox_config
+  # pod_security_policy_config
+  # release_channel
+  # resource_usage_export_config
+  # vertical_pod_autoscaling
+  # workload_identity_config
+
+  # TODO: need a seperate test case for fields in conflict with others.
+  # ip_allocation_policy.cluster_ipv4_cidr_block
+  # ip_allocation_policy.create_subnetwork
+  # ip_allocation_policy.node_ipv4_cidr_block
+  # ip_allocation_policy.services_ipv4_cidr_block
+  # ip_allocation_policy.subnetwork_name
+  # region
+  # zone
+
+  # TODO: problematic fields
+  # node_pool
+
+  name = "test-cluster"
+
+  additional_zones = ["test-additional_zones"]
+  addons_config {
+    horizontal_pod_autoscaling { disabled = true }
+    http_load_balancing { disabled = true }
+    kubernetes_dashboard { disabled = true }
+    network_policy_config { disabled = true }
+  }
+  cluster_ipv4_cidr         = "10.0.0.42/32"
+  default_max_pods_per_node = 42
+  description               = "test-description"
+  enable_kubernetes_alpha   = true
+  enable_legacy_abac        = true
+  initial_node_count        = 42
+  ip_allocation_policy {
+    use_ip_aliases                = true
+    cluster_secondary_range_name  = "test-cluster_secondary_range_name"
+    services_secondary_range_name = "test-services_secondary_range_name"
+  }
+  location        = "test-location"
+  logging_service = "logging.googleapis.com"
+  maintenance_policy {
+    daily_maintenance_window {
+      start_time = "03:00"
+    }
+  }
+  master_auth {
+    username = "test-username"
+    password = "test-password"
+    client_certificate_config {
+      issue_client_certificate = true
+    }
+  }
+  master_authorized_networks_config {
+    cidr_blocks {
+      cidr_block   = "10.0.0.42/32"
+      display_name = "test-display_name1"
+    }
+    cidr_blocks {
+      cidr_block   = "10.0.1.42/32"
+      display_name = "test-display_name2"
+    }
+  }
+  min_master_version = "test-min_master_version"
+  monitoring_service = "monitoring.googleapis.com"
+  network            = "test-network"
+  network_policy {
+    provider = "CALICO"
+    enabled  = true
+  }
+  node_config {
+    disk_size_gb = 42
+    disk_type    = "pd-standard"
+    guest_accelerator {
+      type  = "test-type1"
+      count = 1
+    }
+    guest_accelerator {
+      type  = "test-type2"
+      count = 1
+    }
+    image_type = "test-image_type"
+    labels = {
+      test-label-key = "test-label-value"
+    }
+    local_ssd_count = 42
+    machine_type    = "test-machine_type"
+    metadata = {
+      test-metadata-key = "test-metadata-value"
+    }
+    min_cpu_platform = "test-min_cpu_platform"
+    oauth_scopes     = ["test-oauth_scopes", "storage-ro"]
+    preemptible      = true
+    service_account  = "test-service_account"
+    tags             = ["test-tags"]
+    taint {
+      key    = "test-key1"
+      value  = "test-value1"
+      effect = "NO_SCHEDULE"
+    }
+    taint {
+      key    = "test-key2"
+      value  = "test-value2"
+      effect = "NO_SCHEDULE"
+    }
+  }
+  node_locations = ["test-node_locations"]
+  node_version   = "test-node_version"
+  private_cluster_config {
+    enable_private_endpoint = true
+    enable_private_nodes    = true
+    master_ipv4_cidr_block  = "127.0.0.0/28"
+  }
+  remove_default_node_pool = true
+  resource_labels = {
+    test-resource_labels-key = "test-resource_labels-value"
+  }
+  subnetwork = "test-subnetwork"
+}
diff --git a/tfgcv/testdata/full_container_cluster_assets.json b/tfgcv/testdata/full_container_cluster_assets.json
new file mode 100644
index 00000000..749a2ccd
--- /dev/null
+++ b/tfgcv/testdata/full_container_cluster_assets.json
@@ -0,0 +1,129 @@
+[
+  {
+    "name": "//container.googleapis.com/projects/foobar/locations/test-location/clusters/test-cluster",
+    "asset_type": "container.googleapis.com/Cluster",
+    "ancestry_path": "organization/12345/folder/67890/project/foobar",
+    "resource": {
+      "version": "v1",
+      "discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/container/v1/rest",
+      "discovery_name": "Cluster",
+      "parent": "//cloudresourcemanager.googleapis.com/projects/foobar",
+      "data": {
+        "addonsConfig": {
+          "horizontalPodAutoscaling": {
+            "disabled": true
+          },
+          "httpLoadBalancing": {
+            "disabled": true
+          },
+          "kubernetesDashboard": {
+            "disabled": true
+          },
+          "networkPolicyConfig": {
+            "disabled": true
+          }
+        },
+        "binaryAuthorization": null,
+        "clusterIpv4Cidr": "10.0.0.42/32",
+        "description": "test-description",
+        "enableKubernetesAlpha": true,
+        "initialClusterVersion": "test-min_master_version",
+        "initialNodeCount": 42,
+        "ipAllocationPolicy": {
+          "clusterSecondaryRangeName": "test-cluster_secondary_range_name",
+          "servicesSecondaryRangeName": "test-services_secondary_range_name",
+          "useIpAliases": true
+        },
+        "legacyAbac": {
+          "enabled": true
+        },
+        "location": "test-location",
+        "locations": [
+          "test-node_locations"
+        ],
+        "loggingService": "logging.googleapis.com",
+        "masterAuth": {
+          "clientCertificateConfig": {
+            "issueClientCertificate": true
+          },
+          "password": "test-password",
+          "username": "test-username"
+        },
+        "masterAuthorizedNetworksConfig": {
+          "cidrBlocks": [
+            {
+              "cidrBlock": "10.0.0.42/32",
+              "displayName": "test-display_name1"
+            },
+            {
+              "cidrBlock": "10.0.1.42/32",
+              "displayName": "test-display_name2"
+            }
+          ]
+        },
+        "monitoringService": "monitoring.googleapis.com",
+        "name": "test-cluster",
+        "network": "projects/foobar/global/networks/test-network",
+        "networkPolicy": {
+          "enabled": true,
+          "provider": "CALICO"
+        },
+        "nodeConfig": {
+          "accelerators": [
+            {
+              "acceleratorCount": 1,
+              "acceleratorType": "test-type1"
+            },
+            {
+              "acceleratorCount": 1,
+              "acceleratorType": "test-type2"
+            }
+          ],
+          "diskSizeGb": 42,
+          "diskType": "pd-standard",
+          "imageType": "test-image_type",
+          "labels": {
+            "test-label-key": "test-label-value"
+          },
+          "localSsdCount": 42,
+          "machineType": "test-machine_type",
+          "metadata": {
+            "test-metadata-key": "test-metadata-value"
+          },
+          "minCpuPlatform": "test-min_cpu_platform",
+          "oauthScopes": [
+            "https://www.googleapis.com/auth/devstorage.read_only",
+            "test-oauth_scopes"
+          ],
+          "preemptible": true,
+          "serviceAccount": "test-service_account",
+          "tags": [
+            "test-tags"
+          ],
+          "taints": [
+            {
+              "effect": "NO_SCHEDULE",
+              "key": "test-key1",
+              "value": "test-value1"
+            },
+            {
+              "effect": "NO_SCHEDULE",
+              "key": "test-key2",
+              "value": "test-value2"
+            }
+          ]
+        },
+        "podSecurityPolicyConfig": null,
+        "privateClusterConfig": {
+          "enablePrivateEndpoint": true,
+          "enablePrivateNodes": true,
+          "masterIpv4CidrBlock": "127.0.0.0/28"
+        },
+        "resourceLabels": {
+          "test-resource_labels-key": "test-resource_labels-value"
+        },
+        "subnetwork": "projects/foobar/global/networks/test-subnetwork"
+      }
+    }
+  }
+]
diff --git a/tfgcv/testdata/full_container_cluster_tfplan.json b/tfgcv/testdata/full_container_cluster_tfplan.json
new file mode 100644
index 00000000..3813637d
--- /dev/null
+++ b/tfgcv/testdata/full_container_cluster_tfplan.json
@@ -0,0 +1,706 @@
+{
+  "format_version": "0.1",
+  "terraform_version": "0.12.13",
+  "planned_values": {
+    "root_module": {
+      "resources": [
+        {
+          "address": "google_container_cluster.full_list_default_1",
+          "mode": "managed",
+          "type": "google_container_cluster",
+          "name": "full_list_default_1",
+          "provider_name": "google",
+          "schema_version": 1,
+          "values": {
+            "additional_zones": [
+              "test-additional_zones"
+            ],
+            "addons_config": [
+              {
+                "horizontal_pod_autoscaling": [
+                  {
+                    "disabled": true
+                  }
+                ],
+                "http_load_balancing": [
+                  {
+                    "disabled": true
+                  }
+                ],
+                "kubernetes_dashboard": [
+                  {
+                    "disabled": true
+                  }
+                ],
+                "network_policy_config": [
+                  {
+                    "disabled": true
+                  }
+                ]
+              }
+            ],
+            "cluster_ipv4_cidr": "10.0.0.42/32",
+            "default_max_pods_per_node": 42,
+            "description": "test-description",
+            "enable_intranode_visibility": null,
+            "enable_kubernetes_alpha": true,
+            "enable_legacy_abac": true,
+            "initial_node_count": 42,
+            "ip_allocation_policy": [
+              {
+                "cluster_secondary_range_name": "test-cluster_secondary_range_name",
+                "services_secondary_range_name": "test-services_secondary_range_name",
+                "use_ip_aliases": true
+              }
+            ],
+            "location": "test-location",
+            "logging_service": "logging.googleapis.com",
+            "maintenance_policy": [
+              {
+                "daily_maintenance_window": [
+                  {
+                    "start_time": "03:00"
+                  }
+                ]
+              }
+            ],
+            "master_auth": [
+              {
+                "client_certificate_config": [
+                  {
+                    "issue_client_certificate": true
+                  }
+                ],
+                "password": "test-password",
+                "username": "test-username"
+              }
+            ],
+            "master_authorized_networks_config": [
+              {
+                "cidr_blocks": [
+                  {
+                    "cidr_block": "10.0.0.42/32",
+                    "display_name": "test-display_name1"
+                  },
+                  {
+                    "cidr_block": "10.0.1.42/32",
+                    "display_name": "test-display_name2"
+                  }
+                ]
+              }
+            ],
+            "min_master_version": "test-min_master_version",
+            "monitoring_service": "monitoring.googleapis.com",
+            "name": "test-cluster",
+            "network": "test-network",
+            "network_policy": [
+              {
+                "enabled": true,
+                "provider": "CALICO"
+              }
+            ],
+            "node_config": [
+              {
+                "disk_size_gb": 42,
+                "disk_type": "pd-standard",
+                "guest_accelerator": [
+                  {
+                    "count": 1,
+                    "type": "test-type1"
+                  },
+                  {
+                    "count": 1,
+                    "type": "test-type2"
+                  }
+                ],
+                "image_type": "test-image_type",
+                "labels": {
+                  "test-label-key": "test-label-value"
+                },
+                "local_ssd_count": 42,
+                "machine_type": "test-machine_type",
+                "metadata": {
+                  "test-metadata-key": "test-metadata-value"
+                },
+                "min_cpu_platform": "test-min_cpu_platform",
+                "oauth_scopes": [
+                  "https://www.googleapis.com/auth/devstorage.read_only",
+                  "test-oauth_scopes"
+                ],
+                "preemptible": true,
+                "sandbox_config": [],
+                "service_account": "test-service_account",
+                "tags": [
+                  "test-tags"
+                ],
+                "taint": [
+                  {
+                    "effect": "NO_SCHEDULE",
+                    "key": "test-key1",
+                    "value": "test-value1"
+                  },
+                  {
+                    "effect": "NO_SCHEDULE",
+                    "key": "test-key2",
+                    "value": "test-value2"
+                  }
+                ],
+                "workload_metadata_config": []
+              }
+            ],
+            "node_locations": [
+              "test-node_locations"
+            ],
+            "node_version": "test-node_version",
+            "pod_security_policy_config": [],
+            "private_cluster_config": [
+              {
+                "enable_private_endpoint": true,
+                "enable_private_nodes": true,
+                "master_ipv4_cidr_block": "127.0.0.0/28"
+              }
+            ],
+            "remove_default_node_pool": true,
+            "resource_labels": {
+              "test-resource_labels-key": "test-resource_labels-value"
+            },
+            "subnetwork": "test-subnetwork",
+            "timeouts": null
+          }
+        }
+      ]
+    }
+  },
+  "resource_changes": [
+    {
+      "address": "google_container_cluster.full_list_default_1",
+      "mode": "managed",
+      "type": "google_container_cluster",
+      "name": "full_list_default_1",
+      "provider_name": "google",
+      "change": {
+        "actions": [
+          "create"
+        ],
+        "before": null,
+        "after": {
+          "additional_zones": [
+            "test-additional_zones"
+          ],
+          "addons_config": [
+            {
+              "horizontal_pod_autoscaling": [
+                {
+                  "disabled": true
+                }
+              ],
+              "http_load_balancing": [
+                {
+                  "disabled": true
+                }
+              ],
+              "kubernetes_dashboard": [
+                {
+                  "disabled": true
+                }
+              ],
+              "network_policy_config": [
+                {
+                  "disabled": true
+                }
+              ]
+            }
+          ],
+          "cluster_ipv4_cidr": "10.0.0.42/32",
+          "default_max_pods_per_node": 42,
+          "description": "test-description",
+          "enable_intranode_visibility": null,
+          "enable_kubernetes_alpha": true,
+          "enable_legacy_abac": true,
+          "initial_node_count": 42,
+          "ip_allocation_policy": [
+            {
+              "cluster_secondary_range_name": "test-cluster_secondary_range_name",
+              "services_secondary_range_name": "test-services_secondary_range_name",
+              "use_ip_aliases": true
+            }
+          ],
+          "location": "test-location",
+          "logging_service": "logging.googleapis.com",
+          "maintenance_policy": [
+            {
+              "daily_maintenance_window": [
+                {
+                  "start_time": "03:00"
+                }
+              ]
+            }
+          ],
+          "master_auth": [
+            {
+              "client_certificate_config": [
+                {
+                  "issue_client_certificate": true
+                }
+              ],
+              "password": "test-password",
+              "username": "test-username"
+            }
+          ],
+          "master_authorized_networks_config": [
+            {
+              "cidr_blocks": [
+                {
+                  "cidr_block": "10.0.0.42/32",
+                  "display_name": "test-display_name1"
+                },
+                {
+                  "cidr_block": "10.0.1.42/32",
+                  "display_name": "test-display_name2"
+                }
+              ]
+            }
+          ],
+          "min_master_version": "test-min_master_version",
+          "monitoring_service": "monitoring.googleapis.com",
+          "name": "test-cluster",
+          "network": "test-network",
+          "network_policy": [
+            {
+              "enabled": true,
+              "provider": "CALICO"
+            }
+          ],
+          "node_config": [
+            {
+              "disk_size_gb": 42,
+              "disk_type": "pd-standard",
+              "guest_accelerator": [
+                {
+                  "count": 1,
+                  "type": "test-type1"
+                },
+                {
+                  "count": 1,
+                  "type": "test-type2"
+                }
+              ],
+              "image_type": "test-image_type",
+              "labels": {
+                "test-label-key": "test-label-value"
+              },
+              "local_ssd_count": 42,
+              "machine_type": "test-machine_type",
+              "metadata": {
+                "test-metadata-key": "test-metadata-value"
+              },
+              "min_cpu_platform": "test-min_cpu_platform",
+              "oauth_scopes": [
+                "https://www.googleapis.com/auth/devstorage.read_only",
+                "test-oauth_scopes"
+              ],
+              "preemptible": true,
+              "sandbox_config": [],
+              "service_account": "test-service_account",
+              "tags": [
+                "test-tags"
+              ],
+              "taint": [
+                {
+                  "effect": "NO_SCHEDULE",
+                  "key": "test-key1",
+                  "value": "test-value1"
+                },
+                {
+                  "effect": "NO_SCHEDULE",
+                  "key": "test-key2",
+                  "value": "test-value2"
+                }
+              ],
+              "workload_metadata_config": []
+            }
+          ],
+          "node_locations": [
+            "test-node_locations"
+          ],
+          "node_version": "test-node_version",
+          "pod_security_policy_config": [],
+          "private_cluster_config": [
+            {
+              "enable_private_endpoint": true,
+              "enable_private_nodes": true,
+              "master_ipv4_cidr_block": "127.0.0.0/28"
+            }
+          ],
+          "remove_default_node_pool": true,
+          "resource_labels": {
+            "test-resource_labels-key": "test-resource_labels-value"
+          },
+          "subnetwork": "test-subnetwork",
+          "timeouts": null
+        },
+        "after_unknown": {
+          "additional_zones": [
+            false
+          ],
+          "addons_config": [
+            {
+              "horizontal_pod_autoscaling": [
+                {}
+              ],
+              "http_load_balancing": [
+                {}
+              ],
+              "kubernetes_dashboard": [
+                {}
+              ],
+              "network_policy_config": [
+                {}
+              ]
+            }
+          ],
+          "cluster_autoscaling": true,
+          "enable_binary_authorization": true,
+          "enable_tpu": true,
+          "endpoint": true,
+          "id": true,
+          "instance_group_urls": true,
+          "ip_allocation_policy": [
+            {
+              "cluster_ipv4_cidr_block": true,
+              "create_subnetwork": true,
+              "node_ipv4_cidr_block": true,
+              "services_ipv4_cidr_block": true,
+              "subnetwork_name": true
+            }
+          ],
+          "maintenance_policy": [
+            {
+              "daily_maintenance_window": [
+                {
+                  "duration": true
+                }
+              ]
+            }
+          ],
+          "master_auth": [
+            {
+              "client_certificate": true,
+              "client_certificate_config": [
+                {}
+              ],
+              "client_key": true,
+              "cluster_ca_certificate": true
+            }
+          ],
+          "master_authorized_networks_config": [
+            {
+              "cidr_blocks": [
+                {},
+                {}
+              ]
+            }
+          ],
+          "master_version": true,
+          "network_policy": [
+            {}
+          ],
+          "node_config": [
+            {
+              "guest_accelerator": [
+                {},
+                {}
+              ],
+              "labels": {},
+              "metadata": {},
+              "oauth_scopes": [
+                false,
+                false
+              ],
+              "sandbox_config": [],
+              "shielded_instance_config": true,
+              "tags": [
+                false
+              ],
+              "taint": [
+                {},
+                {}
+              ],
+              "workload_metadata_config": []
+            }
+          ],
+          "node_locations": [
+            false
+          ],
+          "node_pool": true,
+          "pod_security_policy_config": [],
+          "private_cluster_config": [
+            {
+              "private_endpoint": true,
+              "public_endpoint": true
+            }
+          ],
+          "project": true,
+          "region": true,
+          "resource_labels": {},
+          "services_ipv4_cidr": true,
+          "zone": true
+        }
+      }
+    }
+  ],
+  "configuration": {
+    "root_module": {
+      "resources": [
+        {
+          "address": "google_container_cluster.full_list_default_1",
+          "mode": "managed",
+          "type": "google_container_cluster",
+          "name": "full_list_default_1",
+          "provider_config_key": "google",
+          "expressions": {
+            "additional_zones": {
+              "constant_value": [
+                "test-additional_zones"
+              ]
+            },
+            "addons_config": [
+              {
+                "horizontal_pod_autoscaling": [
+                  {
+                    "disabled": {
+                      "constant_value": true
+                    }
+                  }
+                ],
+                "http_load_balancing": [
+                  {
+                    "disabled": {
+                      "constant_value": true
+                    }
+                  }
+                ],
+                "kubernetes_dashboard": [
+                  {
+                    "disabled": {
+                      "constant_value": true
+                    }
+                  }
+                ],
+                "network_policy_config": [
+                  {
+                    "disabled": {
+                      "constant_value": true
+                    }
+                  }
+                ]
+              }
+            ],
+            "cluster_ipv4_cidr": {
+              "constant_value": "10.0.0.42/32"
+            },
+            "default_max_pods_per_node": {
+              "constant_value": 42
+            },
+            "description": {
+              "constant_value": "test-description"
+            },
+            "enable_kubernetes_alpha": {
+              "constant_value": true
+            },
+            "enable_legacy_abac": {
+              "constant_value": true
+            },
+            "initial_node_count": {
+              "constant_value": 42
+            },
+            "location": {
+              "constant_value": "test-location"
+            },
+            "logging_service": {
+              "constant_value": "logging.googleapis.com"
+            },
+            "maintenance_policy": [
+              {
+                "daily_maintenance_window": [
+                  {
+                    "start_time": {
+                      "constant_value": "03:00"
+                    }
+                  }
+                ]
+              }
+            ],
+            "master_auth": [
+              {
+                "client_certificate_config": [
+                  {
+                    "issue_client_certificate": {
+                      "constant_value": true
+                    }
+                  }
+                ],
+                "password": {
+                  "constant_value": "test-password"
+                },
+                "username": {
+                  "constant_value": "test-username"
+                }
+              }
+            ],
+            "master_authorized_networks_config": [
+              {
+                "cidr_blocks": [
+                  {
+                    "cidr_block": {
+                      "constant_value": "10.0.0.42/32"
+                    },
+                    "display_name": {
+                      "constant_value": "test-display_name1"
+                    }
+                  },
+                  {
+                    "cidr_block": {
+                      "constant_value": "10.0.1.42/32"
+                    },
+                    "display_name": {
+                      "constant_value": "test-display_name2"
+                    }
+                  }
+                ]
+              }
+            ],
+            "min_master_version": {
+              "constant_value": "test-min_master_version"
+            },
+            "monitoring_service": {
+              "constant_value": "monitoring.googleapis.com"
+            },
+            "name": {
+              "constant_value": "test-cluster"
+            },
+            "network": {
+              "constant_value": "test-network"
+            },
+            "network_policy": [
+              {
+                "enabled": {
+                  "constant_value": true
+                },
+                "provider": {
+                  "constant_value": "CALICO"
+                }
+              }
+            ],
+            "node_config": [
+              {
+                "disk_size_gb": {
+                  "constant_value": 42
+                },
+                "disk_type": {
+                  "constant_value": "pd-standard"
+                },
+                "image_type": {
+                  "constant_value": "test-image_type"
+                },
+                "labels": {
+                  "constant_value": {
+                    "test-label-key": "test-label-value"
+                  }
+                },
+                "local_ssd_count": {
+                  "constant_value": 42
+                },
+                "machine_type": {
+                  "constant_value": "test-machine_type"
+                },
+                "metadata": {
+                  "constant_value": {
+                    "test-metadata-key": "test-metadata-value"
+                  }
+                },
+                "min_cpu_platform": {
+                  "constant_value": "test-min_cpu_platform"
+                },
+                "oauth_scopes": {
+                  "constant_value": [
+                    "test-oauth_scopes",
+                    "storage-ro"
+                  ]
+                },
+                "preemptible": {
+                  "constant_value": true
+                },
+                "service_account": {
+                  "constant_value": "test-service_account"
+                },
+                "tags": {
+                  "constant_value": [
+                    "test-tags"
+                  ]
+                },
+                "taint": [
+                  {
+                    "effect": {
+                      "constant_value": "NO_SCHEDULE"
+                    },
+                    "key": {
+                      "constant_value": "test-key1"
+                    },
+                    "value": {
+                      "constant_value": "test-value1"
+                    }
+                  },
+                  {
+                    "effect": {
+                      "constant_value": "NO_SCHEDULE"
+                    },
+                    "key": {
+                      "constant_value": "test-key2"
+                    },
+                    "value": {
+                      "constant_value": "test-value2"
+                    }
+                  }
+                ]
+              }
+            ],
+            "node_locations": {
+              "constant_value": [
+                "test-node_locations"
+              ]
+            },
+            "node_version": {
+              "constant_value": "test-node_version"
+            },
+            "private_cluster_config": [
+              {
+                "enable_private_endpoint": {
+                  "constant_value": true
+                },
+                "enable_private_nodes": {
+                  "constant_value": true
+                },
+                "master_ipv4_cidr_block": {
+                  "constant_value": "127.0.0.0/28"
+                }
+              }
+            ],
+            "remove_default_node_pool": {
+              "constant_value": true
+            },
+            "resource_labels": {
+              "constant_value": {
+                "test-resource_labels-key": "test-resource_labels-value"
+              }
+            },
+            "subnetwork": {
+              "constant_value": "test-subnetwork"
+            }
+          },
+          "schema_version": 1
+        }
+      ]
+    }
+  }
+}
diff --git a/tfgcv/testdata/full_container_node_pool.tf b/tfgcv/testdata/full_container_node_pool.tf
new file mode 100644
index 00000000..5b7ef46c
--- /dev/null
+++ b/tfgcv/testdata/full_container_node_pool.tf
@@ -0,0 +1,61 @@
+resource "google_container_node_pool" "full_list_default_1" {
+  name = "test-node-pool"
+
+  # TODO: add beta fields.
+  # node_config.sandbox_config
+  # node_config.workload_metadata_config
+  # node_locations
+
+  autoscaling {
+    min_node_count = 42
+    max_node_count = 1337
+  }
+  cluster = "test-cluster"
+  initial_node_count = 42
+  location = "test-location"
+  management {
+    auto_repair = true
+    auto_upgrade = true
+  }
+  max_pods_per_node = 42
+  node_config {
+    disk_size_gb = 42
+    disk_type = "pd-standard"
+    guest_accelerator {
+      type  = "test-type1"
+      count = 1
+    }
+    guest_accelerator {
+      type  = "test-type2"
+      count = 1
+    }
+    image_type = "test-image_type"
+    labels = {
+      test-label-key = "test-label-value"
+    }
+    local_ssd_count = 42
+    machine_type = "test-machine_type"
+    metadata = {
+      test-metadata-key = "test-metadata-value"
+    }
+    min_cpu_platform = "test-min_cpu_platform"
+    oauth_scopes = ["test-oauth_scopes", "storage-ro"]
+    preemptible = true
+    service_account = "test-service_account"
+    tags = ["test-tags"]
+    taint {
+      key    = "test-key1"
+      value  = "test-value1"
+      effect = "NO_SCHEDULE"
+    }
+    taint {
+      key    = "test-key2"
+      value  = "test-value2"
+      effect = "NO_SCHEDULE"
+    }
+  }
+  node_count = 42
+  region = "test-region"
+  version = "test-version"
+  zone = "test-zone"
+}
diff --git a/tfgcv/testdata/full_container_node_pool_assets.json b/tfgcv/testdata/full_container_node_pool_assets.json
new file mode 100644
index 00000000..50f5f00e
--- /dev/null
+++ b/tfgcv/testdata/full_container_node_pool_assets.json
@@ -0,0 +1,76 @@
+[
+  {
+    "name": "//container.googleapis.com/projects/foobar/locations/test-location/clusters/test-cluster/nodePools/test-node-pool",
+    "asset_type": "container.googleapis.com/NodePool",
+    "ancestry_path": "organization/12345/folder/67890/project/foobar",
+    "resource": {
+      "version": "v1",
+      "discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/container/v1/rest",
+      "discovery_name": "NodePool",
+      "parent": "//cloudresourcemanager.googleapis.com/projects/foobar",
+      "data": {
+        "autoscaling": {
+          "maxNodeCount": 1337,
+          "minNodeCount": 42
+        },
+        "cluster": "projects/foobar/global/clusters/test-cluster",
+        "config": {
+          "accelerators": [
+            {
+              "acceleratorCount": 1,
+              "acceleratorType": "test-type1"
+            },
+            {
+              "acceleratorCount": 1,
+              "acceleratorType": "test-type2"
+            }
+          ],
+          "diskSizeGb": 42,
+          "diskType": "pd-standard",
+          "imageType": "test-image_type",
+          "labels": {
+            "test-label-key": "test-label-value"
+          },
+          "localSsdCount": 42,
+          "machineType": "test-machine_type",
+          "metadata": {
+            "test-metadata-key": "test-metadata-value"
+          },
+          "minCpuPlatform": "test-min_cpu_platform",
+          "oauthScopes": [
+            "https://www.googleapis.com/auth/devstorage.read_only",
+            "test-oauth_scopes"
+          ],
+          "preemptible": true,
+          "serviceAccount": "test-service_account",
+          "tags": [
+            "test-tags"
+          ],
+          "taints": [
+            {
+              "effect": "NO_SCHEDULE",
+              "key": "test-key1",
+              "value": "test-value1"
+            },
+            {
+              "effect": "NO_SCHEDULE",
+              "key": "test-key2",
+              "value": "test-value2"
+            }
+          ]
+        },
+        "initialNodeCount": 42,
+        "location": "test-location",
+        "management": {
+          "autoRepair": true,
+          "autoUpgrade": true
+        },
+        "maxPodsConstraint": {
+          "maxPodsPerNode": 42
+        },
+        "name": "test-node-pool",
+        "version": "test-version"
+      }
+    }
+  }
+]
diff --git a/tfgcv/testdata/full_container_node_pool_tfplan.json b/tfgcv/testdata/full_container_node_pool_tfplan.json
new file mode 100644
index 00000000..bad8d267
--- /dev/null
+++ b/tfgcv/testdata/full_container_node_pool_tfplan.json
@@ -0,0 +1,351 @@
+{
+  "format_version": "0.1",
+  "terraform_version": "0.12.13",
+  "planned_values": {
+    "root_module": {
+      "resources": [
+        {
+          "address": "google_container_node_pool.full_list_default_1",
+          "mode": "managed",
+          "type": "google_container_node_pool",
+          "name": "full_list_default_1",
+          "provider_name": "google",
+          "schema_version": 1,
+          "values": {
+            "autoscaling": [
+              {
+                "max_node_count": 1337,
+                "min_node_count": 42
+              }
+            ],
+            "cluster": "test-cluster",
+            "initial_node_count": 42,
+            "location": "test-location",
+            "management": [
+              {
+                "auto_repair": true,
+                "auto_upgrade": true
+              }
+            ],
+            "max_pods_per_node": 42,
+            "name": "test-node-pool",
+            "node_config": [
+              {
+                "disk_size_gb": 42,
+                "disk_type": "pd-standard",
+                "guest_accelerator": [
+                  {
+                    "count": 1,
+                    "type": "test-type1"
+                  },
+                  {
+                    "count": 1,
+                    "type": "test-type2"
+                  }
+                ],
+                "image_type": "test-image_type",
+                "labels": {
+                  "test-label-key": "test-label-value"
+                },
+                "local_ssd_count": 42,
+                "machine_type": "test-machine_type",
+                "metadata": {
+                  "test-metadata-key": "test-metadata-value"
+                },
+                "min_cpu_platform": "test-min_cpu_platform",
+                "oauth_scopes": [
+                  "https://www.googleapis.com/auth/devstorage.read_only",
+                  "test-oauth_scopes"
+                ],
+                "preemptible": true,
+                "sandbox_config": [],
+                "service_account": "test-service_account",
+                "tags": [
+                  "test-tags"
+                ],
+                "taint": [
+                  {
+                    "effect": "NO_SCHEDULE",
+                    "key": "test-key1",
+                    "value": "test-value1"
+                  },
+                  {
+                    "effect": "NO_SCHEDULE",
+                    "key": "test-key2",
+                    "value": "test-value2"
+                  }
+                ],
+                "workload_metadata_config": []
+              }
+            ],
+            "node_count": 42,
+            "region": "test-region",
+            "timeouts": null,
+            "version": "test-version",
+            "zone": "test-zone"
+          }
+        }
+      ]
+    }
+  },
+  "resource_changes": [
+    {
+      "address": "google_container_node_pool.full_list_default_1",
+      "mode": "managed",
+      "type": "google_container_node_pool",
+      "name": "full_list_default_1",
+      "provider_name": "google",
+      "change": {
+        "actions": [
+          "create"
+        ],
+        "before": null,
+        "after": {
+          "autoscaling": [
+            {
+              "max_node_count": 1337,
+              "min_node_count": 42
+            }
+          ],
+          "cluster": "test-cluster",
+          "initial_node_count": 42,
+          "location": "test-location",
+          "management": [
+            {
+              "auto_repair": true,
+              "auto_upgrade": true
+            }
+          ],
+          "max_pods_per_node": 42,
+          "name": "test-node-pool",
+          "node_config": [
+            {
+              "disk_size_gb": 42,
+              "disk_type": "pd-standard",
+              "guest_accelerator": [
+                {
+                  "count": 1,
+                  "type": "test-type1"
+                },
+                {
+                  "count": 1,
+                  "type": "test-type2"
+                }
+              ],
+              "image_type": "test-image_type",
+              "labels": {
+                "test-label-key": "test-label-value"
+              },
+              "local_ssd_count": 42,
+              "machine_type": "test-machine_type",
+              "metadata": {
+                "test-metadata-key": "test-metadata-value"
+              },
+              "min_cpu_platform": "test-min_cpu_platform",
+              "oauth_scopes": [
+                "https://www.googleapis.com/auth/devstorage.read_only",
+                "test-oauth_scopes"
+              ],
+              "preemptible": true,
+              "sandbox_config": [],
+              "service_account": "test-service_account",
+              "tags": [
+                "test-tags"
+              ],
+              "taint": [
+                {
+                  "effect": "NO_SCHEDULE",
+                  "key": "test-key1",
+                  "value": "test-value1"
+                },
+                {
+                  "effect": "NO_SCHEDULE",
+                  "key": "test-key2",
+                  "value": "test-value2"
+                }
+              ],
+              "workload_metadata_config": []
+            }
+          ],
+          "node_count": 42,
+          "region": "test-region",
+          "timeouts": null,
+          "version": "test-version",
+          "zone": "test-zone"
+        },
+        "after_unknown": {
+          "autoscaling": [
+            {}
+          ],
+          "id": true,
+          "instance_group_urls": true,
+          "management": [
+            {}
+          ],
+          "name_prefix": true,
+          "node_config": [
+            {
+              "guest_accelerator": [
+                {},
+                {}
+              ],
+              "labels": {},
+              "metadata": {},
+              "oauth_scopes": [
+                false,
+                false
+              ],
+              "sandbox_config": [],
+              "shielded_instance_config": true,
+              "tags": [
+                false
+              ],
+              "taint": [
+                {},
+                {}
+              ],
+              "workload_metadata_config": []
+            }
+          ],
+          "project": true
+        }
+      }
+    }
+  ],
+  "configuration": {
+    "root_module": {
+      "resources": [
+        {
+          "address": "google_container_node_pool.full_list_default_1",
+          "mode": "managed",
+          "type": "google_container_node_pool",
+          "name": "full_list_default_1",
+          "provider_config_key": "google",
+          "expressions": {
+            "autoscaling": [
+              {
+                "max_node_count": {
+                  "constant_value": 1337
+                },
+                "min_node_count": {
+                  "constant_value": 42
+                }
+              }
+            ],
+            "cluster": {
+              "constant_value": "test-cluster"
+            },
+            "initial_node_count": {
+              "constant_value": 42
+            },
+            "location": {
+              "constant_value": "test-location"
+            },
+            "management": [
+              {
+                "auto_repair": {
+                  "constant_value": true
+                },
+                "auto_upgrade": {
+                  "constant_value": true
+                }
+              }
+            ],
+            "max_pods_per_node": {
+              "constant_value": 42
+            },
+            "name": {
+              "constant_value": "test-node-pool"
+            },
+            "node_config": [
+              {
+                "disk_size_gb": {
+                  "constant_value": 42
+                },
+                "disk_type": {
+                  "constant_value": "pd-standard"
+                },
+                "image_type": {
+                  "constant_value": "test-image_type"
+                },
+                "labels": {
+                  "constant_value": {
+                    "test-label-key": "test-label-value"
+                  }
+                },
+                "local_ssd_count": {
+                  "constant_value": 42
+                },
+                "machine_type": {
+                  "constant_value": "test-machine_type"
+                },
+                "metadata": {
+                  "constant_value": {
+                    "test-metadata-key": "test-metadata-value"
+                  }
+                },
+                "min_cpu_platform": {
+                  "constant_value": "test-min_cpu_platform"
+                },
+                "oauth_scopes": {
+                  "constant_value": [
+                    "test-oauth_scopes",
+                    "storage-ro"
+                  ]
+                },
+                "preemptible": {
+                  "constant_value": true
+                },
+                "service_account": {
+                  "constant_value": "test-service_account"
+                },
+                "tags": {
+                  "constant_value": [
+                    "test-tags"
+                  ]
+                },
+                "taint": [
+                  {
+                    "effect": {
+                      "constant_value": "NO_SCHEDULE"
+                    },
+                    "key": {
+                      "constant_value": "test-key1"
+                    },
+                    "value": {
+                      "constant_value": "test-value1"
+                    }
+                  },
+                  {
+                    "effect": {
+                      "constant_value": "NO_SCHEDULE"
+                    },
+                    "key": {
+                      "constant_value": "test-key2"
+                    },
+                    "value": {
+                      "constant_value": "test-value2"
+                    }
+                  }
+                ]
+              }
+            ],
+            "node_count": {
+              "constant_value": 42
+            },
+            "region": {
+              "constant_value": "test-region"
+            },
+            "version": {
+              "constant_value": "test-version"
+            },
+            "zone": {
+              "constant_value": "test-zone"
+            }
+          },
+          "schema_version": 1
+        }
+      ]
+    }
+  }
+}