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

provider/azurerm: Create azure App Service Plan resource #13634

Closed
9 changes: 9 additions & 0 deletions builtin/providers/azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/Azure/azure-sdk-for-go/arm/sql"
"github.com/Azure/azure-sdk-for-go/arm/storage"
"github.com/Azure/azure-sdk-for-go/arm/trafficmanager"
"github.com/Azure/azure-sdk-for-go/arm/web"
mainStorage "github.com/Azure/azure-sdk-for-go/storage"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
Expand Down Expand Up @@ -101,6 +102,8 @@ type ArmClient struct {

keyVaultClient keyvault.VaultsClient

appServicePlansClient web.AppServicePlansClient

sqlElasticPoolsClient sql.ElasticPoolsClient
}

Expand Down Expand Up @@ -461,6 +464,12 @@ func (c *Config) getArmClient() (*ArmClient, error) {
kvc.Sender = autorest.CreateSender(withRequestLogging())
client.keyVaultClient = kvc

aspc := web.NewAppServicePlansClientWithBaseURI(endpoint, c.SubscriptionID)
setUserAgent(&aspc.Client)
aspc.Authorizer = spt
aspc.Sender = autorest.CreateSender(withRequestLogging())
client.appServicePlansClient = aspc

sqlepc := sql.NewElasticPoolsClientWithBaseURI(endpoint, c.SubscriptionID)
setUserAgent(&sqlepc.Client)
sqlepc.Authorizer = spt
Expand Down
2 changes: 2 additions & 0 deletions builtin/providers/azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ func Provider() terraform.ResourceProvider {
"azurerm_sql_database": resourceArmSqlDatabase(),
"azurerm_sql_firewall_rule": resourceArmSqlFirewallRule(),
"azurerm_sql_server": resourceArmSqlServer(),

"azurerm_app_service_plan": resourceArmAppServicePlan(),
},
}

Expand Down
132 changes: 132 additions & 0 deletions builtin/providers/azurerm/resource_arm_app_service_plan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package azurerm

import (
"fmt"
"log"
"net/http"

"github.com/Azure/azure-sdk-for-go/arm/web"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceArmAppServicePlan() *schema.Resource {
return &schema.Resource{
Create: resourceArmAppServicePlanCreateUpdate,
Read: resourceArmAppServicePlanRead,
Update: resourceArmAppServicePlanCreateUpdate,
Delete: resourceArmAppServicePlanDelete,

Schema: map[string]*schema.Schema{
"resource_group_name": {
Type: schema.TypeString,
Required: true,
},
"name": {
Type: schema.TypeString,
Required: true,
},
"location": {
Type: schema.TypeString,
Required: true,
},
"tier": {
Type: schema.TypeString,
Required: true,
},
"maximum_number_of_workers": {
Type: schema.TypeString,
Optional: true,
},
},
}
}

func resourceArmAppServicePlanCreateUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
AppServicePlanClient := client.appServicePlansClient

log.Printf("[INFO] preparing arguments for Azure App Service Plan creation.")

resGroup := d.Get("resource_group_name").(string)
name := d.Get("name").(string)
location := d.Get("location").(string)
tier := d.Get("tier").(string)

sku := web.SkuDescription{
Name: &tier,
Copy link
Contributor

Choose a reason for hiding this comment

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

It'd be good to also specify the Size and the Tier here too, as we do in the other resources? We tend to make sku a hash like so:

sku {
  name = "Standard_S0"
  tier = "Standard"
  size = "S0"
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tombuildsstuff do you mean that I have to pass in the Size and Tier as inputs to the provider? At the moment I am only passing in the service tier, e.g. "S0" which determines the tier.

}

properties := web.AppServicePlanProperties{}
if v, ok := d.GetOk("maximum_number_of_workers"); ok {
maximumNumberOfWorkers := v.(int32)
properties.MaximumNumberOfWorkers = &maximumNumberOfWorkers
}

appServicePlan := web.AppServicePlan{
Location: &location,
AppServicePlanProperties: &properties,
Sku: &sku,
}

_, err := AppServicePlanClient.CreateOrUpdate(resGroup, name, appServicePlan, make(chan struct{}))
if err != nil {
return err
}

read, err := AppServicePlanClient.Get(resGroup, name)
if err != nil {
return err
}
if read.ID == nil {
return fmt.Errorf("Cannot read Azure App Service Plan %s (resource group %s) ID", name, resGroup)
}

d.SetId(*read.ID)

return resourceArmAppServicePlanRead(d, meta)
}

func resourceArmAppServicePlanRead(d *schema.ResourceData, meta interface{}) error {
AppServicePlanClient := meta.(*ArmClient).appServicePlansClient

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

log.Printf("[DEBUG] Reading app service plan %s", id)

resGroup := id.ResourceGroup
name := id.Path["serverfarms"]

resp, err := AppServicePlanClient.Get(resGroup, name)
if err != nil {
if resp.StatusCode == http.StatusNotFound {
d.SetId("")
return nil
}
return fmt.Errorf("Error making Read request on Azure App Service Plan %s: %s", name, err)
}

d.Set("name", name)
d.Set("resource_group_name", resGroup)

return nil
}

func resourceArmAppServicePlanDelete(d *schema.ResourceData, meta interface{}) error {
AppServicePlanClient := meta.(*ArmClient).appServicePlansClient

id, err := parseAzureResourceID(d.Id())
if err != nil {
return err
}
resGroup := id.ResourceGroup
name := id.Path["serverfarms"]

log.Printf("[DEBUG] Deleting app service plan %s: %s", resGroup, name)

_, err = AppServicePlanClient.Delete(resGroup, name)

return err
}
100 changes: 100 additions & 0 deletions builtin/providers/azurerm/resource_arm_app_service_plan_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package azurerm

import (
"fmt"
"log"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccAzureRMAppServicePlan_standard(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(TestAccAzureRMAppServicePlan_standard, ri, ri)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMAppServicePlanDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMAppServicePlanExists("azurerm_app_service_plan.test"),
),
},
},
})
}

func testCheckAzureRMAppServicePlanDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*ArmClient).appServicePlansClient

for _, rs := range s.RootModule().Resources {
if rs.Type != "azurerm_app_service_plan" {
continue
}

name := rs.Primary.Attributes["name"]
resourceGroup := rs.Primary.Attributes["resource_group_name"]

resp, err := conn.Get(resourceGroup, name)

if err != nil {
return nil
}

if resp.StatusCode != http.StatusNotFound {
return fmt.Errorf("App Service Plan still exists:\n%#v", resp)
}
}

return nil
}

func testCheckAzureRMAppServicePlanExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
// 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)
}

appServicePlanName := rs.Primary.Attributes["name"]
resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
if !hasResourceGroup {
return fmt.Errorf("Bad: no resource group found in state for App Service Plan: %s", redisName)
}

conn := testAccProvider.Meta().(*ArmClient).appServicePlansClient

resp, err := conn.Get(resourceGroup, appServicePlanName)
if err != nil {
return fmt.Errorf("Bad: Get on appServicePlansClient: %s", err)
}

if resp.StatusCode == http.StatusNotFound {
return fmt.Errorf("Bad: App Service Plan %q (resource group: %q) does not exist", appServicePlanName, resourceGroup)
}

return nil
}
}

var testAccAzureRMAppServicePlan_standard = `
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "West US"
}
resource "azurerm_app_service_plan" "test" {
name = "acctestAppServicePlan-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
tier = "S0"
tags {
environment = "production"
}
}
`
Loading