diff --git a/aws/deploymentframeworks/cf/output.ftl b/aws/deploymentframeworks/cf/output.ftl index 191eb183..858d0647 100644 --- a/aws/deploymentframeworks/cf/output.ftl +++ b/aws/deploymentframeworks/cf/output.ftl @@ -411,24 +411,60 @@ [#return stack_name?join("-")] [/#function] -[#macro addDefaultAWSDeploymentContract prologue=false stack=true change_set=false epilogue=false ] +[#macro addDefaultAWSDeploymentContract prologue=false stack=true changeset=false epilogue=false ] [#local stackName = getCFNStackName()] [#local changeSetName = "hamlet" + getCLORunId() ] [#local runId = getCLORunId()] + [#local cfDir = (getCommandLineOptions().Output.cfDir)!""] [#local s3StackPath = "cfn/" + stackName + "/template.json"] + [#local segmentOperationsDir = (getCommandLineOptions().Output.segmentOperationsDir)!""] + [#local deploymentMode = getDeploymentMode()] [#local deploymentModeDetails = getDeploymentModeDetails(deploymentMode)] [#local deploymentModeOperations = deploymentModeDetails.Operations] + [#local scriptEnv = { + "STACK_NAME": stackName, + "CF_DIR": cfDir, + "SEGMENT_OPERATIONS_DIR": segmentOperationsDir + }] + + [#list getActiveLayers() as type, layerInfo ] + [#local scriptEnv = mergeObjects(scriptEnv, { type?upper_case: layerInfo.Name })] + [/#list] + + [#-- Update deployment contract name --] + [#local contractRenameStageId = "contract_rename" ] + [@contractStage + id=contractRenameStageId + executionMode=CONTRACT_EXECUTION_MODE_SERIAL + priority=1 + /] + [@contractStep + id="rename_contract_file" + stageId=contractRenameStageId + taskType=RENAME_FILE_TASK_TYPE + parameters={ + "currentFileName": formatAbsolutePath( + cfDir, + getOutputFileName("deploymentcontract", "", "") + ), + "newFileName": formatAbsolutePath( + cfDir, + getOutputFileName("deploymentcontract", "final", "") + ) + } + /] + [#-- login to provider --] [#local loginStageId = "login" ] [@contractStage id=loginStageId executionMode=CONTRACT_EXECUTION_MODE_SERIAL - priority=1 + priority=2 /] [@contractStep @@ -444,6 +480,8 @@ [#list deploymentModeOperations as deploymentModeOperation ] + [#local scriptEnv = mergeObjects(scriptEnv, { "STACK_OPERATION": deploymentModeOperation})] + [#if prologue] [#-- prologue script --] [#local prologueStageId = "prologue"] @@ -453,15 +491,43 @@ priority=deploymentModeOperation?index * 100 + 10 /] + [@contractStep + id="prologue_script_details" + priority=10 + stageId=prologueStageId + taskType=FILE_PATH_DETAILS_TASK_TYPE + parameters={ + "FilePath": formatAbsolutePath( + cfDir, + getOutputFileName("prologue", "", "") + ) + } + /] + + [@contractStep + id="no_prologue_file_skip" + priority=15 + stageId=prologueStageId + taskType=CONDITIONAL_STAGE_SKIP_TASK_TYPE + status="skip_stage_if_failure" + parameters={ + "Test" : "True", + "Condition": "Equals", + "Value": "__Properties:output:prologue_script_details:exists__" + } + /] + [@contractStep id="prologue_script" + priority=20 stageId=prologueStageId taskType=AWS_RUN_BASH_SCRIPT_TASK_TYPE parameters={ "ScriptPath": formatAbsolutePath( - (getCommandLineOptions().Output.cfDir)!"", + cfDir, getOutputFileName("prologue", "primary", "") ), + "Environment": getJSON(scriptEnv), "AWSAccessKeyId" : "__Properties:output:aws_login:aws_access_key_id__", "AWSSecretAccessKey": "__Properties:output:aws_login:aws_secret_access_key__", "AWSSessionToken" : "__Properties:output:aws_login:aws_session_token__" @@ -470,7 +536,7 @@ /] [/#if] - [#if ( stack || change_set ) && ["update", "create"]?seq_contains(deploymentModeOperation) ] + [#if ( stack || changeset ) && ["update", "create"]?seq_contains(deploymentModeOperation) ] [#-- Templates to S3 --] [#local templateS3StageId = "templates_to_s3"] [@contractStage @@ -488,7 +554,7 @@ "BucketName": getRegistryBucket(getRegion()), "Object": s3StackPath, "LocalPath": formatAbsolutePath( - (getCommandLineOptions().Output.cfDir)!"", + cfDir, getOutputFileName("template", "primary", "") ), "AWSAccessKeyId" : "__Properties:output:aws_login:aws_access_key_id__", @@ -539,7 +605,7 @@ /] [/#if] - [#if change_set && ["update", "create"]?seq_contains(deploymentModeOperation) ] + [#if changeset && ["update", "create"]?seq_contains(deploymentModeOperation) ] [#-- Run through the change set process as required --] [#local changeSetExecutionStageId = "change_set_execution" ] [@contractStage @@ -608,7 +674,7 @@ /] [/#if] - [#if ( stack || change_set ) && ["update", "create"]?seq_contains(deploymentModeOperation) ] + [#if ( stack || changeset ) && ["update", "create"]?seq_contains(deploymentModeOperation) ] [#-- Get Outputs from stack --] [#local outputStackStageId = "outputs"] [@contractStage @@ -620,18 +686,22 @@ [@contractStep id="outputs" stageId=outputStackStageId - taskType=AWS_CFN_GET_STACK_OUTPUTS_TASK_TYPE + taskType=AWS_CFN_WRITE_STACK_OUTPUTS_TO_FILE_TASK_TYPE parameters={ "StackName": stackName, "AWSAccessKeyId" : "__Properties:output:aws_login:aws_access_key_id__", "AWSSecretAccessKey": "__Properties:output:aws_login:aws_secret_access_key__", - "AWSSessionToken" : "__Properties:output:aws_login:aws_session_token__" + "AWSSessionToken" : "__Properties:output:aws_login:aws_session_token__", + "FilePath": formatAbsolutePath( + cfDir, + getOutputFileName("stack", "", "") + ) } status="available" /] [/#if] - [#if ( stack || change_set ) && ["delete" ]?seq_contains(deploymentModeOperation) ] + [#if ( stack || changeset ) && ["delete" ]?seq_contains(deploymentModeOperation) ] [#-- Delete the stack --] [#local deleteStackStageId = "delete_stack"] @@ -654,6 +724,18 @@ } status="available" /] + + [@contractStep + id="delete_stack_output" + stageId=deleteStackStageId + taskType=FILE_DELETE_TASK_TYPE + parameters={ + "FilePath": formatAbsolutePath( + cfDir, + getOutputFileName("stack", "primary", "") + ) + } + /] [/#if] [#if epilogue] @@ -665,15 +747,43 @@ priority=deploymentModeOperation?index * 100 + 60 /] + [@contractStep + id="epilogue_script_details" + priority=10 + stageId=epilogueStageId + taskType=FILE_PATH_DETAILS_TASK_TYPE + parameters={ + "FilePath": formatAbsolutePath( + cfDir, + getOutputFileName("epilogue", "", "") + ) + } + /] + + [@contractStep + id="no_epilogue_file_skip" + priority=15 + stageId=epilogueStageId + taskType=CONDITIONAL_STAGE_SKIP_TASK_TYPE + status="skip_stage_if_failure" + parameters={ + "Test" : "True", + "Condition": "Equals", + "Value": "__Properties:output:epilogue_script_details:exists__" + } + /] + [@contractStep id="epilogue_script" + priority=20 stageId=epilogueStageId taskType=AWS_RUN_BASH_SCRIPT_TASK_TYPE parameters={ "ScriptPath": formatAbsolutePath( - (getCommandLineOptions().Output.cfDir)!"", + cfDir, getOutputFileName("epilogue", "primary", "") ), + "Environment": getJSON(scriptEnv), "AWSAccessKeyId" : "__Properties:output:aws_login:aws_access_key_id__", "AWSSecretAccessKey": "__Properties:output:aws_login:aws_secret_access_key__", "AWSSessionToken" : "__Properties:output:aws_login:aws_session_token__" diff --git a/aws/tasks/aws_cfn_write_stack_outputs_to_file/id.ftl b/aws/tasks/aws_cfn_write_stack_outputs_to_file/id.ftl new file mode 100644 index 00000000..08131936 --- /dev/null +++ b/aws/tasks/aws_cfn_write_stack_outputs_to_file/id.ftl @@ -0,0 +1,45 @@ +[#ftl] + +[@addTask + type=AWS_CFN_WRITE_STACK_OUTPUTS_TO_FILE_TASK_TYPE + properties=[ + { + "Type" : "Description", + "Value" : "Get the outputs of a stack and write them to file" + } + ] + attributes=[ + { + "Names": "StackName", + "Description": "The name to use for the stack", + "Types": STRING_TYPE, + "Mandatory": true + }, + { + "Names" : "Region", + "Description" : "The name of the region to use for the aws session", + "Types" : STRING_TYPE + }, + { + "Names" : "AWSAccessKeyId", + "Description" : "The AWS Access Key Id with access to decrypt", + "Types" : STRING_TYPE + }, + { + "Names" : "AWSSecretAccessKey", + "Description" : "The AWS Secret Access Key with access to decrypt", + "Types" : STRING_TYPE + }, + { + "Names" : "AWSSessionToken", + "Description" : "The AWS Session Token with access to decrypt", + "Types" : STRING_TYPE + }, + { + "Names": "FilePath", + "Description": "The path to where the file should be written", + "Types" : STRING_TYPE, + "Mandatory" : true + } + ] +/] diff --git a/aws/tasks/aws_run_bash_script/id.ftl b/aws/tasks/aws_run_bash_script/id.ftl index 196239e4..daf60f47 100644 --- a/aws/tasks/aws_run_bash_script/id.ftl +++ b/aws/tasks/aws_run_bash_script/id.ftl @@ -15,6 +15,11 @@ "Types": STRING_TYPE, "Mandatory": true }, + { + "Names": "Environment", + "Description": "A json escaped dict with k/v environment variable pairs", + "Types" : STRING_TYPE + }, { "Names" : "AWSAccessKeyId", "Description" : "The AWS Access Key Id with access to decrypt", diff --git a/aws/tasks/task.ftl b/aws/tasks/task.ftl index 07f55a78..b256cdc1 100644 --- a/aws/tasks/task.ftl +++ b/aws/tasks/task.ftl @@ -25,5 +25,6 @@ [#assign AWS_CFN_GET_STACK_OUTPUTS_TASK_TYPE = "aws_cfn_get_stack_outputs"] [#assign AWS_CFN_GET_CHANGE_SET_CHANGES_TASK_TYPE = "aws_cfn_get_change_set_changes_types"] [#assign AWS_CFN_RUN_STACK_TASK_TYPE = "aws_cfn_run_stack"] +[#assign AWS_CFN_WRITE_STACK_OUTPUTS_TO_FILE_TASK_TYPE = "aws_cfn_write_stack_outputs_to_file"] [#assign AWS_RUN_BASH_SCRIPT_TASK_TYPE = "aws_run_bash_script"]