True false expression errors - amazon-web-services

I am trying to build a module that will apply only in conditions when the requirements of the statement are satisfied. In this case if I specify the value for "var.enable_standbyinfra" that is true then the module will be created. I want to understand if I am approaching this type of method wrong or get on the right path
iam_instance_profile_standby = "${var.enable_standbyinfra == "true" ?
module.aem_disp_a_standby_iam.aws_iam_instance_profile_id : 0 }"
and further used in:
iam_instance_profile = "${local.iam_instance_profile_standby}"
The result is that I get an error when running terraform and the error is:
local.iam_instance_profile_standby: At column 3, line 1: true and false expression types must match; have type list and type int in:
${var.enable_standbyinfra == "true" ? module.aem_disp_a_standby_iam.aws_iam_instance_profile_id : 0 }
So the final result I want to get to is that if I specify that "var.enable_standbyinfra" is equal to true the resource is created. If set to "false" I want it to be skipped.
If I posted it wrong without a clear understanding please accept my excuses I am not a expert user in stackoverflow still learning

This argument should be a string, so:
var.enable_standbyinfra == "true" ?
module.aem_disp_a_standby_iam.aws_iam_instance_profile_id : ""

Related

In terraform, how to assign variable in a resource block only if condition matches

I am trying to set a variable in a block only if a condition matches.
resource "teleport_role" "test_role" {
spec = {
allow = {
kubernetes_labels = {
"label_1" = "${local.some_var == "something" ? ["value_1"] : null}"
}
}
}
}
When a false condition, in terrform plan I get:
+ "label_1" = null
which eventually throws error during terraform apply:
│ When applying changes to teleport_role. test_role, provider
│ "provider[\"terraform.releases.teleport.dev/gravitational/teleport\"]"
│ produced an unexpected new value:
│ .spec.allow.kubernetes_labels["label_1"]: was null, but now
│ cty.ListVal([]cty.Value{cty.StringVal("")}).
In nutshell, null doesn't let label_1 be ignored.
How do I ensure that variable just don't get assigned at all if condition is false
For example if I had to do it in Python, it would have been like:
if some_var == "something":
label_1 = value_1
Ref: https://github.com/gravitational/teleport-plugins/issues/657
This is erroring because Kubernetes does not allow this kind of specification in its spec schema for that API. go-cty does seem to be trying really hard to coerce that HCL2/TF type into something compatible with Kubernetes spec schema, so good on them for that effort.
In most languages (this one included) with potentially unspecified values for enumerables/iterables, then the unspecified needs to be empty instead of nil/null/etc.
kubernetes_labels = local.some_var == "something" ? { "label_1" = ["value_1"] } : {}
There is a very small chance that go will be unable to serialize that for the Kubernetes manifest (in which case the conditional needs to be at a higher key), but this is code for how to achieve this specifically and generally in Terraform.

Retrieving sensitive data from secret version in terraform

When showing the state of the secret version, just get shown this:
terraform state show aws_secretsmanager_secret_version.mysecret
secret_string = (sensitive value)
I want now to see, what the acctual value is, but i do not know how to do it. I have and saw answers like "use terraform output", but when using this:
terraform output aws_secretsmanager_secret_version.mysecret
I get:
The state file either has no outputs defined, or all the defined outputs are empty.
Can anyone help with this, please?
This is by design and for very good reason. Generally, console output will always mask sensitive data from being displayed. The output command you mentioned is only helpful if you have defined an output block that would display this resource or attribute. However, all is not lost. You can either look directly in the state file since the state file will hold the value in plain text. Or you can use terraform console command which is my preference since I prefer where possible to not touch the state file.
CDoyle#MINGW64 ~/PycharmProjects/stack
$ terraform state show random_password.this
# random_password.this:
resource "random_password" "this" {
bcrypt_hash = (sensitive value)
id = "none"
length = 10
lower = true
min_lower = 0
min_numeric = 0
min_special = 0
min_upper = 0
number = true
numeric = true
result = (sensitive value)
special = true
upper = true
}
CDoyle#MINGW64 ~/PycharmProjects/stack
$ terraform console
> nonsensitive(random_password.this.result)
"I]-q*DCL+&"

How to create an RDS instance from the most recent snapshot or from scratch

In terraform, is there a way to conditionally create an RDS instance from the most recent snapshot of a given database or to create an empty database depending on the value of a parameter?
I tried something like that:
variable "db_snapshot_source" {
default = ""
}
data "aws_db_snapshot" "last_snap" {
count = "${var.db_snapshot_source == "" ? 0 : 1}"
most_recent = true
db_instance_identifier = "${var.db_snapshot_source}"
}
resource "aws_db_instance" "db" {
[...]
snapshot_identifier = "${var.db_snapshot_source == "" ? "" : data.aws_db_snapshot.last_snap.db_snapshot_identifier}"
}
Unfortunately, it does not work because TF seems to dereference data.aws_db_snapshot.last_snap even if the ternary is false. I get the following error message: * aws_db_instance.db: Resource 'data.aws_db_snapshot.last_snap' not found for variable 'data.aws_db_snapshot.last_snap.db_snapshot_identifier'.
How can I achieve a such behaviour? The only option I see is to declare two aws_db_instance resources each with opposed count which is horrifying.
By defining a count you are saying the result of the data resource will be a list even if it is a zero value.
resource "aws_db_instance" "db" {
[...]
snapshot_identifier = "${
var.db_snapshot_source == "" ? "" :
element(
concat(data.aws_db_snapshot.last_snap.*.db_snapshot_identifier, list("")), 0)
}"
}
The concat is required if you expect the list to be empty. Otherwise you get an error
element: element() may not be used with an empty list...
Github issue describing the concat behaviour
The documentation reads as though specifying snapshot_identifier is what triggers using a snapshot or not, so passing in an empty string is not enough to avoid starting from a snapshot. In that case, you would need two aws_rds_instance resources, and then have ternary expressions for count on each resource to decide which one to create. As you mentioned, this is horrifying, but it might work ok.
Another way to think about it is if you had a blank snapshot in your inventory to start from. Then it's just a ternary operator away from deciding to use the custom snapshot or this blank snapshot. I don't know that you can create a blank snapshot in Terraform though, it's creation might be out of band.

Update value in soy template declared with let

I have one value that is tied to a flag that comes from a config file that I need to show in my soy template. It is either true or false.
If true, the value needs to be "x" (for example, but it is a string)
If false, the value needs to be "" (empty)
Notice that I cannot pass in the true or false value from my config. I also cannot omit the value on false, it has to supply an empty string.
I've tried various forms of if statements using let, but according to my interpretations of the docs, a value declared with let cannot be changed (which doesn't make sense)
This is basically what I need:
{if $inputValue.value == 'true'}
{let $myVar: ($someValueThatExistsInMyTemplate) /}
{else}
{let $myVar: '' /}
{/if}
Then I will use $myVar in my template. However, whenever I try that, I get this error:
Found references to data keys that are not declared in SoyDoc: [myVar]
What can I do!?
Got it working using the ternary operator:
{let $dataParent: ($item.preferences.accordionOnOff.value == 'true') ? ($item.name) : '' /}

Codeigniter - Regex Expression to include a period - preg_match

I have a regex expression as follows:
return ( ! preg_match("/^([-a-z_ -])+$/i", $str)) ? FALSE : TRUE;
I need to add to it to allow a period, so that the input could be something like this:
"st. austell" or "st. thomas"
I have tried various ways to add the period to the above rule, but the page either crashes out and just displays a blank page, or my validation errors are triggered.
I have tried things like this, but to no avail.
([-a-z_ -.])
([-a-z_ -\.])
([-a-z_ -])\.
(\.[-a-z_ -]) etc etc...
I have tried everything and don't seem to bee having any luck - any ideas
Many Thanks
James
Three points:
The initial regex is redundant, since it specifies - twice.
[a-z_ .-] should work, you just have to let a-z together and - just after [ or just before ] (otherwise, - will be considered as a metachar).
return !condition ? false : true; should be simplified to return condition;, since condition already returns true or false (same logic for if(!condition) {var = false;} else {var = true;} which should be simplified to var = condition;).