AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 625600
Accepted
MLu
MLu
Asked: 2014-09-02 19:41:05 +0800 CST2014-09-02 19:41:05 +0800 CST 2014-09-02 19:41:05 +0800 CST

AWS CloudFormation - 模板中的自定义变量

  • 772

有没有办法为从 CloudFormation 模板参数派生的常用值定义快捷方式?

例如 - 我有一个脚本,它创建一个多可用区项目堆栈,其中 ELB 名称project和 ELB 后面的两个实例称为project-1and project-2。我只将ELBHostName参数传递给模板,然后用它来构造:

"Fn::Join": [
    ".", [
        { "Fn::Join": [ "", [ { "Ref": "ELBHostName" }, "-1" ] ] },
        { "Ref": "EnvironmentVersioned" },
        { "Ref": "HostedZone" }
    ]
]

这种构造或非常相似的构造在整个模板中重复多次 - 以创建 EC2 主机名、Route53 记录等。

我不想一遍又一遍地重复,我想将它的输出分配Fn::Join给某种变量,并且只引用它,就像我可以使用"Ref":语句一样。

理想情况下是这样的:

Var::HostNameFull = "Fn::Join": [ ... ]
...
{ "Name": { "Ref": "Var::HostNameFull" } }

或类似简单的东西。

Amazon CloudFormation 可以做到吗?

amazon-web-services
  • 5 5 个回答
  • 34636 Views

5 个回答

  • Voted
  1. Kevin Audleman
    2017-10-19T09:59:35+08:002017-10-19T09:59:35+08:00

    我没有答案,但确实想指出,您可以通过使用Fn::Sub代替Fn::Join

    { "Fn::Sub": "${ELBHostName"}-1.${EnvironmentVersioned}.${HostedZone}"}
    

    替换

    "Fn::Join": [
        ".", [
            { "Fn::Join": [ "", [ { "Ref": "ELBHostName" }, "-1" ] ] },
            { "Ref": "EnvironmentVersioned" },
            { "Ref": "HostedZone" }
        ]
    ]
    
    • 17
  2. Rob
    2014-09-06T09:17:57+08:002014-09-06T09:17:57+08:00

    不,我试过了,但结果是空的。对我来说有意义的方法是创建一个名为“CustomVariables”的映射条目,并让该条目容纳我的所有变量。它适用于简单的字符串,但不能在 Mappings 中使用 Intrinsics(Refs、Fn::Joins 等)。

    作品:

    "Mappings" : {
      "CustomVariables" : {
        "Variable1" : { "Value" : "foo" },
        "Variable2" : { "Value" : "bar" }
      }
    }
    

    不会工作:

      "Variable3" : { "Value" : { "Ref" : "AWS::Region" } }
    

    这只是一个例子。您不会将独立的 Ref 放入变量中。

    • 7
  3. Best Answer
    Claude
    2016-10-30T05:17:44+08:002016-10-30T05:17:44+08:00

    我正在寻找相同的功能。想到使用 SpoonMeiser 建议的嵌套堆栈,但后来我意识到我真正需要的是自定义函数。幸运的是,CloudFormation 允许使用AWS::CloudFormation::CustomResource,只需做一些工作,就可以做到这一点。对于变量来说,这感觉有点矫枉过正(我认为一开始就应该在 CloudFormation 中),但它完成了工作,此外,还允许所有的灵活性(选择 python/node /java)。应该注意的是,lambda 函数需要花钱,但我们在这里谈论的是便士,除非您每小时创建/删除多次堆栈。

    第一步是在这个页面上创建一个 lambda 函数,它除了获取输入值并将其复制到输出之外什么都不做。我们可以让 lambda 函数做各种疯狂的事情,但是一旦我们有了恒等函数,其他任何事情都变得容易了。或者,我们可以在堆栈本身中创建 lambda 函数。由于我在 1 个帐户中使用了许多堆栈,因此我将拥有一大堆剩余的 lambda 函数和角色(并且所有堆栈都需要使用 创建--capabilities=CAPABILITY_IAM,因为它也需要一个角色。

    创建 lambda 函数

    • 进入lambda 主页,选择您喜欢的地区
    • 选择“空白函数”作为模板
    • 点击“下一步”(不要配置任何触发器)
    • 填写:
      • 名称:CloudFormationIdentity
      • 描述:返回它所得到的,Cloud Formation 中的变量支持
      • 运行时:python2.7
      • 代码输入类型:编辑代码内联
      • 代码:见下文
      • 处理程序:index.handler
      • 角色:创建自定义角色。此时会打开一个弹出窗口,允许您创建新角色。接受此页面上的所有内容,然后单击“允许”。它将创建一个有权发布到 cloudwatch 日志的角色。
      • 内存:128(这是最小值)
      • 超时:3秒(应该足够)
      • VPC:无 VPC

    然后将下面的代码复制粘贴到代码字段中。函数的顶部是来自cfn-response python 模块的代码,它只有在通过 CloudFormation 创建 lambda 函数时才会自动安装,原因很奇怪。该handler功能非常不言自明。

    from __future__ import print_function
    import json
    
    try:
        from urllib2 import HTTPError, build_opener, HTTPHandler, Request
    except ImportError:
        from urllib.error import HTTPError
        from urllib.request import build_opener, HTTPHandler, Request
    
    
    SUCCESS = "SUCCESS"
    FAILED = "FAILED"
    
    
    def send(event, context, response_status, reason=None, response_data=None, physical_resource_id=None):
        response_data = response_data or {}
        response_body = json.dumps(
            {
                'Status': response_status,
                'Reason': reason or "See the details in CloudWatch Log Stream: " + context.log_stream_name,
                'PhysicalResourceId': physical_resource_id or context.log_stream_name,
                'StackId': event['StackId'],
                'RequestId': event['RequestId'],
                'LogicalResourceId': event['LogicalResourceId'],
                'Data': response_data
            }
        )
        if event["ResponseURL"] == "http://pre-signed-S3-url-for-response":
            print("Would send back the following values to Cloud Formation:")
            print(response_data)
            return
    
        opener = build_opener(HTTPHandler)
        request = Request(event['ResponseURL'], data=response_body)
        request.add_header('Content-Type', '')
        request.add_header('Content-Length', len(response_body))
        request.get_method = lambda: 'PUT'
        try:
            response = opener.open(request)
            print("Status code: {}".format(response.getcode()))
            print("Status message: {}".format(response.msg))
            return True
        except HTTPError as exc:
            print("Failed executing HTTP request: {}".format(exc.code))
            return False
    
    def handler(event, context):
        responseData = event['ResourceProperties']
        send(event, context, SUCCESS, None, responseData, "CustomResourcePhysicalID")
    
    • 点击下一步”
    • 点击“创建函数”

    您现在可以通过选择“测试”按钮来测试 lambda 函数,并选择“CloudFormation 创建请求”作为示例模板。您应该在日志中看到返回给它的变量。

    在 CloudFormation 模板中使用变量

    现在我们有了这个 lambda 函数,我们可以在 CloudFormation 模板中使用它。首先记下 lambda 函数 Arn(进入lambda 主页,点击刚刚创建的函数,Arn 应该在右上角,类似于arn:aws:lambda:region:12345:function:CloudFormationIdentity)。

    现在在您的模板中,在资源部分中,指定您的变量,例如:

    Identity:
      Type: "Custom::Variable"
      Properties:
        ServiceToken: "arn:aws:lambda:region:12345:function:CloudFormationIdentity"
        Arn: "arn:aws:lambda:region:12345:function:CloudFormationIdentity"
    
    ClientBucketVar:
      Type: "Custom::Variable"
      Properties:
        ServiceToken: !GetAtt [Identity, Arn]
        Name: !Join ["-", [my-client-bucket, !Ref ClientName]]
        Arn: !Join [":", [arn, aws, s3, "", "", !Join ["-", [my-client-bucket, !Ref ClientName]]]]
    
    ClientBackupBucketVar:
      Type: "Custom::Variable"
      Properties:
        ServiceToken: !GetAtt [Identity, Arn]
        Name: !Join ["-", [my-client-bucket, !Ref ClientName, backup]]
        Arn: !Join [":", [arn, aws, s3, "", "", !Join ["-", [my-client-bucket, !Ref ClientName, backup]]]]
    

    首先,我指定一个Identity包含 lambda 函数的 Arn 的变量。把它放在一个变量中,意味着我只需要指定一次。我将所有变量都设为 type Custom::Variable。Custom::CloudFormation 允许您使用以自定义资源开头的任何类型名称。

    请注意,该Identity变量包含两次 lambda 函数的 Arn。一次指定要使用的 lambda 函数。第二次作为变量的值。

    现在我有了Identity变量,我可以使用定义新变量ServiceToken: !GetAtt [Identity, Arn](我认为 JSON 代码应该类似于"ServiceToken": {"Fn::GetAtt": ["Identity", "Arn"]})。我创建了 2 个新变量,每个变量都有 2 个字段:名称和 Arn。在模板的其余部分中,我可以使用!GetAtt [ClientBucketVar, Name]或!GetAtt [ClientBucketVar, Arn]在需要时使用。

    警告

    使用自定义资源时,如果 lambda 函数崩溃,您会被卡住 1 到 2 小时,因为 CloudFormation 在放弃之前会等待(崩溃)函数的回复一个小时。因此,在开发 lambda 函数时为堆栈指定一个较短的超时时间可能会很好。

    • 7
  4. SpoonMeiser
    2016-08-31T02:55:03+08:002016-08-31T02:55:03+08:00

    您可以使用嵌套堆栈来解析其输出中的所有变量,然后用于Fn::GetAtt从该堆栈读取输出

    使用另一个堆栈作为嵌套堆栈并传入计算的参数示例:

    
      YourResourceName:
        Type: AWS::CloudFormation::Stack
        Properties:
          TemplateURL: ./YourStackYouUseAsNested.yaml
          Parameters:
            ParamOfNestedStack: !Join [ "-", [ "you-compute-value", !Ref AWS::Region ] ]
    
    
    • 3
  5. JoseOlcese
    2014-11-01T13:38:11+08:002014-11-01T13:38:11+08:00

    您可以使用嵌套模板,在其中“解析”外部模板中的所有变量并将它们传递给另一个模板。

    • 2

相关问题

  • AWS RDS 的定价 [关闭]

  • 如何在 AWS ubuntu 实例上安装 apache?

  • 了解 Amazon AWS 使用数据

  • 亚马逊提供的负载均衡服务体验如何?

  • ELB 中现有节点的 AWS 自动缩放问题

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve