I am trying to create an AWS parameter store via terraform that can also pass default values with the JSON format. Here is a sample of the code.
resource "aws_ssm_parameter" "secret" {
name = "/something/env"
description = "This is a something values"
type = "SecureString"
value = "test"
tags = {
environment = "production"
}
}
Instead of passing out a single value as a "test" from value, how can I pass the json one inside value one.
So that AWS parameter store value will be like
{
"key": "value"
}
I think you are looking for jsonencode, which could be used as such:
resource "aws_ssm_parameter" "secret" {
name = "/something/env"
description = "This is a something values"
type = "SecureString"
value = jsonencode({
"key" : "value"
})
tags = {
environment = "production"
}
}
Related
There is resource:
resource "resource_name" "foo" {
name = "test"
config {
version = 14
resources {
disk_type_id = "network-ssd"
}
postgresql_config = {
enable_parallel_hash = true
}
}
}
I need a module which accepts optional user variables in "postgresql_config". There can be many such variables.
I tried next:
variables.tf
variable "postgresql_config" {
description = "User defined for postgresql_config"
type = list(object({
# key1 = value1
# ...
# key50 = value50
}))
}
variable "config" {
description = "for dynamic block 'config' "
type = list(object({
version = number
}))
default = [{
version = 14
}]
}
variable "resources" {
description = "for dynamic block 'resources' "
type = list(object({
disk_type_id = string
}))
default = [{
disk_type_id = "network-hdd"
}]
}
module/postgresql/main.tf
resource "resource_name" "foo" {
name = "test"
dynamic "config" {
for_each = var.config
content {
version = config.value["version"]
dynamic "resources" {
for_each = var.resources
content {
disk_type_id = resources.value["disk_type_id"]
}
}
# problem is here
postgresql_config = {
for_each = var.postgresql_config
each.key = each.value
}
}
}
example/main.tf
module "postgresql" {
source = "../module/postgresql"
postgresql_config = [{
auto_explain_log_buffers = true
log_error_verbosity = "LOG_ERROR_VERBOSITY_UNSPECIFIED"
max_connections = 395
vacuum_cleanup_index_scale_factor = 0.2
}]
That is, I understand that I need to use "dynamic", but it can only be applied to the block "config" and the nested block "resource_name".
How can I pass values for "postgresql_config" from main.tf to module? Of course, my example with for_each = var.postgresql_config doesn't work, but I hope this way to give an idea of what I need.
Or does terraform have no such option to use custom variables dynamically at all, and all of them must be specified explicitly?
Any help would be appreciated, thank you
from what I understand , you are trying to create a map dynamically for your resource postgres_config.
I would recommend using a for expression to solve that problem.
However, I think your problem lies in how you have defined variables for your module . You might run into a problem if your postgress_config list has multiple configs in it because that config can only take a map by the looks of it.
have a look at the following documentation:
this one is for how to define your variables
https://www.terraform.io/language/expressions/dynamic-blocks#multi-level-nested-block-structures
for expressions
https://www.terraform.io/language/expressions/for
my solution for your config problem ,would be something like this assuming that the postgres_config list has one element all the time:
# problem is here
postgresql_config = var.postgresql_config[0]
I am trying to provision aws service catalog product using terraform resource
resource "aws_servicecatalog_provisioned_product" "example" {}
Terraform resource output description
one of the export value of the resource is outputs which is in form of set and i am collecting that into an output variable using below
output "Provisioned_Product_Outputs" {
value = aws_servicecatalog_provisioned_product.example.outputs
}
Output Looks Like
Provisioned_Product_Outputs = toset([
{
"description" = "Backup plan"
"key" = "BackupPlan"
"value" = "light"
},
{
"description" = "Current user zone to run"
"key" = "CurrentAZ"
"value" = "primary"
},
{
"description" = "InstanceID of Vm"
"key" = "EC2InstanceID"
"value" = "i-04*******"
},
{
"description" = "InstanceHostName"
"key" = "InstanceHostName"
"value" = "{\"fqdn\":\"foo.domain.com\"}"
},
{
"description" = "The ARN of the launched Cloudformation Stack"
"key" = "CloudformationStackARN"
"value" = "arn:aws:cloudformation:{region}:{AccountID}:stack/SC-{AccountID}-pp-iy******"
},
])
i would like to have only selected outputs values rather than entire set like below.
output "EC2InstanceID" {
value = "i-04*******"
}
output "InstanceHostName" {
value = ""{\"fqdn\":\"foo.domain.com\"}""
}
output "CloudformationStackARN" {
value = "arn:aws:cloudformation:{region}:{AccountID}:stack/SC-{AccountID}-pp-iy******"
}
Is there a way to apply or have some condition which allows me to check for the right values using key value pair and apply the value in the outputs
regards
Since you know that your output is set, you can create a filter on the objects inside the set using contains:
output "outputs" {
value = {
for output in aws_servicecatalog_provisioned_product.example.outputs : output.key =>
output.value if contains(["EC2InstanceID", "InstanceHostName", "CloudformationStackARN"], output.key)
}
}
The output will be similar to this:
outputs = {
"CloudformationStackARN" = "arn:aws:cloudformation:{region}:{AccountID}:stack/SC-{AccountID}-pp-iy******"
"EC2InstanceID" = "i-04*******"
"InstanceHostName" = "{\"fqdn\":\"foo.domain.com\"}"
}
If you want to have separate outputs, you have to type out each output manually:
output "EC2InstanceID" {
value = [for output in aws_servicecatalog_provisioned_product.example.outputs : output.value if output.key == "EC2InstanceID"][0]
}
output "InstanceHostName" {
value = [for output in aws_servicecatalog_provisioned_product.example.outputs : output.value if output.key == "InstanceHostName"][0]
}
output "CloudformationStackARN" {
value = [for output in aws_servicecatalog_provisioned_product.example.outputs : output.value if output.key == "CloudformationStackARN"][0]
}
You can not have a for_each attribute for outputs. Currently resource and module blocks support for_each attributes.
I have the below terraform template which creates a user, access key and stores in secret manager.
resource "aws_iam_user" "test" {
name = "test"
}
resource "aws_iam_access_key" "test" {
user = aws_iam_user.test.name
}
resource "aws_secretsmanager_secret" "test" {
name = "credentials"
description = "My credentials"
}
resource "aws_secretsmanager_secret_version" "test" {
secret_id = "${aws_secretsmanager_secret.test.id}"
secret_string = "{\"AccessKey\": data.aws_iam_access_key.test.id,\"SecretAccessKey\": data.aws_iam_access_key.test.secret}"
}
The values in the secret_string is not getting set. Is this right usage? Please help me set the right values
secret_string = "{\"AccessKey\": data.aws_iam_access_key.test.id,\"SecretAccessKey\": data.aws_iam_access_key.test.secret}"
You can construct your secret_string argument value as a Map type, and then encode it into a JSON string using Terraform's native jsonencode function to ensure the value is passed correctly to the argument. Your resource would look like:
resource "aws_secretsmanager_secret_version" "test" {
secret_id = "${aws_secretsmanager_secret.test.id}"
secret_string = jsonencode({"AccessKey" = aws_iam_access_key.test.id, "SecretAccessKey" = aws_iam_access_key.test.secret})
}
Note also that aws_iam_access_key.test.id and aws_iam_access_key.test.secret are exported attributes from resources and not data, so the data prefix needs to be removed from their namespace.
I need to have "client_secret" output value as an input for "tenant_app_password"
variables.tf
variable "tenant_app_password" {
description = ""
}
Create-service-principal.tf
resource "random_string" "password" {
length = 32
special = true
}
# Create Service Principal Password
resource "azuread_service_principal_password" "test_sp_pwd" {
service_principal_id = azuread_service_principal.test_sp.id
value = random_string.password.result
end_date = "2020-01-12T07:10:53+00:00"
}
OUTPUT
output "client_secret" {
value = "${azuread_service_principal_password.wvd_sp_pwd.value}"
sensitive = true
}
Is we have any possible way ???
I'm assuming you want to use the output of one Terraform run in another one. You can do this by using a remote state datasource provider.
You cannot put the original output in a variable, but you can use the remote output as a variable directly in another template. For example, in your second template:
// set up the remote state data source
data "terraform_remote_state" "foo" {
backend = "s3"
config = {
bucket = "<your bucket name>"
key = "<your statefile name.tfstate"
region = "<your region>"
}
}
// use it
resource "kubernetes_secret" "bar" {
metadata {
name = "bar"
}
data = {
client_secret = data.terraform_remote_state.foo.outputs.client_secret
}
}
Also check out this question.
Am trying to create cross account role using terraform while giveing the policy name as input getting error Error: Error asking for user input: Cannot parse value for variable policy_arns
data "aws_iam_policy_document" "cross_account" {
statement {
effect = "Allow"
principals {
type = "AWS"
identifiers = ["${var.principal_arns}"]
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role" "cross_account_role" {
name = "${var.name}"
assume_role_policy = "${data.aws_iam_policy_document.cross_account_assume_role_policy.json}"
}
resource "aws_iam_role_policy_attachment" "cross_account_role" {
count = "${length(var.policy_arns)}"
role = "${aws_iam_role.cross_account_role.name}"
policy_arn = "${element(var.policy_arns, count.index)}"
}
variable "name" {
type = "string"
description = "Name of the role being created."
}
variable "principal_arns" {
type = "list"
description = "ARNs of accounts, groups, or users with the ability to assume this role."
}
variable "policy_arns" {
type = "list"
description = "List of ARNs of policies to be associated with the created IAM role"
}
Variables passed with either -var foo=bar command line flag or as the environment variable TF_VAR_foo=bar can only be literal strings:
Variables specified via the -var command line flag will be literal strings "true" and "false", so care should be taken to explicitly use "0" or "1".
Variables specified with the TF_VAR_ environment variables will be literal string values, just like -var.
If you want to be able to use list variables then you will either need to define these ahead of time in a terraform.tfvars file or other vars file or you could use the split() function to take a separated string and turn it into a list:
variable "string_list" {
type = "string"
}
locals {
list_list = "${split(",", var.string_list)}"
}
output "list_list" {
value = ["${local.list_list}"]
}