Hi all,
Firstly, excuse me if the question seems silly. My excuse, I have come from an Ops background
I am working with the “azurerm_log_analytics_solution” resource and it seems that the solution_name
must match the product name.
For example the product would be OMSGallery/Updates
and the solution_name
must be Updates
.
My challenge is to extract “Updates” from product.
I have declared this variable to be used;
variable “plan” {
type = list(object(
{
publisher = string
product = string
}
))
default = [
{
publisher = "Microsoft"
product = "OMSGallery/Updates"
}
]
}
I am struggling to extract “Updates” from this variable.
I have tried various functions and using the Terraform console this is easily done when not tackling an object;element(split("/","Product/Updates"),1)
Using Terraform v0.12.26
Any help would be appreciated.
Thanks.
Hi @CrowersEDF,
It seems like you are on the right track here: splitting on /
and taking the second element (index one) is indeed a reasonable way to extract the second part of those slash-separated strings.
The remaining challenge is how to do that systematically for all of your elements of var.plan
. Unfortunately there are numerous ways to do that and which one to choose depends a lot on what you ultimately intend to do with this value, and because I’m not familiar with azurerm_log_analytics_solution
I don’t feel qualified to guess what that would look like.
Could you share an example of roughly what you’re expecting the azurerm_log_analytics_solution
resource configuration to look like? Don’t worry about getting the syntax exactly right… I’m just hoping to see where the different parts of this var.plan
fit in.
Thanks for the reply ApparentlyMart.
here is the configuration;
resource “azurerm_log_analytics_solution” “law_solution_updates” {
solution_name = element(split(“/”, var.plan.value.product), 1) # hardcoding “Updates” works, whereas any other name hardcoded string does not.
location = var.location
resource_group_name = var.resource_group_name
workspace_resource_id = data.azurerm_log_analytics_workspace.law.id
workspace_name = data.azurerm_log_analytics_workspace.law.name
dynamic “plan” {
for_each = var.plan
content {
publisher = plan.value.publisher
product = plan.value.product
}
}
}
the issue with this resource is that the solution_name
must be “Updates”, in this working example.
Running terraform plan
doesnt throw up an error, the following error only occurs after confirming the apply
pollingTrackerBase#updateRawBody: failed to unmarshal response body: StatusCode=0 – Original Error: invalid character ‘F’ looking for beginning of value on …\main.tf
Therefore, I need to extract “Updates” from from the product argument. I dont really want to create a separate variable if I can help it.
The syntax error I get with the current config is;
Error: Unsupported attribute
*** on main.tf line 13, in resource “azurerm_log_analytics_solution” “law_solution_updates”:***
*** 13: solution_name = element(split(“/”, var.plan.value.product), 1)***
This value does not have any attributes.
Thanks for your support.
Hi @CrowersEDF. Thanks for that additional context!
I was pretty baffled by the design of this resource, because in your example it looks like there would be one plan
block per entry in var.plan
, but the solution_name
isn’t in the plan
block, so was unclear to me what value it ought to take if there were more than one element of var.plan
with different suffixes.
In the end I had to go have a look at the provider source code to understand how this resource type is supposed to work. It looks like the provider only expects a single plan
block, so I think the repetition must be of the resource as a whole rather than the plan
block in particular.
That suggests something like this:
resource “azurerm_log_analytics_solution” “law_solution_updates” {
for_each = {
for p in var.plan : "${p.publisher} ${p.product}" => p
}
solution_name = split("/", each.value.product)[1]
location = var.location
resource_group_name = var.resource_group_name
workspace_resource_id = data.azurerm_log_analytics_workspace.law.id
workspace_name = data.azurerm_log_analytics_workspace.law.name
plan {
publisher = each.value.publisher
product = each.value.product
}
}
Resource for_each
requires each instance to have a unique identifier string associated with it so Terraform can track the instances, so for the sake of this example I just put the publisher and product together into a single string, which will produce addresses like this:
azurerm_log_analytics_solution.law_solution_updates["Microsoft OMSGallery/Updates"]
This identifier format means that if you edit the publisher
or product
of an existing object then Terraform will understand it as the intent to destroy an existing log analytics solution and create a new one, rather than to edit in-place. If you want to be able to edit in-place then you’d need to give each element an explicit unique identifier inside your configuration, which you could do by changing variable "plan"
to be a map instead of a list and then assign that map directly to the for_each
argument.
1 Like
Wow, thanks for taking the time to research this for me.
I did notice that after adding a new item in to the list and it bombed out for the reason you mention.
I haven’t had chance to test your code block yet, I will update you to let you know how it goes.
I would never have thought of doing this though;
azurerm_log_analytics_solution.law_solution_updates["Microsoft OMSGallery/Updates"]
I have a lot to learn
Hey @apparentlymart, just following up.
After some testing (and playing so I understand what is going on), I am happy with this approach and thought it would be courteous so say.
Thanks for taking the time out to reply and I’m grateful for the little education along the way…