From f874617e737b931d9d99096a65dbbfb21f77d9a8 Mon Sep 17 00:00:00 2001 From: john Date: Mon, 20 Jan 2020 16:47:41 +1100 Subject: [PATCH 01/13] Add Directline --- azurerm/internal/services/bot/registration.go | 1 + .../resource_arm_bot_channel_directline.go | 322 ++++++++++++++++++ ...esource_arm_bot_channel_directline_test.go | 142 ++++++++ ...urce_arm_bot_channels_registration_test.go | 10 +- .../docs/r/bot_channel_directline.markdown | 67 ++++ 5 files changed, 538 insertions(+), 4 deletions(-) create mode 100644 azurerm/internal/services/bot/resource_arm_bot_channel_directline.go create mode 100644 azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go create mode 100644 website/docs/r/bot_channel_directline.markdown diff --git a/azurerm/internal/services/bot/registration.go b/azurerm/internal/services/bot/registration.go index a0eadf437cad..67ee57b061c4 100644 --- a/azurerm/internal/services/bot/registration.go +++ b/azurerm/internal/services/bot/registration.go @@ -22,6 +22,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource { "azurerm_bot_channel_email": resourceArmBotChannelEmail(), "azurerm_bot_channel_slack": resourceArmBotChannelSlack(), "azurerm_bot_channel_ms_teams": resourceArmBotChannelMsTeams(), + "azurerm_bot_channel_directline": resourceArmBotChannelDirectline(), "azurerm_bot_channels_registration": resourceArmBotChannelsRegistration(), "azurerm_bot_connection": resourceArmBotConnection(), "azurerm_bot_web_app": resourceArmBotWebApp(), diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go new file mode 100644 index 000000000000..eda31f60573c --- /dev/null +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -0,0 +1,322 @@ +package bot + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/botservice/mgmt/2018-07-12/botservice" + "github.com/hashicorp/go-azure-helpers/response" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmBotChannelDirectline() *schema.Resource { + return &schema.Resource{ + Create: resourceArmBotChannelDirectlineCreate, + Read: resourceArmBotChannelDirectlineRead, + Delete: resourceArmBotChannelDirectlineDelete, + Update: resourceArmBotChannelDirectlineUpdate, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "bot_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "site": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "site_name": { + Type: schema.TypeString, + Required: true, + }, + + "site_id": { + Type: schema.TypeString, + Computed: true, + }, + + "key": { + Type: schema.TypeString, + Computed: true, + }, + + "key2": { + Type: schema.TypeString, + Computed: true, + }, + + "is_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "is_v1_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "is_v3_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "is_secure_site_enabled": { + Type: schema.TypeBool, + Default: false, + Optional: true, + }, + + "trusted_origins": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + } +} + +func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { + + sites := make([]botservice.DirectLineSite, len(input)) + + for i, element := range input { + + site := element.(map[string]interface{}) + if v, ok := site["site_name"]; ok { + siteName := v.(string) + sites[i].SiteName = &siteName + } + if v, ok := site["is_enabled"]; ok { + isEnabled := v.(bool) + sites[i].IsEnabled = &isEnabled + } + if v, ok := site["is_v1_enabled"]; ok { + isV1Enabled := v.(bool) + sites[i].IsV1Enabled = &isV1Enabled + } + if v, ok := site["is_v3_enabled"]; ok { + isV3Enabled := v.(bool) + sites[i].IsV3Enabled = &isV3Enabled + } + if v, ok := site["is_secure_site_enabled"]; ok { + isSecureSiteEnabled := v.(bool) + sites[i].IsSecureSiteEnabled = &isSecureSiteEnabled + } + if v, ok := site["trusted_origins"]; ok { + trustedOrigins := v.([]interface{}) + items := make([]string, len(trustedOrigins)) + for i, raw := range trustedOrigins { + items[i] = raw.(string) + } + sites[i].TrustedOrigins = &items + } + + } + + return &sites, nil +} + +func unExpandSites(input []botservice.DirectLineSite) []interface{} { + + sites := make([]interface{}, len(input)) + + for i, element := range input { + site := make(map[string]interface{}) + site["site_name"] = element.SiteName + site["key"] = element.Key + site["key2"] = element.Key2 + site["is_enabled"] = element.IsEnabled + site["is_v1_enabled"] = element.IsV1Enabled + site["is_v3_enabled"] = element.IsV3Enabled + site["is_secure_site_enabled"] = element.IsSecureSiteEnabled + site["trusted_origins"] = element.TrustedOrigins + + sites[i] = site + } + + return sites +} + +func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.ChannelClient + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + resourceGroup := d.Get("resource_group_name").(string) + botName := d.Get("bot_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, string(botservice.ChannelNameDirectLineChannel1), botName) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of creating Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + } + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_bot_channel_directline", *existing.ID) + } + } + + sites, err := expandSites(d.Get("site").(*schema.Set).List()) + + channel := botservice.BotChannel{ + Properties: botservice.DirectLineChannel{ + Properties: &botservice.DirectLineChannelProperties{ + Sites: sites, + }, + ChannelName: botservice.ChannelNameDirectLineChannel1, + }, + Location: utils.String(azure.NormalizeLocation(d.Get("location").(string))), + Kind: botservice.KindBot, + } + + if _, err := client.Create(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { + return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + if err != nil { + return fmt.Errorf("Error making get request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + if resp.ID == nil { + return fmt.Errorf("Cannot read Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + d.SetId(*resp.ID) + + return resourceArmBotChannelDirectlineRead(d, meta) +} + +func resourceArmBotChannelDirectlineRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.ChannelClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + + botName := id.Path["botServices"] + resp, err := client.Get(ctx, id.ResourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[INFO] Channel Directline for Bot %q (Resource Group %q) was not found - removing from state!", id.ResourceGroup, botName) + d.SetId("") + return nil + } + + return fmt.Errorf("Error reading Channel Directline for Bot %q (Resource Group %q): %+v", id.ResourceGroup, botName, err) + } + + d.Set("resource_group_name", id.ResourceGroup) + d.Set("location", resp.Location) + d.Set("bot_name", botName) + + channelsResp, err := client.ListWithKeys(ctx, id.ResourceGroup, botName, botservice.ChannelNameDirectLineChannel) + if props := channelsResp.Properties; props != nil { + if channel, ok := props.AsDirectLineChannel(); ok { + if channelProps := channel.Properties; channelProps != nil { + d.Set("site", unExpandSites(*channelProps.Sites)) + } + } + } + + return nil +} + +func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.ChannelClient + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + botName := d.Get("bot_name").(string) + resourceGroup := d.Get("resource_group_name").(string) + sites, err := expandSites(d.Get("site").(*schema.Set).List()) + + channel := botservice.BotChannel{ + Properties: botservice.DirectLineChannel{ + Properties: &botservice.DirectLineChannelProperties{ + Sites: sites, + }, + ChannelName: botservice.ChannelNameDirectLineChannel1, + }, + Location: utils.String(azure.NormalizeLocation(d.Get("location").(string))), + Kind: botservice.KindBot, + } + + if _, err := client.Update(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { + return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + if err != nil { + return fmt.Errorf("Error making get request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + if resp.ID == nil { + return fmt.Errorf("Cannot read Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + d.SetId(*resp.ID) + + return resourceArmBotChannelDirectlineRead(d, meta) +} + +func resourceArmBotChannelDirectlineDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.ChannelClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + + botName := id.Path["botServices"] + + resp, err := client.Delete(ctx, id.ResourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + if err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting Channel Directline for Bot %q (Resource Group %q): %+v", id.ResourceGroup, botName, err) + } + } + + return nil +} diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go new file mode 100644 index 000000000000..42a83fabf897 --- /dev/null +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -0,0 +1,142 @@ +package tests + +import ( + "fmt" + "net/http" + "testing" + + "github.com/Azure/azure-sdk-for-go/services/preview/botservice/mgmt/2018-07-12/botservice" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func testAccAzureRMBotChannelDirectline_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_bot_channel_directline", "test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMBotChannelDirectlineDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMBotChannelDirectline_basicConfig(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBotChannelDirectlineExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testAccAzureRMBotChannelDirectline_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_bot_channel_directline", "test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMBotChannelDirectlineDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMBotChannelDirectline_basicConfig(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBotChannelDirectlineExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMBotChannelDirectline_basicUpdate(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBotChannelDirectlineExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testCheckAzureRMBotChannelDirectlineExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Bot.ChannelClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + botName := rs.Primary.Attributes["bot_name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Bot Channel Directline") + } + + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + if err != nil { + return fmt.Errorf("Bad: Get on botChannelClient: %+v", err) + } + + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Bot Channel Directline %q (resource group: %q / bot: %q) does not exist", name, resourceGroup, botName) + } + + return nil + } +} + +func testCheckAzureRMBotChannelDirectlineDestroy(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Bot.ChannelClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_bot_channel_directline" { + continue + } + + botName := rs.Primary.Attributes["bot_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Bot Channel Directline still exists:\n%#v", resp.Properties) + } + } + + return nil +} + +func testAccAzureRMBotChannelDirectline_basicConfig(data acceptance.TestData) string { + template := testAccAzureRMBotChannelsRegistration_basicConfig(data) + return fmt.Sprintf(` +%s + +resource "azurerm_bot_channel_directline" "test" { + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, template) +} + +func testAccAzureRMBotChannelDirectline_basicUpdate(data acceptance.TestData) string { + template := testAccAzureRMBotChannelsRegistration_basicConfig(data) + return fmt.Sprintf(` +%s + +resource "azurerm_bot_channel_directline" "test" { + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + is_enabled = false +} +`, template) +} diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go index 3ac73f98663a..de8ef94f9e29 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go @@ -26,10 +26,12 @@ func TestAccAzureRMBotChannelsRegistration(t *testing.T) { "complete": testAccAzureRMBotConnection_complete, }, "channel": { - "slackBasic": testAccAzureRMBotChannelSlack_basic, - "slackUpdate": testAccAzureRMBotChannelSlack_update, - "msteamsBasic": testAccAzureRMBotChannelMsTeams_basic, - "msteamsUpdate": testAccAzureRMBotChannelMsTeams_update, + "slackBasic": testAccAzureRMBotChannelSlack_basic, + "slackUpdate": testAccAzureRMBotChannelSlack_update, + "msteamsBasic": testAccAzureRMBotChannelMsTeams_basic, + "msteamsUpdate": testAccAzureRMBotChannelMsTeams_update, + "directlineBasic": testAccAzureRMBotChannelDirectline_basic, + "directlineUpdate": testAccAzureRMBotChannelDirectline_update, }, "web_app": { "basic": testAccAzureRMBotWebApp_basic, diff --git a/website/docs/r/bot_channel_directline.markdown b/website/docs/r/bot_channel_directline.markdown new file mode 100644 index 000000000000..9218cc30e98a --- /dev/null +++ b/website/docs/r/bot_channel_directline.markdown @@ -0,0 +1,67 @@ +--- +subcategory: "Bot" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_bot_channel_directline" +description: |- + Manages an Directline integration for a Bot Channel +--- + +# azurerm_bot_connection + +Manages a Directline integration for a Bot Channel + +## Example Usage + +```hcl +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "northeurope" +} + +resource "azurerm_bot_channels_registration" "example" { + name = "example" + location = "global" + resource_group_name = "${azurerm_resource_group.example.name}" + sku = "F0" + microsoft_app_id = "${data.azurerm_client_config.current.service_principal_application_id}" +} + +resource "azurerm_bot_channel_directline" "example" { + bot_name = "${azurerm_bot_channels_registration.example.name}" + location = "${azurerm_bot_channels_registration.example.location}" + resource_group_name = "${azurerm_resource_group.example.name}" + + site { + site_name = "default" + is_enabled = true + } +} +``` + +## Argument Reference + +The following arguments are supported: + +- `resource_group_name` - (Required) The name of the resource group in which to create the Bot Channel. Changing this forces a new resource to be created. + +- `location` - (Required) The supported Azure location where the resource exists. Changing this forces a new resource to be created. + +- `bot_name` - (Required) The name of the Bot Resource this channel will be associated with. Changing this forces a new resource to be created. + +- `site` - (Optional) The sites that belong to this channel. + +## Attributes Reference + +The following attributes are exported: + +- `id` - The Bot Channel ID. + +## Import + +The Microsoft Teams Channel for a Bot can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_bot_channel_ms_teams.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example/providers/Microsoft.BotService/botServices/example/channels/MsTeamsChannel +``` From 9c08648867e7f022a31296d50b7e3692ea0baf2d Mon Sep 17 00:00:00 2001 From: john Date: Mon, 20 Jan 2020 17:40:10 +1100 Subject: [PATCH 02/13] fix tflint errors --- ...resource_arm_bot_channel_directline_test.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index 42a83fabf897..fddc3bf6f246 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -116,27 +116,27 @@ func testCheckAzureRMBotChannelDirectlineDestroy(s *terraform.State) error { func testAccAzureRMBotChannelDirectline_basicConfig(data acceptance.TestData) string { template := testAccAzureRMBotChannelsRegistration_basicConfig(data) - return fmt.Sprintf(` + return fmt.Sprintf(` %s resource "azurerm_bot_channel_directline" "test" { - bot_name = "${azurerm_bot_channels_registration.test.name}" - location = "${azurerm_bot_channels_registration.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" } `, template) } func testAccAzureRMBotChannelDirectline_basicUpdate(data acceptance.TestData) string { template := testAccAzureRMBotChannelsRegistration_basicConfig(data) - return fmt.Sprintf(` + return fmt.Sprintf(` %s resource "azurerm_bot_channel_directline" "test" { - bot_name = "${azurerm_bot_channels_registration.test.name}" - location = "${azurerm_bot_channels_registration.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - is_enabled = false + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + is_enabled = false } `, template) } From eaa2039f8f647c3f2a215a68f4701aa9d55be826 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Mon, 20 Jan 2020 20:01:43 +1100 Subject: [PATCH 03/13] Fix linting errors --- .../bot/resource_arm_bot_channel_directline.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index eda31f60573c..bada6a69cfad 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -111,11 +111,9 @@ func resourceArmBotChannelDirectline() *schema.Resource { } func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { - sites := make([]botservice.DirectLineSite, len(input)) for i, element := range input { - site := element.(map[string]interface{}) if v, ok := site["site_name"]; ok { siteName := v.(string) @@ -145,14 +143,12 @@ func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { } sites[i].TrustedOrigins = &items } - } return &sites, nil } func unExpandSites(input []botservice.DirectLineSite) []interface{} { - sites := make([]interface{}, len(input)) for i, element := range input { @@ -192,7 +188,7 @@ func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interfac } } - sites, err := expandSites(d.Get("site").(*schema.Set).List()) + sites, _ := expandSites(d.Get("site").(*schema.Set).List()) channel := botservice.BotChannel{ Properties: botservice.DirectLineChannel{ @@ -249,7 +245,7 @@ func resourceArmBotChannelDirectlineRead(d *schema.ResourceData, meta interface{ d.Set("location", resp.Location) d.Set("bot_name", botName) - channelsResp, err := client.ListWithKeys(ctx, id.ResourceGroup, botName, botservice.ChannelNameDirectLineChannel) + channelsResp, _ := client.ListWithKeys(ctx, id.ResourceGroup, botName, botservice.ChannelNameDirectLineChannel) if props := channelsResp.Properties; props != nil { if channel, ok := props.AsDirectLineChannel(); ok { if channelProps := channel.Properties; channelProps != nil { @@ -268,7 +264,7 @@ func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interfac botName := d.Get("bot_name").(string) resourceGroup := d.Get("resource_group_name").(string) - sites, err := expandSites(d.Get("site").(*schema.Set).List()) + sites, _ := expandSites(d.Get("site").(*schema.Set).List()) channel := botservice.BotChannel{ Properties: botservice.DirectLineChannel{ From cbba6c0037c05090e3719da9343534f1086c4fae Mon Sep 17 00:00:00 2001 From: John Kendall Date: Mon, 20 Jan 2020 20:59:41 +1100 Subject: [PATCH 04/13] Add sensitive flags to keys --- .../bot/resource_arm_bot_channel_directline.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index bada6a69cfad..a08cd5dd76da 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -63,13 +63,15 @@ func resourceArmBotChannelDirectline() *schema.Resource { }, "key": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, + Sensitive: true, }, "key2": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, + Sensitive: true, }, "is_enabled": { From fef651def293da9bcb08ae1f9775d1c70261676b Mon Sep 17 00:00:00 2001 From: John Kendall Date: Sun, 26 Jan 2020 22:48:36 +1100 Subject: [PATCH 05/13] review feedback response --- .../resource_arm_bot_channel_directline.go | 177 ++++++++++-------- ...esource_arm_bot_channel_directline_test.go | 47 +++++ ...urce_arm_bot_channels_registration_test.go | 13 +- .../docs/r/bot_channel_directline.markdown | 16 +- 4 files changed, 168 insertions(+), 85 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index a08cd5dd76da..219ab8112291 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -53,25 +53,9 @@ func resourceArmBotChannelDirectline() *schema.Resource { Schema: map[string]*schema.Schema{ "site_name": { - Type: schema.TypeString, - Required: true, - }, - - "site_id": { - Type: schema.TypeString, - Computed: true, - }, - - "key": { - Type: schema.TypeString, - Computed: true, - Sensitive: true, - }, - - "key2": { - Type: schema.TypeString, - Computed: true, - Sensitive: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, }, "is_enabled": { @@ -102,9 +86,27 @@ func resourceArmBotChannelDirectline() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, }, }, + + "key": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + + "key2": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + + "site_id": { + Type: schema.TypeString, + Computed: true, + }, }, }, }, @@ -112,64 +114,6 @@ func resourceArmBotChannelDirectline() *schema.Resource { } } -func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { - sites := make([]botservice.DirectLineSite, len(input)) - - for i, element := range input { - site := element.(map[string]interface{}) - if v, ok := site["site_name"]; ok { - siteName := v.(string) - sites[i].SiteName = &siteName - } - if v, ok := site["is_enabled"]; ok { - isEnabled := v.(bool) - sites[i].IsEnabled = &isEnabled - } - if v, ok := site["is_v1_enabled"]; ok { - isV1Enabled := v.(bool) - sites[i].IsV1Enabled = &isV1Enabled - } - if v, ok := site["is_v3_enabled"]; ok { - isV3Enabled := v.(bool) - sites[i].IsV3Enabled = &isV3Enabled - } - if v, ok := site["is_secure_site_enabled"]; ok { - isSecureSiteEnabled := v.(bool) - sites[i].IsSecureSiteEnabled = &isSecureSiteEnabled - } - if v, ok := site["trusted_origins"]; ok { - trustedOrigins := v.([]interface{}) - items := make([]string, len(trustedOrigins)) - for i, raw := range trustedOrigins { - items[i] = raw.(string) - } - sites[i].TrustedOrigins = &items - } - } - - return &sites, nil -} - -func unExpandSites(input []botservice.DirectLineSite) []interface{} { - sites := make([]interface{}, len(input)) - - for i, element := range input { - site := make(map[string]interface{}) - site["site_name"] = element.SiteName - site["key"] = element.Key - site["key2"] = element.Key2 - site["is_enabled"] = element.IsEnabled - site["is_v1_enabled"] = element.IsV1Enabled - site["is_v3_enabled"] = element.IsV3Enabled - site["is_secure_site_enabled"] = element.IsSecureSiteEnabled - site["trusted_origins"] = element.TrustedOrigins - - sites[i] = site - } - - return sites -} - func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Bot.ChannelClient ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) @@ -318,3 +262,80 @@ func resourceArmBotChannelDirectlineDelete(d *schema.ResourceData, meta interfac return nil } + +func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { + sites := make([]botservice.DirectLineSite, len(input)) + + for i, element := range input { + site := element.(map[string]interface{}) + + if v, ok := site["site_name"].(string); ok { + sites[i].SiteName = &v + } + if v, ok := site["is_enabled"].(bool); ok { + sites[i].IsEnabled = &v + } + if v, ok := site["is_v1_enabled"].(bool); ok { + sites[i].IsV1Enabled = &v + } + if v, ok := site["is_v3_enabled"].(bool); ok { + sites[i].IsV3Enabled = &v + } + if v, ok := site["is_secure_site_enabled"].(bool); ok { + sites[i].IsSecureSiteEnabled = &v + } + if v, ok := site["trusted_origins"].([]interface{}); ok { + items := make([]string, len(v)) + for i, raw := range v { + items[i] = raw.(string) + } + sites[i].TrustedOrigins = &items + } + } + + return &sites, nil +} + +func unExpandSites(input []botservice.DirectLineSite) []interface{} { + sites := make([]interface{}, len(input)) + + for i, element := range input { + site := make(map[string]interface{}) + + if element.SiteName != nil { + site["site_name"] = *element.SiteName + } + + if element.Key != nil { + site["key"] = *element.Key + } + + if element.Key2 != nil { + site["key2"] = *element.Key2 + } + + if element.IsEnabled != nil { + site["is_enabled"] = *element.IsEnabled + } + + if element.IsV1Enabled != nil { + site["is_v1_enabled"] = *element.IsV1Enabled + } + + if element.IsV3Enabled != nil { + site["is_v3_enabled"] = *element.IsV3Enabled + } + + if element.IsSecureSiteEnabled != nil { + site["is_secure_site_enabled"] = *element.IsSecureSiteEnabled + } + + if element.TrustedOrigins != nil { + site["trusted_origins"] = *element.TrustedOrigins + } + + sites[i] = site + } + + return sites +} diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index fddc3bf6f246..0bce701508ff 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -32,6 +32,25 @@ func testAccAzureRMBotChannelDirectline_basic(t *testing.T) { }) } +func testAccAzureRMBotChannelDirectline_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_bot_channel_directline", "test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMBotChannelDirectlineDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMBotChannelDirectline_completeConfig(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBotChannelDirectlineExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testAccAzureRMBotChannelDirectline_update(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_bot_channel_directline", "test") @@ -47,6 +66,13 @@ func testAccAzureRMBotChannelDirectline_update(t *testing.T) { ), }, data.ImportStep(), + { + Config: testAccAzureRMBotChannelDirectline_completeConfig(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBotChannelDirectlineExists(data.ResourceName), + ), + }, + data.ImportStep(), { Config: testAccAzureRMBotChannelDirectline_basicUpdate(data), Check: resource.ComposeTestCheckFunc( @@ -127,6 +153,27 @@ resource "azurerm_bot_channel_directline" "test" { `, template) } +func testAccAzureRMBotChannelDirectline_completeConfig(data acceptance.TestData) string { + template := testAccAzureRMBotChannelsRegistration_basicConfig(data) + return fmt.Sprintf(` +%s + +resource "azurerm_bot_channel_directline" "test" { + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + site { + site_name = "test" + is_enabled = true + is_v1_enabled = true + is_v3_enabled = true + is_secure_site_enabled = true + trusted_origins = ["https://example.com"] + } +} +`, template) +} + func testAccAzureRMBotChannelDirectline_basicUpdate(data acceptance.TestData) string { template := testAccAzureRMBotChannelsRegistration_basicConfig(data) return fmt.Sprintf(` diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go index de8ef94f9e29..ff03fc069d7e 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go @@ -26,12 +26,13 @@ func TestAccAzureRMBotChannelsRegistration(t *testing.T) { "complete": testAccAzureRMBotConnection_complete, }, "channel": { - "slackBasic": testAccAzureRMBotChannelSlack_basic, - "slackUpdate": testAccAzureRMBotChannelSlack_update, - "msteamsBasic": testAccAzureRMBotChannelMsTeams_basic, - "msteamsUpdate": testAccAzureRMBotChannelMsTeams_update, - "directlineBasic": testAccAzureRMBotChannelDirectline_basic, - "directlineUpdate": testAccAzureRMBotChannelDirectline_update, + "slackBasic": testAccAzureRMBotChannelSlack_basic, + "slackUpdate": testAccAzureRMBotChannelSlack_update, + "msteamsBasic": testAccAzureRMBotChannelMsTeams_basic, + "msteamsUpdate": testAccAzureRMBotChannelMsTeams_update, + "directlineBasic": testAccAzureRMBotChannelDirectline_basic, + "directlineComplete": testAccAzureRMBotChannelDirectline_complete, + "directlineUpdate": testAccAzureRMBotChannelDirectline_update, }, "web_app": { "basic": testAccAzureRMBotWebApp_basic, diff --git a/website/docs/r/bot_channel_directline.markdown b/website/docs/r/bot_channel_directline.markdown index 9218cc30e98a..450ea6df254f 100644 --- a/website/docs/r/bot_channel_directline.markdown +++ b/website/docs/r/bot_channel_directline.markdown @@ -50,7 +50,21 @@ The following arguments are supported: - `bot_name` - (Required) The name of the Bot Resource this channel will be associated with. Changing this forces a new resource to be created. -- `site` - (Optional) The sites that belong to this channel. +- `site` - (Optional) A site represents a client application that you want to connect to your bot. Multiple `site` blocks may be defined as below + +A `site` block as the following properties: + +- `site_name` - (Required) The name of the site + +- `is_enabled` - (Optional) Enables/Disables this site. Enabled by default + +- `is_v1_enabled` - (Optional) Enables v1 of the Directline protocol for this site. Enabled by default + +- `is_v3_enabled` - (Optional) Enables v3 of the Directline protocol for this site. Enabled by default + +- `is_secure_site_enabled` - (Optional) Enables additional security measures for this site, see [Enhanced Directline Authentication Features](https://blog.botframework.com/2018/09/25/enhanced-direct-line-authentication-features). Disabled by default. + +- `trusted_origins` - (Optional) This field is required when `is_secure_site_enabled` is enabled. Determines which origins can establish a Directline conversation for this site. ## Attributes Reference From 635e2c2cee5ddd8b008d89d1e0a3e4318350c3ec Mon Sep 17 00:00:00 2001 From: John Kendall Date: Mon, 3 Feb 2020 15:43:16 +1100 Subject: [PATCH 06/13] review fixes --- .../resource_arm_bot_channel_directline.go | 50 +++++++++---------- ...esource_arm_bot_channel_directline_test.go | 12 ++--- .../docs/r/bot_channel_directline.markdown | 27 ++++++---- 3 files changed, 47 insertions(+), 42 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index 219ab8112291..8678b9340873 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -52,38 +52,38 @@ func resourceArmBotChannelDirectline() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "site_name": { + "name": { Type: schema.TypeString, Required: true, ValidateFunc: validate.NoEmptyStrings, }, - "is_enabled": { + "enabled": { Type: schema.TypeBool, Optional: true, Default: true, }, - "is_v1_enabled": { + "v1_allowed": { Type: schema.TypeBool, Optional: true, Default: true, }, - "is_v3_enabled": { + "v3_allowed": { Type: schema.TypeBool, Optional: true, Default: true, }, - "is_secure_site_enabled": { + "enhanced_authentication_enabled": { Type: schema.TypeBool, Default: false, Optional: true, }, "trusted_origins": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, @@ -103,7 +103,7 @@ func resourceArmBotChannelDirectline() *schema.Resource { Sensitive: true, }, - "site_id": { + "id": { Type: schema.TypeString, Computed: true, }, @@ -134,12 +134,10 @@ func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interfac } } - sites, _ := expandSites(d.Get("site").(*schema.Set).List()) - channel := botservice.BotChannel{ Properties: botservice.DirectLineChannel{ Properties: &botservice.DirectLineChannelProperties{ - Sites: sites, + Sites: expandDirectlineSites(d.Get("site").(*schema.Set).List()), }, ChannelName: botservice.ChannelNameDirectLineChannel1, }, @@ -195,7 +193,7 @@ func resourceArmBotChannelDirectlineRead(d *schema.ResourceData, meta interface{ if props := channelsResp.Properties; props != nil { if channel, ok := props.AsDirectLineChannel(); ok { if channelProps := channel.Properties; channelProps != nil { - d.Set("site", unExpandSites(*channelProps.Sites)) + d.Set("site", flattenDirectlineSites(*channelProps.Sites)) } } } @@ -210,7 +208,7 @@ func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interfac botName := d.Get("bot_name").(string) resourceGroup := d.Get("resource_group_name").(string) - sites, _ := expandSites(d.Get("site").(*schema.Set).List()) + sites := expandDirectlineSites(d.Get("site").(*schema.Set).List()) channel := botservice.BotChannel{ Properties: botservice.DirectLineChannel{ @@ -263,25 +261,25 @@ func resourceArmBotChannelDirectlineDelete(d *schema.ResourceData, meta interfac return nil } -func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { +func expandDirectlineSites(input []interface{}) *[]botservice.DirectLineSite { sites := make([]botservice.DirectLineSite, len(input)) for i, element := range input { site := element.(map[string]interface{}) - if v, ok := site["site_name"].(string); ok { + if v, ok := site["name"].(string); ok { sites[i].SiteName = &v } - if v, ok := site["is_enabled"].(bool); ok { + if v, ok := site["enabled"].(bool); ok { sites[i].IsEnabled = &v } - if v, ok := site["is_v1_enabled"].(bool); ok { + if v, ok := site["v1_allowed"].(bool); ok { sites[i].IsV1Enabled = &v } - if v, ok := site["is_v3_enabled"].(bool); ok { + if v, ok := site["v3_allowed"].(bool); ok { sites[i].IsV3Enabled = &v } - if v, ok := site["is_secure_site_enabled"].(bool); ok { + if v, ok := site["enhanced_authentication_enabled"].(bool); ok { sites[i].IsSecureSiteEnabled = &v } if v, ok := site["trusted_origins"].([]interface{}); ok { @@ -293,17 +291,17 @@ func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { } } - return &sites, nil + return &sites } -func unExpandSites(input []botservice.DirectLineSite) []interface{} { +func flattenDirectlineSites(input []botservice.DirectLineSite) []interface{} { sites := make([]interface{}, len(input)) for i, element := range input { site := make(map[string]interface{}) - if element.SiteName != nil { - site["site_name"] = *element.SiteName + if v := element.SiteName; v != nil { + site["name"] = *v } if element.Key != nil { @@ -315,19 +313,19 @@ func unExpandSites(input []botservice.DirectLineSite) []interface{} { } if element.IsEnabled != nil { - site["is_enabled"] = *element.IsEnabled + site["enabled"] = *element.IsEnabled } if element.IsV1Enabled != nil { - site["is_v1_enabled"] = *element.IsV1Enabled + site["v1_allowed"] = *element.IsV1Enabled } if element.IsV3Enabled != nil { - site["is_v3_enabled"] = *element.IsV3Enabled + site["v3_allowed"] = *element.IsV3Enabled } if element.IsSecureSiteEnabled != nil { - site["is_secure_site_enabled"] = *element.IsSecureSiteEnabled + site["enhanced_authentication_enabled"] = *element.IsSecureSiteEnabled } if element.TrustedOrigins != nil { diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index 0bce701508ff..b6f6bbc68df1 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -163,11 +163,11 @@ resource "azurerm_bot_channel_directline" "test" { location = "${azurerm_bot_channels_registration.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" site { - site_name = "test" - is_enabled = true - is_v1_enabled = true - is_v3_enabled = true - is_secure_site_enabled = true + name = "test" + enabled = true + v1_allowed = true + v3_allowed = true + enhanced_authentication_enabled = true trusted_origins = ["https://example.com"] } } @@ -183,7 +183,7 @@ resource "azurerm_bot_channel_directline" "test" { bot_name = "${azurerm_bot_channels_registration.test.name}" location = "${azurerm_bot_channels_registration.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - is_enabled = false + enabled = false } `, template) } diff --git a/website/docs/r/bot_channel_directline.markdown b/website/docs/r/bot_channel_directline.markdown index 450ea6df254f..241054e3d702 100644 --- a/website/docs/r/bot_channel_directline.markdown +++ b/website/docs/r/bot_channel_directline.markdown @@ -34,8 +34,8 @@ resource "azurerm_bot_channel_directline" "example" { resource_group_name = "${azurerm_resource_group.example.name}" site { - site_name = "default" - is_enabled = true + name = "default" + enabled = true } } ``` @@ -52,20 +52,27 @@ The following arguments are supported: - `site` - (Optional) A site represents a client application that you want to connect to your bot. Multiple `site` blocks may be defined as below -A `site` block as the following properties: +A `site` block has the following properties: -- `site_name` - (Required) The name of the site +- `name` - (Required) The name of the site -- `is_enabled` - (Optional) Enables/Disables this site. Enabled by default +- `enabled` - (Optional) Enables/Disables this site. Enabled by default -- `is_v1_enabled` - (Optional) Enables v1 of the Directline protocol for this site. Enabled by default +- `v1_allowed` - (Optional) Enables v1 of the Directline protocol for this site. Enabled by default -- `is_v3_enabled` - (Optional) Enables v3 of the Directline protocol for this site. Enabled by default +- `v3_allowed` - (Optional) Enables v3 of the Directline protocol for this site. Enabled by default -- `is_secure_site_enabled` - (Optional) Enables additional security measures for this site, see [Enhanced Directline Authentication Features](https://blog.botframework.com/2018/09/25/enhanced-direct-line-authentication-features). Disabled by default. +- `enhanced_authentication_enabled` - (Optional) Enables additional security measures for this site, see [Enhanced Directline Authentication Features](https://blog.botframework.com/2018/09/25/enhanced-direct-line-authentication-features). Disabled by default. - `trusted_origins` - (Optional) This field is required when `is_secure_site_enabled` is enabled. Determines which origins can establish a Directline conversation for this site. +- `key` - (Computed) Primary key for accessing this site + +- `key2` - (Computed) Secondary key for accessing this site + +- `id` - (Computed) Id for the site + + ## Attributes Reference The following attributes are exported: @@ -74,8 +81,8 @@ The following attributes are exported: ## Import -The Microsoft Teams Channel for a Bot can be imported using the `resource id`, e.g. +The Directline Channel for a Bot can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_bot_channel_ms_teams.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example/providers/Microsoft.BotService/botServices/example/channels/MsTeamsChannel +terraform import azurerm_bot_channel_directline.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example/providers/Microsoft.BotService/botServices/example/channels/DirectlineChannel ``` From d23b08421b52689e565db07bbe578539c2735183 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Mon, 3 Feb 2020 22:01:23 +1100 Subject: [PATCH 07/13] minor fix to directline tests --- .../bot/tests/resource_arm_bot_channel_directline_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index b6f6bbc68df1..1b1db1aba6ce 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -164,7 +164,7 @@ resource "azurerm_bot_channel_directline" "test" { resource_group_name = "${azurerm_resource_group.test.name}" site { name = "test" - enabled = true + enabled = true v1_allowed = true v3_allowed = true enhanced_authentication_enabled = true @@ -183,7 +183,10 @@ resource "azurerm_bot_channel_directline" "test" { bot_name = "${azurerm_bot_channels_registration.test.name}" location = "${azurerm_bot_channels_registration.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - enabled = false + site { + name = "test" + enabled = false + } } `, template) } From 4ea7ed13973492873d9e7606771dea0ec207b459 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Tue, 4 Feb 2020 12:30:53 +1100 Subject: [PATCH 08/13] fix acc test --- .../bot/tests/resource_arm_bot_channel_directline_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index 1b1db1aba6ce..ccbe57ea5b31 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -149,6 +149,10 @@ resource "azurerm_bot_channel_directline" "test" { bot_name = "${azurerm_bot_channels_registration.test.name}" location = "${azurerm_bot_channels_registration.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" + site { + name = "test" + enabled = true + } } `, template) } From 6f7c7720577ca2cfb427cb428ca532b145364281 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Wed, 12 Feb 2020 09:49:07 +1100 Subject: [PATCH 09/13] fix site attributes --- website/docs/r/bot_channel_directline.markdown | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/website/docs/r/bot_channel_directline.markdown b/website/docs/r/bot_channel_directline.markdown index 241054e3d702..33ae413f2072 100644 --- a/website/docs/r/bot_channel_directline.markdown +++ b/website/docs/r/bot_channel_directline.markdown @@ -66,12 +66,6 @@ A `site` block has the following properties: - `trusted_origins` - (Optional) This field is required when `is_secure_site_enabled` is enabled. Determines which origins can establish a Directline conversation for this site. -- `key` - (Computed) Primary key for accessing this site - -- `key2` - (Computed) Secondary key for accessing this site - -- `id` - (Computed) Id for the site - ## Attributes Reference @@ -79,6 +73,16 @@ The following attributes are exported: - `id` - The Bot Channel ID. +--- + +A `site` block exports the following: + +- `key` - Primary key for accessing this site + +- `key2` - Secondary key for accessing this site + +- `id` - Id for the site + ## Import The Directline Channel for a Bot can be imported using the `resource id`, e.g. From 2f4c11727aa86ae6b1f4b4d5731f33076ef19d78 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Wed, 12 Feb 2020 09:54:33 +1100 Subject: [PATCH 10/13] format docs --- website/docs/r/bot_channel_directline.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/bot_channel_directline.markdown b/website/docs/r/bot_channel_directline.markdown index 33ae413f2072..5ac64028af91 100644 --- a/website/docs/r/bot_channel_directline.markdown +++ b/website/docs/r/bot_channel_directline.markdown @@ -34,7 +34,7 @@ resource "azurerm_bot_channel_directline" "example" { resource_group_name = "${azurerm_resource_group.example.name}" site { - name = "default" + name = "default" enabled = true } } From ccde214c3eb589a38453cedbf298c7921cf318bc Mon Sep 17 00:00:00 2001 From: John Kendall Date: Thu, 13 Feb 2020 17:45:23 +1100 Subject: [PATCH 11/13] resolve review comments --- .../resource_arm_bot_channel_directline.go | 59 +++++++++++++++---- ...esource_arm_bot_channel_directline_test.go | 50 ++++++++-------- website/azurerm.erb | 4 ++ 3 files changed, 75 insertions(+), 38 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index 8678b9340873..30b28aa95ed1 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -149,6 +149,12 @@ func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interfac return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } + // Create does not include sites properly, so we need to update as well + time.Sleep(10 * time.Second) + if _, err := client.Update(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { + return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) if err != nil { return fmt.Errorf("Error making get request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) @@ -193,7 +199,7 @@ func resourceArmBotChannelDirectlineRead(d *schema.ResourceData, meta interface{ if props := channelsResp.Properties; props != nil { if channel, ok := props.AsDirectLineChannel(); ok { if channelProps := channel.Properties; channelProps != nil { - d.Set("site", flattenDirectlineSites(*channelProps.Sites)) + d.Set("site", flattenDirectlineSites(filterSites(channelProps.Sites))) } } } @@ -208,12 +214,11 @@ func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interfac botName := d.Get("bot_name").(string) resourceGroup := d.Get("resource_group_name").(string) - sites := expandDirectlineSites(d.Get("site").(*schema.Set).List()) channel := botservice.BotChannel{ Properties: botservice.DirectLineChannel{ Properties: &botservice.DirectLineChannelProperties{ - Sites: sites, + Sites: expandDirectlineSites(d.Get("site").(*schema.Set).List()), }, ChannelName: botservice.ChannelNameDirectLineChannel1, }, @@ -225,6 +230,12 @@ func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interfac return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } + // Create does not include sites properly, so we need to update as well + time.Sleep(10 * time.Second) + if _, err := client.Update(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { + return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) if err != nil { return fmt.Errorf("Error making get request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) @@ -264,31 +275,39 @@ func resourceArmBotChannelDirectlineDelete(d *schema.ResourceData, meta interfac func expandDirectlineSites(input []interface{}) *[]botservice.DirectLineSite { sites := make([]botservice.DirectLineSite, len(input)) - for i, element := range input { + for _, element := range input { + if element == nil { + continue + } + site := element.(map[string]interface{}) + expanded := botservice.DirectLineSite{} if v, ok := site["name"].(string); ok { - sites[i].SiteName = &v + expanded.SiteName = &v } if v, ok := site["enabled"].(bool); ok { - sites[i].IsEnabled = &v + expanded.IsEnabled = &v } if v, ok := site["v1_allowed"].(bool); ok { - sites[i].IsV1Enabled = &v + expanded.IsV1Enabled = &v } if v, ok := site["v3_allowed"].(bool); ok { - sites[i].IsV3Enabled = &v + expanded.IsV3Enabled = &v } if v, ok := site["enhanced_authentication_enabled"].(bool); ok { - sites[i].IsSecureSiteEnabled = &v + expanded.IsSecureSiteEnabled = &v } - if v, ok := site["trusted_origins"].([]interface{}); ok { - items := make([]string, len(v)) - for i, raw := range v { + if v, ok := site["trusted_origins"].(*schema.Set); ok { + origins := v.List() + items := make([]string, len(origins)) + for i, raw := range origins { items[i] = raw.(string) } - sites[i].TrustedOrigins = &items + expanded.TrustedOrigins = &items } + + sites = append(sites, expanded) } return &sites @@ -337,3 +356,17 @@ func flattenDirectlineSites(input []botservice.DirectLineSite) []interface{} { return sites } + +// When creating a new directline channel, a Default Site is created +// There is a race condition where this site is not removed before the create request is completed +func filterSites(sites *[]botservice.DirectLineSite) []botservice.DirectLineSite { + + filtered := make([]botservice.DirectLineSite, 0) + for _, site := range *sites { + if *site.SiteName == "Default Site" { + continue + } + filtered = append(filtered, site) + } + return filtered +} diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index ccbe57ea5b31..94c210e8eabf 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -146,13 +146,13 @@ func testAccAzureRMBotChannelDirectline_basicConfig(data acceptance.TestData) st %s resource "azurerm_bot_channel_directline" "test" { - bot_name = "${azurerm_bot_channels_registration.test.name}" - location = "${azurerm_bot_channels_registration.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - site { - name = "test" - enabled = true - } + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + site { + name = "test" + enabled = true + } } `, template) } @@ -163,17 +163,17 @@ func testAccAzureRMBotChannelDirectline_completeConfig(data acceptance.TestData) %s resource "azurerm_bot_channel_directline" "test" { - bot_name = "${azurerm_bot_channels_registration.test.name}" - location = "${azurerm_bot_channels_registration.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - site { - name = "test" - enabled = true - v1_allowed = true - v3_allowed = true - enhanced_authentication_enabled = true - trusted_origins = ["https://example.com"] - } + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + site { + name = "test" + enabled = true + v1_allowed = true + v3_allowed = true + enhanced_authentication_enabled = true + trusted_origins = ["https://example.com"] + } } `, template) } @@ -184,13 +184,13 @@ func testAccAzureRMBotChannelDirectline_basicUpdate(data acceptance.TestData) st %s resource "azurerm_bot_channel_directline" "test" { - bot_name = "${azurerm_bot_channels_registration.test.name}" - location = "${azurerm_bot_channels_registration.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - site { - name = "test" - enabled = false - } + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + site { + name = "test" + enabled = false + } } `, template) } diff --git a/website/azurerm.erb b/website/azurerm.erb index 648428026d86..4b3538480598 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -846,6 +846,10 @@ azurerm_bot_channel_slack +
  • + azurerm_bot_channel_directline +
  • +
  • azurerm_bot_channels_registration
  • From 08feb94a75739fb2bfd371f960f4eef0625ce100 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Fri, 14 Feb 2020 10:11:53 +1100 Subject: [PATCH 12/13] remove synthentic delays --- .../services/bot/resource_arm_bot_channel_directline.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index 30b28aa95ed1..e33a7f534a30 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -149,8 +149,7 @@ func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interfac return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } - // Create does not include sites properly, so we need to update as well - time.Sleep(10 * time.Second) + // Unable to create a new site with enhanced_authentication_enabled in the same operation, so we need to make two calls if _, err := client.Update(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } @@ -230,8 +229,7 @@ func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interfac return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } - // Create does not include sites properly, so we need to update as well - time.Sleep(10 * time.Second) + // Unable to create a new site with enhanced_authentication_enabled in the same operation, so we need to make two calls if _, err := client.Update(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } From da671823b9722dc4e0bb9ef514106c9802c7f26a Mon Sep 17 00:00:00 2001 From: John Kendall Date: Fri, 14 Feb 2020 10:46:04 +1100 Subject: [PATCH 13/13] Fix whitespace --- .../internal/services/bot/resource_arm_bot_channel_directline.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index e33a7f534a30..b84927665a03 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -358,7 +358,6 @@ func flattenDirectlineSites(input []botservice.DirectLineSite) []interface{} { // When creating a new directline channel, a Default Site is created // There is a race condition where this site is not removed before the create request is completed func filterSites(sites *[]botservice.DirectLineSite) []botservice.DirectLineSite { - filtered := make([]botservice.DirectLineSite, 0) for _, site := range *sites { if *site.SiteName == "Default Site" {