diff --git a/.changelog/18887.txt b/.changelog/18887.txt new file mode 100644 index 00000000000..f74bb1c19cf --- /dev/null +++ b/.changelog/18887.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +`google_compute_network_edge_security_service` (ga) +``` \ No newline at end of file diff --git a/google/services/compute/resource_compute_network_edge_security_service.go b/google/services/compute/resource_compute_network_edge_security_service.go new file mode 100644 index 00000000000..41d0de7350d --- /dev/null +++ b/google/services/compute/resource_compute_network_edge_security_service.go @@ -0,0 +1,706 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This code is generated by Magic Modules using the following: +// +// Configuration: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/compute/NetworkEdgeSecurityService.yaml +// Template: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/resource.go.tmpl +// +// DO NOT EDIT this file directly. Any changes made to this file will be +// overwritten during the next generation cycle. +// +// ---------------------------------------------------------------------------- + +package compute + +import ( + "bytes" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "log" + "net/http" + "reflect" + "regexp" + "slices" + "sort" + "strconv" + "strings" + "time" + + "github.com/hashicorp/errwrap" + "github.com/hashicorp/go-cty/cty" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-google/google/registry" + "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" + + "google.golang.org/api/googleapi" +) + +var ( + _ = bytes.Clone + _ = context.WithCancel + _ = base64.NewDecoder + _ = json.Marshal + _ = fmt.Sprintf + _ = log.Print + _ = http.Get + _ = reflect.ValueOf + _ = regexp.Match + _ = slices.Min([]int{1}) + _ = sort.IntSlice{} + _ = strconv.Atoi + _ = strings.Trim + _ = time.Now + _ = errwrap.Wrap + _ = cty.BoolVal + _ = diag.Diagnostic{} + _ = customdiff.All + _ = id.UniqueId + _ = logging.LogLevel + _ = retry.Retry + _ = schema.Noop + _ = validation.All + _ = structure.ExpandJsonFromString + _ = terraform.State{} + _ = tpgresource.SetLabels + _ = transport_tpg.Config{} + _ = verify.ValidateEnum + _ = googleapi.Error{} +) + +func init() { + registry.Schema{ + Name: "google_compute_network_edge_security_service", + ProductName: "compute", + Type: registry.SchemaTypeResource, + Schema: ResourceComputeNetworkEdgeSecurityService(), + }.Register() +} + +func ResourceComputeNetworkEdgeSecurityService() *schema.Resource { + return &schema.Resource{ + Create: resourceComputeNetworkEdgeSecurityServiceCreate, + Read: resourceComputeNetworkEdgeSecurityServiceRead, + Update: resourceComputeNetworkEdgeSecurityServiceUpdate, + Delete: resourceComputeNetworkEdgeSecurityServiceDelete, + + Importer: &schema.ResourceImporter{ + State: resourceComputeNetworkEdgeSecurityServiceImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderDeletionPolicy("DELETE"), + ), + + Identity: &schema.ResourceIdentity{ + Version: 1, + SchemaFunc: func() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + RequiredForImport: true, + }, + "region": { + Type: schema.TypeString, + OptionalForImport: true, + }, + "project": { + Type: schema.TypeString, + OptionalForImport: true, + }, + } + }, + }, + ResourceBehavior: schema.ResourceBehavior{ + MutableIdentity: true, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Name of the resource. Provided by the client when the resource is created.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `Free-text description of the resource.`, + }, + "region": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The region of the gateway security policy.`, + }, + "security_policy": { + Type: schema.TypeString, + Optional: true, + Description: `The resource URL for the network edge security service associated with this network edge security service.`, + }, + "creation_timestamp": { + Type: schema.TypeString, + Computed: true, + Description: `Creation timestamp in RFC3339 text format.`, + }, + "fingerprint": { + Type: schema.TypeString, + Computed: true, + Description: `Fingerprint of this resource. A hash of the contents stored in this object. This field is used in optimistic locking. This field will be ignored when inserting a NetworkEdgeSecurityService. +An up-to-date fingerprint must be provided in order to update the NetworkEdgeSecurityService, otherwise the request will fail with error 412 conditionNotMet.`, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `Server-defined URL for the resource.`, + }, + "self_link_with_service_id": { + Type: schema.TypeString, + Computed: true, + Description: `Server-defined URL for this resource with the resource id.`, + }, + "service_id": { + Type: schema.TypeString, + Computed: true, + Description: `The unique identifier for the resource. This identifier is defined by the server.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "deletion_policy": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Whether Terraform will be prevented from destroying the instance. Defaults to "DELETE". +When a 'terraform destroy' or 'terraform apply' would delete the instance, +the command will fail if this field is set to "PREVENT" in Terraform state. +When set to "ABANDON", the command will remove the resource from Terraform +management without updating or deleting the resource in the API. +When set to "DELETE", deleting the resource is allowed. +`, + }, + }, + UseJSONNumber: true, + } +} + +func resourceComputeNetworkEdgeSecurityServiceCreate(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{}) + nameProp, err := expandComputeNetworkEdgeSecurityServiceName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + descriptionProp, err := expandComputeNetworkEdgeSecurityServiceDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + fingerprintProp, err := expandComputeNetworkEdgeSecurityServiceFingerprint(d.Get("fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(fingerprintProp)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { + obj["fingerprint"] = fingerprintProp + } + securityPolicyProp, err := expandComputeNetworkEdgeSecurityServiceSecurityPolicy(d.Get("security_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("security_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(securityPolicyProp)) && (ok || !reflect.DeepEqual(v, securityPolicyProp)) { + obj["securityPolicy"] = securityPolicyProp + } + + url, err := tpgresource.ReplaceVars(d, config, transport_tpg.BaseUrl(Product, config)+"projects/{{project}}/regions/{{region}}/networkEdgeSecurityServices?networkEdgeSecurityService={{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new NetworkEdgeSecurityService: %#v", obj) + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for NetworkEdgeSecurityService: %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 + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + Headers: headers, + }) + if err != nil { + return fmt.Errorf("Error creating NetworkEdgeSecurityService: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/regions/{{region}}/networkEdgeSecurityServices/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = ComputeOperationWaitTime( + config, res, project, "Creating NetworkEdgeSecurityService", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create NetworkEdgeSecurityService: %s", err) + } + + log.Printf("[DEBUG] Finished creating NetworkEdgeSecurityService %q: %#v", d.Id(), res) + + identity, err := d.Identity() + if err == nil && identity != nil { + if nameValue, ok := d.GetOk("name"); ok && nameValue.(string) != "" { + if err = identity.Set("name", nameValue.(string)); err != nil { + return fmt.Errorf("Error setting name: %s", err) + } + } + if regionValue, ok := d.GetOk("region"); ok && regionValue.(string) != "" { + if err = identity.Set("region", regionValue.(string)); err != nil { + return fmt.Errorf("Error setting region: %s", err) + } + } + if projectValue, ok := d.GetOk("project"); ok && projectValue.(string) != "" { + if err = identity.Set("project", projectValue.(string)); err != nil { + return fmt.Errorf("Error setting project: %s", err) + } + } + } else { + log.Printf("[DEBUG] (Create) identity not set: %s", err) + } + + return resourceComputeNetworkEdgeSecurityServiceRead(d, meta) +} + +func resourceComputeNetworkEdgeSecurityServiceRead(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, transport_tpg.BaseUrl(Product, config)+"projects/{{project}}/regions/{{region}}/networkEdgeSecurityServices/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for NetworkEdgeSecurityService: %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 + } + + headers := make(http.Header) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("ComputeNetworkEdgeSecurityService %q", d.Id())) + } + + log.Printf("[DEBUG] Finished reading ComputeNetworkEdgeSecurityService %q: %#v", d.Id(), res) + + // Explicitly set virtual fields to default values if unset + if _, ok := d.GetOkExists("deletion_policy"); !ok { + //prioritize config's value if present + if config.DeletionPolicy != "" { + if err := d.Set("deletion_policy", config.DeletionPolicy); err != nil { + return fmt.Errorf("Error setting deletion_policy: %s", err) + } + } else { + if err := d.Set("deletion_policy", "DELETE"); err != nil { + return fmt.Errorf("Error setting deletion_policy: %s", err) + } + } + } + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading NetworkEdgeSecurityService: %s", err) + } + + err = ResourceComputeNetworkEdgeSecurityServiceFlatten(d, meta, res, config, project, userAgent, billingProject, url, headers) + if err != nil { + return err + } + + identity, err := d.Identity() + if err == nil && identity != nil { + if v, ok := identity.GetOk("name"); !ok && v == "" { + err = identity.Set("name", d.Get("name").(string)) + if err != nil { + return fmt.Errorf("Error setting name: %s", err) + } + } + if v, ok := identity.GetOk("region"); !ok && v == "" { + err = identity.Set("region", d.Get("region").(string)) + if err != nil { + return fmt.Errorf("Error setting region: %s", err) + } + } + if v, ok := identity.GetOk("project"); !ok && v == "" { + err = identity.Set("project", d.Get("project").(string)) + if err != nil { + return fmt.Errorf("Error setting project: %s", err) + } + } + } else { + log.Printf("[DEBUG] (Read) identity not set: %s", err) + } + + return nil +} + +func resourceComputeNetworkEdgeSecurityServiceUpdate(d *schema.ResourceData, meta interface{}) error { + clientSideFields := map[string]bool{"deletion_policy": true} + clientSideOnly := true + for field := range ResourceComputeNetworkEdgeSecurityService().Schema { + if d.HasChange(field) && !clientSideFields[field] { + clientSideOnly = false + break + } + } + if clientSideOnly { + log.Print("[DEBUG] Only client-side changes detected. Cancelling update operation.") + return resourceComputeNetworkEdgeSecurityServiceRead(d, meta) + } + + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + identity, err := d.Identity() + if err == nil && identity != nil { + if nameValue, ok := d.GetOk("name"); ok && nameValue.(string) != "" { + if err = identity.Set("name", nameValue.(string)); err != nil { + return fmt.Errorf("Error setting name: %s", err) + } + } + if regionValue, ok := d.GetOk("region"); ok && regionValue.(string) != "" { + if err = identity.Set("region", regionValue.(string)); err != nil { + return fmt.Errorf("Error setting region: %s", err) + } + } + if projectValue, ok := d.GetOk("project"); ok && projectValue.(string) != "" { + if err = identity.Set("project", projectValue.(string)); err != nil { + return fmt.Errorf("Error setting project: %s", err) + } + } + } else { + log.Printf("[DEBUG] (Update) identity not set: %s", err) + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for NetworkEdgeSecurityService: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + descriptionProp, err := expandComputeNetworkEdgeSecurityServiceDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + fingerprintProp, err := expandComputeNetworkEdgeSecurityServiceFingerprint(d.Get("fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { + obj["fingerprint"] = fingerprintProp + } + securityPolicyProp, err := expandComputeNetworkEdgeSecurityServiceSecurityPolicy(d.Get("security_policy"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("security_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, securityPolicyProp)) { + obj["securityPolicy"] = securityPolicyProp + } + + url, err := tpgresource.ReplaceVars(d, config, transport_tpg.BaseUrl(Product, config)+"projects/{{project}}/regions/{{region}}/networkEdgeSecurityServices/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating NetworkEdgeSecurityService %q: %#v", d.Id(), obj) + headers := make(http.Header) + updateMask := []string{} + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("fingerprint") { + updateMask = append(updateMask, "fingerprint") + } + + if d.HasChange("security_policy") { + updateMask = append(updateMask, "securityPolicy") + } + // updateMask is a URL parameter but not present in the schema, so ReplaceVars + // won't set it + url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + // if updateMask is empty we are not updating anything so skip the post + if len(updateMask) > 0 { + 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), + Headers: headers, + }) + + if err != nil { + return fmt.Errorf("Error updating NetworkEdgeSecurityService %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating NetworkEdgeSecurityService %q: %#v", d.Id(), res) + } + + err = ComputeOperationWaitTime( + config, res, project, "Updating NetworkEdgeSecurityService", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + } + + return resourceComputeNetworkEdgeSecurityServiceRead(d, meta) +} + +func resourceComputeNetworkEdgeSecurityServiceDelete(d *schema.ResourceData, meta interface{}) error { + if d.Get("deletion_policy").(string) == "PREVENT" { + return fmt.Errorf("cannot destroy ComputeNetworkEdgeSecurityService without setting deletion_policy=\"DELETE\" and running `terraform apply`") + } + if d.Get("deletion_policy").(string) == "ABANDON" { + log.Printf("[DEBUG] deletion_policy set to \"ABANDON\", removing NetworkEdgeSecurityService %q from Terraform state without deletion", d.Id()) + return nil + } + 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 NetworkEdgeSecurityService: %s", err) + } + billingProject = project + url, err := tpgresource.ReplaceVars(d, config, transport_tpg.BaseUrl(Product, config)+"projects/{{project}}/regions/{{region}}/networkEdgeSecurityServices/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + headers := make(http.Header) + + log.Printf("[DEBUG] Deleting NetworkEdgeSecurityService %q", d.Id()) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutDelete), + Headers: headers, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "NetworkEdgeSecurityService") + } + + err = ComputeOperationWaitTime( + config, res, project, "Deleting NetworkEdgeSecurityService", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting NetworkEdgeSecurityService %q: %#v", d.Id(), res) + return nil +} + +func resourceComputeNetworkEdgeSecurityServiceImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^projects/(?P[^/]+)/regions/(?P[^/]+)/networkEdgeSecurityServices/(?P[^/]+)$", + "^(?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}}/regions/{{region}}/networkEdgeSecurityServices/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenComputeNetworkEdgeSecurityServiceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenComputeNetworkEdgeSecurityServiceDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenComputeNetworkEdgeSecurityServiceServiceId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenComputeNetworkEdgeSecurityServiceCreationTimestamp(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenComputeNetworkEdgeSecurityServiceSelfLink(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenComputeNetworkEdgeSecurityServiceSelfLinkWithServiceId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenComputeNetworkEdgeSecurityServiceFingerprint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenComputeNetworkEdgeSecurityServiceSecurityPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandComputeNetworkEdgeSecurityServiceName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandComputeNetworkEdgeSecurityServiceDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandComputeNetworkEdgeSecurityServiceFingerprint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandComputeNetworkEdgeSecurityServiceSecurityPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func ResourceComputeNetworkEdgeSecurityServiceFlatten(d *schema.ResourceData, meta interface{}, res map[string]interface{}, config *transport_tpg.Config, project string, userAgent string, billingProject string, url string, headers http.Header) error { + var err error + + if err = d.Set("name", flattenComputeNetworkEdgeSecurityServiceName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading NetworkEdgeSecurityService: %s", err) + } + if err = d.Set("description", flattenComputeNetworkEdgeSecurityServiceDescription(res["description"], d, config)); err != nil { + return fmt.Errorf("Error reading NetworkEdgeSecurityService: %s", err) + } + if err = d.Set("service_id", flattenComputeNetworkEdgeSecurityServiceServiceId(res["id"], d, config)); err != nil { + return fmt.Errorf("Error reading NetworkEdgeSecurityService: %s", err) + } + if err = d.Set("creation_timestamp", flattenComputeNetworkEdgeSecurityServiceCreationTimestamp(res["creationTimestamp"], d, config)); err != nil { + return fmt.Errorf("Error reading NetworkEdgeSecurityService: %s", err) + } + if err = d.Set("self_link", flattenComputeNetworkEdgeSecurityServiceSelfLink(res["selfLink"], d, config)); err != nil { + return fmt.Errorf("Error reading NetworkEdgeSecurityService: %s", err) + } + if err = d.Set("self_link_with_service_id", flattenComputeNetworkEdgeSecurityServiceSelfLinkWithServiceId(res["selfLinkWithId"], d, config)); err != nil { + return fmt.Errorf("Error reading NetworkEdgeSecurityService: %s", err) + } + if err = d.Set("fingerprint", flattenComputeNetworkEdgeSecurityServiceFingerprint(res["fingerprint"], d, config)); err != nil { + return fmt.Errorf("Error reading NetworkEdgeSecurityService: %s", err) + } + if err = d.Set("security_policy", flattenComputeNetworkEdgeSecurityServiceSecurityPolicy(res["securityPolicy"], d, config)); err != nil { + return fmt.Errorf("Error reading NetworkEdgeSecurityService: %s", err) + } + + return nil +} diff --git a/google/services/compute/resource_compute_network_edge_security_service_generated_meta.yaml b/google/services/compute/resource_compute_network_edge_security_service_generated_meta.yaml new file mode 100644 index 00000000000..47e1fc236e3 --- /dev/null +++ b/google/services/compute/resource_compute_network_edge_security_service_generated_meta.yaml @@ -0,0 +1,23 @@ +# Copyright IBM Corp. 2014, 2026 +# SPDX-License-Identifier: MPL-2.0 +resource: google_compute_network_edge_security_service +generation_type: mmv1 +source_file: products/compute/NetworkEdgeSecurityService.yaml +api_service_name: compute.googleapis.com +api_version: v1 +api_resource_type_kind: NetworkEdgeSecurityService +fields: + - api_field: creationTimestamp + - api_field: description + - api_field: fingerprint + - api_field: name + - field: region + provider_only: true + - api_field: securityPolicy + - api_field: selfLink + - api_field: selfLinkWithId + field: self_link_with_service_id + - api_field: id + field: service_id + - field: deletion_policy + provider_only: true diff --git a/google/services/compute/resource_compute_network_edge_security_service_generated_test.go b/google/services/compute/resource_compute_network_edge_security_service_generated_test.go new file mode 100644 index 00000000000..1def9ca9a20 --- /dev/null +++ b/google/services/compute/resource_compute_network_edge_security_service_generated_test.go @@ -0,0 +1,139 @@ +// Copyright IBM Corp. 2014, 2026 +// 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 compute_test + +import ( + "fmt" + "log" + "regexp" + "strconv" + "strings" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/services/compute" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + + "google.golang.org/api/googleapi" +) + +var ( + _ = fmt.Sprintf + _ = log.Print + _ = regexp.MatchString + _ = strconv.Atoi + _ = strings.Trim + _ = time.Now + _ = resource.TestMain + _ = terraform.NewState + _ = envvar.TestEnvVar + _ = tpgresource.SetLabels + _ = transport_tpg.Config{} + _ = googleapi.Error{} + _ = compute.Product +) + +func TestAccComputeNetworkEdgeSecurityService_computeNetworkEdgeSecurityServiceBasicExample(t *testing.T) { + t.Parallel() + + randomSuffix := acctest.RandString(t, 10) + + context := map[string]interface{}{ + "project_id": envvar.GetTestProjectFromEnv(), + "region": "us-east1", + "resource_name": "tf-test-my-edge-security-service" + randomSuffix, + "random_suffix": randomSuffix, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeNetworkEdgeSecurityServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeNetworkEdgeSecurityService_computeNetworkEdgeSecurityServiceBasicExample(context), + }, + { + ResourceName: "google_compute_network_edge_security_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"region"}, + }, + { + ResourceName: "google_compute_network_edge_security_service.default", + RefreshState: true, + ExpectNonEmptyPlan: true, + ImportStateKind: resource.ImportBlockWithResourceIdentity, + }, + }, + }) +} + +func testAccComputeNetworkEdgeSecurityService_computeNetworkEdgeSecurityServiceBasicExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network_edge_security_service" "default" { + name = "%{resource_name}" + region = "%{region}" + description = "My basic resource" +} +`, context) +} + +func testAccCheckComputeNetworkEdgeSecurityServiceDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_compute_network_edge_security_service" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + url, err := tpgresource.ReplaceVarsForTest(config, rs, transport_tpg.BaseUrl(compute.Product, config)+"projects/{{project}}/regions/{{region}}/networkEdgeSecurityServices/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("ComputeNetworkEdgeSecurityService still exists at %s", url) + } + } + + return nil + } +} diff --git a/google/services/compute/resource_compute_network_edge_security_service_sweeper.go b/google/services/compute/resource_compute_network_edge_security_service_sweeper.go index b77bcb98d35..4d8a2a26128 100644 --- a/google/services/compute/resource_compute_network_edge_security_service_sweeper.go +++ b/google/services/compute/resource_compute_network_edge_security_service_sweeper.go @@ -8,10 +8,104 @@ // // This code is generated by Magic Modules using the following: // -// Source file: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services/compute/resource_compute_network_edge_security_service_sweeper.go.tmpl +// Source file: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services/compute/resource_compute_network_edge_security_service_sweeper.go // // DO NOT EDIT this file directly. Any changes made to this file will be // overwritten during the next generation cycle. // // ---------------------------------------------------------------------------- package compute + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-provider-google/google/sweeper" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + sweeper.AddTestSweepersLegacy("ComputeNetworkEdgeSecurityService", testSweepComputeNetworkEdgeSecurityService) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepComputeNetworkEdgeSecurityService(region string) error { + resourceName := "ComputeNetworkEdgeSecurityService" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + listUrl := fmt.Sprintf("%sprojects/%s/aggregated/networkEdgeSecurityServices", transport_tpg.BaseUrl(Product, config), config.Project) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request: %s", err) + return nil + } + + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + // Aggregated list response: items is a map keyed by "regions/{region}" + items, ok := res["items"].(map[string]interface{}) + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + for regionPath, regionDataRaw := range items { + regionData, ok := regionDataRaw.(map[string]interface{}) + if !ok { + continue + } + resourcesRaw, ok := regionData["networkEdgeSecurityServices"] + if !ok { + continue + } + for _, tpRaw := range resourcesRaw.([]interface{}) { + tp := tpRaw.(map[string]interface{}) + name := tp["name"].(string) + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + region := tpgresource.GetResourceNameFromSelfLink(regionPath) + deleteUrl := fmt.Sprintf("%sprojects/%s/regions/%s/networkEdgeSecurityServices/%s", transport_tpg.BaseUrl(Product, config), config.Project, region, name) + // Don't wait on operations as we may have a lot to delete + _, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: deleteUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting %s resource %s : %s", resourceName, name, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/google/services/compute/resource_compute_network_edge_security_service_test.go b/google/services/compute/resource_compute_network_edge_security_service_test.go index e7afa093072..da3e7ffc5c3 100644 --- a/google/services/compute/resource_compute_network_edge_security_service_test.go +++ b/google/services/compute/resource_compute_network_edge_security_service_test.go @@ -8,10 +8,87 @@ // // This code is generated by Magic Modules using the following: // -// Source file: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services/compute/resource_compute_network_edge_security_service_test.go.tmpl +// Source file: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services/compute/resource_compute_network_edge_security_service_test.go // // DO NOT EDIT this file directly. Any changes made to this file will be // overwritten during the next generation cycle. // // ---------------------------------------------------------------------------- package compute_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + _ "github.com/hashicorp/terraform-provider-google/google/services/compute" +) + +func TestAccComputeNetworkEdgeSecurityService_update(t *testing.T) { + t.Parallel() + + pName := fmt.Sprintf("tf-test-security-policy-%s", acctest.RandString(t, 10)) + nesName := fmt.Sprintf("tf-test-edge-security-services-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeNetworkEdgeSecurityServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkEdgeSecurityService_basic(pName, nesName), + }, + { + ResourceName: "google_compute_network_edge_security_service.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccNetworkEdgeSecurityService_update(pName, nesName), + }, + { + ResourceName: "google_compute_network_edge_security_service.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccNetworkEdgeSecurityService_basic(pName, nesName string) string { + return fmt.Sprintf(` +resource "google_compute_region_security_policy" "foobar" { + name = "%s" + description = "basic region security policy" + type = "CLOUD_ARMOR_NETWORK" + # can only exist one of this resource per region + region = "us-central1" +} + +resource "google_compute_network_edge_security_service" "foobar" { + name = "%s" + region = "us-central1" + description = "My basic resource using security policy" + security_policy = google_compute_region_security_policy.foobar.self_link +} +`, pName, nesName) +} + +func testAccNetworkEdgeSecurityService_update(pName, nesName string) string { + return fmt.Sprintf(` +resource "google_compute_region_security_policy" "foobar" { + name = "%s" + description = "basic region security policy" + type = "CLOUD_ARMOR_NETWORK" + region = "us-central1" +} + +resource "google_compute_network_edge_security_service" "foobar" { + name = "%s" + region = "us-central1" + description = "My basic updated resource using security policy" + security_policy = google_compute_region_security_policy.foobar.self_link +} +`, pName, nesName) +} diff --git a/website/docs/r/compute_network_edge_security_service.html.markdown b/website/docs/r/compute_network_edge_security_service.html.markdown index c53ace6856b..b6b368c62f7 100644 --- a/website/docs/r/compute_network_edge_security_service.html.markdown +++ b/website/docs/r/compute_network_edge_security_service.html.markdown @@ -23,8 +23,6 @@ description: |- Google Cloud Armor network edge security service resource. -~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](../guides/provider_versions.html.markdown) for more details on beta resources. To get more information about NetworkEdgeSecurityService, see: @@ -37,8 +35,6 @@ To get more information about NetworkEdgeSecurityService, see: ```hcl resource "google_compute_network_edge_security_service" "default" { - provider = google-beta - name = "my-edge-security-service" region = "us-east1" description = "My basic resource"