Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CodeRepositoryIndex cascade deletion #9036

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/12601.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note: enhancement
gemini: added `force_destroy` field to resource `google_code_repository_index`, enabling deletion of the resource even when it has dependent RepositoryGroups
```
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ SUSPENDED`,
Computed: true,
Description: `Output only. Update time stamp.`,
},
"force_destroy": {
Type: schema.TypeBool,
Optional: true,
Description: `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.`,
Default: false,
},
"project": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -271,6 +277,12 @@ func resourceGeminiCodeRepositoryIndexRead(d *schema.ResourceData, meta interfac
return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("GeminiCodeRepositoryIndex %q", d.Id()))
}

// Explicitly set virtual fields to default values if unset
if _, ok := d.GetOkExists("force_destroy"); !ok {
if err := d.Set("force_destroy", false); err != nil {
return fmt.Errorf("Error setting force_destroy: %s", err)
}
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading CodeRepositoryIndex: %s", err)
}
Expand Down Expand Up @@ -424,6 +436,12 @@ func resourceGeminiCodeRepositoryIndexDelete(d *schema.ResourceData, meta interf
}

headers := make(http.Header)
obj = make(map[string]interface{})
if v, ok := d.GetOk("force_destroy"); ok {
if v == true {
obj["force"] = true
}
}

log.Printf("[DEBUG] Deleting CodeRepositoryIndex %q", d.Id())
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Expand Down Expand Up @@ -470,6 +488,11 @@ func resourceGeminiCodeRepositoryIndexImport(d *schema.ResourceData, meta interf
}
d.SetId(id)

// Explicitly set virtual fields to default values on import
if err := d.Set("force_destroy", false); err != nil {
return nil, fmt.Errorf("Error setting force_destroy: %s", err)
}

return []*schema.ResourceData{d}, nil
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package gemini_test

import (
"fmt"
"os"
"testing"

Expand Down Expand Up @@ -45,6 +46,136 @@ 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", "force_destroy"},
},
{
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}"
force_destroy = true
}

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"}
depends_on = [
google_gemini_code_repository_index.example
]
}

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)
}

// 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" {
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" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ The following arguments are supported:
* `project` - (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.

* `force_destroy` - (Optional) 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.

## Attributes Reference

Expand Down
Loading