From 67fac19ce0c043e63b0d2dc61d909313de8a0b46 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Thu, 21 Oct 2021 10:36:40 -0500 Subject: [PATCH 01/10] feat: added bot resource --- internal/services/bot/bot_resource.go | 313 +++++++++++++++++++++ internal/services/bot/bot_resource_test.go | 190 +++++++++++++ internal/services/bot/registration.go | 1 + website/docs/r/bot.html.markdown | 85 ++++++ 4 files changed, 589 insertions(+) create mode 100644 internal/services/bot/bot_resource.go create mode 100644 internal/services/bot/bot_resource_test.go create mode 100644 website/docs/r/bot.html.markdown diff --git a/internal/services/bot/bot_resource.go b/internal/services/bot/bot_resource.go new file mode 100644 index 000000000000..56b493587eb9 --- /dev/null +++ b/internal/services/bot/bot_resource.go @@ -0,0 +1,313 @@ +package bot + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/botservice/mgmt/2021-03-01/botservice" + "github.com/hashicorp/go-azure-helpers/response" + "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" + "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/location" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/bot/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tags" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +func resourceBot() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceBotCreate, + Read: resourceBotRead, + Update: resourceBotUpdate, + Delete: resourceBotDelete, + Importer: pluginsdk.ImporterValidatingResourceIdThen(func(id string) error { + _, err := parse.BotServiceID(id) + return err + }, func(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) ([]*pluginsdk.ResourceData, error) { + client := meta.(*clients.Client).Bot.BotClient + + id, err := parse.BotServiceID(d.Id()) + if err != nil { + return nil, err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil, fmt.Errorf("Bot %q was not found in Resource Group %q", id.Name, id.ResourceGroup) + } + + return nil, fmt.Errorf("retrieving Bot %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + } + + return []*pluginsdk.ResourceData{d}, nil + }), + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(30 * time.Minute), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Update: pluginsdk.DefaultTimeout(30 * time.Minute), + Delete: pluginsdk.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "kind": { + Type: pluginsdk.TypeString, + Optional: true, + Default: string(botservice.KindAzurebot), // Azure Bot + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(botservice.KindAzurebot), + string(botservice.KindBot), + string(botservice.KindDesigner), + string(botservice.KindFunction), + string(botservice.KindSdk), + }, false), + }, + + "sku": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(botservice.SkuNameF0), + string(botservice.SkuNameS1), + }, false), + }, + + "microsoft_app_id": { + Type: pluginsdk.TypeString, + ForceNew: true, + Required: true, + ValidateFunc: validation.IsUUID, + }, + + "display_name": { + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "endpoint": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "developer_app_insights_key": { + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.IsUUID, + }, + + "developer_app_insights_api_key": { + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + Sensitive: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "developer_app_insights_application_id": { + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.IsUUID, + }, + + "luis_app_ids": { + Type: pluginsdk.TypeList, + Optional: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: validation.IsUUID, + }, + }, + + "luis_key": { + Type: pluginsdk.TypeString, + Optional: true, + Sensitive: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceBotCreate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.BotClient + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + resourceId := parse.NewBotServiceID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + if d.IsNewResource() { + existing, err := client.Get(ctx, resourceId.ResourceGroup, resourceId.Name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of creating Bot %q (Resource Group %q): %+v", resourceId.Name, resourceId.ResourceGroup, err) + } + } + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_bot", resourceId.ID()) + } + } + + displayName := d.Get("display_name").(string) + if displayName == "" { + displayName = resourceId.Name + } + + bot := botservice.Bot{ + Properties: &botservice.BotProperties{ + DisplayName: utils.String(displayName), + Endpoint: utils.String(d.Get("endpoint").(string)), + MsaAppID: utils.String(d.Get("microsoft_app_id").(string)), + DeveloperAppInsightKey: utils.String(d.Get("developer_app_insights_key").(string)), + DeveloperAppInsightsAPIKey: utils.String(d.Get("developer_app_insights_api_key").(string)), + DeveloperAppInsightsApplicationID: utils.String(d.Get("developer_app_insights_application_id").(string)), + LuisAppIds: utils.ExpandStringSlice(d.Get("luis_app_ids").([]interface{})), + LuisKey: utils.String(d.Get("luis_key").(string)), + }, + Location: utils.String(d.Get("location").(string)), + Sku: &botservice.Sku{ + Name: botservice.SkuName(d.Get("sku").(string)), + }, + Kind: botservice.Kind(d.Get("kind").(string)), + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), + } + + if _, err := client.Create(ctx, resourceId.ResourceGroup, resourceId.Name, bot); err != nil { + return fmt.Errorf("creating Bot %q (Resource Group %q): %+v", resourceId.Name, resourceId.ResourceGroup, err) + } + + // TODO: in 3.0 we should remove the "Default Site" on the Directline resource at this point if we can + + d.SetId(resourceId.ID()) + return resourceBotRead(d, meta) +} + +func resourceBotRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.BotClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.BotServiceID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[INFO] Bot %q was not found in Resource Group %q - removing from state", id.Name, id.ResourceGroup) + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving Bot %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + } + + d.Set("name", id.Name) + d.Set("resource_group_name", id.ResourceGroup) + d.Set("location", location.NormalizeNilable(resp.Location)) + + if sku := resp.Sku; sku != nil { + d.Set("sku", string(sku.Name)) + } + + d.Set("kind", resp.Kind) + + if props := resp.Properties; props != nil { + d.Set("microsoft_app_id", props.MsaAppID) + d.Set("endpoint", props.Endpoint) + d.Set("display_name", props.DisplayName) + d.Set("developer_app_insights_key", props.DeveloperAppInsightKey) + d.Set("developer_app_insights_application_id", props.DeveloperAppInsightsApplicationID) + d.Set("luis_app_ids", props.LuisAppIds) + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceBotUpdate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.BotClient + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.BotServiceID(d.Id()) + if err != nil { + return err + } + + displayName := d.Get("display_name").(string) + if displayName == "" { + displayName = id.Name + } + + bot := botservice.Bot{ + Properties: &botservice.BotProperties{ + DisplayName: utils.String(displayName), + Endpoint: utils.String(d.Get("endpoint").(string)), + MsaAppID: utils.String(d.Get("microsoft_app_id").(string)), + DeveloperAppInsightKey: utils.String(d.Get("developer_app_insights_key").(string)), + DeveloperAppInsightsAPIKey: utils.String(d.Get("developer_app_insights_api_key").(string)), + DeveloperAppInsightsApplicationID: utils.String(d.Get("developer_app_insights_application_id").(string)), + LuisAppIds: utils.ExpandStringSlice(d.Get("luis_app_ids").([]interface{})), + LuisKey: utils.String(d.Get("luis_key").(string)), + }, + Location: utils.String(d.Get("location").(string)), + Sku: &botservice.Sku{ + Name: botservice.SkuName(d.Get("sku").(string)), + }, + Kind: botservice.Kind(d.Get("kind").(string)), + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), + } + + if _, err := client.Update(ctx, id.ResourceGroup, id.Name, bot); err != nil { + return fmt.Errorf("updating Bot %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + } + + return resourceBotRead(d, meta) +} + +func resourceBotDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.BotClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.BotServiceID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Delete(ctx, id.ResourceGroup, id.Name) + if err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("deleting Bot %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + } + } + + return nil +} diff --git a/internal/services/bot/bot_resource_test.go b/internal/services/bot/bot_resource_test.go new file mode 100644 index 000000000000..0696fb78a5e5 --- /dev/null +++ b/internal/services/bot/bot_resource_test.go @@ -0,0 +1,190 @@ +package bot_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/bot/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type BotResource struct { +} + +func TestAccBot_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_bot", "test") + r := BotResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.basicConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("kind").HasValue("azurebot"), + ), + }, + data.ImportStep("developer_app_insights_api_key"), + }) +} + +func TestAccBot_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_bot", "test") + r := BotResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.basicConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("kind").HasValue("azurebot"), + ), + }, + data.ImportStep("developer_app_insights_api_key"), + { + Config: r.updateConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("kind").HasValue("sdk"), + ), + }, + data.ImportStep("developer_app_insights_api_key"), + }) +} + +func TestAccBot_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_bot", "test") + r := BotResource{} + + data.ResourceSequentialTest(t, r, []acceptance.TestStep{ + { + Config: r.completeConfig(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("kind").HasValue("azurebot"), + ), + }, + data.ImportStep("developer_app_insights_api_key"), + }) +} + +func (t BotResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := parse.BotServiceID(state.ID) + if err != nil { + return nil, err + } + + resp, err := clients.Bot.BotClient.Get(ctx, id.ResourceGroup, id.Name) + if err != nil { + return nil, fmt.Errorf("retrieving %s: %v", id.String(), err) + } + + return utils.Bool(resp.Properties != nil), nil +} + +func (BotResource) basicConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +data "azurerm_client_config" "current" { +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_bot" "test" { + name = "acctestdf%d" + location = "global" + resource_group_name = azurerm_resource_group.test.name + sku = "F0" + microsoft_app_id = data.azurerm_client_config.current.client_id + + tags = { + environment = "production" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} + +func (BotResource) updateConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +data "azurerm_client_config" "current" { +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_bot" "test" { + name = "acctestdf%d" + location = "global" + resource_group_name = azurerm_resource_group.test.name + sku = "F0" + kind = "sdk" + microsoft_app_id = data.azurerm_client_config.current.client_id + + tags = { + environment = "production" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} + +func (BotResource) completeConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +data "azurerm_client_config" "current" { +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestappinsights-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + application_type = "web" +} + +resource "azurerm_application_insights_api_key" "test" { + name = "acctestappinsightsapikey-%d" + application_insights_id = azurerm_application_insights.test.id + read_permissions = ["aggregate", "api", "draft", "extendqueries", "search"] +} + +resource "azurerm_bot" "test" { + name = "acctestdf%d" + location = "global" + resource_group_name = azurerm_resource_group.test.name + microsoft_app_id = data.azurerm_client_config.current.client_id + sku = "F0" + kind = "azurebot" + + endpoint = "https://example.com" + developer_app_insights_api_key = azurerm_application_insights_api_key.test.api_key + developer_app_insights_application_id = azurerm_application_insights.test.app_id + + tags = { + environment = "production" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} diff --git a/internal/services/bot/registration.go b/internal/services/bot/registration.go index aa32e8688435..e7ef6b9b42e5 100644 --- a/internal/services/bot/registration.go +++ b/internal/services/bot/registration.go @@ -40,5 +40,6 @@ func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { "azurerm_bot_connection": resourceArmBotConnection(), "azurerm_healthbot": resourceHealthbotService(), "azurerm_bot_web_app": resourceBotWebApp(), + "azurerm_bot": resourceBot(), } } diff --git a/website/docs/r/bot.html.markdown b/website/docs/r/bot.html.markdown new file mode 100644 index 000000000000..686a77fce924 --- /dev/null +++ b/website/docs/r/bot.html.markdown @@ -0,0 +1,85 @@ +--- +subcategory: "Bot" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_bot" +description: |- + Manages a Bot. +--- + +# azurerm_bot + +Manages a Bot. + +## Example Usage + +```hcl +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_bot" "example" { + name = "example" + location = "global" + resource_group_name = azurerm_resource_group.example.name + sku = "F0" + microsoft_app_id = "${data.azurerm_client_config.current.client_id}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the Bot. Changing this forces a new resource to be created. Must be globally unique. + +* `resource_group_name` - (Required) The name of the resource group in which to create the Bot. 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. + +* `sku` - (Required) The SKU of the Bot. Valid values include `F0` or `S1`. Changing this forces a new resource to be created. + +* `microsoft_app_id` - (Required) The Microsoft Application ID for the Bot. Changing this forces a new resource to be created. + +* `kind` - (Optional) The kind of Bot to create. This defaults to `azurebot` if not specified. Available values are `azurebot`, `bot`, `designer`, `function`, and `sdk`. + +* `display_name` - (Optional) The name of the Bot will be displayed as. This defaults to `name` if not specified. + +* `endpoint` - (Optional) The Bot endpoint. + +* `developer_app_insights_key` - (Optional) The Application Insights Key to associate with the Bot. + +* `developer_app_insights_api_key` - (Optional) The Application Insights API Key to associate with the Bot. + +* `developer_app_insights_application_id` - (Optional) The Application Insights Application ID to associate with the Bot. + +* `luis_app_ids` - (Optional) A list of LUIS App IDs to associate with the Bot. + +* `luis_key` - (Optional) The LUIS key to associate with the Bot. + +* `tags` - (Optional) A mapping of tags to assign to the resource. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Bot. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Bot. +* `update` - (Defaults to 30 minutes) Used when updating the Bot. +* `read` - (Defaults to 5 minutes) Used when retrieving the Bot. +* `delete` - (Defaults to 30 minutes) Used when deleting the Bot. + +## Import + +Bot's can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_bot.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example/providers/Microsoft.BotService/botServices/example +``` From da1baf531b757a4ef06d55dd647803832c0b512f Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Fri, 5 Nov 2021 14:17:46 -1000 Subject: [PATCH 02/10] Update internal/services/bot/bot_resource.go Co-authored-by: stephybun --- internal/services/bot/bot_resource.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/services/bot/bot_resource.go b/internal/services/bot/bot_resource.go index 56b493587eb9..16b7aa021602 100644 --- a/internal/services/bot/bot_resource.go +++ b/internal/services/bot/bot_resource.go @@ -40,10 +40,10 @@ func resourceBot() *pluginsdk.Resource { resp, err := client.Get(ctx, id.ResourceGroup, id.Name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - return nil, fmt.Errorf("Bot %q was not found in Resource Group %q", id.Name, id.ResourceGroup) + return nil, fmt.Errorf("%s was not found", *id) } - return nil, fmt.Errorf("retrieving Bot %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + return nil, fmt.Errorf("retrieving %s: %+v", *id, err) } return []*pluginsdk.ResourceData{d}, nil From 9a30ce4dd7afde3b53c096ebb68fcabc7a0013d1 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Fri, 5 Nov 2021 14:18:04 -1000 Subject: [PATCH 03/10] Update internal/services/bot/bot_resource.go Co-authored-by: stephybun --- internal/services/bot/bot_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/bot/bot_resource.go b/internal/services/bot/bot_resource.go index 16b7aa021602..db08b75ba85c 100644 --- a/internal/services/bot/bot_resource.go +++ b/internal/services/bot/bot_resource.go @@ -166,7 +166,7 @@ func resourceBotCreate(d *pluginsdk.ResourceData, meta interface{}) error { existing, err := client.Get(ctx, resourceId.ResourceGroup, resourceId.Name) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("checking for presence of creating Bot %q (Resource Group %q): %+v", resourceId.Name, resourceId.ResourceGroup, err) + return fmt.Errorf("checking for presence of %s: %+v", resourceId, err) } } if existing.ID != nil && *existing.ID != "" { From bb5b1a8dcf3c4a6a70ce0c61962d78e2907879ad Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Fri, 5 Nov 2021 14:18:13 -1000 Subject: [PATCH 04/10] Update internal/services/bot/bot_resource.go Co-authored-by: stephybun --- internal/services/bot/bot_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/bot/bot_resource.go b/internal/services/bot/bot_resource.go index db08b75ba85c..a3eccec54ca5 100644 --- a/internal/services/bot/bot_resource.go +++ b/internal/services/bot/bot_resource.go @@ -199,7 +199,7 @@ func resourceBotCreate(d *pluginsdk.ResourceData, meta interface{}) error { } if _, err := client.Create(ctx, resourceId.ResourceGroup, resourceId.Name, bot); err != nil { - return fmt.Errorf("creating Bot %q (Resource Group %q): %+v", resourceId.Name, resourceId.ResourceGroup, err) + return fmt.Errorf("creating %s: %+v", resourceId, err) } // TODO: in 3.0 we should remove the "Default Site" on the Directline resource at this point if we can From 3200e4be52d9df8609d71395e30b7081de769469 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Fri, 5 Nov 2021 14:18:23 -1000 Subject: [PATCH 05/10] Update internal/services/bot/bot_resource.go Co-authored-by: stephybun --- internal/services/bot/bot_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/bot/bot_resource.go b/internal/services/bot/bot_resource.go index a3eccec54ca5..7064ec3c80ae 100644 --- a/internal/services/bot/bot_resource.go +++ b/internal/services/bot/bot_resource.go @@ -221,7 +221,7 @@ func resourceBotRead(d *pluginsdk.ResourceData, meta interface{}) error { resp, err := client.Get(ctx, id.ResourceGroup, id.Name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[INFO] Bot %q was not found in Resource Group %q - removing from state", id.Name, id.ResourceGroup) + log.Printf("[INFO] %s was not found - removing from state", *id) d.SetId("") return nil } From 8d9fd1c1fbbc2ead0c13ef2cac56b7300cef2309 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Fri, 5 Nov 2021 14:18:30 -1000 Subject: [PATCH 06/10] Update internal/services/bot/bot_resource.go Co-authored-by: stephybun --- internal/services/bot/bot_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/bot/bot_resource.go b/internal/services/bot/bot_resource.go index 7064ec3c80ae..6f875e713937 100644 --- a/internal/services/bot/bot_resource.go +++ b/internal/services/bot/bot_resource.go @@ -226,7 +226,7 @@ func resourceBotRead(d *pluginsdk.ResourceData, meta interface{}) error { return nil } - return fmt.Errorf("retrieving Bot %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", *id, err) } d.Set("name", id.Name) From 7a0df41e43c3b95cf4bbae06f44ca1f74dfc42f0 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Fri, 5 Nov 2021 14:18:43 -1000 Subject: [PATCH 07/10] Update internal/services/bot/bot_resource.go Co-authored-by: stephybun --- internal/services/bot/bot_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/bot/bot_resource.go b/internal/services/bot/bot_resource.go index 6f875e713937..6baf87dd481c 100644 --- a/internal/services/bot/bot_resource.go +++ b/internal/services/bot/bot_resource.go @@ -286,7 +286,7 @@ func resourceBotUpdate(d *pluginsdk.ResourceData, meta interface{}) error { } if _, err := client.Update(ctx, id.ResourceGroup, id.Name, bot); err != nil { - return fmt.Errorf("updating Bot %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + return fmt.Errorf("updating %s: %+v", *id, err) } return resourceBotRead(d, meta) From cfaebbaae473a0dcfba7dd21cdd421721a253423 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Fri, 5 Nov 2021 14:18:51 -1000 Subject: [PATCH 08/10] Update internal/services/bot/bot_resource.go Co-authored-by: stephybun --- internal/services/bot/bot_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/bot/bot_resource.go b/internal/services/bot/bot_resource.go index 6baf87dd481c..0b2660028a9f 100644 --- a/internal/services/bot/bot_resource.go +++ b/internal/services/bot/bot_resource.go @@ -305,7 +305,7 @@ func resourceBotDelete(d *pluginsdk.ResourceData, meta interface{}) error { resp, err := client.Delete(ctx, id.ResourceGroup, id.Name) if err != nil { if !response.WasNotFound(resp.Response) { - return fmt.Errorf("deleting Bot %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + return fmt.Errorf("deleting %s: %+v", id, err) } } From 027112c49277e5dbd2c9c0410ed1e9ef97509b88 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Fri, 5 Nov 2021 14:18:57 -1000 Subject: [PATCH 09/10] Update internal/services/bot/bot_resource_test.go Co-authored-by: stephybun --- internal/services/bot/bot_resource_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/bot/bot_resource_test.go b/internal/services/bot/bot_resource_test.go index 0696fb78a5e5..2933d5f2cbf2 100644 --- a/internal/services/bot/bot_resource_test.go +++ b/internal/services/bot/bot_resource_test.go @@ -80,7 +80,7 @@ func (t BotResource) Exists(ctx context.Context, clients *clients.Client, state resp, err := clients.Bot.BotClient.Get(ctx, id.ResourceGroup, id.Name) if err != nil { - return nil, fmt.Errorf("retrieving %s: %v", id.String(), err) + return nil, fmt.Errorf("retrieving %s: %v", *id, err) } return utils.Bool(resp.Properties != nil), nil From 556c691a2421dc2717984d31729bc60e49906b33 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Fri, 5 Nov 2021 14:24:13 -1000 Subject: [PATCH 10/10] changed to ImporterValidatingResourceId --- internal/services/bot/bot_resource.go | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/internal/services/bot/bot_resource.go b/internal/services/bot/bot_resource.go index 0b2660028a9f..f5e3beccaf3f 100644 --- a/internal/services/bot/bot_resource.go +++ b/internal/services/bot/bot_resource.go @@ -26,27 +26,9 @@ func resourceBot() *pluginsdk.Resource { Read: resourceBotRead, Update: resourceBotUpdate, Delete: resourceBotDelete, - Importer: pluginsdk.ImporterValidatingResourceIdThen(func(id string) error { + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { _, err := parse.BotServiceID(id) return err - }, func(ctx context.Context, d *pluginsdk.ResourceData, meta interface{}) ([]*pluginsdk.ResourceData, error) { - client := meta.(*clients.Client).Bot.BotClient - - id, err := parse.BotServiceID(d.Id()) - if err != nil { - return nil, err - } - - resp, err := client.Get(ctx, id.ResourceGroup, id.Name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return nil, fmt.Errorf("%s was not found", *id) - } - - return nil, fmt.Errorf("retrieving %s: %+v", *id, err) - } - - return []*pluginsdk.ResourceData{d}, nil }), Timeouts: &pluginsdk.ResourceTimeout{