如何在CloudFormation脚本中获取当前日期?

时间:2013-03-26 13:12:42

标签: amazon-web-services amazon-cloudformation

我使用我的cfn脚本中的标记标记我的资源:

"Tags" : [ { "Key" : "Owner",       "Value" : "my name" },
           { "Key" : "Name",        "Value" : "instance name" } 
           { "Key" : "DateCreated", "Value" : <something goes here> } 
         ],

我想根据上面的示例创建一个包含当前日期的标记。有可能吗?

2 个答案:

答案 0 :(得分:8)

您可以使用“自定义资源”生成时间戳(或任何其他值)。

Custom resources是CloudFormation中的新功能(于2014年左右推出),允许您基本上调用lambda函数来“创建”,“更新”或“删除”CloudFormation不提供语言支持的资源(甚至可以是AWS之外的资源)。

我经常使用自定义资源来计算一些值,以便在堆栈的其他部分中使用,例如创建保存计算值的“变量”(例如使用!Join和类似的函数)我需要经常使用并想计算一次。

您可以轻松使用自定义资源生成时间戳。下面是一些示例代码,与我在生产中实际使用的代码非常接近:

创建“资源”实现

Resources:
  ValueFunc:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: >
          var r = require('cfn-response');
          exports.handler = function(ev, ctx) {
            ev.ResourceProperties.Time = new Date().toISOString();
            r.send(ev, ctx, r.SUCCESS, ev.ResourceProperties);
          }; 
      Handler: index.handler
      Runtime: nodejs6.10
      Timeout: 30
      Role: !GetAtt ValueFunctionExecutionRole.Arn

  ValueFunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal: { Service: [ lambda.amazonaws.com ] }
            Action: sts:AssumeRole
      Policies:
        - PolicyName: 
            Fn::Sub: "value-custom-res-${AWS::StackName}-${AWS::Region}"
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: "arn:aws:logs:*:*:*"
              - Effect: Allow
                Action: cloudformation:DescribeStacks
                Resource: "arn:aws:cloudformation:*:*:*"

然后,无论您想在哪里生成时间戳,都可以执行以下操作(从here获取的计划操作示例):

创建计算其创建时间的自定义资源

GetTimeThisTime:
  Type: Custom::Value
  Properties:
    ServiceToken: !GetAtt ValueFunc.Arn

使用Time属性

读取创建的时间戳
ScheduledActionUp: 
  Type: AWS::AutoScaling::ScheduledAction
  Properties:
    AutoScalingGroupName: !Ref WebServerGroup
    DesiredCapacity: 2
    StartTime: !GetAtt GetTimeThisTime.Time
    Recurrence: "0 7 * * *"

您可以在创建堆栈的不同时间生成多个时间戳,只需创建一个新的“自定义值”,该值取决于您想要计时的逻辑实体。

答案 1 :(得分:7)

@Guy的建议是正确的,您可以从堆栈属性访问堆栈的创建时间戳。

如果您仍需要将标记指定为参数,则可以通过以下方式执行此操作。目前,JSON语法支持极其有限的set of functions。因此,动态修改模板的可能性非常小。我看到引入这个标签的唯一方法是向模板本身添加另一个参数。根据初始化堆栈的方式,您可以编写动态指定的参数脚本或在Web控制台中提供该参数。

例如,如果您在模板中有此内容:

  "Parameters" : {
    "CreationDate" : {
      "Description" : "Date",
      "Type" : "String",
      "Default" : "2013-03-20 21:15:00",
      "AllowedPattern" : "^\\d{4}(-\\d{2}){2} (\\d{2}:){2}\\d{2}$",
      "ConstraintDescription" : "Date and time of creation"
    }
  },

您可以稍后使用标签中的Ref关键字引用它,如下所示:

 "Tags" : [ { "Key" : "Owner",       "Value" : "my name" },
            { "Key" : "Name",        "Value" : "instance name" },
            { "Key" : "DateCreated", "Value" : { "Ref" : "CreationDate" } } 
          ],

如果您从AWS控制台创建堆栈,则自动分配当前时间并非易事,但如果您使用CLI工具,则可以像这样调用cfn-create-stack:

  cfn-create-stack MyStack --template-file My.template --parameters "CreationDate=$(date +'%F %T')"

希望这有帮助!