Closed ms-henglu closed 2 months ago
Other considerations here @ms-henglu can we do them?
Locations could work like this:
https://registry.terraform.io/modules/Azure/regions/azurerm/latest
Merging date from locations API and compute provider to determine if a location has zones support.
We should cache the API response in the provider to adhere to HashiCorp's recommendation. This means we get consistent results. Plus the data won't change that frequently.
@stemaMSFT @grayzu
Hello! Looking for any suggestions on the function to build Azure resource IDs. I think there are two options:
Allow users to provide parentID
, resource type
, and name
to construct the resource ID, as described in this guide.
Pros: quite straightforward & less parameters needed
Cons: users may not know what the parent id is?
Allow users to provide resource type
, name
, and other specifics like subscription ID
and resource group name
etc..., and use those to construct the parentID
internally, which is then used to build the full resource ID.
Pros: referring to more specific names that user knows about
Cons: too many parameters & a lot of cases to think about in building the parent id internally
@hqhqhqhqhqhqhqhqhqhqhq I think it would make sense to do option 1, since that would be consistent with the behavior of AzAPI (as parent_id
is already a parameter in resource definitions). It keeps consistent with Azure as well, which is what we're aiming for philosophically with AzAPI.
I think we could have a few functions.
The option 1 as mentioned above plus dedicated functions for the four major scopes in azure:
Tenant - just need resource type and name
Management group - need MG id plus resource type and name
Subscription - need sub id, resource type and name
Resource group - sub id, RG name, resource type and name
For more complex scenarios we can use the parent id option and maybe nest the functions?
@matt-FFFFFF would you mind elaborating on why you prefer four separate functions compared to one function to construct resource IDs generically? Maybe with some scenarios. Would help us understand which direction to take.
@matt-FFFFFF would you mind elaborating on why you prefer four separate functions compared to one function to construct resource IDs generically? Maybe with some scenarios. Would help us understand which direction to take.
@stemaMSFT
Thinking more I think this could be one function, with a variadic input.
E.g.
provider::azapi::resource_id("resource_group", "<subscription id>", "<resource group name>", "<resource type>", "<resource name>")
provider::azapi::resource_id("management_group", "<management group id>", "<resource type>", "<resource name>")
provider::azapi::resource_id("tenant", "<resource type>", "<resource name>")
provider::azapi::resource_id("parent", "<parent resource id>" , "<resource type>", "<resource name>")
And so on. As long as each mode was identified by the first input I think that would work.
Makes sense to me. @ms-henglu if you don't have any other concerns, I think we can move forward with this approach.
Hi @matt-FFFFFF ,
Thanks for the suggestions! But unfortunately variadic function is supported by the Terraform provider function.
How about the below design proposed by @hqhqhqhqhqhqhqhqhqhqhq https://github.com/Azure/terraform-provider-azapi/pull/553#issue-2408065215
@matt-FFFFFF @stemaMSFT Adding to above, I think the difference lies where the scope is defined. We can:
pros:
cons:
pros:
cons:
may become more complex given that different scopes needs different number of parameters
personally think having multiple functions can be more suitable, especially that it's not likely for more scope types to be introduced anytime soon, so it really just need 4-5 more functions
I just noticed that the bicep/ARM templates have similar functions: https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions-resource#subscriptionresourceid
So I'm proposing the following functions which are similar with the bicep's.
The # 1 function is just the provider function implementation of the azapi_resource_id
data source. And the rest of them allow user to build the resource ID with only the "name" part, for example, the management group name, resource group name and each resource name. Users don't need to worry about the ID format.
And to support nested resource under different deployed scope, the last argument of these functions is a list of string. More details please see the below examples:
resourceId(resourceType, parentId, name)
Example:
resourceId("Microsoft.Network/virtualNetworks", "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1", "vnet1")
= "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/virtualNetworks/vnet1"
tenantResourceId(resourceType, [resourceName1, resourceName2, ...])
Example:
tenantResourceId("Microsoft.Billing/billingAccounts/billingProfiles", ["ba1", "bp1"])
= "/providers/Microsoft.Billing/billingAccounts/ba1/billingProfiles/bp1"
subscriptionResourceId(subscriptionId, resourceType, [resourceName1, resourceName2, ...])
Example:
subscriptionResourceId("00000000-0000-0000-0000-000000000000", "Microsoft.Resources/resourceGroups", ["rg1"])
= "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1"
managementGroupResourceId(managementGroupName, resourceType, [resourceName1, resourceName2, ...])
Example:
managementGroupResourceId("mg1", "Microsoft.Billing/billingAccounts/billingProfiles", ["ba1", "bp1"])
= "/providers/Microsoft.Management/managementGroups/mg1/providers/Microsoft.Billing/billingAccounts/ba1/billingProfiles/bp1"
extensionResourceId(resourceId, extensionName, [resourceName1, resourceName2, ...])
Example:
extensionResourceId("/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/virtualNetworks/vnet1", "Microsoft.Authorization/locks", ["mylock"])
= "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/virtualNetworks/vnet1/providers/Microsoft.Authorization/locks/mylock"
resourceGroupResourceId(subscriptionId, resourceGroupName, resourceType, [resourceName1, resourceName2, ...])
Example:
resourceGroupResourceId("00000000-0000-0000-0000-000000000000", "rg1", "Microsoft.Network/virtualNetworks/subnets", ["vnet1", "subnet1"])
= "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.Network/virtualNetworks/vnet1/subnets/subnet1"
To support functions like
refs: https://developer.hashicorp.com/terraform/plugin/framework/functions/concepts