Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Resource: azurerm_bot_connection #4311

Merged
merged 5 commits into from
Sep 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions azurerm/internal/services/bot/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@ import (
)

type Client struct {
BotClient *botservice.BotsClient
BotClient *botservice.BotsClient
ConnectionClient *botservice.BotConnectionClient
}

func BuildClient(o *common.ClientOptions) *Client {

BotClient := botservice.NewBotsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&BotClient.Client, o.ResourceManagerAuthorizer)
botClient := botservice.NewBotsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&botClient.Client, o.ResourceManagerAuthorizer)

connectionClient := botservice.NewBotConnectionClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&connectionClient.Client, o.ResourceManagerAuthorizer)

return &Client{
BotClient: &BotClient,
BotClient: &botClient,
ConnectionClient: &connectionClient,
}
}
1 change: 1 addition & 0 deletions azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_batch_application": resourceArmBatchApplication(),
"azurerm_batch_certificate": resourceArmBatchCertificate(),
"azurerm_bot_channels_registration": resourceArmBotChannelsRegistration(),
"azurerm_bot_connection": resourceArmBotConnection(),
"azurerm_batch_pool": resourceArmBatchPool(),
"azurerm_cdn_endpoint": resourceArmCdnEndpoint(),
"azurerm_cdn_profile": resourceArmCdnProfile(),
Expand Down
17 changes: 6 additions & 11 deletions azurerm/resource_arm_bot_channels_registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func resourceArmBotChannelsRegistration() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.CosmosEntityName,
ValidateFunc: validate.NoEmptyStrings,
},

"resource_group_name": azure.SchemaResourceGroupName(),
Expand All @@ -53,7 +53,7 @@ func resourceArmBotChannelsRegistration() *schema.Resource {
Type: schema.TypeString,
ForceNew: true,
Required: true,
ValidateFunc: azure.ValidateResourceID,
ValidateFunc: validate.UUID,
},

"display_name": {
Expand Down Expand Up @@ -109,17 +109,12 @@ func resourceArmBotChannelsRegistrationCreate(d *schema.ResourceData, meta inter
if !utils.ResponseWasNotFound(existing.Response) {
return fmt.Errorf("Error checking for presence of creating Bot Channels Registration %q (Resource Group %q): %+v", name, resourceGroup, err)
}
} else {
id, err := azure.CosmosGetIDFromResponse(existing.Response)
if err != nil {
return fmt.Errorf("Error generating import ID for Bot Channels Registration %q (Resource Group %q): %+v", name, resourceGroup, err)
}

return tf.ImportAsExistsError("azurerm_bot", id)
}
if existing.ID != nil && *existing.ID != "" {
return tf.ImportAsExistsError("azurerm_bot_channels_registration", *existing.ID)
}
}

t := d.Get("tags").(map[string]interface{})
displayName := d.Get("display_name").(string)
if displayName == "" {
displayName = name
Expand All @@ -139,7 +134,7 @@ func resourceArmBotChannelsRegistrationCreate(d *schema.ResourceData, meta inter
Name: botservice.SkuName(d.Get("sku").(string)),
},
Kind: botservice.KindBot,
Tags: tags.Expand(t),
Tags: tags.Expand(d.Get("tags").(map[string]interface{})),
}

if _, err := client.Create(ctx, resourceGroup, name, bot); err != nil {
Expand Down
28 changes: 19 additions & 9 deletions azurerm/resource_arm_bot_channels_registration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,29 @@ import (
func TestAccAzureRMBotChannelsRegistration(t *testing.T) {
// NOTE: this is a combined test rather than separate split out tests due to
// Azure only being able provision against one app id at a time
testCases := map[string]func(t *testing.T){
"basic": testAccAzureRMBotChannelsRegistration_basic,
"update": testAccAzureRMBotChannelsRegistration_update,
"complete": testAccAzureRMBotChannelsRegistration_complete,
testCases := map[string]map[string]func(t *testing.T){
"basic": {
"basic": testAccAzureRMBotChannelsRegistration_basic,
"update": testAccAzureRMBotChannelsRegistration_update,
"complete": testAccAzureRMBotChannelsRegistration_complete,
},
"coonection": {
mbfrahry marked this conversation as resolved.
Show resolved Hide resolved
"basic": testAccAzureRMBotConnection_basic,
"complete": testAccAzureRMBotConnection_complete,
},
}

for name, tc := range testCases {
tc := tc
t.Run(name, func(t *testing.T) {
tc(t)
for group, m := range testCases {
m := m
t.Run(group, func(t *testing.T) {
for name, tc := range m {
tc := tc
t.Run(name, func(t *testing.T) {
tc(t)
})
}
})
}

}

func testAccAzureRMBotChannelsRegistration_basic(t *testing.T) {
Expand Down
262 changes: 262 additions & 0 deletions azurerm/resource_arm_bot_connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
package azurerm

import (
"fmt"
"log"

"github.com/Azure/azure-sdk-for-go/services/preview/botservice/mgmt/2018-07-12/botservice"
"github.com/hashicorp/terraform/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response"
"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/features"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmBotConnection() *schema.Resource {
return &schema.Resource{
Create: resourceArmBotConnectionCreate,
Read: resourceArmBotConnectionRead,
Update: resourceArmBotConnectionUpdate,
Delete: resourceArmBotConnectionDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

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

"location": azure.SchemaLocation(),

"resource_group_name": azure.SchemaResourceGroupName(),

"bot_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validate.NoEmptyStrings,
},

"service_provider_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.NoEmptyStrings,
},

"client_id": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validate.NoEmptyStrings,
},

"client_secret": {
Type: schema.TypeString,
Required: true,
Sensitive: true,
ValidateFunc: validate.NoEmptyStrings,
},

"scopes": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validate.NoEmptyStrings,
},

"parameters": {
Type: schema.TypeMap,
Optional: true,
},

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

func resourceArmBotConnectionCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).bot.ConnectionClient
ctx := meta.(*ArmClient).StopContext

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

if features.ShouldResourcesBeImported() && d.IsNewResource() {
existing, err := client.Get(ctx, resourceGroup, name, botName)
if err != nil {
if !utils.ResponseWasNotFound(existing.Response) {
return fmt.Errorf("Error checking for presence of creating Bot Connection %q (Resource Group %q / Bot %q): %+v", name, resourceGroup, botName, err)
}
}
if existing.ID != nil && *existing.ID != "" {
return tf.ImportAsExistsError("azurerm_bot_connection", *existing.ID)
}
}

connection := botservice.ConnectionSetting{
Properties: &botservice.ConnectionSettingProperties{
ServiceProviderDisplayName: utils.String(d.Get("service_provider_name").(string)),
ClientID: utils.String(d.Get("client_id").(string)),
ClientSecret: utils.String(d.Get("client_secret").(string)),
Scopes: utils.String(d.Get("scopes").(string)),
Parameters: expandAzureRMBotConnectionParameters(d.Get("parameters").(map[string]interface{})),
},
Kind: botservice.KindBot,
Location: utils.String(d.Get("location").(string)),
Tags: tags.Expand(d.Get("tags").(map[string]interface{})),
}

if _, err := client.Create(ctx, resourceGroup, botName, name, connection); err != nil {
return fmt.Errorf("Error issuing create request for creating Bot Connection %q (Resource Group %q / Bot %q): %+v", name, resourceGroup, botName, err)
}

resp, err := client.Get(ctx, resourceGroup, botName, name)
if err != nil {
return fmt.Errorf("Error making get request for Bot Connection %q (Resource Group %q / Bot %q): %+v", name, resourceGroup, botName, err)
}

if resp.ID == nil {
return fmt.Errorf("Cannot read Bot Connection %q (Resource Group %q / Bot %q): %+v", name, resourceGroup, botName, err)
}

d.SetId(*resp.ID)

return resourceArmBotConnectionRead(d, meta)
}

func resourceArmBotConnectionRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).bot.ConnectionClient
ctx := meta.(*ArmClient).StopContext

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

botName := id.Path["botServices"]
name := id.Path["connections"]

resp, err := client.Get(ctx, id.ResourceGroup, botName, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[INFO] Error reading Bot Connection %q (Resource Group %q / Bot %q)", name, id.ResourceGroup, botName)
d.SetId("")
return nil
}

return fmt.Errorf("Error reading Bot Connection %q (Resource Group %q / Bot %q): %+v", name, id.ResourceGroup, botName, err)
}

d.Set("resource_group_name", id.ResourceGroup)
d.Set("name", name)
d.Set("bot_name", botName)
d.Set("location", resp.Location)

if props := resp.Properties; props != nil {
d.Set("client_id", props.ClientID)
d.Set("scopes", props.Scopes)
if parameters := props.Parameters; parameters != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

we can remove this if check and move it inside of the flatten function - since we should return an empty slice in that case so that parameters is always set into the state

if err := d.Set("parameters", flattenAzureRMBotConnectionParameters(parameters)); err != nil {
return fmt.Errorf("Error setting `parameters`: %+v", err)
}
}
}

return tags.FlattenAndSet(d, resp.Tags)
}

func resourceArmBotConnectionUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).bot.ConnectionClient
ctx := meta.(*ArmClient).StopContext

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

connection := botservice.ConnectionSetting{
Properties: &botservice.ConnectionSettingProperties{
ServiceProviderDisplayName: utils.String(d.Get("service_provider_name").(string)),
ClientID: utils.String(d.Get("client_id").(string)),
ClientSecret: utils.String(d.Get("client_secret").(string)),
Scopes: utils.String(d.Get("scopes").(string)),
Parameters: expandAzureRMBotConnectionParameters(d.Get("parameters").(map[string]interface{})),
},
Kind: botservice.KindBot,
Location: utils.String(d.Get("location").(string)),
Tags: tags.Expand(d.Get("tags").(map[string]interface{})),
}

if _, err := client.Update(ctx, resourceGroup, botName, name, connection); err != nil {
return fmt.Errorf("Error issuing update request for creating Bot Connection %q (Resource Group %q / Bot %q): %+v", name, resourceGroup, botName, err)
}

resp, err := client.Get(ctx, resourceGroup, botName, name)
if err != nil {
return fmt.Errorf("Error making get request for Bot Connection %q (Resource Group %q / Bot %q): %+v", name, resourceGroup, botName, err)
}

if resp.ID == nil {
return fmt.Errorf("Cannot read Bot Connection %q (Resource Group %q / Bot %q): %+v", name, resourceGroup, botName, err)
}

d.SetId(*resp.ID)

return resourceArmBotConnectionRead(d, meta)

}

func resourceArmBotConnectionDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).bot.ConnectionClient
ctx := meta.(*ArmClient).StopContext

id, err := azure.ParseAzureResourceID(d.Id())
if err != nil {
return err
}
botName := id.Path["botServices"]
name := id.Path["connections"]

resp, err := client.Delete(ctx, id.ResourceGroup, botName, name)
if err != nil {
if !response.WasNotFound(resp.Response) {
return fmt.Errorf("Error deleting Bot Connection %q (Resource Group %q / Bot %q): %+v", name, id.ResourceGroup, botName, err)
}
}

return nil
}

func expandAzureRMBotConnectionParameters(input map[string]interface{}) *[]botservice.ConnectionSettingParameter {
output := make([]botservice.ConnectionSettingParameter, 0)

for k, v := range input {
output = append(output, botservice.ConnectionSettingParameter{
Key: utils.String(k),
Value: utils.String(v.(string)),
})
}
return &output
}

func flattenAzureRMBotConnectionParameters(input *[]botservice.ConnectionSettingParameter) map[string]interface{} {
output := make(map[string]interface{})

for _, parameter := range *input {
if key := parameter.Key; key != nil {
// We disregard the clientSecret and clientId as one is sensitive and the other is returned in the ClientId attribute.
if *key != "clientSecret" && *key != "clientId" && *key != "scopes" {
if value := parameter.Value; value != nil {
output[*key] = *value
}
}
}
}

return output
}
Loading