diff --git a/internal/services/signalr/registration.go b/internal/services/signalr/registration.go index 81c99dd9ad4a..ec8488ecc685 100644 --- a/internal/services/signalr/registration.go +++ b/internal/services/signalr/registration.go @@ -89,6 +89,7 @@ func (r Registration) EphemeralResources() []func() ephemeral.EphemeralResource func (r Registration) ListResources() []sdk.FrameworkListWrappedResource { return []sdk.FrameworkListWrappedResource{ + CustomCertWebPubsubListResource{}, SignalRServiceListResource{}, WebPubSubListResource{}, } diff --git a/internal/services/signalr/web_pubsub_custom_certificate_resource.go b/internal/services/signalr/web_pubsub_custom_certificate_resource.go index a7c97a357079..ea68fdd39c22 100644 --- a/internal/services/signalr/web_pubsub_custom_certificate_resource.go +++ b/internal/services/signalr/web_pubsub_custom_certificate_resource.go @@ -3,6 +3,8 @@ package signalr +//go:generate go run ../../tools/generator-tests resourceidentity -resource-name web_pubsub_custom_certificate -service-package-name signalr -properties "name" -compare-values "subscription_id:web_pubsub_id,resource_group_name:web_pubsub_id,web_pub_sub_name:web_pubsub_id" + import ( "context" "fmt" @@ -12,6 +14,7 @@ import ( "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-helpers/resourcemanager/keyvault" + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" "github.com/hashicorp/go-azure-sdk/resource-manager/webpubsub/2024-03-01/webpubsub" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" @@ -26,9 +29,18 @@ type CustomCertWebPubsubModel struct { CertificateVersion string `tfschema:"certificate_version"` } +const webPubsubCustomCertificateResourceType = "azurerm_web_pubsub_custom_certificate" + type CustomCertWebPubsubResource struct{} -var _ sdk.Resource = CustomCertWebPubsubResource{} +var ( + _ sdk.Resource = CustomCertWebPubsubResource{} + _ sdk.ResourceWithIdentity = CustomCertWebPubsubResource{} +) + +func (r CustomCertWebPubsubResource) Identity() resourceids.ResourceId { + return &webpubsub.CustomCertificateId{} +} func (r CustomCertWebPubsubResource) Arguments() map[string]*pluginsdk.Schema { return map[string]*pluginsdk.Schema{ @@ -69,7 +81,7 @@ func (r CustomCertWebPubsubResource) ModelObject() interface{} { } func (r CustomCertWebPubsubResource) ResourceType() string { - return "azurerm_web_pubsub_custom_certificate" + return webPubsubCustomCertificateResourceType } func (r CustomCertWebPubsubResource) Create() sdk.ResourceFunc { @@ -124,6 +136,9 @@ func (r CustomCertWebPubsubResource) Create() sdk.ResourceFunc { } metadata.SetID(id) + if err := pluginsdk.SetResourceIdentityData(metadata.ResourceData, &id); err != nil { + return err + } return nil }, } @@ -153,8 +168,6 @@ func (r CustomCertWebPubsubResource) Read() sdk.ResourceFunc { } vaultBasedUri := resp.Model.Properties.KeyVaultBaseUri - certName := resp.Model.Properties.KeyVaultSecretName - subscriptionResourceId := commonids.NewSubscriptionID(id.SubscriptionId) keyVaultIdRaw, err := keyVaultClient.KeyVaultIDFromBaseUrl(ctx, subscriptionResourceId, vaultBasedUri) if err != nil { @@ -166,25 +179,8 @@ func (r CustomCertWebPubsubResource) Read() sdk.ResourceFunc { return fmt.Errorf("parsing key vault %s: %+v", vaultId, err) } } - certVersion := "" - if resp.Model.Properties.KeyVaultSecretVersion != nil { - certVersion = *resp.Model.Properties.KeyVaultSecretVersion - } - nestedItem, err := keyvault.NewNestedItemID(vaultBasedUri, keyvault.NestedItemTypeCertificate, certName, certVersion) - if err != nil { - return err - } - - certId := nestedItem.ID() - state := CustomCertWebPubsubModel{ - Name: id.CustomCertificateName, - CustomCertId: certId, - WebPubsubId: webpubsub.NewWebPubSubID(id.SubscriptionId, id.ResourceGroupName, id.WebPubSubName).ID(), - CertificateVersion: pointer.From(resp.Model.Properties.KeyVaultSecretVersion), - } - - return metadata.Encode(&state) + return r.flatten(metadata, id, resp.Model) }, } } @@ -248,3 +244,30 @@ func webPubsubCustomCertificateDeleteRefreshFunc(ctx context.Context, client *we return res, "Exists", nil } } + +func (r CustomCertWebPubsubResource) flatten(metadata sdk.ResourceMetaData, id *webpubsub.CustomCertificateId, model *webpubsub.CustomCertificate) error { + if model == nil { + return fmt.Errorf("retrieving %s: got nil model", *id) + } + + vaultBasedUri := model.Properties.KeyVaultBaseUri + certName := model.Properties.KeyVaultSecretName + certVersion := pointer.From(model.Properties.KeyVaultSecretVersion) + nestedItem, err := keyvault.NewNestedItemID(vaultBasedUri, keyvault.NestedItemTypeCertificate, certName, certVersion) + if err != nil { + return err + } + + state := CustomCertWebPubsubModel{ + Name: id.CustomCertificateName, + CustomCertId: nestedItem.ID(), + WebPubsubId: webpubsub.NewWebPubSubID(id.SubscriptionId, id.ResourceGroupName, id.WebPubSubName).ID(), + CertificateVersion: certVersion, + } + + if err := pluginsdk.SetResourceIdentityData(metadata.ResourceData, id); err != nil { + return err + } + + return metadata.Encode(&state) +} diff --git a/internal/services/signalr/web_pubsub_custom_certificate_resource_identity_gen_test.go b/internal/services/signalr/web_pubsub_custom_certificate_resource_identity_gen_test.go new file mode 100644 index 000000000000..c4e13519f172 --- /dev/null +++ b/internal/services/signalr/web_pubsub_custom_certificate_resource_identity_gen_test.go @@ -0,0 +1,40 @@ +// Copyright IBM Corp. 2014, 2025 +// SPDX-License-Identifier: MPL-2.0 + +package signalr_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + customstatecheck "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/statecheck" +) + +func TestAccWebPubsubCustomCertificate_resourceIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_web_pubsub_custom_certificate", "test") + r := WebPubsubCustomCertificateResource{} + + checkedFields := map[string]struct{}{ + "name": {}, + "resource_group_name": {}, + "subscription_id": {}, + "web_pub_sub_name": {}, + } + + data.ResourceIdentityTest(t, []acceptance.TestStep{ + { + Config: r.basic(data), + ConfigStateChecks: []statecheck.StateCheck{ + customstatecheck.ExpectAllIdentityFieldsAreChecked("azurerm_web_pubsub_custom_certificate.test", checkedFields), + statecheck.ExpectIdentityValueMatchesStateAtPath("azurerm_web_pubsub_custom_certificate.test", tfjsonpath.New("name"), tfjsonpath.New("name")), + customstatecheck.ExpectStateContainsIdentityValueAtPath("azurerm_web_pubsub_custom_certificate.test", tfjsonpath.New("resource_group_name"), tfjsonpath.New("web_pubsub_id")), + customstatecheck.ExpectStateContainsIdentityValueAtPath("azurerm_web_pubsub_custom_certificate.test", tfjsonpath.New("subscription_id"), tfjsonpath.New("web_pubsub_id")), + customstatecheck.ExpectStateContainsIdentityValueAtPath("azurerm_web_pubsub_custom_certificate.test", tfjsonpath.New("web_pub_sub_name"), tfjsonpath.New("web_pubsub_id")), + }, + }, + data.ImportBlockWithResourceIdentityStep(false), + data.ImportBlockWithIDStep(false), + }, false) +} diff --git a/internal/services/signalr/web_pubsub_custom_certificate_resource_list.go b/internal/services/signalr/web_pubsub_custom_certificate_resource_list.go new file mode 100644 index 000000000000..dc3db274a516 --- /dev/null +++ b/internal/services/signalr/web_pubsub_custom_certificate_resource_list.go @@ -0,0 +1,104 @@ +// Copyright IBM Corp. 2014, 2025 +// SPDX-License-Identifier: MPL-2.0 + +package signalr + +import ( + "context" + "fmt" + + "github.com/hashicorp/go-azure-helpers/framework/typehelpers" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-sdk/resource-manager/webpubsub/2024-03-01/webpubsub" + "github.com/hashicorp/terraform-plugin-framework/list" + "github.com/hashicorp/terraform-plugin-framework/list/schema" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" +) + +type ( + CustomCertWebPubsubListResource struct{} + CustomCertWebPubsubListModel struct { + WebPubsubId types.String `tfsdk:"web_pubsub_id"` + } +) + +var _ sdk.FrameworkListWrappedResource = new(CustomCertWebPubsubListResource) + +func (r CustomCertWebPubsubListResource) ResourceFunc() *pluginsdk.Resource { + return sdk.WrappedResource(CustomCertWebPubsubResource{}) +} + +func (r CustomCertWebPubsubListResource) Metadata(_ context.Context, _ resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = CustomCertWebPubsubResource{}.ResourceType() +} + +func (r CustomCertWebPubsubListResource) ListResourceConfigSchema(_ context.Context, _ list.ListResourceSchemaRequest, response *list.ListResourceSchemaResponse) { + response.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "web_pubsub_id": schema.StringAttribute{ + Required: true, + Validators: []validator.String{ + typehelpers.WrappedStringValidator{Func: webpubsub.ValidateWebPubSubID}, + }, + }, + }, + } +} + +func (r CustomCertWebPubsubListResource) List(ctx context.Context, request list.ListRequest, stream *list.ListResultsStream, metadata sdk.ResourceMetadata) { + client := metadata.Client.SignalR.WebPubSubClient.WebPubSub + + var data CustomCertWebPubsubListModel + diags := request.Config.Get(ctx, &data) + if diags.HasError() { + stream.Results = list.ListResultsStreamDiagnostics(diags) + return + } + + webPubsubId, err := webpubsub.ParseWebPubSubID(data.WebPubsubId.ValueString()) + if err != nil { + sdk.SetResponseErrorDiagnostic(stream, fmt.Sprintf("parsing Web PubSub ID for `%s`", webPubsubCustomCertificateResourceType), err) + return + } + + resp, err := client.CustomCertificatesListComplete(ctx, *webPubsubId) + if err != nil { + sdk.SetResponseErrorDiagnostic(stream, fmt.Sprintf("listing `%s`", webPubsubCustomCertificateResourceType), err) + return + } + + stream.Results = func(push func(list.ListResult) bool) { + for _, cert := range resp.Items { + result := request.NewListResult(ctx) + result.DisplayName = pointer.From(cert.Name) + + id, err := webpubsub.ParseCustomCertificateIDInsensitively(pointer.From(cert.Id)) + if err != nil { + sdk.SetErrorDiagnosticAndPushListResult(result, push, "parsing Web PubSub Custom Certificate ID", err) + return + } + + r := CustomCertWebPubsubResource{} + rmd := sdk.NewResourceMetaData(metadata.Client, r) + rmd.ResourceData.SetId(id.ID()) + + if err := r.flatten(rmd, id, &cert); err != nil { + sdk.SetErrorDiagnosticAndPushListResult(result, push, fmt.Sprintf("encoding `%s` resource data", r.ResourceType()), err) + return + } + + sdk.EncodeListResult(ctx, rmd.ResourceData, &result) + if result.Diagnostics.HasError() { + push(result) + return + } + if !push(result) { + return + } + } + } +} diff --git a/internal/services/signalr/web_pubsub_custom_certificate_resource_list_test.go b/internal/services/signalr/web_pubsub_custom_certificate_resource_list_test.go new file mode 100644 index 000000000000..e4b9f2738a2a --- /dev/null +++ b/internal/services/signalr/web_pubsub_custom_certificate_resource_list_test.go @@ -0,0 +1,59 @@ +package signalr_test + +import ( + "context" + "regexp" + "strconv" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/querycheck" + "github.com/hashicorp/terraform-plugin-testing/tfversion" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/provider/framework" +) + +func TestAccCustomCertWebPubsub_listByWebPubSubID(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_web_pubsub_custom_certificate", "testlist") + r := CustomCertWebPubsubResource{} + + resource.Test(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_14_0), + }, + ProtoV5ProviderFactories: framework.ProtoV5ProviderFactoriesInit(context.Background(), "azurerm"), + Steps: []resource.TestStep{ + { + Config: r.basic(data), + }, + { + Query: true, + Config: r.basicListQuery(), + QueryResultChecks: []querycheck.QueryResultCheck{ + querycheck.ExpectLengthAtLeast("azurerm_web_pubsub_custom_certificate.list", 1), + querycheck.ExpectIdentity( + "azurerm_web_pubsub_custom_certificate.list", + map[string]knownvalue.Check{ + "name": knownvalue.StringRegexp(regexp.MustCompile(data.RandomString)), + "web_pub_sub_name": knownvalue.StringRegexp(regexp.MustCompile(strconv.Itoa(data.RandomInteger))), + "resource_group_name": knownvalue.StringRegexp(regexp.MustCompile(strconv.Itoa(data.RandomInteger))), + "subscription_id": knownvalue.StringExact(data.Subscriptions.Primary), + }, + ), + }, + }, + }, + }) +} + +func (r CustomCertWebPubsubResource) basicListQuery() string { + return ` +list "azurerm_web_pubsub_custom_certificate" "list" { + provider = azurerm + config { + web_pubsub_id = azurerm_web_pubsub.test.id + } +} +` +} diff --git a/internal/services/signalr/web_pubsub_custom_certificate_resource_test.go b/internal/services/signalr/web_pubsub_custom_certificate_resource_test.go index 2fc06f514d88..a9b8b01b133c 100644 --- a/internal/services/signalr/web_pubsub_custom_certificate_resource_test.go +++ b/internal/services/signalr/web_pubsub_custom_certificate_resource_test.go @@ -19,6 +19,9 @@ import ( type CustomCertWebPubsubResource struct{} +// Alias retained for generated identity test naming. +type WebPubsubCustomCertificateResource = CustomCertWebPubsubResource + func TestAccCustomCertWebPubsub_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_web_pubsub_custom_certificate", "test") r := CustomCertWebPubsubResource{} diff --git a/website/docs/list-resources/web_pubsub_custom_certificate.html.markdown b/website/docs/list-resources/web_pubsub_custom_certificate.html.markdown new file mode 100644 index 000000000000..6a98479e279f --- /dev/null +++ b/website/docs/list-resources/web_pubsub_custom_certificate.html.markdown @@ -0,0 +1,30 @@ +--- +subcategory: "Messaging" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_web_pubsub_custom_certificate" +description: |- + Lists Web PubSub Custom Certificate resources. +--- + +# List resource: azurerm_web_pubsub_custom_certificate + +Lists Web PubSub Custom Certificate resources. + +## Example Usage + +### List Web PubSub Custom Certificates in a Web PubSub service + +```hcl +list "azurerm_web_pubsub_custom_certificate" "example" { + provider = azurerm + config { + web_pubsub_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myresourcegroup/providers/Microsoft.SignalRService/webPubSub/mywps" + } +} +``` + +## Argument Reference + +This list resource supports the following arguments: + +* `web_pubsub_id` - (Required) The ID of the Web PubSub service to query.