# Copyright 2024 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
name: 'RegionNetworkEndpointGroup'
api_resource_type_kind: NetworkEndpointGroup
kind: 'compute#networkEndpointGroup'
description: |
  A regional NEG that can support Serverless Products, proxying traffic to
  external backends and providing traffic to the PSC port mapping endpoints.

  When in use by a resource that can be updated, recreating a RegionNetworkEndpointGroup
  will give a `resourceInUseByAnotherResource` error because Terraform will attempt to
  delete the  RegionNetworkEndpointGroup first, but an in-use RegionNetworkEndpointGroup
  can't be deleted in the API. Use `lifecycle.create_before_destroy` to reorder the plan
  and create the new resource first, allowing the deletion to go through successfully.
  This is only recommended when strictly necessary, as the `create_before_destroy`
  directive can be passed onto further dependencies, creating unexpected plans.
references:
  guides:
    'Serverless NEGs Official Documentation': 'https://cloud.google.com/load-balancing/docs/negs/serverless-neg-concepts'
    'Internet NEGs Official Documentation': 'https://cloud.google.com/load-balancing/docs/negs/internet-neg-concepts'
  api: 'https://cloud.google.com/compute/docs/reference/rest/beta/regionNetworkEndpointGroups'
docs:
base_url: 'projects/{{project}}/regions/{{region}}/networkEndpointGroups'
has_self_link: true
immutable: true
timeouts:
  insert_minutes: 20
  update_minutes: 20
  delete_minutes: 20
async:
  actions: ['create', 'delete', 'update']
  type: 'OpAsync'
  operation:
    base_url: '{{op_id}}'
  result:
    resource_inside_response: false
collection_url_key: 'items'
custom_code:
sweeper:
  url_substitutions:
    - region: "us-central1"
    - region: "europe-west4"
    - region: "asia-northeast3"
examples:
  - name: 'region_network_endpoint_group_functions'
    primary_resource_id: 'function_neg'
    vars:
      neg_name: 'function-neg'
      function_name: 'function-neg'
      bucket_name: 'cloudfunctions-function-example-bucket'
      zip_path: 'path/to/index.zip'
    test_vars_overrides:
      'zip_path': 'acctest.CreateZIPArchiveForCloudFunctionSource(t, "./test-fixtures/http_trigger.js")'
  - name: 'region_network_endpoint_group_cloudrun'
    primary_resource_id: 'cloudrun_neg'
    vars:
      neg_name: 'cloudrun-neg'
  - name: 'region_network_endpoint_group_appengine'
    primary_resource_id: 'appengine_neg'
    vars:
      neg_name: 'appengine-neg'
  - name: 'region_network_endpoint_group_appengine_empty'
    primary_resource_id: 'appengine_neg'
    vars:
      neg_name: 'appengine-neg'
  - name: 'region_network_endpoint_group_psc'
    primary_resource_id: 'psc_neg'
    vars:
      neg_name: 'psc-neg'
  - name: 'region_network_endpoint_group_psc_service_attachment'
    primary_resource_id: 'psc_neg_service_attachment'
    vars:
      neg_name: 'psc-neg'
      network_name: 'psc-network'
      subnetwork_name: 'psc-subnetwork'
      psc_subnetwork_name: 'psc-subnetwork-nat'
      backend_service_name: 'psc-backend'
      forwarding_rule_name: 'psc-forwarding-rule'
      service_attachment_name: 'psc-service-attachment'
      health_check_name: 'psc-healthcheck'
  - name: 'region_network_endpoint_group_internet_ip_port'
    primary_resource_id: 'region_network_endpoint_group_internet_ip_port'
    vars:
      neg_name: 'ip-port-neg'
      network_name: 'network'
  - name: 'region_network_endpoint_group_internet_fqdn_port'
    primary_resource_id: 'region_network_endpoint_group_internet_fqdn_port'
    vars:
      neg_name: 'ip-port-neg'
      network_name: 'network'
  - name: 'region_network_endpoint_group_portmap'
    primary_resource_id: 'region_network_endpoint_group_portmap'
    min_version: 'beta'
    vars:
      network_name: 'network'
      subnetwork_name: 'subnetwork'
      neg_name: 'portmap-neg'
parameters:
  - name: 'region'
    type: ResourceRef
    description: |
      A reference to the region where the regional NEGs reside.
    required: true
    custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.tmpl'
    resource: 'Region'
    imports: 'name'
properties:
  - name: 'name'
    type: String
    description: |
      Name of the resource; provided by the client when the resource is
      created. The name must be 1-63 characters long, and comply with
      RFC1035. Specifically, the name must be 1-63 characters long and match
      the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the
      first character must be a lowercase letter, and all following
      characters must be a dash, lowercase letter, or digit, except the last
      character, which cannot be a dash.
    required: true
    validation:
      function: 'verify.ValidateGCEName'
  - name: 'description'
    type: String
    description: |
      An optional description of this resource. Provide this property when
      you create the resource.
  - name: 'networkEndpointType'
    type: Enum
    description: |
      Type of network endpoints in this network endpoint group. Defaults to SERVERLESS.
    default_value: "SERVERLESS"
    enum_values:
      - 'SERVERLESS'
      - 'PRIVATE_SERVICE_CONNECT'
      - 'INTERNET_IP_PORT'
      - 'INTERNET_FQDN_PORT'
      - 'GCE_VM_IP_PORTMAP'
  - name: 'pscTargetService'
    type: String
    description: |
      This field is only used for PSC and INTERNET NEGs.

      The target service url used to set up private service connection to
      a Google API or a PSC Producer Service Attachment.
  - name: 'network'
    type: ResourceRef
    description: |
      This field is only used for PSC and INTERNET NEGs.

      The URL of the network to which all network endpoints in the NEG belong. Uses
      "default" project network if unspecified.
    custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.tmpl'
    resource: 'Network'
    imports: 'selfLink'
  - name: 'subnetwork'
    type: ResourceRef
    description: |
      This field is only used for PSC NEGs.

      Optional URL of the subnetwork to which all network endpoints in the NEG belong.
    custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.tmpl'
    resource: 'Subnetwork'
    imports: 'selfLink'
  - name: 'pscData'
    type: NestedObject
    description: |
      This field is only used for PSC NEGs.
    default_from_api: true
    properties:
      - name: 'producerPort'
        type: String
        ignore_read: true
        description: |
          The PSC producer port to use when consumer PSC NEG connects to a producer. If
          this flag isn't specified for a PSC NEG with endpoint type
          private-service-connect, then PSC NEG will be connected to a first port in the
          available PSC producer port range.
  - name: 'cloudRun'
    type: NestedObject
    description: |
      This field is only used for SERVERLESS NEGs.

      Only one of cloud_run, app_engine, cloud_function or serverless_deployment may be set.
    conflicts:
      - cloud_function
      - app_engine
      - serverless_deployment
    properties:
      - name: 'service'
        type: String
        description: |
          Cloud Run service is the main resource of Cloud Run.
          The service must be 1-63 characters long, and comply with RFC1035.
          Example value: "run-service".
        at_least_one_of:
          - 'cloud_run.0.service'
          - 'cloud_run.0.url_mask'
      - name: 'tag'
        type: String
        description: |
          Cloud Run tag represents the "named-revision" to provide
          additional fine-grained traffic routing information.
          The tag must be 1-63 characters long, and comply with RFC1035.
          Example value: "revision-0010".
      - name: 'urlMask'
        type: String
        description: |
          A template to parse service and tag fields from a request URL.
          URL mask allows for routing to multiple Run services without having
          to create multiple network endpoint groups and backend services.

          For example, request URLs "foo1.domain.com/bar1" and "foo1.domain.com/bar2"
          an be backed by the same Serverless Network Endpoint Group (NEG) with
          URL mask ".domain.com/". The URL mask will parse them to { service="bar1", tag="foo1" }
          and { service="bar2", tag="foo2" } respectively.
        at_least_one_of:
          - 'cloud_run.0.service'
          - 'cloud_run.0.url_mask'
  - name: 'appEngine'
    type: NestedObject
    description: |
      This field is only used for SERVERLESS NEGs.

      Only one of cloud_run, app_engine, cloud_function or serverless_deployment may be set.
    send_empty_value: true
    allow_empty_object: true
    conflicts:
      - cloud_run
      - cloud_function
      - serverless_deployment
    properties:
      - name: 'service'
        type: String
        description: |
          Optional serving service.
          The service name must be 1-63 characters long, and comply with RFC1035.
          Example value: "default", "my-service".
      - name: 'version'
        type: String
        description: |
          Optional serving version.
          The version must be 1-63 characters long, and comply with RFC1035.
          Example value: "v1", "v2".
      - name: 'urlMask'
        type: String
        description: |
          A template to parse service and version fields from a request URL.
          URL mask allows for routing to multiple App Engine services without
          having to create multiple Network Endpoint Groups and backend services.

          For example, the request URLs "foo1-dot-appname.appspot.com/v1" and
          "foo1-dot-appname.appspot.com/v2" can be backed by the same Serverless NEG with
          URL mask "-dot-appname.appspot.com/". The URL mask will parse
          them to { service = "foo1", version = "v1" } and { service = "foo1", version = "v2" } respectively.
  - name: 'cloudFunction'
    type: NestedObject
    description: |
      This field is only used for SERVERLESS NEGs.

      Only one of cloud_run, app_engine, cloud_function or serverless_deployment may be set.
    conflicts:
      - cloud_run
      - app_engine
      - serverless_deployment
    properties:
      - name: 'function'
        type: String
        description: |
          A user-defined name of the Cloud Function.
          The function name is case-sensitive and must be 1-63 characters long.
          Example value: "func1".
        at_least_one_of:
          - 'cloud_function.0.function'
          - 'cloud_function.0.url_mask'
      - name: 'urlMask'
        type: String
        description: |
          A template to parse function field from a request URL. URL mask allows
          for routing to multiple Cloud Functions without having to create
          multiple Network Endpoint Groups and backend services.

          For example, request URLs "mydomain.com/function1" and "mydomain.com/function2"
          can be backed by the same Serverless NEG with URL mask "/". The URL mask
          will parse them to { function = "function1" } and { function = "function2" } respectively.
        at_least_one_of:
          - 'cloud_function.0.function'
          - 'cloud_function.0.url_mask'
  - name: 'serverlessDeployment'
    type: NestedObject
    description: |
      This field is only used for SERVERLESS NEGs.

      Only one of cloudRun, appEngine, cloudFunction or serverlessDeployment may be set.
    min_version: 'beta'
    send_empty_value: true
    allow_empty_object: true
    conflicts:
      - cloud_run
      - cloud_function
      - app_engine
    properties:
      - name: 'platform'
        type: String
        # Docs (https://cloud.google.com/compute/docs/reference/rest/beta/regionNetworkEndpointGroups) say support is offered for:
        # API Gateway: apigateway.googleapis.com, App Engine: appengine.googleapis.com,
        # Cloud Functions: cloudfunctions.googleapis.com, Cloud Run: run.googleapis.com
        # However, only API Gateway is currently supported
        description: |
          The platform of the NEG backend target(s). Possible values:
          API Gateway: apigateway.googleapis.com
        required: true
      - name: 'resource'
        type: String
        description: |
          The user-defined name of the workload/instance. This value must be provided explicitly or in the urlMask.
          The resource identified by this value is platform-specific and is as follows: API Gateway: The gateway ID, App Engine: The service name,
          Cloud Functions: The function name, Cloud Run: The service name
      - name: 'version'
        type: String
        description: |
          The optional resource version. The version identified by this value is platform-specific and is follows:
          API Gateway: Unused, App Engine: The service version, Cloud Functions: Unused, Cloud Run: The service tag
      - name: 'urlMask'
        type: String
        description: |
          A template to parse platform-specific fields from a request URL. URL mask allows for routing to multiple resources
          on the same serverless platform without having to create multiple Network Endpoint Groups and backend resources.
          The fields parsed by this template are platform-specific and are as follows: API Gateway: The gateway ID,
          App Engine: The service and version, Cloud Functions: The function name, Cloud Run: The service and tag
        required: false
