Skip to content

Commit

Permalink
Merge pull request #19 from john-shaskin/cloudformation-output
Browse files Browse the repository at this point in the history
Allow CloudFormation action in CodePipeline to push stack outputs to an optional output artifact
  • Loading branch information
brettswift committed Oct 5, 2018
2 parents 2147cc8 + bf19f58 commit 152d09d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 8 deletions.
4 changes: 1 addition & 3 deletions cumulus/policies/cloudformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ def get_policy_cloudformation_general_access(policy_name):
awacs.aws.Action("lambda", "*"),
awacs.aws.Action("sqs", "*"),
awacs.aws.Action("events", "*"),
awacs.ecr.GetDownloadUrlForLayer,
awacs.ecr.BatchGetImage,
awacs.ecr.BatchCheckLayerAvailability,
awacs.aws.Action("ecr", "*"),
awacs.iam.PassRole,
],
Resource=["*"]
Expand Down
4 changes: 1 addition & 3 deletions cumulus/policies/codebuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ def get_policy_code_build_general_access(policy_name):
awacs.aws.Action("sqs", "*"),
awacs.aws.Action("events", "*"),
awacs.aws.Action("logs", "*"),
awacs.ecr.GetDownloadUrlForLayer,
awacs.ecr.BatchGetImage,
awacs.ecr.BatchCheckLayerAvailability,
awacs.aws.Action("ecr", "*"),
awacs.iam.PassRole,
],
Resource=["*"]
Expand Down
18 changes: 16 additions & 2 deletions cumulus/steps/dev_tools/cloud_formation_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@

class CloudFormationAction(step.Step):

OUTPUT_FILE_NAME = 'StackOutputs.json'

def __init__(self,
action_name,
input_artifact_names,
input_template_path,
input_template_configuration,
stage_name_to_add,
stack_name,
action_mode):
action_mode,
output_artifact_name=None):
"""
:type action_name: basestring Displayed on the console
:type input_artifact_names: [basestring] List of input artifacts
Expand All @@ -36,6 +39,7 @@ def __init__(self,
self.stage_name_to_add = stage_name_to_add
self.stack_name = stack_name
self.action_mode = action_mode
self.output_artifact_name = output_artifact_name

def handle(self, chain_context):

Expand Down Expand Up @@ -81,11 +85,21 @@ def handle(self, chain_context):
'StackName': self.stack_name,
'Capabilities': 'CAPABILITY_NAMED_IAM',
'TemplateConfiguration': self.input_template_configuration,
'TemplatePath': self.input_template_path
'TemplatePath': self.input_template_path,
},
RunOrder="1"
)

# Add optional configuration
if (self.output_artifact_name):
output_artifact = codepipeline.OutputArtifacts(
Name=self.output_artifact_name
)
cloud_formation_action.OutputArtifacts = [
output_artifact
]
cloud_formation_action.Configuration['OutputFileName'] = CloudFormationAction.OUTPUT_FILE_NAME

chain_context.template.add_resource(cloud_formation_role)

stage = cumulus.util.template_query.TemplateQuery.get_pipeline_stage_by_name(
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/steps/dev_tools/test_cloud_formation_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ def test_handle_adds_cloud_formation_action_to_stage(self):
self.assertEqual(test_action.Configuration['ActionMode'], action_mode.ActionMode.REPLACE_ON_FAILURE.value)
self.assertEquals(len(test_action.InputArtifacts), 1)
self.assertEquals(test_action.InputArtifacts[0].Name, "InfraInput")
# By default no output artifact is created
self.assertFalse(hasattr(test_action, 'OutputArtifacts'))
self.assertFalse('OutputFileName' in test_action.Configuration)

def test_raises_error_if_target_stage_does_not_exist(self):
action = cloud_formation_action.CloudFormationAction(
Expand Down Expand Up @@ -113,3 +116,25 @@ def test_can_add_multiple_input_artifacts(self):
self.assertEquals(len(test_action.InputArtifacts), 2)
self.assertEquals(test_action.InputArtifacts[0].Name, "InfraInput")
self.assertEquals(test_action.InputArtifacts[1].Name, "ParameterInput")

def test_can_create_output_artifact(self):
action = cloud_formation_action.CloudFormationAction(
action_name="CloudFormation",
input_artifact_names=["InfraInput"],
input_template_path="InfraInput::template.json",
input_template_configuration="InfraInput::myenv.json",
output_artifact_name="AllOfTheThings",
stage_name_to_add=self.deploy_stage_name,
stack_name="my-microservice",
action_mode=action_mode.ActionMode.REPLACE_ON_FAILURE
)

action.handle(self.context)

deploy_stage = TemplateQuery.get_resource_by_type(self.context.template, codepipeline.Stages)[0]
self.assertEqual(len(deploy_stage.Actions), 1)

test_action = deploy_stage.Actions[0]
self.assertEquals(len(test_action.OutputArtifacts), 1)
self.assertEquals(test_action.OutputArtifacts[0].Name, "AllOfTheThings")
self.assertEquals(test_action.Configuration['OutputFileName'], "StackOutputs.json")

0 comments on commit 152d09d

Please sign in to comment.