Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Aris van Ommeren committed Apr 10, 2020
1 parent 950fbaf commit 848ec44
Show file tree
Hide file tree
Showing 6 changed files with 672 additions and 0 deletions.
40 changes: 40 additions & 0 deletions azurerm/internal/services/web/function_app_slot.go
@@ -0,0 +1,40 @@
package web

import (
"fmt"

"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
)

type FunctionAppSlotResourceID struct {
ResourceGroup string
FunctionAppName string
Name string
}

func ParseFunctionAppSlotID(input string) (*FunctionAppSlotResourceID, error) {
id, err := azure.ParseAzureResourceID(input)
if err != nil {
return nil, fmt.Errorf("[ERROR] Unable to parse App Service Slot ID %q: %+v", input, err)
}

slot := FunctionAppSlotResourceID{
ResourceGroup: id.ResourceGroup,
FunctionAppName: id.Path["sites"],
Name: id.Path["slots"],
}

if slot.FunctionAppName, err = id.PopSegment("sites"); err != nil {
return nil, err
}

if slot.Name, err = id.PopSegment("slots"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &slot, nil
}
1 change: 1 addition & 0 deletions azurerm/internal/services/web/registration.go
Expand Up @@ -44,5 +44,6 @@ func (r Registration) SupportedResources() map[string]*schema.Resource {
"azurerm_app_service_virtual_network_swift_connection": resourceArmAppServiceVirtualNetworkSwiftConnection(),
"azurerm_app_service": resourceArmAppService(),
"azurerm_function_app": resourceArmFunctionApp(),
"azurerm_function_app_slot": resourceArmFunctionAppSlot(),
}
}
216 changes: 216 additions & 0 deletions azurerm/internal/services/web/resource_arm_function_slot.go
@@ -0,0 +1,216 @@
package web

import (
"fmt"
"log"
"time"

"github.com/Azure/azure-sdk-for-go/services/web/mgmt/2019-08-01/web"
"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/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features"
"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 resourceArmFunctionAppSlot() *schema.Resource {
return &schema.Resource{
Create: resourceArmFunctionAppSlotCreateUpdate,
Read: resourceArmFunctionAppSlotRead,
Update: resourceArmFunctionAppSlotCreateUpdate,
Delete: resourceArmFunctionAppSlotDelete,
Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error {
_, err := ParseFunctionAppSlotID(id)
return err
}),

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{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"resource_group_name": azure.SchemaResourceGroupName(),

"location": azure.SchemaLocation(),

"function_app_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"app_service_plan_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

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

func resourceArmFunctionAppSlotCreateUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Web.AppServicesClient
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()

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

if features.ShouldResourcesBeImported() && d.IsNewResource() {
existing, err := client.GetSlot(ctx, resourceGroup, functionAppName, slot)
if err != nil {
if !utils.ResponseWasNotFound(existing.Response) {
return fmt.Errorf("Error checking for presence of existing Slot %q (Function App %q / Resource Group %q): %s", slot, functionAppName, resourceGroup, err)
}
}

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

location := azure.NormalizeLocation(d.Get("location").(string))
appServicePlanId := d.Get("app_service_plan_id").(string)
t := d.Get("tags").(map[string]interface{})

siteEnvelope := web.Site{
Location: &location,
Tags: tags.Expand(t),
SiteProperties: &web.SiteProperties{
ServerFarmID: utils.String(appServicePlanId),
},
}

createFuture, err := client.CreateOrUpdateSlot(ctx, resourceGroup, functionAppName, siteEnvelope, slot)
if err != nil {
return fmt.Errorf("Error creating Slot %q (Function App %q / Resource Group %q): %s", slot, functionAppName, resourceGroup, err)
}

err = createFuture.WaitForCompletionRef(ctx, client.Client)
if err != nil {
return fmt.Errorf("Error waiting for creation of Slot %q (Function App %q / Resource Group %q): %s", slot, functionAppName, resourceGroup, err)
}

read, err := client.GetSlot(ctx, resourceGroup, functionAppName, slot)
if err != nil {
return fmt.Errorf("Error retrieving Slot %q (Function App %q / Resource Group %q): %s", slot, functionAppName, resourceGroup, err)
}

if read.ID == nil {
return fmt.Errorf("Cannot read ID for Slot %q (Function App %q / Resource Group %q) ID", slot, functionAppName, resourceGroup)
}

d.SetId(*read.ID)

return resourceArmFunctionAppSlotUpdate(d, meta)
}

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

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

location := azure.NormalizeLocation(d.Get("location").(string))
appServicePlanId := d.Get("app_service_plan_id").(string)
t := d.Get("tags").(map[string]interface{})

siteEnvelope := web.Site{
Location: &location,
Tags: tags.Expand(t),
SiteProperties: &web.SiteProperties{
ServerFarmID: utils.String(appServicePlanId),
},
}

createFuture, err := client.CreateOrUpdateSlot(ctx, id.ResourceGroup, id.FunctionAppName, siteEnvelope, id.Name)
if err != nil {
return fmt.Errorf("Error updating Slot %q (Function App %q / Resource Group %q): %s", id.Name, id.FunctionAppName, id.ResourceGroup, err)
}

err = createFuture.WaitForCompletionRef(ctx, client.Client)
if err != nil {
return fmt.Errorf("Error waiting for update of Slot %q (Function App %q / Resource Group %q): %s", id.Name, id.FunctionAppName, id.ResourceGroup, err)
}

return resourceArmFunctionAppSlotRead(d, meta)
}

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

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

resp, err := client.GetSlot(ctx, id.ResourceGroup, id.FunctionAppName, id.Name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[DEBUG] Slot %q (Function App %q / Resource Group %q) were not found - removing from state!", id.Name, id.FunctionAppName, id.ResourceGroup)
d.SetId("")
return nil
}

return fmt.Errorf("Error reading Slot %q (Function App %q / Resource Group %q): %s", id.Name, id.FunctionAppName, id.ResourceGroup, err)
}

d.Set("name", id.Name)
d.Set("function_app_name", id.FunctionAppName)
d.Set("resource_group_name", id.ResourceGroup)
if location := resp.Location; location != nil {
d.Set("location", azure.NormalizeLocation(*location))
}

if props := resp.SiteProperties; props != nil {
d.Set("app_service_plan_id", props.ServerFarmID)
}

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

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

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

log.Printf("[DEBUG] Deleting Slot %q (Function App %q / Resource Group %q)", id.Name, id.FunctionAppName, id.ResourceGroup)

deleteMetrics := true
deleteEmptyServerFarm := false
resp, err := client.DeleteSlot(ctx, id.ResourceGroup, id.FunctionAppName, id.Name, &deleteMetrics, &deleteEmptyServerFarm)
if err != nil {
if !utils.ResponseWasNotFound(resp) {
return fmt.Errorf("Error deleting Slot %q (Function App %q / Resource Group %q): %s", id.Name, id.FunctionAppName, id.ResourceGroup, err)
}
}

return nil
}

0 comments on commit 848ec44

Please sign in to comment.