From 1cd93813e79e2174c23daa4f7100e9532a33ac92 Mon Sep 17 00:00:00 2001 From: helayoty Date: Mon, 25 Jan 2021 18:15:01 -0800 Subject: [PATCH 01/12] Add servicebus terratest module --- .../README.md | 31 ++ .../main.tf | 160 +++++++ .../outputs.tf | 62 +++ .../variables.tf | 82 ++++ modules/azure/servicebus.go | 410 ++++++++++++++++++ 5 files changed, 745 insertions(+) create mode 100644 examples/azure/terraform-azure-servicebus-example/README.md create mode 100644 examples/azure/terraform-azure-servicebus-example/main.tf create mode 100644 examples/azure/terraform-azure-servicebus-example/outputs.tf create mode 100644 examples/azure/terraform-azure-servicebus-example/variables.tf create mode 100644 modules/azure/servicebus.go diff --git a/examples/azure/terraform-azure-servicebus-example/README.md b/examples/azure/terraform-azure-servicebus-example/README.md new file mode 100644 index 000000000..64ecad686 --- /dev/null +++ b/examples/azure/terraform-azure-servicebus-example/README.md @@ -0,0 +1,31 @@ +# Terraform Azure Service Bus Example + +This folder contains a Terraform module that deploys resources in [Azure](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys a Service Bus. + +- A [Service Bus](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview) with the namespace specified in the `namespace_name` variable. + +Check out [test/azure/terraform_azure_servicebus_example_test.go](./../../../test/azure/terraform_azure_servicebus_example_test.go) to see how you can write automated tests for this module and validate the configuration of the parameters and options. + +**WARNING**: This module and the automated tests for it deploy real resources into your Azure account which can cost you money. The resources are all part of the [Azure Free Account](https://azure.microsoft.com/en-us/free/), so if you haven't used that up, +it should be free, but you are completely responsible for all Azure charges. + +## Running this module manually +1. Sign up for [Azure](https://azure.microsoft.com/). +1. Configure your Azure credentials using one of the [supported methods for Azure CLI + tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest) +1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`. +1. Ensure [environment variables](../README.md#review-environment-variables) are available +1. Run `terraform init` +1. Run `terraform apply` +1. When you're done, run `terraform destroy`. + + +## Running automated tests against this module +1. Sign up for [Azure](https://azure.microsoft.com/) +1. Configure your Azure credentials using one of the [supported methods for Azure CLI + tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest) +1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH` +1. Configure your Terratest [Go test environment](../README.md) +1. `cd test/azure` +1. `go build terraform_azure_servicebus_example_test.go` +1. `go test -v -run TestTerraformAzureServiceBusExample` diff --git a/examples/azure/terraform-azure-servicebus-example/main.tf b/examples/azure/terraform-azure-servicebus-example/main.tf new file mode 100644 index 000000000..f06b59167 --- /dev/null +++ b/examples/azure/terraform-azure-servicebus-example/main.tf @@ -0,0 +1,160 @@ +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AN AZURE SERVICE BUS +# This is an example of how to deploy an Azure service bus. +# See test/terraform_azure_example_test.go for how to write automated tests for this code. +# --------------------------------------------------------------------------------------------------------------------- + + +# --------------------------------------------------------------------------------------------------------------------- +# CONFIGURE OUR AZURE CONNECTION +# --------------------------------------------------------------------------------------------------------------------- + +provider "azurerm" { + version = "~>2.29" + features {} +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY A RESOURCE GROUP +# --------------------------------------------------------------------------------------------------------------------- + +resource "azurerm_resource_group" "seervicebus" { + name = "terratest-rg-${var.postfix}" + location = var.location +} + + +# --------------------------------------------------------------------------------------------------------------------- +# DDefine locals variables +# --------------------------------------------------------------------------------------------------------------------- +locals { + topic_authorization_rules = flatten([ + for topic in var.topics : [ + for rule in topic.authorization_rules : + merge( + rule, { + topic_name = topic.name + }) + ] + ]) + + topic_subscriptions = flatten([ + for topic in var.topics : [ + for subscription in topic.subscriptions : + merge( + subscription, { + topic_name = topic.name + }) + ] + ]) + + topic_subscription_rules = flatten([ + for subscription in local.topic_subscriptions : + merge({ + filter_type = "" + sql_filter = "" + action = "" + }, subscription, { + topic_name = subscription.topic_name + subscription_name = subscription.name + }) + if subscription.filter_type != null + ]) +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AZURE Service Bus Namespace +# --------------------------------------------------------------------------------------------------------------------- +resource "azurerm_servicebus_namespace" "servicebus" { + name = var.namespace_name + location = azurerm_resource_group.servicebus.location + resource_group_name = azurerm_resource_group.servicebus.name + sku = var.sku + tags = var.tags +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AZURE Service Bus Namespace Authorization Rule +# --------------------------------------------------------------------------------------------------------------------- +resource "azurerm_servicebus_namespace_authorization_rule" "sbnamespaceauth" { + count = length(var.namespace_authorization_rules) + + name = var.namespace_authorization_rules[count.index].policy_name + namespace_name = azurerm_servicebus_namespace.servicebus.name + resource_group_name = azurerm_resource_group.servicebus.name + + listen = var.namespace_authorization_rules[count.index].claims.listen + send = var.namespace_authorization_rules[count.index].claims.send + manage = var.namespace_authorization_rules[count.index].claims.manage +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AZURE Service Bus Topic +# --------------------------------------------------------------------------------------------------------------------- +resource "azurerm_servicebus_topic" "sptopic" { + count = length(var.topics) + + name = var.topics[count.index].name + resource_group_name = azurerm_resource_group.servicebus.name + namespace_name = azurerm_servicebus_namespace.servicebus.name + + requires_duplicate_detection = var.topics[count.index].requires_duplicate_detection + default_message_ttl = var.topics[count.index].default_message_ttl + enable_partitioning = var.topics[count.index].enable_partitioning + support_ordering = var.topics[count.index].support_ordering +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AZURE Service Bus Topic Authorization Rule +# --------------------------------------------------------------------------------------------------------------------- +resource "azurerm_servicebus_topic_authorization_rule" "topicaauth" { + count = length(local.topic_authorization_rules) + + name = local.topic_authorization_rules[count.index].policy_name + resource_group_name = azurerm_resource_group.servicebus.name + namespace_name = azurerm_servicebus_namespace.servicebus.name + topic_name = local.topic_authorization_rules[count.index].topic_name + + listen = local.topic_authorization_rules[count.index].claims.listen + send = local.topic_authorization_rules[count.index].claims.send + manage = local.topic_authorization_rules[count.index].claims.manage + + depends_on = [azurerm_servicebus_topic.sptopic] +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AZURE Service Bus Subscription +# --------------------------------------------------------------------------------------------------------------------- +resource "azurerm_servicebus_subscription" "subscription" { + count = length(local.topic_subscriptions) + + name = local.topic_subscriptions[count.index].name + resource_group_name = azurerm_resource_group.servicebus.name + namespace_name = azurerm_servicebus_namespace.servicebus.name + topic_name = local.topic_subscriptions[count.index].topic_name + + max_delivery_count = local.topic_subscriptions[count.index].max_delivery_count + lock_duration = local.topic_subscriptions[count.index].lock_duration + forward_to = local.topic_subscriptions[count.index].forward_to + dead_lettering_on_message_expiration = local.topic_subscriptions[count.index].dead_lettering_on_message_expiration + + depends_on = [azurerm_servicebus_topic.sptopic] +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AZURE Service Bus Subscription Rules +# --------------------------------------------------------------------------------------------------------------------- +resource "azurerm_servicebus_subscription_rule" "subrules" { + count = length(local.topic_subscription_rules) + + name = local.topic_subscription_rules[count.index].name + resource_group_name = azurerm_resource_group.servicebus.name + namespace_name = azurerm_servicebus_namespace.servicebus.name + topic_name = local.topic_subscription_rules[count.index].topic_name + subscription_name = local.topic_subscription_rules[count.index].subscription_name + filter_type = local.topic_subscription_rules[count.index].filter_type != "" ? "SqlFilter" : null + sql_filter = local.topic_subscription_rules[count.index].sql_filter + action = local.topic_subscription_rules[count.index].action + + depends_on = [azurerm_servicebus_subscription.subscription] +} \ No newline at end of file diff --git a/examples/azure/terraform-azure-servicebus-example/outputs.tf b/examples/azure/terraform-azure-servicebus-example/outputs.tf new file mode 100644 index 000000000..6acb94e66 --- /dev/null +++ b/examples/azure/terraform-azure-servicebus-example/outputs.tf @@ -0,0 +1,62 @@ +output "namespace_name" { + description = "The namespace name." + value = azurerm_servicebus_namespace.servicebus.name +} + +output "resource_group" { + description = "The resource group name of the Service Bus namespace." + value = data.azurerm_resource_group.resourcegroup.name +} + +output "namespace_id" { + description = "The namespace ID." + value = azurerm_servicebus_namespace.servicebus.id +} + +output "namespace_authorization_rules" { + description = "List of namespace authorization rules." + value = { + for auth in azurerm_servicebus_namespace_authorization_rule.sbnamespaceauth : + auth.name => { + listen = auth.listen + send = auth.send + manage = auth.manage + } + } +} + +output "service_bus_namespace_default_primary_key" { + description = "The primary access key for the authorization rule RootManageSharedAccessKey which is created automatically by Azure." + value = azurerm_servicebus_namespace.servicebus.default_primary_key +} + +output "service_bus_namespace_default_connection_string" { + description = "The primary connection string for the authorization rule RootManageSharedAccessKey which is created automatically by Azure." + value = azurerm_servicebus_namespace.servicebus.default_primary_connection_string +} + + +output "topics" { + value = { + for topic in azurerm_servicebus_topic.sptopic : + topic.name => { + id = topic.id + name = topic.name + authorization_rules = { + for auth in azurerm_servicebus_topic_authorization_rule.topicaauth : + auth.name => { + listen = auth.listen + send = auth.send + manage = auth.manage + } if topic.name == auth.topic_name + } + subscriptions = { + for subscription in azurerm_servicebus_subscription.subscription : + subscription.name => { + name = subscription.name + } if topic.name == subscription.topic_name + } + } + } + description = "All topics with the corresponding subscriptions" +} diff --git a/examples/azure/terraform-azure-servicebus-example/variables.tf b/examples/azure/terraform-azure-servicebus-example/variables.tf new file mode 100644 index 000000000..64f7bab6c --- /dev/null +++ b/examples/azure/terraform-azure-servicebus-example/variables.tf @@ -0,0 +1,82 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables +# --------------------------------------------------------------------------------------------------------------------- + +# ARM_CLIENT_ID +# ARM_CLIENT_SECRET +# ARM_SUBSCRIPTION_ID +# ARM_TENANT_ID + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED PARAMETERS +# You must provide a value for each of these parameters. +# --------------------------------------------------------------------------------------------------------------------- + +variable "namespace_name" { + description = "The name of the namespace." + type = string +} + +variable "postfix" { + description = "The name of the resource group for the provisioned service bus." + type = string +} + +variable "namespace_authorization_rules" { + description = "List of namespace authorization rules." + type = list(object({ + policy_name = string + claims = object({ listen = bool, manage = bool, send = bool }) + })) + default = [] +} + +variable "topics" { + description = "topics list" + type = list(object({ + name = string + default_message_ttl = string //ISO 8601 format + enable_partitioning = bool + requires_duplicate_detection = bool + support_ordering = bool + authorization_rules = list(object({ + policy_name = string + claims = object({ listen = bool, manage = bool, send = bool }) + + })) + subscriptions = list(object({ + name = string + max_delivery_count = number + lock_duration = string //ISO 8601 format + forward_to = string //set with the topic name that will be used for forwarding. Otherwise, set to "" + dead_lettering_on_message_expiration = bool + filter_type = string // SqlFilter is the only supported type now. + sql_filter = string //Required when filter_type is set to SqlFilter + action = string + })) + })) +} + +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL PARAMETERS +# These parameters have reasonable defaults. +# --------------------------------------------------------------------------------------------------------------------- + +variable "location" { + description = "The supported azure location where the resource exists" + type = string + default = "West US2" +} + +variable "sku" { + description = "The SKU of the namespace. The options are: `Basic`, `Standard`, `Premium`." + type = string + default = "Standard" +} + +variable "tags" { + description = " A mapping of tags to assign to the resource." + type = map(string) + default = {} +} diff --git a/modules/azure/servicebus.go b/modules/azure/servicebus.go new file mode 100644 index 000000000..7ea760539 --- /dev/null +++ b/modules/azure/servicebus.go @@ -0,0 +1,410 @@ +package azure + +import ( + "context" + "testing" + + "github.com/Azure/azure-sdk-for-go/services/servicebus/mgmt/2017-04-01/servicebus" +) + +func serviceBusClientE(subscriptionID string) (*servicebus.BaseClient, error) { + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + + client := servicebus.New(subscriptionID) + client.Authorizer = *authorizer + return &client, nil +} + +func serviceBusNamespaceClientE(subscriptionID string) (*servicebus.NamespacesClient, error) { + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + + nsClient := servicebus.NewNamespacesClient(subscriptionID) + nsClient.Authorizer = *authorizer + return &nsClient, nil +} + +func serviceBusTopicClientE(subscriptionID string) (*servicebus.TopicsClient, error) { + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + + tClient := servicebus.NewTopicsClient(subscriptionID) + tClient.Authorizer = *authorizer + return &tClient, nil +} + +func serviceBusSubscriptionsClientE(subscriptionID string) (*servicebus.SubscriptionsClient, error) { + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + + sClient := servicebus.NewSubscriptionsClient(subscriptionID) + sClient.Authorizer = *authorizer + return &sClient, nil +} + +// ListServiceBusNamespaceE list all SB namespaces in all resource groups in the given subscription ID +func ListServiceBusNamespaceE(subscriptionID string) (*[]servicebus.SBNamespace, error) { + nsClient, err := serviceBusNamespaceClientE(subscriptionID) + if err != nil { + return nil, err + } + + iteratorSBNamespace, err := nsClient.ListComplete(context.Background()) + if err != nil { + return nil, err + } + + results := make([]servicebus.SBNamespace, 0) + for iteratorSBNamespace.NotDone() { + results = append(results, iteratorSBNamespace.Value()) + err = iteratorSBNamespace.Next() + if err != nil { + return nil, err + } + } + + return &results, nil +} + +// ListServiceBusNamespace - like ListServiceBusNamespaceE but fails in the case an error is returned +func ListServiceBusNamespace(t *testing.T, subscriptionID string) *[]servicebus.SBNamespace { + results, err := ListServiceBusNamespaceE(subscriptionID) + if err != nil { + t.Fatal(err) + } + + return results +} + +// ListServiceBusNamespaceNamesE list names of all SB namespaces in all resource groups in the given subscription ID +func ListServiceBusNamespaceNamesE(subscriptionID string) (*[]string, error) { + sbNamespace, err := ListServiceBusNamespaceE(subscriptionID) + + if err != nil { + return nil, err + } + + results := make([]string, 0) + for _, namespace := range *sbNamespace { + results = append(results, *namespace.Name) + if err != nil { + return nil, err + } + } + + return &results, nil +} + +// ListServiceBusNamespaceNames like ListServiceBusNamespaceNamesE but fails in the case an error is returned +func ListServiceBusNamespaceNames(t *testing.T, subscriptionID string) *[]string { + results, err := ListServiceBusNamespaceNamesE(subscriptionID) + if err != nil { + t.Fatal(err) + } + + return results +} + +// ListServiceBusNamespaceIDsE list IDs of all SB namespaces in all resource groups in the given subscription ID +func ListServiceBusNamespaceIDsE(subscriptionID string) (*[]string, error) { + sbNamespace, err := ListServiceBusNamespaceE(subscriptionID) + + if err != nil { + return nil, err + } + + results := make([]string, 0) + for _, namespace := range *sbNamespace { + results = append(results, *namespace.ID) + if err != nil { + return nil, err + } + } + + return &results, nil +} + +// ListServiceBusNamespaceIDs like ListServiceBusNamespaceIDsE but fails in the case an error is returned +func ListServiceBusNamespaceIDs(t *testing.T, subscriptionID string) *[]string { + results, err := ListServiceBusNamespaceIDsE(subscriptionID) + if err != nil { + t.Fatal(err) + } + + return results +} + +// ListServiceBusNamespaceByResourceGroupE list all SB namespaces in the given resource group +func ListServiceBusNamespaceByResourceGroupE(subscriptionID string, resourceGroup string) (*[]servicebus.SBNamespace, error) { + nsClient, err := serviceBusNamespaceClientE(subscriptionID) + if err != nil { + return nil, err + } + + iteratorSBNamespace, err := nsClient.ListByResourceGroupComplete(context.Background(), resourceGroup) + if err != nil { + return nil, err + } + + results := make([]servicebus.SBNamespace, 0) + + for iteratorSBNamespace.NotDone() { + results = append(results, iteratorSBNamespace.Value()) + err = iteratorSBNamespace.Next() + if err != nil { + return nil, err + } + } + + return &results, nil +} + +// ListServiceBusNamespaceByResourceGroup like ListServiceBusNamespaceByResourceGroupE but fails in the case an error is returned +func ListServiceBusNamespaceByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) *[]servicebus.SBNamespace { + results, err := ListServiceBusNamespaceByResourceGroupE(subscriptionID, resourceGroup) + if err != nil { + t.Fatal(err) + } + + return results +} + +// ListServiceBusNamespaceNamesByResourceGroupE list names of all SB namespaces in the given resource group +func ListServiceBusNamespaceNamesByResourceGroupE(subscriptionID string, resourceGroup string) (*[]string, error) { + sbNamespace, err := ListServiceBusNamespaceByResourceGroupE(subscriptionID, resourceGroup) + + if err != nil { + return nil, err + } + + results := make([]string, 0) + for _, namespace := range *sbNamespace { + results = append(results, *namespace.Name) + if err != nil { + return nil, err + } + } + + return &results, nil +} + +// ListServiceBusNamespaceNamesByResourceGroup like ListServiceBusNamespaceNamesByResourceGroupE but fails in the case an error is returned +func ListServiceBusNamespaceNamesByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) *[]string { + results, err := ListServiceBusNamespaceNamesByResourceGroupE(subscriptionID, resourceGroup) + if err != nil { + t.Fatal(err) + } + + return results +} + +// ListServiceBusNamespaceIDsByResourceGroupE list IDs of all SB namespaces in the given resource group +func ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID string, resourceGroup string) (*[]string, error) { + sbNamespace, err := ListServiceBusNamespaceByResourceGroupE(subscriptionID, resourceGroup) + + if err != nil { + return nil, err + } + + results := make([]string, 0) + for _, namespace := range *sbNamespace { + results = append(results, *namespace.ID) + if err != nil { + return nil, err + } + } + + return &results, nil +} + +// ListServiceBusNamespaceIDsByResourceGroup like ListServiceBusNamespaceIDsByResourceGroupE but fails in the case an error is returned +func ListServiceBusNamespaceIDsByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) *[]string { + results, err := ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID, resourceGroup) + if err != nil { + t.Fatal(err) + } + + return results +} + +// ListNamespaceAuthRulesE - authenticate namespace client and enumerates all values to get list of authorization rules for the given namespace name, +// automatically crossing page boundaries as required. +func ListNamespaceAuthRulesE(subscriptionID string, namespace string, resourceGroup string) (*[]string, error) { + nsClient, err := serviceBusNamespaceClientE(subscriptionID) + if err != nil { + return nil, err + } + iteratorNamespaceRules, err := nsClient.ListAuthorizationRulesComplete( + context.Background(), resourceGroup, namespace) + + if err != nil { + return nil, err + } + + results := make([]string, 0) + for iteratorNamespaceRules.NotDone() { + results = append(results, *(iteratorNamespaceRules.Value()).Name) + err = iteratorNamespaceRules.Next() + if err != nil { + return nil, err + } + } + return &results, nil +} + +// ListNamespaceAuthRules - like ListNamespaceAuthRulesE but fails in the case an error is returned +func ListNamespaceAuthRules(t *testing.T, subscriptionID string, namespace string, resourceGroup string) *[]string { + results, err := ListNamespaceAuthRulesE(subscriptionID, namespace, resourceGroup) + if err != nil { + t.Fatal(err) + } + + return results +} + +// ListNamespaceTopicsE - authenticate topic client and enumerates all values, automatically crossing page boundaries as required. +func ListNamespaceTopicsE(subscriptionID string, namespace string, resourceGroup string) (*[]servicebus.SBTopic, error) { + tClient, err := serviceBusTopicClientE(subscriptionID) + if err != nil { + return nil, err + } + + iteratorTopics, err := tClient.ListByNamespaceComplete(context.Background(), resourceGroup, namespace, nil, nil) + if err != nil { + return nil, err + } + + results := make([]servicebus.SBTopic, 0) + + for iteratorTopics.NotDone() { + results = append(results, iteratorTopics.Value()) + err = iteratorTopics.Next() + if err != nil { + return nil, err + } + } + + return &results, nil +} + +// ListNamespaceTopics - like ListNamespaceTopicsE but fails in the case an error is returned +func ListNamespaceTopics(t *testing.T, subscriptionID string, namespace string, resourceGroup string) *[]servicebus.SBTopic { + results, err := ListNamespaceTopicsE(subscriptionID, namespace, resourceGroup) + if err != nil { + t.Fatal(err) + } + + return results +} + +// ListTopicSubscriptionsE - authenticate subscriptions client and enumerates all values, automatically crossing page boundaries as required. +func ListTopicSubscriptionsE(subscriptionID string, namespace string, resourceGroup string, topicName string) ([]servicebus.SBSubscription, error) { + sClient, err := serviceBusSubscriptionsClientE(subscriptionID) + if err != nil { + return nil, err + } + iteratorSubscription, err := sClient.ListByTopicComplete(context.Background(), resourceGroup, namespace, topicName, nil, nil) + + if err != nil { + return nil, err + } + + results := make([]servicebus.SBSubscription, 0) + + for iteratorSubscription.NotDone() { + results = append(results, iteratorSubscription.Value()) + err = iteratorSubscription.Next() + if err != nil { + return nil, err + } + } + return results, nil +} + +// ListTopicSubscriptions - like ListTopicSubscriptionsE but fails in the case an error is returned +func ListTopicSubscriptions(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) *[]servicebus.SBSubscription { + results, err := ListTopicSubscriptionsE(subscriptionID, namespace, resourceGroup, topicName) + if err != nil { + t.Fatal(err) + } + + return &results +} + +// ListTopicSubscriptionsNameE - authenticate subscriptions client and enumerates all values to get list of subscriptions for the given topic name, +// automatically crossing page boundaries as required. +func ListTopicSubscriptionsNameE(subscriptionID string, namespace string, resourceGroup string, topicName string) (*[]string, error) { + sClient, err := serviceBusSubscriptionsClientE(subscriptionID) + if err != nil { + return nil, err + } + iteratorSubscription, err := sClient.ListByTopicComplete(context.Background(), resourceGroup, namespace, topicName, nil, nil) + + if err != nil { + return nil, err + } + + results := make([]string, 0) + for iteratorSubscription.NotDone() { + results = append(results, *(iteratorSubscription.Value()).Name) + err = iteratorSubscription.Next() + if err != nil { + return nil, err + } + } + return &results, nil +} + +// ListTopicSubscriptionsName - like ListTopicSubscriptionsNameE but fails in the case an error is returned +func ListTopicSubscriptionsName(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) *[]string { + results, err := ListTopicSubscriptionsNameE(subscriptionID, namespace, resourceGroup, topicName) + if err != nil { + t.Fatal(err) + } + + return results +} + +// ListTopicAuthRulesE - authenticate topic client and enumerates all values to get list of authorization rules for the given topic name, +// automatically crossing page boundaries as required. +func ListTopicAuthRulesE(subscriptionID string, namespace string, resourceGroup string, topicName string) (*[]string, error) { + tClient, err := serviceBusTopicClientE(subscriptionID) + if err != nil { + return nil, err + } + iteratorTopicsRules, err := tClient.ListAuthorizationRulesComplete( + context.Background(), resourceGroup, namespace, topicName) + + if err != nil { + return nil, err + } + + results := make([]string, 0) + for iteratorTopicsRules.NotDone() { + results = append(results, *(iteratorTopicsRules.Value()).Name) + err = iteratorTopicsRules.Next() + if err != nil { + return nil, err + } + } + return &results, nil +} + +// ListTopicAuthRules - like ListTopicAuthRulesE but fails in the case an error is returned +func ListTopicAuthRules(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) *[]string { + results, err := ListTopicAuthRulesE(subscriptionID, namespace, resourceGroup, topicName) + if err != nil { + t.Fatal(err) + } + + return results +} From cd10ea7ba0cb4d1a1b233ca65f6f64426dfefdf2 Mon Sep 17 00:00:00 2001 From: helayoty Date: Mon, 25 Jan 2021 18:15:01 -0800 Subject: [PATCH 02/12] Add tests and terraform module for service bus --- .../main.tf | 1 - modules/azure/servicebus_test.go | 79 +++++++++++++++++++ ...terraform_azure_servicebus_example_test.go | 71 +++++++++++++++++ 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 modules/azure/servicebus_test.go create mode 100644 test/azure/terraform_azure_servicebus_example_test.go diff --git a/examples/azure/terraform-azure-servicebus-example/main.tf b/examples/azure/terraform-azure-servicebus-example/main.tf index f06b59167..cdb0d8328 100644 --- a/examples/azure/terraform-azure-servicebus-example/main.tf +++ b/examples/azure/terraform-azure-servicebus-example/main.tf @@ -23,7 +23,6 @@ resource "azurerm_resource_group" "seervicebus" { location = var.location } - # --------------------------------------------------------------------------------------------------------------------- # DDefine locals variables # --------------------------------------------------------------------------------------------------------------------- diff --git a/modules/azure/servicebus_test.go b/modules/azure/servicebus_test.go new file mode 100644 index 000000000..25c3aad4a --- /dev/null +++ b/modules/azure/servicebus_test.go @@ -0,0 +1,79 @@ +// +build azure + +// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for +// CircleCI. +package azure + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +/* +The below tests are currently stubbed out, with the expectation that they will throw errors. These tests can be extended. +*/ +func TestListServiceBusNamespaceNamesE(t *testing.T) { + t.Parallel() + + subscriptionID := "" + + _, err := ListServiceBusNamespaceNamesE(subscriptionID) + require.Error(t, err) +} + +func TestListServiceBusNamespaceIDsByResourceGroupE(t *testing.T) { + t.Parallel() + + subscriptionID := "" + resourceGroup := "" + + _, err := ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID, resourceGroup) + require.Error(t, err) +} + +func TestListNamespaceAuthRulesE(t *testing.T) { + t.Parallel() + + subscriptionID := "" + namespace := "" + resourceGroup := "" + + _, err := ListNamespaceAuthRulesE(subscriptionID, namespace, resourceGroup) + require.Error(t, err) +} + +func TestListNamespaceTopicsE(t *testing.T) { + t.Parallel() + + subscriptionID := "" + namespace := "" + resourceGroup := "" + + _, err := ListNamespaceTopicsE(subscriptionID, namespace, resourceGroup) + require.Error(t, err) +} + +func TestListTopicAuthRulesE(t *testing.T) { + t.Parallel() + + subscriptionID := "" + namespace := "" + resourceGroup := "" + topicName := "" + + _, err := ListTopicAuthRulesE(subscriptionID, namespace, resourceGroup, topicName) + require.Error(t, err) +} + +func TestListTopicSubscriptionsNameE(t *testing.T) { + t.Parallel() + + subscriptionID := "" + namespace := "" + resourceGroup := "" + topicName := "" + + _, err := ListTopicSubscriptionsNameE(subscriptionID, namespace, resourceGroup, topicName) + require.Error(t, err) +} \ No newline at end of file diff --git a/test/azure/terraform_azure_servicebus_example_test.go b/test/azure/terraform_azure_servicebus_example_test.go new file mode 100644 index 000000000..6624fb2db --- /dev/null +++ b/test/azure/terraform_azure_servicebus_example_test.go @@ -0,0 +1,71 @@ +// +build azure + +// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for +// CircleCI. + +package test + +import ( + "strings" + "testing" + "os" + + "github.com/gruntwork-io/terratest/modules/azure" + "github.com/gruntwork-io/terratest/modules/random" + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" +) + +func TestTerraformAzureServiceBusExample(t *testing.T) { + t.Parallel() + + uniquePostfix := strings.ToLower(random.UniqueId()) + + // website::tag::1:: Configure Terraform setting up a path to Terraform code. + terraformOptions := &terraform.Options{ + // The path to where our Terraform code is located + TerraformDir: "../../examples/azure/terraform-azure-servicebus-example", + Vars: map[string]interface{}{ + "postfix": uniquePostfix, + }, + } + + // website::tag::4:: At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // website::tag::2:: Run `terraform init` and `terraform apply`. Fail the test if there are any errors. + terraform.InitAndApply(t, terraformOptions) + + // website::tag::3:: Run `terraform output` to get the values of output variables + expectedTopicSubscriptionsMap := terraform.OutputMapOfObjects(t, terraformOptions, "topics") + expectedNamespaceName := terraform.Output(t, terraformOptions, "namespace_name") + expectedResourceGroup := terraform.Output(t, terraformOptions, "resource_group") + + for topicName, topicsMap := range expectedTopicSubscriptionsMap { + subscriptionNamesFromAzure, err := azure.ListTopicSubscriptionsNameE( + os.Getenv("ARM_SUBSCRIPTION_ID"), + expectedNamespaceName, + expectedResourceGroup, + topicName) + + if err != nil { + t.Fatal(err) + } + + subscriptionsMap := topicsMap.(map[string]interface{})["subscriptions"].(map[string]interface{}) + subscriptionNamesFromOutput := getMapKeylist(subscriptionsMap) + // each subscription from the output should also exist in Azure + assert.Equal(t, len(*subscriptionNamesFromOutput), len(*subscriptionNamesFromAzure)) + for _, subscrptionName := range *subscriptionNamesFromOutput { + assert.Contains(t, *subscriptionNamesFromAzure, subscrptionName) + } + } +} + +func getMapKeylist(mapList map[string]interface{}) *[]string { + names := make([]string, 0) + for key := range mapList { + names = append(names, key) + } + return &names +} From 59f60ea75774384c09b30f1bb7760f695d148a6f Mon Sep 17 00:00:00 2001 From: helayoty Date: Wed, 27 Jan 2021 11:49:51 -0800 Subject: [PATCH 03/12] Remove unused func --- modules/azure/servicebus.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/modules/azure/servicebus.go b/modules/azure/servicebus.go index 7ea760539..c0cadc6df 100644 --- a/modules/azure/servicebus.go +++ b/modules/azure/servicebus.go @@ -7,17 +7,6 @@ import ( "github.com/Azure/azure-sdk-for-go/services/servicebus/mgmt/2017-04-01/servicebus" ) -func serviceBusClientE(subscriptionID string) (*servicebus.BaseClient, error) { - authorizer, err := NewAuthorizer() - if err != nil { - return nil, err - } - - client := servicebus.New(subscriptionID) - client.Authorizer = *authorizer - return &client, nil -} - func serviceBusNamespaceClientE(subscriptionID string) (*servicebus.NamespacesClient, error) { authorizer, err := NewAuthorizer() if err != nil { From 260bcb856c2db8c7e66f7548044160b14a82f969 Mon Sep 17 00:00:00 2001 From: helayoty Date: Wed, 27 Jan 2021 14:12:23 -0800 Subject: [PATCH 04/12] Add default values for required variables --- .../main.tf | 4 +- .../outputs.tf | 2 +- .../variables.tf | 52 ++++++++++--------- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/examples/azure/terraform-azure-servicebus-example/main.tf b/examples/azure/terraform-azure-servicebus-example/main.tf index cdb0d8328..bdc063755 100644 --- a/examples/azure/terraform-azure-servicebus-example/main.tf +++ b/examples/azure/terraform-azure-servicebus-example/main.tf @@ -18,7 +18,7 @@ provider "azurerm" { # DEPLOY A RESOURCE GROUP # --------------------------------------------------------------------------------------------------------------------- -resource "azurerm_resource_group" "seervicebus" { +resource "azurerm_resource_group" "servicebus" { name = "terratest-rg-${var.postfix}" location = var.location } @@ -65,7 +65,7 @@ locals { # DEPLOY AZURE Service Bus Namespace # --------------------------------------------------------------------------------------------------------------------- resource "azurerm_servicebus_namespace" "servicebus" { - name = var.namespace_name + name = "terratest-namespace-${var.namespace_name}" location = azurerm_resource_group.servicebus.location resource_group_name = azurerm_resource_group.servicebus.name sku = var.sku diff --git a/examples/azure/terraform-azure-servicebus-example/outputs.tf b/examples/azure/terraform-azure-servicebus-example/outputs.tf index 6acb94e66..dffe2c15a 100644 --- a/examples/azure/terraform-azure-servicebus-example/outputs.tf +++ b/examples/azure/terraform-azure-servicebus-example/outputs.tf @@ -5,7 +5,7 @@ output "namespace_name" { output "resource_group" { description = "The resource group name of the Service Bus namespace." - value = data.azurerm_resource_group.resourcegroup.name + value = azurerm_resource_group.servicebus.name } output "namespace_id" { diff --git a/examples/azure/terraform-azure-servicebus-example/variables.tf b/examples/azure/terraform-azure-servicebus-example/variables.tf index 64f7bab6c..c8bfc968b 100644 --- a/examples/azure/terraform-azure-servicebus-example/variables.tf +++ b/examples/azure/terraform-azure-servicebus-example/variables.tf @@ -13,14 +13,38 @@ # You must provide a value for each of these parameters. # --------------------------------------------------------------------------------------------------------------------- +variable "postfix" { + description = "The name of the resource group for the provisioned service bus." + type = string +} + +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL PARAMETERS +# These parameters have reasonable defaults. +# --------------------------------------------------------------------------------------------------------------------- + +variable "location" { + description = "The supported azure location where the resource exists" + type = string + default = "West US2" +} + variable "namespace_name" { description = "The name of the namespace." type = string + default = "testservicebus101" } -variable "postfix" { - description = "The name of the resource group for the provisioned service bus." +variable "sku" { + description = "The SKU of the namespace. The options are: `Basic`, `Standard`, `Premium`." type = string + default = "Standard" +} + +variable "tags" { + description = " A mapping of tags to assign to the resource." + type = map(string) + default = {} } variable "namespace_authorization_rules" { @@ -56,27 +80,5 @@ variable "topics" { action = string })) })) -} - -# --------------------------------------------------------------------------------------------------------------------- -# OPTIONAL PARAMETERS -# These parameters have reasonable defaults. -# --------------------------------------------------------------------------------------------------------------------- - -variable "location" { - description = "The supported azure location where the resource exists" - type = string - default = "West US2" -} - -variable "sku" { - description = "The SKU of the namespace. The options are: `Basic`, `Standard`, `Premium`." - type = string - default = "Standard" -} - -variable "tags" { - description = " A mapping of tags to assign to the resource." - type = map(string) - default = {} + default = [] } From f73b81932d1cba945b617376e25551e9bdc93fe3 Mon Sep 17 00:00:00 2001 From: helayoty Date: Wed, 27 Jan 2021 14:19:22 -0800 Subject: [PATCH 05/12] fix format --- examples/azure/terraform-azure-servicebus-example/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/azure/terraform-azure-servicebus-example/variables.tf b/examples/azure/terraform-azure-servicebus-example/variables.tf index c8bfc968b..8c3477e0e 100644 --- a/examples/azure/terraform-azure-servicebus-example/variables.tf +++ b/examples/azure/terraform-azure-servicebus-example/variables.tf @@ -32,7 +32,7 @@ variable "location" { variable "namespace_name" { description = "The name of the namespace." type = string - default = "testservicebus101" + default = "testservicebus101" } variable "sku" { From 6a20c394038ae491489f7fa2619a9b90baeb9df0 Mon Sep 17 00:00:00 2001 From: helayoty Date: Thu, 28 Jan 2021 10:11:27 -0800 Subject: [PATCH 06/12] Address code review comments --- .../main.tf | 20 ++-- .../outputs.tf | 14 ++- .../variables.tf | 2 +- modules/azure/servicebus.go | 94 ++++++++----------- ...terraform_azure_servicebus_example_test.go | 9 +- 5 files changed, 62 insertions(+), 77 deletions(-) diff --git a/examples/azure/terraform-azure-servicebus-example/main.tf b/examples/azure/terraform-azure-servicebus-example/main.tf index bdc063755..0f0f32a51 100644 --- a/examples/azure/terraform-azure-servicebus-example/main.tf +++ b/examples/azure/terraform-azure-servicebus-example/main.tf @@ -18,13 +18,13 @@ provider "azurerm" { # DEPLOY A RESOURCE GROUP # --------------------------------------------------------------------------------------------------------------------- -resource "azurerm_resource_group" "servicebus" { +resource "azurerm_resource_group" "servicebus_rg" { name = "terratest-rg-${var.postfix}" location = var.location } # --------------------------------------------------------------------------------------------------------------------- -# DDefine locals variables +# Define locals variables # --------------------------------------------------------------------------------------------------------------------- locals { topic_authorization_rules = flatten([ @@ -66,8 +66,8 @@ locals { # --------------------------------------------------------------------------------------------------------------------- resource "azurerm_servicebus_namespace" "servicebus" { name = "terratest-namespace-${var.namespace_name}" - location = azurerm_resource_group.servicebus.location - resource_group_name = azurerm_resource_group.servicebus.name + location = azurerm_resource_group.servicebus_rg.location + resource_group_name = azurerm_resource_group.servicebus_rg.name sku = var.sku tags = var.tags } @@ -80,7 +80,7 @@ resource "azurerm_servicebus_namespace_authorization_rule" "sbnamespaceauth" { name = var.namespace_authorization_rules[count.index].policy_name namespace_name = azurerm_servicebus_namespace.servicebus.name - resource_group_name = azurerm_resource_group.servicebus.name + resource_group_name = azurerm_resource_group.servicebus_rg.name listen = var.namespace_authorization_rules[count.index].claims.listen send = var.namespace_authorization_rules[count.index].claims.send @@ -94,7 +94,7 @@ resource "azurerm_servicebus_topic" "sptopic" { count = length(var.topics) name = var.topics[count.index].name - resource_group_name = azurerm_resource_group.servicebus.name + resource_group_name = azurerm_resource_group.servicebus_rg.name namespace_name = azurerm_servicebus_namespace.servicebus.name requires_duplicate_detection = var.topics[count.index].requires_duplicate_detection @@ -110,7 +110,7 @@ resource "azurerm_servicebus_topic_authorization_rule" "topicaauth" { count = length(local.topic_authorization_rules) name = local.topic_authorization_rules[count.index].policy_name - resource_group_name = azurerm_resource_group.servicebus.name + resource_group_name = azurerm_resource_group.servicebus_rg.name namespace_name = azurerm_servicebus_namespace.servicebus.name topic_name = local.topic_authorization_rules[count.index].topic_name @@ -128,7 +128,7 @@ resource "azurerm_servicebus_subscription" "subscription" { count = length(local.topic_subscriptions) name = local.topic_subscriptions[count.index].name - resource_group_name = azurerm_resource_group.servicebus.name + resource_group_name = azurerm_resource_group.servicebus_rg.name namespace_name = azurerm_servicebus_namespace.servicebus.name topic_name = local.topic_subscriptions[count.index].topic_name @@ -147,7 +147,7 @@ resource "azurerm_servicebus_subscription_rule" "subrules" { count = length(local.topic_subscription_rules) name = local.topic_subscription_rules[count.index].name - resource_group_name = azurerm_resource_group.servicebus.name + resource_group_name = azurerm_resource_group.servicebus_rg.name namespace_name = azurerm_servicebus_namespace.servicebus.name topic_name = local.topic_subscription_rules[count.index].topic_name subscription_name = local.topic_subscription_rules[count.index].subscription_name @@ -156,4 +156,4 @@ resource "azurerm_servicebus_subscription_rule" "subrules" { action = local.topic_subscription_rules[count.index].action depends_on = [azurerm_servicebus_subscription.subscription] -} \ No newline at end of file +} diff --git a/examples/azure/terraform-azure-servicebus-example/outputs.tf b/examples/azure/terraform-azure-servicebus-example/outputs.tf index dffe2c15a..e9c9b5012 100644 --- a/examples/azure/terraform-azure-servicebus-example/outputs.tf +++ b/examples/azure/terraform-azure-servicebus-example/outputs.tf @@ -1,16 +1,17 @@ +output "resource_group" { + description = "The resource group name of the Service Bus namespace." + value = azurerm_resource_group.servicebus_rg.name +} + output "namespace_name" { description = "The namespace name." value = azurerm_servicebus_namespace.servicebus.name } -output "resource_group" { - description = "The resource group name of the Service Bus namespace." - value = azurerm_resource_group.servicebus.name -} - output "namespace_id" { description = "The namespace ID." value = azurerm_servicebus_namespace.servicebus.id + sensitive = true } output "namespace_authorization_rules" { @@ -23,16 +24,19 @@ output "namespace_authorization_rules" { manage = auth.manage } } + sensitive = true } output "service_bus_namespace_default_primary_key" { description = "The primary access key for the authorization rule RootManageSharedAccessKey which is created automatically by Azure." value = azurerm_servicebus_namespace.servicebus.default_primary_key + sensitive = true } output "service_bus_namespace_default_connection_string" { description = "The primary connection string for the authorization rule RootManageSharedAccessKey which is created automatically by Azure." value = azurerm_servicebus_namespace.servicebus.default_primary_connection_string + sensitive = true } diff --git a/examples/azure/terraform-azure-servicebus-example/variables.tf b/examples/azure/terraform-azure-servicebus-example/variables.tf index 8c3477e0e..dda4acf63 100644 --- a/examples/azure/terraform-azure-servicebus-example/variables.tf +++ b/examples/azure/terraform-azure-servicebus-example/variables.tf @@ -14,7 +14,7 @@ # --------------------------------------------------------------------------------------------------------------------- variable "postfix" { - description = "The name of the resource group for the provisioned service bus." + description = "string mitigate resource name collisions." type = string } diff --git a/modules/azure/servicebus.go b/modules/azure/servicebus.go index c0cadc6df..01c26463d 100644 --- a/modules/azure/servicebus.go +++ b/modules/azure/servicebus.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/services/servicebus/mgmt/2017-04-01/servicebus" + "github.com/stretchr/testify/require" ) func serviceBusNamespaceClientE(subscriptionID string) (*servicebus.NamespacesClient, error) { @@ -40,7 +41,7 @@ func serviceBusSubscriptionsClientE(subscriptionID string) (*servicebus.Subscrip return &sClient, nil } -// ListServiceBusNamespaceE list all SB namespaces in all resource groups in the given subscription ID +// ListServiceBusNamespaceE list all SB namespaces in all resource groups in the given subscription ID. This function would fail the test if there is an error. func ListServiceBusNamespaceE(subscriptionID string) (*[]servicebus.SBNamespace, error) { nsClient, err := serviceBusNamespaceClientE(subscriptionID) if err != nil { @@ -64,17 +65,16 @@ func ListServiceBusNamespaceE(subscriptionID string) (*[]servicebus.SBNamespace, return &results, nil } -// ListServiceBusNamespace - like ListServiceBusNamespaceE but fails in the case an error is returned +// ListServiceBusNamespace - list all SB namespaces in all resource groups in the given subscription ID. func ListServiceBusNamespace(t *testing.T, subscriptionID string) *[]servicebus.SBNamespace { results, err := ListServiceBusNamespaceE(subscriptionID) - if err != nil { - t.Fatal(err) - } + + require.NoError(t, err) return results } -// ListServiceBusNamespaceNamesE list names of all SB namespaces in all resource groups in the given subscription ID +// ListServiceBusNamespaceNamesE list names of all SB namespaces in all resource groups in the given subscription ID. This function would fail the test if there is an error. func ListServiceBusNamespaceNamesE(subscriptionID string) (*[]string, error) { sbNamespace, err := ListServiceBusNamespaceE(subscriptionID) @@ -93,17 +93,16 @@ func ListServiceBusNamespaceNamesE(subscriptionID string) (*[]string, error) { return &results, nil } -// ListServiceBusNamespaceNames like ListServiceBusNamespaceNamesE but fails in the case an error is returned +// ListServiceBusNamespaceNames list names of all SB namespaces in all resource groups in the given subscription ID. func ListServiceBusNamespaceNames(t *testing.T, subscriptionID string) *[]string { results, err := ListServiceBusNamespaceNamesE(subscriptionID) - if err != nil { - t.Fatal(err) - } + + require.NoError(t, err) return results } -// ListServiceBusNamespaceIDsE list IDs of all SB namespaces in all resource groups in the given subscription ID +// ListServiceBusNamespaceIDsE list IDs of all SB namespaces in all resource groups in the given subscription ID. This function would fail the test if there is an error. func ListServiceBusNamespaceIDsE(subscriptionID string) (*[]string, error) { sbNamespace, err := ListServiceBusNamespaceE(subscriptionID) @@ -122,17 +121,15 @@ func ListServiceBusNamespaceIDsE(subscriptionID string) (*[]string, error) { return &results, nil } -// ListServiceBusNamespaceIDs like ListServiceBusNamespaceIDsE but fails in the case an error is returned +// ListServiceBusNamespaceIDs list IDs of all SB namespaces in all resource groups in the given subscription ID. func ListServiceBusNamespaceIDs(t *testing.T, subscriptionID string) *[]string { results, err := ListServiceBusNamespaceIDsE(subscriptionID) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return results } -// ListServiceBusNamespaceByResourceGroupE list all SB namespaces in the given resource group +// ListServiceBusNamespaceByResourceGroupE list all SB namespaces in the given resource group. This function would fail the test if there is an error. func ListServiceBusNamespaceByResourceGroupE(subscriptionID string, resourceGroup string) (*[]servicebus.SBNamespace, error) { nsClient, err := serviceBusNamespaceClientE(subscriptionID) if err != nil { @@ -157,17 +154,15 @@ func ListServiceBusNamespaceByResourceGroupE(subscriptionID string, resourceGrou return &results, nil } -// ListServiceBusNamespaceByResourceGroup like ListServiceBusNamespaceByResourceGroupE but fails in the case an error is returned +// ListServiceBusNamespaceByResourceGroup list all SB namespaces in the given resource group. func ListServiceBusNamespaceByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) *[]servicebus.SBNamespace { results, err := ListServiceBusNamespaceByResourceGroupE(subscriptionID, resourceGroup) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return results } -// ListServiceBusNamespaceNamesByResourceGroupE list names of all SB namespaces in the given resource group +// ListServiceBusNamespaceNamesByResourceGroupE list names of all SB namespaces in the given resource group. This function would fail the test if there is an error. func ListServiceBusNamespaceNamesByResourceGroupE(subscriptionID string, resourceGroup string) (*[]string, error) { sbNamespace, err := ListServiceBusNamespaceByResourceGroupE(subscriptionID, resourceGroup) @@ -186,17 +181,15 @@ func ListServiceBusNamespaceNamesByResourceGroupE(subscriptionID string, resourc return &results, nil } -// ListServiceBusNamespaceNamesByResourceGroup like ListServiceBusNamespaceNamesByResourceGroupE but fails in the case an error is returned +// ListServiceBusNamespaceNamesByResourceGroup list names of all SB namespaces in the given resource group. func ListServiceBusNamespaceNamesByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) *[]string { results, err := ListServiceBusNamespaceNamesByResourceGroupE(subscriptionID, resourceGroup) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return results } -// ListServiceBusNamespaceIDsByResourceGroupE list IDs of all SB namespaces in the given resource group +// ListServiceBusNamespaceIDsByResourceGroupE list IDs of all SB namespaces in the given resource group. This function would fail the test if there is an error. func ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID string, resourceGroup string) (*[]string, error) { sbNamespace, err := ListServiceBusNamespaceByResourceGroupE(subscriptionID, resourceGroup) @@ -215,18 +208,16 @@ func ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID string, resourceG return &results, nil } -// ListServiceBusNamespaceIDsByResourceGroup like ListServiceBusNamespaceIDsByResourceGroupE but fails in the case an error is returned +// ListServiceBusNamespaceIDsByResourceGroup list IDs of all SB namespaces in the given resource group. func ListServiceBusNamespaceIDsByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) *[]string { results, err := ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID, resourceGroup) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return results } // ListNamespaceAuthRulesE - authenticate namespace client and enumerates all values to get list of authorization rules for the given namespace name, -// automatically crossing page boundaries as required. +// automatically crossing page boundaries as required. This function would fail the test if there is an error. func ListNamespaceAuthRulesE(subscriptionID string, namespace string, resourceGroup string) (*[]string, error) { nsClient, err := serviceBusNamespaceClientE(subscriptionID) if err != nil { @@ -250,17 +241,16 @@ func ListNamespaceAuthRulesE(subscriptionID string, namespace string, resourceGr return &results, nil } -// ListNamespaceAuthRules - like ListNamespaceAuthRulesE but fails in the case an error is returned +// ListNamespaceAuthRules - authenticate namespace client and enumerates all values to get list of authorization rules for the given namespace name, +// automatically crossing page boundaries as required. func ListNamespaceAuthRules(t *testing.T, subscriptionID string, namespace string, resourceGroup string) *[]string { results, err := ListNamespaceAuthRulesE(subscriptionID, namespace, resourceGroup) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return results } -// ListNamespaceTopicsE - authenticate topic client and enumerates all values, automatically crossing page boundaries as required. +// ListNamespaceTopicsE - authenticate topic client and enumerates all values, automatically crossing page boundaries as required. This function would fail the test if there is an error. func ListNamespaceTopicsE(subscriptionID string, namespace string, resourceGroup string) (*[]servicebus.SBTopic, error) { tClient, err := serviceBusTopicClientE(subscriptionID) if err != nil { @@ -285,17 +275,15 @@ func ListNamespaceTopicsE(subscriptionID string, namespace string, resourceGroup return &results, nil } -// ListNamespaceTopics - like ListNamespaceTopicsE but fails in the case an error is returned +// ListNamespaceTopics - authenticate topic client and enumerates all values, automatically crossing page boundaries as required. func ListNamespaceTopics(t *testing.T, subscriptionID string, namespace string, resourceGroup string) *[]servicebus.SBTopic { results, err := ListNamespaceTopicsE(subscriptionID, namespace, resourceGroup) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return results } -// ListTopicSubscriptionsE - authenticate subscriptions client and enumerates all values, automatically crossing page boundaries as required. +// ListTopicSubscriptionsE - authenticate subscriptions client and enumerates all values, automatically crossing page boundaries as required. This function would fail the test if there is an error. func ListTopicSubscriptionsE(subscriptionID string, namespace string, resourceGroup string, topicName string) ([]servicebus.SBSubscription, error) { sClient, err := serviceBusSubscriptionsClientE(subscriptionID) if err != nil { @@ -319,18 +307,16 @@ func ListTopicSubscriptionsE(subscriptionID string, namespace string, resourceGr return results, nil } -// ListTopicSubscriptions - like ListTopicSubscriptionsE but fails in the case an error is returned +// ListTopicSubscriptions - authenticate subscriptions client and enumerates all values, automatically crossing page boundaries as required. func ListTopicSubscriptions(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) *[]servicebus.SBSubscription { results, err := ListTopicSubscriptionsE(subscriptionID, namespace, resourceGroup, topicName) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return &results } // ListTopicSubscriptionsNameE - authenticate subscriptions client and enumerates all values to get list of subscriptions for the given topic name, -// automatically crossing page boundaries as required. +// automatically crossing page boundaries as required. This function would fail the test if there is an error. func ListTopicSubscriptionsNameE(subscriptionID string, namespace string, resourceGroup string, topicName string) (*[]string, error) { sClient, err := serviceBusSubscriptionsClientE(subscriptionID) if err != nil { @@ -353,18 +339,17 @@ func ListTopicSubscriptionsNameE(subscriptionID string, namespace string, resour return &results, nil } -// ListTopicSubscriptionsName - like ListTopicSubscriptionsNameE but fails in the case an error is returned +// ListTopicSubscriptionsName - authenticate subscriptions client and enumerates all values to get list of subscriptions for the given topic name, +// automatically crossing page boundaries as required. func ListTopicSubscriptionsName(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) *[]string { results, err := ListTopicSubscriptionsNameE(subscriptionID, namespace, resourceGroup, topicName) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return results } // ListTopicAuthRulesE - authenticate topic client and enumerates all values to get list of authorization rules for the given topic name, -// automatically crossing page boundaries as required. +// automatically crossing page boundaries as required. This function would fail the test if there is an error. func ListTopicAuthRulesE(subscriptionID string, namespace string, resourceGroup string, topicName string) (*[]string, error) { tClient, err := serviceBusTopicClientE(subscriptionID) if err != nil { @@ -388,12 +373,11 @@ func ListTopicAuthRulesE(subscriptionID string, namespace string, resourceGroup return &results, nil } -// ListTopicAuthRules - like ListTopicAuthRulesE but fails in the case an error is returned +// ListTopicAuthRules - authenticate topic client and enumerates all values to get list of authorization rules for the given topic name, +// automatically crossing page boundaries as required. func ListTopicAuthRules(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) *[]string { results, err := ListTopicAuthRulesE(subscriptionID, namespace, resourceGroup, topicName) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return results } diff --git a/test/azure/terraform_azure_servicebus_example_test.go b/test/azure/terraform_azure_servicebus_example_test.go index 6624fb2db..d84981fb8 100644 --- a/test/azure/terraform_azure_servicebus_example_test.go +++ b/test/azure/terraform_azure_servicebus_example_test.go @@ -42,22 +42,19 @@ func TestTerraformAzureServiceBusExample(t *testing.T) { expectedResourceGroup := terraform.Output(t, terraformOptions, "resource_group") for topicName, topicsMap := range expectedTopicSubscriptionsMap { - subscriptionNamesFromAzure, err := azure.ListTopicSubscriptionsNameE( + actualsubscriptionNames := azure.ListTopicSubscriptionsName( os.Getenv("ARM_SUBSCRIPTION_ID"), expectedNamespaceName, expectedResourceGroup, topicName) - if err != nil { - t.Fatal(err) - } subscriptionsMap := topicsMap.(map[string]interface{})["subscriptions"].(map[string]interface{}) subscriptionNamesFromOutput := getMapKeylist(subscriptionsMap) // each subscription from the output should also exist in Azure - assert.Equal(t, len(*subscriptionNamesFromOutput), len(*subscriptionNamesFromAzure)) + assert.Equal(t, len(*subscriptionNamesFromOutput), len(*actualsubscriptionNames)) for _, subscrptionName := range *subscriptionNamesFromOutput { - assert.Contains(t, *subscriptionNamesFromAzure, subscrptionName) + assert.Contains(t, *actualsubscriptionNames, subscrptionName) } } } From 72d81e544f76e0a30fc318b741d5bafae2d959f5 Mon Sep 17 00:00:00 2001 From: helayoty Date: Thu, 28 Jan 2021 10:19:52 -0800 Subject: [PATCH 07/12] add test as param --- test/azure/terraform_azure_servicebus_example_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/azure/terraform_azure_servicebus_example_test.go b/test/azure/terraform_azure_servicebus_example_test.go index d84981fb8..9cd306468 100644 --- a/test/azure/terraform_azure_servicebus_example_test.go +++ b/test/azure/terraform_azure_servicebus_example_test.go @@ -42,7 +42,7 @@ func TestTerraformAzureServiceBusExample(t *testing.T) { expectedResourceGroup := terraform.Output(t, terraformOptions, "resource_group") for topicName, topicsMap := range expectedTopicSubscriptionsMap { - actualsubscriptionNames := azure.ListTopicSubscriptionsName( + actualsubscriptionNames := azure.ListTopicSubscriptionsName(t, os.Getenv("ARM_SUBSCRIPTION_ID"), expectedNamespaceName, expectedResourceGroup, From 0f7956faae58e7f8b976cfaf4c1e31639c280a9d Mon Sep 17 00:00:00 2001 From: helayoty Date: Thu, 28 Jan 2021 12:10:54 -0800 Subject: [PATCH 08/12] add `sb` to the resource gourp name --- examples/azure/terraform-azure-servicebus-example/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/azure/terraform-azure-servicebus-example/main.tf b/examples/azure/terraform-azure-servicebus-example/main.tf index 0f0f32a51..6ff4550c0 100644 --- a/examples/azure/terraform-azure-servicebus-example/main.tf +++ b/examples/azure/terraform-azure-servicebus-example/main.tf @@ -19,7 +19,7 @@ provider "azurerm" { # --------------------------------------------------------------------------------------------------------------------- resource "azurerm_resource_group" "servicebus_rg" { - name = "terratest-rg-${var.postfix}" + name = "terratest-sb-rg-${var.postfix}" location = var.location } From b324f4b5c6a3f775664dc811725ea322aa30abc3 Mon Sep 17 00:00:00 2001 From: helayoty Date: Tue, 2 Feb 2021 16:33:08 -0800 Subject: [PATCH 09/12] move postfix to optional variables --- .../terraform-azure-servicebus-example/variables.tf | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/azure/terraform-azure-servicebus-example/variables.tf b/examples/azure/terraform-azure-servicebus-example/variables.tf index dda4acf63..fb065985f 100644 --- a/examples/azure/terraform-azure-servicebus-example/variables.tf +++ b/examples/azure/terraform-azure-servicebus-example/variables.tf @@ -13,11 +13,6 @@ # You must provide a value for each of these parameters. # --------------------------------------------------------------------------------------------------------------------- -variable "postfix" { - description = "string mitigate resource name collisions." - type = string -} - # --------------------------------------------------------------------------------------------------------------------- # OPTIONAL PARAMETERS # These parameters have reasonable defaults. @@ -29,6 +24,12 @@ variable "location" { default = "West US2" } +variable "postfix" { + description = "string mitigate resource name collisions." + type = string + default = "servicebus" +} + variable "namespace_name" { description = "The name of the namespace." type = string From e6d6ca650901fe2f9bd09955ff91873df505ed15 Mon Sep 17 00:00:00 2001 From: Hadwa Abdelhalem Date: Wed, 1 Sep 2021 12:53:28 -0700 Subject: [PATCH 10/12] address PR review comments --- .../outputs.tf | 2 +- modules/azure/servicebus.go | 166 +++++++++--------- ...terraform_azure_servicebus_example_test.go | 17 +- 3 files changed, 89 insertions(+), 96 deletions(-) diff --git a/examples/azure/terraform-azure-servicebus-example/outputs.tf b/examples/azure/terraform-azure-servicebus-example/outputs.tf index e9c9b5012..d8435b170 100644 --- a/examples/azure/terraform-azure-servicebus-example/outputs.tf +++ b/examples/azure/terraform-azure-servicebus-example/outputs.tf @@ -41,6 +41,7 @@ output "service_bus_namespace_default_connection_string" { output "topics" { + description = "All topics with the corresponding subscriptions" value = { for topic in azurerm_servicebus_topic.sptopic : topic.name => { @@ -62,5 +63,4 @@ output "topics" { } } } - description = "All topics with the corresponding subscriptions" } diff --git a/modules/azure/servicebus.go b/modules/azure/servicebus.go index 01c26463d..3816f0c21 100644 --- a/modules/azure/servicebus.go +++ b/modules/azure/servicebus.go @@ -41,8 +41,8 @@ func serviceBusSubscriptionsClientE(subscriptionID string) (*servicebus.Subscrip return &sClient, nil } -// ListServiceBusNamespaceE list all SB namespaces in all resource groups in the given subscription ID. This function would fail the test if there is an error. -func ListServiceBusNamespaceE(subscriptionID string) (*[]servicebus.SBNamespace, error) { +// ListServiceBusNamespaceE list all SB namespaces in all resource groups in the given subscription ID. +func ListServiceBusNamespaceE(subscriptionID string) ([]servicebus.SBNamespace, error) { nsClient, err := serviceBusNamespaceClientE(subscriptionID) if err != nil { return nil, err @@ -62,75 +62,83 @@ func ListServiceBusNamespaceE(subscriptionID string) (*[]servicebus.SBNamespace, } } - return &results, nil + return results, nil } -// ListServiceBusNamespace - list all SB namespaces in all resource groups in the given subscription ID. -func ListServiceBusNamespace(t *testing.T, subscriptionID string) *[]servicebus.SBNamespace { +// ListServiceBusNamespace - list all SB namespaces in all resource groups in the given subscription ID. This function would fail the test if there is an error. +func ListServiceBusNamespace(t *testing.T, subscriptionID string) []servicebus.SBNamespace { results, err := ListServiceBusNamespaceE(subscriptionID) - + require.NoError(t, err) return results } -// ListServiceBusNamespaceNamesE list names of all SB namespaces in all resource groups in the given subscription ID. This function would fail the test if there is an error. -func ListServiceBusNamespaceNamesE(subscriptionID string) (*[]string, error) { +// ListServiceBusNamespaceNamesE list names of all SB namespaces in all resource groups in the given subscription ID. +func ListServiceBusNamespaceNamesE(subscriptionID string) ([]string, error) { sbNamespace, err := ListServiceBusNamespaceE(subscriptionID) if err != nil { return nil, err } - results := make([]string, 0) - for _, namespace := range *sbNamespace { + results := BuildNamespaceNamesList(sbNamespace) + return results, nil +} + +// BuildNamespaceNamesList helper method to build namespace name list +func BuildNamespaceNamesList(sbNamespace []servicebus.SBNamespace) []string { + results := []string{} + for _, namespace := range sbNamespace { results = append(results, *namespace.Name) - if err != nil { - return nil, err - } + + } + + return results +} + +// BuildNamespaceIdsList helper method to build namespace id list +func BuildNamespaceIdsList(sbNamespace []servicebus.SBNamespace) []string { + results := []string{} + for _, namespace := range sbNamespace { + results = append(results, *namespace.ID) + } - return &results, nil + return results } -// ListServiceBusNamespaceNames list names of all SB namespaces in all resource groups in the given subscription ID. -func ListServiceBusNamespaceNames(t *testing.T, subscriptionID string) *[]string { +// ListServiceBusNamespaceNames list names of all SB namespaces in all resource groups in the given subscription ID. This function would fail the test if there is an error. +func ListServiceBusNamespaceNames(t *testing.T, subscriptionID string) []string { results, err := ListServiceBusNamespaceNamesE(subscriptionID) - + require.NoError(t, err) return results } -// ListServiceBusNamespaceIDsE list IDs of all SB namespaces in all resource groups in the given subscription ID. This function would fail the test if there is an error. -func ListServiceBusNamespaceIDsE(subscriptionID string) (*[]string, error) { +// ListServiceBusNamespaceIDsE list IDs of all SB namespaces in all resource groups in the given subscription ID. +func ListServiceBusNamespaceIDsE(subscriptionID string) ([]string, error) { sbNamespace, err := ListServiceBusNamespaceE(subscriptionID) if err != nil { return nil, err } - results := make([]string, 0) - for _, namespace := range *sbNamespace { - results = append(results, *namespace.ID) - if err != nil { - return nil, err - } - } - - return &results, nil + results := BuildNamespaceIdsList(sbNamespace) + return results, nil } -// ListServiceBusNamespaceIDs list IDs of all SB namespaces in all resource groups in the given subscription ID. -func ListServiceBusNamespaceIDs(t *testing.T, subscriptionID string) *[]string { +// ListServiceBusNamespaceIDs list IDs of all SB namespaces in all resource groups in the given subscription ID. This function would fail the test if there is an error. +func ListServiceBusNamespaceIDs(t *testing.T, subscriptionID string) []string { results, err := ListServiceBusNamespaceIDsE(subscriptionID) require.NoError(t, err) return results } -// ListServiceBusNamespaceByResourceGroupE list all SB namespaces in the given resource group. This function would fail the test if there is an error. -func ListServiceBusNamespaceByResourceGroupE(subscriptionID string, resourceGroup string) (*[]servicebus.SBNamespace, error) { +// ListServiceBusNamespaceByResourceGroupE list all SB namespaces in the given resource group. +func ListServiceBusNamespaceByResourceGroupE(subscriptionID string, resourceGroup string) ([]servicebus.SBNamespace, error) { nsClient, err := serviceBusNamespaceClientE(subscriptionID) if err != nil { return nil, err @@ -151,11 +159,11 @@ func ListServiceBusNamespaceByResourceGroupE(subscriptionID string, resourceGrou } } - return &results, nil + return results, nil } -// ListServiceBusNamespaceByResourceGroup list all SB namespaces in the given resource group. -func ListServiceBusNamespaceByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) *[]servicebus.SBNamespace { +// ListServiceBusNamespaceByResourceGroup list all SB namespaces in the given resource group. This function would fail the test if there is an error. +func ListServiceBusNamespaceByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) []servicebus.SBNamespace { results, err := ListServiceBusNamespaceByResourceGroupE(subscriptionID, resourceGroup) require.NoError(t, err) @@ -163,53 +171,39 @@ func ListServiceBusNamespaceByResourceGroup(t *testing.T, subscriptionID string, } // ListServiceBusNamespaceNamesByResourceGroupE list names of all SB namespaces in the given resource group. This function would fail the test if there is an error. -func ListServiceBusNamespaceNamesByResourceGroupE(subscriptionID string, resourceGroup string) (*[]string, error) { +func ListServiceBusNamespaceNamesByResourceGroupE(subscriptionID string, resourceGroup string) ([]string, error) { sbNamespace, err := ListServiceBusNamespaceByResourceGroupE(subscriptionID, resourceGroup) if err != nil { return nil, err } - results := make([]string, 0) - for _, namespace := range *sbNamespace { - results = append(results, *namespace.Name) - if err != nil { - return nil, err - } - } - - return &results, nil + results := BuildNamespaceNamesList(sbNamespace) + return results, nil } // ListServiceBusNamespaceNamesByResourceGroup list names of all SB namespaces in the given resource group. -func ListServiceBusNamespaceNamesByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) *[]string { +func ListServiceBusNamespaceNamesByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) []string { results, err := ListServiceBusNamespaceNamesByResourceGroupE(subscriptionID, resourceGroup) require.NoError(t, err) return results } -// ListServiceBusNamespaceIDsByResourceGroupE list IDs of all SB namespaces in the given resource group. This function would fail the test if there is an error. -func ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID string, resourceGroup string) (*[]string, error) { +// ListServiceBusNamespaceIDsByResourceGroupE list IDs of all SB namespaces in the given resource group. +func ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID string, resourceGroup string) ([]string, error) { sbNamespace, err := ListServiceBusNamespaceByResourceGroupE(subscriptionID, resourceGroup) if err != nil { return nil, err } - results := make([]string, 0) - for _, namespace := range *sbNamespace { - results = append(results, *namespace.ID) - if err != nil { - return nil, err - } - } - - return &results, nil + results := BuildNamespaceIdsList(sbNamespace) + return results, nil } -// ListServiceBusNamespaceIDsByResourceGroup list IDs of all SB namespaces in the given resource group. -func ListServiceBusNamespaceIDsByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) *[]string { +// ListServiceBusNamespaceIDsByResourceGroup list IDs of all SB namespaces in the given resource group. This function would fail the test if there is an error. +func ListServiceBusNamespaceIDsByResourceGroup(t *testing.T, subscriptionID string, resourceGroup string) []string { results, err := ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID, resourceGroup) require.NoError(t, err) @@ -217,8 +211,8 @@ func ListServiceBusNamespaceIDsByResourceGroup(t *testing.T, subscriptionID stri } // ListNamespaceAuthRulesE - authenticate namespace client and enumerates all values to get list of authorization rules for the given namespace name, -// automatically crossing page boundaries as required. This function would fail the test if there is an error. -func ListNamespaceAuthRulesE(subscriptionID string, namespace string, resourceGroup string) (*[]string, error) { +// automatically crossing page boundaries as required. +func ListNamespaceAuthRulesE(subscriptionID string, namespace string, resourceGroup string) ([]string, error) { nsClient, err := serviceBusNamespaceClientE(subscriptionID) if err != nil { return nil, err @@ -230,7 +224,7 @@ func ListNamespaceAuthRulesE(subscriptionID string, namespace string, resourceGr return nil, err } - results := make([]string, 0) + results := []string{} for iteratorNamespaceRules.NotDone() { results = append(results, *(iteratorNamespaceRules.Value()).Name) err = iteratorNamespaceRules.Next() @@ -238,20 +232,20 @@ func ListNamespaceAuthRulesE(subscriptionID string, namespace string, resourceGr return nil, err } } - return &results, nil + return results, nil } // ListNamespaceAuthRules - authenticate namespace client and enumerates all values to get list of authorization rules for the given namespace name, -// automatically crossing page boundaries as required. -func ListNamespaceAuthRules(t *testing.T, subscriptionID string, namespace string, resourceGroup string) *[]string { +// automatically crossing page boundaries as required. This function would fail the test if there is an error. +func ListNamespaceAuthRules(t *testing.T, subscriptionID string, namespace string, resourceGroup string) []string { results, err := ListNamespaceAuthRulesE(subscriptionID, namespace, resourceGroup) require.NoError(t, err) return results } -// ListNamespaceTopicsE - authenticate topic client and enumerates all values, automatically crossing page boundaries as required. This function would fail the test if there is an error. -func ListNamespaceTopicsE(subscriptionID string, namespace string, resourceGroup string) (*[]servicebus.SBTopic, error) { +// ListNamespaceTopicsE - authenticate topic client and enumerates all values, automatically crossing page boundaries as required. +func ListNamespaceTopicsE(subscriptionID string, namespace string, resourceGroup string) ([]servicebus.SBTopic, error) { tClient, err := serviceBusTopicClientE(subscriptionID) if err != nil { return nil, err @@ -272,18 +266,18 @@ func ListNamespaceTopicsE(subscriptionID string, namespace string, resourceGroup } } - return &results, nil + return results, nil } -// ListNamespaceTopics - authenticate topic client and enumerates all values, automatically crossing page boundaries as required. -func ListNamespaceTopics(t *testing.T, subscriptionID string, namespace string, resourceGroup string) *[]servicebus.SBTopic { +// ListNamespaceTopics - authenticate topic client and enumerates all values, automatically crossing page boundaries as required. This function would fail the test if there is an error. +func ListNamespaceTopics(t *testing.T, subscriptionID string, namespace string, resourceGroup string) []servicebus.SBTopic { results, err := ListNamespaceTopicsE(subscriptionID, namespace, resourceGroup) require.NoError(t, err) return results } -// ListTopicSubscriptionsE - authenticate subscriptions client and enumerates all values, automatically crossing page boundaries as required. This function would fail the test if there is an error. +// ListTopicSubscriptionsE - authenticate subscriptions client and enumerates all values, automatically crossing page boundaries as required. func ListTopicSubscriptionsE(subscriptionID string, namespace string, resourceGroup string, topicName string) ([]servicebus.SBSubscription, error) { sClient, err := serviceBusSubscriptionsClientE(subscriptionID) if err != nil { @@ -307,17 +301,17 @@ func ListTopicSubscriptionsE(subscriptionID string, namespace string, resourceGr return results, nil } -// ListTopicSubscriptions - authenticate subscriptions client and enumerates all values, automatically crossing page boundaries as required. -func ListTopicSubscriptions(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) *[]servicebus.SBSubscription { +// ListTopicSubscriptions - authenticate subscriptions client and enumerates all values, automatically crossing page boundaries as required. This function would fail the test if there is an error. +func ListTopicSubscriptions(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) []servicebus.SBSubscription { results, err := ListTopicSubscriptionsE(subscriptionID, namespace, resourceGroup, topicName) require.NoError(t, err) - return &results + return results } // ListTopicSubscriptionsNameE - authenticate subscriptions client and enumerates all values to get list of subscriptions for the given topic name, -// automatically crossing page boundaries as required. This function would fail the test if there is an error. -func ListTopicSubscriptionsNameE(subscriptionID string, namespace string, resourceGroup string, topicName string) (*[]string, error) { +// automatically crossing page boundaries as required. +func ListTopicSubscriptionsNameE(subscriptionID string, namespace string, resourceGroup string, topicName string) ([]string, error) { sClient, err := serviceBusSubscriptionsClientE(subscriptionID) if err != nil { return nil, err @@ -328,7 +322,7 @@ func ListTopicSubscriptionsNameE(subscriptionID string, namespace string, resour return nil, err } - results := make([]string, 0) + results := []string{} for iteratorSubscription.NotDone() { results = append(results, *(iteratorSubscription.Value()).Name) err = iteratorSubscription.Next() @@ -336,12 +330,12 @@ func ListTopicSubscriptionsNameE(subscriptionID string, namespace string, resour return nil, err } } - return &results, nil + return results, nil } // ListTopicSubscriptionsName - authenticate subscriptions client and enumerates all values to get list of subscriptions for the given topic name, -// automatically crossing page boundaries as required. -func ListTopicSubscriptionsName(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) *[]string { +// automatically crossing page boundaries as required. This function would fail the test if there is an error. +func ListTopicSubscriptionsName(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) []string { results, err := ListTopicSubscriptionsNameE(subscriptionID, namespace, resourceGroup, topicName) require.NoError(t, err) @@ -349,8 +343,8 @@ func ListTopicSubscriptionsName(t *testing.T, subscriptionID string, namespace s } // ListTopicAuthRulesE - authenticate topic client and enumerates all values to get list of authorization rules for the given topic name, -// automatically crossing page boundaries as required. This function would fail the test if there is an error. -func ListTopicAuthRulesE(subscriptionID string, namespace string, resourceGroup string, topicName string) (*[]string, error) { +// automatically crossing page boundaries as required. +func ListTopicAuthRulesE(subscriptionID string, namespace string, resourceGroup string, topicName string) ([]string, error) { tClient, err := serviceBusTopicClientE(subscriptionID) if err != nil { return nil, err @@ -362,7 +356,7 @@ func ListTopicAuthRulesE(subscriptionID string, namespace string, resourceGroup return nil, err } - results := make([]string, 0) + results := []string{} for iteratorTopicsRules.NotDone() { results = append(results, *(iteratorTopicsRules.Value()).Name) err = iteratorTopicsRules.Next() @@ -370,12 +364,12 @@ func ListTopicAuthRulesE(subscriptionID string, namespace string, resourceGroup return nil, err } } - return &results, nil + return results, nil } // ListTopicAuthRules - authenticate topic client and enumerates all values to get list of authorization rules for the given topic name, -// automatically crossing page boundaries as required. -func ListTopicAuthRules(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) *[]string { +// automatically crossing page boundaries as required. This function would fail the test if there is an error. +func ListTopicAuthRules(t *testing.T, subscriptionID string, namespace string, resourceGroup string, topicName string) []string { results, err := ListTopicAuthRulesE(subscriptionID, namespace, resourceGroup, topicName) require.NoError(t, err) diff --git a/test/azure/terraform_azure_servicebus_example_test.go b/test/azure/terraform_azure_servicebus_example_test.go index 9cd306468..64dd12f53 100644 --- a/test/azure/terraform_azure_servicebus_example_test.go +++ b/test/azure/terraform_azure_servicebus_example_test.go @@ -6,9 +6,9 @@ package test import ( + "os" "strings" "testing" - "os" "github.com/gruntwork-io/terratest/modules/azure" "github.com/gruntwork-io/terratest/modules/random" @@ -20,7 +20,7 @@ func TestTerraformAzureServiceBusExample(t *testing.T) { t.Parallel() uniquePostfix := strings.ToLower(random.UniqueId()) - + // website::tag::1:: Configure Terraform setting up a path to Terraform code. terraformOptions := &terraform.Options{ // The path to where our Terraform code is located @@ -42,27 +42,26 @@ func TestTerraformAzureServiceBusExample(t *testing.T) { expectedResourceGroup := terraform.Output(t, terraformOptions, "resource_group") for topicName, topicsMap := range expectedTopicSubscriptionsMap { - actualsubscriptionNames := azure.ListTopicSubscriptionsName(t, + actualsubscriptionNames := azure.ListTopicSubscriptionsName(t, os.Getenv("ARM_SUBSCRIPTION_ID"), expectedNamespaceName, expectedResourceGroup, topicName) - subscriptionsMap := topicsMap.(map[string]interface{})["subscriptions"].(map[string]interface{}) subscriptionNamesFromOutput := getMapKeylist(subscriptionsMap) // each subscription from the output should also exist in Azure - assert.Equal(t, len(*subscriptionNamesFromOutput), len(*actualsubscriptionNames)) - for _, subscrptionName := range *subscriptionNamesFromOutput { - assert.Contains(t, *actualsubscriptionNames, subscrptionName) + assert.Equal(t, len(subscriptionNamesFromOutput), len(actualsubscriptionNames)) + for _, subscrptionName := range subscriptionNamesFromOutput { + assert.Contains(t, actualsubscriptionNames, subscrptionName) } } } -func getMapKeylist(mapList map[string]interface{}) *[]string { +func getMapKeylist(mapList map[string]interface{}) []string { names := make([]string, 0) for key := range mapList { names = append(names, key) } - return &names + return names } From 9c04d478b6cd7a3527f68dbf2d9fdc5a49a377c2 Mon Sep 17 00:00:00 2001 From: Hadwa Abdelhalem Date: Fri, 24 Sep 2021 11:58:44 -0700 Subject: [PATCH 11/12] fix servicebus_test.go fmt --- modules/azure/servicebus_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/azure/servicebus_test.go b/modules/azure/servicebus_test.go index 25c3aad4a..f96077dd4 100644 --- a/modules/azure/servicebus_test.go +++ b/modules/azure/servicebus_test.go @@ -18,7 +18,7 @@ func TestListServiceBusNamespaceNamesE(t *testing.T) { subscriptionID := "" - _, err := ListServiceBusNamespaceNamesE(subscriptionID) + _, err := ListServiceBusNamespaceNamesE(subscriptionID) require.Error(t, err) } @@ -28,7 +28,7 @@ func TestListServiceBusNamespaceIDsByResourceGroupE(t *testing.T) { subscriptionID := "" resourceGroup := "" - _, err := ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID, resourceGroup) + _, err := ListServiceBusNamespaceIDsByResourceGroupE(subscriptionID, resourceGroup) require.Error(t, err) } @@ -39,7 +39,7 @@ func TestListNamespaceAuthRulesE(t *testing.T) { namespace := "" resourceGroup := "" - _, err := ListNamespaceAuthRulesE(subscriptionID, namespace, resourceGroup) + _, err := ListNamespaceAuthRulesE(subscriptionID, namespace, resourceGroup) require.Error(t, err) } @@ -50,7 +50,7 @@ func TestListNamespaceTopicsE(t *testing.T) { namespace := "" resourceGroup := "" - _, err := ListNamespaceTopicsE(subscriptionID, namespace, resourceGroup) + _, err := ListNamespaceTopicsE(subscriptionID, namespace, resourceGroup) require.Error(t, err) } @@ -62,7 +62,7 @@ func TestListTopicAuthRulesE(t *testing.T) { resourceGroup := "" topicName := "" - _, err := ListTopicAuthRulesE(subscriptionID, namespace, resourceGroup, topicName) + _, err := ListTopicAuthRulesE(subscriptionID, namespace, resourceGroup, topicName) require.Error(t, err) } @@ -76,4 +76,4 @@ func TestListTopicSubscriptionsNameE(t *testing.T) { _, err := ListTopicSubscriptionsNameE(subscriptionID, namespace, resourceGroup, topicName) require.Error(t, err) -} \ No newline at end of file +} From ef72d8d101a4b90340bc1026cdd463afe8c1d5f4 Mon Sep 17 00:00:00 2001 From: Hadwa Abdelhalem Date: Fri, 24 Sep 2021 13:03:36 -0700 Subject: [PATCH 12/12] address pr comments --- modules/azure/servicebus.go | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/modules/azure/servicebus.go b/modules/azure/servicebus.go index 3816f0c21..ca6eab3b2 100644 --- a/modules/azure/servicebus.go +++ b/modules/azure/servicebus.go @@ -56,8 +56,7 @@ func ListServiceBusNamespaceE(subscriptionID string) ([]servicebus.SBNamespace, results := make([]servicebus.SBNamespace, 0) for iteratorSBNamespace.NotDone() { results = append(results, iteratorSBNamespace.Value()) - err = iteratorSBNamespace.Next() - if err != nil { + if err := iteratorSBNamespace.Next(); err != nil { return nil, err } } @@ -153,8 +152,7 @@ func ListServiceBusNamespaceByResourceGroupE(subscriptionID string, resourceGrou for iteratorSBNamespace.NotDone() { results = append(results, iteratorSBNamespace.Value()) - err = iteratorSBNamespace.Next() - if err != nil { + if err := iteratorSBNamespace.Next(); err != nil { return nil, err } } @@ -227,8 +225,7 @@ func ListNamespaceAuthRulesE(subscriptionID string, namespace string, resourceGr results := []string{} for iteratorNamespaceRules.NotDone() { results = append(results, *(iteratorNamespaceRules.Value()).Name) - err = iteratorNamespaceRules.Next() - if err != nil { + if err := iteratorNamespaceRules.Next(); err != nil { return nil, err } } @@ -260,8 +257,7 @@ func ListNamespaceTopicsE(subscriptionID string, namespace string, resourceGroup for iteratorTopics.NotDone() { results = append(results, iteratorTopics.Value()) - err = iteratorTopics.Next() - if err != nil { + if err := iteratorTopics.Next(); err != nil { return nil, err } } @@ -293,8 +289,7 @@ func ListTopicSubscriptionsE(subscriptionID string, namespace string, resourceGr for iteratorSubscription.NotDone() { results = append(results, iteratorSubscription.Value()) - err = iteratorSubscription.Next() - if err != nil { + if err := iteratorSubscription.Next(); err != nil { return nil, err } } @@ -325,8 +320,7 @@ func ListTopicSubscriptionsNameE(subscriptionID string, namespace string, resour results := []string{} for iteratorSubscription.NotDone() { results = append(results, *(iteratorSubscription.Value()).Name) - err = iteratorSubscription.Next() - if err != nil { + if err := iteratorSubscription.Next(); err != nil { return nil, err } } @@ -359,8 +353,7 @@ func ListTopicAuthRulesE(subscriptionID string, namespace string, resourceGroup results := []string{} for iteratorTopicsRules.NotDone() { results = append(results, *(iteratorTopicsRules.Value()).Name) - err = iteratorTopicsRules.Next() - if err != nil { + if err := iteratorTopicsRules.Next(); err != nil { return nil, err } }