CloudFormation:如果资源不存在,则创建它们,但不要删除它们 [英] CloudFormation: Create resources if they do not exist, but do not delete them

查看:67
本文介绍了CloudFormation:如果资源不存在,则创建它们,但不要删除它们的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下CloudFormation模板。 (它是基于默认的模板而创建的,该模板是为在AWS Lambda中运行C#Web API而创建的,但这可能不相关。)

I have the following CloudFormation template. (It is based off default the template created for running C# Web API in AWS Lambda, but that may not be relevant.)

它创建一个AWS Lambda函数。如果没有将现有资源的名称作为参数提供,则模板还将创建一个IAM角色和一个DynamoDB表。

It creates an AWS Lambda function. The template also creates an IAM Role and a DynamoDB table if the names of existing resources are not supplied as arguments.

该部分有效。如果没有为角色和表提供名称,则会创建它们。

That part works. If no names are supplied for the role and table, they are created.

当我第二次运行模板以执行更新时,存在问题:

The problem exists when I run the template a second time to perform updates: at this point, my role and table exist, so I provide the names as arguments. However, when CloudFormation runs the second time, the resources it created the first time (the role and table) are deleted.

是否有一些设置方法模板,以便在不存在的情况下创建新资源,而在不存在的情况下不删除它们?

我还没有做过CloudFormation的使用很多,但是我确实浏览了文档。我找到的最接近的是设置堆栈策略 ,但它似乎不是模板的一部分。事实看来,我将不得不在管理控制台中执行此操作。

I haven't done a lot with CloudFormation, but I did go through the documentation. The closest I found was setting a stack policy, but it doesn't seem to be part of the template. It looks like I would have to do this in the management console after the fact.

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Transform" : "AWS::Serverless-2016-10-31",
  "Description" : "...",

  "Parameters" : {
    "ShouldCreateTable" : {
      "Type" : "String",        
      "AllowedValues" : ["true", "false"],
      "Description" : "If true then the underlying DynamoDB table will be created with the CloudFormation stack."
    },  
    "TableName" : {
        "Type" : "String",
        "Description" : "Name of DynamoDB table to be used for underlying data store. If left blank a new table will be created.",
        "MinLength" : "0"
    },
    "ShouldCreateRole" : {
      "Type" : "String",        
      "AllowedValues" : ["true", "false"],
      "Description" : "If true then the role for the Lambda function will be created with the CloudFormation stack."
    },  
    "RoleARN" : {
        "Type" : "String",
        "Description" : "ARN of the IAM Role used to run the Lambda function. If left blank a new role will be created.",
        "MinLength" : "0"
    }
  },

  "Conditions" : {
    "CreateDynamoTable" : {"Fn::Equals" : [{"Ref" : "ShouldCreateTable"}, "true"]},
    "TableNameGenerated" : {"Fn::Equals" : [{"Ref" : "TableName"}, ""]},
    "CreateRole":{"Fn::Equals" : [{"Ref" : "ShouldCreateRole"}, "true"]},
    "RoleGenerated" : {"Fn::Equals" : [{"Ref" : "RoleARN"}, ""]}
  },

  "Resources" : {

    "Get" : {
      "Type" : "AWS::Serverless::Function",
      "Properties": {
        ...
        "Role": {"Fn::If" : ["CreateRole", {"Fn::GetAtt":["LambdaRole", "Arn"]}, {"Ref":"RoleARN"}]},
        "Environment" : {
          "Variables" : {
            "AppDynamoTable" : { "Fn::If" : ["CreateDynamoTable", {"Ref":"DynamoTable"}, { "Ref" : "TableName" } ] }
          }
        },
        ...
      }
    },

    "LambdaRole":{
        "Type":"AWS::IAM::Role",
        "Condition":"CreateRole",
        "Properties":{
            "ManagedPolicyArns":["arn:aws:iam::aws:policy/AWSLambdaFullAccess"],
            "AssumeRolePolicyDocument": {
               "Version" : "2012-10-17",
               "Statement": [ {
                  "Effect": "Allow",
                  "Principal": {
                     "Service": [ "lambda.amazonaws.com" ]
                  },
                  "Action": [ "sts:AssumeRole" ]
               } ]
            },
            "Policies": [  {
                "PolicyName": "root",
                "PolicyDocument": {
                        "Version": "2012-10-17",
                        "Statement": [
                            {
                                "Effect": "Allow",
                                "Action": [
                                    "dynamodb:Query",
                                    "dynamodb:Scan",
                                    "dynamodb:PutItem",
                                    "dynamodb:GetItem",
                                    "dynamodb:UpdateItem",
                                    "dynamodb:DeleteItem",
                                    "logs:CreateLogGroup",
                                    "logs:CreateLogStream",
                                    "logs:PutLogEvents"
                                ],
                                "Resource": [
                                    "*"
                                ]
                            }
                        ]
                    }
                }
            ]
        }
    },

    "DynamoTable" : {
        "Type" : "AWS::DynamoDB::Table",
        "Condition" : "CreateDynamoTable",
        "Properties" : {
            "TableName" : { "Fn::If" : ["TableNameGenerated", {"Ref" : "AWS::NoValue" }, { "Ref" : "TableName" } ] },
            "AttributeDefinitions": [
                { "AttributeName" : "id", "AttributeType" : "S" }
            ],
            "KeySchema" : [
                { "AttributeName" : "id", "KeyType" : "HASH"}
            ],          
            "ProvisionedThroughput" : { "ReadCapacityUnits" : "5", "WriteCapacityUnits" : "5" }
        }
    }
  },

  "Outputs" : {
    "UnderlyingDynamoTable" : {
        "Value" : { "Fn::If" : ["CreateDynamoTable", {"Ref":"DynamoTable"}, { "Ref" : "TableName" } ] }
    },
    "LambdaRole" : {
        "Value" : {"Fn::If" : ["CreateRole", {"Fn::GetAtt":["LambdaRole", "Arn"]}, {"Ref":"RoleARN"} ] }
    }
  }
}

我可以删除创建步骤并手动创建资源在API网关之前,但似乎应该可以实现。

I could just remove the creation step and create the resource manually before the API Gateway, but it seems like what I am trying to do should be possible.

推荐答案

在更新现有的堆栈,请勿更改参数。因此,即使在更新堆栈时,也将 ShouldCreateTable 设置为 true

When you are updating your existing stack, do not change the parameters. So even when you are updating your stack, set ShouldCreateTable to true.

是的,当表已经存在时,更新堆栈以显示创建表时,这似乎违反直觉,但是您需要这样做。

Yes, it seems counter-intuitive when updating your stack to say "Create a table", when a table already exists, but you need to do that.

原因如下:


  1. 创建堆栈时,设置 ShouldCreateTable 设为 true ,模板将使用其条件逻辑并创建表作为其自己的托管资源。

  2. 更新堆栈时,将 ShouldCreateTable 设置为 false ,模板将使用它的条件逻辑并确定您不再需要托管表,因为您现在提供自己的。该资源应删除。它不能识别表是否相同。

  1. When the stack is created, you set ShouldCreateTable to true, and the template applies it's conditional logic and creates the table as it's own managed resource.
  2. When the stack is updated, you set ShouldCreateTable to false, and the template applies it's conditional logic and determines you no longer need the managed table because you're providing your own now. The resource should be deleted. It does not recognize that the table is the same.

使用模板时,只说 ShouldCreateTable == false 如果要提供自己创建的表

When using your template, only say ShouldCreateTable == false if you are providing your own table that you created.

这篇关于CloudFormation:如果资源不存在,则创建它们,但不要删除它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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