diff --git a/.changelog/8268.txt b/.changelog/8268.txt new file mode 100644 index 00000000000..7cd0169efa3 --- /dev/null +++ b/.changelog/8268.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +gkehub: promoted the `google_gke_hub_feature` resource's `fleetobservability` block to GA. +``` diff --git a/google/resource_gke_hub_feature_test.go b/google/resource_gke_hub_feature_test.go index 0639901841f..8fd12b3db18 100644 --- a/google/resource_gke_hub_feature_test.go +++ b/google/resource_gke_hub_feature_test.go @@ -16,6 +16,131 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) +func TestAccGKEHubFeature_gkehubFeatureFleetObservability(t *testing.T) { + // VCR fails to handle batched project services + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckGKEHubFeatureDestroyProducer(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testAccGKEHubFeature_gkehubFeatureFleetObservability(context), + }, + { + ResourceName: "google_gke_hub_feature.feature", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccGKEHubFeature_gkehubFeatureFleetObservabilityUpdate1(context), + }, + { + ResourceName: "google_gke_hub_feature.feature", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccGKEHubFeature_gkehubFeatureFleetObservabilityUpdate2(context), + }, + { + ResourceName: "google_gke_hub_feature.feature", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccGKEHubFeature_gkehubFeatureFleetObservability(context map[string]interface{}) string { + return gkeHubFeatureProjectSetupForGA(context) + acctest.Nprintf(` +resource "time_sleep" "wait_for_gkehub_enablement" { + create_duration = "150s" + depends_on = [google_project_service.gkehub] +} + +resource "google_gke_hub_feature" "feature" { + name = "fleetobservability" + location = "global" + project = google_project.project.project_id + spec { + fleetobservability { + logging_config { + default_config { + mode = "MOVE" + } + fleet_scope_logs_config { + mode = "COPY" + } + } + } + } + depends_on = [time_sleep.wait_for_gkehub_enablement] +} +`, context) +} + +func testAccGKEHubFeature_gkehubFeatureFleetObservabilityUpdate1(context map[string]interface{}) string { + return gkeHubFeatureProjectSetupForGA(context) + acctest.Nprintf(` +resource "time_sleep" "wait_for_gkehub_enablement" { + create_duration = "150s" + depends_on = [google_project_service.gkehub] +} + +resource "google_gke_hub_feature" "feature" { + name = "fleetobservability" + location = "global" + project = google_project.project.project_id + spec { + fleetobservability { + logging_config { + default_config { + mode = "MOVE" + } + } + } + } + depends_on = [time_sleep.wait_for_gkehub_enablement] +} +`, context) +} + +func testAccGKEHubFeature_gkehubFeatureFleetObservabilityUpdate2(context map[string]interface{}) string { + return gkeHubFeatureProjectSetupForGA(context) + acctest.Nprintf(` +resource "time_sleep" "wait_for_gkehub_enablement" { + create_duration = "150s" + depends_on = [google_project_service.gkehub] +} + +resource "google_gke_hub_feature" "feature" { + name = "fleetobservability" + location = "global" + project = google_project.project.project_id + spec { + fleetobservability { + logging_config { + fleet_scope_logs_config { + mode = "COPY" + } + } + } + } + depends_on = [time_sleep.wait_for_gkehub_enablement] +} +`, context) +} + func TestAccGKEHubFeature_gkehubFeatureMciUpdate(t *testing.T) { // VCR fails to handle batched project services acctest.SkipIfVcr(t) diff --git a/google/services/gkehub2/resource_gke_hub_feature.go b/google/services/gkehub2/resource_gke_hub_feature.go index d862f0bae76..92816999fcb 100644 --- a/google/services/gkehub2/resource_gke_hub_feature.go +++ b/google/services/gkehub2/resource_gke_hub_feature.go @@ -28,6 +28,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-provider-google/google/verify" ) func ResourceGKEHub2Feature() *schema.Resource { @@ -74,6 +75,58 @@ func ResourceGKEHub2Feature() *schema.Resource { MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "fleetobservability": { + Type: schema.TypeList, + Optional: true, + Description: `Fleet Observability feature spec.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "logging_config": { + Type: schema.TypeList, + Optional: true, + Description: `Specified if fleet logging feature is enabled for the entire fleet. If UNSPECIFIED, fleet logging feature is disabled for the entire fleet.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default_config": { + Type: schema.TypeList, + Optional: true, + Description: `Specified if applying the default routing config to logs not specified in other configs.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"MODE_UNSPECIFIED", "COPY", "MOVE", ""}), + Description: `Specified if fleet logging feature is enabled. Possible values: ["MODE_UNSPECIFIED", "COPY", "MOVE"]`, + }, + }, + }, + }, + "fleet_scope_logs_config": { + Type: schema.TypeList, + Optional: true, + Description: `Specified if applying the routing config to all logs for all fleet scopes.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"MODE_UNSPECIFIED", "COPY", "MOVE", ""}), + Description: `Specified if fleet logging feature is enabled. Possible values: ["MODE_UNSPECIFIED", "COPY", "MOVE"]`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, "multiclusteringress": { Type: schema.TypeList, Optional: true, @@ -521,6 +574,8 @@ func flattenGKEHub2FeatureSpec(v interface{}, d *schema.ResourceData, config *tr transformed := make(map[string]interface{}) transformed["multiclusteringress"] = flattenGKEHub2FeatureSpecMulticlusteringress(original["multiclusteringress"], d, config) + transformed["fleetobservability"] = + flattenGKEHub2FeatureSpecFleetobservability(original["fleetobservability"], d, config) return []interface{}{transformed} } func flattenGKEHub2FeatureSpecMulticlusteringress(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { @@ -540,6 +595,68 @@ func flattenGKEHub2FeatureSpecMulticlusteringressConfigMembership(v interface{}, return v } +func flattenGKEHub2FeatureSpecFleetobservability(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["logging_config"] = + flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfig(original["loggingConfig"], d, config) + return []interface{}{transformed} +} +func flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["default_config"] = + flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfigDefaultConfig(original["defaultConfig"], d, config) + transformed["fleet_scope_logs_config"] = + flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfigFleetScopeLogsConfig(original["fleetScopeLogsConfig"], d, config) + return []interface{}{transformed} +} +func flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfigDefaultConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["mode"] = + flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfigDefaultConfigMode(original["mode"], d, config) + return []interface{}{transformed} +} +func flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfigDefaultConfigMode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfigFleetScopeLogsConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["mode"] = + flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfigFleetScopeLogsConfigMode(original["mode"], d, config) + return []interface{}{transformed} +} +func flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfigFleetScopeLogsConfigMode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenGKEHub2FeatureState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return nil @@ -621,6 +738,13 @@ func expandGKEHub2FeatureSpec(v interface{}, d tpgresource.TerraformResourceData transformed["multiclusteringress"] = transformedMulticlusteringress } + transformedFleetobservability, err := expandGKEHub2FeatureSpecFleetobservability(original["fleetobservability"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFleetobservability); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["fleetobservability"] = transformedFleetobservability + } + return transformed, nil } @@ -646,3 +770,94 @@ func expandGKEHub2FeatureSpecMulticlusteringress(v interface{}, d tpgresource.Te func expandGKEHub2FeatureSpecMulticlusteringressConfigMembership(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } + +func expandGKEHub2FeatureSpecFleetobservability(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.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{}) + + transformedLoggingConfig, err := expandGKEHub2FeatureSpecFleetobservabilityLoggingConfig(original["logging_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLoggingConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["loggingConfig"] = transformedLoggingConfig + } + + return transformed, nil +} + +func expandGKEHub2FeatureSpecFleetobservabilityLoggingConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.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{}) + + transformedDefaultConfig, err := expandGKEHub2FeatureSpecFleetobservabilityLoggingConfigDefaultConfig(original["default_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDefaultConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["defaultConfig"] = transformedDefaultConfig + } + + transformedFleetScopeLogsConfig, err := expandGKEHub2FeatureSpecFleetobservabilityLoggingConfigFleetScopeLogsConfig(original["fleet_scope_logs_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFleetScopeLogsConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["fleetScopeLogsConfig"] = transformedFleetScopeLogsConfig + } + + return transformed, nil +} + +func expandGKEHub2FeatureSpecFleetobservabilityLoggingConfigDefaultConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.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{}) + + transformedMode, err := expandGKEHub2FeatureSpecFleetobservabilityLoggingConfigDefaultConfigMode(original["mode"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMode); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["mode"] = transformedMode + } + + return transformed, nil +} + +func expandGKEHub2FeatureSpecFleetobservabilityLoggingConfigDefaultConfigMode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureSpecFleetobservabilityLoggingConfigFleetScopeLogsConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.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{}) + + transformedMode, err := expandGKEHub2FeatureSpecFleetobservabilityLoggingConfigFleetScopeLogsConfigMode(original["mode"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMode); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["mode"] = transformedMode + } + + return transformed, nil +} + +func expandGKEHub2FeatureSpecFleetobservabilityLoggingConfigFleetScopeLogsConfigMode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/website/docs/r/gke_hub_feature.html.markdown b/website/docs/r/gke_hub_feature.html.markdown index 520113448c5..8c385ee9359 100644 --- a/website/docs/r/gke_hub_feature.html.markdown +++ b/website/docs/r/gke_hub_feature.html.markdown @@ -95,7 +95,6 @@ resource "google_gke_hub_feature" "feature" { } } } - provider = google-beta } ``` ## Example Usage - Enable Fleet Observability For Scope Logs With Move @@ -114,7 +113,6 @@ resource "google_gke_hub_feature" "feature" { } } } - provider = google-beta } ``` ## Example Usage - Enable Fleet Observability For Both Default And Scope Logs @@ -136,7 +134,6 @@ resource "google_gke_hub_feature" "feature" { } } } - provider = google-beta } ``` @@ -178,7 +175,7 @@ The following arguments are supported: Structure is [documented below](#nested_multiclusteringress). * `fleetobservability` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) + (Optional) Fleet Observability feature spec. Structure is [documented below](#nested_fleetobservability).