Skip to content

Commit

Permalink
New Resource azurerm_healthbot (#11002)
Browse files Browse the repository at this point in the history
Co-authored-by: kt <[email protected]>
Co-authored-by: Haiyuan Zhang <[email protected]>

Support for Azure health bot Service
  • Loading branch information
haiyuazhang authored Apr 23, 2021
1 parent 9d5d4dc commit 9507698
Show file tree
Hide file tree
Showing 21 changed files with 2,279 additions and 0 deletions.
198 changes: 198 additions & 0 deletions azurerm/internal/services/bot/bot_healthbot_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package bot

import (
"fmt"
"log"
"time"

"github.com/Azure/azure-sdk-for-go/services/healthbot/mgmt/2020-12-08/healthbot"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"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/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/location"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/bot/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/bot/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags"
azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceHealthbotService() *schema.Resource {
return &schema.Resource{
Create: resourceHealthbotServiceCreate,
Read: resourceHealthbotServiceRead,
Update: resourceHealthbotServiceUpdate,
Delete: resourceHealthbotServiceDelete,

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),
},

Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error {
_, err := parse.BotHealthbotID(id)
return err
}),

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.HealthbotName,
},

"resource_group_name": azure.SchemaResourceGroupName(),

"location": azure.SchemaLocation(),

"sku_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
string(healthbot.F0),
string(healthbot.S1),
}, false),
},

"bot_management_portal_url": {
Type: schema.TypeString,
Computed: true,
},

"tags": tags.Schema(),
},
}
}

func resourceHealthbotServiceCreate(d *schema.ResourceData, meta interface{}) error {
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
client := meta.(*clients.Client).Bot.HealthbotClient
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()

name := d.Get("name").(string)
resourceGroup := d.Get("resource_group_name").(string)

id := parse.NewBotHealthbotID(subscriptionId, resourceGroup, name)

if d.IsNewResource() {
existing, err := client.Get(ctx, id.ResourceGroup, id.HealthBotName)
if err != nil {
if !utils.ResponseWasNotFound(existing.Response) {
return fmt.Errorf("checking for existing %s: %+v", id, err)
}
}
if !utils.ResponseWasNotFound(existing.Response) {
return tf.ImportAsExistsError("azurerm_healthbot", id.ID())
}
}

parameters := healthbot.HealthBot{
Location: utils.String(location.Normalize(d.Get("location").(string))),
Sku: &healthbot.Sku{
Name: healthbot.SkuName(d.Get("sku_name").(string)),
},
Tags: tags.Expand(d.Get("tags").(map[string]interface{})),
}

future, err := client.Create(ctx, resourceGroup, name, parameters)
if err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}

if err := future.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("waiting for creation of %s: %+v", id, err)
}

d.SetId(id.ID())

return resourceHealthbotServiceRead(d, meta)
}

func resourceHealthbotServiceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Bot.HealthbotClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.BotHealthbotID(d.Id())
if err != nil {
return err
}

resp, err := client.Get(ctx, id.ResourceGroup, id.HealthBotName)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[INFO] healthbot %q does not exist - removing from state", d.Id())
d.SetId("")
return nil
}
return fmt.Errorf("retrieving %s: %+v", id, err)
}

d.Set("name", id.HealthBotName)
d.Set("resource_group_name", id.ResourceGroup)
d.Set("location", location.NormalizeNilable(resp.Location))

if sku := resp.Sku; sku != nil {
d.Set("sku_name", sku.Name)
}

if props := resp.Properties; props != nil {
d.Set("bot_management_portal_link", props.BotManagementPortalLink)
}
return tags.FlattenAndSet(d, resp.Tags)
}

func resourceHealthbotServiceUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Bot.HealthbotClient
ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.BotHealthbotID(d.Id())
if err != nil {
return err
}

parameters := healthbot.UpdateParameters{}
if d.HasChange("sku_name") {
parameters.Sku = &healthbot.Sku{
Name: healthbot.SkuName(d.Get("sku_name").(string)),
}
}

if d.HasChange("tags") {
parameters.Tags = tags.Expand(d.Get("tags").(map[string]interface{}))
}

if _, err := client.Update(ctx, id.ResourceGroup, id.HealthBotName, parameters); err != nil {
return fmt.Errorf("updating %s: %+v", id, err)
}
return resourceHealthbotServiceRead(d, meta)
}

func resourceHealthbotServiceDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Bot.HealthbotClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

id, err := parse.BotHealthbotID(d.Id())
if err != nil {
return err
}

future, err := client.Delete(ctx, id.ResourceGroup, id.HealthBotName)
if err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}

if err := future.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("waiting for deletion of %s: %+v", id, err)
}
return nil
}
160 changes: 160 additions & 0 deletions azurerm/internal/services/bot/bot_healthbot_resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package bot_test

import (
"context"
"fmt"
"testing"

"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/acceptance/check"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/bot/parse"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

type HealthbotResource struct{}

func TestAccBotHealthbot_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_healthbot", "test")
r := HealthbotResource{}
data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.basic(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccBotHealthbot_requiresImport(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_healthbot", "test")
r := HealthbotResource{}
data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.basic(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.RequiresImportErrorStep(r.requiresImport),
})
}

func TestAccBotHealthbot_complete(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_healthbot", "test")
r := HealthbotResource{}
data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.complete(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccBotHealthbot_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_healthbot", "test")
r := HealthbotResource{}
data.ResourceTest(t, r, []resource.TestStep{
{
Config: r.basic(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.complete(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.basic(data),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func (r HealthbotResource) Exists(ctx context.Context, client *clients.Client, state *terraform.InstanceState) (*bool, error) {
id, err := parse.BotHealthbotID(state.ID)
if err != nil {
return nil, err
}

resp, err := client.Bot.HealthbotClient.Get(ctx, id.ResourceGroup, id.HealthBotName)
if err != nil {
return nil, fmt.Errorf("retrieving Healthbot service %q (resource group: %q): %+v", id.HealthBotName, id.ResourceGroup, err)
}

return utils.Bool(resp.Properties != nil), nil
}

func (r HealthbotResource) template(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctest-healthbot-%d"
location = "%s"
}
`, data.RandomInteger, data.Locations.Primary)
}

func (r HealthbotResource) basic(data acceptance.TestData) string {
template := r.template(data)
return fmt.Sprintf(`
%s
resource "azurerm_healthbot" "test" {
name = "acctest-hb-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
sku_name = "F0"
}
`, template, data.RandomInteger)
}

func (r HealthbotResource) requiresImport(data acceptance.TestData) string {
config := r.basic(data)
return fmt.Sprintf(`
%s
resource "azurerm_healthbot" "import" {
name = azurerm_healthbot.test.name
resource_group_name = azurerm_healthbot.test.resource_group_name
location = azurerm_healthbot.test.location
sku_name = azurerm_healthbot.test.sku_name
}
`, config)
}

func (r HealthbotResource) complete(data acceptance.TestData) string {
template := r.template(data)
return fmt.Sprintf(`
%s
resource "azurerm_healthbot" "test" {
name = "acctest-hb-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
sku_name = "S1"
tags = {
ENV = "Test"
}
}
`, template, data.RandomInteger)
}
6 changes: 6 additions & 0 deletions azurerm/internal/services/bot/client/client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package client

import (
"github.com/Azure/azure-sdk-for-go/services/healthbot/mgmt/2020-12-08/healthbot"
"github.com/Azure/azure-sdk-for-go/services/preview/botservice/mgmt/2018-07-12/botservice"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common"
)
Expand All @@ -9,6 +10,7 @@ type Client struct {
BotClient *botservice.BotsClient
ConnectionClient *botservice.BotConnectionClient
ChannelClient *botservice.ChannelsClient
HealthbotClient *healthbot.BotsClient
}

func NewClient(o *common.ClientOptions) *Client {
Expand All @@ -21,9 +23,13 @@ func NewClient(o *common.ClientOptions) *Client {
channelClient := botservice.NewChannelsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&channelClient.Client, o.ResourceManagerAuthorizer)

healthBotClient := healthbot.NewBotsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&healthBotClient.Client, o.ResourceManagerAuthorizer)

return &Client{
BotClient: &botClient,
ChannelClient: &channelClient,
ConnectionClient: &connectionClient,
HealthbotClient: &healthBotClient,
}
}
Loading

0 comments on commit 9507698

Please sign in to comment.