我想使用CodePipeline运行CloudFormation模板。该模板需要一个输入参数,该参数需要包含当前的日期/时间。不幸的是,CloudFormation不能直接生成当前的DateTime。
我的方法是首先运行一个简单的Lambda函数来创建当前时间戳并将其保存为OutputArtifacts
。随后的CloudFormation任务将此工件导入为InputArtifacts
,并从DateTime属性获取值,并通过ParameterOverrides
指令将其传递给CloudFormation。
不幸的是,CodePipeline一直说DateTimeInput
参数无效(显然GetArtifactAtt查找失败)。
我认为lambda输出(python:print)没有正确保存为工件?
您知道如何正确传递lambda输出,还是有一个更好的方法来实现这一点?
所有管道组件都使用CloudFormation定义为YAML。以下是相关部分:
Lambda函数:
Resources:
...
GetDateTimeFunction:
Type: AWS::Lambda::Function
Properties:
Handler: index.lambda_handler
Runtime: python2.7
Timeout: '10'
Role: !GetAtt GetDateTimeFunctionExecutionRole.Arn
Code:
ZipFile: |
import datetime
import boto3
import json
code_pipeline = boto3.client('codepipeline')
def lambda_handler(event, context):
now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
responseData = {'DateTime':now}
print json.dumps(responseData)
response = code_pipeline.put_job_success_result(jobId=event['CodePipeline.job']['id'])
return response
以下是管道任务:
Resources:
...
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
ArtifactStore:
Location: !Ref ArtifactStoreBucket
Type: S3
DisableInboundStageTransitions: []
Name: !Ref PipelineName
RoleArn: !GetAtt PipelineRole.Arn
Stages:
- Name: Deploy
Actions:
- Name: GetDateTime
RunOrder: 1
ActionTypeId:
Category: Invoke
Owner: AWS
Provider: Lambda
Version: '1'
Configuration:
FunctionName: !Ref GetDateTimeFunction
OutputArtifacts:
- Name: GetDateTimeOutput
- Name: CreateStack
RunOrder: 2
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: '1'
InputArtifacts:
- Name: TemplateSource
- Name: GetDateTimeOutput
Configuration:
ActionMode: REPLACE_ON_FAILURE
Capabilities: CAPABILITY_IAM
RoleArn: !GetAtt CloudFormationRole.Arn
StackName: !Ref CFNStackname
TemplatePath: !Sub TemplateSource::${CFNScriptfile}
TemplateConfiguration: !Sub TemplateSource::${CFNConfigfile}
ParameterOverrides: |
{
"DateTimeInput" : { "Fn::GetArtifactAtt" : [ "GetDateTimeOutput", "DateTime" ] }
}
更新:我很天真,认为会有一种简单的方法。 现在,我知道这是一个更高级的手动任务,只是提供带有lambda的简单输出工件。
在python代码内部,必须评估传递的event
字典(CodePipeline.job
)才能查找:
-预定义的OutputArtifacts(S3存储桶/密钥)和
-CodePipeline提供的临时S3会话凭据。
然后,必须使用这些凭据来初始化S3客户端。 S3 put_object
之后需要运行。
https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.html https://forums.aws.amazon.com/thread.jspa?threadID=232174
所以我的问题又是:你们是否有一个想法,如何以更好或更简单的方式实现这一目标?
我只想将当前日期和时间作为CloudFormation的输入参数,并且不想破坏自动化。
答案 0 :(得分:2)
是的,我不知道需要自己亲自处理输出工件。
最后,这成功了:
import Data.List(sortBy)
import Data.Ord(comparing)
check :: (Ord n, Enum n) => [n] -> [[n]]
check = go . sortBy (comparing fromEnum)
where go (x:na@(n:xs)) | succ x == n || x == n = (x:r) : rs
| otherwise = [x]: ra
where ra@(~(r:rs)) = go na
go [x] = [[x]]
go [] = []
这项琐碎的任务的开销很大;-)
答案 1 :(得分:0)
您应使用“ Fn :: GetParam”而不是“ Fn :: GetArtifactAtt”。根据CloudFormation文档,“ Fn :: GetArtifactAtt”只能获取工件的属性,例如BucketName,ObjectKey和URL。 “ Fn :: GetParam”可以从工件中的json文件中获取值。因此,如果您可以将工件“ GetDateTimeOutput”生成为zip文件,其中包括具有以下内容的JSON文件(例如param.json)
{ “ DateTime”:“ 2018/10/31 13:32:00” }
然后您可以使用{“ Fn :: GetParam”:[“ GetDateTimeOutput”,“ param.json”,“ DateTime”]}来获取时间。
您可以修改Lambda函数来执行此操作,也可以使用CodeBuild操作。 CodeBuild负责创建zip,您只需指定构建命令即可在输出文件夹中创建JSON文件。您可以在以下文档中找到有关如何在CodePipeline中使用CodeBuild的更多信息。
CloudFormation文档 https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-parameter-override-functions.html#w2ab1c13c17b9
CodeBuild文档 https://docs.aws.amazon.com/codebuild/latest/userguide/how-to-create-pipeline.html