From b249495e91f83f4e76513f0be0d12c308df01ec1 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Sun, 7 Jul 2019 21:44:16 +0200 Subject: [PATCH] azurerm_app_service: fixing the code comments from #3330 ``` $ acctests azurerm TestAccAzureRMAppService_backup === RUN TestAccAzureRMAppService_backup === PAUSE TestAccAzureRMAppService_backup === CONT TestAccAzureRMAppService_backup --- PASS: TestAccAzureRMAppService_backup (660.26s) PASS ok github.com/terraform-providers/terraform-provider-azurerm/azurerm 660.313s ``` ``` $ acctests azurerm TestAccAzureRMAppService_basic === RUN TestAccAzureRMAppService_basic === PAUSE TestAccAzureRMAppService_basic === RUN TestAccAzureRMAppService_basicWindowsContainer === PAUSE TestAccAzureRMAppService_basicWindowsContainer === CONT TestAccAzureRMAppService_basic --- PASS: TestAccAzureRMAppService_basic (189.59s) === CONT TestAccAzureRMAppService_basicWindowsContainer --- PASS: TestAccAzureRMAppService_basicWindowsContainer (369.53s) PASS ok github.com/terraform-providers/terraform-provider-azurerm/azurerm 559.155s ``` --- .../azure/app_service_schedule_backup.go | 186 ++++++++++++---- azurerm/resource_arm_app_service.go | 97 ++++----- azurerm/resource_arm_app_service_test.go | 201 ++++++++++++++++++ examples/app-service/backup/README.md | 3 + examples/app-service/backup/main.tf | 88 ++++++++ .../{scheduler-backup => backup}/output.tf | 0 .../{scheduler-backup => backup}/variables.tf | 4 +- .../app-service/scheduler-backup/README.md | 3 - examples/app-service/scheduler-backup/main.tf | 88 -------- website/docs/r/app_service.html.markdown | 24 ++- 10 files changed, 486 insertions(+), 208 deletions(-) create mode 100644 examples/app-service/backup/README.md create mode 100644 examples/app-service/backup/main.tf rename examples/app-service/{scheduler-backup => backup}/output.tf (100%) rename examples/app-service/{scheduler-backup => backup}/variables.tf (80%) delete mode 100644 examples/app-service/scheduler-backup/README.md delete mode 100644 examples/app-service/scheduler-backup/main.tf diff --git a/azurerm/helpers/azure/app_service_schedule_backup.go b/azurerm/helpers/azure/app_service_schedule_backup.go index c18549894cd1..d809059dfbe9 100644 --- a/azurerm/helpers/azure/app_service_schedule_backup.go +++ b/azurerm/helpers/azure/app_service_schedule_backup.go @@ -4,58 +4,85 @@ import ( "fmt" "time" + "github.com/hashicorp/terraform/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" "github.com/Azure/go-autorest/autorest/date" "github.com/Azure/azure-sdk-for-go/services/web/mgmt/2018-02-01/web" "github.com/hashicorp/terraform/helper/schema" - "github.com/hashicorp/terraform/helper/validation" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" ) -func SchemaAppServiceScheduleBackup() *schema.Schema { +func SchemaAppServiceBackup() *schema.Schema { return &schema.Schema{ Type: schema.TypeList, Optional: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "frequency_interval": { - Type: schema.TypeInt, + "name": { + Type: schema.TypeString, Required: true, - ValidateFunc: validateFrequencyInterval, + ValidateFunc: validate.NoEmptyStrings, }, - "frequency_unit": { - Type: schema.TypeString, - Optional: true, - Default: "Day", - ValidateFunc: validation.StringInSlice([]string{ - "Day", - "Hour", - }, false), + "storage_account_url": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: validate.URLIsHTTPS, }, - "keep_at_least_one_backup": { + "enabled": { Type: schema.TypeBool, Optional: true, - Default: false, - }, - - "retention_period_in_days": { - Type: schema.TypeInt, - Optional: true, - Default: 30, - ValidateFunc: validateRetentionPeriod, + Default: true, }, - "start_time": { - Type: schema.TypeString, - Optional: true, - DiffSuppressFunc: suppress.RFC3339Time, - ValidateFunc: validate.RFC3339Time, + "schedule": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "frequency_interval": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validateFrequencyInterval, + }, + + "frequency_unit": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Day", + "Hour", + }, false), + }, + + "keep_at_least_one_backup": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "retention_period_in_days": { + Type: schema.TypeInt, + Optional: true, + Default: 30, + ValidateFunc: validateRetentionPeriod, + }, + + "start_time": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: suppress.RFC3339Time, + ValidateFunc: validate.RFC3339Time, + }, + }, + }, }, }, }, @@ -80,36 +107,101 @@ func validateRetentionPeriod(val interface{}, key string) (warns []string, errs return } -func ExpandAppServiceScheduleBackup(input interface{}) web.BackupSchedule { - configs := input.([]interface{}) - backupSchedule := web.BackupSchedule{} - - if len(configs) == 0 { - return backupSchedule +func ExpandAppServiceBackup(input []interface{}) *web.BackupRequest { + if len(input) == 0 { + return nil } - config := configs[0].(map[string]interface{}) + vals := input[0].(map[string]interface{}) - if v, ok := config["frequency_interval"].(int); ok { - backupSchedule.FrequencyInterval = utils.Int32(int32(v)) + name := vals["name"].(string) + storageAccountUrl := vals["storage_account_url"].(string) + enabled := vals["enabled"].(bool) + + request := &web.BackupRequest{ + BackupRequestProperties: &web.BackupRequestProperties{ + BackupName: utils.String(name), + StorageAccountURL: utils.String(storageAccountUrl), + Enabled: utils.Bool(enabled), + }, } - if v, ok := config["frequency_unit"]; ok { - backupSchedule.FrequencyUnit = web.FrequencyUnit(v.(string)) + scheduleRaw := vals["schedule"].([]interface{}) + if len(scheduleRaw) > 0 { + schedule := scheduleRaw[0].(map[string]interface{}) + backupSchedule := web.BackupSchedule{} + + if v, ok := schedule["frequency_interval"].(int); ok { + backupSchedule.FrequencyInterval = utils.Int32(int32(v)) + } + + if v, ok := schedule["frequency_unit"]; ok { + backupSchedule.FrequencyUnit = web.FrequencyUnit(v.(string)) + } + + if v, ok := schedule["keep_at_least_one_backup"]; ok { + backupSchedule.KeepAtLeastOneBackup = utils.Bool(v.(bool)) + } + + if v, ok := schedule["retention_period_in_days"].(int); ok { + backupSchedule.RetentionPeriodInDays = utils.Int32(int32(v)) + } + + if v, ok := schedule["start_time"].(string); ok { + dateTimeToStart, _ := time.Parse(time.RFC3339, v) //validated by schema + backupSchedule.StartTime = &date.Time{Time: dateTimeToStart} + } + + request.BackupRequestProperties.BackupSchedule = &backupSchedule } - if v, ok := config["keep_at_least_one_backup"]; ok { - backupSchedule.KeepAtLeastOneBackup = utils.Bool(v.(bool)) + return request +} + +func FlattenAppServiceBackup(input *web.BackupRequestProperties) []interface{} { + if input == nil { + return []interface{}{} } - if v, ok := config["retention_period_in_days"].(int); ok { - backupSchedule.RetentionPeriodInDays = utils.Int32(int32(v)) + output := make(map[string]interface{}) + + if input.BackupName != nil { + output["name"] = *input.BackupName + } + if input.Enabled != nil { + output["enabled"] = *input.Enabled } + if input.StorageAccountURL != nil { + output["storage_account_url"] = *input.StorageAccountURL + } + + schedules := make([]interface{}, 0) + if input.BackupSchedule != nil { + v := *input.BackupSchedule + + schedule := make(map[string]interface{}) + + if v.FrequencyInterval != nil { + schedule["frequency_interval"] = int(*v.FrequencyInterval) + } - if v, ok := config["start_time"].(string); ok { - dateTimeToStart, _ := time.Parse(time.RFC3339, v) //validated by schema - backupSchedule.StartTime = &date.Time{Time: (dateTimeToStart)} + schedule["frequency_unit"] = string(v.FrequencyUnit) + + if v.KeepAtLeastOneBackup != nil { + schedule["keep_at_least_one_backup"] = *v.KeepAtLeastOneBackup + } + if v.RetentionPeriodInDays != nil { + schedule["retention_period_in_days"] = int(*v.RetentionPeriodInDays) + } + if v.StartTime != nil && !v.StartTime.IsZero() { + schedule["start_time"] = v.StartTime.Format(time.RFC3339) + } + + schedules = append(schedules, schedule) } + output["schedule"] = schedules - return backupSchedule + return []interface{}{ + output, + } } diff --git a/azurerm/resource_arm_app_service.go b/azurerm/resource_arm_app_service.go index 468b58ff6d62..f42915b935d8 100644 --- a/azurerm/resource_arm_app_service.go +++ b/azurerm/resource_arm_app_service.go @@ -10,7 +10,6 @@ import ( "github.com/hashicorp/terraform/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/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -49,20 +48,7 @@ func resourceArmAppService() *schema.Resource { "logs": azure.SchemaAppServiceLogsConfig(), - "backup_schedule": azure.SchemaAppServiceScheduleBackup(), - - "storage_account_url": { - Type: schema.TypeString, - Optional: true, - Sensitive: true, - ValidateFunc: validate.URLIsHTTPS, - }, - - "backup_name": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validate.NoEmptyStrings, - }, + "backup": azure.SchemaAppServiceBackup(), "client_affinity_enabled": { Type: schema.TypeBool, @@ -258,17 +244,17 @@ func resourceArmAppServiceCreate(d *schema.ResourceData, meta interface{}) error createFuture, err := client.CreateOrUpdate(ctx, resGroup, name, siteEnvelope) if err != nil { - return err + return fmt.Errorf("Error creating App Service %q (Resource Group %q): %s", name, resGroup, err) } err = createFuture.WaitForCompletionRef(ctx, client.Client) if err != nil { - return err + return fmt.Errorf("Error waiting for App Service %q (Resource Group %q) to be created: %s", name, resGroup, err) } read, err := client.Get(ctx, resGroup, name) if err != nil { - return err + return fmt.Errorf("Error retrieving App Service %q (Resource Group %q): %s", name, resGroup, err) } if read.ID == nil { return fmt.Errorf("Cannot read App Service %q (resource group %q) ID", name, resGroup) @@ -297,6 +283,14 @@ func resourceArmAppServiceCreate(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error updating diagnostic logs config for App Service %q (Resource Group %q): %+s", name, resGroup, err) } + backupRaw := d.Get("backup").([]interface{}) + if backup := azure.ExpandAppServiceBackup(backupRaw); backup != nil { + _, err = client.UpdateBackupConfiguration(ctx, resGroup, name, *backup) + if err != nil { + return fmt.Errorf("Error updating Backup Settings for App Service %q (Resource Group %q): %s", name, resGroup, err) + } + } + return resourceArmAppServiceUpdate(d, meta) } @@ -313,8 +307,6 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error name := id.Path["sites"] location := azure.NormalizeLocation(d.Get("location").(string)) - storageAccountURL := d.Get("storage_account_url").(string) - backupName := d.Get("backup_name").(string) appServicePlanId := d.Get("app_service_plan_id").(string) enabled := d.Get("enabled").(bool) @@ -386,25 +378,17 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error } } - if d.HasChange("backup_schedule") { - backupSchedule := azure.ExpandAppServiceScheduleBackup(d.Get("backup_schedule")) - if storageAccountURL != "" { - request := web.BackupRequest{ - BackupRequestProperties: &web.BackupRequestProperties{ - BackupName: utils.String(backupName), - StorageAccountURL: utils.String(storageAccountURL), - Enabled: utils.Bool(true), - BackupSchedule: &backupSchedule, - }, - } - _, err = client.UpdateBackupConfiguration(ctx, resGroup, name, request) + if d.HasChange("backup") { + backupRaw := d.Get("backup").([]interface{}) + if backup := azure.ExpandAppServiceBackup(backupRaw); backup != nil { + _, err = client.UpdateBackupConfiguration(ctx, resGroup, name, *backup) if err != nil { - return err + return fmt.Errorf("Error updating Backup Settings for App Service %q (Resource Group %q): %s", name, resGroup, err) } } else { - err = resourceArmDeleteScheduleBackup(d, meta) + _, err = client.DeleteBackupConfiguration(ctx, resGroup, name) if err != nil { - return err + return fmt.Errorf("Error removing Backup Settings for App Service %q (Resource Group %q): %s", name, resGroup, err) } } } @@ -520,6 +504,13 @@ func resourceArmAppServiceRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error retrieving the AuthSettings for App Service %q (Resource Group %q): %+v", name, resGroup, err) } + backupResp, err := client.GetBackupConfiguration(ctx, resGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(backupResp.Response) { + return fmt.Errorf("Error retrieving the BackupConfiguration for App Service %q (Resource Group %q): %+v", name, resGroup, err) + } + } + logsResp, err := client.GetDiagnosticLogsConfiguration(ctx, resGroup, name) if err != nil { return fmt.Errorf("Error retrieving the DiagnosticsLogsConfiguration for App Service %q (Resource Group %q): %+v", name, resGroup, err) @@ -587,15 +578,19 @@ func resourceArmAppServiceRead(d *schema.ResourceData, meta interface{}) error { delete(appSettings, "DIAGNOSTICS_AZUREBLOBRETENTIONINDAYS") if err := d.Set("app_settings", appSettings); err != nil { - return err + return fmt.Errorf("Error setting `app_settings`: %s", err) + } + + if err := d.Set("backup", azure.FlattenAppServiceBackup(backupResp.BackupRequestProperties)); err != nil { + return fmt.Errorf("Error setting `backup`: %s", err) } if err := d.Set("storage_account", azure.FlattenAppServiceStorageAccounts(storageAccountsResp.Properties)); err != nil { - return err + return fmt.Errorf("Error setting `storage_account`: %s", err) } if err := d.Set("connection_string", flattenAppServiceConnectionStrings(connectionStringsResp.Properties)); err != nil { - return err + return fmt.Errorf("Error setting `connection_string`: %s", err) } siteConfig := azure.FlattenAppServiceSiteConfig(configResp.SiteConfig) @@ -615,17 +610,17 @@ func resourceArmAppServiceRead(d *schema.ResourceData, meta interface{}) error { scm := flattenAppServiceSourceControl(scmResp.SiteSourceControlProperties) if err := d.Set("source_control", scm); err != nil { - return err + return fmt.Errorf("Error setting `source_control`: %s", err) } siteCred := flattenAppServiceSiteCredential(siteCredResp.UserProperties) if err := d.Set("site_credential", siteCred); err != nil { - return err + return fmt.Errorf("Error setting `site_credential`: %s", err) } identity := azure.FlattenAppServiceIdentity(resp.Identity) if err := d.Set("identity", identity); err != nil { - return err + return fmt.Errorf("Error setting `identity`: %s", err) } flattenAndSetTags(d, resp.Tags) @@ -764,23 +759,3 @@ func flattenAppServiceSiteCredential(input *web.UserProperties) []interface{} { return append(results, result) } - -func resourceArmDeleteScheduleBackup(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).appServicesClient - ctx := meta.(*ArmClient).StopContext - - id, err := parseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - name := id.Path["sites"] - - _, err = client.DeleteBackupConfiguration(ctx, resGroup, name) - if err != nil { - return err - } - - return nil -} diff --git a/azurerm/resource_arm_app_service_test.go b/azurerm/resource_arm_app_service_test.go index e1fdc346ba38..93040cc76d88 100644 --- a/azurerm/resource_arm_app_service_test.go +++ b/azurerm/resource_arm_app_service_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/services/web/mgmt/2018-02-01/web" + "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" @@ -212,6 +213,69 @@ func TestAccAzureRMAppService_32Bit(t *testing.T) { }) } +func TestAccAzureRMAppService_backup(t *testing.T) { + resourceName := "azurerm_app_service.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(5) + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAppServiceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAppService_backup(ri, rs, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAzureRMAppService_backupUpdated(ri, rs, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + // Enabled + Config: testAccAzureRMAppService_backup(ri, rs, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceExists(resourceName), + ), + }, + { + // Disabled + Config: testAccAzureRMAppService_backupDisabled(ri, rs, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceExists(resourceName), + ), + }, + { + // remove it + Config: testAccAzureRMAppService_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAzureRMAppService_http2Enabled(t *testing.T) { resourceName := "azurerm_app_service.test" ri := tf.AccRandTimeInt() @@ -2232,6 +2296,143 @@ resource "azurerm_app_service" "test" { `, rInt, location, rInt, rInt) } +func testAccAzureRMAppService_backup(rInt int, rString, location string) string { + template := testAccAzureRMAppService_backupTemplate(rInt, rString, location) + return fmt.Sprintf(` +%s + +resource "azurerm_app_service" "test" { + name = "acctestAS-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + app_service_plan_id = "${azurerm_app_service_plan.test.id}" + + backup { + name = "acctest" + storage_account_url = "https://${azurerm_storage_account.test.name}.blob.core.windows.net/${azurerm_storage_container.test.name}${data.azurerm_storage_account_sas.test.sas}&sr=b" + schedule { + frequency_interval = 1 + frequency_unit = "Day" + } + } +} +`, template, rInt) +} + +func testAccAzureRMAppService_backupDisabled(rInt int, rString, location string) string { + template := testAccAzureRMAppService_backupTemplate(rInt, rString, location) + return fmt.Sprintf(` +%s + +resource "azurerm_app_service" "test" { + name = "acctestAS-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + app_service_plan_id = "${azurerm_app_service_plan.test.id}" + + backup { + name = "acctest" + storage_account_url = "https://${azurerm_storage_account.test.name}.blob.core.windows.net/${azurerm_storage_container.test.name}${data.azurerm_storage_account_sas.test.sas}&sr=b" + enabled = false + schedule { + frequency_interval = 1 + frequency_unit = "Day" + } + } +} +`, template, rInt) +} + +func testAccAzureRMAppService_backupUpdated(rInt int, rString, location string) string { + template := testAccAzureRMAppService_backupTemplate(rInt, rString, location) + return fmt.Sprintf(` +%s + +resource "azurerm_app_service" "test" { + name = "acctestAS-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + app_service_plan_id = "${azurerm_app_service_plan.test.id}" + + backup { + name = "acctest" + storage_account_url = "https://${azurerm_storage_account.test.name}.blob.core.windows.net/${azurerm_storage_container.test.name}${data.azurerm_storage_account_sas.test.sas}&sr=b" + schedule { + frequency_interval = 2 + frequency_unit = "Hour" + } + } +} +`, template, rInt) +} + +func testAccAzureRMAppService_backupTemplate(rInt int, rString, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_storage_container" "test" { + name = "example" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_name = "${azurerm_storage_account.test.name}" + container_access_type = "private" +} + +data "azurerm_storage_account_sas" "test" { + connection_string = "${azurerm_storage_account.test.primary_connection_string}" + https_only = true + + resource_types { + service = false + container = false + object = true + } + + services { + blob = true + queue = false + table = false + file = false + } + + start = "2019-03-21" + expiry = "2022-03-21" + + permissions { + read = false + write = true + delete = false + list = false + add = false + create = false + update = false + process = false + } +} + +resource "azurerm_app_service_plan" "test" { + name = "acctestASP-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + tier = "Standard" + size = "S1" + } +} +`, rInt, location, rString, rInt) +} + func testAccAzureRMAppService_http2Enabled(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/examples/app-service/backup/README.md b/examples/app-service/backup/README.md new file mode 100644 index 000000000000..cfd5951cce8c --- /dev/null +++ b/examples/app-service/backup/README.md @@ -0,0 +1,3 @@ +# Example: an App Service with a Scheduled Backup + +This example provisions an App Service with a Backup configured. diff --git a/examples/app-service/backup/main.tf b/examples/app-service/backup/main.tf new file mode 100644 index 000000000000..3f9c6054f08b --- /dev/null +++ b/examples/app-service/backup/main.tf @@ -0,0 +1,88 @@ +resource "azurerm_resource_group" "test" { + name = "${var.prefix}-resources" + location = "${var.location}" +} + +resource "azurerm_storage_account" "test" { + name = "${var.prefix}sa" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_storage_container" "test" { + name = "${var.prefix}-sc" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_name = "${azurerm_storage_account.test.name}" + container_access_type = "private" +} + +resource "azurerm_app_service_plan" "test" { + name = "${var.prefix}-splan" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + tier = "Standard" + size = "S1" + } +} + +data "azurerm_storage_account_sas" "test" { + connection_string = "${azurerm_storage_account.test.primary_connection_string}" + https_only = true + + resource_types { + service = false + container = false + object = true + } + + services { + blob = true + queue = false + table = false + file = false + } + + start = "2019-03-21" + expiry = "2020-03-21" + + permissions { + read = false + write = true + delete = false + list = false + add = false + create = false + update = false + process = false + } +} + +resource "azurerm_app_service" "test" { + name = "${var.prefix}-appservice" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + app_service_plan_id = "${azurerm_app_service_plan.test.id}" + + backup { + name = "Example" + storage_account_url = "https://${azurerm_storage_account.test.name}.blob.core.windows.net/${azurerm_storage_container.test.name}${data.azurerm_storage_account_sas.test.sas}&sr=b" + + schedule { + frequency_interval = "30" + frequency_unit = "Day" + } + } + + site_config { + dotnet_framework_version = "v4.0" + scm_type = "LocalGit" + } + + app_settings = { + "SOME_KEY" = "some-value" + } +} diff --git a/examples/app-service/scheduler-backup/output.tf b/examples/app-service/backup/output.tf similarity index 100% rename from examples/app-service/scheduler-backup/output.tf rename to examples/app-service/backup/output.tf diff --git a/examples/app-service/scheduler-backup/variables.tf b/examples/app-service/backup/variables.tf similarity index 80% rename from examples/app-service/scheduler-backup/variables.tf rename to examples/app-service/backup/variables.tf index 9efea09ff138..c23806156932 100644 --- a/examples/app-service/scheduler-backup/variables.tf +++ b/examples/app-service/backup/variables.tf @@ -1,7 +1,9 @@ variable "prefix" { description = "The prefix used for all resources in this example" + default = "tomdev88" } variable "location" { description = "The Azure location where all resources in this example should be created" -} \ No newline at end of file + default = "West Europe" +} diff --git a/examples/app-service/scheduler-backup/README.md b/examples/app-service/scheduler-backup/README.md deleted file mode 100644 index dba01c6f608e..000000000000 --- a/examples/app-service/scheduler-backup/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Example: a Basic schedule backup App Service - -This example provisions a schedule backup App Service. diff --git a/examples/app-service/scheduler-backup/main.tf b/examples/app-service/scheduler-backup/main.tf deleted file mode 100644 index 68db6601e276..000000000000 --- a/examples/app-service/scheduler-backup/main.tf +++ /dev/null @@ -1,88 +0,0 @@ -resource "azurerm_resource_group" "testrg" { - name = "${var.prefix}-resources" - location = "${var.location}" -} - -resource "azurerm_storage_account" "testsa" { - name = "${var.prefix}sa" - resource_group_name = "${azurerm_resource_group.testrg.name}" - location = "${azurerm_resource_group.testrg.location}" - account_tier = "Standard" - account_replication_type = "LRS" -} - -resource "azurerm_storage_container" "test" { - name = "${var.prefix}-sc" - resource_group_name = "${azurerm_resource_group.testrg.name}" - storage_account_name = "${azurerm_storage_account.testsa.name}" - container_access_type = "private" -} - -resource "azurerm_app_service_plan" "test" { - name = "${var.prefix}-splan" - location = "${azurerm_resource_group.testrg.location}" - resource_group_name = "${azurerm_resource_group.testrg.name}" - - sku { - tier = "Standard" - size = "S1" - } -} - -data "azurerm_storage_account_sas" "test" { - connection_string = "${azurerm_storage_account.testsa.primary_connection_string}" - https_only = true - - resource_types { - service = false - container = false - object = true - } - - services { - blob = true - queue = false - table = false - file = false - } - - start = "2019-03-21" - expiry = "2020-03-21" - - permissions { - read = false - write = true - delete = false - list = false - add = false - create = false - update = false - process = false - } -} - -resource "azurerm_app_service" "test" { - name = "${var.prefix}-appservice" - location = "${azurerm_resource_group.testrg.location}" - resource_group_name = "${azurerm_resource_group.testrg.name}" - app_service_plan_id = "${azurerm_app_service_plan.test.id}" - storage_account_url = "https://${azurerm_storage_account.testsa.name}.blob.core.windows.net/${azurerm_storage_container.test.name}${data.azurerm_storage_account_sas.test.sas}&sr=b" - - backup_schedule { - frequency_interval = "30" -# frequency_unit = "Day" -# keep_at_least_one_backup = false -# retention_period_in_days = "9" -# start_time = "2019-04-29T09:40:00+02:00" - } - - site_config { - dotnet_framework_version = "v4.0" - scm_type = "LocalGit" - } - - app_settings = { - "SOME_KEY" = "some-value" - } - -} diff --git a/website/docs/r/app_service.html.markdown b/website/docs/r/app_service.html.markdown index d04de0b41267..1c2a107b9e0c 100644 --- a/website/docs/r/app_service.html.markdown +++ b/website/docs/r/app_service.html.markdown @@ -93,10 +93,6 @@ The following arguments are supported: * `identity` - (Optional) A Managed Service Identity block as defined below. -* `storage_account_url` (Optional) Sets SAS URL to the container where save the backup. - -* `backup_name` (Optional) Sets name of the backup. - --- A `storage_account` block supports the following: @@ -305,15 +301,27 @@ A `microsoft` block supports the following: --- -A `backup_schedule` block supports the following: +A `backup` block supports the following: + +* `backup_name` (Required) Specifies the name for this Backup. + +* `enabled` - (Required) Is this Backup enabled? + +* `storage_account_url` (Optional) The SAS URL to a Storage Container where Backups should be saved. + +* `schedule` - (Optional) A `schedule` block as defined below. + +--- + +A `schedule` block supports the following: * `frequency_interval` - (Required) Sets how often the backup should be executed. -* `frequency_unit` - (Optional) Sets the unit of time for how often the backup should be executed, possible values: `Day` or `Hour`. Defaults to `Day`. +* `frequency_unit` - (Optional) Sets the unit of time for how often the backup should be executed. Possible values are `Day` or `Hour`. -* `keep_at_least_one_backup` - (Optional) Sets `true` if the retention policy should always keep at least one backup in the storage account, regardless how old it is; `false` otherwise. Defaults to `true`. +* `keep_at_least_one_backup` - (Optional) Should at least one backup always be kept in the Storage Account by the Retention Policy, regardless of how old it is? -* `retention_period_in_days` - (Optional) Sets after how many days backups should be deleted. Defaults to `30`. +* `retention_period_in_days` - (Optional) Specifies the number of days after which Backups should be deleted. * `start_time` - (Optional) Sets when the schedule should start working.