I am trying to write a generic Bicep file that creates a storage account. I am trying to following the standard naming convention when creating the resource, eg: it would be something like st<storage name><location-code><###>.
What I want to do is parameterize the 'location' value. If I do this though, how can I get the abbreviated 'region code' to put in the name. Eg: If I pass in Central US as the region, the name would be sttestcus001. If I put in East US, the name would be sttesteus001.
Thanks,
You could always maintain an object that will do the mapping for you:
param location string = 'Central US'
// Object containing a mapping for location / region code
var regionCodes = {
centralus: 'cus'
eastus: 'eus'
}
// remove space and make sure all lower case
var satinatizedLocation = toLower(replace(location, ' ', ''))
// get the region code
var regionCode = regionCodes[satinatizedLocation]
Related
The problem I am trying to solve is I need to identify one of the Azure subnets in a virtual network by part of it's name. This is so I can then later retrieve it's CIDR. I only know part beforehand such as "mgmt-1" or "egress-1". The actual name of the subnet is much longer but will end in something like that. This was my process:
I have the vnet name so I pull all subnets:
data "azurerm_virtual_network" "this" {
name = local.vnet
resource_group_name = "myrg"
}
Now what I wish I could do is this:
locals {
mgmt_index = index(data.azurerm_virtual_network.this.subnets, "*mgmt-1")
mgmt_subnet = data.azurerm_virtual_network.this.subnets[local.mgmt_index]
}
However index wants an exact match, not a regex. Is this possible to do? Perhaps a better way?
Thank you,
It is not possible to directly look up a list item using a regex match, but you can use for expressions to apply arbitrary filters to a collection when constructing a new collection:
locals {
mgmt_subnets = toset([
for s in data.azurerm_virtual_network.this.subnets : s
if can(regex(".*?mgmt-1", s.name))
])
}
In principle an expression like the above could match more than one object, so I wrote this to produce a set of objects that match.
If you expect that there will never be more than one object whose name matches the pattern then you can use Terraform's one function to assert that and then Terraform will check to confirm that there's no more than one element (returning an error if not) and then return that one value.
locals {
mgmt_subnet = one([
for s in data.azurerm_virtual_network.this.subnets : s
if can(regex(".*?mgmt-1", s.name))
])
}
If the condition doesn't match any of the subnet objects then in the first case you'll have an empty set and in the second case you'll have the value null.
In my Terraform configuration, I want to obtain the names of all members of an Azure AD Group called "`VaultUsers`" and then read and display the result from my Terraform output file called `outputs.tf`.
I have two snippets of Terraform configuration that complete part of the above task, as described below.
[ Snippet 1 ]
This first code block will display the object ids of the group members. Unfortunately, the test.group. object does not include a property to display the group member names and so for now, I'm simply displaying the Azure AD object id of each group member by using the notation - data.azuread_group.test_group.members.
data "azuread_group" "test_group" {
display_name = "VaultUsers"
}
output "azuread_groups_root-users" {
value = data.azuread_group.test_group.members
}
The second snippet (below) on the other hand, will display a large chunk of Azure AD metadata for each group member, including the following:
+ mail_nicknames
+ object_ids
+ user_principal_names
[ Snippet 2 ]
data "azuread_users" "users" {
return_all = true
}
output "azuread_groups_root-user-members" {
value = data.azuread_users.users
}
Crucially, it also displays the below additional metadata in a users block and ultimately, it is the display_name value that I'm desperately seeking to extract. Any idea or suggestions on how I can achieve this?
I already have a azure app service plan, from which i want to get the sku->tier property
data "azurerm_app_service_plan" "shared" {
name = "SharedMove-AP"
resource_group_name = "SharedMove-RG"
}
Since SKU itself is a block as defined below
How can i get the tier property inside the sku ?
I tried like
app_service_plan_tier = "${data.azurerm_app_service_plan.shared.sku.tier}"
But i got the error like
This value does not have any attributes.
How can i get the tier property inside the sku block from data module ?
Could you possibly try
data.azurerm_app_service_plan.shared.sku[0].tier
Might need to declare the index position.
So i want to get the variable in the terraform remote state, however we have a number of different one per environment on the shared route53
So for a given environement, we want to pull the zone id out as such;
zone_id = data.terraform_remote_state.route_53.route53_zone_${var.environment}_id
How would I do this please.
In general, it is not possible to use arbitrary dynamic strings as variable names.
However, in this particular case the outputs from terraform_remote_state are collection values and so you can use the index syntax to access a dynamically-built key from your map value:
data.terraform_remote_state.outputs.route53["route53_zone_${var.environment}_id"]
With that said, if possible I would recommend structuring the output values better so that the Route53 zone ids are given as a map by environment, so that this can be obtained in a more intuitive way.
For example, you could make your route53 output be a map of objects whose keys are the environment names:
data.terraform_remote_state.outputs.route53[var.environment].zone_id
output "route53" {
value = tomap({
production = {
zone_id = aws_route53_zone.production.id
}
staging = {
zone_id = aws_route53_zone.staging.id
}
})
}
Or, if you have a variety of different per-environment settings you could structure it as a single output value that is a map of all of those per environment settings keyed by environment name:
data.terraform_remote_state.outputs.environments[var.environment].route53_zone_id
output "environments" {
value = tomap({
production = {
ec2_vpc_id = aws_vpc.production.id
route53_zone_id = aws_route53_zone.production.id
}
staging = {
ec2_vpc_id = aws_vpc.staging.id
route53_zone_id = aws_route53_zone.staging.id
}
})
}
This doesn't change anything about the ultimate result, but grouping things by your environment keys in your outputs is likely to make your intent clearer to future maintainers of these configurations.
(You might also consider whether it'd be better to have a separate configuration/state per environment rather than managing them altogether, but that is a big topic in itself.)
Please excuse if this is a dumb question. I'm a terraform noob and trying to determine the best approach to meet an enterprise requirement for resource naming.
Our cloud governance team has determined a naming scheme for all resources where you have [region][resource_type][app_name][instance 0001-999][env] So, for instance we might have something like the following for vm's:
uw1vmmyapp001dev
uw1vmmyapp002dev
etc.
This is all well and good when deploying from scratch as I just use the {count.index} However, now I am trying to determine how to deploy additional resources and start from the previously deloyed resources (that weren't deployed by terraform). Is there a terraform standard for gathering the existing inventory, parsing the current values and starting your incrementing from the highest instance number? (I was using randoms but our cloud governance team squashed that quickly.)
I'm really doing a poor job with my wording. Hopefully this makes some sort of sense?
Oh, I'm using azurerm_virtual_machine
It's going to be pretty difficult when there isn't any delimiting characters... it's just a shoved together string. If there was a delimiting character you could maybe use split to break up the string and find out the number portion. There also doesn't appear to be a data source equivalent of azurerm_virtual_machine to get the naming information anyway.
Given that you'd need to manually look up the name or id anyway to import information about current resources you could find the highest numbered VM then use something like the following to add additional VMs and increment the number:
${var.region}${var.resource_type}${var.appname}${format("%03d", count.index + var.last_num)}${var.env}
To test what this looks like you can look at this example:
variable "last_num" {
default = 98
}
variable "region" {
default = "uw"
}
variable "resource_type" {
default = "vm"
}
variable "appname" {
default = "myapp"
}
variable "env" {
default = "dev"
}
resource "local_file" "foo" {
count = 3
filename = "foo.text"
content = "${var.region}${var.resource_type}${var.appname}${format("%03d", count.index + 1 + var.last_num)}${var.env}"
}
This gives naming output like this:
+ local_file.foo[0]
id: <computed>
content: "uwvmmyapp099dev"
filename: "foo.text"
+ local_file.foo[1]
id: <computed>
content: "uwvmmyapp100dev"
filename: "foo.text"
+ local_file.foo[2]
id: <computed>
content: "uwvmmyapp101dev"
filename: "foo.text"