2016-01-05 21 views
10

Nhiệm vụ tôi cần làm là CDN phải phụ thuộc vào nhóm S3, nhưng chúng tôi cũng có thể sử dụng nhóm hiện có thay vì tạo nhóm mới.CloudFormation, áp dụng Điều kiện trên DependsOn

Dưới đây là đoạn code mẫu mà tôi đang chiến đấu với:

"Parameters" : { 
    "UseExistingBucket" : { 
    "Description" : "Yes/No", 
    "Default" : "yes", 
    "Type" : "String", 
    "AllowedValues" : [ "yes", "no" ] 
    } 
}, 
"Conditions" : { 
    "CreateS3Resources" : {"Fn::Equals" : [{"Ref" : "UseExistingBucket"}, "no"]} 
}, 
"Resources" : { 
    "StaticBucket" : { 
    "Type" : "AWS::S3::Bucket", 
    "Condition" : "CreateS3Resources", 
    "Properties" : { 
     "BucketName" : { "Fn::Join": [ "-", [ "app", { "Ref": "EnvType" }, "static" ] ] } 
    }, 
    "DeletionPolicy": "Retain" 
    }, 
    "MyStaticDistribution": { 
    "Type": "AWS::CloudFront::Distribution", 
    "Properties": { 
     "DistributionConfig": { 
     "Origins": [ 
      { 
      "DomainName": { 
       "Fn::If" : [ 
       "CreateS3Resources", 
       { "Fn::Join": [ "-", [ "app", { "Ref": "EnvType" }, "static" ] ] }, 
       {"Fn::GetAtt": [ "StaticBucket", "DomainName" ] } 
       ] 
      }, 
      "Id": "S3Origin", 
      } 
     ] 
     } 
    }, 
    "DependsOn": [{ 
     "Fn::If" : [ 
     "CreateS3Resources", 
     { "Fn::Join": [ "-", [ "app", { "Ref": "EnvType" }, "static" ] ] }, 
     "" 
     ] 
    }] 
    } 
} 

Xin gợi ý cho tôi nhiều hơn bất kỳ chi tiết nếu cần thiết (ít nhất stackoverflow không muốn biết thêm chi tiết, nhưng không chỉ định bất kỳ :-P)

Trả lời

0

Tôi đang chiến đấu cùng một điều. Lỗi này là:

A client error (ValidationError) occurred when calling the ValidateTemplate operation: Template format error: DependsOn must be a string or list of strings.

Dường như không thể đặt điều kiện trong DependsOn.

Tôi bắt đầu xem xét các cách khác để thể hiện nó. Có thể đặt mã phụ thuộc vào 2 mẫu con khác nhau. Phát hiện tình trạng bên ngoài và chuyển tên mẫu lồng nhau thích hợp vào thông số mẫu chính. Do đó DependsOn xem thông số mà tôi truyền vào dưới dạng mẫu phụ thuộc.

Có vẻ như logic quá méo mó.

Phải là cách tốt hơn.

7

Bạn có thể thực hiện việc này bằng cách sử dụng Fn:GetAtt được bao bọc trong điều kiện Fn:If. Sử dụng Fn: GetAtt ngụ ý sự phụ thuộc, do đó CloudFormation sẽ tự động chờ khi nó đạt đến chức năng đó, giống như khi bạn đang sử dụng DependsOn.

Ví dụ

Đoạn mã dưới đây cho thấy điều này bằng cách có điều kiện lấy tên của một chồng lồng nhau mà vẫn chưa được tạo ra nhưng chỉ làm như vậy nếu UseNestedStack điều kiện được thiết lập là true. Nếu UseNestedStack là false, nó sẽ không đợi và thay vào đó lấy một tên biến cục bộ.

{ 
"Fn::If": ["UseNestedStack", { 
    "Fn::GetAtt": ["NestedStack", "Outputs.Name"] 
}, { 
    "Ref": "LocalName" 
}] 

Tôi làm cách nào để biết điều này? (Ví dụ khác)

Thật không may là không có tài liệu chính thức nào chính thức nêu điều này, nhưng AWS đã bảo tôi làm theo cách này và trong ví dụ mã của họ, bạn có thể thấy khi đặt hàng họ sử dụng Fn: GetAtt. Tôi đã thử nhiều lần và nó hoạt động mọi lúc. Hãy thử nó trên một chồng đơn giản. Dưới đây là một số bằng chứng giả từ một ví dụ AWS lambda mà tôi tinh chỉnh và đã sử dụng bản thân mình. Ngăn xếp dưới đây có thể không hoạt động nếu chức năng AMI được tạo sau thông tin AMI tài nguyên, AMI Info cần đầu ra của hàm AMI, vì vậy AWS đã ghép chúng lại với nhau bằng Fn: GetAtt. Để xem cuộn này ở phía dưới và nhìn vào tài nguyên AMIInfo và bạn sẽ thấy nó tham chiếu AMIFunction qua fn: Gett. CloudFormation thấy điều này và quay trở lại AMIFunction để tạo nó trước.

"AMIInfoFunction": { 
    "DependsOn":"SourceStack", 
    "Type": "AWS::Lambda::Function", 
    "Properties": { 
    "Code": { 
     "S3Bucket": { "Ref": "DeploymentBucket" }, 
     "S3Key": {"Fn::Join": [ 
     "", 
     [ 
      { 
      "Ref": "ApplicationName" 
      }, 
      "/amilookup.zip" 
     ] 
     ]} 
    }, 
    "Handler": "amilookup.handler", 
    "Runtime": "nodejs", 
    "Timeout": "30", 
    "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] }, 
    "VpcConfig": { 
     "SecurityGroupIds": [ {"Ref": "InstanceSecurityGroup"}], 
     "SubnetIds": [ {"Ref":"PrivateSubnetA"},{"Ref":"PrivateSubnetB"} ] 
    } 
    } 
}, 
"AMIInfo": { 
    "Type": "Custom::AMIInfo", 
    "Properties": { 
    "ServiceToken": { "Fn::GetAtt" : ["AMIInfoFunction", "Arn"] }, 
    "StackName": { "Ref":"SourceStack" } 
    } 
} 
+0

Có tài liệu ở đâu đó rằng nói rằng GetAtt sẽ tự động chờ đợi cho các nguồn lực khác được hoàn thành trước khi di chuyển về phía trước? – doeiqts

+2

@doeiqts Câu hỏi hay. Thật không may là tôi đã không nhìn thấy nó tài liệu nhưng tôi tin tưởng điều này là đúng từ việc sử dụng nó trong ví dụ AWS, thực tế là tôi đã nhìn thấy nó làm việc nhiều lần, và từ các kỹ sư AWS hướng dẫn tôi làm theo cách này. Tôi đã thêm một ví dụ lambda từ AWS, trong đó họ trì hoãn việc tạo ra theo cách này. Nhưng có một số tài liệu chính thức sẽ được sạch hơn. –

0

Trong mẫu của bạn, bạn không cần phải thêm thuộc tính DependsOn vào tài nguyên MyStaticDistribution khi bạn đã có tham chiếu đến tài nguyên StaticBucket.

này được diễn tả trong Quy định rõ Dependencies phần của bài đăng blog Optimize AWS CloudFormation Templates: https://aws.amazon.com/blogs/devops/optimize-aws-cloudformation-templates/

When you need CloudFormation to wait to provision one resource until another one has been provisioned, you can use the DependsOn attribute.

You can also introduce references between elements by using either the { "Ref": "MyResource" } or the { "Fn::GetAtt" : [ "MyResource" , "MyAttribute" ] } functions. When you use one of these functions, CloudFormation behaves as if you’ve added a DependsOn attribute to the resource.

Các vấn đề liên quan