Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions internal/services/signalr/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ func (r Registration) EphemeralResources() []func() ephemeral.EphemeralResource

func (r Registration) ListResources() []sdk.FrameworkListWrappedResource {
return []sdk.FrameworkListWrappedResource{
CustomCertWebPubsubListResource{},
WebPubSubListResource{},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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{
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
},
}
Expand Down Expand Up @@ -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 {
Expand All @@ -166,22 +179,14 @@ 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)

state, err := flattenCustomCertWebPubsubModel(*id, resp.Model)
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),
if err := pluginsdk.SetResourceIdentityData(metadata.ResourceData, id); err != nil {
return err
}

return metadata.Encode(&state)
Expand Down Expand Up @@ -248,3 +253,25 @@ func webPubsubCustomCertificateDeleteRefreshFunc(ctx context.Context, client *we
return res, "Exists", nil
}
}

func flattenCustomCertWebPubsubModel(id webpubsub.CustomCertificateId, model *webpubsub.CustomCertificate) (CustomCertWebPubsubModel, error) {
if model == nil {
return CustomCertWebPubsubModel{}, 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 CustomCertWebPubsubModel{}, err
}

return CustomCertWebPubsubModel{
Name: id.CustomCertificateName,
CustomCertId: nestedItem.ID(),
WebPubsubId: webpubsub.NewWebPubSubID(id.SubscriptionId, id.ResourceGroupName, id.WebPubSubName).ID(),
CertificateVersion: certVersion,
}, nil
}
Original file line number Diff line number Diff line change
@@ -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)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// 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-plugin-sdk/v2/terraform"
"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 {
wrapper := sdk.NewResourceWrapper(CustomCertWebPubsubResource{})
resource, err := wrapper.Resource()
if err != nil {
panic(fmt.Sprintf("building resource schema for `%s`: %+v", webPubsubCustomCertificateResourceType, err))
}

return resource
}

func (r CustomCertWebPubsubListResource) Metadata(_ context.Context, _ resource.MetadataRequest, response *resource.MetadataResponse) {
response.TypeName = webPubsubCustomCertificateResourceType
}

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
}

state, err := flattenCustomCertWebPubsubModel(*id, &cert)
if err != nil {
sdk.SetErrorDiagnosticAndPushListResult(result, push, "flattening Web PubSub Custom Certificate", err)
return
}

rd := r.ResourceFunc().Data(&terraform.InstanceState{})
rd.SetId(id.ID())
if err := pluginsdk.SetResourceIdentityData(rd, id); err != nil {
sdk.SetErrorDiagnosticAndPushListResult(result, push, "setting resource identity data", err)
return
}

if err := rd.Set("name", state.Name); err != nil {
sdk.SetErrorDiagnosticAndPushListResult(result, push, "setting name", err)
return
}
if err := rd.Set("web_pubsub_id", state.WebPubsubId); err != nil {
sdk.SetErrorDiagnosticAndPushListResult(result, push, "setting web_pubsub_id", err)
return
}
if err := rd.Set("custom_certificate_id", state.CustomCertId); err != nil {
sdk.SetErrorDiagnosticAndPushListResult(result, push, "setting custom_certificate_id", err)
return
}
if err := rd.Set("certificate_version", state.CertificateVersion); err != nil {
sdk.SetErrorDiagnosticAndPushListResult(result, push, "setting certificate_version", err)
return
}

sdk.EncodeListResult(ctx, rd, &result)
if result.Diagnostics.HasError() {
push(result)
return
}
if !push(result) {
return
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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
}
}
`
}
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
Expand Down
Loading
Loading