regex to string - amazon-web-services

I am trying to just use the value before the # symbol as a value for my name during the creation of my ressource. However, I got an error: Inappropriate value for attribute "email": string required. my regex is working on the terraform console so I think it's more an error on where I am applying this regex function.
main.tf
resource "aws_organizations_account" "account" {
for_each = local.all_users
name = "${regex("(.*)#", "john.doe#test.com")}"
email = "admin#test.com"
role_name = "Administrator"
parent_id = var.sandbox_organizational_unit_id
}
I also tried "${tostring(regex("(.*)#", "tom#gmail.com"))}" and I got a different error, Invalid value for "v" parameter: cannot convert tuple to string.

It should be:
name = regex("(.*)#", "john.doe#test.com")[0]

Related

How to disable terraform error "Error: Your query returned no results. Please change your search criteria and try again." for data block?

Can someone tell me how to disable the raising of the error if the terraform data block result is empty? I want to handle this situation myself.
My code is below.
data "aws_ami" "specified" {
for_each = toset([
for v in var.ec2_confg_params : v.ami if v.ami != null
])
most_recent = true
include_deprecated = false
filter {
/*
Filter based on the '--filters (list)' keys described here
https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-images.html
*/
name = "image-id"
values = [
each.value,
]
}
filter {
name = "state"
values = ["available"]
}
lifecycle {
postcondition {
condition = try(each.value == self.id)
error_message = "Image '${each.value}' not found!"
}
}
}
If the value var.ec2_confg_params.ami is set but the date block does not find it, I get an error:
Error: Your query returned no results. Please change your search criteria and try again.
│
│ with data.aws_ami.specified["ami-xxxxxxxxxxxxxxxxx"],
│ on main.tf line 293, in data "aws_ami" "specified":
│ 293: data "aws_ami" "specified" {
but I need the lifecycle postcondition block to work.
Thanks in advance for help!
The only solution I found is to select all AMIs with data.aws_ami_ids, and check if the ami in var.ec2_confg_params.ami is in the list data.aws_ami_ids.all.ids. But this option is processed for a long time and it is difficult to set parameters for filtering based on AMI 'owner'.
This particular data source is designed to return exactly one AMI matching the given criteria or return an error if that isn't possible. There is no way to change that behavior.
It is in principle possible for a provider to offer a data resource that doesn't fail when an object doesn't exist, or to return a set of objects that all together match some criteria. The hashicorp/aws provider offers aws_ami_ids as an alternative which returns a set of IDs matching the given criteria, and so you could potentially get the result you wanted using that data source instead:
data "aws_ami_ids" "example" {
for_each = toset([
for v in var.ec2_confg_params : v.ami
if v.ami != null
])
filter {
name = "image-id"
values = [
each.value,
]
}
filter {
name = "state"
values = ["available"]
}
lifecycle {
postcondition {
condition = length(self.ids) == 1
error_message = "Image '${each.value}' not found."
}
}
}
This is an unusual approach though, since it's just replacing an error case that the provider already handles with exactly the same error case implemented in your module. Unless you have a particular reason to return a different error message than normal I would suggest using the built-in behavior for simplicity.

How to create AWS SSM Parameter from Terraform

I am trying to copy AWS SSM parameter(for cloudwatch) from one region to another. I have the json which is created as a String in one region.
I am trying to write a terraform script to create this ssm parameter in another region.
According to the terraform documentation, I need to do this
resource "aws_ssm_parameter" "foo" {
name = "foo"
type = "String"
value = "bar"
}
In my case value is a json. Is there a way to store the json in a file and pass this file as value to the above resource? I tried using jsonencode,
resource "aws_ssm_parameter" "my-cloudwatch" {
name = "my-cloudwatch"
type = "String"
value = jsonencode({my-json})
that did not work either. I am getting this error
Extra characters after interpolation expression I believe this is because the json has characters like quotes and colon.
Any idea?
I tested the following & this worked for me:
resource "aws_ssm_parameter" "my-cloudwatch" {
name = "my-cloudwatch"
type = "String"
#value = file("${path.module}/ssm-param.json")
value = jsonencode(file("${path.module}/files/ssm-param.json"))
}
./files/ssm-param.json content:
{
"Value": "Something"
}
and the parameter store value looks like this:
"{\n \"Value\": \"Something\"\n}"
I just faced this issue the $ in the CW config is causing the problem. Use $$
"Note: If you specify the template as a literal string instead of loading a file, the inline template must use double dollar signs (like $${hello}) to prevent Terraform from interpolating values from the configuration into the string. "
https://www.terraform.io/docs/configuration-0-11/interpolation.html
"metrics": {
"append_dimensions": {
"AutoScalingGroupName": "$${aws:AutoScalingGroupName}",
"ImageId": "$${aws:ImageId}",
"InstanceId": "$${aws:InstanceId}",
"InstanceType": "$${aws:InstanceType}"
},
I prefer Pauls aproach though.
You need to insert your json with escaped quotas, is a little trick in AWS, and you need to parse this when retrieve:
const value = JSON.parse(Value)
Example of insert:
"Value": "\"{\"flag\":\"market_store\",\"app\":\"ios\",\"enabled\":\"false\"}\"",

The given value is not suitable for child module variable "aws_auth_user_map" : list of object required

I am trying to load values to below terraform variable but I am getting The given value is not suitable for child module variable The given value is not suitable for child module variable "aws_auth_user_map" defined at modules/cluster/variables.tf:139,1-29: list of object required.
variable "aws_auth_user_map" {
type = list(object({
userarn = string
username = string
groups = list(string)
}))
default = []
description = "A list of mappings from aws user arns to kubernetes users, and their groups"
}
and this is how I am adding default values.
{userarn="arn:aws:iam::XXXXXX:user/pXXl.brXXd", username="XX.XX", groups=["admin", "dev"]}
Not sure what I am doing wrong here
The default value should be a list:
variable "aws_auth_user_map" {
type = list(object({
userarn = string
username = string
groups = list(string)
}))
default = [{userarn="arn:aws:iam::XXXXXX:user/pXXl.brXXd", username="XX.XX", groups=["admin", "dev"]}]
description = "A list of mappings from aws user arns to kubernetes users, and their groups"
}

How to upload a parameter with all tags included?

For example. I am creating an AMI-ID parameter with Terraform and I want to upload it's value to AWS Parameter store. But also this AMI has a bunch of tags, out of this tags I want a specific value of one of this tag to be uploaded as a parameter as well. How we can create a parameter for a tag?
resource "aws_ssm_parameter" "ami_id" {
name = ami_id
type = "String"
value = data.aws_ami.centos_ami.id
provide = aws.us-west-2
overwrite = true
}
Your question title and question content are not the same.
If you want to find a specific tag on the AMI, and create a new SSM Parameter from that, then it would look like this:
resource "aws_ssm_parameter" "ami_tag_value" {
name = "ami_tag_value"
type = "String"
value = data.aws_ami.centos_ami.tags[index(data.aws_ami.centos_ami.tags.*.key, "tag_name")].value
provide = aws.us-west-2
overwrite = true
}
Where "tag_name" is the name of the tag you want the value for.
If you want to copy all the tags from the AMI to the SSM parameter, it would look like this:
resource "aws_ssm_parameter" "ami_id" {
name = ami_id
type = "String"
value = data.aws_ami.centos_ami.id
provide = aws.us-west-2
overwrite = true
tags = data.aws_ami.centos_ami.tags
}

gcp google_project_iam_member gives invalid argument message on terraform

I'm using terraform to deploy the following
resource "google_project_iam_custom_role" "brw-user-function-item-registered-role" {
role_id = "brw_user_function_item_registered_role"
title = "brw-user-function-item-registered-role"
description = "Role used by the brw-user-function item-registered"
permissions = [
"storage.objects.create",
"storage.objects.get",
"storage.objects.list"
]
}
resource "google_service_account" "brw-user-function-item-registered-service-account" {
account_id = "brw-user-function-item-reg-svc"
display_name = "brw-user-function-item-registered-service_account"
}
resource "google_project_iam_member" "brw-user-function-item-registered-service-account-binding" {
project = local.project
role = "roles/${google_project_iam_custom_role.brw-user-function-item-registered-role.role_id}"
member = "serviceAccount:${google_service_account.brw-user-function-item-registered-service-account.email}"
depends_on = [
google_project_iam_custom_role.brw-user-function-item-registered-role,
google_service_account.brw-user-function-item-registered-service-account
]
}
However when I try to deploy this through terraform, I get the following error
Request "Create IAM Members roles/brw_user_function_item_registered_role serviceAccount:brw-user-function-item-reg-svc#brw-user.iam.gserviceaccount.com for \"project \\\"BRW-User\\\"\"" returned error: Error retrieving IAM policy for project "BRW-User": googleapi: Error 400: Request contains an invalid argument., badRequest
I'm not sure what is wrong here, I have added the depends_on as well just to make sure it is created in the correct order. Could the member attribute be wrong, I tried giving account_id as well and I still get the same error.
Only predefined roles have the string roles/ in front of the name.
You are using the string:
role = "roles/${google_project_iam_custom_role.brw-user-function-item-registered-role.role_id}"
Change it to:
role = google_project_iam_custom_role.brw-user-function-item-registered-role.name
Note the removal of roles/, changing role_id to name, and removing string interpolation.
In the resource google_project_iam_member, if you are passing a custom role it must be of the format:
[projects|organizations]/{parent-name}/roles/{role-name}
Here is an example:
resource "google_project_iam_member" "access" {
project = var.project_name
role = "projects/${var.project_name}/roles/${google_project_iam_custom_role.customer_access.role_id}"
member = "serviceAccount:${google_service_account.service_account.email}"
}
Also, as a best practice avoid using dashes in the resources name (better underscore) and try not make it too long. I've run into issues with long names.