如何使CloudFormation模板中的整个对象可选? [英] How to make a whole object in CloudFormation templates optional?

查看:101
本文介绍了如何使CloudFormation模板中的整个对象可选?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过CloudFormation模板制作Lambda函数,我想使其成为可选的,以输入VpcConfig属性的信息.我发现了类似这样的文章,介绍如何使参数可选:

I'm making a Lambda function via CloudFormation template, and I'd like to make it optional to enter the information for the VpcConfig property. I've found articles like this one on how to make parameters optional:

https://cloudonaut.io/optional-parameter-in-cloudformation/

这对于查找语法以使具有单个值的属性为可选(例如单个字符串值)非常有帮助.

That was very helpful for finding syntax to make properties with single values optional (like a single string value).

但是我需要弄清楚的是如何使整个VpcConfig对象成为可选的.

But what I need to figure out is how to make the whole VpcConfig OBJECT optional.

这有点棘手,因为VpcConfig对象具有两个属性:SecurityGroupIds和SubnetIds.并且两者都是必需的.因此,用户需要输入两个或两个都不输入.如果两者都不输入,则整个VpcConfig对象应该为空或不存在(这应该没问题,因为VpConfig对象本身是可选的).

It's a little tricky, because the VpcConfig object has two properties: SecurityGroupIds and SubnetIds. And both are required. So the user needs to enter both of those or neither of those. If neither are entered, then the whole VpcConfig object should be empty, or not exist (which should be okay, since the VpConfig object itself is optional).

这是我现在的截断版本,但这还不够,因为我仍然收到错误消息,说SecurityGroupIds和SubnetIds不能有空值,因为只要对象存在于VpcConfig属性中,它们都是必需的:

Here's a truncated version of what I have now, but it's not enough since I still get errors saying that SecurityGroupIds and SubnetIds can't have empty values, because they're required as long as the object is present in the VpcConfig property:

"Conditions": {
        "HasSecurityGroups": {"Fn::Not": [{"Fn::Equals": [{"Fn::Join": ["", {"Ref": "SecurityGroupIds"}]}, ""]}]},
        "HasSubnetIds": {"Fn::Not": [{"Fn::Equals": [{"Fn::Join": ["", {"Ref": "SubnetIds"}]}, ""]}]}
      },

,然后在Lambda资源中:

and then in the Lambda resource:

"VpcConfig" : {
          "SecurityGroupIds" : {"Fn::If": ["HasSecurityGroups", {"Ref": "SecurityGroupIds"}, {"Ref": "AWS::NoValue"}]},
          "SubnetIds" : {"Fn::If": ["HasSubnetIds", {"Ref": "SubnetIds"}, {"Ref": "AWS::NoValue"}]}
        },

这是整个模板,如果有帮助的话:

Here's the entire template, if that's helpful:

 {
  "AWSTemplateFormatVersion" : "2010-09-09",

  "Description" : "Lambda template for testing purposes",

  "Parameters" : {
    "S3BucketName" : {
      "Type" : "String",
      "Description" : "The name of the Amazon S3 bucket where the .zip file that contains your deployment package is stored."
    },
    "S3FileLocation" : {
      "Type" : "String",
      "Description" : "The location and name of the .zip file that contains your source code."
    },
    "S3ObjectVersion" : {
      "Type" : "String",
      "Description" : "If you have S3 versioning enabled, the version ID of the zip file that contains your source code."
    },
    "DeadLetterArn" : {
      "Type" : "String",
      "Description" : "ARN that specifies a Dead Letter Queue (DLQ) that Lambda sends events to when it can't process them. For example, you can send unprocessed events to an Amazon Simple Notification Service (Amazon SNS) topic, where you can take further action."
    },
    "EnvironmentVariable" : {
      "Type" : "String",
      "Default" : "test",
      "Description" : "Environment Variable"
    },
    "KmsKeyArn" : {
      "Type" : "String",
      "Description" : "KMS Key ARN if environment variables are encrypted"
    },
    "HandlerFunctionName" : {
      "Type" : "String",
      "Description" : "Name of function to initiate the Lambda"
    },
    "MemorySize" : {
      "Type" : "Number",
      "Description" : "Number of MB to allocate to the Lambda function",
      "ConstraintDescription" : "Multiples of 64, between 128 and 3008",
      "MinValue" : "128",
      "Default" : "128"
    },
    "SecurityGroupIds" : {
      "Type" : "CommaDelimitedList",
      "Description" : "A list of one or more security groups IDs in the VPC that includes the resources to which your Lambda function requires access."
    },
    "SubnetIds" : {
      "Type" : "CommaDelimitedList",
      "Description" : "A list of one or more subnet IDs in the VPC that includes the resources to which your Lambda function requires access."
    },
    "Role" : {
      "Type" : "String",
      "Description" : "ARN of Lambda Role"
    },
    "FuncName" : {
      "Type" : "String",
      "Description" : "Name of the the new Lambda function?"
    }
  },

  "Conditions": {
    "HasSecurityGroups": {"Fn::Not": [{"Fn::Equals": [{"Fn::Join": ["", {"Ref": "SecurityGroupIds"}]}, ""]}]},
    "HasSubnetIds": {"Fn::Not": [{"Fn::Equals": [{"Fn::Join": ["", {"Ref": "SubnetIds"}]}, ""]}]}
  },

  "Resources" : {

    "LambdaFunction" : {
      "Type" : "AWS::Lambda::Function",
      "Properties" : {
        "Code" : {
          "S3Bucket" : { "Ref" : "S3BucketName" },
          "S3Key" : { "Ref" : "S3FileLocation" },
          "S3ObjectVersion" : { "Ref" : "S3ObjectVersion" }
        },
        "DeadLetterConfig" : {
          "TargetArn" : { "Ref" : "DeadLetterArn" }
        },
        "Description" : "Lambda",
        "Environment" : {
          "Variables" : {
            "SomeVariable": {
              "Ref" : "EnvironmentVariable"
            }  
          }
        },
        "FunctionName" : { "Ref" : "FuncName" },
        "Handler" : { "Ref" : "HandlerFunctionName" },
        "KmsKeyArn" : { "Ref" : "KmsKeyArn" },
        "MemorySize" : { "Ref" : "MemorySize" },
        "Role" : { "Ref" : "Role" },
        "Runtime" : "python3.6",
        "VpcConfig" : {
          "SecurityGroupIds" : {"Fn::If": ["HasSecurityGroups", {"Ref": "SecurityGroupIds"}, {"Ref": "AWS::NoValue"}]},
          "SubnetIds" : {"Fn::If": ["HasSubnetIds", {"Ref": "SubnetIds"}, {"Ref": "AWS::NoValue"}]}
        },
        "Tags" : [ {
          "Key" : "test",
          "Value" : "true"
        } ]
      }
    }
  },
  "Outputs" : {
    "LambdaFunction" : {
      "Description" : "Lambda function",
      "Value" : { "Ref" : "LambdaFunction" },
      "Export" : {
        "Name" : {"Fn::Sub": "${AWS::StackName}-Lambda" }
      }
    }
  }
}

更新:水泥砌块在下面发布的答案适用于AWS GUI控制台,但是不幸的是,如果尝试使用CLI部署模板,它仍然会遇到相同的问题.我在下面的链接上创建了一个新问题,以单独解决此问题,因为我认为他的回答将为大多数引用此帖子的人提供帮助.

Update: the answer posted below by cementblocks works for the AWS GUI Console, but unfortunately it's still hitting the same issue if you try to deploy the template using the CLI. I've created a new question at the link below to address this issue separately, since I imagine his answer will do the trick for most people who reference this post.

使用AWS CLI启动CloudFormation时的可选参数模板

推荐答案

创建第三个条件HasVPC,当使用Fn::And的HasSecurityGroups和HasSubnetIds都为true时,它应该为true.您将必须复制条件语句;您不能在其他条件下引用.

Create a 3rd condition HasVPC it should be true when HasSecurityGroups and HasSubnetIds are both true using Fn::And. You will have to duplicate the condition statement; you can't reference on condition in another.

然后使用Fn::If

"VpcConfig": {
  "Fn::If": [
    "HasVPC",
    {
      "SecurityGroupIds" : {"Ref": "SecurityGroupIds"},
      "SubnetIds" : {"Ref": "SubnetIds"}
    },
    { "Ref":"AWS::NoValue" }
  ]
}

然后可以删除HasSecurityGroupsHasSubnetIds条件,除非您在其他地方使用它们.

You can remove the HasSecurityGroups and HasSubnetIds conditions then unless you use them elsewhere.

这篇关于如何使CloudFormation模板中的整个对象可选?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆