Related
I have two different scenarios, one with public subnets and one with private.
For both, I would like to apply some combination of for-loop and zipmask to have a single map object. You can assume I have checked the ordering of the two input maps/lists and that they are align.
Using the public-subnet as the first example, I have one cidr for each user:
pub_cidr_map = {
"user2" = "10.0.8.0/21"
"user4" = "10.0.24.0/21"
"user1" = "10.0.0.0/21"
"user3" = "10.0.16.0/21"
}
pub_id_list = [
"subnet-666666662ee6f3442",
"subnet-6666666696b92d895",
"subnet-66666666cbaa4bfb3",
"subnet-6666666655a09d064",
]
I would like this to look like this so I can access both values with a single key:
pub_lookup_map = {
"user2" = ["10.0.8.0/21", "subnet-666666662ee6f3442"]
"user4" = ["10.0.24.0/21", "subnet-6666666696b92d895"]
"user1" = ["10.0.0.0/21", "subnet-66666666cbaa4bfb3"]
"user3" = ["10.0.16.0/21", "subnet-6666666655a09d064"]
}
I'd also like to accomplish something similar with my private subets, which are apportioned two-per-user:
priv_cidr_map = {
"user1" = [
"10.0.96.0/20",
"10.0.112.0/20",
]
"user2" = [
"10.0.160.0/20",
"10.0.176.0/20",
]
"user3" = [
"10.0.64.0/20",
"10.0.80.0/20",
]
"user4" = [
"10.0.128.0/20",
"10.0.144.0/20",
]
}
priv_id_list = [
"subnet-666666662f611f9a5",
"subnet-6666666689f1eff5e",
"subnet-66666666a3fe6efb9",
"subnet-66666666faf4a62a8",
"subnet-666666668f1442700",
"subnet-66666666328a4b134",
"subnet-666666661b147a933",
"subnet-666666661ce02c330"
]
I would like this to look like
priv_lookup_map = {
"user1" = [
["10.0.96.0/20","subnet-666666662f611f9a5"]
["10.0.112.0/20","subnet-6666666689f1eff5e"]
]
"user2" = [
["10.0.160.0/20","subnet-66666666a3fe6efb9"]
["10.0.176.0/20","subnet-66666666faf4a62a8"]
]
"user3" = [
["10.0.64.0/20","subnet-666666668f1442700"]
["10.0.80.0/20","subnet-66666666328a4b134"]
]
"user4" = [
["10.0.128.0/20","subnet-666666661b147a933"]
["10.0.144.0/20","subnet-666666661ce02c330"]
]
}
I am open to any other structures someone might think are useful; the use case here is to provision subnets and EIPs as part of a separate, stateful deployment of a VPC prior to the deployment of the resources (like EC2, RDS) that will reside within these ranges.
I can not guarantee that this solution is correct, I will share my attempt anyway hoping it might be helpful.
For the public subnets:
locals {
pub_lookup_map = {for key, value in zipmap(keys(var.pub_cidr_map), var.pub_id_list) : key => [var.pub_cidr_map[key], value] }
}
This will produce the following output:
pub = {
"user1" = [
"10.0.0.0/21",
"subnet-666666662ee6f3442",
]
"user2" = [
"10.0.8.0/21",
"subnet-6666666696b92d895",
]
"user3" = [
"10.0.16.0/21",
"subnet-66666666cbaa4bfb3",
]
"user4" = [
"10.0.24.0/21",
"subnet-6666666655a09d064",
]
}
The problem with this output is that, as I noted in the comments, the iteration over a the keys of a map happens in a lexicographical order. This means that user1 will be mapped to the first entry from pub_id_list, user2 to the second entry, etc. Even if you are suggesting in the comments that "I've checked this ordering issue and not to worry about it", please double check this solution before using it.
For the private subnets:
locals {
cidr_subnet_id = zipmap(flatten(values(var.priv_cidr_map)), var.priv_id_list)
priv_lookup_map = {for key, value in var.priv_cidr_map: key => [ for cidr in value: [cidr, local.cidr_subnet_id[cidr]]]}
}
Please note, that I'm using an intermediary local variable to make my code readable. The value for cidr_subnet_id will be:
cidr_subnet_id = {
"10.0.112.0/20" = "subnet-6666666689f1eff5e"
"10.0.128.0/20" = "subnet-666666661b147a933"
"10.0.144.0/20" = "subnet-666666661ce02c330"
"10.0.160.0/20" = "subnet-66666666a3fe6efb9"
"10.0.176.0/20" = "subnet-66666666faf4a62a8"
"10.0.64.0/20" = "subnet-666666668f1442700"
"10.0.80.0/20" = "subnet-66666666328a4b134"
"10.0.96.0/20" = "subnet-666666662f611f9a5"
}
This is essentially a map between the CIDR and the subnet id. Apparently, this works correctly, because the keys from the priv_lookup_map are in lexicographical order when provided. I think this somewhat answers your question in the comments for "if both maps are in lexigraphical order isn't this a non-issue?"
The output for priv_lookup_map will be:
priv = {
"user1" = [
[
"10.0.96.0/20",
"subnet-666666662f611f9a5",
],
[
"10.0.112.0/20",
"subnet-6666666689f1eff5e",
],
]
"user2" = [
[
"10.0.160.0/20",
"subnet-66666666a3fe6efb9",
],
[
"10.0.176.0/20",
"subnet-66666666faf4a62a8",
],
]
"user3" = [
[
"10.0.64.0/20",
"subnet-666666668f1442700",
],
[
"10.0.80.0/20",
"subnet-66666666328a4b134",
],
]
"user4" = [
[
"10.0.128.0/20",
"subnet-666666661b147a933",
],
[
"10.0.144.0/20",
"subnet-666666661ce02c330",
],
]
}
In Terraform, I need to transform my input data structure from e.g.:
vip_lists = [
["1.0.1.1", "1.0.1.2", "1.0.1.3", "1.0.1.4"]
["1.0.2.1", "1.0.2.2", "1.0.2.3", "1.0.2.4"]
["1.0.0.1", "1.0.0.2", "1.0.0.3", "1.0.0.4"]
]
to produce an output like this:
vip_sets = [
["1.0.1.1", "1.0.2.1", "1.0.0.1"]
["1.0.1.2", "1.0.2.2", "1.0.0.2"]
["1.0.1.3", "1.0.2.3", "1.0.0.3"]
["1.0.1.4", "1.0.2.4", "1.0.0.4"]
]
So essentially, i need to take my input list of lists and create an output which is again a list of lists but whose 0th list is a list of the 0th elements from each of the lists in the input...then the same again for the 1st and so on.
I can't know in advance how many lists will be in the input or how long they will be, but we can assume the lists will all be the same length if that helps.
I've tried pretty much everything I can think of and searched the web but since with no luck. All suggestions would be very welcome!
I once wrote version of this for lists of lists that are not the same length for one of our modules on github.com/mineiros-io where we used such transformations to create 2 dimensional sets of resources using count. (Those are not in use atm as we transformed them to maps for use with ressource level for_each).
locals {
matrix = [
["1.0.1.1", "1.0.1.4"],
["1.0.2.1", "1.0.2.2", "1.0.2.3", "1.0.2.4"],
["1.0.0.1", "1.0.0.3", "1.0.0.4"]
]
row_lengths = [
for row in local.matrix : length(row)
]
max_row_length = max(0, local.row_lengths...)
output = [
for i in range(0, local.max_row_length) : [
for j, _ in local.matrix : try(local.matrix[j][i], null)
]
]
output_compact = [
for i in range(0, local.max_row_length) : compact([
for j, _ in local.matrix : try(local.matrix[j][i], null)
])
]
}
output "matrix" {
value = local.output
}
output "compact" {
value = local.output_compact
}
which can handle dynamic list sizes and output them compact or filled with null values:
Outputs:
compact = [
[ "1.0.1.1", "1.0.2.1", "1.0.0.1" ],
[ "1.0.1.4", "1.0.2.2", "1.0.0.3" ],
[ "1.0.2.3", "1.0.0.4" ],
[ "1.0.2.4" ],
]
matrix = [
[ "1.0.1.1", "1.0.2.1", "1.0.0.1" ],
[ "1.0.1.4", "1.0.2.2", "1.0.0.3" ],
[ null, "1.0.2.3", "1.0.0.4" ],
[ null, "1.0.2.4", null ],
]
I know an answer is already accepted, but maybe some one can still make use of this dynamic version.
This is sort of horrible, but it works (Although I haven't tested what it'd do if vip_lists was empty. Probably crash, as I'm indexing to vip_lists[0] without checking):
locals {
vip_lists = [
["1.0.1.1", "1.0.1.2", "1.0.1.3", "1.0.1.4"],
["1.0.2.1", "1.0.2.2", "1.0.2.3", "1.0.2.4"],
["1.0.0.1", "1.0.0.2", "1.0.0.3", "1.0.0.4"]
]
vip_sets = [for i in range(0, length(local.vip_lists[0])): [for j in range(0, length(local.vip_lists)): local.vip_lists[j][i]]]
}
output "vip_sets" {
value = local.vip_sets
}
$ terraform apply
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
vip_sets = [
[
"1.0.1.1",
"1.0.2.1",
"1.0.0.1",
],
[
"1.0.1.2",
"1.0.2.2",
"1.0.0.2",
],
[
"1.0.1.3",
"1.0.2.3",
"1.0.0.3",
],
[
"1.0.1.4",
"1.0.2.4",
"1.0.0.4",
],
]
I have data in geojson format.
Here is my data :
{
"type" : "FeatureCollection",
"features" : [
{
"type" : "Feature",
"properties" : {
"year" : 2015,
"season" : "rabbi",
"crop" : "banana",
"district" : "pune",
"taluka" : "haveli",
"circle" : "uralikanchan",
"farmer" : 100
},
"geometry" : {
"type" : "Polygon",
"coordinates" : [
[
74.129992,
18.505494
],
[
74.129047,
18.505494
],
[
74.128275,
18.504436
],
[
74.127588,
18.503052
],
[
74.114456,
18.498331
],
[
74.113941,
18.498331
],
[
74.112482,
18.493773
],
[
74.112053,
18.491494
],
[
74.143724,
18.473992
],
[
74.144497,
18.474888
],
[
74.145269,
18.476027
],
[
74.15617,
18.486854
],
[
74.155912,
18.488319
],
[
74.145956,
18.502564
],
[
74.129992,
18.505494
]
]
}
}
]
}
views.py file :
from rest_framework_mongoengine.viewsets import ModelViewSet as MongoModelViewSet
from app.serializers import *
from rest_framework_mongoengine.generics import *
def index_view(request):
context = {}
return TemplateResponse(request, 'index.html', context)
class ToolViewSet(MongoModelViewSet):
serializer_class = ToolSerializer
my_filter_fields = ('type','features','geometry',) # specify the fields on which you want to filter
def get_kwargs_for_filtering(self):
filtering_kwargs = {}
for field in self.my_filter_fields: # iterate over the filter fields
field_value = self.request.query_params.get(field) # get the value of a field from request query parameter
if field_value:
if ',' in field_value: # put your queryParams into an array and use the built-in django filter method '__in'
filtering_kwargs[field + '__in'] = field_value.split(',')
else:
filtering_kwargs[field] = field_value
return filtering_kwargs
def get_queryset(self):
queryset = Tool.objects.all()
filtering_kwargs = self.get_kwargs_for_filtering() # get the fields with values for filtering
if filtering_kwargs:
queryset = Tool.objects.filter(**filtering_kwargs) # filter the queryset based on 'filtering_kwargs'
return queryset
This dynamic query works for field "type","features" and "geometry".
But, I have to show data using my properties fields
( i.e : year,season,crop,district,taluka. this all fields in fields{properties{"crop","district",.....}}
what I have to changes in this code for working dictionary fields
then If I have go to server http://api/tool/?crop=banana then it's display this data ?
I need to traverse through below nested dictionary and get the values highlighted "REM" and "signmeup-3.4.208.zip". Can anyone help in getting these values out?
{"actions":[{},{"parameters":[{"name":"ReleaseRequest","value":"REM"},{"name":"Artifact","value":"signmeup-3.4.2088.zip"}]},{"causes":[{"shortDescription":"Started by user ","userId":"sbc","userName":"xyz"}]},{},{},{},{},{},{"parameters":[{"name":"DESCRIPTION_SETTER_DESCRIPTION","value":"inf-xyz"}]},{}],"artifacts":[{"displayPath":"INT_backup.xml","fileName":"INT_backup.xml","relativePath":"INT_backup.xml"},{"displayPath":"Invalidlist.txt","fileName":"Invalidlist.txt","relativePath":"Invalidlist.txt"},{"displayPath":"OUT_backup.xml","fileName":"OUT_backup.xml","relativePath":"OUTP_backup.xml"}],"building":False,"description":"inf-ECR2.2088.zip","duration":1525074,"estimatedDuration":1303694,"executor":None,"fullDisplayName":"inf-#33","id":"2015-07-27_18-17-00","keepLog":False,"number":33,"result":"SUCCESS","timestamp":1438046220000,"url":"inf/33/","builtOn":"Windows_Slave","changeSet":{"items":[],"kind":None},"culprits":[]}
>>> d = {
... "actions": [
... {},
... {"parameters": [
... {"name": "ReleaseRequest", "value": "REM"},
... {"name": "Artifact", "value": "signmeup-3.4.208.zip"}
... ]},
... {"causes": [{"shortDescription": "user"}]}
... ]
... }
To get each value:
>>> d['actions'][1]['parameters'][0]['value']
'REM'
>>> d['actions'][1]['parameters'][1]['value']
'signmeup-3.4.208.zip'
To get all values:
>>> [param['value'] for param in d['actions'][1]['parameters']]
['REM', 'signmeup-3.4.208.zip']
I have this regular expression which is what is allowed in the String.
^\pL*['#-]?\pL*\$
The requirements have changed and now I need to drop everything else from the String. For example only one of these special characters ', #, and - is allowed.
How can I change this regex to drop everything else that does not fit this ?
Here is the list of expected values:
JohnO'Connell -> allowed. should be as is.
JohnDias -> allowed. should be as is.
JohnOConnell' -> allowed. should be as is.
JohnOConnell# -> allowed. should be as is.
JohnOConnell- -> allowed. should be as is.
JohnOConnell-# -> should return JohnOConnell-
JohnOConn34ell -> should return JohnOConnell
*JohnOConnell -> should return JohnOConnell
JohnOConnell* -> should return JohnOConnell
JohnOConn$%ell -> should return JohnOConnell
Thanks
If I understand it correctly, you could do it this way:
// Test data
def tests = [ [ input:"JohnO'Connell", output:"JohnO'Connell" ],
[ input:"JohnDias", output:"JohnDias" ],
[ input:"JohnOConnell'", output:"JohnOConnell'" ],
[ input:"JohnOConnell#", output:"JohnOConnell#" ],
[ input:"JohnOConnell-", output:"JohnOConnell-" ],
[ input:"JohnOConnell-#", output:"JohnOConnell-" ],
[ input:"JohnOConn34ell", output:"JohnOConnell" ],
[ input:"*JohnOConnell", output:"JohnOConnell" ],
[ input:"JohnOConnell*", output:"JohnOConnell" ],
[ input:"JohnOConn\$%ell", output:"JohnOConnell" ] ]
String normalize( String input ) {
int idx = 0
input.replaceAll( /[^A-Za-z'#\-]/, '' ) // remove all disallowed chars
.replaceAll( /['#\-]/ ) { match -> // replace 2nd+ instance of special chars
idx++ == 0 ? match : ''
}
}
tests.each {
assert normalize( it.input ) == it.output
}