def test_rules(self): t = Template() t.add_parameter("One") t.add_parameter("Two") rule = { "Assertions": [ { "Assert": { "Fn::Equals": [ { "Ref": "One" }, { "Ref": "Two" }, ], }, }, ], } t.add_rule("ValidateEqual", rule) self.assertTrue("ValidateEqual" in t.rules) rendered = t.to_dict() self.assertEqual(rendered["Rules"]["ValidateEqual"], rule)
def test_custom_resource_type(self): """ Ensures that a custom resource type is implicitly defined. """ template = Template() template.add_resource(MyCustomResource("foo", Foo="bar", ServiceToken="baz")) generated = TemplateGenerator(json.loads(template.to_json())) # validated that the templates are equal to each other self.assertDictEqual(template.to_dict(), generated.to_dict()) foo = generated.resources["foo"] self.assertFalse(isinstance(foo, MyCustomResource))
def create_template(): t = Template() oauth_token = t.add_parameter( Parameter( "GitHubOAuthToken", Description="Secret for github", Type="AWS::SSM::Parameter::Value<String>", Default="oauth", NoEcho=True, )) owner = t.add_parameter(Parameter( "Owner", Type="String", )) repo = t.add_parameter(Parameter( "Repo", Type="String", )) branch = t.add_parameter(Parameter( "Branch", Type="String", )) artifact_bucket = t.add_resource(Bucket('ArtifactBucket')) cd_role = t.add_resource(code_build_service_role(artifact_bucket)) code_build = t.add_resource( Project( 'CodeBuild', Name=STACK_NAME, Artifacts=Artifacts(Type='NO_ARTIFACTS', ), Environment=Environment( ComputeType='BUILD_GENERAL1_SMALL', Image='aws/codebuild/python:3.6.5', Type='LINUX_CONTAINER', ), ServiceRole=Ref(cd_role), Source=Source( Type='GITHUB', Auth=SourceAuth(Type='OAUTH', ), Location= 'https://github.com/karlw00t/aws-encryption-sdk-cli.git', ), Triggers=ProjectTriggers(Webhook=True, ), )) return t.to_dict()
def test_macro_resource(self): """ Ensures that a custom member can be defined. """ template = Template() template.add_resource(MyMacroResource("foo", Foo="bar")) generated = TemplateGenerator(json.loads(template.to_json()), CustomMembers=[MyMacroResource]) # validated that the templates are equal to each other self.assertDictEqual(template.to_dict(), generated.to_dict()) foo = generated.resources["foo"] self.assertTrue(isinstance(foo, MyMacroResource)) self.assertEqual("bar", foo.Foo)
def test_macro_resource(self): """ Ensures that a custom member can be defined. """ template = Template() template.add_resource(MyMacroResource("foo", Foo="bar")) generated = TemplateGenerator(json.loads(template.to_json()), CustomMembers=[MyMacroResource]) # validated that the templates are equal to each other self.assertDictEqual(template.to_dict(), generated.to_dict()) foo = generated.resources["foo"] self.assertTrue(isinstance(foo, MyMacroResource)) self.assertEquals("bar", foo.Foo)
def build_task_definition(self, container_configurations, ecr_image_uri, fallback_task_role, fallback_task_execution_role, deployment_identifier): t = Template() t.add_resource( self.build_cloudformation_resource( container_configurations, ecr_image_uri=ecr_image_uri, fallback_task_role=fallback_task_role, fallback_task_execution_role=fallback_task_execution_role, deployment_identifier=deployment_identifier)) task_definition = t.to_dict()["Resources"][self._resource_name( self.service_name)]["Properties"] return _cloudformation_to_boto3_payload( task_definition, ignore_keys={'Options', 'DockerLabels'})
def generate_template(): _template = request.get_json() template = Template() template.set_version('2010-09-09') template.set_description(_template['description']) params = _template['parameters'] params = generateParams(params) for param in params: template.add_parameter(param) resources = _template['resources'] for resource in resources: template.add_resource(dispatcher(resource)) return template.to_dict()
def create_template(zip_path): template = Template( Description='CloudFormation custom resource creator, part of cloudseeder', ) role = template.add_resource(Role( 'CloudSeederRole', ManagedPolicyArns=[ # custom resources pretty much need to be able to do anything... 'arn:aws:iam::aws:policy/AdministratorAccess', ], # I'd use awacs but it seems like a bit of a waste AssumeRolePolicyDocument={ 'Version': '2012-10-17', 'Statement': [{ 'Effect': 'Allow', 'Principal': { 'Service': ['lambda.amazonaws.com'], }, 'Action': ['sts:AssumeRole'], }], }, )) function = template.add_resource(FunctionLocalCode( 'CloudSeederLambda', Code=os.path.abspath(zip_path), Handler='cloudseeder.lambda_handler', MemorySize=256, Role=GetAtt(role, 'Arn'), Timeout=300, Runtime='python2.7' if six.PY2 else 'python3.6', )) template.add_output(Output( LAMBDA_ARN_EXPORT, Value=GetAtt(function, 'Arn'), Export=Export(LAMBDA_ARN_EXPORT), )) return json.dumps(template.to_dict(), indent=4, sort_keys=True) + '\n'
class CreateTemplate: def __init__(self): self.template = Template() def add_alarm(self, alarmName): self.template.add_resource(Alarm( alarmName, ComparisonOperator='GreaterThanThreshold', Statistic='Maximum', EvaluationPeriods=1, MetricName='BucketSizeBytes', Namespace='S3', Period='60', Threshold=0 )) def to_yaml(self): return self.template.to_yaml() def to_json(self): return json.dumps(self.to_dict()) def to_dict(self): return self.template.to_dict()
class CloudFront(object): config_path = 'app.yml' def __init__(self, config=None, config_path=None): self.load_config(config,config_path) self.cf_config = self.config.get('cloudfront', None) if self.cf_config: self.distribution_name = self.cf_config.keys()[0] self.t = Template() self.create_distribution() def load_config(self,config,config_path=None): if config: self.config = config return config_filename = config_path or self.config_path try: with open(config_filename, 'r') as f: self.config = yaml.safe_load(f) except IOError: self.config = dict() def create_distribution(self): origins, behaviours = self._construct_origins() self.t.add_resource(Distribution( self.distribution_name, DistributionConfig=DistributionConfig( Origins=origins, CacheBehaviors=behaviours, DefaultCacheBehavior=DefaultCacheBehavior( AllowedMethods=['GET', 'HEAD'], CachedMethods=['GET', 'HEAD'], ForwardedValues=ForwardedValues( QueryString=True, Headers=[], Cookies=Cookies(Forward='none') ), TargetOriginId=origins[0].Id, ViewerProtocolPolicy='https-only' ), Enabled = True ) )) def _construct_origins(self): origins = [] behaviors = [] origin_ids = self.cf_config[self.distribution_name].keys() for origin_id in origin_ids: kwargs = self.cf_config[self.distribution_name][origin_id].copy() CloudFront.capitalize_keys(kwargs) CloudFront._prepare_origins(kwargs) CloudFront._prepare_behaviors(kwargs) kwargs['Origin']['Id'] = origin_id origins.append(Origin(**kwargs['Origin'])) kwargs['Behaviors']['TargetOriginId'] = origin_id behaviors.append(CacheBehavior(**kwargs['Behaviors'])) return origins, behaviors @staticmethod def capitalize(string): return ''.join([x.capitalize() for x in string.split('_')]) @staticmethod def capitalize_keys(dictionary): if isinstance(dictionary, dict): for key in dictionary.keys(): capitalized_key = CloudFront.capitalize(key) value = dictionary.pop(key) dictionary[capitalized_key] = value if isinstance(value, dict): CloudFront.capitalize_keys(dictionary[capitalized_key]) @staticmethod def _prepare_behaviors(dictionary): behaviors = dictionary['Behaviors'] key = 'ForwardedValues' if key in behaviors: if 'Cookies' in behaviors[key]: behaviors[key]['Cookies'] = \ getattr(sys.modules[__name__], 'Cookies')(**behaviors[key]['Cookies']) behaviors[key] = getattr(sys.modules[__name__], key)(**behaviors[key]) @staticmethod def _prepare_origins(dictionary): class_name_replace = {'S3OriginConfig': 'S3Origin', 'CustomOriginConfig': 'CustomOrigin'} custom_origin_replace = {'HttpPort': 'HTTPPort', 'HttpsPort': 'HTTPSPort'} origin = dictionary['Origin'] # for these keys a value should be a corresponding class instance for key in ['CustomOriginConfig', 'S3OriginConfig','OriginCustomHeaders']: if key in origin: # need to rename HttpPort-> HTTPPort, HttpsPort-> HTTPSPort if key is 'CustomOriginConfig': for custom_origin_key in origin[key].keys(): origin[key][custom_origin_replace.get( custom_origin_key, custom_origin_key)] =\ origin[key].pop(custom_origin_key) origin[key] = getattr(sys.modules[__name__], class_name_replace.get(key, key))(**origin[key]) def to_json(self): return self.t.to_json() def to_dict(self): return self.t.to_dict()
class Stack(cfn.Stack): """Cloudformation stack using troposphere resources.""" def __init__( self, stack_name: str, description: Optional[str] = None, cfn_role_arn: Optional[str] = None, deploy_session: Optional[Session] = None, dry_run: Optional[bool] = False, s3_bucket: Optional[str] = None, s3_key: Optional[str] = None, ) -> None: """Initialize Stack attributes. :param stack_name: stack name :param cfn_role_arn: role asssumed by cloud formation to create the stack :param deploy_session: AWS session to deploy non CloudFormation AWS resources (aka Assets) :param dry_run: True if the stack is not to be deployed. :param description: a description of the stack :param s3_bucket: s3 bucket used to store data needed by the stack :param s3_key: s3 prefix in s3_bucket in which data is stored """ super().__init__( stack_name, cfn_role_arn=cfn_role_arn, description=description, s3_bucket=s3_bucket, s3_key=s3_key, ) self.constructs: list[Construct | AWSObject] = [] self.deploy_session = deploy_session self.dry_run = dry_run self.template = Template() def add(self, element: Union[AWSObject, Construct, Stack]) -> Stack: """Add a Construct or AWSObject to the stack. :param element: if a resource an AWSObject or Construct add the resource to the stack. If a stack merge its resources into the current stack. """ if isinstance(element, Stack): constructs = element.constructs else: constructs = [element] # Add the new constructs (non expanded) self.constructs += constructs # Update the template resources = [] for construct in constructs: if isinstance(construct, Construct): resources += construct.resources(stack=self) if isinstance(construct, AWSObject): resources.append(construct) self.template.add_resource(resources) return self def add_condition(self, condition_name: str, condition: ConditionFunction) -> None: """Add condition to stack template. :param condition_name: name of the condition to add :param condition: condition to add """ self.template.add_condition(condition_name, condition) def cfn_policy_document(self) -> PolicyDocument: """Return stack necessary policy document for CloudFormation.""" result = PolicyDocument([]) for construct in self.constructs: if isinstance(construct, Construct): result += construct.cfn_policy_document(stack=self) return result def __getitem__(self, resource_name: str) -> AWSObject: """Return AWSObject associated with resource_name. :param resource_name: name of the resource to retrieve """ return self.template.resources[name_to_id(resource_name)] def export(self) -> dict: """Export stack as dict. :return: a dict that can be serialized as YAML to produce a template """ result = self.template.to_dict() if self.description is not None: result["Description"] = self.description return result def create_data_dir(self, root_dir: str) -> None: """Populate root_dir with data needed by all constructs in the stack. :param root_dir: the local directory in which to store the data """ for construct in self.constructs: if isinstance(construct, Construct): construct.create_data_dir(root_dir)