diff --git a/mmv1/products/apphub/Service.yaml b/mmv1/products/apphub/Service.yaml new file mode 100644 index 000000000000..7558666e9582 --- /dev/null +++ b/mmv1/products/apphub/Service.yaml @@ -0,0 +1,235 @@ +# 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. + +--- !ruby/object:Api::Resource +base_url: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services +create_url: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services?serviceId={{service_id}} +self_link: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services/{{service_id}} +id_format: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services/{{service_id}} +import_format: + - projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services/{{service_id}} +name: Service +description: 'Service is a network/api interface that exposes some functionality to clients for consumption over the network. + Service typically has one or more Workloads behind it. It registers identified service to the Application.' +autogen_async: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "apphub_service_basic" + pull_external: true + primary_resource_id: "example" + vars: + application_id: "example-application-1" + service_project_attachment_id: "project-1" + ilb_network: "l7-ilb-network" + ilb_subnet: "l7-ilb-subnet" + forwarding_rule: "l7-ilb-forwarding-rule" + backend_service: "l7-ilb-backend-subnet" + health_check: "l7-ilb-hc" + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT + - !ruby/object:Provider::Terraform::Examples + name: "apphub_service_full" + pull_external: true + primary_resource_id: "example" + vars: + application_id: "example-application-1" + service_project_attachment_id: "project-1" + display_name: "Example Service Full" + description: "Register service for testing" + business_name: "Alice" + business_email: "alice@google.com" + developer_name: "Bob" + developer_email: "bob@google.com" + operator_name: "Charlie" + operator_email: "charlie@google.com" + ilb_network: "l7-ilb-network" + ilb_subnet: "l7-ilb-subnet" + forwarding_rule: "l7-ilb-forwarding-rule" + backend_service: "l7-ilb-backend-subnet" + health_check: "l7-ilb-hc" + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + path: name + base_url: "{{op_id}}" + wait_ms: 1000 + timeouts: + result: !ruby/object:Api::OpAsync::Result + path: response + resource_inside_response: true + status: !ruby/object:Api::OpAsync::Status + path: done + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: error + message: message +update_verb: :PATCH +update_mask: true +parameters: + - !ruby/object:Api::Type::String + name: location + description: 'Part of `parent`. Full resource name of a parent Application. Example: projects/{HOST_PROJECT_ID}/locations/{LOCATION}/applications/{APPLICATION_ID} ' + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: applicationId + description: 'Part of `parent`. Full resource name of a parent Application. Example: projects/{HOST_PROJECT_ID}/locations/{LOCATION}/applications/{APPLICATION_ID}' + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: serviceId + description: 'The Service identifier. ' + url_param_only: true + required: true + immutable: true +properties: + - !ruby/object:Api::Type::String + name: name + output: true + description: "Identifier. The resource name of a Service. Format:\n\"projects/{host-project-id}/locations/{location}/applications/{application-id}/services/{service-id}\" " + - !ruby/object:Api::Type::String + name: displayName + description: 'User-defined name for the Service. ' + - !ruby/object:Api::Type::String + name: description + description: 'User-defined description of a Service. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: uri + description: "Output only. The underlying resource URI (For example, URI of Forwarding + Rule, URL Map,\nand Backend Service). " + output: true + output: true + name: serviceReference + description: 'Reference to an underlying networking resource that can comprise a + Service. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: gcpProject + description: "Output only. The service project identifier that the underlying + cloud resource resides in. " + output: true + - !ruby/object:Api::Type::String + name: location + description: "Output only. The location that the underlying resource resides in, + for example, us-west1. " + output: true + - !ruby/object:Api::Type::String + name: zone + description: "Output only. The location that the underlying resource resides in + if it is zonal, for example, us-west1-a). " + output: true + output: true + name: serviceProperties + description: 'Properties of an underlying cloud resource that can comprise a Service. ' + - !ruby/object:Api::Type::NestedObject + name: attributes + description: 'Consumer provided attributes. ' + properties: + - !ruby/object:Api::Type::NestedObject + name: criticality + description: 'Criticality of the Application, Service, or Workload ' + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Criticality type. ' + required: true + values: + - :MISSION_CRITICAL + - :HIGH + - :MEDIUM + - :LOW + - !ruby/object:Api::Type::NestedObject + name: environment + description: 'Environment of the Application, Service, or Workload ' + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Environment type. ' + required: true + values: + - :PRODUCTION + - :STAGING + - :TEST + - :DEVELOPMENT + - !ruby/object:Api::Type::Array + name: developerOwners + description: 'Developer team that owns development and coding. ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Required. Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::Array + name: operatorOwners + description: 'Operator team that ensures runtime and operations. ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Required. Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::Array + name: businessOwners + description: 'Business team that ensures user needs are met and value + is delivered ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Required. Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::String + name: discoveredService + diff_suppress_func: 'tpgresource.ProjectNumberDiffSuppress' + description: 'Immutable. The resource name of the original discovered + service. ' + required: true + immutable: true + - !ruby/object:Api::Type::String + name: createTime + description: 'Output only. Create time. ' + output: true + - !ruby/object:Api::Type::String + name: updateTime + description: 'Output only. Update time. ' + output: true + - !ruby/object:Api::Type::String + name: uid + description: "Output only. A universally unique identifier (UUID) for the `Service` + in the UUID4\nformat. " + output: true + - !ruby/object:Api::Type::String + name: state + description: "Output only. Service state. Possible values: STATE_UNSPECIFIED CREATING ACTIVE DELETING DETACHED" + output: true diff --git a/mmv1/templates/terraform/examples/apphub_service_basic.tf.erb b/mmv1/templates/terraform/examples/apphub_service_basic.tf.erb new file mode 100644 index 000000000000..f62288859da8 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_service_basic.tf.erb @@ -0,0 +1,110 @@ +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + provider = google + location = "us-central1" + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [google_apphub_service_project_attachment.service_project_attachment, time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +resource "google_apphub_service" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + service_id = google_compute_forwarding_rule.forwarding_rule.name + discovered_service = data.google_apphub_discovered_service.catalog-service.name +} + + +#creates service + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "<%= ctx[:vars]['ilb_network'] %>" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "<%= ctx[:vars]['ilb_subnet'] %>" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name ="<%= ctx[:vars]['forwarding_rule'] %>" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + + + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "<%= ctx[:vars]['backend_service'] %>" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "<%= ctx[:vars]['health_check'] %>" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} + + diff --git a/mmv1/templates/terraform/examples/apphub_service_full.tf.erb b/mmv1/templates/terraform/examples/apphub_service_full.tf.erb new file mode 100644 index 000000000000..2a0bdde9ed19 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_service_full.tf.erb @@ -0,0 +1,132 @@ +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + provider = google + location = "us-central1" + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [google_apphub_service_project_attachment.service_project_attachment, time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +resource "google_apphub_service" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + service_id = google_compute_forwarding_rule.forwarding_rule.name + discovered_service = data.google_apphub_discovered_service.catalog-service.name + display_name = "<%= ctx[:vars]['display_name'] %>" + description = "<%= ctx[:vars]['description'] %>" + attributes { + environment { + type = "STAGING" + } + criticality { + type = "MISSION_CRITICAL" + } + business_owners { + display_name = "<%= ctx[:vars]['business_name'] %>" + email = "<%= ctx[:vars]['business_email'] %>" + } + developer_owners { + display_name = "<%= ctx[:vars]['developer_name'] %>" + email = "<%= ctx[:vars]['developer_email'] %>" + } + operator_owners { + display_name = "<%= ctx[:vars]['operator_name'] %>" + email = "<%= ctx[:vars]['operator_email'] %>" + } + } +} + + +#creates service + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "<%= ctx[:vars]['ilb_network'] %>" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "<%= ctx[:vars]['ilb_subnet'] %>" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name ="<%= ctx[:vars]['forwarding_rule'] %>" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + + + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "<%= ctx[:vars]['backend_service'] %>" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "<%= ctx[:vars]['health_check'] %>" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} + + diff --git a/mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go b/mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go new file mode 100644 index 000000000000..0ea290f3992e --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go @@ -0,0 +1,163 @@ +package apphub_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccApphubService_serviceUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + "time": {}, + }, + CheckDestroy: testAccCheckApphubServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccApphubService_apphubServiceFullExample(context), + }, + { + ResourceName: "google_apphub_service.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id", "service_id"}, + }, + { + Config: testAccApphubService_apphubServiceUpdate(context), + }, + { + ResourceName: "google_apphub_service.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id", "service_id"}, + }, + }, + }) +} + +func testAccApphubService_apphubServiceUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "tf-test-example-application-1%{random_suffix}" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="tf-test-project-1%{random_suffix}" + name = "Service Project" + org_id = "%{org_id}" + billing_account = "%{billing_account}" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + provider = google + location = "us-central1" + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [google_apphub_service_project_attachment.service_project_attachment, time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +resource "google_apphub_service" "example" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + service_id = google_compute_forwarding_rule.forwarding_rule.name + discovered_service = data.google_apphub_discovered_service.catalog-service.name +} + + +#creates service + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "tf-test-l7-ilb-network%{random_suffix}" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "tf-test-l7-ilb-subnet%{random_suffix}" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name ="tf-test-l7-ilb-forwarding-rule%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + + + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "tf-test-l7-ilb-backend-subnet%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "tf-test-l7-ilb-hc%{random_suffix}" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} +`, context) +}