I have two environments. I'm trying to write a condition in the ssh metadata block to add a ssh key depending on the environment.
For example: If env-1, add ssh1 key, if env-2 add ssh-2 key. Trying with map, but can not do this correctly. How to do it better?
metadata = {
count = var.ENV_TYPE != "ENV-1" ? 1 : 0
ssh-keys = "centos:ssh-rsa AAAAsfdsds..."
instance_role = var.GCP_CUSTOM_METADATA
app_env_monitoring = var.GCP_CUSTOM_METADATA_MONITORING
}
metadata = {
count = var.ENV_TYPE = "ENV-1" ? 1 : 0
ssh-keys = "centos:ssh-rsa BBBBsfdsds..."
instance_role = var.GCP_CUSTOM_METADATA
app_env_monitoring = var.GCP_CUSTOM_METADATA_MONITORING
}
You can probably achieve what you want by using a ternary operator:
metadata = {
ssh-keys = var.ENV_TYPE == "ENV-1" ? "centos:ssh-rsa BBBBsfdsds..." : "centos:ssh-rsa AAAAsfdsds..."
instance_role = var.GCP_CUSTOM_METADATA
app_env_monitoring = var.GCP_CUSTOM_METADATA_MONITORING
}
Additionally, I would strongly suggest moving the SSH key at least into a variable. In that case, the above code would look cleaner:
metadata = {
ssh-keys = var.ENV_TYPE == "ENV-1" ? var.ssh_key_env1 : var.ssh_key_env2
instance_role = var.GCP_CUSTOM_METADATA
app_env_monitoring = var.GCP_CUSTOM_METADATA_MONITORING
}
Related
Prompt me, please, how can I get separately a value for key paswd-0. I mean, I need separated values for password and username.
This is remote data from data.terraform_remote_state.user_passwd.outputs.login_passwd
output = {
paswd-0 = jsonencode(
{
password = "uGo="
username = "git"
}
)
paswd-1 = jsonencode(
{
password = "wM="
username = "kun"
}
)
}
I'm trying this and get error parameter: lookup() requires a map as the
output "tetts" {
value = lookup(tomap(data.terraform_remote_state.user_passwd.outputs.login_passwd.paswd-0), "password", null)
}
Ideally I would go through of each value and fill these fields.
argocd_repositories = {
[
"private-repo" = {
url = "https://repo.git"
username = "argocd"
password = "access_token"
},
"git-repo" = {
url = "https://repo.git"
password = "argocd_access_token"
username = "admin"
},
"private-helm-chart" = {
url = "https://charts.jetstack.io"
type = "helm"
username = "foo"
password = "bar"
},
]
}
As per my comment, you can get the value from the data source by using the jsondecode built-in function [1]. You would have to update the output to look like the following:
output "tetts" {
value = lookup(tomap(jsondecode(data.terraform_remote_state.user_passwd.outputs.login_passwd["paswd-0"]), "password", null)
}
This is only to make it work as you intended it to. However, it will output only the value for the password. Since I do not have the remote state, I managed to get close to what you want with locals and the following:
locals {
output = {
paswd-0 = jsonencode(
{
password = "uGo="
username = "git"
}
)
paswd-1 = jsonencode(
{
password = "wM="
username = "kun"
}
)
}
sorted_values = { for k, v in local.output : jsondecode(v).username => jsondecode(v).password }
}
Note that jsondecode is used on the values of the original map. Furthermore, since the JSON decoded values are also in a key value pair format, you can access the keys and corresponding values using the usual terraform notation (i.e., jsondecode(v).username and jsondecode(v).password). Using terraform console, the local sorted_values variable has the following look:
> local.sorted_values
{
"git" = "uGo="
"kun" = "wM="
}
I guess this is close to what you wanted to achieve with the tomap function.
[1] https://www.terraform.io/language/functions/jsondecode
I am working on something like this (adding charts to gcp monitoring)
data "template_file" "templatefileone" {
template = file("${path.module}/templatefileone.json.tmpl")
count = length(var.one)
vars = {
title = var.metrics[count.index][0]
metricName = var.metrics[count.index][3]
endpoint = var.metrics[count.index][2]
environmentName = "#ENVIRONMENT"
applicationName = var.appName
clusterName = "#CLUSTERNAME"
envName = var.envName
}
}
data "template_file" "templatefiletwo" {
template = file("${path.module}/templatefiletwo.json.tmpl")
count = length(var.two)
vars = {
title = var.jvmMetrics[count.index][0]
metricName = var.jvmMetrics[count.index][1]
environmentName = "#ENVIRONMENT"
applicationName = var.appName
clusterName = "#CLUSTERNAME"
envName = var.envName
}
}
resource "google_monitoring_dashboard" "dashboard" {
for_each = local.environmentsLabels
dashboard_json = templatefile("${path.module}/dashboard.json.tmpl", {
app_name = var.appName,
env_name = each.key,
widgets = join(",",
[for metric in sort(concat(
data.template_file.templatefileone.*.rendered,
[for xyz in data.template_file.templatefiletwo: xyz if (try(sm.vars.endpoint, "") != "")].*.rendered
)) : doSomethingThatDoesntMatterHere()]
)
})
project = var.projectId
}
I am trying to filter through charts 'templatefiletwo', so that only those that have something in variable 'endpoint' will be joined in 'widgets' variable. Currently it looks like:
widgets = join(",",
[for metric in sort(concat(
data.template_file.templatefileone.*.rendered,
data.template_file.templatefiletwo.*.rendered
)) : doSomethingThatDoesntMatterHere()]
)
I expected
[for xyz in data.template_file.templatefiletwo: xyz if (try(sm.vars.endpoint, "") != "")]
to just return same thing as data.template_file.templatefiletwo so that I will be able to call .*.rendered on it, but apparently It doesn't work like this.
After half a day put into this I decided to just push it to environment and see the error that it sends me.
Seems like all along my code worked perfectly as expected, it's just that the terrafrom plugin for IDEA couldn't handle it and thought it's an error. I won't delete the question because it probably will save someone a lot of time.
I have this terraform code that is generating me this JSON.
{
host = {
path = "/xxxx/yyyy"
}
name = "NAME"
}
Currently it's working, but I have 3 loops, consider it not efficient, wondering if I can reduce it to 2 or probably 1 loop? Or this isn't possible.
My first loop validates that container_mounts isn't empty. Don't want to generate it, if that comes empty. The second and the third is specific for getting the information as container_mounts is a map of strings.
variable "container_mounts" {
type = map(string)
default = { "app/data" = "/xxxx/yyyyy" }
}
json = jsonencode(
[
for i in range(length(var.container_mounts)) :
{
name = [for sourceVolume in keys(var.container_mounts) :
replace(substr(sourceVolume, 1, length(sourceVolume)), "/", "-")][0]
host = {
sourcePath = [for key, value in var.container_mounts : value][0]
}
}
]
)
Is there a way to improve it? I assume that yes, but running into different scenarios were it's not working.
So after talking with a friend, looks I complicated my life doing what I did.
json = jsonencode(
[
for key, value in var.container_mounts :{
host = { "sourcePath" = value }
name = replace(substr(key, 1, length(key)), "/", "-")
}
]
)
It can be done only with one loop.
I'm pretty much new to terraform. I wanted to know is there a way to reuse a resource? Below is my code. Below is the main.tf, where I have a module declared.
module "deployments" {
source = "./modules/odo_deployments"
artifact_versions = local.artifact_versions
}
In the modules/odo_deployments folder, I have two resources which does exactly the same except for a different ad. Is there a way I can use just one resource and pass arguments (ad) like a function to this resource?
variable "artifact_versions" {
description = "What gets injected by terraform at the ET level"
}
resource "odo_deployment" "incident-management-service-dev" {
count = var.artifact_versions["incident-management-service"].version == "skip" ? 0 : 1
ad = "phx-ad-1"
alias = "cloud-incident-management-application"
artifact {
url = var.artifact_versions["incident-management-service"].uri
build_tag = var.artifact_versions["incident-management-service"].version
type = var.artifact_versions["incident-management-service"].type
}
flags = ["SKIP_UP_TO_DATE_NODES"]
}
resource "odo_deployment" "incident-management-service-dev-ad3" {
count = var.artifact_versions["incident-management-service"].version == "skip" ? 0 : 1
ad = "phx-ad-3"
alias = "cloud-incident-management-application"
artifact {
url = var.artifact_versions["incident-management-service"].uri
build_tag = var.artifact_versions["incident-management-service"].version
type = var.artifact_versions["incident-management-service"].type
}
flags = ["SKIP_UP_TO_DATE_NODES"]
}
What I did to solve this is,I added a locals in the main.tf and pass the local variable in the module like below
locals {
ad = ["phx-ad-1", "phx-ad3"]
}
module "deployments" {
source = "./modules/odo_deployments"
artifact_versions = local.artifact_versions
ad = local.ad
and in the resource instead of hard coding the ad value, I used it like below
count = length(var.ad)
ad = var.ad[count.index]
Suppose I have two kineses, I'd like to get the one of them with the key word _consumer.
variable "kinesis" {
default = ["kinesis_publisher", "kinesis_consumer"]
}
resource "aws_kinesis_stream" "test_stream" {
count = "${length(var.kinesis)}"
name = "${var.kinesis[count.index]}"
shard_count = 1
retention_period = 48
shard_level_metrics = [
"IncomingBytes",
"OutgoingBytes",
]
tags = {
Environment = "test"
}
}
How do I get consumer arn only?
output "kinesis_consumer_arn" {
value = "??? lookup or matchkeys with _consumer ???"
}
It is not always the same sequence and will be many kinesis. So I can't use 0 or 1 directly.
You may create modules for each kafka stream , thereby giving more control on variables passed into and derived from the resources.
module "kinesis_publisher" {
source = "../modules/test_stream"
stream_name = "kinesis_publisher"
}
module "kinesis_consumer" {
source = "../modules/test_stream"
stream_name = "kinesis_consumer"
}
And then output can be filtered on basis of modules.
output "kinesis_consumer_arn" {
value = "{module.kinesis_consumer.arn}"
}