From 62ba0499309ff515ea6c590f2b67a66445442582 Mon Sep 17 00:00:00 2001 From: Nick Stenning Date: Mon, 19 Nov 2018 16:38:35 +0100 Subject: [PATCH] Support app_command_line in App Service site_config (#2350) App Service supports setting a command line to use with Linux applications (e.g. to override the default in the container image). Expose this configuration as `app_command_line` in `site_config` for `azurerm_app_service`. N.B. This is also referred to as "startup file" by some sources, including the `az` Azure CLI and the Azure Portal. References: - https://docs.microsoft.com/en-us/rest/api/appservice/webapps/createorupdate#siteconfig - https://docs.microsoft.com/en-us/cli/azure/webapp?view=azure-cli-latest#az-webapp-create --- azurerm/helpers/azure/app_service.go | 13 ++++ azurerm/resource_arm_app_service_slot_test.go | 65 +++++++++++++++++++ azurerm/resource_arm_app_service_test.go | 57 ++++++++++++++++ website/docs/d/app_service.html.markdown | 2 + website/docs/r/app_service.html.markdown | 1 + website/docs/r/app_service_slot.html.markdown | 1 + 6 files changed, 139 insertions(+) diff --git a/azurerm/helpers/azure/app_service.go b/azurerm/helpers/azure/app_service.go index e6100981925c..e774fff5dfb8 100644 --- a/azurerm/helpers/azure/app_service.go +++ b/azurerm/helpers/azure/app_service.go @@ -26,6 +26,11 @@ func SchemaAppServiceSiteConfig() *schema.Schema { Default: false, }, + "app_command_line": { + Type: schema.TypeString, + Optional: true, + }, + "default_documents": { Type: schema.TypeList, Optional: true, @@ -221,6 +226,10 @@ func ExpandAppServiceSiteConfig(input interface{}) web.SiteConfig { siteConfig.AlwaysOn = utils.Bool(v.(bool)) } + if v, ok := config["app_command_line"]; ok { + siteConfig.AppCommandLine = utils.String(v.(string)) + } + if v, ok := config["default_documents"]; ok { input := v.([]interface{}) @@ -347,6 +356,10 @@ func FlattenAppServiceSiteConfig(input *web.SiteConfig) []interface{} { result["always_on"] = *input.AlwaysOn } + if input.AppCommandLine != nil { + result["app_command_line"] = *input.AppCommandLine + } + documents := make([]string, 0) if s := input.DefaultDocuments; s != nil { documents = *s diff --git a/azurerm/resource_arm_app_service_slot_test.go b/azurerm/resource_arm_app_service_slot_test.go index 8e4df15aaa4b..80cc4692cb19 100644 --- a/azurerm/resource_arm_app_service_slot_test.go +++ b/azurerm/resource_arm_app_service_slot_test.go @@ -89,6 +89,32 @@ func TestAccAzureRMAppServiceSlot_alwaysOn(t *testing.T) { }) } +func TestAccAzureRMAppServiceSlot_appCommandLine(t *testing.T) { + resourceName := "azurerm_app_service_slot.test" + ri := acctest.RandInt() + config := testAccAzureRMAppServiceSlot_appCommandLine(ri, testLocation()) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAppServiceSlotDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAppServiceSlotExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "site_config.0.app_command_line", "/sbin/myservice -b 0.0.0.0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAzureRMAppServiceSlot_appSettings(t *testing.T) { resourceName := "azurerm_app_service_slot.test" ri := acctest.RandInt() @@ -960,6 +986,45 @@ resource "azurerm_app_service_slot" "test" { `, rInt, location, rInt, rInt, rInt) } +func testAccAzureRMAppServiceSlot_appCommandLine(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}" +} + +resource "azurerm_app_service_slot" "test" { + name = "acctestASSlot-%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}" + app_service_name = "${azurerm_app_service.test.name}" + + site_config { + app_command_line = "/sbin/myservice -b 0.0.0.0" + } +} +`, rInt, location, rInt, rInt, rInt) +} + func testAccAzureRMAppServiceSlot_appSettings(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/azurerm/resource_arm_app_service_test.go b/azurerm/resource_arm_app_service_test.go index 8d435622ea72..4e20bb995c2a 100644 --- a/azurerm/resource_arm_app_service_test.go +++ b/azurerm/resource_arm_app_service_test.go @@ -204,6 +204,32 @@ func TestAccAzureRMAppService_alwaysOn(t *testing.T) { }) } +func TestAccAzureRMAppService_appCommandLine(t *testing.T) { + resourceName := "azurerm_app_service.test" + ri := acctest.RandInt() + config := testAccAzureRMAppService_appCommandLine(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), + resource.TestCheckResourceAttr(resourceName, "site_config.0.app_command_line", "/sbin/myserver -b 0.0.0.0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAzureRMAppService_httpsOnly(t *testing.T) { resourceName := "azurerm_app_service.test" ri := acctest.RandInt() @@ -1255,6 +1281,37 @@ resource "azurerm_app_service" "test" { `, rInt, location, rInt, rInt) } +func testAccAzureRMAppService_appCommandLine(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}" + + site_config { + app_command_line = "/sbin/myserver -b 0.0.0.0" + } +} +`, rInt, location, rInt, rInt) +} + func testAccAzureRMAppService_httpsOnly(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/d/app_service.html.markdown b/website/docs/d/app_service.html.markdown index 83afdbcac849..a8128a791a39 100644 --- a/website/docs/d/app_service.html.markdown +++ b/website/docs/d/app_service.html.markdown @@ -67,6 +67,8 @@ output "app_service_id" { * `always_on` - Is the app be loaded at all times? +* `app_command_line` - App command line to launch. + * `default_documents` - The ordering of default documents to load, if an address isn't specified. * `dotnet_framework_version` - The version of the .net framework's CLR used in this App Service. diff --git a/website/docs/r/app_service.html.markdown b/website/docs/r/app_service.html.markdown index 561f1c0f137e..a39f7e69159b 100644 --- a/website/docs/r/app_service.html.markdown +++ b/website/docs/r/app_service.html.markdown @@ -154,6 +154,7 @@ The following arguments are supported: `site_config` supports the following: * `always_on` - (Optional) Should the app be loaded at all times? Defaults to `false`. +* `app_command_line` - (Optional) App command line to launch, e.g. `/sbin/myserver -b 0.0.0.0`. * `default_documents` - (Optional) The ordering of default documents to load, if an address isn't specified. * `dotnet_framework_version` - (Optional) The version of the .net framework's CLR used in this App Service. Possible values are `v2.0` (which will use the latest version of the .net framework for the .net CLR v2 - currently `.net 3.5`) and `v4.0` (which corresponds to the latest version of the .net CLR v4 - which at the time of writing is `.net 4.7.1`). [For more information on which .net CLR version to use based on the .net framework you're targeting - please see this table](https://en.wikipedia.org/wiki/.NET_Framework_version_history#Overview). Defaults to `v4.0`. * `http2_enabled` - (Optional) Is HTTP2 Enabled on this App Service? Defaults to `false`. diff --git a/website/docs/r/app_service_slot.html.markdown b/website/docs/r/app_service_slot.html.markdown index ee6997d492ce..9345f03f6ba5 100644 --- a/website/docs/r/app_service_slot.html.markdown +++ b/website/docs/r/app_service_slot.html.markdown @@ -183,6 +183,7 @@ The following arguments are supported: `site_config` supports the following: * `always_on` - (Optional) Should the app be loaded at all times? Defaults to `false`. +* `app_command_line` - (Optional) App command line to launch, e.g. `/sbin/myserver -b 0.0.0.0`. * `default_documents` - (Optional) The ordering of default documents to load, if an address isn't specified. * `dotnet_framework_version` - (Optional) The version of the .net framework's CLR used in this App Service Slot. Possible values are `v2.0` (which will use the latest version of the .net framework for the .net CLR v2 - currently `.net 3.5`) and `v4.0` (which corresponds to the latest version of the .net CLR v4 - which at the time of writing is `.net 4.7.1`). [For more information on which .net CLR version to use based on the .net framework you're targeting - please see this table](https://en.wikipedia.org/wiki/.NET_Framework_version_history#Overview). Defaults to `v4.0`. * `http2_enabled` - (Optional) Is HTTP2 Enabled on this App Service? Defaults to `false`.