I am trying to figure out a way to skip the iteration of an inner for loop if a particular attribute does not exist - in this case variables. However, I am beginning to wonder if I am expecting too much from a declarative language.
This is my input:
locals {
environments = {
dev : {
name: "development"
variables : [
{
key: "GCP_PROJECT"
value: "gcp-project-1"
},
{
key: "ANOTHER_VAR"
value: "some-value"
}
]
}
prod : {
name : "production"
variables : [
{
key: "GCP_PROJECT"
value: "gcp-project-2"
}
]
}
}
}
environments is consumed here, which basically iterates through variables to convert and store it in a data structure that is easier to work with later on:
locals {
variables = flatten([
for k, env in local.environments : [
for var, var in env.variables : { <--- Is there a way to skip an iteration if env.variables does not exist?
key: var.key
value: var.value
}
]
])
}
This loop will output something similar to this:
variables = [
{
key = "KEY"
value = "VALUE"
}
]
Which ultimately is used here:
resource "gitlab_project_variable" "variable" {
for_each = {
for i, v in local.variables : v.terraform_id => v
}
key = each.value.key
value = each.value.value
}
You can use lookup:
locals {
variables = flatten([
for k, env in local.environments : [
for var, var in lookup(env, "variables", {}) : {
key: var.key
value: var.value
}
]
])
}
I would typically recommend setting object attributes to null when you aren't using them so that the object type remains consistent in all cases, and then you can use comparison with null as the filter:
locals {
variables = flatten([
for k, env in local.environments : [
for var, var in env.variables : {
key: var.key
value: var.value
}
]
if env.variables != null
])
}
You could also set the inapplicable ones to be an empty list and then your expression would work without any extra conditions at all.
If you really do want to use inconsistent object types for your environment objects then it's not so clean to handle but you can still get something similar to the above by using the can function to detect when accessing the variables attribute would fail:
locals {
variables = flatten([
for k, env in local.environments : [
for var, var in env.variables : {
key: var.key
value: var.value
}
]
if can(env.variables)
])
}
Related
I have a data called votes, i want to get value votes.voteDict.12
But 12 is a variable, that's a cat id get from api. And i want shop.poiId = 691904
How can i call it?
<v-if="shop.poiId === votes.voteDict.[catid]">
data: function () {
return {
votes:[]
}
}
Data
"voteDict": {
"12": [
691904,
649950,
649031
],
"13": [
677267,
686968
],
"29": [
545344,
499690,
431970,
618904,
510121
],
"30": [
618540,
613464,
632345,
672805,
654174
],
Thank you
I would like to know how to get this data
You will need the value 691904 stored in some variable depending on some condition as 12 contains "12": [691904,649950,649031]. Then you can try:
computed: {
selectedIndex() {
const idx = votes.voteDict[catid].findIndex(num => num === 691904)
return idx === -1 ? 0 : idx
}
}
Then change your if statement to
<v-if="shop.poiId === votes.voteDict[catid][selectedIndex]">
Again, the number (691904) in the computed property should be a variable set according to some condition or dependent on the result of an API call.
You should use Array.includes to test for the shop.poiId value. Also accessing "12" property of votes.voteDict would be like votes.voteDict[catId] where catId is the integer 12
<div v-if="votes.voteDict[catId].includes(shop.poiId)">
let's suppose we have this variable:
foobars = {
"first" : {
specialkeys: [
"a",
"b",
"c"
]
}
"second" : {}
}
now let's say we would like to loop over that foobars object knowing that specialkeys doesn't exist in the "second" object.
This is what I tried but it complains that
This object does not have an attribute named specialkeys
My tries:
data = flatten([
for k, v in var.foobars : [
for sk in v.specialkeys : {
special = sk,
foo = k
}
]
])
I believe you would want to do the following:
data = flatten([
for k, v in local.foobars :
[
for sk, sv in v :
[
for spec in sv : {
special = spec,
foo = k
}
]
]
])
This will output something like this:
[
{
"foo" = "first"
"special" = "a"
},
{
"foo" = "first"
"special" = "b"
},
{
"foo" = "first"
"special" = "c"
},
]
Again I'm stuck with a nested Array of objects. I want to flatten it out, but I do have to keep some nested objects. The Problem I'm running into: How to rename the keys of the nested objects since I have an undefined number of nested objects. There might be 3 of them oder 8. So property1_3 has to be renamed to eg property1_3_1, property1_3_2 - depending on how many objects are in the original json data. And how to aply them to the correct parent object.
The json data I recieve looks like:
data = [{
"property1_1": "value1_1",
"property1_2": "value1_2",
"property1_3": [
[{
"subproperty1_1_1": "subvalue1_1_1",
"subproperty1_1_2": "subvalue1_1_2"
}],
[{
"subproperty1_2_1": "subvalue1_2_1",
"subproperty1_2_2": "subvalue1_2_2"
}]
]
},
{
"property2_1": "value2_1",
"property2_2": "value2_2",
"property2_3": [
[{
"subproperty2_1_1": "subvalue2_2_1",
"subproperty2_1_2": "subvalue2_2_2"
}],
[{
"subproperty2_2_1": "subvalue2_2_1",
"subproperty2_2_2": "subvalue2_2_2"
}],
[{
"subproperty2_3_1": "subvalue2_2_1",
"subproperty2_3_2": "subvalue2_2_2"
}]
]
}
]
What I want to achieve now is:
data = [
{
"property1_1": "value1_1",
"property1_2": "value1_2",
"property1_3_index1": {"subproperty1_1_1":"subvalue1_1_1", "subproperty1_1_2":"subvalue1_1_2"},
"property1_3_index2": {"subproperty1_2_1":"subvalue1_2_1", "subproperty1_2_2":"subvalue1_2_2"}
},
{
"property2_1": "value2_1",
"property2_2": "value2_2",
"property2_3_index1": {"subproperty2_1_1":"subvalue2_2_1", "subproperty2_1_2":"subvalue2_2_2"},
"property2_3_index2": {"subproperty2_2_1":"subvalue2_2_1", "subproperty2_2_2":"subvalue2_2_2"},
"property2_3_index3": {"subproperty2_3_1":"subvalue2_2_1", "subproperty2_3_2":"subvalue2_2_2"}
}
]
My last try was:
transformData(input) {
const testArray = [];
input.map(obj => {
for (const prop in obj) {
if (obj.hasOwnProperty(prop) && Array.isArray(obj[prop])) {
for (const [index, element] of obj[prop].entries()) {
testArray.push(element[0]);
}
}
}
});
}
but this only leeds to an array with all the single subobjects in one array. I'm also not quite sure if it's best trying to convert the original data or to build a new array as I tried before.
I finally found a way to achieve this.
transformData(input) {
return input.map(obj => {
for (const prop in obj) {
if (obj.hasOwnProperty(prop) && Array.isArray(obj[prop])) {
for (let i = 0; i < obj[prop].length; i++) {
const name = prop + (i + 1).toString();
obj[name] = obj[prop].flat(1)[i];
}
delete obj[prop];
}
}
return obj;
});
}
i would like to build a list of maps in terraform. Is there an operation that would let me do that.
eg: i would like to build the structure (from aws_instance.test.*.private_ip)
addresses = [
{
address = private_ip-1
},
{
address = private_ip-2
}
...
]
Apologies if this has already been resolved, I see that it's an older question.
I'm not sure if this is best practice, but this is the way I would attempt to reach the desired state.
Using the null_resource you'd be able to do the following:
variable "addresses" {
type = "list"
default = [
"private_ip-1",
"private_ip-2",
"private_ip-3"
]
}
resource "null_resource" "test" {
count = "${length(var.addresses)}"
triggers {
address = "${element(var.addresses, count.index)}"
}
}
output "addresses" {
value = "${null_resource.test.*.triggers}"
}
And have this output:
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
addresses = [
{
address = private_ip-1
},
{
address = private_ip-2
},
{
address = private_ip-3
}
]
I'm currently on terraform 0.11.5, null_resource appears to have been added in 0.6.7
There are limitations to the null_resource triggers though. interpolated variables can only result in strings. So, unfortunately you won't be able to interpolate a value that would result in a list or a map; for example:
resource "null_resource" "test" {
triggers {
mylist = "${var.addresses}"
}
}
will result in an error
Error: null_resource.test: triggers (address): '' expected type 'string', got unconvertible type '[]interface {}'
With terraform 10.8 you can
output "private_subnets" {
value = [
"${aws_subnet.private.*.id}"
]
}
https://github.com/hashicorp/terraform/issues/7430
I have a js object array like this.
[
{
name:"Japanilainen ravintola Koto",
rating:3.9,
photo:[
{
height:2160,
html_attributions:[
"Hannes Junnila"
],
photo_reference:"CoQBdwAAAMDlivT0nOnYg8jC1txZ3RbfBR59XvKN0WphDbRVUXaUTQclzzaIaXJ8-p7s3x_aG67AUsM_HLNML6pzGl3v_wV2D-eudH_3wy2cB1ROrRgGcGyf4lRuNpE3WwXYbYZu6EK8oEPiJ5B17Lybj-eVbYM2EgVVBgOrUJhsblY1mfxWEhAZ4oHCFakH-hgkbksfGa2uGhQe4aUeOrS2isAir01KUwQ7N3Ce2Q",
width:2269
}
]
},
{
name:"Kin Sushi Helsinki",
rating:4.2,
photo:[
{
height:2988,
html_attributions:[
"Stephan Winter"
],
photo_reference:"CoQBdwAAAN4iMumSbQjtRnJIH1AKRdbSfnI02WGh11r1xaVnZl1ohebKp6zpAS4mmJFqTagrIqUJ39kzulVI0sz2UzzfaVdsAFc5f80PnOCzSLqL5gnpsqv90dVJIqUWD3Bcc9TgYPPs3oGwyekkOsmjQ59o9yqdoF5GzrpaKkojhMNLxpfzEhBKpRkA2CzINpUzAAe3e90TGhQ_KbYCmtJYLfVGIu1kZkzQIAwE4A",
width:5312
}
]
}
]
I get this array above by doing this for each.
response.results.forEach((entry)=>{
var restaurantName = {
"name" : entry.name,
"rating" : entry.rating,
"photo_reference" : entry.photos
}
arr.push(restaurantName);
});
res.send(arr);
And I send the array to my browser so I can see it.
What I am trying to do is to get photo_reference from the entry.photos
I tried entry.photos[0].photo_reference and many more ways and in all of them I am getting a cannot read properly, and now I am not sure how to get that information out.
I edited some of the variable names to make it easier to simulate here, but just map the objects in the photo arrays to their references, and you'll get an array of photo references.
const data = [
{
name:"Japanilainen ravintola Koto",
rating:3.9,
photo:[
{
height:2160,
html_attributions:[
'Hannes Junnila'
],
photo_reference:"CoQBdwAAAMDlivT0nOnYg8jC1txZ3RbfBR59XvKN0WphDbRVUXaUTQclzzaIaXJ8-p7s3x_aG67AUsM_HLNML6pzGl3v_wV2D-eudH_3wy2cB1ROrRgGcGyf4lRuNpE3WwXYbYZu6EK8oEPiJ5B17Lybj-eVbYM2EgVVBgOrUJhsblY1mfxWEhAZ4oHCFakH-hgkbksfGa2uGhQe4aUeOrS2isAir01KUwQ7N3Ce2Q",
width:2269
}
]
},
{
name:"Kin Sushi Helsinki",
rating:4.2,
photo:[
{
height:2988,
html_attributions:[
'Stephan Winter'
],
photo_reference:"CoQBdwAAAN4iMumSbQjtRnJIH1AKRdbSfnI02WGh11r1xaVnZl1ohebKp6zpAS4mmJFqTagrIqUJ39kzulVI0sz2UzzfaVdsAFc5f80PnOCzSLqL5gnpsqv90dVJIqUWD3Bcc9TgYPPs3oGwyekkOsmjQ59o9yqdoF5GzrpaKkojhMNLxpfzEhBKpRkA2CzINpUzAAe3e90TGhQ_KbYCmtJYLfVGIu1kZkzQIAwE4A",
width:5312
}
]
}
]
const arr = []
data.forEach((entry)=>{
var restaurantName = {
"name" : entry.name,
"rating" : entry.rating,
"photo_reference" : entry.photo.map(x => x.photo_reference)
}
arr.push(restaurantName);
});
console.log(arr);
entry.photoes is not defined in your response.results object array.. did you mean to access it as entry.photo (inside your foreach function) ?