From 0df5465c8386dcfcdfcfcd43f99a116774b07797 Mon Sep 17 00:00:00 2001 From: Jiawei Tao Date: Fri, 9 Feb 2024 14:42:44 +0800 Subject: [PATCH 1/5] New Resource: azurerm_dev_center_catalog --- .../devcenter/dev_center_catalogs_resource.go | 305 ++++++++++++++++++ .../dev_center_catalogs_resource_test.go | 164 ++++++++++ internal/services/devcenter/registration.go | 1 + .../docs/r/dev_center_catalogs.html.markdown | 89 +++++ 4 files changed, 559 insertions(+) create mode 100644 internal/services/devcenter/dev_center_catalogs_resource.go create mode 100644 internal/services/devcenter/dev_center_catalogs_resource_test.go create mode 100644 website/docs/r/dev_center_catalogs.html.markdown diff --git a/internal/services/devcenter/dev_center_catalogs_resource.go b/internal/services/devcenter/dev_center_catalogs_resource.go new file mode 100644 index 000000000000..cfb1db310fd7 --- /dev/null +++ b/internal/services/devcenter/dev_center_catalogs_resource.go @@ -0,0 +1,305 @@ +package devcenter + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-sdk/resource-manager/devcenter/2023-04-01/catalogs" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +type DevCenterCatalogsResourceModel struct { + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + DevCenterID string `tfschema:"dev_center_id"` + CatalogType string `tfschema:"catalog_type"` + URI string `tfschema:"uri"` + Branch string `tfschema:"branch"` + SecretIdentifier string `tfschema:"secret_identifier"` + Path string `tfschema:"path"` +} + +type DevCenterCatalogsResource struct{} + +var _ sdk.Resource = DevCenterCatalogsResource{} + +func (r DevCenterCatalogsResource) ModelObject() interface{} { + return &DevCenterCatalogsResourceModel{} +} + +func (r DevCenterCatalogsResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return catalogs.ValidateCatalogID +} + +func (r DevCenterCatalogsResource) ResourceType() string { + return "azurerm_dev_center_catalog" +} + +func (r DevCenterCatalogsResource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Required: true, + Type: pluginsdk.TypeString, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "resource_group_name": commonschema.ResourceGroupName(), + + "dev_center_id": { + Required: true, + Type: pluginsdk.TypeString, + ForceNew: true, + ValidateFunc: catalogs.ValidateDevCenterID, + }, + + "catalog_type": { + Required: true, + Type: pluginsdk.TypeString, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + "gitHub", + "adoGit", + }, false), + }, + + "uri": { + Required: true, + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "branch": { + Required: true, + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "secret_identifier": { + Required: true, + Type: pluginsdk.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "path": { + Required: true, + Type: pluginsdk.TypeString, + }, + } +} + +func (r DevCenterCatalogsResource) Attributes() map[string]*schema.Schema { + return map[string]*schema.Schema{} +} + +func (r DevCenterCatalogsResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var model DevCenterCatalogsResourceModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding %+v", err) + } + + client := metadata.Client.DevCenter.V20230401.Catalogs + subscriptionId := metadata.Client.Account.SubscriptionId + devCenterId, err := catalogs.ParseDevCenterID(model.DevCenterID) + if err != nil { + return fmt.Errorf("parsing dev center id: %+v", err) + } + devCenterName := devCenterId.DevCenterName + id := catalogs.NewCatalogID(subscriptionId, model.ResourceGroupName, devCenterName, model.Name) + + existing, err := client.Get(ctx, id) + if err != nil { + if !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for the presence of an existing %s: %+v", id, err) + } + } + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + var properties catalogs.Catalog + if model.CatalogType == "gitHub" { + gitHubProps := catalogs.GitCatalog{ + Branch: pointer.To(model.Branch), + Uri: pointer.To(model.URI), + Path: pointer.To(model.Path), + SecretIdentifier: pointer.To(model.SecretIdentifier), + } + + properties = catalogs.Catalog{ + Properties: &catalogs.CatalogProperties{ + GitHub: pointer.To(gitHubProps), + }, + } + } else { + adoGitProps := catalogs.GitCatalog{ + Branch: pointer.To(model.Branch), + Uri: pointer.To(model.URI), + Path: pointer.To(model.Path), + SecretIdentifier: pointer.To(model.SecretIdentifier), + } + + properties = catalogs.Catalog{ + Properties: &catalogs.CatalogProperties{ + AdoGit: pointer.To(adoGitProps), + }, + } + } + + if _, err := client.CreateOrUpdate(ctx, id, properties); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + metadata.SetID(id) + return nil + }, + } +} + +func (r DevCenterCatalogsResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var model DevCenterCatalogsResourceModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding %+v", err) + } + + client := metadata.Client.DevCenter.V20230401.Catalogs + id, err := catalogs.ParseCatalogID(metadata.ResourceData.Id()) + if err != nil { + return fmt.Errorf("parsing catalog id: %+v", err) + } + + resp, err := client.Get(ctx, *id) + if err != nil { + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + properties := resp.Model + if properties == nil { + return fmt.Errorf("retrieving %s: model was nil", id) + } + + if metadata.ResourceData.HasChange("uri") { + if model.CatalogType == "gitHub" { + properties.Properties.GitHub.Uri = pointer.To(model.URI) + } else { + properties.Properties.AdoGit.Uri = pointer.To(model.URI) + } + } + + if metadata.ResourceData.HasChange("branch") { + if model.CatalogType == "gitHub" { + properties.Properties.GitHub.Branch = pointer.To(model.Branch) + } else { + properties.Properties.AdoGit.Branch = pointer.To(model.Branch) + } + } + + if metadata.ResourceData.HasChange("path") { + if model.CatalogType == "gitHub" { + properties.Properties.GitHub.Path = pointer.To(model.Path) + } else { + properties.Properties.AdoGit.Path = pointer.To(model.Path) + } + } + + if metadata.ResourceData.HasChange("secret_identifier") { + if model.CatalogType == "gitHub" { + properties.Properties.GitHub.SecretIdentifier = pointer.To(model.SecretIdentifier) + } else { + properties.Properties.AdoGit.SecretIdentifier = pointer.To(model.SecretIdentifier) + } + } + + if _, err := client.CreateOrUpdate(ctx, *id, *properties); err != nil { + return fmt.Errorf("updating %s: %+v", *id, err) + } + + return nil + }, + } +} + +func (r DevCenterCatalogsResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DevCenter.V20230401.Catalogs + + id, err := catalogs.ParseCatalogID(metadata.ResourceData.Id()) + if err != nil { + return fmt.Errorf("parsing catalog id: %+v", err) + } + + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return metadata.MarkAsGone(id) + } + + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + model := resp.Model + if model == nil { + return fmt.Errorf("retrieving %s: model was nil", id) + } + + state := DevCenterCatalogsResourceModel{ + Name: id.CatalogName, + ResourceGroupName: id.ResourceGroupName, + } + state.DevCenterID = catalogs.NewDevCenterID(id.SubscriptionId, id.ResourceGroupName, id.DevCenterName).ID() + + if properties := model.Properties; properties != nil { + if gitHub := properties.GitHub; gitHub != nil { + state.CatalogType = "gitHub" + state.URI = pointer.From(gitHub.Uri) + state.Branch = pointer.From(gitHub.Branch) + state.Path = pointer.From(gitHub.Path) + state.SecretIdentifier = pointer.From(gitHub.SecretIdentifier) + } else if adoGit := properties.AdoGit; adoGit != nil { + state.CatalogType = "adoGit" + state.URI = pointer.From(adoGit.Uri) + state.Branch = pointer.From(adoGit.Branch) + state.Path = pointer.From(adoGit.Path) + state.SecretIdentifier = pointer.From(adoGit.SecretIdentifier) + } + } + + return metadata.Encode(&state) + }, + } +} + +func (r DevCenterCatalogsResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DevCenter.V20230401.Catalogs + + id, err := catalogs.ParseCatalogID(metadata.ResourceData.Id()) + if err != nil { + return fmt.Errorf("parsing catalog id: %+v", err) + } + + if err := client.DeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + + return nil + }, + } +} diff --git a/internal/services/devcenter/dev_center_catalogs_resource_test.go b/internal/services/devcenter/dev_center_catalogs_resource_test.go new file mode 100644 index 000000000000..5b2c9a03552c --- /dev/null +++ b/internal/services/devcenter/dev_center_catalogs_resource_test.go @@ -0,0 +1,164 @@ +package devcenter_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/go-azure-sdk/resource-manager/devcenter/2023-04-01/catalogs" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type DevCenterCatalogsResource struct{} + +func (r DevCenterCatalogsResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := catalogs.ParseCatalogID(state.ID) + if err != nil { + return nil, err + } + + resp, err := client.DevCenter.V20230401.Catalogs.Get(ctx, *id) + if err != nil { + return nil, fmt.Errorf("reading %s: %+v", *id, err) + } + + return utils.Bool(resp.Model != nil), nil +} + +func TestAccDevCenterCatalogs_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_dev_center_catalog", "test") + r := DevCenterCatalogsResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccDevCenterCatalogs_adoGit(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_dev_center_catalog", "test") + r := DevCenterCatalogsResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.adoGit(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccDevCenterCatalogs_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_dev_center_catalog", "test") + r := DevCenterCatalogsResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.update(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (r DevCenterCatalogsResource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_dev_center_catalog" "test" { + name = "acctest-catalog-%d" + resource_group_name = azurerm_resource_group.test.name + dev_center_id = azurerm_dev_center.test.id + catalog_type = "gitHub" + branch = "main" + path = "/template" + uri = "https://github.com/am-lim/deployment-environments.git" + secret_identifier = "https://amlim-kv.vault.azure.net/secrets/envTest/0a79f15246ce4b35a13957367b422cab" +} +`, r.template(data), data.RandomInteger) +} + +func (r DevCenterCatalogsResource) adoGit(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_dev_center_catalog" "test" { + name = "acctest-catalog-%d" + resource_group_name = azurerm_resource_group.test.name + dev_center_id = azurerm_dev_center.test.id + catalog_type = "adoGit" + branch = "main" + path = "/template" + uri = "https://amlim@dev.azure.com/amlim/testCatalog/_git/testCatalog" + secret_identifier = "https://amlim-kv.vault.azure.net/secrets/ado/6279752c2bdd4a38a3e79d958cc36a75" +} +`, r.template(data), data.RandomInteger) +} + +func (r DevCenterCatalogsResource) update(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_dev_center_catalog" "test" { + name = "acctest-catalog-%d" + resource_group_name = azurerm_resource_group.test.name + dev_center_id = azurerm_dev_center.test.id + catalog_type = "gitHub" + branch = "foo" + path = "" + uri = "https://github.com/am-lim/deployment-environments.git" + secret_identifier = "https://amlim-kv.vault.azure.net/secrets/envTest/0a79f15246ce4b35a13957367b422cab" +} +`, r.template(data), data.RandomInteger) +} + +func (r DevCenterCatalogsResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctest-rg-%[1]d" + location = "%s" +} + +resource "azurerm_dev_center" "test" { + name = "acctdc-%[1]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + + identity { + type = "SystemAssigned" + } +} +`, data.RandomInteger, "West Europe") +} diff --git a/internal/services/devcenter/registration.go b/internal/services/devcenter/registration.go index a02d120e2300..b243e5f276e0 100644 --- a/internal/services/devcenter/registration.go +++ b/internal/services/devcenter/registration.go @@ -32,6 +32,7 @@ func (r Registration) DataSources() []sdk.DataSource { func (r Registration) Resources() []sdk.Resource { resources := []sdk.Resource{ DevCenterGalleryResource{}, + DevCenterCatalogsResource{}, } return append(resources, r.autoRegistration.Resources()...) } diff --git a/website/docs/r/dev_center_catalogs.html.markdown b/website/docs/r/dev_center_catalogs.html.markdown new file mode 100644 index 000000000000..3045dfcead07 --- /dev/null +++ b/website/docs/r/dev_center_catalogs.html.markdown @@ -0,0 +1,89 @@ +--- +subcategory: "Dev Center" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_dev_center_catalog" +description: |- + Manages a Dev Center Catalog. +--- +# azurerm_dev_center_catalog + +Manages a Dev Center Catalog. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} +resource "azurerm_dev_center" "example" { + location = azurerm_resource_group.example.location + name = "example" + resource_group_name = azurerm_resource_group.example.name + + identity { + type = "SystemAssigned" + } +} + +resource "azurerm_dev_center_catalog" "example" { + name = "example" + resource_group_name = azurerm_resource_group.test.name + dev_center_id = azurerm_dev_center.test.id + catalog_type = "gitHub" + branch = "foo" + path = "" + uri = "example URI" + secret_identifier = "secret" +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of this Dev Center Catalog. Changing this forces a new Dev Center to be created. + +* `resource_group_name` - (Required) Specifies the name of the Resource Group within which this Dev Center Catalog should exist. Changing this forces a new Dev Center to be created. + +* `dev_center_id` - (Required) Specifies the Dev Center Id within which this Dev Center Catalog should exist. Changing this forces a new Dev Center Catalog to be created. + +* `catalog_type` - (Required) The type of the Dev Center Catalog. Possible values are `gitHub` and `adoGit`. + +* `branch` - (Required) The Git branch of the Dev Center Catalog. + +* `path` - (Required) The folder where the catalog items can be found inside the repository. + +* `secret_identifier` - (Required) A reference to the Key Vault secret containing a security token to authenticate to a Git repository. + +* `uri` - (Required) The Git URI of the Dev Center Catalog. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Dev Center Catalog. + +--- + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating this Dev Center Catalog. +* `delete` - (Defaults to 30 minutes) Used when deleting this Dev Center Catalog. +* `read` - (Defaults to 5 minutes) Used when retrieving this Dev Center Catalog. +* `update` - (Defaults to 30 minutes) Used when updating this Dev Center Catalog. + +## Import + +An existing Dev Center Catalog can be imported into Terraform using the `resource id`, e.g. + +```shell +terraform import azurerm_dev_center.example /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DevCenter/devCenters/{devCenterName}/catalogs/{catalogName} +``` + +* Where `{subscriptionId}` is the ID of the Azure Subscription where the Dev Center exists. For example `12345678-1234-9876-4563-123456789012`. +* Where `{resourceGroupName}` is the name of Resource Group where this Dev Center exists. For example `example-resource-group`. +* Where `{devCenterName}` is the name of the Dev Center. For example `devCenterValue`. +* Where `{catalogName}` is the name of the Dev Center Catalog. For example `catalogValue`. From 3e6ebc55078b3626cfc0c056dd172612cbf19a62 Mon Sep 17 00:00:00 2001 From: Jiawei Tao Date: Fri, 9 Feb 2024 15:09:59 +0800 Subject: [PATCH 2/5] fix timeout --- internal/services/devcenter/dev_center_catalogs_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/devcenter/dev_center_catalogs_resource.go b/internal/services/devcenter/dev_center_catalogs_resource.go index cfb1db310fd7..da606589f6e0 100644 --- a/internal/services/devcenter/dev_center_catalogs_resource.go +++ b/internal/services/devcenter/dev_center_catalogs_resource.go @@ -234,7 +234,7 @@ func (r DevCenterCatalogsResource) Update() sdk.ResourceFunc { func (r DevCenterCatalogsResource) Read() sdk.ResourceFunc { return sdk.ResourceFunc{ - Timeout: 30 * time.Minute, + Timeout: 5 * time.Minute, Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { client := metadata.Client.DevCenter.V20230401.Catalogs From 6a4f7928e4b2cdbdd963abaa34d67f76f1c81364 Mon Sep 17 00:00:00 2001 From: Jiawei Tao Date: Mon, 12 Feb 2024 09:53:02 +0800 Subject: [PATCH 3/5] fix naming --- .../devcenter/dev_center_catalogs_resource.go | 18 +++++++++--------- .../dev_center_catalogs_resource_test.go | 6 +++--- .../docs/r/dev_center_catalogs.html.markdown | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/internal/services/devcenter/dev_center_catalogs_resource.go b/internal/services/devcenter/dev_center_catalogs_resource.go index da606589f6e0..527fdde18256 100644 --- a/internal/services/devcenter/dev_center_catalogs_resource.go +++ b/internal/services/devcenter/dev_center_catalogs_resource.go @@ -22,7 +22,7 @@ type DevCenterCatalogsResourceModel struct { CatalogType string `tfschema:"catalog_type"` URI string `tfschema:"uri"` Branch string `tfschema:"branch"` - SecretIdentifier string `tfschema:"secret_identifier"` + KeyVaultKeyUrl string `tfschema:"key_vault_key_url"` Path string `tfschema:"path"` } @@ -82,7 +82,7 @@ func (r DevCenterCatalogsResource) Arguments() map[string]*pluginsdk.Schema { ValidateFunc: validation.StringIsNotEmpty, }, - "secret_identifier": { + "key_vault_key_url": { Required: true, Type: pluginsdk.TypeString, ValidateFunc: validation.StringIsNotEmpty, @@ -133,7 +133,7 @@ func (r DevCenterCatalogsResource) Create() sdk.ResourceFunc { Branch: pointer.To(model.Branch), Uri: pointer.To(model.URI), Path: pointer.To(model.Path), - SecretIdentifier: pointer.To(model.SecretIdentifier), + SecretIdentifier: pointer.To(model.KeyVaultKeyUrl), } properties = catalogs.Catalog{ @@ -146,7 +146,7 @@ func (r DevCenterCatalogsResource) Create() sdk.ResourceFunc { Branch: pointer.To(model.Branch), Uri: pointer.To(model.URI), Path: pointer.To(model.Path), - SecretIdentifier: pointer.To(model.SecretIdentifier), + SecretIdentifier: pointer.To(model.KeyVaultKeyUrl), } properties = catalogs.Catalog{ @@ -215,11 +215,11 @@ func (r DevCenterCatalogsResource) Update() sdk.ResourceFunc { } } - if metadata.ResourceData.HasChange("secret_identifier") { + if metadata.ResourceData.HasChange("key_vault_key_url") { if model.CatalogType == "gitHub" { - properties.Properties.GitHub.SecretIdentifier = pointer.To(model.SecretIdentifier) + properties.Properties.GitHub.SecretIdentifier = pointer.To(model.KeyVaultKeyUrl) } else { - properties.Properties.AdoGit.SecretIdentifier = pointer.To(model.SecretIdentifier) + properties.Properties.AdoGit.SecretIdentifier = pointer.To(model.KeyVaultKeyUrl) } } @@ -269,13 +269,13 @@ func (r DevCenterCatalogsResource) Read() sdk.ResourceFunc { state.URI = pointer.From(gitHub.Uri) state.Branch = pointer.From(gitHub.Branch) state.Path = pointer.From(gitHub.Path) - state.SecretIdentifier = pointer.From(gitHub.SecretIdentifier) + state.KeyVaultKeyUrl = pointer.From(gitHub.SecretIdentifier) } else if adoGit := properties.AdoGit; adoGit != nil { state.CatalogType = "adoGit" state.URI = pointer.From(adoGit.Uri) state.Branch = pointer.From(adoGit.Branch) state.Path = pointer.From(adoGit.Path) - state.SecretIdentifier = pointer.From(adoGit.SecretIdentifier) + state.KeyVaultKeyUrl = pointer.From(adoGit.SecretIdentifier) } } diff --git a/internal/services/devcenter/dev_center_catalogs_resource_test.go b/internal/services/devcenter/dev_center_catalogs_resource_test.go index 5b2c9a03552c..d1c3678e403e 100644 --- a/internal/services/devcenter/dev_center_catalogs_resource_test.go +++ b/internal/services/devcenter/dev_center_catalogs_resource_test.go @@ -97,7 +97,7 @@ resource "azurerm_dev_center_catalog" "test" { branch = "main" path = "/template" uri = "https://github.com/am-lim/deployment-environments.git" - secret_identifier = "https://amlim-kv.vault.azure.net/secrets/envTest/0a79f15246ce4b35a13957367b422cab" + key_vault_key_url = "https://amlim-kv.vault.azure.net/secrets/envTest/0a79f15246ce4b35a13957367b422cab" } `, r.template(data), data.RandomInteger) } @@ -118,7 +118,7 @@ resource "azurerm_dev_center_catalog" "test" { branch = "main" path = "/template" uri = "https://amlim@dev.azure.com/amlim/testCatalog/_git/testCatalog" - secret_identifier = "https://amlim-kv.vault.azure.net/secrets/ado/6279752c2bdd4a38a3e79d958cc36a75" + key_vault_key_url = "https://amlim-kv.vault.azure.net/secrets/ado/6279752c2bdd4a38a3e79d958cc36a75" } `, r.template(data), data.RandomInteger) } @@ -139,7 +139,7 @@ resource "azurerm_dev_center_catalog" "test" { branch = "foo" path = "" uri = "https://github.com/am-lim/deployment-environments.git" - secret_identifier = "https://amlim-kv.vault.azure.net/secrets/envTest/0a79f15246ce4b35a13957367b422cab" + key_vault_key_url = "https://amlim-kv.vault.azure.net/secrets/envTest/0a79f15246ce4b35a13957367b422cab" } `, r.template(data), data.RandomInteger) } diff --git a/website/docs/r/dev_center_catalogs.html.markdown b/website/docs/r/dev_center_catalogs.html.markdown index 3045dfcead07..9901e71b0c45 100644 --- a/website/docs/r/dev_center_catalogs.html.markdown +++ b/website/docs/r/dev_center_catalogs.html.markdown @@ -34,7 +34,7 @@ resource "azurerm_dev_center_catalog" "example" { branch = "foo" path = "" uri = "example URI" - secret_identifier = "secret" + key_vault_key_url = "secret" } ``` @@ -54,7 +54,7 @@ The following arguments are supported: * `path` - (Required) The folder where the catalog items can be found inside the repository. -* `secret_identifier` - (Required) A reference to the Key Vault secret containing a security token to authenticate to a Git repository. +* `key_vault_key_url` - (Required) A reference to the Key Vault secret containing a security token to authenticate to a Git repository. * `uri` - (Required) The Git URI of the Dev Center Catalog. From 627052d44d32479c054f1959368a615da71c2f84 Mon Sep 17 00:00:00 2001 From: Jiawei Tao Date: Sun, 18 Feb 2024 15:32:03 +0800 Subject: [PATCH 4/5] split github/adogit blocks --- .../devcenter/dev_center_catalogs_resource.go | 196 ++++++++---------- .../dev_center_catalogs_resource_test.go | 33 +-- .../docs/r/dev_center_catalogs.html.markdown | 31 ++- 3 files changed, 133 insertions(+), 127 deletions(-) diff --git a/internal/services/devcenter/dev_center_catalogs_resource.go b/internal/services/devcenter/dev_center_catalogs_resource.go index 527fdde18256..0902542b5ad0 100644 --- a/internal/services/devcenter/dev_center_catalogs_resource.go +++ b/internal/services/devcenter/dev_center_catalogs_resource.go @@ -16,14 +16,18 @@ import ( ) type DevCenterCatalogsResourceModel struct { - Name string `tfschema:"name"` - ResourceGroupName string `tfschema:"resource_group_name"` - DevCenterID string `tfschema:"dev_center_id"` - CatalogType string `tfschema:"catalog_type"` - URI string `tfschema:"uri"` - Branch string `tfschema:"branch"` - KeyVaultKeyUrl string `tfschema:"key_vault_key_url"` - Path string `tfschema:"path"` + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + DevCenterID string `tfschema:"dev_center_id"` + CatalogGitHub []CatalogPropertiesModel `tfschema:"catalog_github"` + CatalogAdoGit []CatalogPropertiesModel `tfschema:"catalog_adogit"` +} + +type CatalogPropertiesModel struct { + URI string `tfschema:"uri"` + Branch string `tfschema:"branch"` + KeyVaultKeyUrl string `tfschema:"key_vault_key_url"` + Path string `tfschema:"path"` } type DevCenterCatalogsResource struct{} @@ -60,38 +64,9 @@ func (r DevCenterCatalogsResource) Arguments() map[string]*pluginsdk.Schema { ValidateFunc: catalogs.ValidateDevCenterID, }, - "catalog_type": { - Required: true, - Type: pluginsdk.TypeString, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - "gitHub", - "adoGit", - }, false), - }, - - "uri": { - Required: true, - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringIsNotEmpty, - }, - - "branch": { - Required: true, - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringIsNotEmpty, - }, - - "key_vault_key_url": { - Required: true, - Type: pluginsdk.TypeString, - ValidateFunc: validation.StringIsNotEmpty, - }, + "catalog_github": CatalogPropertiesSchema(), - "path": { - Required: true, - Type: pluginsdk.TypeString, - }, + "catalog_adogit": CatalogPropertiesSchema(), } } @@ -127,36 +102,14 @@ func (r DevCenterCatalogsResource) Create() sdk.ResourceFunc { return metadata.ResourceRequiresImport(r.ResourceType(), id) } - var properties catalogs.Catalog - if model.CatalogType == "gitHub" { - gitHubProps := catalogs.GitCatalog{ - Branch: pointer.To(model.Branch), - Uri: pointer.To(model.URI), - Path: pointer.To(model.Path), - SecretIdentifier: pointer.To(model.KeyVaultKeyUrl), - } - - properties = catalogs.Catalog{ - Properties: &catalogs.CatalogProperties{ - GitHub: pointer.To(gitHubProps), - }, - } - } else { - adoGitProps := catalogs.GitCatalog{ - Branch: pointer.To(model.Branch), - Uri: pointer.To(model.URI), - Path: pointer.To(model.Path), - SecretIdentifier: pointer.To(model.KeyVaultKeyUrl), - } - - properties = catalogs.Catalog{ - Properties: &catalogs.CatalogProperties{ - AdoGit: pointer.To(adoGitProps), - }, - } + catalogProperties := catalogs.Catalog{ + Properties: &catalogs.CatalogProperties{ + AdoGit: expandCatalogProperties(model.CatalogAdoGit), + GitHub: expandCatalogProperties(model.CatalogGitHub), + }, } - if _, err := client.CreateOrUpdate(ctx, id, properties); err != nil { + if _, err := client.CreateOrUpdate(ctx, id, catalogProperties); err != nil { return fmt.Errorf("creating %s: %+v", id, err) } @@ -191,36 +144,12 @@ func (r DevCenterCatalogsResource) Update() sdk.ResourceFunc { return fmt.Errorf("retrieving %s: model was nil", id) } - if metadata.ResourceData.HasChange("uri") { - if model.CatalogType == "gitHub" { - properties.Properties.GitHub.Uri = pointer.To(model.URI) - } else { - properties.Properties.AdoGit.Uri = pointer.To(model.URI) - } + if metadata.ResourceData.HasChange("catalog_github") { + properties.Properties.GitHub = expandCatalogProperties(model.CatalogGitHub) } - if metadata.ResourceData.HasChange("branch") { - if model.CatalogType == "gitHub" { - properties.Properties.GitHub.Branch = pointer.To(model.Branch) - } else { - properties.Properties.AdoGit.Branch = pointer.To(model.Branch) - } - } - - if metadata.ResourceData.HasChange("path") { - if model.CatalogType == "gitHub" { - properties.Properties.GitHub.Path = pointer.To(model.Path) - } else { - properties.Properties.AdoGit.Path = pointer.To(model.Path) - } - } - - if metadata.ResourceData.HasChange("key_vault_key_url") { - if model.CatalogType == "gitHub" { - properties.Properties.GitHub.SecretIdentifier = pointer.To(model.KeyVaultKeyUrl) - } else { - properties.Properties.AdoGit.SecretIdentifier = pointer.To(model.KeyVaultKeyUrl) - } + if metadata.ResourceData.HasChange("catalog_adogit") { + properties.Properties.AdoGit = expandCatalogProperties(model.CatalogAdoGit) } if _, err := client.CreateOrUpdate(ctx, *id, *properties); err != nil { @@ -265,17 +194,25 @@ func (r DevCenterCatalogsResource) Read() sdk.ResourceFunc { if properties := model.Properties; properties != nil { if gitHub := properties.GitHub; gitHub != nil { - state.CatalogType = "gitHub" - state.URI = pointer.From(gitHub.Uri) - state.Branch = pointer.From(gitHub.Branch) - state.Path = pointer.From(gitHub.Path) - state.KeyVaultKeyUrl = pointer.From(gitHub.SecretIdentifier) - } else if adoGit := properties.AdoGit; adoGit != nil { - state.CatalogType = "adoGit" - state.URI = pointer.From(adoGit.Uri) - state.Branch = pointer.From(adoGit.Branch) - state.Path = pointer.From(adoGit.Path) - state.KeyVaultKeyUrl = pointer.From(adoGit.SecretIdentifier) + state.CatalogGitHub = []CatalogPropertiesModel{ + { + URI: pointer.From(gitHub.Uri), + Branch: pointer.From(gitHub.Branch), + KeyVaultKeyUrl: pointer.From(gitHub.SecretIdentifier), + Path: pointer.From(gitHub.Path), + }, + } + } + + if adoGit := properties.AdoGit; adoGit != nil { + state.CatalogAdoGit = []CatalogPropertiesModel{ + { + URI: pointer.From(adoGit.Uri), + Branch: pointer.From(adoGit.Branch), + KeyVaultKeyUrl: pointer.From(adoGit.SecretIdentifier), + Path: pointer.From(adoGit.Path), + }, + } } } @@ -303,3 +240,50 @@ func (r DevCenterCatalogsResource) Delete() sdk.ResourceFunc { }, } } + +func CatalogPropertiesSchema() *pluginsdk.Schema { + return &pluginsdk.Schema{ + Type: pluginsdk.TypeList, + MaxItems: 1, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "uri": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "branch": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "key_vault_key_url": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "path": { + Type: pluginsdk.TypeString, + Required: true, + }, + }, + }, + } +} + +func expandCatalogProperties(input []CatalogPropertiesModel) *catalogs.GitCatalog { + if input == nil || len(input) == 0 { + return nil + } + + return &catalogs.GitCatalog{ + Uri: pointer.To(input[0].URI), + Branch: pointer.To(input[0].Branch), + SecretIdentifier: pointer.To(input[0].KeyVaultKeyUrl), + Path: pointer.To(input[0].Path), + } +} diff --git a/internal/services/devcenter/dev_center_catalogs_resource_test.go b/internal/services/devcenter/dev_center_catalogs_resource_test.go index d1c3678e403e..1ba4a8001a13 100644 --- a/internal/services/devcenter/dev_center_catalogs_resource_test.go +++ b/internal/services/devcenter/dev_center_catalogs_resource_test.go @@ -93,11 +93,12 @@ resource "azurerm_dev_center_catalog" "test" { name = "acctest-catalog-%d" resource_group_name = azurerm_resource_group.test.name dev_center_id = azurerm_dev_center.test.id - catalog_type = "gitHub" - branch = "main" - path = "/template" - uri = "https://github.com/am-lim/deployment-environments.git" - key_vault_key_url = "https://amlim-kv.vault.azure.net/secrets/envTest/0a79f15246ce4b35a13957367b422cab" + catalog_github { + branch = "main" + path = "/template" + uri = "https://github.com/am-lim/deployment-environments.git" + key_vault_key_url = "https://amlim-kv.vault.azure.net/secrets/envTest/0a79f15246ce4b35a13957367b422cab" + } } `, r.template(data), data.RandomInteger) } @@ -114,11 +115,12 @@ resource "azurerm_dev_center_catalog" "test" { name = "acctest-catalog-%d" resource_group_name = azurerm_resource_group.test.name dev_center_id = azurerm_dev_center.test.id - catalog_type = "adoGit" - branch = "main" - path = "/template" - uri = "https://amlim@dev.azure.com/amlim/testCatalog/_git/testCatalog" - key_vault_key_url = "https://amlim-kv.vault.azure.net/secrets/ado/6279752c2bdd4a38a3e79d958cc36a75" + catalog_adogit { + branch = "main" + path = "/template" + uri = "https://amlim@dev.azure.com/amlim/testCatalog/_git/testCatalog" + key_vault_key_url = "https://amlim-kv.vault.azure.net/secrets/ado/6279752c2bdd4a38a3e79d958cc36a75" + } } `, r.template(data), data.RandomInteger) } @@ -135,11 +137,12 @@ resource "azurerm_dev_center_catalog" "test" { name = "acctest-catalog-%d" resource_group_name = azurerm_resource_group.test.name dev_center_id = azurerm_dev_center.test.id - catalog_type = "gitHub" - branch = "foo" - path = "" - uri = "https://github.com/am-lim/deployment-environments.git" - key_vault_key_url = "https://amlim-kv.vault.azure.net/secrets/envTest/0a79f15246ce4b35a13957367b422cab" + catalog_github { + branch = "foo" + path = "" + uri = "https://github.com/am-lim/deployment-environments.git" + key_vault_key_url = "https://amlim-kv.vault.azure.net/secrets/envTest/0a79f15246ce4b35a13957367b422cab" + } } `, r.template(data), data.RandomInteger) } diff --git a/website/docs/r/dev_center_catalogs.html.markdown b/website/docs/r/dev_center_catalogs.html.markdown index 9901e71b0c45..5ebf1f117e26 100644 --- a/website/docs/r/dev_center_catalogs.html.markdown +++ b/website/docs/r/dev_center_catalogs.html.markdown @@ -30,11 +30,12 @@ resource "azurerm_dev_center_catalog" "example" { name = "example" resource_group_name = azurerm_resource_group.test.name dev_center_id = azurerm_dev_center.test.id - catalog_type = "gitHub" - branch = "foo" - path = "" - uri = "example URI" - key_vault_key_url = "secret" + catalog_github { + branch = "foo" + path = "" + uri = "example URI" + key_vault_key_url = "secret" + } } ``` @@ -48,7 +49,25 @@ The following arguments are supported: * `dev_center_id` - (Required) Specifies the Dev Center Id within which this Dev Center Catalog should exist. Changing this forces a new Dev Center Catalog to be created. -* `catalog_type` - (Required) The type of the Dev Center Catalog. Possible values are `gitHub` and `adoGit`. +* `catalog_github` - (Optional) A `catalog_github` block as defined below. + +* `catalog_adogit` - (Optional) A `catalog_adogit` block as defined below. + +--- + +* `catalog_github` supports the following: + +* `branch` - (Required) The Git branch of the Dev Center Catalog. + +* `path` - (Required) The folder where the catalog items can be found inside the repository. + +* `key_vault_key_url` - (Required) A reference to the Key Vault secret containing a security token to authenticate to a Git repository. + +* `uri` - (Required) The Git URI of the Dev Center Catalog. + +--- + +* `catalog_adogit` supports the following: * `branch` - (Required) The Git branch of the Dev Center Catalog. From 2ca895119b54226b7ed79d45883a676d8ee4a986 Mon Sep 17 00:00:00 2001 From: Jiawei Tao Date: Sun, 18 Feb 2024 15:42:28 +0800 Subject: [PATCH 5/5] remove nil check --- internal/services/devcenter/dev_center_catalogs_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/devcenter/dev_center_catalogs_resource.go b/internal/services/devcenter/dev_center_catalogs_resource.go index 0902542b5ad0..56477c245676 100644 --- a/internal/services/devcenter/dev_center_catalogs_resource.go +++ b/internal/services/devcenter/dev_center_catalogs_resource.go @@ -276,7 +276,7 @@ func CatalogPropertiesSchema() *pluginsdk.Schema { } func expandCatalogProperties(input []CatalogPropertiesModel) *catalogs.GitCatalog { - if input == nil || len(input) == 0 { + if len(input) == 0 { return nil }