aws-cdk template porting migration tips

AWS-CDK Migration Tips

When migrating to a new framework there are going to be some working pains. This is just a collection of frustrations that I encountered while adopting aws-cdk. I did some research prior and found the article “Hey CDK, how can I migrate my existing CloudFormation templates?” by Philipp Garbe and the “core module AWS CDK” documentation most helpful in thinking about migrating initially.

Import Immutable Roles

Use the mutable flag when importing existing roles with Role.fromRoleArn() otherwise the precision of the aws-cdk may lead to the dreaded “Maximum policy size of 10240 bytes” error. Eventually aws-cdk issue #4465 will be fixed and we will welcome the precise IAM policies the CDK generates.

The maximum policy size error was most often encountered on CodePipeline deploy roles where we had a large number of independent artifacts deploying CloudFormations.

Explicit to_string() in python

Having to explicitly call the core.Fn.get_att(‘Foo’, ‘Bar’).to_string() operator instead of using a str() for f'{var}’ style tripped me up.

I noticed in my IDE that the signature called for a string (thanks types!) so I tried:

str(core.Fn.get_att('Foo','Bar'))

and

f'{core.Fn.get_att('Foo','Bar')}'

but because only __repr__ is defined in the python interface I got an ugly object name when I expected __str__ to be implemented. I overlooked the to_string(), which is a pretty common method for many object oriented languages, as I expected the class to behave more pythonically.

Beware of Copy Paste / Naming

Name a stack the same as another? You get a diff but if you aren’t paying attention you’ll blow away a stack before realizing it. Also you end up with the old stack as well not updated because of this config SNAFU.

Import Pains

CfnImport is great for importing old CloudFormations but the stack is immutable upon import. Any changes to the stack must happen prior to making the call. We leaned on PyYAML but then had to undo a few of the niceties of only processing the template with AWS based systems.

Intrinsic Function Shortcuts

For example all bang, “!” ie “!Ref” or “!Sub”, references need to be updated to be the full function command, ie “Ref:” and “Fn::Sub:”.

Attributeerror: ‘datetime.date’

IAM Policy Documents specifying the Version unquoted instead of as a string, ie Version: 2012-10-17 instead of Version: ‘2012-10-17’, will have the cdk synth command greet them with following obscure error.

This error also occurs on AWSTemplateFormatVersion blocks so beware.

 AttributeError: 'datetime.date' object has no attribute '__jsii__type__'.

Example CfnImport

Here is an example of using the CfnImport to inject parameters into a traditional template and then load it into the CDK stack.


import yaml
from aws_cdk import core
class RawStack(core.Stack):
def __init__(self, scope: core.Construct, name: str, template_path: str, wrapped_parameters=None,
**kwargs) -> None:
"""import a stack off a path and munge in ssm variables if desired
:param template_path: path to raw stack being imported
:param wrapped_parameters: map of Parameter keys and default values
:param kwargs: all the stack stuff
"""
super().__init__(scope=scope, name=name, **kwargs)
if not wrapped_parameters:
wrapped_parameters = {}
template_path = Path(template_path)
with open(template_path, 'r') as f:
template = yaml.load(f, Loader=yaml.SafeLoader)
if project_name:
for pk, pv in template['Parameters'].items():
if 'Default' in pv:
if pk in wrapped_parameters:
template['Parameters'][pk]['Default'] = wrapped_parameters[pk]
elif pv['Default'] == "":
template['Parameters'][pk]['Type'] = 'AWS::SSM::Parameter::Value<String>'
template['Parameters'][pk]['Default'] = str(pk)
else:
if pk in wrapped_parameters:
template['Parameters'][pk]['Default'] = wrapped_parameters[pk]
else:
template['Parameters'][pk]['Type'] = 'AWS::SSM::Parameter::Value<String>'
template['Parameters'][pk]['Default'] = str(pk)
core.CfnInclude(self, 'RawStack', template=template)

view raw

raw_stack.py

hosted with ❤ by GitHub

raw_stack.py gist link

 

Fixing unhandled instruction bytes error Running Valgrind on AWS CodeBuild

When running Valgrind against one of our C libraries we encountered some discrepancies in the build where locally all would pass but on AWS CodeBuild using the aws/codebuild/standard:2.0 image we would get errors like:

vex amd64->IR: unhandled instruction bytes: 0x62 0xF1 0x7D 0x48 0xEF 0xC0 0xC5 0xF9 0x2E 0x45

The full message was like:

==16128== Memcheck, a memory error detector
==16128== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16128== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==16128== Command: /root/build/meh/test/.libs/state
==16128== 
[==========] Running 2 test(s).
[ RUN      ] test1
vex amd64->IR: unhandled instruction bytes: 0x62 0xF1 0x7D 0x48 0xEF 0xC0 0xC5 0xF9 0x2E 0x45
vex amd64->IR:   REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=NONE
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==16128== valgrind: Unrecognised instruction at address 0x1173bd.
=...
==16128== Your program just tried to execute an instruction that Valgrind
==16128== did not recognise.  There are two possible reasons for this.
==16128== 1. Your program has a bug and erroneously jumped to a non-code
==16128==    location.  If you are running Memcheck and you just saw a
==16128==    warning about a bad jump, it's probably your program's fault.
==16128== 2. The instruction is legitimate but Valgrind doesn't handle it,
==16128==    i.e. it's Valgrind's fault.  If you think this is the case or
==16128==    you are not sure, please let us know and we'll try to fix it.
==16128== Either way, Valgrind will now raise a SIGILL signal which will
==16128== probably kill your program.

The error seems to indicate that the architecture doesn’t seem to match what the docker image had so going off of a Linux Headers Reinstall article we added the following and then the architecture packages were fine.

apt upgrade --fix-missing -y && apt autoremove -y && apt autoclean -y