I need to create Bigquery user defined function/procedure in Terraform
resource "google_bigquery_routine" "sproc" {
dataset_id = "cssp"
routine_id = "tf_test_routine_id"
routine_type = "TABLE_VALUED_FUNCTION"
language = "SQL"
definition_body = <<-EOS
SELECT 1 + value AS value
EOS
arguments {
name = "value"
argument_kind = "FIXED_TYPE"
data_type = jsonencode({ "typeKind" : "INT64" })
}
return_table_type = jsonencode({"columns" : [
{ "name" : "value", "type" : { "typeKind" : "INT64" } },
] })
}
Related
I am newbie to Terraform, apologies in advance in case inappropriate logic is used.
There is nested map, want to create new map using existing one.
terraform.tfvars
vpcs_info= {
"devops" = {
main = {
cidr = "10.14.0.0/16"
region = "ap-south-1"
peering = {
creator = {
devops = "poc",
uat = "main"
}
}
},
poc = {
cidr = "10.9.0.0/16"
region = "ap-south-1"
peering = {
creator = {
dev = "main"
}
}
}
}
}
locas.tf
locals {
vpcs_info = {
for vpc, properties in var.vpcs_info.devops:
vpc => {for dst_env, dst_vpc in properties.peering.creator : vpc => {"name": "${dst_env}-${dst_vpc}-vpc", "id": "${timestamp()}" }...}
}
}
Actual output:
{
"main" = {
"main" = [
{
"id" = "2023-02-05T21:23:24Z"
"name" = "devops-poc-vpc"
},
{
"id" = "2023-02-05T21:23:24Z"
"name" = "uat-main-vpc"
},
]
}
"poc" = {
"poc" = [
{
"id" = "2023-02-05T21:23:24Z"
"name" = "dev-main-vpc"
},
]
}
}
If we observe, in the output there is duplicity in KEYS. Need to get below desired output using for expression:
Desired output:
{
"main" = {
{
"id" = "2023-02-05T21:23:24Z"
"name" = "devops-poc-vpc"
},
{
"id" = "2023-02-05T21:23:24Z"
"name" = "uat-main-vpc"
}
}
"poc" = {
{
"id" = "2023-02-05T21:23:24Z"
"name" = "dev-main-vpc"
}
}
}
Note: "id" is sensitive information in actual requirement, to avoid security challenges, "${timestamp()}" is being used here.
You can do that with merge:
vpcs_info = merge([
for vpc, properties in var.vpcs_info.devops: {
for dst_env, dst_vpc in properties.peering.creator:
vpc => {
"name" = "${dst_env}-${dst_vpc}-vpc"
"id" = "${timestamp()}"
}...
}
]...)
I have two collections data like below . I need compare the two collections data and get the data if the data is same . Tried with below query but is it not giving any results .I am new to mongodb query ,Can anyone help me how to get the code key values if the data is same in both collections .The query is not returning any errors but the code values are not getting populated to new cllection
**Collection 1:**
{
"_id" : {
"value" : "12345"
},
"value" : {
"Identifier" : "12345",
"statu" : "simple",
"code" : {
"key" : "US",
"value" : "United State of America"
},
"Code" : {
"key" : "UK",
"value" : "London"
}
}
**Collection 2** :
{
"_id" : ObjectId("12345"),
"value" : {
"Identifier" : "12345",
"statu" : "simple",
"code" : {
"key" : "US",
"value" : "United State of America"
},
"Code" : {
"key" : "UK",
"value" : "London"
}
},
}
Mongo DB :
var identifiers = db.getSiblingDB("Datbase").getCollection("Collection1").find({
$or:[
{'code':{$exists:true}},
{'Code1':{$exists:true}},
]
}).toArray()
var bulk = db.getSiblingDB("Database2").getCollection("Collection2").initializeUnorderedBulkOp()
identifiers.forEach(Identifier =>{
db.getSiblingDB("Database2").getCollection("Collection2").aggregate([
{
$match:{
"Identifier":'$Identifier',
}
},
{
"$group" : {
"_id" : {
"Identifier":'$Identifier',
"key" : "$code.key",
"value" : "$code.value",
"key1" : "$code1.key1",
"value1" : "$code1.value2",
}
}
}, {
$merge:{
into:{
db:'Database',
coll:'Collection'
}
}
}
])
})
Using cursor get one by one items from 1st collection
For every item from 1st collection query 2nd collection for existense
If item does not exist or it's body is different (Use lodash.isEqual method) push them to some array or use replaceOne method to insert or replace document. (install lodash: npm i --save lodash)
const _ = require('lodash'); // import it at top
(async () => { // You can remove it if Your code already inside async scope
const source = db.getSiblingDB("Datbase").getCollection("Collection1");
const destination = db.getSiblingDB("Datbase").getCollection("Collection2");
const query = {$or:[
{'code':{$exists:true}},
{'Code1':{$exists:true}},
]};
const cursor = await source.find(query);
const differentItems = [];
// iterating source collection items
while(await cursor.hasNext()) {
const src = await cursor.next(); // source collectio inem
const queryDestination = {
"Identifier": src.Identifier, // extend Your equality constrains here
};
const dest = await destination.findOne(queryDestination);
// it may not exist || may be different (not equal)
const isDifferent = !dest || !(
_.isEqual(
_.omit(src, ['_id']),
_.omit(dest, ['_id'])
)
);
if (isDifferent) {
differentItems.push({src, dest});
/* or replace in db
await destination.replaceOne(
queryDestination,
_.omit(src, ['_id']),
{
upsert: true,
}
);
*/
}
}
console.log(`found ${differentItems.length} different documments`);
console.log(JSON.stringify(differentItems, null, 4));
)();
I could be going about this the wrong way, but I'm trying to copy a complex type and inject an object at specific point in a list of complex types. I have a working solution but it is not dynamic and I am forced to repeat myself for each point that I'm modifying.
The below works, but is not dynamic. I am required to repeat a block in the conditional merge statement for each property I need to manipulate.
locals {
map_to_merge = {
foo = "bar"
}
original_list = [
{
property_1 = "value"
property_2 = {
"nested" = {
string_property = "string"
map_property_1 = {
a = "b"
list = []
}
map_property_2 = {
x = "y"
}
}
}
}
]
modified_list = [
for item in local.original_list : merge(item, {property_2 = {
for key, value in item.property_2 : key => merge(value,
contains(keys(value), "map_property_1") ? {
map_property_1 = merge(value.map_property_1, local.map_to_merge)
} : {},
contains(keys(value), "map_property_2") ? {
map_property_2 = merge(value.map_property_2, local.map_to_merge)
} : {}
)
}})
]
}
output "test_original" {
value = local.original_list
}
output "test_modified" {
value = local.modified_list
}
The output is,
+ test_modified = [
+ {
+ property_1 = "value"
+ property_2 = {
+ nested = {
+ map_property_1 = {
+ a = "b"
+ foo = "bar"
+ list = []
}
+ map_property_2 = {
+ foo = "bar"
+ x = "y"
}
+ string_property = "string"
}
}
},
]
+ test_original = [
+ {
+ property_1 = "value"
+ property_2 = {
+ nested = {
+ map_property_1 = {
+ a = "b"
+ list = []
}
+ map_property_2 = {
+ x = "y"
}
+ string_property = "string"
}
}
},
]
What I'd like to do is something like below as it allows me not to repeat the conditional merge statement for each property I want to merge with.
locals {
map_to_merge = {
foo = "bar"
}
original_list = [
{
property_1 = "value"
property_2 = {
"nested" = {
string_property = "string"
map_property_1 = {
a = "b"
list = []
}
map_property_2 = {
x = "y"
}
}
}
}
]
modified_list = [
for item in local.original_list : merge(item, {property_2 = {
for nested, definition in item.property_2 : nested => merge(definition, {
for key, value in definition : key => can(tomap(value))
? merge(
value,
key == "map_property_1" || key == "map_property_2"
? local.map_to_merge
: {}
)
: value
})
}})
]
}
output "test_original" {
value = local.original_list
}
output "test_modified" {
value = local.modified_list
}
But I am getting an error,
Error: Inconsistent conditional result types
on test.tf line 41, in locals:
40: for key, value in definition : key => can(tomap(value))
41: ? merge(
42: value,
43: key == "map_property_1" || key == "map_property_2"
44: ? { foo = "bar" }
45: : {}
46: )
47: : value
The true and false result expressions must have consistent types. The given
expressions are object and object, respectively.
Is there a dynamic/better way to do this or do I need to repeat the block for each property that needs to be manipulated?
Turns out that switching from the use of can to try enables this to run as I'd expect.
locals {
map_to_merge = {
foo = "bar"
}
original_list = [
{
property_1 = "value"
property_2 = {
"nested" = {
string_property = "string"
map_property_1 = {
a = "b"
list = []
}
map_property_2 = {
x = "y"
}
}
}
}
]
modified_list = [
for item in local.original_list : merge(item, {property_2 = {
for nested, definition in item.property_2 : nested => merge(definition, {
for key, value in definition : key => try(
merge(
value,
key == "map_property_1" || key == "map_property_2"
? local.map_to_merge
: {}
),
value
)
})
}})
]
}
output "test_original" {
value = local.original_list
}
output "test_modified" {
value = local.modified_list
}
Here is the output,
+ test_modified = [
+ {
+ property_1 = "value"
+ property_2 = {
+ nested = {
+ map_property_1 = {
+ a = "b"
+ foo = "bar"
+ list = []
}
+ map_property_2 = {
+ foo = "bar"
+ x = "y"
}
+ string_property = "string"
}
}
},
]
+ test_original = [
+ {
+ property_1 = "value"
+ property_2 = {
+ nested = {
+ map_property_1 = {
+ a = "b"
+ list = []
}
+ map_property_2 = {
+ x = "y"
}
+ string_property = "string"
}
}
},
]
variable "query_param" {
type = list(string)
default = [
"hello",
"one",
"two"
]
}
locals {
common_tags = flatten([
for i in var.query_param: {
"method.request.querystring.${i}" = false
}
])
}
output name {
value = local.common_tags
description = "description"
}
I have this code to iterate the variable(list) to locals (map). I got the below output which is not desired.
name = [
{
"method.request.querystring.hello" = false
},
{
"method.request.querystring.one" = false
},
{
"method.request.querystring.two" = false
},
]
The desired output is getting all the values in a single array. As shown below.
name = [
{
"method.request.querystring.hello" = false,
"method.request.querystring.one" = false,
"method.request.querystring.two" = false
}
]
Is there any way to achieve this?
I think you would want something like this:
locals {
common_tags = {
for i in var.query_param :
"method.request.querystring.${i}" => false
}
}
The output of the code above will be as follows:
name = {
"method.request.querystring.hello" = false
"method.request.querystring.one" = false
"method.request.querystring.two" = false
}
Please note, the name itself is not an array in this case. If you want it to be, you can do the following:
locals {
common_tags = [{
for i in var.query_param :
"method.request.querystring.${i}" => false
}]
}
The output will be:
name = [
{
"method.request.querystring.hello" = false
"method.request.querystring.one" = false
"method.request.querystring.two" = false
}
]
This is doing my head in a little bit. So I want to create a map of objects like so:
{
"nic_1" = {
"interface_id" = "blah"
"ip_configuration_name" = "blah"
},
"nic_2" = {
"interface_id" = "blah"
"ip_configuration_name" = "blah"
},
}
The source for this data comes from the below list:
ni-resource = [
{
"id" = "blah"
"ip_configuration" = [
{
"name" = "blah"
},
]
"name" = "nic_1"
},
{
"id" = "blah"
"ip_configuration" = [
{
"name" = "blah"
},
]
"name" = "nic_2"
},
]
So in other words the ni-resource->id needs to map to interface_id and ni-resource->ip_configuration->name needs to map to ip_configuration_name.
I am trying to create a local as below which is not working:
locals {
ni_list = { for ni in ni-resource :
ni["name"] => {
interface_id = ni["id"]
ip_configuration = ni["ip_configuration"][0]["name"]
}
}
}
The error I am getting is as follows:
Error: Invalid object key
The key expression produced an invalid result: string required.
Here is the full ni-resource output:
ni-resource = [
{
"applied_dns_servers" = []
"dns_servers" = []
"enable_accelerated_networking" = false
"enable_ip_forwarding" = false
"id" = "blah"
"internal_dns_name_label" = ""
"internal_domain_name_suffix" = "blah"
"ip_configuration" = [
{
"name" = "blah"
"primary" = true
"private_ip_address" = "dummy"
"private_ip_address_allocation" = "Dynamic"
"private_ip_address_version" = "IPv4"
"public_ip_address_id" = ""
"subnet_id" = "dummy"
},
]
"location" = "dummy"
"mac_address" = ""
"name" = "nic_1l"
"private_ip_address" = "dummy"
"private_ip_addresses" = [
"dummy",
]
"resource_group_name" = "dummy"
"virtual_machine_id" = ""
},
]