簡體   English   中英

如何使CloudFormation模板中的整個對象可選?

[英]How to make a whole object in CloudFormation templates optional?

我正在通過CloudFormation模板制作Lambda函數,並且希望使其可選以輸入VpcConfig屬性的信息。 我發現了這樣的文章,介紹如何使參數可選:

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

這對於查找語法以使具有單個值的屬性為可選(例如單個字符串值)非常有幫助。

但是我需要弄清楚的是如何使整個VpcConfig OBJECT可選。

這有點棘手,因為VpcConfig對象具有兩個屬性:SecurityGroupIds和SubnetIds。 並且兩者都是必需的。 因此,用戶需要輸入兩個或兩個都不輸入。 如果兩者都不輸入,則整個VpcConfig對象應該為空或不存在(這可以,因為VpConfig對象本身是可選的)。

這是我現在的截斷版本,但這還不夠,因為我仍然收到錯誤消息,說SecurityGroupIds和SubnetIds不能有空值,因為只要對象存在於VpcConfig屬性中,它們都是必需的:

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

然后在Lambda資源中:

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

這是整個模板,如果有幫助的話:

 {
  "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" }
      }
    }
  }
}

更新 :cementblocks在下面發布的答案適用於AWS GUI控制台,但是不幸的是,如果嘗試使用CLI部署模板,它仍然會遇到相同的問題。 我在下面的鏈接中創建了一個新問題,以單獨解決此問題,因為我認為他的回答將為大多數引用此帖子的人提供幫助。

使用AWS CLI啟動CloudFormation模板時的可選參數

創建第三個條件HasVPC ,當使用Fn::And HasSecurityGroups和HasSubnetIds均為true時,它應該為true。 您將必須復制條件語句; 您不能在其他條件下引用。

然后使用Fn::If設置vpcConfig屬性

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

然后可以刪除HasSecurityGroupsHasSubnetIds條件,除非在其他地方使用它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM