Skip to content

Commit

Permalink
Release: v2.5.1
Browse files Browse the repository at this point in the history
  • Loading branch information
AWS authored and AWS committed Oct 19, 2022
1 parent 78b8662 commit 8d79ba3
Show file tree
Hide file tree
Showing 60 changed files with 2,768 additions and 2,216 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2.5.0
v2.5.1
34 changes: 17 additions & 17 deletions customizations-for-aws-control-tower.template

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion deployment/build-s3-dist.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,26 @@ zip -Xr "$build_dist_dir"/custom-control-tower-configuration.zip ./*

# build regional config zip file
echo -e "\n*** Build regional config zip file"
declare -a region_list=( "ap-northeast-2" "ap-southeast-2" "ca-central-1" "eu-west-1" "eu-west-2" "me-south-1" "us-east-1" "us-west-1" "ap-east-1" "ap-south-1" "eu-central-1" "eu-north-1" "eu-west-3" "sa-east-1" "us-east-2" "us-west-2" "ap-northeast-1" "ap-southeast-1" )
# Support all regions in https://docs.aws.amazon.com/controltower/latest/userguide/region-how.html + GovCloud regions
declare -a region_list=(
"us-east-1"
"us-east-2"
"us-west-2"
"ca-central-1"
"ap-southeast-2"
"ap-southeast-1"
"eu-central-1"
"eu-west-1"
"eu-west-2"
"eu-north-1"
"ap-south-1"
"ap-northeast-2"
"ap-northeast-1"
"eu-west-3"
"sa-east-1"
"us-gov-west-1"
"us-gov-east-1"
)
for region in "${region_list[@]}"
do
echo -e "\n Building config zip for $region region"
Expand Down
15 changes: 11 additions & 4 deletions deployment/lambda_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
# !/usr/bin/env python3
import glob
import os
import sys
import shutil
import subprocess
import sys
from pathlib import Path

LIB_PATH = "source/src"
Expand All @@ -32,7 +32,7 @@
"deployment_lambda": "custom-control-tower-config-deployer",
"build_scripts": "custom-control-tower-scripts",
"lifecycle_event_handler": "custom-control-tower-lifecycle-event-handler",
"state_machine_trigger": "custom-control-tower-state-machine-trigger"
"state_machine_trigger": "custom-control-tower-state-machine-trigger",
}


Expand Down Expand Up @@ -92,7 +92,12 @@ def main(argv):
else:
os.makedirs(S3_OUTPUT_PATH, exist_ok=True)
print(" Installing dependencies...")
install_dependencies(dist_folder=DIST_PATH, lib_path=LIB_PATH, handlers_path=HANDLERS_PATH, codebuild_script_path=CODEBUILD_SCRIPTS_PATH)
install_dependencies(
dist_folder=DIST_PATH,
lib_path=LIB_PATH,
handlers_path=HANDLERS_PATH,
codebuild_script_path=CODEBUILD_SCRIPTS_PATH,
)

for arg in argv:
if arg in LAMBDA_BUILD_MAPPING:
Expand All @@ -112,7 +117,9 @@ def main(argv):

print(f" Creating archive for {zip_file_name}..")
create_lambda_archive(
zip_file_name=zip_file_name, source=DIST_PATH, output_path=S3_OUTPUT_PATH
zip_file_name=zip_file_name,
source=DIST_PATH,
output_path=S3_OUTPUT_PATH,
)


Expand Down
72 changes: 39 additions & 33 deletions source/codebuild_scripts/find_replace.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@

# !/bin/python

import os
import inspect
import yaml
import sys
import json
from jinja2 import Environment, FileSystemLoader
from cfct.utils.logger import Logger
import os
import sys

import yaml
from cfct.utils.logger import Logger
from jinja2 import Environment, FileSystemLoader

# initialise logger
log_level = 'info'
log_level = "info"
logger = Logger(loglevel=log_level)


Expand All @@ -37,18 +37,17 @@ def find_replace(function_path, file_name, destination_file, parameters):
j2template = j2env.get_template(file_name)
dictionary = {}
for key, value in parameters.items():
if 'json' in file_name and not isinstance(value, list):
value = "\"%s\"" % value
elif 'json' in file_name and isinstance(value, list):
if "json" in file_name and not isinstance(value, list):
value = '"%s"' % value
elif "json" in file_name and isinstance(value, list):
value = json.dumps(value)
dictionary.update({key: value})
logger.debug(dictionary)
output = j2template.render(dictionary)
with open(destination_file, "w") as fh:
fh.write(output)
except Exception as e:
logger.log_general_exception(
__file__.split('/')[-1], inspect.stack()[0][3], e)
logger.log_general_exception(__file__.split("/")[-1], inspect.stack()[0][3], e)
raise


Expand All @@ -57,40 +56,46 @@ def update_add_on_manifest(event, path):
exclude_j2_files = []

# Find and replace the variable in Manifest file
for item in event.get('input_parameters'):
f = item.get('file_name')
for item in event.get("input_parameters"):
f = item.get("file_name")
exclude_j2_files.append(f)
filename, file_extension = os.path.splitext(f)
destination_file_path = extract_path + "/" + filename \
if file_extension == '.j2' else extract_path + "/" + f
find_replace(extract_path, f, destination_file_path,
item.get('parameters'))
destination_file_path = (
extract_path + "/" + filename
if file_extension == ".j2"
else extract_path + "/" + f
)
find_replace(extract_path, f, destination_file_path, item.get("parameters"))


def sanitize_boolean_type(s, bools):
s = ' ' + s
s = " " + s
logger.info("Adding quotes around the boolean values: {}".format(bools))
logger.info("Print original string: {}".format(s))
for w in [x.strip() for x in bools.split(',')]:
s = s.replace(':' + ' ' + w, ': "' + w + '"')
logger.info("If found, wrapped '{}' with double quotes, printing"
" the modified string: {}".format(w, s))
for w in [x.strip() for x in bools.split(",")]:
s = s.replace(":" + " " + w, ': "' + w + '"')
logger.info(
"If found, wrapped '{}' with double quotes, printing"
" the modified string: {}".format(w, s)
)
return yaml.safe_load(s[1:])


def sanitize_null_type(d, none_type_values):
s = json.dumps(d)
s = ' ' + s
s = " " + s
logger.info("Replacing none_type/null with empty quotes.")
for w in [x.strip() for x in none_type_values.split(',')]:
s = s.replace(':' + ' ' + w, ': ""')
logger.info("If found, replacing '{}' with double quotes, printing"
" the modified string: {}".format(w, s))
for w in [x.strip() for x in none_type_values.split(",")]:
s = s.replace(":" + " " + w, ': ""')
logger.info(
"If found, replacing '{}' with double quotes, printing"
" the modified string: {}".format(w, s)
)
return yaml.safe_load(s[1:])


def generate_event(user_input_file, path, bools, none_types):
logger.info('Generating Event')
logger.info("Generating Event")
with open(user_input_file) as f:
user_input = sanitize_boolean_type(f.read(), bools)
logger.info("Boolean values wrapped with quotes (if applicable)")
Expand All @@ -101,16 +106,17 @@ def generate_event(user_input_file, path, bools, none_types):
update_add_on_manifest(user_input, path)


if __name__ == '__main__':
if __name__ == "__main__":
if len(sys.argv) > 4:
path = sys.argv[2]
file_name = sys.argv[1]
none_type_values = sys.argv[4]
boolean_type_values = sys.argv[3]
generate_event(file_name, path, boolean_type_values, none_type_values)
else:
print('Not enough arguments provided. Please provide the path and'
' user input file names.')
print('Example: merge_manifest.py <PATH-OF-FILES>'
' <USER-INPUT-FILE-NAME>')
print(
"Not enough arguments provided. Please provide the path and"
" user input file names."
)
print("Example: merge_manifest.py <PATH-OF-FILES>" " <USER-INPUT-FILE-NAME>")
sys.exit(2)
85 changes: 47 additions & 38 deletions source/codebuild_scripts/merge_baseline_template_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@
###############################################################################

import json
import sys
import os
import subprocess
import sys

from cfct.utils.logger import Logger


def _read_file(file):
if os.path.isfile(file):
logger.info('File - {} exists'.format(file))
logger.info("File - {} exists".format(file))
logger.info("Reading from {}".format(file))
with open(file) as f:
return json.load(f)
Expand All @@ -31,7 +32,7 @@ def _read_file(file):
sys.exit(1)


def _write_file(data, file, mode='w'):
def _write_file(data, file, mode="w"):
logger.info("Writing to {}".format(file))
with open(file, mode) as outfile:
json.dump(data, outfile, indent=2)
Expand All @@ -46,44 +47,42 @@ def _flip_to_json(yaml_file):


def _flip_to_yaml(json_file):
yaml_file = json_file[:-len(updated_flag)]
yaml_file = json_file[: -len(updated_flag)]
logger.info("Flipping JSON > {} to YAML > {}".format(json_file, yaml_file))
# final stage - convert json avm template to yaml format
subprocess.run(["cfn-flip", "-y", json_file, yaml_file])


def file_matcher(master_data, add_on_data, master_key='master',
add_on_key='add_on'):
def file_matcher(master_data, add_on_data, master_key="master", add_on_key="add_on"):
for item in master_data.get(master_key):
logger.info("Iterating Master AVM File List")
for key, value in item.items():
logger.info('{}: {}'.format(key, value))
master_file_name = value.split('/')[-1]
logger.info("master_value: {}".format(value.split('/')[-1]))
logger.info("{}: {}".format(key, value))
master_file_name = value.split("/")[-1]
logger.info("master_value: {}".format(value.split("/")[-1]))
for i in add_on_data.get(add_on_key):
logger.info("Iterating Add-On AVM File List for comparision.")
for k, v in i.items():
logger.info('{}: {}'.format(k, v))
add_on_file_name = v.split('/')[-1]
logger.info("add_on_value: {}".format(v.split('/')[-1]))
logger.info("{}: {}".format(k, v))
add_on_file_name = v.split("/")[-1]
logger.info("add_on_value: {}".format(v.split("/")[-1]))
if master_file_name == add_on_file_name:
logger.info("Matching file names found - "
"full path below")
logger.info("Matching file names found - " "full path below")
logger.info("File in master list: {}".format(value))
logger.info("File in add-on list: {}".format(v))
# Pass value and v to merge functions
if master_file_name.lower().endswith('.template'):
if master_file_name.lower().endswith(".template"):
logger.info("Processing template file")
# merge master avm template with add_on template
# send json data
final_json = update_template(_flip_to_json(value),
_flip_to_json(v))
final_json = update_template(
_flip_to_json(value), _flip_to_json(v)
)
# write the json data to json file
updated_json_file_name = \
os.path.join(value+updated_flag)
updated_json_file_name = os.path.join(value + updated_flag)
_write_file(final_json, updated_json_file_name)
_flip_to_yaml(updated_json_file_name)
if master_file_name.lower().endswith('.json'):
if master_file_name.lower().endswith(".json"):
logger.info("Processing parameter file")
update_parameters(value, v)

Expand All @@ -92,16 +91,17 @@ def update_level_1_dict(master, add_on, level_1_key):
for key1, value1 in add_on.items():
if isinstance(value1, dict) and key1 == level_1_key:
# Check if primary key matches
logger.info("Level 1 keys matched ADDON {} == {}".format(
key1, level_1_key))
logger.info("Level 1 keys matched ADDON {} == {}".format(key1, level_1_key))
# Iterate through the 2nd level dicts in the value
for key2, value2 in value1.items():
logger.info("----------------------------------")
# Match k with master dict keys - add if not present
for k1, v1 in master.items():
if isinstance(v1, dict) and k1 == level_1_key:
logger.info("Level 1 keys matched MASTER "
"{} == {}".format(k1, level_1_key))
logger.info(
"Level 1 keys matched MASTER "
"{} == {}".format(k1, level_1_key)
)
flag = False
# Iterate through the 2nd level dicts in
# the value
Expand All @@ -110,17 +110,17 @@ def update_level_1_dict(master, add_on, level_1_key):
if key2 == k2:
logger.info("Found matching keys")
flag = False
logger.info("Setting flag value to {}"
.format(flag))
logger.info("Setting flag value to {}".format(flag))
break
else:
flag = True
logger.info(
"Add-on key not found in existing"
" dict, setting flag value to {}"
" to update dict.".format(flag))
" to update dict.".format(flag)
)
if flag:
logger.info('Adding key {}'.format(key2))
logger.info("Adding key {}".format(key2))
d2 = {key2: value2}
v1.update(d2)
logger.debug(master)
Expand Down Expand Up @@ -152,7 +152,7 @@ def update_template(master, add_on):
return master


def update_parameters(master, add_on, decision_key='ParameterKey'):
def update_parameters(master, add_on, decision_key="ParameterKey"):
logger.info("Merging parameter files.")
m_list = _read_file(master)
add_list = _read_file(add_on)
Expand All @@ -164,11 +164,16 @@ def update_parameters(master, add_on, decision_key='ParameterKey'):
for i in m_list:
logger.info(i.get(decision_key))
if item.get(decision_key) == i.get(decision_key):
logger.info("Keys: '{}' matched, skipping"
.format(item.get(decision_key)))
logger.info(
"Keys: '{}' matched, skipping".format(
item.get(decision_key)
)
)
flag = False
logger.info("Setting flag value to {} and stopping"
" the loop.".format(flag))
logger.info(
"Setting flag value to {} and stopping"
" the loop.".format(flag)
)
break
else:
flag = True
Expand All @@ -181,7 +186,7 @@ def update_parameters(master, add_on, decision_key='ParameterKey'):
return m_list


if __name__ == '__main__':
if __name__ == "__main__":
if len(sys.argv) > 3:
log_level = sys.argv[1]
master_baseline_file = sys.argv[2]
Expand All @@ -196,8 +201,12 @@ def update_parameters(master, add_on, decision_key='ParameterKey'):
file_matcher(master_list, add_on_list)

else:
print('No arguments provided. Please provide the existing and '
'new manifest files names.')
print('Example: merge_baseline_template_parameter.py <LOG-LEVEL>'
' <MASTER_FILE_NAME> <ADD_ON_FILE_NAME>')
print(
"No arguments provided. Please provide the existing and "
"new manifest files names."
)
print(
"Example: merge_baseline_template_parameter.py <LOG-LEVEL>"
" <MASTER_FILE_NAME> <ADD_ON_FILE_NAME>"
)
sys.exit(2)
Loading

0 comments on commit 8d79ba3

Please sign in to comment.