How to create a python variable from a json format - json

I want to create a global variable from json data. I'm sending the json data with websockets from a server to a client and I want that when the client receives json data, it creates a global variables for further use.
My json data is:
set_variable_data = [{
'component' : {
'name' : input("Component name: "),
'evse' : {
'id' : int(input("Number of Evses: ")),
'connector_id' : int(input("Number of connectors: "))
}
},
'variable' : {
'name' : input("Variable name: ")
}
}]
And I've tried to implement this code into the client program:
global set_variable_data[0]['variable']['name'] = set_variable_data[0]['component']['evse']['connector_id']
There's no problem with the send/receive procedures, all the messages are sent and received between the client and the server. I just want to know if we can create a global variable from this.
Thanks in advance

You can use the global keyword to modify a global variable from inside the function thar receives the data:
variable_data = {}
def receive_data(interface):
global variable_data
variable_data = interface.recv_json()
The global keyword allows to reference the variable variable_data when is assigned a value to it, in other case you will be making the assignation to a variable only inside the context of the function.

Related

Create Terraform resources out of JSON values

I am looking for a way to generate Terraform code based on JSON values.
Imagine I have a JSON file with the following structure:
{
"settings": [
{
"conf": [
{
"setting": "DeploymentPolicy",
"namespace": "aws:elasticbeanstalk:command",
"value": "AllAtOnce"
},
{
"setting": "BatchSize",
"namespace": "aws:elasticbeanstalk:command",
"value": "30"
},
{
"setting": "BatchSizeType",
"namespace": "aws:elasticbeanstalk:command",
"value": "Percentage"
}
]
}
]
}
What I want to do is the following:
Creating a working Terraform resource based on the JSON file values, e.g. a beanstalk environment like this:
resource "aws_elastic_beanstalk_environment" "app_prod" {
name = "${aws_elastic_beanstalk_application_version.app.name}-prod"
application = aws_elastic_beanstalk_application.app.name
solution_stack_name = data.aws_elastic_beanstalk_solution_stack.latest_linux_java.name
wait_for_ready_timeout = "10m"
version_label = aws_elastic_beanstalk_application_version.app.name
# Elastic beanstalk configuration
setting {
name = "DeploymentPolicy"
namespace = "aws:elasticbeanstalk:command"
value = "AllAtOnce"
}
setting {
name = "BatchSize"
namespace = "aws:elasticbeanstalk:command"
value = "30"
}
...
}
Therefore I have to create the settings block in HCL (Terraform configuration) based on the JSON values.
This means the JSON file above should result in:
setting {
name = "DeploymentPolicy"
namespace = "aws:elasticbeanstalk:command"
value = "AllAtOnce"
}
setting {
name = "BatchSize"
namespace = "aws:elasticbeanstalk:command"
value = "30"
}
setting {
name = "BatchSizeType"
namespace = "aws:elasticbeanstalk:command"
value = "Percentage"
}
As you can see, the structure of JSON and HCL is very similar, but not identical. See e.g. settings, conf, or setting instead of name in the JSON.
A possible approach would be to read the JSON values and store them in an array or a map. But I have no idea how I could generate valid HCL and inject it in the desired part of the resource. Furthermore I tried to use a template but Terraform does not support the looping functionality that I need to iterate over the settings.
To sum up:
Input is a JSON file that must be read
JSON contains settings (besides other information)
The number of settings can differ
Somehow I have to generate a settings block
Somehow I have to inject this settings blok in the resource
Does anyone have an idea how to do that? Any other approaches?
Thanks a lot!
Assuming that your JSON object were in a file called settings.json inside your module directory, you could do something like this:
locals {
environment_settings = jsondecode(file("${path.module}/settings.json")).settings[0].conf[0]
}
resource "aws_elastic_beanstalk_environment" "app_prod" {
name = "${aws_elastic_beanstalk_application_version.app.name}-prod"
application = aws_elastic_beanstalk_application.app.name
solution_stack_name = data.aws_elastic_beanstalk_solution_stack.latest_linux_java.name
wait_for_ready_timeout = "10m"
version_label = aws_elastic_beanstalk_application_version.app.name
dynamic "setting" {
for_each = local.environment_settings
content {
namespace = setting.value.namespace
name = setting.value.setting
value = setting.value.value
}
}
}
This special dynamic block is a sort of macro to create repeated setting blocks, each one correlating with one element of the collection given in for_each.
You can do whatever transformations of the input you need using Terraform's expression language in the locals block to ensure that the local.environment_settings value contains one element for each setting block you will generate, and then in the content nested block tell Terraform how to populate the setting arguments based on those element values.

How to add array values in Claims of IdToken in Cognito using claimsToAddOrOverride

I am using Pre Token Generation to update the claims of IdToken.
I am successfully able to update claim using single key:value pair.
Below is the sample example of that.
event["response"] = {"claimsOverrideDetails":{"claimsToAddOrOverride":{"scope": "test.debug"}}}
But when i am trying to add array of string inside that, it giving me internal server error (Response from AWS Cognito)
Ex:
event["response"] = {"claimsOverrideDetails":{"claimsToAddOrOverride":{"scope": ["test1","test2]}}}
It is working fine using 'Test' option of lambda function.
If i am using groupsToOverride then it is overriding the cognito:groups claim.
Any help?
I think this must be a bug with Cognito and unfortunately will require a workaround until it's resolved.
It's not ideal I know, but I've worked around this issue by using a delimited string which I then parse to an array when I receive the token.
Lambda:
exports.handler = (event, context, callback) => {
event.response = {
"claimsOverrideDetails": {
"claimsToAddOrOverride": {
"scope": "test1|test2"
}
}
};
// Return to Amazon Cognito
callback(null, event);
};
Client:
const token = jwt.decode(id_token);
const scopes = token.scope.split('|');
The name scope have special meaning in a JWT, libraries expect this to be a list in string form separated by space. So the scopes test1 and test2 would become "test1 test2".
I would recommend using space as separator and not any other format. If you prefer another format just give your field a different name - like group.
{
"iss": "https://authorization-server.example.com/",
"sub": " 5ba552d67",
"aud": "https://rs.example.com/",
"exp": 1544645174,
"client_id": "s6BhdRkqt3_",
"scope": "openid profile reademail"
}

HTML indexing into JSON variable for NgModel

In all the component classes of each of page of my Angular 2 form, I'm calling an API for retrieval of saved input values to be stored in a global variable in JSON format inside of a global service, if this global variable has not been filled in yet.
After retrieval and initializing the global variable with the JSON data from the API, I'd like to establish 2-way data binding using NgModel on each of my HTML pages with the corresponding values inside this global variable. However, I'm having trouble indexing properly into this global variable containing my JSON data. I'd like to bind my input value directly to the global variable, because upon saving of the form, I can simply call one service that would send this one global variable in the body of a POST call.
JSON Data stored in globalVariable:
How do I retrieve "value a", "value b", "value c" in the HTML?
{
"data": [
{
"field 1" : "value 1",
"page1" : {
"field a" : "value a"
"field b" : "value b"
},
"page2" : {
"field c" : "value c"
}
}
]
}
page1.component.ts:
constructor(..., public globalService: GlobalService:, #Inject(GlobalVariable) private globalVariable: any, ...) {}
ngOnInit() {
if (Object.keys(this.globalService.globalVariable).length < 1) {
this.globalService.getAPI().subscribe(
data => this.globalService.globalVariable = data['data'],
err => console.error(err),
() => {
console.log(this.globalService.globalVariable[0]['page1']['field a']); //Prints 'value a' correctly!
//In HTML:NgModel: I can't index globalVariable[0]['page1']['field a']
//this._privateVariable = this.globalService.globalVariable;
//In HTML:NgModel: I can't index _privateVariable[0]['page1']['field a']
//this._privateVariable = this.saveInformation.information[0]['page1'];
//In HTML:NgModel: I can index _privateVariable['field a'] for ['value a'], but //I don't want to manage many _privateVariables, each storing each page's input
//values to be sent in POST request in save.
}
)
}
}
page1.component.html:
...
<div>
<input type="text" [(ngModel)]="globalVariable[0]['page1']['field a']">
</div>
...
The above line outputs the following error to console:
angular2.dev.js:25644 ORIGINAL EXCEPTION: TypeError: Cannot read property '0' of undefined
There are mistake in your code while fetching data and using in the view (HTML). you have to use code like this :-
<input type="text" [(ngModel)]="globalVariable.data[0].page1['field a']">
also
PS: There is space between your name of key i.e field a so to access the value of JSON object key having space you have to use bracket notation of javascript.
see here working demo of your use case
Working Example
see also
https://medium.com/#prufrock123/js-dot-notation-vs-bracket-notation-797c4e34f01d#.ytvne8m86

Getting an Environment Variable in Terraform configuration?

I have two environment variables. One is TF_VAR_UN and another is TF_VAR_PW. Then I have a terraform file that looks like this.
resource "google_container_cluster" "primary" {
name = "marcellus-wallace"
zone = "us-central1-a"
initial_node_count = 3
master_auth {
username = ${env.TF_VAR_UN}
password = ${env.TF_VAR_PW}
}
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
}
}
The two values I'd like to replace with the environment variables TF_VAR_UN and TF_VAR_PW are the values username and password. I tried what is shown above, with no success, and I've toyed around with a few other things but always get syntax issues.
I would try something more like this, which seems closer to the documentation.
variable "UN" {
type = string
}
variable "PW" {
type = string
}
resource "google_container_cluster" "primary" {
name = "marcellus-wallace"
zone = "us-central1-a"
initial_node_count = 3
master_auth {
username = var.UN
password = var.PW
}
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
}
}
With the CLI command being the below.
TF_VAR_UN=foo TF_VAR_PW=bar terraform apply
The use of interpolation syntax throws warning with terraform v0.12.18. Now you don't need to use the interpolation syntax. You can just reference it as var.hello.
Caution :
One important thing to understand from a language standpoint is that, you cannot declare variables using environment variables. You can only assign values for declared variables in the script using environment varibles. For example, let's say you have the following .tf script
variable "hello" {
type=string
}
Now if the environment has a variable TF_VAR_hello="foobar", during runtime the variable hello will have the value "foobar". If you assign the variable without the declaration of the variable there will not be any effect.
You can do the following to get this working.
Declare the variable in terraform configuration that you want to use as environment Variable.
variable "db_password" { type= string }
In the resource section where you want to use this variable change it as
"db_password":"${var.db_password}"
Export the environment variable.
export TF_VAR_db_password="##password##"
terraform plan or terraform apply
Use a null_resource to execute a terminal command (read an environment variable), redirect output to a file, then read the file content:
resource "null_resource" "read_environment_var_value_via_cli" {
triggers = { always_run = "${timestamp()}" }
provisioner "local-exec" {
command = "echo $TF_VAR_UN > TF_VAR_UN.txt" # add gitignore
}
}
data "local_file" "temp_file" {
depends_on = [ null_resource.read_environment_var_value_via_cli]
filename = "${path.module}/TF_VAR_UN.txt"
}
# use value as desired
resource "google_container_cluster" "primary" {
master_auth {
username = data.local_file.temp_file.content # value of $TF_VAR_UN
..
}
}
Most of the providers use:
DefaultFunc: schema.EnvDefaultFunc("
https://github.com/terraform-providers/terraform-provider-infoblox/blob/master/infoblox/provider.go
https://github.com/terraform-providers/terraform-provider-openstack/blob/master/openstack/provider.go
...
Alternatively, you can replace the variables in the file itself using the envsubst utility in bash:
$ envsubst < main.tf > main.tf
Or using an intermediate file with variables and the final config on the output:
$ envsubst < main.txt > main.tf
! Variables for envsubst must be declared using export:
$ export MYVAR=1729
The variables in the source file must be of the form: $VARIABLE or ${VARIABLE}.
in order to use a variable it needs to be wrapped with ""
for example:
username = "${var.UN}"

creating multiple nodes with properties in json in neo4j

I am a newbie in Neo4j and facing a small problem.
I created around 5000 router nodes with its ipaddress property set to specific ip.
Now I have around 5000 more interfaces and needs to create their nodes. I am using json and rest api for that in c++.
Every interface has a Routerip property and if the routerip matches the ipaddress of the router node that is already created I need to create that interface.
I have used this
http://docs.neo4j.org/chunked/snapshot/rest-api-cypher.html#rest-api-create-mutiple-nodes-with-properties link to create my routers.
Now I want to use the same method in order to create my interfaces.
Is there a way wherein I can do so passing array of properties as paramaters in the cypher query and check for the router present to create my interface?
There are several ways to do this. Breaking it down into steps:
For each interface, find the matching router
Create the interface & connect the interface to that router
That would look something like
MATCH (router:Router)
WHERE router.ipaddress = props.RouterIp
CREATE (n:Interface { props } )-[:CONNECTED_TO]->(router)
Hey When I try to run this simple query as above it gives me java exception
{
"params" : {
"props" : [
{
"LocalAsNumber" : 0,
"NodeDescription" : "10TiMOS-B-4.0.R2 ",
"NodeId" : "10.227.28.95",
"NodeName" : "BLR_WAO_SARF7"
}
]
},
"query" : "MATCH (n:Router) where n.NodeId = {props}.NodeId RETURN n"}
"message" : "The statement has been closed.",
"exception" : "BadInputException",
"fullname" : "org.neo4j.server.rest.repr.BadInputException",
"stacktrace" : [ "org.neo4j.server.rest.repr.RepresentationExceptionHandlingIterable.exceptionOnHasNext(RepresentationExceptionHandlingIterable.java:50)", "org.neo4j.helpers.collection.ExceptionHandlingIterable$1.hasNext(ExceptionHandlingIterable.java:46)", "org.neo4j.helpers.collection.IteratorWrapper.hasNext(IteratorWrapper.java:42)", "org.neo4j.server.rest.repr.ListRepresentation.serialize(ListRepresentation.java:71)", "org.neo4j.server.rest.repr.Serializer.serialize(Serializer.java:75)", "org.neo4j.server.rest.repr.MappingSerializer.putList(MappingSerializer.java:61)", "org.neo4j.server.rest.repr.CypherResultRepresentation.serialize(CypherResultRepresentation.java:83)", "org.neo4j.server.rest.repr.MappingRepresentation.serialize(MappingRepresentation.java:41)", "org.neo4j.server.rest.repr.OutputFormat.assemble(OutputFormat.java:215)", "org.neo4j.server.rest.repr.OutputFormat.formatRepresentation(OutputFormat.java:147)", "org.neo4j.server.rest.repr.OutputFormat.response(OutputFormat.java:130)", "org.neo4j.server.rest.repr.OutputFormat.ok(OutputFormat.java:67)", "org.neo4j.server.rest.web.CypherService.cypher(CypherService.java:101)", "java.lang.reflect.Method.invoke(Method.java:606)", "org.neo4j.server.rest.transactional.TransactionalRequestDispatcher.dispatch(TransactionalRequestDispatcher.java:132)", "org.neo4j.server.rest.security.SecurityFilter.doFilter(SecurityFilter.java:112)", "java.lang.Thread.run(Thread.java:744)" ],