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

Support app service HTTP blob logging #4249

Merged
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
54 changes: 54 additions & 0 deletions azurerm/helpers/azure/app_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,26 @@ func SchemaAppServiceLogsConfig() *schema.Schema {
},
},
},
ConflictsWith: []string{"logs.0.http_logs.0.azure_blob_storage"},
},
"azure_blob_storage": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sas_url": {
Type: schema.TypeString,
Required: true,
Sensitive: true,
},
"retention_in_days": {
Type: schema.TypeInt,
Required: true,
},
},
},
ConflictsWith: []string{"logs.0.http_logs.0.file_system"},
},
},
},
Expand Down Expand Up @@ -1190,7 +1210,27 @@ func FlattenAppServiceLogs(input *web.SiteLogsConfigProperties) []interface{} {
fileSystem = append(fileSystem, fileSystemItem)
}
}

blobStorage := make([]interface{}, 0)
if blobStorageInput := input.HTTPLogs.AzureBlobStorage; blobStorageInput != nil {
blobStorageItem := make(map[string]interface{})

if blobStorageInput.SasURL != nil {
blobStorageItem["sas_url"] = *blobStorageInput.SasURL
}

if blobStorageInput.RetentionInDays != nil {
blobStorageItem["retention_in_days"] = *blobStorageInput.RetentionInDays
}

// The API returns a non nil blob logs object when other logs are specified so we'll check that this is disabled before adding it to the statefile.
if blobStorageInput.Enabled != nil && *blobStorageInput.Enabled {
blobStorage = append(blobStorage, blobStorageItem)
}
}

httpLogsItem["file_system"] = fileSystem
httpLogsItem["azure_blob_storage"] = blobStorage
httpLogs = append(httpLogs, httpLogsItem)
}
result["http_logs"] = httpLogs
Expand Down Expand Up @@ -1253,6 +1293,20 @@ func ExpandAppServiceLogs(input interface{}) web.SiteLogsConfigProperties {
}
}
}

if v, ok := httpLogsConfig["azure_blob_storage"]; ok {
storageConfigs := v.([]interface{})

for _, config := range storageConfigs {
storageConfig := config.(map[string]interface{})

logs.HTTPLogs.AzureBlobStorage = &web.AzureBlobStorageHTTPLogsConfig{
SasURL: utils.String(storageConfig["sas_url"].(string)),
RetentionInDays: utils.Int32(int32(storageConfig["retention_in_days"].(int))),
Enabled: utils.Bool(true),
}
}
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion azurerm/resource_arm_app_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,9 +586,11 @@ func resourceArmAppServiceRead(d *schema.ResourceData, meta interface{}) error {

appSettings := flattenAppServiceAppSettings(appSettingsResp.Properties)

// remove DIAGNOSTICS* settings - Azure will sync these, so just maintain the logs block equivalents in the state
// remove DIAGNOSTICS*, WEBSITE_HTTPLOGGING* settings - Azure will sync these, so just maintain the logs block equivalents in the state
delete(appSettings, "DIAGNOSTICS_AZUREBLOBCONTAINERSASURL")
delete(appSettings, "DIAGNOSTICS_AZUREBLOBRETENTIONINDAYS")
delete(appSettings, "WEBSITE_HTTPLOGGING_CONTAINER_URL")
delete(appSettings, "WEBSITE_HTTPLOGGING_RETENTION_DAYS")

if err := d.Set("app_settings", appSettings); err != nil {
return fmt.Errorf("Error setting `app_settings`: %s", err)
Expand Down
60 changes: 60 additions & 0 deletions azurerm/resource_arm_app_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,44 @@ func TestAccAzureRMAppService_httpFileSystemLogs(t *testing.T) {
})
}

func TestAccAzureRMAppService_httpBlobStorageLogs(t *testing.T) {
resourceName := "azurerm_app_service.test"
ri := tf.AccRandTimeInt()
rs := acctest.RandString(5)
config := testAccAzureRMAppService_httpBlobStorageLogs(ri, rs, 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_httpFileSystemAndStorageBlobLogs(t *testing.T) {
resourceName := "azurerm_app_service.test"
ri := tf.AccRandTimeInt()
Expand Down Expand Up @@ -3343,6 +3381,28 @@ resource "azurerm_app_service" "test" {
}
`, rInt, location, rInt, rInt)
}
func testAccAzureRMAppService_httpBlobStorageLogs(rInt int, rString string, 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}"

logs {
http_logs {
azure_blob_storage {
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
}
}
}
}
`, template, rInt)
}

func testAccAzureRMAppService_httpFileSystemAndStorageBlobLogs(rInt int, rString string, location string) string {
template := testAccAzureRMAppService_backupTemplate(rInt, rString, location)
Expand Down
16 changes: 9 additions & 7 deletions website/docs/r/app_service.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -145,19 +145,21 @@ An `application_logs` block supports the following:

---

An `azure_blob_storage` block supports the following:

* `level` - (Required) The level at which to log. Possible values include `Error`, `Warning`, `Information`, `Verbose` and `Off`.
An `http_logs` block supports *one* of the following:

* `sas_url` - (Required) The URL to the storage container, with a Service SAS token appended. **NOTE:** there is currently no means of generating Service SAS tokens with the `azurerm` provider.
* `file_system` - (Optional) A `file_system` block as defined below.

* `retention_in_days` - (Required) The number of days to retain logs for.
* `azure_blob_storage` - (Optional) An `azure_blob_storage` block as defined below.

---

An `http_logs` block supports the following:
An `azure_blob_storage` block supports the following:

* `file_system` - (Optional) A `file_system` block as defined below.
* `level` - (Required) The level at which to log. Possible values include `Error`, `Warning`, `Information`, `Verbose` and `Off`. **NOTE:** this field is not available for `http_logs`

* `sas_url` - (Required) The URL to the storage container, with a Service SAS token appended. **NOTE:** there is currently no means of generating Service SAS tokens with the `azurerm` provider.

* `retention_in_days` - (Required) The number of days to retain logs for.

---

Expand Down