From bdd6daf67fae0d78a4721642e9afb14c9c996aee Mon Sep 17 00:00:00 2001 From: The Magician Date: Mon, 6 Nov 2023 14:09:34 -0800 Subject: [PATCH] Add fleet_default_member_config field to google_gke_hub_feature resource (#9234) (#6608) * Adding Terraform resources for Tenancy APIs in GKEHub * Segregating MembershipBinding and MembershipRBACRoleBinding to keep things simpler in the review * Fixing the docu URIs * Adding TF support for Tenancy API for Membership Binding * Adding dependent membership binding to the same commit chain * Making Scope un-updatable and replacing hard coded project number with the one from test env * Making Scope RRBAC updatable * Making Namespace immutable * Adding update test cases * Removing all memberships field from Scope since it is no longer supported * Removing all_memberships field for Scope from all test cases * Enabling Membership resource to be regionalized with global as default value * Moving the test to be the first one in sequence to work-around the IAM test failure * Update mmv1/products/gkehub/Membership.yaml * Adding state migration for gke hub membership * Update mmv1/templates/terraform/examples/gkehub_membership_regional.tf.erb * Adding fleet_default_member_config field to the Feature resource * Fixing the enum value in example * Fixing lint error * Temporary removal of skipIfVcr test flag for the tests to run in PR * Temporary removal of skipIfVcr test flag for the tests to run in PR * Removing unnecessary field spec from feature * Changing feature id to servicemesh * Adding dependency of feature on servicemesh API * Enabling mesh and gkehub APIs to be used in the tests * Temporary enabling services in the test project * Adding dependency of feature test on new project * Testing a few more newly-added fields * Depending on Terraform test project * Skipping if VCR * Depending on the newly created project for the tests * Adding service enablement for Anthos --------- [upstream:e0e5f8df72d7c1b089c89dc6567f801209c6e540] Signed-off-by: Modular Magician --- .changelog/9234.txt | 3 + .../gkehub2/resource_gke_hub_feature.go | 615 ++++++++++++++++++ .../gkehub2/resource_gke_hub_feature_test.go | 162 +++++ website/docs/r/gke_hub_feature.html.markdown | 142 ++++ 4 files changed, 922 insertions(+) create mode 100644 .changelog/9234.txt diff --git a/.changelog/9234.txt b/.changelog/9234.txt new file mode 100644 index 0000000000..2d38f16692 --- /dev/null +++ b/.changelog/9234.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +gkehub: added `fleet_default_member_config` field to `google_gke_hub_feature` resource +``` diff --git a/google-beta/services/gkehub2/resource_gke_hub_feature.go b/google-beta/services/gkehub2/resource_gke_hub_feature.go index a7eb50117a..1d0cd8ee93 100644 --- a/google-beta/services/gkehub2/resource_gke_hub_feature.go +++ b/google-beta/services/gkehub2/resource_gke_hub_feature.go @@ -61,6 +61,147 @@ func ResourceGKEHub2Feature() *schema.Resource { ForceNew: true, Description: `The location for the resource`, }, + "fleet_default_member_config": { + Type: schema.TypeList, + Optional: true, + Description: `Optional. Fleet Default Membership Configuration.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "configmanagement": { + Type: schema.TypeList, + Optional: true, + Description: `Config Management spec`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "config_sync": { + Type: schema.TypeList, + Optional: true, + Description: `ConfigSync configuration for the cluster`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "git": { + Type: schema.TypeList, + Optional: true, + Description: `Git repo configuration for the cluster`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "secret_type": { + Type: schema.TypeString, + Required: true, + Description: `Type of secret configured for access to the Git repo`, + }, + "gcp_service_account_email": { + Type: schema.TypeString, + Optional: true, + Description: `The Google Cloud Service Account Email used for auth when secretType is gcpServiceAccount`, + }, + "https_proxy": { + Type: schema.TypeString, + Optional: true, + Description: `URL for the HTTPS Proxy to be used when communicating with the Git repo`, + }, + "policy_dir": { + Type: schema.TypeString, + Optional: true, + Description: `The path within the Git repository that represents the top level of the repo to sync`, + }, + "sync_branch": { + Type: schema.TypeString, + Optional: true, + Description: `The branch of the repository to sync from. Default: master`, + }, + "sync_repo": { + Type: schema.TypeString, + Optional: true, + Description: `The URL of the Git repository to use as the source of truth`, + }, + "sync_rev": { + Type: schema.TypeString, + Optional: true, + Description: `Git revision (tag or hash) to check out. Default HEAD`, + }, + "sync_wait_secs": { + Type: schema.TypeString, + Optional: true, + Description: `Period in seconds between consecutive syncs. Default: 15`, + }, + }, + }, + }, + "oci": { + Type: schema.TypeList, + Optional: true, + Description: `OCI repo configuration for the cluster`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "secret_type": { + Type: schema.TypeString, + Required: true, + Description: `Type of secret configured for access to the Git repo`, + }, + "gcp_service_account_email": { + Type: schema.TypeString, + Optional: true, + Description: `The Google Cloud Service Account Email used for auth when secretType is gcpServiceAccount`, + }, + "policy_dir": { + Type: schema.TypeString, + Optional: true, + Description: `The absolute path of the directory that contains the local resources. Default: the root directory of the image`, + }, + "sync_repo": { + Type: schema.TypeString, + Optional: true, + Description: `The OCI image repository URL for the package to sync from`, + }, + "sync_wait_secs": { + Type: schema.TypeString, + Optional: true, + Description: `Period in seconds between consecutive syncs. Default: 15`, + }, + "version": { + Type: schema.TypeString, + Optional: true, + Description: `Version of ACM installed`, + }, + }, + }, + }, + "source_format": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies whether the Config Sync Repo is in hierarchical or unstructured mode`, + }, + }, + }, + }, + }, + }, + }, + "mesh": { + Type: schema.TypeList, + Optional: true, + Description: `Service Mesh spec`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "management": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateEnum([]string{"MANAGEMENT_UNSPECIFIED", "MANAGEMENT_AUTOMATIC", "MANAGEMENT_MANUAL"}), + Description: `Whether to automatically manage Service Mesh Possible values: ["MANAGEMENT_UNSPECIFIED", "MANAGEMENT_AUTOMATIC", "MANAGEMENT_MANUAL"]`, + }, + }, + }, + }, + }, + }, + }, "labels": { Type: schema.TypeMap, Optional: true, @@ -259,6 +400,12 @@ func resourceGKEHub2FeatureCreate(d *schema.ResourceData, meta interface{}) erro } else if v, ok := d.GetOkExists("spec"); !tpgresource.IsEmptyValue(reflect.ValueOf(specProp)) && (ok || !reflect.DeepEqual(v, specProp)) { obj["spec"] = specProp } + fleetDefaultMemberConfigProp, err := expandGKEHub2FeatureFleetDefaultMemberConfig(d.Get("fleet_default_member_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fleet_default_member_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(fleetDefaultMemberConfigProp)) && (ok || !reflect.DeepEqual(v, fleetDefaultMemberConfigProp)) { + obj["fleetDefaultMemberConfig"] = fleetDefaultMemberConfigProp + } labelsProp, err := expandGKEHub2FeatureEffectiveLabels(d.Get("effective_labels"), d, config) if err != nil { return err @@ -383,6 +530,9 @@ func resourceGKEHub2FeatureRead(d *schema.ResourceData, meta interface{}) error if err := d.Set("spec", flattenGKEHub2FeatureSpec(res["spec"], d, config)); err != nil { return fmt.Errorf("Error reading Feature: %s", err) } + if err := d.Set("fleet_default_member_config", flattenGKEHub2FeatureFleetDefaultMemberConfig(res["fleetDefaultMemberConfig"], d, config)); err != nil { + return fmt.Errorf("Error reading Feature: %s", err) + } if err := d.Set("state", flattenGKEHub2FeatureState(res["state"], d, config)); err != nil { return fmt.Errorf("Error reading Feature: %s", err) } @@ -427,6 +577,12 @@ func resourceGKEHub2FeatureUpdate(d *schema.ResourceData, meta interface{}) erro } else if v, ok := d.GetOkExists("spec"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, specProp)) { obj["spec"] = specProp } + fleetDefaultMemberConfigProp, err := expandGKEHub2FeatureFleetDefaultMemberConfig(d.Get("fleet_default_member_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fleet_default_member_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, fleetDefaultMemberConfigProp)) { + obj["fleetDefaultMemberConfig"] = fleetDefaultMemberConfigProp + } labelsProp, err := expandGKEHub2FeatureEffectiveLabels(d.Get("effective_labels"), d, config) if err != nil { return err @@ -447,6 +603,10 @@ func resourceGKEHub2FeatureUpdate(d *schema.ResourceData, meta interface{}) erro updateMask = append(updateMask, "spec") } + if d.HasChange("fleet_default_member_config") { + updateMask = append(updateMask, "fleetDefaultMemberConfig") + } + if d.HasChange("effective_labels") { updateMask = append(updateMask, "labels") } @@ -699,6 +859,178 @@ func flattenGKEHub2FeatureSpecFleetobservabilityLoggingConfigFleetScopeLogsConfi return v } +func flattenGKEHub2FeatureFleetDefaultMemberConfig(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["mesh"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigMesh(original["mesh"], d, config) + transformed["configmanagement"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagement(original["configmanagement"], d, config) + return []interface{}{transformed} +} +func flattenGKEHub2FeatureFleetDefaultMemberConfigMesh(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["management"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigMeshManagement(original["management"], d, config) + return []interface{}{transformed} +} +func flattenGKEHub2FeatureFleetDefaultMemberConfigMeshManagement(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagement(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["config_sync"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSync(original["configSync"], d, config) + return []interface{}{transformed} +} +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSync(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["source_format"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncSourceFormat(original["sourceFormat"], d, config) + transformed["git"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGit(original["git"], d, config) + transformed["oci"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOci(original["oci"], d, config) + return []interface{}{transformed} +} +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncSourceFormat(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGit(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["sync_repo"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncRepo(original["syncRepo"], d, config) + transformed["sync_branch"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncBranch(original["syncBranch"], d, config) + transformed["policy_dir"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitPolicyDir(original["policyDir"], d, config) + transformed["sync_rev"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncRev(original["syncRev"], d, config) + transformed["secret_type"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSecretType(original["secretType"], d, config) + transformed["https_proxy"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitHttpsProxy(original["httpsProxy"], d, config) + transformed["gcp_service_account_email"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitGcpServiceAccountEmail(original["gcpServiceAccountEmail"], d, config) + transformed["sync_wait_secs"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncWaitSecs(original["syncWaitSecs"], d, config) + return []interface{}{transformed} +} +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncRepo(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncBranch(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitPolicyDir(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncRev(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSecretType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitHttpsProxy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitGcpServiceAccountEmail(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncWaitSecs(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOci(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["sync_repo"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSyncRepo(original["syncRepo"], d, config) + transformed["policy_dir"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciPolicyDir(original["policyDir"], d, config) + transformed["secret_type"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSecretType(original["secretType"], d, config) + transformed["gcp_service_account_email"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciGcpServiceAccountEmail(original["gcpServiceAccountEmail"], d, config) + transformed["sync_wait_secs"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSyncWaitSecs(original["syncWaitSecs"], d, config) + transformed["version"] = + flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciVersion(original["version"], d, config) + return []interface{}{transformed} +} +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSyncRepo(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciPolicyDir(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSecretType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciGcpServiceAccountEmail(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSyncWaitSecs(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciVersion(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 @@ -912,6 +1244,289 @@ func expandGKEHub2FeatureSpecFleetobservabilityLoggingConfigFleetScopeLogsConfig return v, nil } +func expandGKEHub2FeatureFleetDefaultMemberConfig(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{}) + + transformedMesh, err := expandGKEHub2FeatureFleetDefaultMemberConfigMesh(original["mesh"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMesh); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["mesh"] = transformedMesh + } + + transformedConfigmanagement, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagement(original["configmanagement"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedConfigmanagement); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["configmanagement"] = transformedConfigmanagement + } + + return transformed, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigMesh(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{}) + + transformedManagement, err := expandGKEHub2FeatureFleetDefaultMemberConfigMeshManagement(original["management"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedManagement); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["management"] = transformedManagement + } + + return transformed, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigMeshManagement(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagement(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{}) + + transformedConfigSync, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSync(original["config_sync"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedConfigSync); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["configSync"] = transformedConfigSync + } + + return transformed, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSync(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{}) + + transformedSourceFormat, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncSourceFormat(original["source_format"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSourceFormat); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sourceFormat"] = transformedSourceFormat + } + + transformedGit, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGit(original["git"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedGit); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["git"] = transformedGit + } + + transformedOci, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOci(original["oci"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedOci); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["oci"] = transformedOci + } + + return transformed, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncSourceFormat(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGit(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{}) + + transformedSyncRepo, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncRepo(original["sync_repo"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSyncRepo); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["syncRepo"] = transformedSyncRepo + } + + transformedSyncBranch, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncBranch(original["sync_branch"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSyncBranch); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["syncBranch"] = transformedSyncBranch + } + + transformedPolicyDir, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitPolicyDir(original["policy_dir"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPolicyDir); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["policyDir"] = transformedPolicyDir + } + + transformedSyncRev, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncRev(original["sync_rev"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSyncRev); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["syncRev"] = transformedSyncRev + } + + transformedSecretType, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSecretType(original["secret_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSecretType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["secretType"] = transformedSecretType + } + + transformedHttpsProxy, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitHttpsProxy(original["https_proxy"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHttpsProxy); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["httpsProxy"] = transformedHttpsProxy + } + + transformedGcpServiceAccountEmail, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitGcpServiceAccountEmail(original["gcp_service_account_email"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedGcpServiceAccountEmail); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["gcpServiceAccountEmail"] = transformedGcpServiceAccountEmail + } + + transformedSyncWaitSecs, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncWaitSecs(original["sync_wait_secs"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSyncWaitSecs); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["syncWaitSecs"] = transformedSyncWaitSecs + } + + return transformed, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncRepo(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncBranch(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitPolicyDir(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncRev(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSecretType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitHttpsProxy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitGcpServiceAccountEmail(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncGitSyncWaitSecs(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOci(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{}) + + transformedSyncRepo, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSyncRepo(original["sync_repo"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSyncRepo); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["syncRepo"] = transformedSyncRepo + } + + transformedPolicyDir, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciPolicyDir(original["policy_dir"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPolicyDir); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["policyDir"] = transformedPolicyDir + } + + transformedSecretType, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSecretType(original["secret_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSecretType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["secretType"] = transformedSecretType + } + + transformedGcpServiceAccountEmail, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciGcpServiceAccountEmail(original["gcp_service_account_email"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedGcpServiceAccountEmail); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["gcpServiceAccountEmail"] = transformedGcpServiceAccountEmail + } + + transformedSyncWaitSecs, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSyncWaitSecs(original["sync_wait_secs"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSyncWaitSecs); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["syncWaitSecs"] = transformedSyncWaitSecs + } + + transformedVersion, err := expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciVersion(original["version"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVersion); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["version"] = transformedVersion + } + + return transformed, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSyncRepo(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciPolicyDir(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSecretType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciGcpServiceAccountEmail(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciSyncWaitSecs(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandGKEHub2FeatureFleetDefaultMemberConfigConfigmanagementConfigSyncOciVersion(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandGKEHub2FeatureEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { if v == nil { return map[string]string{}, nil diff --git a/google-beta/services/gkehub2/resource_gke_hub_feature_test.go b/google-beta/services/gkehub2/resource_gke_hub_feature_test.go index 3c1b8656fb..e1e74f7920 100644 --- a/google-beta/services/gkehub2/resource_gke_hub_feature_test.go +++ b/google-beta/services/gkehub2/resource_gke_hub_feature_test.go @@ -346,6 +346,163 @@ resource "google_gke_hub_feature" "feature" { `, context) } +func TestAccGKEHubFeature_FleetDefaultMemberConfigServiceMesh(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), + Steps: []resource.TestStep{ + { + Config: testAccGKEHubFeature_FleetDefaultMemberConfigServiceMesh(context), + }, + { + ResourceName: "google_gke_hub_feature.feature", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"project"}, + }, + { + Config: testAccGKEHubFeature_FleetDefaultMemberConfigServiceMeshUpdate(context), + }, + { + ResourceName: "google_gke_hub_feature.feature", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccGKEHubFeature_FleetDefaultMemberConfigServiceMesh(context map[string]interface{}) string { + return gkeHubFeatureProjectSetupForGA(context) + acctest.Nprintf(` +resource "google_gke_hub_feature" "feature" { + name = "servicemesh" + location = "global" + fleet_default_member_config { + mesh { + management = "MANAGEMENT_AUTOMATIC" + } + } + depends_on = [google_project_service.anthos, google_project_service.gkehub, google_project_service.mesh] + project = google_project.project.project_id +} +`, context) +} + +func testAccGKEHubFeature_FleetDefaultMemberConfigServiceMeshUpdate(context map[string]interface{}) string { + return gkeHubFeatureProjectSetupForGA(context) + acctest.Nprintf(` +resource "google_gke_hub_feature" "feature" { + name = "servicemesh" + location = "global" + fleet_default_member_config { + mesh { + management = "MANAGEMENT_MANUAL" + } + } + depends_on = [google_project_service.anthos, google_project_service.gkehub, google_project_service.mesh] + project = google_project.project.project_id +} +`, context) +} + +func TestAccGKEHubFeature_FleetDefaultMemberConfigConfigManagement(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), + Steps: []resource.TestStep{ + { + Config: testAccGKEHubFeature_FleetDefaultMemberConfigConfigManagement(context), + }, + { + ResourceName: "google_gke_hub_feature.feature", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"project"}, + }, + { + Config: testAccGKEHubFeature_FleetDefaultMemberConfigConfigManagementUpdate(context), + }, + { + ResourceName: "google_gke_hub_feature.feature", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccGKEHubFeature_FleetDefaultMemberConfigConfigManagement(context map[string]interface{}) string { + return gkeHubFeatureProjectSetupForGA(context) + acctest.Nprintf(` +resource "google_gke_hub_feature" "feature" { + name = "configmanagement" + location = "global" + fleet_default_member_config { + configmanagement { + config_sync { + source_format = "hierarchy" + git { + sync_repo = "https://github.com/GoogleCloudPlatform/magic-modules" + sync_branch = "master" + policy_dir = "." + sync_rev = "HEAD" + secret_type = "none" + sync_wait_secs = "15" + } + } + } + } + depends_on = [google_project_service.anthos, google_project_service.gkehub, google_project_service.acm] + project = google_project.project.project_id +} +`, context) +} + +func testAccGKEHubFeature_FleetDefaultMemberConfigConfigManagementUpdate(context map[string]interface{}) string { + return gkeHubFeatureProjectSetupForGA(context) + acctest.Nprintf(` +resource "google_gke_hub_feature" "feature" { + name = "configmanagement" + location = "global" + fleet_default_member_config { + configmanagement { + config_sync { + source_format = "unstructured" + oci { + sync_repo = "us-central1-docker.pkg.dev/corp-gke-build-artifacts/acm/configs:latest" + policy_dir = "/acm/nonprod-root/" + secret_type = "gcpserviceaccount" + sync_wait_secs = "15" + gcp_service_account_email = "gke-cluster@gke-foo-nonprod.iam.gserviceaccount.com" + } + } + } + } + depends_on = [google_project_service.anthos, google_project_service.gkehub, google_project_service.acm] + project = google_project.project.project_id +} +`, context) +} + func TestAccGKEHubFeature_gkehubFeatureMcsd(t *testing.T) { // VCR fails to handle batched project services acctest.SkipIfVcr(t) @@ -454,6 +611,11 @@ resource "google_project_service" "container" { disable_on_destroy = false } +resource "google_project_service" "anthos" { + project = google_project.project.project_id + service = "anthos.googleapis.com" +} + resource "google_project_service" "gkehub" { project = google_project.project.project_id service = "gkehub.googleapis.com" diff --git a/website/docs/r/gke_hub_feature.html.markdown b/website/docs/r/gke_hub_feature.html.markdown index fff390b5e7..89bd68e5e3 100644 --- a/website/docs/r/gke_hub_feature.html.markdown +++ b/website/docs/r/gke_hub_feature.html.markdown @@ -136,6 +136,38 @@ resource "google_gke_hub_feature" "feature" { } } ``` +## Example Usage - Enable Fleet Default Member Config Service Mesh + + +```hcl +resource "google_gke_hub_feature" "feature" { + name = "servicemesh" + location = "global" + fleetDefaultMemberConfig { + mesh { + management = "MANAGEMENT_AUTOMATIC" + } + } +} +``` +## Example Usage - Enable Fleet Default Member Config Configmanagement + + +```hcl +resource "google_gke_hub_feature" "feature" { + name = "configmanagement" + location = "global" + fleetDefaultMemberConfig { + configmanagement { + config_sync { + git { + sync_repo = "https://github.com/hashicorp/terraform" + } + } + } + } +} +``` ## Argument Reference @@ -165,6 +197,11 @@ The following arguments are supported: Optional. Hub-wide Feature configuration. If this Feature does not support any Hub-wide configuration, this field may be unused. Structure is [documented below](#nested_spec). +* `fleet_default_member_config` - + (Optional) + Optional. Fleet Default Membership Configuration. + Structure is [documented below](#nested_fleet_default_member_config). + * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. @@ -223,6 +260,111 @@ The following arguments are supported: Specified if fleet logging feature is enabled. Possible values are: `MODE_UNSPECIFIED`, `COPY`, `MOVE`. +The `fleet_default_member_config` block supports: + +* `mesh` - + (Optional) + Service Mesh spec + Structure is [documented below](#nested_mesh). + +* `configmanagement` - + (Optional) + Config Management spec + Structure is [documented below](#nested_configmanagement). + + +The `mesh` block supports: + +* `management` - + (Required) + Whether to automatically manage Service Mesh + Possible values are: `MANAGEMENT_UNSPECIFIED`, `MANAGEMENT_AUTOMATIC`, `MANAGEMENT_MANUAL`. + +The `configmanagement` block supports: + +* `config_sync` - + (Optional) + ConfigSync configuration for the cluster + Structure is [documented below](#nested_config_sync). + + +The `config_sync` block supports: + +* `source_format` - + (Optional) + Specifies whether the Config Sync Repo is in hierarchical or unstructured mode + +* `git` - + (Optional) + Git repo configuration for the cluster + Structure is [documented below](#nested_git). + +* `oci` - + (Optional) + OCI repo configuration for the cluster + Structure is [documented below](#nested_oci). + + +The `git` block supports: + +* `sync_repo` - + (Optional) + The URL of the Git repository to use as the source of truth + +* `sync_branch` - + (Optional) + The branch of the repository to sync from. Default: master + +* `policy_dir` - + (Optional) + The path within the Git repository that represents the top level of the repo to sync + +* `sync_rev` - + (Optional) + Git revision (tag or hash) to check out. Default HEAD + +* `secret_type` - + (Required) + Type of secret configured for access to the Git repo + +* `https_proxy` - + (Optional) + URL for the HTTPS Proxy to be used when communicating with the Git repo + +* `gcp_service_account_email` - + (Optional) + The Google Cloud Service Account Email used for auth when secretType is gcpServiceAccount + +* `sync_wait_secs` - + (Optional) + Period in seconds between consecutive syncs. Default: 15 + +The `oci` block supports: + +* `sync_repo` - + (Optional) + The OCI image repository URL for the package to sync from + +* `policy_dir` - + (Optional) + The absolute path of the directory that contains the local resources. Default: the root directory of the image + +* `secret_type` - + (Required) + Type of secret configured for access to the Git repo + +* `gcp_service_account_email` - + (Optional) + The Google Cloud Service Account Email used for auth when secretType is gcpServiceAccount + +* `sync_wait_secs` - + (Optional) + Period in seconds between consecutive syncs. Default: 15 + +* `version` - + (Optional) + Version of ACM installed + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: