From 8da955479aefb8f20c4867fb4050a731e6fe7c4c Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Tue, 6 Aug 2019 16:21:36 -0700 Subject: [PATCH 1/4] Adding http logs --- azurerm/helpers/azure/app_service.go | 97 +++++++++++++++++++++++- azurerm/resource_arm_app_service_test.go | 73 ++++++++++++++++++ website/docs/r/app_service.html.markdown | 10 +++ 3 files changed, 177 insertions(+), 3 deletions(-) diff --git a/azurerm/helpers/azure/app_service.go b/azurerm/helpers/azure/app_service.go index c8a5ff6d3de3..5bd5568755eb 100644 --- a/azurerm/helpers/azure/app_service.go +++ b/azurerm/helpers/azure/app_service.go @@ -520,6 +520,34 @@ func SchemaAppServiceLogsConfig() *schema.Schema { }, }, }, + "http_logs": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "file_system": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "retention_in_mb": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(25, 100), + }, + "retention_in_days": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntAtLeast(0), + }, + }, + }, + }, + }, + }, + }, }, }, } @@ -1114,16 +1142,55 @@ func FlattenAppServiceLogs(input *web.SiteLogsConfigProperties) []interface{} { blobStorageItem["retention_in_days"] = *blobStorageInput.RetentionInDays } - blobStorage = append(blobStorage, blobStorageItem) + // The API returns a non nil application logs object when other logs are specified so we'll check that this structure is empty before adding it to the statefile. + if blobStorageInput.SasURL != nil { + blobStorage = append(blobStorage, blobStorageItem) + + appLogsItem["azure_blob_storage"] = blobStorage + } - appLogsItem["azure_blob_storage"] = blobStorage } - appLogs = append(appLogs, appLogsItem) + if len(appLogsItem) > 0 { + appLogs = append(appLogs, appLogsItem) + } result["application_logs"] = appLogs } + if input.HTTPLogs != nil { + httpLogs := make([]interface{}, 0) + + httpLogsItem := make(map[string]interface{}) + + if fileSystemInput := input.HTTPLogs.FileSystem; fileSystemInput != nil { + fileSystem := make([]interface{}, 0) + + fileSystemItem := make(map[string]interface{}) + + if fileSystemInput.RetentionInDays != nil { + fileSystemItem["retention_in_days"] = *fileSystemInput.RetentionInDays + } + + if fileSystemInput.RetentionInMb != nil { + fileSystemItem["retention_in_mb"] = *fileSystemInput.RetentionInMb + } + + // The API returns a non nil filesystem logs object when other logs are specified so we'll check that this is disabled before adding it to the statefile. + if fileSystemInput.Enabled != nil && *fileSystemInput.Enabled { + fileSystem = append(fileSystem, fileSystemItem) + + httpLogsItem["file_system"] = fileSystem + } + } + + if len(httpLogsItem) > 0 { + httpLogs = append(httpLogs, httpLogsItem) + } + + result["http_logs"] = httpLogs + } + return append(results, result) } @@ -1161,6 +1228,30 @@ func ExpandAppServiceLogs(input interface{}) web.SiteLogsConfigProperties { } } + if v, ok := config["http_logs"]; ok { + httpLogsConfigs := v.([]interface{}) + + for _, config := range httpLogsConfigs { + httpLogsConfig := config.(map[string]interface{}) + + logs.HTTPLogs = &web.HTTPLogsConfig{} + + if v, ok := httpLogsConfig["file_system"]; ok { + fileSystemConfigs := v.([]interface{}) + + for _, config := range fileSystemConfigs { + fileSystemConfig := config.(map[string]interface{}) + + logs.HTTPLogs.FileSystem = &web.FileSystemHTTPLogsConfig{ + RetentionInMb: utils.Int32(int32(fileSystemConfig["retention_in_mb"].(int))), + RetentionInDays: utils.Int32(int32(fileSystemConfig["retention_in_days"].(int))), + Enabled: utils.Bool(true), + } + } + } + } + } + return logs } diff --git a/azurerm/resource_arm_app_service_test.go b/azurerm/resource_arm_app_service_test.go index f14ef12af364..ee9a1f2cd9de 100644 --- a/azurerm/resource_arm_app_service_test.go +++ b/azurerm/resource_arm_app_service_test.go @@ -955,6 +955,43 @@ func TestAccAzureRMAppService_applicationBlobStorageLogs(t *testing.T) { }) } +func TestAccAzureRMAppService_httpFileSystemLogs(t *testing.T) { + resourceName := "azurerm_app_service.test" + ri := tf.AccRandTimeInt() + config := testAccAzureRMAppService_httpFileSystemLogs(ri, testLocation()) + config2 := testAccAzureRMAppService_basic(ri, testLocation()) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAppServiceDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: config2, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAzureRMAppService_managedPipelineMode(t *testing.T) { resourceName := "azurerm_app_service.test" ri := tf.AccRandTimeInt() @@ -3172,6 +3209,42 @@ resource "azurerm_app_service" "test" { `, rInt, location, rInt, rInt) } +func testAccAzureRMAppService_httpFileSystemLogs(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +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" + } +} + +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}" + + logs { + http_logs { + file_system { + retention_in_days = 4 + retention_in_mb = 25 + } + } + } +} +`, rInt, location, rInt, rInt) +} + func testAccAzureRMAppService_managedPipelineMode(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/app_service.html.markdown b/website/docs/r/app_service.html.markdown index 1c2a107b9e0c..c77c43ff73b7 100644 --- a/website/docs/r/app_service.html.markdown +++ b/website/docs/r/app_service.html.markdown @@ -135,6 +135,8 @@ A `logs` block supports the following: * `application_logs` - (Optional) An `application_logs` block as defined below. +* `http_logs` - (Optional) An `https_logs` block as defined below. + --- An `application_logs` block supports the following: @@ -153,6 +155,14 @@ An `azure_blob_storage` block supports the following: --- +An `http_logs` block supports the following: + +* `retention_in_days` - (Required) The number of days to retain logs for. + +* `retention_in_mb` - (Required) The maximum size in megabytes that http log files can use before being removed. + +--- + A `site_config` block supports the following: * `always_on` - (Optional) Should the app be loaded at all times? Defaults to `false`. From d180ef30346d3e5691f8b178ce796e1937106931 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Wed, 7 Aug 2019 13:03:52 -0700 Subject: [PATCH 2/4] Addressing review --- azurerm/helpers/azure/app_service.go | 11 ++-- azurerm/resource_arm_app_service_test.go | 68 ++++++++++++++++++++++++ website/docs/r/app_service.html.markdown | 2 +- 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/azurerm/helpers/azure/app_service.go b/azurerm/helpers/azure/app_service.go index 5bd5568755eb..66d875759416 100644 --- a/azurerm/helpers/azure/app_service.go +++ b/azurerm/helpers/azure/app_service.go @@ -1122,8 +1122,8 @@ func FlattenAppServiceLogs(input *web.SiteLogsConfigProperties) []interface{} { result := make(map[string]interface{}) + appLogs := make([]interface{}, 0) if input.ApplicationLogs != nil { - appLogs := make([]interface{}, 0) appLogsItem := make(map[string]interface{}) @@ -1145,7 +1145,6 @@ func FlattenAppServiceLogs(input *web.SiteLogsConfigProperties) []interface{} { // The API returns a non nil application logs object when other logs are specified so we'll check that this structure is empty before adding it to the statefile. if blobStorageInput.SasURL != nil { blobStorage = append(blobStorage, blobStorageItem) - appLogsItem["azure_blob_storage"] = blobStorage } @@ -1155,12 +1154,11 @@ func FlattenAppServiceLogs(input *web.SiteLogsConfigProperties) []interface{} { appLogs = append(appLogs, appLogsItem) } - result["application_logs"] = appLogs } + result["application_logs"] = appLogs + httpLogs := make([]interface{}, 0) if input.HTTPLogs != nil { - httpLogs := make([]interface{}, 0) - httpLogsItem := make(map[string]interface{}) if fileSystemInput := input.HTTPLogs.FileSystem; fileSystemInput != nil { @@ -1187,9 +1185,8 @@ func FlattenAppServiceLogs(input *web.SiteLogsConfigProperties) []interface{} { if len(httpLogsItem) > 0 { httpLogs = append(httpLogs, httpLogsItem) } - - result["http_logs"] = httpLogs } + result["http_logs"] = httpLogs return append(results, result) } diff --git a/azurerm/resource_arm_app_service_test.go b/azurerm/resource_arm_app_service_test.go index ee9a1f2cd9de..42a059b37ea5 100644 --- a/azurerm/resource_arm_app_service_test.go +++ b/azurerm/resource_arm_app_service_test.go @@ -992,6 +992,31 @@ func TestAccAzureRMAppService_httpFileSystemLogs(t *testing.T) { }) } +func TestAccAzureRMAppService_httpFileSystemAndStorageBlobLogs(t *testing.T) { + resourceName := "azurerm_app_service.test" + ri := tf.AccRandTimeInt() + config := testAccAzureRMAppService_httpFileSystemAndStorageBlobLogs(ri, testLocation()) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAppServiceDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAzureRMAppService_managedPipelineMode(t *testing.T) { resourceName := "azurerm_app_service.test" ri := tf.AccRandTimeInt() @@ -3245,6 +3270,49 @@ resource "azurerm_app_service" "test" { `, rInt, location, rInt, rInt) } +func testAccAzureRMAppService_httpFileSystemAndStorageBlobLogs(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +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" + } +} + +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}" + + logs { + application_logs { + azure_blob_storage { + level = "Information" + sas_url = "http://x.com/" + retention_in_days = 3 + } + } + http_logs { + file_system { + retention_in_days = 4 + retention_in_mb = 25 + } + } + } +} +`, rInt, location, rInt, rInt) +} + func testAccAzureRMAppService_managedPipelineMode(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/app_service.html.markdown b/website/docs/r/app_service.html.markdown index c77c43ff73b7..846aaadc4683 100644 --- a/website/docs/r/app_service.html.markdown +++ b/website/docs/r/app_service.html.markdown @@ -135,7 +135,7 @@ A `logs` block supports the following: * `application_logs` - (Optional) An `application_logs` block as defined below. -* `http_logs` - (Optional) An `https_logs` block as defined below. +* `http_logs` - (Optional) An `http_logs` block as defined below. --- From 864f9ed7c8e32f0ae8c2a5ace67e3cc03e01b123 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 12 Aug 2019 09:41:24 -0700 Subject: [PATCH 3/4] Address review --- azurerm/helpers/azure/app_service.go | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/azurerm/helpers/azure/app_service.go b/azurerm/helpers/azure/app_service.go index 66d875759416..20c9e6356cc9 100644 --- a/azurerm/helpers/azure/app_service.go +++ b/azurerm/helpers/azure/app_service.go @@ -485,6 +485,7 @@ func SchemaAppServiceLogsConfig() *schema.Schema { "application_logs": { Type: schema.TypeList, Optional: true, + Computed: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -523,6 +524,7 @@ func SchemaAppServiceLogsConfig() *schema.Schema { "http_logs": { Type: schema.TypeList, Optional: true, + Computed: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -1127,9 +1129,8 @@ func FlattenAppServiceLogs(input *web.SiteLogsConfigProperties) []interface{} { appLogsItem := make(map[string]interface{}) + blobStorage := make([]interface{}, 0) if blobStorageInput := input.ApplicationLogs.AzureBlobStorage; blobStorageInput != nil { - blobStorage := make([]interface{}, 0) - blobStorageItem := make(map[string]interface{}) blobStorageItem["level"] = string(blobStorageInput.Level) @@ -1143,17 +1144,12 @@ func FlattenAppServiceLogs(input *web.SiteLogsConfigProperties) []interface{} { } // The API returns a non nil application logs object when other logs are specified so we'll check that this structure is empty before adding it to the statefile. - if blobStorageInput.SasURL != nil { + if blobStorageInput.SasURL != nil && *blobStorageInput.SasURL != "" { blobStorage = append(blobStorage, blobStorageItem) - appLogsItem["azure_blob_storage"] = blobStorage } - } - - if len(appLogsItem) > 0 { - appLogs = append(appLogs, appLogsItem) - } - + appLogsItem["azure_blob_storage"] = blobStorage + appLogs = append(appLogs, appLogsItem) } result["application_logs"] = appLogs @@ -1161,8 +1157,8 @@ func FlattenAppServiceLogs(input *web.SiteLogsConfigProperties) []interface{} { if input.HTTPLogs != nil { httpLogsItem := make(map[string]interface{}) + fileSystem := make([]interface{}, 0) if fileSystemInput := input.HTTPLogs.FileSystem; fileSystemInput != nil { - fileSystem := make([]interface{}, 0) fileSystemItem := make(map[string]interface{}) @@ -1177,14 +1173,10 @@ func FlattenAppServiceLogs(input *web.SiteLogsConfigProperties) []interface{} { // The API returns a non nil filesystem logs object when other logs are specified so we'll check that this is disabled before adding it to the statefile. if fileSystemInput.Enabled != nil && *fileSystemInput.Enabled { fileSystem = append(fileSystem, fileSystemItem) - - httpLogsItem["file_system"] = fileSystem } } - - if len(httpLogsItem) > 0 { - httpLogs = append(httpLogs, httpLogsItem) - } + httpLogsItem["file_system"] = fileSystem + httpLogs = append(httpLogs, httpLogsItem) } result["http_logs"] = httpLogs From 8927029b3da9f4cfab8dfa7ac284906f7548ff39 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Thu, 15 Aug 2019 12:08:42 -0700 Subject: [PATCH 4/4] Addressing final comment --- azurerm/resource_arm_app_service_test.go | 26 +++++++----------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/azurerm/resource_arm_app_service_test.go b/azurerm/resource_arm_app_service_test.go index 42a059b37ea5..d045b947784c 100644 --- a/azurerm/resource_arm_app_service_test.go +++ b/azurerm/resource_arm_app_service_test.go @@ -995,7 +995,8 @@ func TestAccAzureRMAppService_httpFileSystemLogs(t *testing.T) { func TestAccAzureRMAppService_httpFileSystemAndStorageBlobLogs(t *testing.T) { resourceName := "azurerm_app_service.test" ri := tf.AccRandTimeInt() - config := testAccAzureRMAppService_httpFileSystemAndStorageBlobLogs(ri, testLocation()) + rs := acctest.RandString(5) + config := testAccAzureRMAppService_httpFileSystemAndStorageBlobLogs(ri, rs, testLocation()) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -3270,23 +3271,10 @@ resource "azurerm_app_service" "test" { `, rInt, location, rInt, rInt) } -func testAccAzureRMAppService_httpFileSystemAndStorageBlobLogs(rInt int, location string) string { +func testAccAzureRMAppService_httpFileSystemAndStorageBlobLogs(rInt int, rString string, location string) string { + template := testAccAzureRMAppService_backupTemplate(rInt, rString, location) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -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" - } -} +%s resource "azurerm_app_service" "test" { name = "acctestAS-%d" @@ -3298,7 +3286,7 @@ resource "azurerm_app_service" "test" { application_logs { azure_blob_storage { level = "Information" - sas_url = "http://x.com/" + sas_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" retention_in_days = 3 } } @@ -3310,7 +3298,7 @@ resource "azurerm_app_service" "test" { } } } -`, rInt, location, rInt, rInt) +`, template, rInt) } func testAccAzureRMAppService_managedPipelineMode(rInt int, location string) string {