Lookup function on nested locals variable - terraform

Using the lookup function, how could I lookup the value of c?
lookup({a="ay", b={c="ce"}}, "c", "what?")
"what?"

If your goal is to produce the value "what?" if either b or b.c are absent from the data structure then you can achieve that concisely using the try function:
> try({ a = "ay", b = { c = "ce" } }.b.c, "what?")
"ce"
> try({ a = "ay", b = {} }.b.c, "what?")
"what?"
> try({ a = "ay" }.b.c, "what?")
"what?"

Hope this helps:
locals {
# NOTE: lookup(map, key, default)
value_out = lookup({a="ay", b={c="ce"}}, "b", "what?")
value_out_c = local.value_out.c
}
output "value_returned_c" {
value = local.value_out_c
}

I tried this with terraform version v1.0.0. Not sure whether it solves your problem?
lookup(lookup({a="ay", b={c="ce"}}, "b", "what?"),"c", "what")

Related

How to remove values from a map in Terraform that match a list of keys?

I want to remove values from a map in Terraform that match a list of keys e.g. remove keys_b and keys_c from the map below.
Input
map = {
key_a = value_a,
key_b = value_b,
key_c = value_c
...
key_m = value_m
}
Desired Output
filtered_map = {
key_a = value_a,
...
key_m = value_m
}
I've tried using the contains function but that passes through only one value and not a list of values. I am not sure how to loop over this either.
output "test" {
value = { for k, v in var.map: k => v if ! contains(values(v), var.exclude) }
}
You were almost there. You had wrong arguments in contains. It should be:
output "test" {
value = { for k, v in var.map: k => v if contains(var.exclude, k) }
}

condition checking in terraform

I have a block of terraform code.
data "am_nodes" "tm_nodes" {
count = length(local.l_domains)
ay = local.l_domains[count.index].name
pol = local.am_pool[count.index].resource_id
host_reg = "${local.reg_k}${local.cte_env_map[local.environment]}-pd${local.pI}-mr*"
}
here I want to put a condition like if local.pI value is 0 then ignore entire host_reg
is there any way to achieve this ?
Yes you can do that with the ternary operator, like this:
data "am_nodes" "mt_nodes" {
count = length(local.l_domains)
ay = local.l_domains[count.index].name
pol = local.am_pool[count.index].resource_id
host_reg = local.pl == 0 ? null : "${local.reg_k}${local.cte_env_map[local.environment]}-dp${local.pI}-mr*"
}

Override variables in Terraform

I've started to use Terraform lately, and i need some help. I hope it's not too basic. I've the following Terraform data structure.
abc_template = {
a = var.a
b = var.b
c = var.c
d = var.d
....
....
....
k = var.k
}
And then i run:
resource "local_file" "aaa" {
count = 1
content = templatefile("${path.module}/templates/abc.tmpl", local.abc_template)
....
....
}
I need to create a new template (xyz_template), Which should be very similar to abc_template, While only a few variables will changed from the original template. What can i do instead of duplicating so many code lines? Is there a way to inherit abc_template, and just to override the relevant variables, Instead of creating xyz_template which might be very similar to abc_template?
Please advise.
You could use a map:
variable "global" {
type = "map"
default = {
name = "TEST"
addr = "Test123"
}
}
output "example" {
value = templatefile("${path.module}/web.tpl", {
global = var.global
})
}
template:
My name is ${global.name}.
And you can override values in a map using the merge() function.
You can use the merge function to produce a new map using a blend of elements from multiple maps.
For example:
locals {
abc_template = {
a = var.a
b = var.b
c = var.c
d = var.d
}
xyz_template = merge(
local.abc_template,
{
d = var.other_d
x = var.x
y = var.y
z = var.z
},
)
}
In the above example, local.xyz_template would have all of the same elements as local.abc_template except that d is overridden, and it would additionally have elements x, y, and z.

Selecting a tuple index using a variable in Swift

That is what i am trying to do:
var i = 0
var string = "abcdef"
for value in string
{
value.[Put value of variable i here] = "a"
i++
}
How can i insert the value of i in the code?
Easiest is probably just convert it to an NSMutableString:
let string = "abcdef".mutableCopy() as NSMutableString
println( "\(string)")
for var i = 0; i < string.length; ++i {
string.replaceCharactersInRange(NSMakeRange(i, 1), withString: "a")
}
println( "\(string)")
Yes, it's a bit ugly but it works.
A much cleaner way is to use Swifts map function:
var string = "abcdef"
let result = map(string) { (c) -> Character in
"a"
}
println("\(result)") // aaaaaa
You should just be able to use the following but this doesn't compile:
map(string) { "a" }
In you comments you mention you want to split up the string on a space, you can just use this for that:
let stringWithSpace = "abcdef 012345"
let splitString = stringWithSpace.componentsSeparatedByString(" ")
println("\(splitString[0])") // abcdef
println("\(splitString[1])") // 012345

match check in matlab

i have strings like these:
s{1,2} = 'string';
s{2,2} = 'string2';
and in workspace structure like this
U.W.string = [2 2.5 3]
I want to check (in loop) s{1,2} or s{2,2} or s{i,2} matches any structure with the same name. If so, assign values from this structure to some variable var(i). How can it be done?
Use isfields to check, if a string is the name of a field in a struct. Then use the syntax struct.(name), where name is a string to access the field. Your code might look something like:
test = struct('hello', 'world', 'count', 42, 'mean', 10);
fields = {'test', 'count';
'hello', 'text';
'more', 'less'};
values = {pi, 'dummy', -1};
for row = 1 : size(fields, 1)
for column = 1 : size(fields, 2)
if isfield(test, fields{row, column})
test.(fields{row, column}) = values{row};
end
end
end
This converts the initial struct
test =
hello: 'world'
count: 42
mean: 10
to this one
test =
hello: 'dummy'
count: 3.1416
mean: 10
A shorter implementation is achieved by removing the inner loop and giving a cell-array to isfields:
for row = 1 : size(fields, 1)
%# Note the parenthesis instead of curly braces in the next statement.
match = isfield(test, fields(row, :));
if any(match)
test.(fields{row, match}) = values{row};
end
end
Use isfield(structName,fieldName). This should do the trick:
strings{1,1} = 'foo';
strings{1,2} = 'bar';
strings{1, 3} = 'foobar';
U.W.foo = 1;
U.W.foobar = 5;
for idx = 1:length(strings)
if(isfield(U.W,strings{1,idx}))
expression = sprintf('outvar(idx) = U.W.%s',strings{1,idx});
eval(expression);
end
end

Resources