【问题标题】:How can I get current date in a CloudFormation script?如何在 CloudFormation 脚本中获取当前日期?
【发布时间】:2013-03-16 07:12:18
【问题描述】:

我正在使用我的 cfn 脚本中的标签来标记我的资源:

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

我想按照上面的例子创建一个带有当前日期的标签。有可能吗?

【问题讨论】:

标签: amazon-web-services amazon-cloudformation


【解决方案1】:

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

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 * * *"

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

【讨论】:

  • 这似乎只适用于初始堆栈创建,但不适用于后续堆栈更新
  • 确实如此。如果您知道要导致时间戳自定义值发生更改的更改(我假设您不想为每一个小更改都这样做),那么您可以将另一个属性添加到您将手动的自定义值(或使用其他工具)根据需要进行更改。例如,Serial: !Ref Serial,然后有一个参数Serial,您可以根据需要进行更新。请参阅此问题及其答案以进行一些讨论:stackoverflow.com/q/46824171/53538
【解决方案2】:

@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')"

希望这会有所帮助!

【讨论】:

  • 不只是实例 - 这种方法也适用于卷、AMI 以及您可以标记的任何其他内容 - 谢谢。
  • 使用 aws cli cloudformation 的等效项是 aws cloudformation create-stack \ --stack-name yourname \ --template-body file://template.yaml \ --parameters \ ParameterKey=CreationDate,ParameterValue="$(date +'%F %T')"
猜你喜欢
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 2017-02-27
  • 2012-01-29
  • 2010-11-07
  • 2010-12-04
相关资源
最近更新 更多