Azure / azure-rest-api-specs

The source for REST API specifications for Microsoft Azure.
MIT License
2.63k stars 5.05k forks source link

Storage Account deployment fails when isHnsEnabled = false #18441

Open KenBenjamin opened 2 years ago

KenBenjamin commented 2 years ago

Setting isHnsEnabled: false throws an error: The property 'isHnsEnabled' was specified in the input, but it cannot be updated as it is read-only. For more information, see - https://aka.ms/storageaccountupdate

When setting isHnsEnabled: true, you can successfully redeploy the storage account.

Tested when deploying and redeploying storage accounts via Bicep using 'Microsoft.Storage/storageAccounts@2021-08-01' against pre-existing non-Hns storage accounts (created with API v. 2021-04-01) and when creating an Hns storage account.

Also see other people reporting the same issue:

blueww commented 2 years ago

@KenBenjamin

If you want to enable HNS on an exist account, you need to use hnsonmigration API in: https://github.com/Azure/azure-rest-api-specs/blob/568e394c3634d052ddec89f685b4afb5ab21aaec/specification/storage/resource-manager/Microsoft.Storage/stable/2021-09-01/storage.json#L780 (First run the API with requestType 'HnsOnValidationRequest', if no error, then with requestType 'HnsOnHydrationRequest')

isHnsEnabled: true can only be set on create a new storage account .

KenBenjamin commented 2 years ago

@blueww I appreciate the information but I'm not trying to alter the existing settings. I simply want to run an ARM template more than once without error. Templates are supposed to be idempotent but this specific property setting breaks that for the Storage Account API. It's a bug.

blueww commented 2 years ago

As the error is from server, we need include server team to look at this.

@HimanshuChhabra , @priyapansrp Would you please help to look at the issue? It looks breaking the ARM template since not idempotent.

crimsonical commented 2 years ago

Some additional information as I am experiencing the same problem.

The error only occurs when a resource was originally deployed without defining a value for isHnsEnabled, and then redeploying it with isHnsEnabled set to false.

IF the resource was deployed orignially with isHnsEnabled set to false, it can be redeployed without issues.

One way to check whether the value for isHnsEnabled was set during the original deployment is by exporting an arm template for the deployed resource and checking under properties whether the isHnsEnabled property is present.

A possible solution could be for Azure to add the property isHnsEnabled to all existing storage accounts. Or not to throw an error when the property is added to and existing deployment if the value is set to false.

brantley-svt commented 1 year ago

Running into this issue as well. I found a workaround using union() but it ain't pretty.

param storageAccountName string
param storageAccountType string
param storageAccountSku string
param isHnsEnabled bool

var properties = {
  allowBlobPublicAccess: false
  minimumTlsVersion: 'TLS1_2'
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-02-01' = {
  name: storageAccountName
  location: location
  kind: storageAccountType
  sku: {
    name: storageAccountSku
  }
  properties: isHnsEnabled ? union(properties, {isHnsEnabled: true}) : properties
}
JakobGSvendsen commented 1 year ago

we have the same issue, but in our case we use a central storage account of approved ARM templates, so we cannot make the union fix, and then fixes in ARM template is even uglier. Any news on this issue?

We need to have everyone upgrade their template to a newer approved version but this blocks usunless we make the template with conditional resource deployments or move all config of the resource into variables and use union there. any other ideas is very welcomed.

One fix is of cause to run the upgrade API command (we did it via powershell), but this can only be done if we want it enabled, and not if we want it to stay disabled. This adds risks for whether the code and scripts using the accounts will continue to work or not. is there a way to run the migration without enabling it?

rasmus-watjen commented 11 months ago

This issue seems to be forgotten. It's also misclassified as a question. It may have started out that way, but it seems to be a bug.

Redeploying a resource where the default value is explicitly declared should be possible.

blueww commented 11 months ago

@rasmus-watjen

This is a server issue, instead of pure swagger issue. To get more efficient responds from server team, you can raise a help ticker on Azure Portal, see details here.

theplankmeister commented 9 months ago

This is also a problem affecting our infrastructure. We have several hundred deployed storage accounts. In a specific scenario for a single storage account, we need to specifically control the isHnsEnabled flag, the problem is that none of the deployed SAs have this setting, and, as mentioned, not having the flag set, and setting it as false are considered to be changing the flag, which results in us not being able to re-deploy infrastructure, which is a huge problem. Please, @HimanshuChhabra @priyapansrp can you triage this issue so we have an idea of timescale for a fix to this issue?

o-l-a-v commented 3 months ago

I'm in the same situation as @theplankmeister. Wanted to adopt AVM for existing Storage Accounts with no value for isHnsEnabled, but I now learned I can't.

Just to confirm, we'd be right to expect that "isHnsEnabled": null should go through then, if the resource provider played by the rules? Like AVM does it here:

theplankmeister commented 3 months ago

@o-l-a-v In the end, our solution was to migrate from an ARM template to Bicep, that provides the "union" feature. The bicep solution looks something like this (extraneous code removed):

param isHnsEnabled bool = false

var hnsPropertyObject = isHnsEnabled ? {
  isHnsEnabled: true
} : {}

resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: storageAccountName
  location: location
  kind: 'StorageV2'
  sku: {
    name: storageSKU
  }
  identity: {
    type: 'SystemAssigned'
  }
  properties: union({
    accessTier: 'Hot'
    supportsHttpsTrafficOnly: true
    allowBlobPublicAccess: allowBlobPublicAccess

    networkAcls: {
      defaultAction: (length(ipRules) > 0) || !empty(subnetId) ? 'Deny' : 'Allow'
      resourceAccessRules: resourceAccessRulesObject
      ipRules: networkIpRules
      virtualNetworkRules: virtualNetworkRules
    }
  }, hnsPropertyObject)
}

...so if the provided isHnsEnabled is false, the object merged by the union in the properties value is an empty object, and therefore won't encounter the problem. If isHnsEnabled is true (for new storage accounts), then when union merges the properties, the isHnsEnabled key is correctly set.

Hope this helps.

o-l-a-v commented 3 months ago

Thanks @theplankmeister. 😊