2017-07-17 43 views
1

我有以下的CloudFormation模板。 (这是默认的基于关闭在AWS运行LAMBDA C#的Web API创建的模板,但可能不相关。)CloudFormation:创建资源,如果他们不存在,但不删除它们

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

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

当我第二次运行模板执行更新时存在问题:此时,我的角色和表已存在,因此我提供了名称作为参数。但是,当CloudFormation第二次运行时,首次创建的资源(角色和表)将被删除。

是否有某种方法可以设置模板,使其在不存在的情况下创建新资源,但是如果它们已经存在则不会将其删除?

我没有做很多与CloudFormation,但我没去,可通过文档。我发现的最接近是setting a stack policy,但它似乎并没有成为模板的一部分。看起来事实之后,我必须在管理控制台中执行此操作。

{ 
    "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网关之前手动创建资源,但它似乎像什么,我要做的应该是可能的。

回答

2

当您更新现有堆栈时,请勿更改参数。因此,即使当你更新堆栈,ShouldCreateTabletrue

是的,当一个表已经存在,但你需要这样做时,更新你的堆栈来说“创建表”似乎是违反直觉的。

原因是这样的:

  1. 在创建堆栈,您可以设置ShouldCreateTabletrue,并且模板应用于它的条件逻辑,并创建为它自己的管理资源表。
  2. 更新堆栈时,您将ShouldCreateTable设置为false,并且该模板将其应用于条件逻辑并确定您不再需要托管表,因为您现在正在提供自己的托管表。资源应该被删除。它不承认表格是相同的。

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

相关问题