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

azurerm_web_pubsub_hub - add event_listener property #21145

Merged
merged 9 commits into from
Apr 5, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
141 changes: 141 additions & 0 deletions internal/services/signalr/web_pubsub_hub_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/webpubsub/2023-02-01/webpubsub"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
eventhubValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/eventhub/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/signalr/migration"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/signalr/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
Expand Down Expand Up @@ -105,6 +106,45 @@ func resourceWebPubSubHub() *pluginsdk.Resource {
},
},

"event_listener": {
Type: pluginsdk.TypeList,
Optional: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"user_event_name_filter": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"system_event_name_filter": {
Type: pluginsdk.TypeSet,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Suggested change
Type: pluginsdk.TypeSet,
Type: pluginsdk.TypeList,

Optional: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
ValidateFunc: validation.StringInSlice([]string{
"connect",
"connected",
"disconnected",
}, false),
},
},

"eventhub_namespace_name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: eventhubValidate.ValidateEventHubNamespaceName(),
},

"eventhub_name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: eventhubValidate.ValidateEventHubName(),
},
xiaxyi marked this conversation as resolved.
Show resolved Hide resolved
},
},
},

"anonymous_connections_enabled": {
Type: pluginsdk.TypeBool,
Optional: true,
Expand Down Expand Up @@ -151,6 +191,13 @@ func resourceWebPubSubHubCreateUpdate(d *pluginsdk.ResourceData, meta interface{
},
}

eventListener, err := expandEventListener(d.Get("event_listener").([]interface{}))
if err != nil {
return fmt.Errorf("expanding event listener for web pubsub %s: %+v", id, err)
}

parameters.Properties.EventListeners = eventListener

if err := client.HubsCreateOrUpdateThenPoll(ctx, id, parameters); err != nil {
return fmt.Errorf("creating/updating %s: %+v", id, err)
}
Expand Down Expand Up @@ -188,6 +235,13 @@ func resourceWebPubSubHubRead(d *pluginsdk.ResourceData, meta interface{}) error
return fmt.Errorf("setting `event_handler`: %+v", err)
}
d.Set("anonymous_connections_enabled", strings.EqualFold(*model.Properties.AnonymousConnectPolicy, "Allow"))
eventListener, err := flattenEventListener(model.Properties.EventListeners)
if err != nil {
return fmt.Errorf("flatten event listener: %+v", err)
}
if err := d.Set("event_listener", eventListener); err != nil {
return fmt.Errorf("setting `event_listener`: %+v", err)
}
}

return nil
Expand Down Expand Up @@ -278,6 +332,93 @@ func flattenEventHandler(input *[]webpubsub.EventHandler) []interface{} {
return eventHandlerBlock
}

func expandEventListener(input []interface{}) (*[]webpubsub.EventListener, error) {
result := make([]webpubsub.EventListener, 0)
if len(input) == 0 {
return &result, nil
}

for _, eventListenerItem := range input {
block := eventListenerItem.(map[string]interface{})

var (
filter webpubsub.EventListenerFilter
endpoint webpubsub.EventListenerEndpoint
eventFilterType webpubsub.EventListenerFilterDiscriminator
endpointFilterType webpubsub.EventListenerEndpointDiscriminator
)

switch eventFilterType {
default:
systemEvents := make([]string, 0)
userEventPattern := "*"
if v, ok := block["user_event_name_filter"]; ok {
userEventPattern = v.(string)
}
if v, ok := block["system_event_name_filter"]; ok {
for _, item := range v.(*pluginsdk.Set).List() {
systemEvents = append(systemEvents, item.(string))
}
}
filter = webpubsub.EventNameFilter{
SystemEvents: &systemEvents,
UserEventPattern: utils.String(userEventPattern),
}
}

var endpointName string
switch endpointFilterType {
default:
endpointName = block["eventhub_namespace_name"].(string)
fullQualifiedName := endpointName + ".servicebus.windows.net"
if _, ok := block["eventhub_name"]; !ok {
return nil, fmt.Errorf("no event hub is specified")
}
ehName := block["eventhub_name"].(string)
endpoint = webpubsub.EventHubEndpoint{
FullyQualifiedNamespace: fullQualifiedName,
EventHubName: ehName,
}
}

result = append(result, webpubsub.EventListener{
Filter: filter,
Endpoint: endpoint,
})
}
return &result, nil
}

func flattenEventListener(listener *[]webpubsub.EventListener) ([]interface{}, error) {
eventListenerBlocks := make([]interface{}, 0)
if listener == nil {
return eventListenerBlocks, nil
}

for _, item := range *listener {
listenerBlock := make(map[string]interface{}, 0)
// todo use the type Assertion or Type field in sdk to get the different sub-class
if eventFilter := item.Filter; eventFilter != nil {
eventNameFilter := item.Filter.(webpubsub.EventNameFilter)
if eventNameFilter.SystemEvents != nil {
listenerBlock["system_event_name_filter"] = utils.FlattenStringSlice(eventNameFilter.SystemEvents)
}
if eventNameFilter.UserEventPattern != nil {
listenerBlock["user_event_name_filter"] = *eventNameFilter.UserEventPattern
}
}

if eventEndpoint := item.Endpoint; eventEndpoint != nil {
eventhubEndpoint := item.Endpoint.(webpubsub.EventHubEndpoint)
listenerBlock["eventhub_namespace_name"] = strings.TrimSuffix(eventhubEndpoint.FullyQualifiedNamespace, ".servicebus.windows.net")
listenerBlock["eventhub_name"] = eventhubEndpoint.EventHubName
}
eventListenerBlocks = append(eventListenerBlocks, listenerBlock)
}

return eventListenerBlocks, nil
}

func expandAuth(input []interface{}) *webpubsub.UpstreamAuthSettings {
if len(input) == 0 || input[0] == nil {
authType := webpubsub.UpstreamAuthTypeNone
Expand Down
80 changes: 79 additions & 1 deletion internal/services/signalr/web_pubsub_hub_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func TestAccWebPubsubHub_withPropertyUpdate(t *testing.T) {
})
}

func TestAccWebPubsubHub_withMultipleEventhandlerSettingsUpdate(t *testing.T) {
func TestAccWebPubsubHub_withMultipleEventHandlerSettingsUpdate(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_web_pubsub_hub", "test")
r := WebPubsubHubResource{}

Expand All @@ -137,6 +137,32 @@ func TestAccWebPubsubHub_withMultipleEventhandlerSettingsUpdate(t *testing.T) {
})
}

func TestAccWebPubsubHub_withMultipleEventListenerSettingsUpdate(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_web_pubsub_hub", "test")
r := WebPubsubHubResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.withMultipleEventListenerSettings(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r)),
},
data.ImportStep(),
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r)),
},
data.ImportStep(),
{
Config: r.withMultipleEventListenerSettings(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r)),
},
data.ImportStep(),
})
}

func (r WebPubsubHubResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := webpubsub.ParseHubID(state.ID)
if err != nil {
Expand Down Expand Up @@ -271,6 +297,54 @@ resource "azurerm_web_pubsub_hub" "test" {
`, r.template(data), data.RandomInteger, data.RandomInteger, data.RandomInteger)
}

func (r WebPubsubHubResource) withMultipleEventListenerSettings(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

resource "azurerm_eventhub_namespace" "test" {
name = "acctesteventhubnamespace-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
sku = "Standard"
}

resource "azurerm_eventhub" "test" {
name = "acctesteventhub-%d"
namespace_name = azurerm_eventhub_namespace.test.name
resource_group_name = azurerm_resource_group.test.name
partition_count = 1
message_retention = 1
}

resource "azurerm_eventhub" "test1" {
name = "acctesteventhub-%d"
namespace_name = azurerm_eventhub_namespace.test.name
resource_group_name = azurerm_resource_group.test.name
partition_count = 1
message_retention = 1
}

resource "azurerm_web_pubsub_hub" "test" {
name = "acctestwpsh%d"
web_pubsub_id = azurerm_web_pubsub.test.id

event_listener {
system_event_name_filter = ["disconnected", "connected"]
user_event_name_filter = "test1"
eventhub_namespace_name = azurerm_eventhub_namespace.test.name
eventhub_name = azurerm_eventhub.test.name
}

event_listener {
system_event_name_filter = ["connected"]
user_event_name_filter = "event1, event2"
eventhub_namespace_name = azurerm_eventhub_namespace.test.name
eventhub_name = azurerm_eventhub.test1.name
}
}
`, r.template(data), data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger)
}

func (r WebPubsubHubResource) withMultipleEventhandlerSettingsAndNoAuth(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
Expand Down Expand Up @@ -342,6 +416,10 @@ resource "azurerm_web_pubsub" "test" {
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
sku = "Standard_S1"

identity {
type = "SystemAssigned"
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}
16 changes: 16 additions & 0 deletions website/docs/r/web_pubsub_hub.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ The following arguments are supported:

-> **NOTE:** User can change the order of `event_handler` to change the priority accordingly.

* `event_listener` - (Optional) An `event_listener` block as defined below.

-> **NOTE:** The managed identity of Web PubSub service must be enabled, and the identity should have the "Azure Event Hubs Data sender" role to access Event Hub.
xiaxyi marked this conversation as resolved.
Show resolved Hide resolved

---

An `event_handler` block supports the following:
Expand All @@ -87,6 +91,18 @@ An `event_handler` block supports the following:

---

An `event_listener` block supports the following:

* `system_event_name_filter` - (Optional) Specify the list of system events. Supported values are `connect`, `connected` and `disconnected`.

* `user_event_name_filter` - (Optional) Specify the matching event names. There are 3 kind of patterns supported: * `*` matches any event name * `,` Combine multiple events with `,` for example `event1,event2`, it matches event `event1` and `event2` * The single event name, for example `event1`, it matches `event1`. Defaults to `"*"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this property be a lint then instead of CSV?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks kt for the review, sorry that I can't quite follow your question, can you be more specific about it? Thanks

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry list. ie as it is * or event1,event2 it could be user_event_name_filter = ["*"] and user_event_name_filter = ['event1","event2"]


* `eventhub_namespace_name` - (Required) Specify the event hub namespace name to receive the events.

* `eventhub_name` - (Required) Specify the event hub name to receive the events.

---

An `auth` block supports the following:

* `managed_identity_id` - (Required) Specify the identity ID of the target resource.
Expand Down