From d9bcd052fa5bbdc706626532caeeb0e5e4ea2760 Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Thu, 14 Sep 2023 14:09:05 +0000 Subject: [PATCH] Artifact Registry: implement VPC SC Config (#8787) * Artifact Registry: implement VPC SC Config * Altering behavior from reset resource to simply drop resource * removing skip_test * re-adding skip_test since organization-level resources are out of scope for testing Signed-off-by: Modular Magician --- .changelog/8787.txt | 3 + google-beta/provider/provider.go | 5 +- ...resource_artifact_registry_vpcsc_config.go | 307 ++++++++++++++++++ ...tifact_registry_vpcsc_config.html.markdown | 101 ++++++ 4 files changed, 414 insertions(+), 2 deletions(-) create mode 100644 .changelog/8787.txt create mode 100644 google-beta/services/artifactregistry/resource_artifact_registry_vpcsc_config.go create mode 100644 website/docs/r/artifact_registry_vpcsc_config.html.markdown diff --git a/.changelog/8787.txt b/.changelog/8787.txt new file mode 100644 index 0000000000..adcaa1ffef --- /dev/null +++ b/.changelog/8787.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +`google_artifact_registry_vpcsc_config` +``` diff --git a/google-beta/provider/provider.go b/google-beta/provider/provider.go index 9c47f3aff4..b89a6a4586 100644 --- a/google-beta/provider/provider.go +++ b/google-beta/provider/provider.go @@ -1114,9 +1114,9 @@ func DatasourceMapWithErrors() (map[string]*schema.Resource, error) { }) } -// Generated resources: 383 +// Generated resources: 384 // Generated IAM resources: 237 -// Total generated resources: 620 +// Total generated resources: 621 func ResourceMap() map[string]*schema.Resource { resourceMap, _ := ResourceMapWithErrors() return resourceMap @@ -1190,6 +1190,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) { "google_artifact_registry_repository_iam_binding": tpgiamresource.ResourceIamBinding(artifactregistry.ArtifactRegistryRepositoryIamSchema, artifactregistry.ArtifactRegistryRepositoryIamUpdaterProducer, artifactregistry.ArtifactRegistryRepositoryIdParseFunc), "google_artifact_registry_repository_iam_member": tpgiamresource.ResourceIamMember(artifactregistry.ArtifactRegistryRepositoryIamSchema, artifactregistry.ArtifactRegistryRepositoryIamUpdaterProducer, artifactregistry.ArtifactRegistryRepositoryIdParseFunc), "google_artifact_registry_repository_iam_policy": tpgiamresource.ResourceIamPolicy(artifactregistry.ArtifactRegistryRepositoryIamSchema, artifactregistry.ArtifactRegistryRepositoryIamUpdaterProducer, artifactregistry.ArtifactRegistryRepositoryIdParseFunc), + "google_artifact_registry_vpcsc_config": artifactregistry.ResourceArtifactRegistryVPCSCConfig(), "google_backup_dr_management_server": backupdr.ResourceBackupDRManagementServer(), "google_beyondcorp_app_connection": beyondcorp.ResourceBeyondcorpAppConnection(), "google_beyondcorp_app_connector": beyondcorp.ResourceBeyondcorpAppConnector(), diff --git a/google-beta/services/artifactregistry/resource_artifact_registry_vpcsc_config.go b/google-beta/services/artifactregistry/resource_artifact_registry_vpcsc_config.go new file mode 100644 index 0000000000..c155b092e0 --- /dev/null +++ b/google-beta/services/artifactregistry/resource_artifact_registry_vpcsc_config.go @@ -0,0 +1,307 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package artifactregistry + +import ( + "fmt" + "log" + "reflect" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" +) + +func ResourceArtifactRegistryVPCSCConfig() *schema.Resource { + return &schema.Resource{ + Create: resourceArtifactRegistryVPCSCConfigCreate, + Read: resourceArtifactRegistryVPCSCConfigRead, + Update: resourceArtifactRegistryVPCSCConfigUpdate, + Delete: resourceArtifactRegistryVPCSCConfigDelete, + + Importer: &schema.ResourceImporter{ + State: resourceArtifactRegistryVPCSCConfigImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "location": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + Description: `The name of the location this config is located in.`, + }, + "vpcsc_policy": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"DENY", "ALLOW", ""}), + Description: `The VPC SC policy for project and location. Possible values: ["DENY", "ALLOW"]`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the project's VPC SC Config. +Always of the form: projects/{project}/location/{location}/vpcscConfig`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceArtifactRegistryVPCSCConfigCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + vpcscPolicyProp, err := expandArtifactRegistryVPCSCConfigVpcscPolicy(d.Get("vpcsc_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("vpcsc_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(vpcscPolicyProp)) && (ok || !reflect.DeepEqual(v, vpcscPolicyProp)) { + obj["vpcscPolicy"] = vpcscPolicyProp + } + + obj, err = resourceArtifactRegistryVPCSCConfigEncoder(d, meta, obj) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{ArtifactRegistryBasePath}}projects/{{project}}/locations/{{location}}/vpcscConfig") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new VPCSCConfig: %#v", obj) + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for VPCSCConfig: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + }) + if err != nil { + return fmt.Errorf("Error creating VPCSCConfig: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/vpcscConfig") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + log.Printf("[DEBUG] Finished creating VPCSCConfig %q: %#v", d.Id(), res) + + return resourceArtifactRegistryVPCSCConfigRead(d, meta) +} + +func resourceArtifactRegistryVPCSCConfigRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{ArtifactRegistryBasePath}}projects/{{project}}/locations/{{location}}/vpcscConfig") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for VPCSCConfig: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("ArtifactRegistryVPCSCConfig %q", d.Id())) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading VPCSCConfig: %s", err) + } + + if err := d.Set("vpcsc_policy", flattenArtifactRegistryVPCSCConfigVpcscPolicy(res["vpcscPolicy"], d, config)); err != nil { + return fmt.Errorf("Error reading VPCSCConfig: %s", err) + } + if err := d.Set("name", flattenArtifactRegistryVPCSCConfigName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading VPCSCConfig: %s", err) + } + + return nil +} + +func resourceArtifactRegistryVPCSCConfigUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for VPCSCConfig: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + vpcscPolicyProp, err := expandArtifactRegistryVPCSCConfigVpcscPolicy(d.Get("vpcsc_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("vpcsc_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, vpcscPolicyProp)) { + obj["vpcscPolicy"] = vpcscPolicyProp + } + + obj, err = resourceArtifactRegistryVPCSCConfigEncoder(d, meta, obj) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{ArtifactRegistryBasePath}}projects/{{project}}/locations/{{location}}/vpcscConfig") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating VPCSCConfig %q: %#v", d.Id(), obj) + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + + if err != nil { + return fmt.Errorf("Error updating VPCSCConfig %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating VPCSCConfig %q: %#v", d.Id(), res) + } + + return resourceArtifactRegistryVPCSCConfigRead(d, meta) +} + +func resourceArtifactRegistryVPCSCConfigDelete(d *schema.ResourceData, meta interface{}) error { + log.Printf("[WARNING] ArtifactRegistry VPCSCConfig resources"+ + " cannot be deleted from Google Cloud. The resource %s will be removed from Terraform"+ + " state, but will still be present on Google Cloud.", d.Id()) + d.SetId("") + + return nil +} + +func resourceArtifactRegistryVPCSCConfigImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "projects/(?P[^/]+)/locations/(?P[^/]+)/vpcscConfig/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)/(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/vpcscConfig") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenArtifactRegistryVPCSCConfigVpcscPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenArtifactRegistryVPCSCConfigName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandArtifactRegistryVPCSCConfigVpcscPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func resourceArtifactRegistryVPCSCConfigEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + config := meta.(*transport_tpg.Config) + if _, ok := d.GetOk("location"); !ok { + location, err := tpgresource.GetRegionFromSchema("region", "zone", d, config) + if err != nil { + return nil, fmt.Errorf("Cannot determine location: set in this resource, or set provider-level 'region' or 'zone'.") + } + if err := d.Set("location", location); err != nil { + return nil, fmt.Errorf("Error setting location: %s", err) + } + } + return obj, nil +} diff --git a/website/docs/r/artifact_registry_vpcsc_config.html.markdown b/website/docs/r/artifact_registry_vpcsc_config.html.markdown new file mode 100644 index 0000000000..7ad6bf6b36 --- /dev/null +++ b/website/docs/r/artifact_registry_vpcsc_config.html.markdown @@ -0,0 +1,101 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- +subcategory: "Artifact Registry" +description: |- + The Artifact Registry VPC SC config that applies to a Project. +--- + +# google\_artifact\_registry\_vpcsc\_config + +The Artifact Registry VPC SC config that applies to a Project. + +~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. +See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. + +To get more information about VPCSCConfig, see: + +* [API documentation](https://cloud.google.com/artifact-registry/docs/reference/rest/v1/VPCSCConfig) + +~> **Note:** VPC SC configs are automatically created for a given location. Creating a +resource of this type will acquire and update the resource that already +exists at the location. Deleting this resource will remove the config from +your Terraform state but leave the resource as is. +## Example Usage - Artifact Registry Vpcsc Config + + +```hcl +resource "google_artifact_registry_vpcsc_config" "my-config" { + provider = google-beta + location = "us-central1" + vpcsc_policy = "ALLOW" +} +``` + +## Argument Reference + +The following arguments are supported: + + + +- - - + + +* `vpcsc_policy` - + (Optional) + The VPC SC policy for project and location. + Possible values are: `DENY`, `ALLOW`. + +* `location` - + (Optional) + The name of the location this config is located in. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/locations/{{location}}/vpcscConfig` + +* `name` - + The name of the project's VPC SC Config. + Always of the form: projects/{project}/location/{location}/vpcscConfig + + +## Timeouts + +This resource provides the following +[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: + +- `create` - Default is 20 minutes. +- `update` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + + +VPCSCConfig can be imported using any of these accepted formats: + +``` +$ terraform import google_artifact_registry_vpcsc_config.default projects/{{project}}/locations/{{location}}/vpcscConfig/{{name}} +$ terraform import google_artifact_registry_vpcsc_config.default {{project}}/{{location}}/{{name}} +$ terraform import google_artifact_registry_vpcsc_config.default {{location}}/{{name}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override).