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

azurerm_[linux|windows]_function_app and azurerm_[linux|windows]_function_app_slot add storage_account #18760

Merged
merged 11 commits into from
Oct 24, 2022
Merged
30 changes: 28 additions & 2 deletions internal/services/appservice/linux_function_app_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type LinuxFunctionAppModel struct {
HttpsOnly bool `tfschema:"https_only"`
KeyVaultReferenceIdentityID string `tfschema:"key_vault_reference_identity_id"`
SiteConfig []helpers.SiteConfigLinuxFunctionApp `tfschema:"site_config"`
StorageAccounts []helpers.StorageAccount `tfschema:"storage_account"`
Tags map[string]string `tfschema:"tags"`
VirtualNetworkSubnetID string `tfschema:"virtual_network_subnet_id"`

Expand Down Expand Up @@ -251,6 +252,8 @@ func (r LinuxFunctionAppResource) Arguments() map[string]*pluginsdk.Schema {

"sticky_settings": helpers.StickySettingsSchema(),

"storage_account": helpers.StorageAccountSchema(),

"tags": tags.Schema(),

"virtual_network_subnet_id": {
Expand Down Expand Up @@ -493,7 +496,7 @@ func (r LinuxFunctionAppResource) Create() sdk.ResourceFunc {
SlotConfigNames: stickySettings,
}
if _, err := client.UpdateSlotConfigurationNames(ctx, id.ResourceGroup, id.SiteName, stickySettingsUpdate); err != nil {
return fmt.Errorf("updating Sticky Settings for Windows %s: %+v", id, err)
return fmt.Errorf("updating Sticky Settings for Linux %s: %+v", id, err)
}
}

Expand All @@ -511,6 +514,15 @@ func (r LinuxFunctionAppResource) Create() sdk.ResourceFunc {
}
}

storageConfig := helpers.ExpandStorageConfig(functionApp.StorageAccounts)
if storageConfig.Properties != nil {
if _, err := client.UpdateAzureStorageAccounts(ctx, id.ResourceGroup, id.SiteName, *storageConfig); err != nil {
if err != nil {
return fmt.Errorf("setting Storage Accounts for Linux %s: %+v", id, err)
}
}
}

connectionStrings := helpers.ExpandConnectionStrings(functionApp.ConnectionStrings)
if connectionStrings.Properties != nil {
if _, err := client.UpdateConnectionStrings(ctx, id.ResourceGroup, id.SiteName, *connectionStrings); err != nil {
Expand Down Expand Up @@ -568,6 +580,11 @@ func (r LinuxFunctionAppResource) Read() sdk.ResourceFunc {
return fmt.Errorf("reading Sticky Settings for Linux %s: %+v", id, err)
}

storageAccounts, err := client.ListAzureStorageAccounts(ctx, id.ResourceGroup, id.SiteName)
if err != nil {
return fmt.Errorf("reading Storage Account information for Linux %s: %+v", id, err)
}

siteCredentialsFuture, err := client.ListPublishingCredentials(ctx, id.ResourceGroup, id.SiteName)
if err != nil {
return fmt.Errorf("listing Site Publishing Credential information for Linux %s: %+v", id, err)
Expand Down Expand Up @@ -648,6 +665,8 @@ func (r LinuxFunctionAppResource) Read() sdk.ResourceFunc {

state.SiteConfig[0].AppServiceLogs = helpers.FlattenFunctionAppAppServiceLogs(logs)

state.StorageAccounts = helpers.FlattenStorageAccounts(storageAccounts)

state.HttpsOnly = utils.NormaliseNilableBool(functionApp.HTTPSOnly)
state.ClientCertEnabled = utils.NormaliseNilableBool(functionApp.ClientCertEnabled)

Expand Down Expand Up @@ -777,6 +796,13 @@ func (r LinuxFunctionAppResource) Update() sdk.ResourceFunc {
existing.Tags = tags.FromTypedObject(state.Tags)
}

if metadata.ResourceData.HasChange("storage_account") {
storageAccountUpdate := helpers.ExpandStorageConfig(state.StorageAccounts)
if _, err := client.UpdateAzureStorageAccounts(ctx, id.ResourceGroup, id.SiteName, *storageAccountUpdate); err != nil {
return fmt.Errorf("updating Storage Accounts for Linux %s: %+v", id, err)
}
}

storageString := state.StorageAccountName
if !state.StorageUsesMSI {
if state.StorageKeyVaultSecretID != "" {
Expand All @@ -789,7 +815,7 @@ func (r LinuxFunctionAppResource) Update() sdk.ResourceFunc {
if sendContentSettings {
appSettingsResp, err := client.ListApplicationSettings(ctx, id.ResourceGroup, id.SiteName)
if err != nil {
return fmt.Errorf("reading App Settings for Windows %s: %+v", id, err)
return fmt.Errorf("reading App Settings for Linux %s: %+v", id, err)
}
if state.AppSettings == nil {
state.AppSettings = make(map[string]string)
Expand Down
212 changes: 208 additions & 4 deletions internal/services/appservice/linux_function_app_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,79 @@ func TestAccLinuxFunctionApp_withAuthSettingsStandard(t *testing.T) {
})
}

func TestAccLinuxFunctionApp_withStorageAccountBlock(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_linux_function_app", "test")
r := LinuxFunctionAppResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.withStorageAccountSingle(data, SkuStandardPlan),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccLinuxFunctionApp_withStorageAccountBlocks(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_linux_function_app", "test")
r := LinuxFunctionAppResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.withStorageAccountMultiple(data, SkuStandardPlan),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccLinuxFunctionApp_withStorageAccountBlockUpdate(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_linux_function_app", "test")
r := LinuxFunctionAppResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data, SkuStandardPlan),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.withStorageAccountSingle(data, SkuStandardPlan),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.withStorageAccountMultiple(data, SkuStandardPlan),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.withStorageAccountSingle(data, SkuStandardPlan),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.basic(data, SkuStandardPlan),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccLinuxFunctionApp_scmIpRestrictionSubnet(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_linux_function_app", "test")
r := LinuxFunctionAppResource{}
Expand Down Expand Up @@ -3514,7 +3587,6 @@ resource "azurerm_linux_function_app" "test" {
storage_account_access_key = azurerm_storage_account.test.primary_access_key

site_config {}

}
`, r.template(data, planSku), data.RandomInteger, data.RandomInteger)
}
Expand Down Expand Up @@ -3577,15 +3649,13 @@ resource "azurerm_linux_function_app" "test" {
storage_account_access_key = azurerm_storage_account.test.primary_access_key

site_config {}

}
`, r.template(data, planSku), data.RandomInteger, data.RandomInteger)
}

func (r LinuxFunctionAppResource) withASEV3(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

resource "azurerm_storage_account" "test" {
name = "acctestsa%s"
resource_group_name = azurerm_resource_group.test.name
Expand All @@ -3607,6 +3677,140 @@ resource "azurerm_linux_function_app" "test" {
vnet_route_all_enabled = true
}
}

`, ServicePlanResource{}.aseV3Linux(data), data.RandomString, data.RandomInteger)
}

func (r LinuxFunctionAppResource) withStorageAccountSingle(data acceptance.TestData, planSKU string) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

%s

resource "azurerm_linux_function_app" "test" {
name = "acctestWA-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
service_plan_id = azurerm_service_plan.test.id
storage_account_name = azurerm_storage_account.test.name
storage_account_access_key = azurerm_storage_account.test.primary_access_key

site_config {}

storage_account {
name = "files"
type = "AzureFiles"
account_name = azurerm_storage_account.test.name
share_name = azurerm_storage_share.test.name
access_key = azurerm_storage_account.test.primary_access_key
mount_path = "/files"
}
}
`, r.templateWithStorageAccountExtras(data, planSKU), data.RandomInteger)
}

func (r LinuxFunctionAppResource) withStorageAccountMultiple(data acceptance.TestData, planSKU string) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

%s

resource "azurerm_linux_function_app" "test" {
name = "acctestWA-%d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
service_plan_id = azurerm_service_plan.test.id
storage_account_name = azurerm_storage_account.test.name
storage_account_access_key = azurerm_storage_account.test.primary_access_key

site_config {}

storage_account {
name = "files"
type = "AzureFiles"
account_name = azurerm_storage_account.test.name
share_name = azurerm_storage_share.test.name
access_key = azurerm_storage_account.test.primary_access_key
mount_path = "/files"
}

storage_account {
name = "blobs"
type = "AzureBlob"
account_name = azurerm_storage_account.test.name
share_name = azurerm_storage_share.test2.name
access_key = azurerm_storage_account.test.primary_access_key
mount_path = "/blob"
}
}
`, r.templateWithStorageAccountExtras(data, planSKU), data.RandomInteger)
}

func (r LinuxFunctionAppResource) templateWithStorageAccountExtras(data acceptance.TestData, planSKU string) string {
return fmt.Sprintf(`
%s

resource "azurerm_user_assigned_identity" "test" {
name = "acct-%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
}

resource "azurerm_storage_container" "test" {
name = "test"
storage_account_name = azurerm_storage_account.test.name
container_access_type = "private"
}

resource "azurerm_storage_share" "test" {
name = "test"
storage_account_name = azurerm_storage_account.test.name
quota = 1
}

resource "azurerm_storage_container" "test2" {
name = "test2"
storage_account_name = azurerm_storage_account.test.name
container_access_type = "private"
}

resource "azurerm_storage_share" "test2" {
name = "test2"
storage_account_name = azurerm_storage_account.test.name
quota = 1
}

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 = "2021-04-01"
expiry = "2024-03-30"
permissions {
read = false
write = true
delete = false
list = false
add = false
create = false
update = false
process = false
tag = false
filter = false
}
}
`, r.template(data, planSKU), data.RandomInteger)
}
Loading