From 6200eb8968389e65cf6d0bde002ee2daaf072d0e Mon Sep 17 00:00:00 2001 From: Mahamed Date: Thu, 14 Apr 2022 22:15:20 +0100 Subject: [PATCH] Add support for Cloud Deploy resources (#5710) * add cloud deploy resources Co-authored-by: upodroid * add new test * apply suggestions from sam * remove custom flattener * fix import id, add new tests and fix bad rebase --- mmv1/products/clouddeploy/api.yaml | 203 ++++++++++++++++++ mmv1/products/clouddeploy/terraform.yaml | 55 +++++ .../cloud_deploy_delivery_pipeline.tf.erb | 16 ++ .../examples/cloud_deploy_target.tf.erb | 7 + .../examples/cloud_deploy_target_full.tf.erb | 19 ++ .../resource_cloud_deploy_target_test.go | 74 +++++++ 6 files changed, 374 insertions(+) create mode 100644 mmv1/products/clouddeploy/api.yaml create mode 100644 mmv1/products/clouddeploy/terraform.yaml create mode 100644 mmv1/templates/terraform/examples/cloud_deploy_delivery_pipeline.tf.erb create mode 100644 mmv1/templates/terraform/examples/cloud_deploy_target.tf.erb create mode 100644 mmv1/templates/terraform/examples/cloud_deploy_target_full.tf.erb create mode 100644 mmv1/third_party/terraform/tests/resource_cloud_deploy_target_test.go diff --git a/mmv1/products/clouddeploy/api.yaml b/mmv1/products/clouddeploy/api.yaml new file mode 100644 index 000000000000..514f70716442 --- /dev/null +++ b/mmv1/products/clouddeploy/api.yaml @@ -0,0 +1,203 @@ +# Copyright 2022 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::Product +name: CloudDeploy +display_name: Cloud Deploy +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://clouddeploy.googleapis.com/v1/ +scopes: + - https://www.googleapis.com/auth/cloud-platform +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + path: 'name' + base_url: '{{op_id}}' + wait_ms: 1000 + 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' +objects: + - !ruby/object:Api::Resource + name: 'DeliveryPipeline' + base_url: projects/{{project}}/locations/{{region}}/deliveryPipelines + self_link: 'projects/{{project}}/locations/{{region}}/deliveryPipelines/{{name}}' + create_url: projects/{{project}}/locations/{{region}}/deliveryPipelines?deliveryPipelineId={{name}} + input: true + references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': + 'https://cloud.google.com/deploy/docs' + api: 'https://cloud.google.com/deploy/docs/api/reference/rest/v1/projects.locations.deliveryPipelines' + description: |- + A DeliveryPipeline defines a pipeline through which a Skaffold configuration can progress. + parameters: + - !ruby/object:Api::Type::String + name: region + description: The region of the DeliveryPipeline Store. eg us-central1 + url_param_only: true + input: true + properties: + - !ruby/object:Api::Type::String + name: 'name' + description: The name of the DeliveryPipeline. This value may be up to 60 characters, and valid characters are [a-z0-9_]. The first character cannot be a number. + input: true + url_param_only: true + pattern: projects/{{project}}/locations/{{region}}/deliveryPipelines/{{name}} + - !ruby/object:Api::Type::String + name: 'description' + description: Description of the DeliveryPipeline. + input: true + - !ruby/object:Api::Type::KeyValuePairs + name: 'labels' + description: | + Resource labels to represent user-provided metadata. + - !ruby/object:Api::Type::KeyValuePairs + name: 'annotations' + description: | + User annotations. These attributes can only be set and used by the user, and not by Google Cloud Deploy. + - !ruby/object:Api::Type::NestedObject + name: 'serialPipeline' + required: true + description: | + SerialPipeline defines a sequential set of stages for a DeliveryPipeline. + properties: + - !ruby/object:Api::Type::Array + required: true + name: 'stages' + description: | + Stage specifies a location to which to deploy. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'targetId' + required: true + input: true + description: | + The targetId to which this stage points. This field refers exclusively to the last segment of a target name. + For example, this field would just be my-target (rather than projects/project/locations/location/targets/my-target). + The location of the Target is inferred to be the same as the location of the DeliveryPipeline that contains this Stage. + - !ruby/object:Api::Type::Array + name: 'profiles' + item_type: Api::Type::String + input: true + description: | + Skaffold profiles to use when rendering the manifest for this stage's Target. + - !ruby/object:Api::Resource + name: 'Target' + base_url: projects/{{project}}/locations/{{region}}/targets + self_link: 'projects/{{project}}/locations/{{region}}/targets/{{name}}' + create_url: projects/{{project}}/locations/{{region}}/targets?targetId={{name}} + update_verb: :PATCH + update_mask: true + references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': + 'https://cloud.google.com/deploy/docs' + api: 'https://cloud.google.com/deploy/docs/api/reference/rest/v1/projects.locations.targets' + description: |- + A Target defines a location to which a Skaffold configuration can be deployed. + parameters: + - !ruby/object:Api::Type::String + name: region + description: The region of the Target Store. eg us-central1 + url_param_only: true + input: true + properties: + - !ruby/object:Api::Type::String + name: 'name' + description: The name of the Target. This value may be up to 60 characters, and valid characters are [a-z0-9_]. The first character cannot be a number. + input: true + url_param_only: true + pattern: projects/{{project}}/locations/{{region}}/targets/{{name}} + - !ruby/object:Api::Type::String + name: 'description' + description: Description of the Target. + - !ruby/object:Api::Type::KeyValuePairs + name: 'labels' + description: | + Resource labels to represent user-provided metadata. + - !ruby/object:Api::Type::KeyValuePairs + name: 'annotations' + description: | + User annotations. These attributes can only be set and used by the user, and not by Google Cloud Deploy. + - !ruby/object:Api::Type::Boolean + name: 'requireApproval' + description: | + Whether or not the Target requires approval. + - !ruby/object:Api::Type::NestedObject + name: 'gke' + description: | + Information specifying a GKE Cluster. + properties: + - !ruby/object:Api::Type::String + name: 'cluster' + exactly_one_of: + - gke.0.cluster + - anthos_cluster.0.membership + description: | + Information specifying a GKE Cluster. Format is `projects/{projectId}/locations/{locationId}/clusters/{cluster_id}. + - !ruby/object:Api::Type::Boolean + name: 'internalIp' + description: | + If true, cluster is accessed using the private IP address of the control plane endpoint. Otherwise, the default IP address of the control plane endpoint is used. + The default IP address is the private IP address for clusters with private control-plane endpoints and the public IP address otherwise. + - !ruby/object:Api::Type::NestedObject + name: 'anthosCluster' + description: | + Information specifying a GKE Cluster. + properties: + - !ruby/object:Api::Type::String + name: 'membership' + exactly_one_of: + - gke.0.cluster + - anthos_cluster.0.membership + description: | + Membership of the GKE Hub-registered cluster to which to apply the Skaffold configuration. Format is projects/{project}/locations/{location}/memberships/{membership_name}. + - !ruby/object:Api::Type::Array + name: 'executionConfigs' + description: | + Configurations for all execution that relates to this Target. Each ExecutionEnvironmentUsage value may only be used in a single configuration; + using the same value multiple times is an error. When one or more configurations are specified, they must include the RENDER and DEPLOY ExecutionEnvironmentUsage values. + When no configurations are specified, execution will use the default specified in DefaultPool. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::Array + name: 'usages' + required: true + item_type: Api::Type::String + description: | + Possible usages of this configuration. + - !ruby/object:Api::Type::String + name: 'serviceAccount' + description: | + Google service account to use for execution. If unspecified, the project execution service account (-compute@developer.gserviceaccount.com) will be used. + - !ruby/object:Api::Type::String + name: 'artifactStorage' + description: | + Cloud Storage location where execution outputs should be stored. This can either be a bucket ("gs://my-bucket") or a path within a bucket ("gs://my-bucket/my-dir"). + If unspecified, a default bucket located in the same region will be used. + - !ruby/object:Api::Type::String + name: 'workerPool' + description: | + Resource name of the Cloud Build worker pool to use. The format is projects/{project}/locations/{location}/workerPools/{pool}. diff --git a/mmv1/products/clouddeploy/terraform.yaml b/mmv1/products/clouddeploy/terraform.yaml new file mode 100644 index 000000000000..80d8f19f833f --- /dev/null +++ b/mmv1/products/clouddeploy/terraform.yaml @@ -0,0 +1,55 @@ +# Copyright 2022 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:Provider::Terraform::Config +overrides: !ruby/object:Overrides::ResourceOverrides + DeliveryPipeline: !ruby/object:Overrides::Terraform::ResourceOverride + autogen_async: true + id_format: 'projects/{{project}}/locations/{{region}}/deliveryPipelines/{{name}}' + examples: + - !ruby/object:Provider::Terraform::Examples + name: "cloud_deploy_delivery_pipeline" + primary_resource_id: "pipeline" + vars: + name: "dev" + properties: + region: !ruby/object:Overrides::Terraform::PropertyOverride + default_from_api: true + Target: !ruby/object:Overrides::Terraform::ResourceOverride + autogen_async: true + id_format: 'projects/{{project}}/locations/{{region}}/targets/{{name}}' + examples: + - !ruby/object:Provider::Terraform::Examples + name: "cloud_deploy_target" + primary_resource_id: "pipeline" + vars: + name: "tf-test" + test_env_vars: + project: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: "cloud_deploy_target_full" + primary_resource_id: "pipeline" + vars: + name: "tf-test" + test_env_vars: + project: :PROJECT_NAME + properties: + region: !ruby/object:Overrides::Terraform::PropertyOverride + default_from_api: true + +# This is for copying files over +files: !ruby/object:Provider::Config::Files + # These files have templating (ERB) code that will be run. + # This is usually to add licensing info, autogeneration notices, etc. + compile: +<%= lines(indent(compile('provider/terraform/product~compile.yaml'), 4)) -%> diff --git a/mmv1/templates/terraform/examples/cloud_deploy_delivery_pipeline.tf.erb b/mmv1/templates/terraform/examples/cloud_deploy_delivery_pipeline.tf.erb new file mode 100644 index 000000000000..37e1dd505cb0 --- /dev/null +++ b/mmv1/templates/terraform/examples/cloud_deploy_delivery_pipeline.tf.erb @@ -0,0 +1,16 @@ +resource "google_cloud_deploy_delivery_pipeline" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['name'] %>" + description = "Dev Pipeline" + serial_pipeline { + stages { + target_id = "dev" + } + } + annotations = { + generated-by = "magic-modules" + } + labels = { + env = "dev" + } + region = "us-central1" +} diff --git a/mmv1/templates/terraform/examples/cloud_deploy_target.tf.erb b/mmv1/templates/terraform/examples/cloud_deploy_target.tf.erb new file mode 100644 index 000000000000..0dce8b3da97c --- /dev/null +++ b/mmv1/templates/terraform/examples/cloud_deploy_target.tf.erb @@ -0,0 +1,7 @@ +resource "google_cloud_deploy_target" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['name'] %>" + description = "Target Cluster" + gke { + cluster = "projects/<%= ctx[:test_env_vars]['project'] %>/locations/us-central1/clusters/dev" + } +} diff --git a/mmv1/templates/terraform/examples/cloud_deploy_target_full.tf.erb b/mmv1/templates/terraform/examples/cloud_deploy_target_full.tf.erb new file mode 100644 index 000000000000..5c151a8d43d4 --- /dev/null +++ b/mmv1/templates/terraform/examples/cloud_deploy_target_full.tf.erb @@ -0,0 +1,19 @@ +resource "google_cloud_deploy_target" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['name'] %>" + description = "Target Cluster" + annotations = { + generated-by = "magic-modules" + } + + require_approval = true + labels = { + env = "dev" + } + gke { + cluster = "projects/<%= ctx[:test_env_vars]['project'] %>/locations/us-central1/clusters/dev" + } + execution_configs { + usages = ["RENDER", "DEPLOY"] + service_account = "<%= ctx[:test_env_vars]['project'] %>@appspot.gserviceaccount.com" + } +} diff --git a/mmv1/third_party/terraform/tests/resource_cloud_deploy_target_test.go b/mmv1/third_party/terraform/tests/resource_cloud_deploy_target_test.go new file mode 100644 index 000000000000..2d6abb5b2048 --- /dev/null +++ b/mmv1/third_party/terraform/tests/resource_cloud_deploy_target_test.go @@ -0,0 +1,74 @@ +package google + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccCloudDeployTarget_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project": getTestProjectFromEnv(), + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDataCatalogEntryGroupDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudDeployTarget_cloudDeployTargetFullExample(context), + }, + { + ResourceName: "google_cloud_deploy_target.pipeline", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "region"}, + }, + { + Config: testAccCloudDeployTarget_cloudDeployTargetFullExample_update(context), + }, + { + ResourceName: "google_cloud_deploy_target.pipeline", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "region"}, + }, + }, + }) +} + +func testAccCloudDeployTarget_cloudDeployTargetFullExample_update(context map[string]interface{}) string { + return Nprintf(` +resource "google_cloud_deploy_target" "pipeline" { + name = "tf-test-tf-test%{random_suffix}" + description = "Target Prod Cluster" + annotations = { + generated-by = "magic-modules" + another = "one" + } + labels = { + env = "prod" + } + gke { + cluster = "projects/%{project}/locations/us-central1/clusters/prod" + } + execution_configs { + usages = ["RENDER"] + service_account = data.google_compute_default_service_account.default.email + } + + execution_configs { + usages = ["DEPLOY"] + service_account = "%{project}@appspot.gserviceaccount.com" + } + +} + +data "google_compute_default_service_account" "default" { +} +`, context) +}