Edit

Share via


Linter rule - no hardcoded locations

This rule finds uses of Azure location values that aren't parameterized.

Note

This rule is off by default. Change the level in bicepconfig.json to enable it.

Linter rule code

Use the following value in the Bicep configuration file to customize rule settings:

no-hardcoded-location

Solution

Template users may have limited access to regions where they can create resources. A hardcoded resource location might block users from creating a resource, thus preventing them from using the template. By providing a location parameter that defaults to the resource group location, users can use the default value when convenient but also specify a different location.

Rather than using a hardcoded string or variable value, use a parameter, the string 'global', or an expression (but not resourceGroup().location or deployment().location, see no-loc-expr-outside-params). Best practice suggests that to set your resources' locations, your template should have a string parameter named location. This parameter may default to the resource group or deployment location (resourceGroup().location or deployment().location).

The following example fails this test because the resource's location property uses a string literal:

resource stg 'Microsoft.Storage/storageAccounts@2024-01-01' = {
  name: 'stg'
  location: 'westus'
  kind: 'StorageV2'
  sku: {
    name: 'Premium_LRS'
  }
}

You can fix it by creating a new location string parameter (which may optionally have a default value - resourceGroup().location is frequently used as a default):

param location string = resourceGroup().location

resource stg 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  name: 'stg${uniqueString(resourceGroup().id)}'
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Premium_LRS'
  }
}

Use Quick Fix to create a location parameter and replace the string literal with the parameter name. See the following screenshot:

The screenshot of No hardcoded location linter rule warning with quickfix.

The following example fails this test because the resource's location property uses a variable with a string literal.

var location = 'westus'
resource stg 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  location: location
}

You can fix it by turning the variable into a parameter:

param location string = 'westus'
resource stg 'Microsoft.Storage/storageAccounts@2023-04-01' = {
    location: location
}

The following example fails this test because a string literal is being passed in to a module parameter that is in turn used for a resource's location property:

module m1 'module1.bicep' = {
  name: 'module1'
  params: {
    location: 'westus'
  }
}

where module1.bicep is:

param location string

resource storageaccount 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  name: 'storageaccount'
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Premium_LRS'
  }
}

You can fix the failure by creating a new parameter for the value:

param location string // optionally with a default value
module m1 'module1.bicep' = {
  name: 'module1'
  params: {
    location: location
  }
}

Next steps

For more information about the linter, see Use Bicep linter.