From 9b9dfd2f7893998965b9e5a69868ae369d7271cf Mon Sep 17 00:00:00 2001 From: Julia Matuszewska Date: Wed, 18 Dec 2024 16:46:43 +0000 Subject: [PATCH 1/4] Force delete for CodeRepositoryIndex nested resource removal --- mmv1/products/gemini/CodeRepositoryIndex.yaml | 2 ++ .../pre_delete/code_repository_index_force_delete.go.tmpl | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 mmv1/templates/terraform/pre_delete/code_repository_index_force_delete.go.tmpl diff --git a/mmv1/products/gemini/CodeRepositoryIndex.yaml b/mmv1/products/gemini/CodeRepositoryIndex.yaml index 62cb5236c845..9a397e041745 100644 --- a/mmv1/products/gemini/CodeRepositoryIndex.yaml +++ b/mmv1/products/gemini/CodeRepositoryIndex.yaml @@ -51,6 +51,8 @@ async: result: resource_inside_response: true include_project: false +custom_code: + pre_delete: templates/terraform/pre_delete/code_repository_index_force_delete.go.tmpl error_retry_predicates: - 'transport_tpg.IsCodeRepositoryIndexUnreadyError' - 'transport_tpg.IsRepositoryGroupQueueError' diff --git a/mmv1/templates/terraform/pre_delete/code_repository_index_force_delete.go.tmpl b/mmv1/templates/terraform/pre_delete/code_repository_index_force_delete.go.tmpl new file mode 100644 index 000000000000..dcd492c9d0f6 --- /dev/null +++ b/mmv1/templates/terraform/pre_delete/code_repository_index_force_delete.go.tmpl @@ -0,0 +1,4 @@ +{{- if ne $.TargetVersionName "ga" -}} +obj = make(map[string]interface{}) +obj["force"] = true +{{- end }} \ No newline at end of file From 286088015d3448811aa8f7c6ac95c685b2765697 Mon Sep 17 00:00:00 2001 From: Julia Matuszewska Date: Wed, 8 Jan 2025 17:01:42 +0000 Subject: [PATCH 2/4] Test CodeRepositoryIndex force deletion --- ..._gemini_code_repository_index_test.go.tmpl | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/mmv1/third_party/terraform/services/gemini/resource_gemini_code_repository_index_test.go.tmpl b/mmv1/third_party/terraform/services/gemini/resource_gemini_code_repository_index_test.go.tmpl index ab1520dbc92b..bc90b006b3b8 100644 --- a/mmv1/third_party/terraform/services/gemini/resource_gemini_code_repository_index_test.go.tmpl +++ b/mmv1/third_party/terraform/services/gemini/resource_gemini_code_repository_index_test.go.tmpl @@ -2,6 +2,7 @@ package gemini_test {{- if ne $.TargetVersionName "ga" }} import ( + "fmt" "os" "testing" @@ -44,6 +45,131 @@ func TestAccGeminiCodeRepositoryIndex_update(t *testing.T) { }) } +// TestAccGeminiCodeRepositoryIndex_delete checks if there is no error in deleting CRI along with children resource +// note: this is an example of a bad usage, where RGs refer to the CRI using a string id, not a reference, as they +// will be force-removed upon CRI deletion, because the CRI provider uses --force option by default +// The plan after the _delete function should not be empty due to the child resource in plan +func TestAccGeminiCodeRepositoryIndex_delete(t *testing.T) { + bootstrappedKMS := acctest.BootstrapKMSKeyInLocation(t, "us-central1") + randomSuffix := acctest.RandString(t, 10) + context := map[string]interface{}{ + "random_suffix": randomSuffix, + "project_id": os.Getenv("GOOGLE_PROJECT"), + "kms_key": bootstrappedKMS.CryptoKey.Name, + "cri_id": fmt.Sprintf("tf-test-cri-index-delete-example-%s", randomSuffix), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccGeminiCodeRepositoryIndex_withChildren_basic(context), + }, + { + ResourceName: "google_gemini_code_repository_index.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"code_repository_index_id", "labels", "location", "terraform_labels"}, + }, + { + Config: testAccGeminiCodeRepositoryIndex_withChildren_delete(context), + ExpectNonEmptyPlan: true, + PlanOnly: true, + }, + }, + }) +} + +func testAccGeminiCodeRepositoryIndex_withChildren_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_gemini_code_repository_index" "example" { + provider = google-beta + labels = {"ccfe_debug_note": "terraform_e2e_should_be_deleted"} + location = "us-central1" + code_repository_index_id = "%{cri_id}" +} + +resource "google_gemini_repository_group" "example" { + provider = google-beta + location = "us-central1" + code_repository_index = "%{cri_id}" + repository_group_id = "tf-test-rg-repository-group-id-%{random_suffix}" + repositories { + resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}" + branch_pattern = "main" + } + labels = {"label1": "value1"} +} + +resource "google_developer_connect_git_repository_link" "conn" { + provider = google-beta + git_repository_link_id = "tf-test-repository-conn-delete" + parent_connection = google_developer_connect_connection.github_conn.connection_id + clone_uri = "https://github.com/CC-R-github-robot/tf-test.git" + location = "us-central1" + annotations = {} +} + +resource "google_developer_connect_connection" "github_conn" { + provider = google-beta + location = "us-central1" + connection_id = "tf-test-cloudaicompanion-delete-%{random_suffix}" + disabled = false + + github_config { + github_app = "DEVELOPER_CONNECT" + app_installation_id = 54180648 + + authorizer_credential { + oauth_token_secret_version = "projects/502367051001/secrets/tf-test-cloudaicompanion-github-oauthtoken-c42e5c/versions/1" + } + } +} +`, context) +} + +func testAccGeminiCodeRepositoryIndex_withChildren_delete(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_gemini_repository_group" "example" { + provider = google-beta + location = "us-central1" + code_repository_index = "%{cri_id}" + repository_group_id = "tf-test-rg-repository-group-id-%{random_suffix}" + repositories { + resource = "projects/%{project_id}/locations/us-central1/connections/${google_developer_connect_connection.github_conn.connection_id}/gitRepositoryLinks/${google_developer_connect_git_repository_link.conn.git_repository_link_id}" + branch_pattern = "main" + } + labels = {"label1": "value1"} +} + +resource "google_developer_connect_git_repository_link" "conn" { + provider = google-beta + git_repository_link_id = "tf-test-repository-conn-delete" + parent_connection = google_developer_connect_connection.github_conn.connection_id + clone_uri = "https://github.com/CC-R-github-robot/tf-test.git" + location = "us-central1" + annotations = {} +} + +resource "google_developer_connect_connection" "github_conn" { + provider = google-beta + location = "us-central1" + connection_id = "tf-test-cloudaicompanion-delete-%{random_suffix}" + disabled = false + + github_config { + github_app = "DEVELOPER_CONNECT" + app_installation_id = 54180648 + + authorizer_credential { + oauth_token_secret_version = "projects/502367051001/secrets/tf-test-cloudaicompanion-github-oauthtoken-c42e5c/versions/1" + } + } +} +`, context) +} + func testAccGeminiCodeRepositoryIndex_basic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_gemini_code_repository_index" "example" { From b83073fa0dfc486984e9bd62595dc2c462af06fe Mon Sep 17 00:00:00 2001 From: Julia Matuszewska Date: Thu, 9 Jan 2025 21:46:42 +0000 Subject: [PATCH 3/4] Add force_destroy flag to CodeRepositoryIndex --- mmv1/products/gemini/CodeRepositoryIndex.yaml | 6 ++++++ .../pre_delete/code_repository_index_force_delete.go.tmpl | 8 ++++++-- .../resource_gemini_code_repository_index_test.go.tmpl | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/mmv1/products/gemini/CodeRepositoryIndex.yaml b/mmv1/products/gemini/CodeRepositoryIndex.yaml index 9a397e041745..681db84a501e 100644 --- a/mmv1/products/gemini/CodeRepositoryIndex.yaml +++ b/mmv1/products/gemini/CodeRepositoryIndex.yaml @@ -56,6 +56,12 @@ custom_code: error_retry_predicates: - 'transport_tpg.IsCodeRepositoryIndexUnreadyError' - 'transport_tpg.IsRepositoryGroupQueueError' +virtual_fields: + - name: 'force_destroy' + description: + If set to true, any RepositoryGroups for this CodeRepositoryIndex will also be deleted. + type: Boolean + default_value: false parameters: - name: location type: String diff --git a/mmv1/templates/terraform/pre_delete/code_repository_index_force_delete.go.tmpl b/mmv1/templates/terraform/pre_delete/code_repository_index_force_delete.go.tmpl index dcd492c9d0f6..a451d1ece932 100644 --- a/mmv1/templates/terraform/pre_delete/code_repository_index_force_delete.go.tmpl +++ b/mmv1/templates/terraform/pre_delete/code_repository_index_force_delete.go.tmpl @@ -1,4 +1,8 @@ {{- if ne $.TargetVersionName "ga" -}} obj = make(map[string]interface{}) -obj["force"] = true -{{- end }} \ No newline at end of file +if v, ok := d.GetOk("force_destroy"); ok { + if v == true { + obj["force"] = true + } +} +{{- end }} diff --git a/mmv1/third_party/terraform/services/gemini/resource_gemini_code_repository_index_test.go.tmpl b/mmv1/third_party/terraform/services/gemini/resource_gemini_code_repository_index_test.go.tmpl index bc90b006b3b8..ddbd7c17168f 100644 --- a/mmv1/third_party/terraform/services/gemini/resource_gemini_code_repository_index_test.go.tmpl +++ b/mmv1/third_party/terraform/services/gemini/resource_gemini_code_repository_index_test.go.tmpl @@ -70,7 +70,7 @@ func TestAccGeminiCodeRepositoryIndex_delete(t *testing.T) { ResourceName: "google_gemini_code_repository_index.example", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"code_repository_index_id", "labels", "location", "terraform_labels"}, + ImportStateVerifyIgnore: []string{"code_repository_index_id", "labels", "location", "terraform_labels", "force_destroy"}, }, { Config: testAccGeminiCodeRepositoryIndex_withChildren_delete(context), @@ -88,6 +88,7 @@ resource "google_gemini_code_repository_index" "example" { labels = {"ccfe_debug_note": "terraform_e2e_should_be_deleted"} location = "us-central1" code_repository_index_id = "%{cri_id}" + force_destroy = true } resource "google_gemini_repository_group" "example" { @@ -100,6 +101,9 @@ resource "google_gemini_repository_group" "example" { branch_pattern = "main" } labels = {"label1": "value1"} + depends_on = [ + google_gemini_code_repository_index.example + ] } resource "google_developer_connect_git_repository_link" "conn" { @@ -129,6 +133,7 @@ resource "google_developer_connect_connection" "github_conn" { `, context) } +// Removed depends_on to not break plan test func testAccGeminiCodeRepositoryIndex_withChildren_delete(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_gemini_repository_group" "example" { From 14f469091f620168d053be953a23571fe5717267 Mon Sep 17 00:00:00 2001 From: Nick Elliot Date: Fri, 10 Jan 2025 13:29:18 -0800 Subject: [PATCH 4/4] Update mmv1/products/gemini/CodeRepositoryIndex.yaml --- mmv1/products/gemini/CodeRepositoryIndex.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mmv1/products/gemini/CodeRepositoryIndex.yaml b/mmv1/products/gemini/CodeRepositoryIndex.yaml index 681db84a501e..c2730c35bfe6 100644 --- a/mmv1/products/gemini/CodeRepositoryIndex.yaml +++ b/mmv1/products/gemini/CodeRepositoryIndex.yaml @@ -59,7 +59,8 @@ error_retry_predicates: virtual_fields: - name: 'force_destroy' description: - If set to true, any RepositoryGroups for this CodeRepositoryIndex will also be deleted. + If set to true, will allow deletion of the CodeRepositoryIndex even if there are existing + RepositoryGroups for the resource. These RepositoryGroups will also be deleted. type: Boolean default_value: false parameters: