I have defined an azurerm_resource_group_template_deployment my_rm which has ARM template source:
{
...
"parameters": {... },
"resources": [ ... ],
"outputs": {
"db_name": {
"type": "string",
"value": "test_value"
}
}
}
I would like to use this output in terraform, like:
output "db_name" {
value = azurerm_resource_group_template_deployment.my_rm.output_content["db_name"]
}
Unfortunately above definition returns empty value.
What is the correct way to define the output in terraform?
The output_content exports the JSON Content of the Outputs of the ARM Template Deployment.
After my validation, you could output the content with
output "db_name" {
value = azurerm_resource_group_template_deployment.my_rm.output_content
}
Then run terraform apply, you will see the output result, then you can change to filter the result with
output "db_name" {
value = jsondecode(azurerm_resource_group_template_deployment.my_rm.output_content).db_name.value
}
Please note that the db_name is not the same declaration db_name in your terraform code, it really should match the output JSON key in the first above step.
For example,
Related
I am trying to fetch the tags of AMI using AWS CLI and want to reuse the values from the output.
I have a terraform code below which is returning outputs in string format(Maybe not sure of format) which I want to convert into a map object.
variable "ami" {
default = "ami-xxxx"
}
locals {
tags = {
"platform" = lookup(data.local_file.read_tags.content, "platform", "") #Expecting to get platform from Map of read_tags
}
}
data "template_file" "log_name" {
template = "${path.module}/output.log"
}
resource "null_resource" "ami_tags" {
provisioner "local-exec" {
command = "aws ec2 describe-tags --filters Name=resource-id,Values=${var.ami} --query Tags[*].[Key,Value] > ${data.template_file.log_name.rendered}"
}
}
data "local_file" "read_tags" {
filename = "${data.template_file.log_name.rendered}"
depends_on = ["null_resource.ami_tags"]
}
output "tags" {
value = local.tags
}
output "cli-output-tags" {
value = "${concat(data.local_file.read_tags.content)}"
}
output of cli-output-tags is below:
[
[
"ENV",
"DEV"
],
[
"Name",
"Base-AMI"
],
[
"platform",
"Linux"
]
]
How can I convert this output into Map as below using terraform/(jq command), or is there any other way to fetch required values directly from cli-output-tags output:
{
ENV = "DEV",
Name = "Base-AMI",
platform = "Linux"
}
I have also tried changing the CLI command a bit like below but still not able to fetch values as expected:
'Tags[].{Key:Key,Value:Value}'
Resulted below output:
[
{
"Key": "ENV",
"Value": "DEV"
},
{
"Key": "Name",
"Value": "Base-AMI"
},
{
"Key": "platform",
"Value": "Linux"
}
]
You could use zipmap:
output "cli-output-tags" {
value = zipmap(
jsondecode(data.local_file.read_tags.content)[*][0],
jsondecode(data.local_file.read_tags.content)[*][1]
)
}
The code first changes string data from your file to json, then
gets all first elements [*][0] (same for second elements [*][1]), and zips them into map.
How can I convert this output into Map as below
One way would be to use jq as follows (assuming cli-output-tags is the name of the file holding the JSON array of arrays):
jq -r -f '"{", (.[] | "\(.[0]) = \"\(.[1])\""), "}"' cli-output-tags
I am trying to create an aws config rule for checking that cloudtrail alarms are enabled. I get the following error Error: Error creating AWSConfig rule: Failed to create AWSConfig rule: InvalidParameterValueException: Blank spaces are not acceptable for input parameter: threshold. when I run terraform apply. I'm not sure what the formatting issue is in the input parameters argument (see input_parameters). The apply works if I remove everything except for metricName i.e
input_parameters = "{\"metricName\":\"CloudTrailConfigChanges\"}"
Any help would be greatly appreciated.
resource aws_config_config_rule ensure-log-alarm-exists-for-cloudtrail {
name = "ensure-log-alarm-exists-for-cloudtrail"
description = "Checks whether cloudwatch alarm is on for cloudtrail configuration changes"
source {
owner = "AWS"
source_identifier = "CLOUDWATCH_ALARM_SETTINGS_CHECK"
}
input_parameters = "{\"metricName\":\"CloudTrailConfigChanges\",\"threshold\":1,\"evaluationPeriod\":1,\"period\":300,\"comparisionOperator\":\"GreaterThanOrEqualToThreshold\",\"statistic\":\"Sum\"}"
}
It seems like there is an issue parsing type ints from json strings: https://github.com/hashicorp/terraform-provider-aws/issues/773#issuecomment-385454229
I get the same error even with
input_parameters =<<EOF
{
"metricName":"CloudTrailConfigChanges",
"threshold":1
}
EOF
or
input_parameters = jsonencode({"metricName":"CloudTrailConfigChanges","threshold"=1})
Converting wrapping the int value in quotes does not work either.
resource "aws_config_config_rule" "ensure-log-alarm-exists-for-cloudtrail" {
name = "ensure-log-alarm-exists-for-cloudtrail"
description = "Checks whether cloudwatch alarm is on for cloudtrail configuration changes"
source {
owner = "AWS"
source_identifier = "CLOUDWATCH_ALARM_SETTINGS_CHECK"
}
input_parameters = jsonencode({
metricName = "CloudTrailConfigChanges"
threshold = "1"
})
}
The code above produces the following error:
Unknown parameters provided in the inputParameters:
With your examples you're still specifying the threshold as an integer. Try making it a string.
resource "aws_config_config_rule" "ensure-log-alarm-exists-for-cloudtrail" {
name = "ensure-log-alarm-exists-for-cloudtrail"
description = "Checks whether cloudwatch alarm is on for cloudtrail configuration changes"
source {
owner = "AWS"
source_identifier = "CLOUDWATCH_ALARM_SETTINGS_CHECK"
}
input_parameters = jsonencode({
metricName = "CloudTrailConfigChanges"
threshold = "1"
})
}
I ran into an error like this, and what resolved it for me was to add a condition. I don't fully understand why this worked and why it caused this error without the condition, but I saw the condition used in an AWS example.
For example, I first tried using something straightforward like this to reference a parameter:
"InputParameters": {
"appNames": {
"Ref": "ApplicationNames"
}
}
When my resource referenced the ApplicationNames parameter directly like this, it was giving that error. But using Conditions and referencing the parameter this way caused it to work, as in this full template example:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Just a stripped-down example",
"Parameters": {
"ApplicationNames": {
"Type": "String",
"Default": "This Has Spaces",
"MinLength": "1",
"ConstraintDescription": "This parameter is required."
}
},
"Conditions": {
"ApplicationNamesDefined": {
"Fn::Not": [
{
"Fn::Equals": [
"",
{
"Ref": "ApplicationNames"
}
]
}
]
}
},
"Resources": {
"SampleRule": {
"Type": "AWS::Config::ConfigRule",
"DependsOn": "SecurityHubCustomUpdaterFunction",
"Properties": {
"ConfigRuleName": "TheName",
"Description": "It was here that I was getting 'Blank spaces are not acceptable for input parameter: applicationNames' before I added the Conditions and Fn::If to reference it",
"InputParameters": {
"appNames": {
"Fn::If": [
"ApplicationNamesDefined",
{
"Ref": "ApplicationNames"
},
{
"Ref": "AWS::NoValue"
}
]
}
},
"Scope": {
"ComplianceResourceTypes": [
"AWS::SSM::ManagedInstanceInventory"
]
},
"Source": {
"Owner": "AWS",
"SourceIdentifier": "EC2_MANAGEDINSTANCE_APPLICATIONS_REQUIRED"
}
}
}
}
}
So you may want to try with Conditions usage.
Trying to recreate a resource group from template I previously exported but getting this error :
The value of deployment parameter 'Redis_polyrediscachegraphicsxp_name' is null. Please specify the value or use the parameter reference.
Indeed the parameters.json file has null values :
"parameters": {
"Redis_polyrediscachegraphicsxp_name": {
"value": null
},
"storageAccounts_polystorgraphicsxp_name": {
"value": null
},
"databaseAccounts_polycosmosgraphicsxp_name": {
"value": null
}
}
How can this be fixed ?
The error already shows the mistake you made. Your parameters are null. So you need to change your parameters.json file with the right values like this:
"parameters": {
"Redis_polyrediscachegraphicsxp_name": {
"value": "xxxxxx"
},
"storageAccounts_polystorgraphicsxp_name": {
"value": "xxxxxx"
},
"databaseAccounts_polycosmosgraphicsxp_name": {
"value": "xxxxxx"
}
}
Take the example here.
I am tying to to provision Azure AD Domain Service using Terraform by giving Terraform the Azure ARM template, this is because Terrafrom does not support provisioning Azure AD Domain Service natively.
I have exported the ARM Template and it's parameters, one of the parameters is called "notificationSettings" which is a type Object and looks like below :
"notificationSettings": {
"value": {
"notifyGlobalAdmins": "Enabled",
"notifyDcAdmins": "Enabled",
"additionalRecipients": []
}
}
Other parameters are all strings and I can pass them without any issue, for example:
"apiVersion" = "2017-06-01"
I have tried passing this object to parameters like below :
"notificationSettings" = [{
"notifyGlobalAdmins" = "Enabled"
"notifyDcAdmins" ="Enabled"
"additionalRecipients" = []
}]
However, when I execute terrafrom apply, terrafrom complains and say:
Inappropriate value for attribute "parameters": element
"notificationSettings": string required.
How do I pass parameters type of Object to template body?
I have also tried giving the entire ARM json parameter as a file to terrafrom by using parameters_body option like below :
parameters_body = "${file("${path.module}/temp/params.json")}"
however, I am getting the followig error when executing the terrafrom script:
The request content was invalid and could not be deserialized: 'Error
converting value
"https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#"
to type
'Microsoft.WindowsAzure.ResourceStack.Frontdoor.Data.Definitions.DeploymentParameterDefinition'.
Path 'properties.parameters.$schema', line 1, position 2952.'.
Below is the params.json file:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"apiVersion": {
"value": "2017-06-01"
},
"sku": {
"value": "Standard"
"location": {
"value": "westus"
},
"notificationSettings": {
"value": {
"notifyGlobalAdmins": "Enabled",
"notifyDcAdmins": "Enabled",
"additionalRecipients": []
}
},
"subnetName": {
"value": "xxxx"
},
"vnetName": {
"value": "xxxx"
},
"vnetAddressPrefixes": {
"value": [
"10.0.1.0/24"
]
},
"subnetAddressPrefix": {
"value": "10.0.1.0/24"
},
"nsgName": {
"value": "xxxxx"
}
}
}
There is a way to pass arbitrary data structures from Terraform to ARM.
There are two ways to pass data to the ARM template within the azure_template_deployment provider
use the parameters block, which is limited to string parameters only
use the parameters_body block, which is pretty much arbitrary JSON.
I find the easiest way to use the parameters block is to create a local variable with the structure I require, then call jsonencode on it. I also like to keep the ARM template in a separate file and pull it in via a file() call, reducing the complexity of the terraform.
locals {
location = "string"
members = [
"array",
"of",
"members"
]
enabled = true
tags = {
"key" = "value",
"simple" = "store"
}
# this is the format required by ARM templates
parameters_body = {
location = {
value = "${local.location}"
},
properties = {
value = {
users = {
members = "${local.members}"
}
boolparameter = "${local.enabled}"
}
}
tags = {
value = "${module.global.tags}"
}
}
}
resource "azurerm_template_deployment" "sample" {
name = "sample"
resource_group_name = "rg"
deployment_mode = "Incremental"
template_body = "${file("${path.module}/arm/sample_arm.json")}"
parameter_body = "${jsonencode(local.parameters_body)}"
}
The only caveat I've found is that the bool parameters pass as a string, so declare them as a string in the ARM parameters section, then use a ARM function to convert to bool
"parameters: {
"boolParameter": {
"type": "string"
}
},
"variables": {
"boolVariable": "[bool(parameters('boolParameter'))]"
},
"resources": [
...
"boolArm": "[variables('boolVariable')]",
...
]
Using terraform and Azure ARM template, in order to configre event grid with a particular azure function, I am trying to recover some values in a terraform output.
Indeed, I have this ARm template deployment to have the systems keys of a particular function:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"functionApp": {
"type": "string",
"defaultValue": ""
}
},
"variables": {
"functionAppId": "[resourceId('Microsoft.Web/sites', parameters('functionApp'))]"
},
"resources": [],
"outputs": {
"systemKeys": {
"type": "object",
"value": "[listkeys(concat(variables('functionAppId'), '/host/default'), '2018-11-01').systemKeys]"
}
}
}
My deployment working well, because I can see in Azure Portal that there are in output a json objecy like this:
{
"durabletask_extension": "ASensituveValueIDoNotShareForDurableTaskExtension==",
"eventgrid_extension": "ASensituveValueIDoNotShareForEventGridExtension=="
}
Now the purpose is to get one of this value in a terraform output.
I tried these but I have got some errors:
output "syst_key" {
value = "${azurerm_template_deployment.function_keys.outputs["systemKeys"]}"
}
Error: on outputs.tf line 69, in output "syst_key":
69: value = "${azurerm_template_deployment.function_keys.outputs["systemKeys"]}"
|----------------
| azurerm_template_deployment.function_keys.outputs is empty map of string
output "syst_keys" {
value = "${lookup(azurerm_template_deployment.function_keys.outputs, "systemKeys")}"
}
Error: on outputs.tf line 77, in output "syst_key":
77: value = "${lookup(azurerm_template_deployment.function_keys.outputs, "systemKeys")}"
|----------------
| azurerm_template_deployment.function_keys.outputs is empty map of string
Call to function "lookup" failed: lookup failed to find 'systemKeys'.
In order to trigger eventgrid on this function I have to recover the values in terraform output of systemKeys from my ARM deployment template. I know that the deployment is working well, I just don't know how to recover theses values with terraform.
For your issue, you need to take care that only the type String, Int and Bool are supported in Terraform. So you need to change the output type in the template, then you can output them in Terraform. For more details, see outputs. And the right output in Terraform is below:
output "syst_key" {
value = "${azurerm_template_deployment.function_keys.outputs["systemKeys"]}"
}