Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am working on a python script to call a variable from a file from another file.It is an IAM policy for an IAM user. I have a function calling variables in another file file with the function is named "template_utils.py". I want the output in JSON format. I am not sure what is the problem.

import sys
import json
import time 
import meta_templates
from jinja2 import Template
def create_aws_iam_policy_template(**kwargs):
  template_data = {}
  template_data["region"] = kwargs.get('region')
  template_data["instance_types"] = kwargs.get('instance_type')
  template_data["ebs_volume_size"] = kwargs.get('ebs_volume_size')
  template_data["meta_template_name"] = kwargs.get('meta_template_name')

  meta_template_dict = getattr(meta_templates, template_data["meta_template_name"])
  meta_template_json = json.dumps(meta_template_dict)
  template_json = meta_template_json.format(template_data)
  return template_json  

template_json = create_aws_iam_policy_template(
  region="us-east2",
  instance_type="t2.micro",
  ebs_volume_size=20,
  meta_template_name="ec2_policy_meta_template"
)

print(template_json)

This is the file with policy called "meta_template.py"

import json
from jinja2 import Template
ec2_policy_meta_template = { 
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": "ec2:RunInstances",
                "Resource": [
                    "arn:aws:ec2:{{region}}::instance/*",
                    "arn:aws:ec2:{{region}}::network-interface/*",
                    "arn:aws:ec2:{{region}}::key-pair/*",
                    "arn:aws:ec2:{{region}}::security-group/*",
                    "arn:aws:ec2:{{region}}::subnet/*",
                    "arn:aws:ec2:{{region}}::volume/*",
                    "arn:aws:ec2:{{region}}::image/ami-*"
                ],
                "Condition": {
                    "ForAllValues:NumericLessThanEquals": {
                        "ec2:VolumeSize": "{{ebs_volume_size}}"
                    },
                    "ForAllValues:StringEquals": {
                        "ec2:InstanceType": "{{instance_type}}"
                    }
                }
            },
            {
                "Sid": "VisualEditor1",
                "Effect": "Allow",
                "Action": [
                    "ec2:TerminateInstances",
                    "ec2:StartInstances",
                    "ec2:StopInstances"
                ],
                "Resource": "arn:aws:ec2:{{region}}::instance/*",
                "Condition": {
                    "ForAllValues:StringEquals": {
                        "ec2:InstanceType": "{{instance_type}}"
                    }
                }
            },
            {
                "Sid": "VisualEditor2",
                "Effect": "Allow",
                "Action": [
                    "ec2:Describe*",
                    "ec2:GetConsole*",
                    "cloudwatch:DescribeAlarms",
                    "iam:ListInstanceProfiles",
                    "cloudwatch:GetMetricStatistics",
                    "ec2:DescribeKeyPairs",
                    "ec2:CreateKeyPair"
                ],
                "Resource": "*",
                "Condition": {
                    "DateGreaterThan": {
                        "aws:CurrentTime": "{{start_time}}"
                    },
                    "DateLessThanEquals": {
                        "aws:CurrentTime": "{{end_time}}"
                    }
                }
            }
        ]
    }
tm = Template(json.dumps(ec2_policy_meta_template))
parsed_policy = tm.render(region='us-east-1', ebs_volume_size='12', instance_type='t2.micro')
print(parsed_policy)

This is the error I am getting when running "template_utils.py"

{"Version": "2012-10-17", "Statement": [{"Sid": "VisualEditor0", "Effect": "Allow", "Action": "ec2:RunInstances", "Resource": ["arn:aws:ec2:us-east-1::instance/*", "arn:aws:ec2:us-east-1::network-interface/*", "arn:aws:ec2:us-east-1::key-pair/*", "arn:aws:ec2:us-east-1::security-group/*", "arn:aws:ec2:us-east-1::subnet/*", "arn:aws:ec2:us-east-1::volume/*", "arn:aws:ec2:us-east-1::image/ami-*"], "Condition": {"ForAllValues:NumericLessThanEquals": {"ec2:VolumeSize": "12"}, "ForAllValues:StringEquals": {"ec2:InstanceType": "t2.micro"}}}, {"Sid": "VisualEditor1", "Effect": "Allow", "Action": ["ec2:TerminateInstances", "ec2:StartInstances", "ec2:StopInstances"], "Resource": "arn:aws:ec2:us-east-1::instance/*", "Condition": {"ForAllValues:StringEquals": {"ec2:InstanceType": "t2.micro"}}}, {"Sid": "VisualEditor2", "Effect": "Allow", "Action": ["ec2:Describe*", "ec2:GetConsole*", "cloudwatch:DescribeAlarms", "iam:ListInstanceProfiles", "cloudwatch:GetMetricStatistics", "ec2:DescribeKeyPairs", "ec2:CreateKeyPair"], "Resource": "*", "Condition": {"DateGreaterThan": {"aws:CurrentTime": ""}, "DateLessThanEquals": {"aws:CurrentTime": ""}}}]}
Traceback (most recent call last):
  File "/home/pranay/Desktop/work/template_utils.py", line 18, in <module>
    template_json = create_aws_iam_policy_template(
  File "/home/pranay/Desktop/work/template_utils.py", line 15, in create_aws_iam_policy_template
    template_json = meta_template_json.format(template_data)
KeyError: '"Version"'

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
216 views
Welcome To Ask or Share your Answers For Others

1 Answer

I think all your problem is you mix two differen methods to fill templates - text.format() and jinja2

text.format() uses

  • {variable} to put value in template
  • {{ }} to keep it as normal { }

jinja2 uses

  • {{variable}} to put value in template
  • { } to keep it as normal { }

And you have {{region}} to put value so you exepect jinj2 method but you use format() which uses other method and it sees {"VERSION"... in your template and it tries to replace it.

You have to use jinja2 - it will be simpler then changing template for format()


string formatting

'{"VERSION": "{{region}}" }'.format(region="us-east2")

result:

KeyError: '"VERSION"'

jinja2

from jinja2 import Template

t = Template('{"VERSION": "{{region}}" }')
t.render(region="us-east2")

result:

'{"VERSION": "us-east2" }'

EDIT:

It seems you still don't understand it.

jinja2 is not function of string but external module which you have to install

 pip install Jinja2

and import and use it in special way.

For your example it can be something like this

from jinja2 import Template

template_json = Template(meta_template_json).render(template_data)

It uses placeholders with double {{ and }} - like in your template {{region}}. And it doesn't try to replace value when you have single { } like in '{"VERSION": ...}. So it will works with your template in correct way.

But original format() works in different way - it uses placeholders with single { and } - so it thing that you have placeholder '{"VERSION": ...} and it can't find variable "VERSION" in template_data to replace it. And it makes problem.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...