From 03e22f8fd88e92fdec9d91badbf20716c3e3243f Mon Sep 17 00:00:00 2001 From: gmarjoram Date: Tue, 13 Jun 2023 12:59:54 +0100 Subject: [PATCH] Tagging for CD Toolchains (#4607) * Tagging for CD Toolchains * Add missing diff function * Toolchain tags tests --- .../data_source_ibm_cd_toolchain.go | 15 +++++- .../data_source_ibm_cd_toolchain_test.go | 16 +++++- .../cdtoolchain/resource_ibm_cd_toolchain.go | 51 ++++++++++++++++++- .../resource_ibm_cd_toolchain_test.go | 15 ++++-- website/docs/d/cd_toolchain.html.markdown | 3 ++ website/docs/r/cd_toolchain.html.markdown | 3 ++ 6 files changed, 95 insertions(+), 8 deletions(-) diff --git a/ibm/service/cdtoolchain/data_source_ibm_cd_toolchain.go b/ibm/service/cdtoolchain/data_source_ibm_cd_toolchain.go index 60dc07c626..e185e7ec9d 100644 --- a/ibm/service/cdtoolchain/data_source_ibm_cd_toolchain.go +++ b/ibm/service/cdtoolchain/data_source_ibm_cd_toolchain.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2022 All Rights Reserved. +// Copyright IBM Corp. 2022, 2023 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package cdtoolchain @@ -81,6 +81,12 @@ func DataSourceIBMCdToolchain() *schema.Resource { Computed: true, Description: "Identity that created the toolchain.", }, + "tags": &schema.Schema{ + Type: schema.TypeSet, + Computed: true, + Description: "Toolchain tags.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, }, } } @@ -103,6 +109,13 @@ func dataSourceIBMCdToolchainRead(context context.Context, d *schema.ResourceDat d.SetId(fmt.Sprintf("%s", *getToolchainByIDOptions.ToolchainID)) + tags, err := flex.GetTagsUsingCRN(meta, *toolchain.CRN) + if err != nil { + log.Printf( + "Error on get of toolchain (%s) tags: %s", d.Id(), err) + } + d.Set("tags", tags) + if err = d.Set("name", toolchain.Name); err != nil { return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) } diff --git a/ibm/service/cdtoolchain/data_source_ibm_cd_toolchain_test.go b/ibm/service/cdtoolchain/data_source_ibm_cd_toolchain_test.go index fa85924569..e64b50512e 100644 --- a/ibm/service/cdtoolchain/data_source_ibm_cd_toolchain_test.go +++ b/ibm/service/cdtoolchain/data_source_ibm_cd_toolchain_test.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2022 All Rights Reserved. +// Copyright IBM Corp. 2022, 2023 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package cdtoolchain_test @@ -50,6 +50,12 @@ func TestAccIBMCdToolchainDataSourceAllArgs(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, Providers: acc.TestAccProviders, + ExternalProviders: map[string]resource.ExternalProvider{ + "time": { + Source: "hashicorp/time", + VersionConstraint: ">=0.9.1", + }, + }, Steps: []resource.TestStep{ resource.TestStep{ Config: testAccCheckIBMCdToolchainDataSourceConfig(toolchainName, toolchainResourceGroupName, toolchainDescription), @@ -67,6 +73,7 @@ func TestAccIBMCdToolchainDataSourceAllArgs(t *testing.T) { resource.TestCheckResourceAttrSet("data.ibm_cd_toolchain.cd_toolchain", "created_at"), resource.TestCheckResourceAttrSet("data.ibm_cd_toolchain.cd_toolchain", "updated_at"), resource.TestCheckResourceAttrSet("data.ibm_cd_toolchain.cd_toolchain", "created_by"), + resource.TestCheckResourceAttr("data.ibm_cd_toolchain.cd_toolchain", "tags.#", "2"), ), }, }, @@ -100,10 +107,17 @@ func testAccCheckIBMCdToolchainDataSourceConfig(toolchainName string, toolchainR name = "%s" resource_group_id = data.ibm_resource_group.resource_group.id description = "%s" + tags = ["tag1","tag2"] } + resource "time_sleep" "wait_time" { + create_duration = "10s" + depends_on = [ibm_cd_toolchain.cd_toolchain] + } + data "ibm_cd_toolchain" "cd_toolchain" { toolchain_id = ibm_cd_toolchain.cd_toolchain.id + depends_on = [time_sleep.wait_time] } `, toolchainResourceGroupName, toolchainName, toolchainDescription) } diff --git a/ibm/service/cdtoolchain/resource_ibm_cd_toolchain.go b/ibm/service/cdtoolchain/resource_ibm_cd_toolchain.go index 277a61147f..64f7ebfd07 100644 --- a/ibm/service/cdtoolchain/resource_ibm_cd_toolchain.go +++ b/ibm/service/cdtoolchain/resource_ibm_cd_toolchain.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2022 All Rights Reserved. +// Copyright IBM Corp. 2022, 2023 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package cdtoolchain @@ -7,8 +7,10 @@ import ( "context" "fmt" "log" + "os" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" @@ -24,6 +26,11 @@ func ResourceIBMCdToolchain() *schema.Resource { UpdateContext: resourceIBMCdToolchainUpdate, DeleteContext: resourceIBMCdToolchainDelete, Importer: &schema.ResourceImporter{}, + CustomizeDiff: customdiff.Sequence( + func(_ context.Context, diff *schema.ResourceDiff, v interface{}) error { + return flex.ResourceTagsCustomizeDiff(diff) + }, + ), Schema: map[string]*schema.Schema{ "name": &schema.Schema{ @@ -85,6 +92,15 @@ func ResourceIBMCdToolchain() *schema.Resource { Computed: true, Description: "Identity that created the toolchain.", }, + "tags": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString, ValidateFunc: validate.InvokeValidator("ibm_cd_toolchain", "tags")}, + Set: flex.ResourceIBMVPCHash, + ValidateFunc: validate.InvokeValidator("ibm_cd_toolchain", "tags"), + Description: "Toolchain tags.", + }, }, } } @@ -119,6 +135,13 @@ func ResourceIBMCdToolchainValidator() *validate.ResourceValidator { MinValueLength: 0, MaxValueLength: 500, }, + validate.ValidateSchema{ + Identifier: "tags", + ValidateFunctionIdentifier: validate.ValidateCloudData, + Type: validate.TypeString, + CloudDataType: "tags", + Optional: true, + }, ) resourceValidator := validate.ResourceValidator{ResourceName: "ibm_cd_toolchain", Schema: validateSchema} @@ -147,6 +170,16 @@ func resourceIBMCdToolchainCreate(context context.Context, d *schema.ResourceDat d.SetId(*toolchainPost.ID) + v := os.Getenv("IC_ENV_TAGS") + if _, ok := d.GetOk("tags"); ok || v != "" { + oldList, newList := d.GetChange("tags") + err = flex.UpdateTagsUsingCRN(oldList, newList, meta, *toolchainPost.CRN) + if err != nil { + log.Printf( + "Error on create of toolchain (%s) tags: %s", d.Id(), err) + } + } + return resourceIBMCdToolchainRead(context, d, meta) } @@ -170,6 +203,13 @@ func resourceIBMCdToolchainRead(context context.Context, d *schema.ResourceData, return diag.FromErr(fmt.Errorf("GetToolchainByIDWithContext failed %s\n%s", err, response)) } + tags, err := flex.GetTagsUsingCRN(meta, *toolchain.CRN) + if err != nil { + log.Printf( + "Error on get of toolchain (%s) tags: %s", d.Id(), err) + } + d.Set("tags", tags) + if err = d.Set("name", toolchain.Name); err != nil { return diag.FromErr(fmt.Errorf("Error setting name: %s", err)) } @@ -235,6 +275,15 @@ func resourceIBMCdToolchainUpdate(context context.Context, d *schema.ResourceDat hasChange = true } + if d.HasChange("tags") { + oldList, newList := d.GetChange("tags") + err = flex.UpdateTagsUsingCRN(oldList, newList, meta, d.Get("crn").(string)) + if err != nil { + log.Printf( + "Error on update of toolchain (%s) tags: %s", d.Id(), err) + } + } + if hasChange { updateToolchainOptions.ToolchainPrototypePatch, _ = patchVals.AsPatch() _, response, err := cdToolchainClient.UpdateToolchainWithContext(context, updateToolchainOptions) diff --git a/ibm/service/cdtoolchain/resource_ibm_cd_toolchain_test.go b/ibm/service/cdtoolchain/resource_ibm_cd_toolchain_test.go index 2602867189..6b70ca4818 100644 --- a/ibm/service/cdtoolchain/resource_ibm_cd_toolchain_test.go +++ b/ibm/service/cdtoolchain/resource_ibm_cd_toolchain_test.go @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2022 All Rights Reserved. +// Copyright IBM Corp. 2022, 2023 All Rights Reserved. // Licensed under the Mozilla Public License v2.0 package cdtoolchain_test @@ -51,8 +51,10 @@ func TestAccIBMCdToolchainAllArgs(t *testing.T) { name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) rgName := acc.CdResourceGroupName description := fmt.Sprintf("tf_description_%d", acctest.RandIntRange(10, 100)) + tags := `["tag1", "tag2"]` nameUpdate := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) descriptionUpdate := fmt.Sprintf("tf_description_%d", acctest.RandIntRange(10, 100)) + tagsUpdate := `["tag1","tag2","tag3"]` resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, @@ -60,20 +62,22 @@ func TestAccIBMCdToolchainAllArgs(t *testing.T) { CheckDestroy: testAccCheckIBMCdToolchainDestroy, Steps: []resource.TestStep{ resource.TestStep{ - Config: testAccCheckIBMCdToolchainConfig(name, rgName, description), + Config: testAccCheckIBMCdToolchainConfig(name, rgName, description, tags), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckIBMCdToolchainExists("ibm_cd_toolchain.cd_toolchain", conf), resource.TestCheckResourceAttr("ibm_cd_toolchain.cd_toolchain", "name", name), resource.TestCheckResourceAttrSet("ibm_cd_toolchain.cd_toolchain", "resource_group_id"), resource.TestCheckResourceAttr("ibm_cd_toolchain.cd_toolchain", "description", description), + resource.TestCheckResourceAttr("ibm_cd_toolchain.cd_toolchain", "tags.#", "2"), ), }, resource.TestStep{ - Config: testAccCheckIBMCdToolchainConfig(nameUpdate, rgName, descriptionUpdate), + Config: testAccCheckIBMCdToolchainConfig(nameUpdate, rgName, descriptionUpdate, tagsUpdate), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("ibm_cd_toolchain.cd_toolchain", "name", nameUpdate), resource.TestCheckResourceAttrSet("ibm_cd_toolchain.cd_toolchain", "resource_group_id"), resource.TestCheckResourceAttr("ibm_cd_toolchain.cd_toolchain", "description", descriptionUpdate), + resource.TestCheckResourceAttr("ibm_cd_toolchain.cd_toolchain", "tags.#", "3"), ), }, resource.TestStep{ @@ -98,7 +102,7 @@ func testAccCheckIBMCdToolchainConfigBasic(name string, rgName string) string { `, rgName, name) } -func testAccCheckIBMCdToolchainConfig(name string, rgName string, description string) string { +func testAccCheckIBMCdToolchainConfig(name string, rgName string, description string, tags string) string { return fmt.Sprintf(` data "ibm_resource_group" "resource_group" { name = "%s" @@ -108,8 +112,9 @@ func testAccCheckIBMCdToolchainConfig(name string, rgName string, description st name = "%s" resource_group_id = data.ibm_resource_group.resource_group.id description = "%s" + tags = %s } - `, rgName, name, description) + `, rgName, name, description, tags) } func testAccCheckIBMCdToolchainExists(n string, obj cdtoolchainv2.Toolchain) resource.TestCheckFunc { diff --git a/website/docs/d/cd_toolchain.html.markdown b/website/docs/d/cd_toolchain.html.markdown index c89e129ab0..20d1ac80a8 100644 --- a/website/docs/d/cd_toolchain.html.markdown +++ b/website/docs/d/cd_toolchain.html.markdown @@ -53,3 +53,6 @@ In addition to all argument references listed, you can access the following attr * `updated_at` - (String) Latest toolchain update timestamp. +* `tags` - (Array of Strings) Tags associated with the toolchain. + + diff --git a/website/docs/r/cd_toolchain.html.markdown b/website/docs/r/cd_toolchain.html.markdown index 2fc2e70921..3bc8a43d09 100644 --- a/website/docs/r/cd_toolchain.html.markdown +++ b/website/docs/r/cd_toolchain.html.markdown @@ -17,6 +17,7 @@ resource "ibm_cd_toolchain" "cd_toolchain_instance" { description = "A sample toolchain to test the API" name = "TestToolchainV2" resource_group_id = "6a9a01f2cff54a7f966f803d92877123" + tags = ["tag1", "tag2"] } ``` @@ -30,6 +31,8 @@ Review the argument reference that you can specify for your resource. * Constraints: The maximum length is `128` characters. The minimum length is `0` characters. The value must match regular expression `/^([^\\x00-\\x7F]|[a-zA-Z0-9-._ ])+$/`. * `resource_group_id` - (Required, Forces new resource, String) Resource group where toolchain will be created. * Constraints: The maximum length is `32` characters. The minimum length is `32` characters. The value must match regular expression `/^[0-9a-f]{32}$/`. +* `tags` - (Optional, Array of Strings) Tags associated with the toolchain. + ## Attribute Reference