![](/img/trans.png)
[英]how to build, package and deploy AWS SAM lambda function of python from azure Devops CI/CD pipeline to AWS
[英]How to create s3 buckets dynamically in azure devops CI/CD pipeline
我想根据 yaml 文件之一中提到的数据,通过 CI/CD 管道自动创建存储桶的过程。 所以,我有 bucket.yaml 文件,其中包含所有存储桶的名称。 随着将来添加更多存储桶名称,此文件会不断更改。 目前,这就是 bucket.yaml 的样子
BucketName:
- test-bucket
- test-bucket2
- test-bucket3
我有一个 template.yaml 文件,它是用于创建 s3 存储桶的 cloudformation 模板。 这是它的外观:
Resources:
S3Bucket:
Type: 'AWS::S3::Bucket'
DeletionPolicy: Retain
Properties:
BucketName: This will come from bucket.yaml
现在,template.yaml 将从 bucket.yaml 文件中获取存储桶名称,并应创建 3 个存储桶,如 bucket.yaml 中所述。 如果有人在 bucket.yaml 中再添加 2 个存储桶,则 template.yaml 也应该创建这 2 个新存储桶。 此外,如果有人从 bucket.yaml 中删除任何存储桶名称,那么这些存储桶也应该被删除。 我在研究中找不到过程,只是找到了零碎的信息。所以,在这里我有一些具体的问题,如果可以的话:
如何从 bucket.yaml 和 template.yaml 中获取存储桶名称应该创建所有存储桶。
在bucket.yaml
,您可以使用参数来设置BucketName
。
例如:
parameters:
- name: BucketName
type: object
default:
- test-bucket
- test-bucket2
- test-bucket3
steps:
- ${{ each value in parameters.BucketName }}:
- script: echo ${{ value }}
此处的步骤可以遍历参数BucketName
的值。
在template.yaml
中,您可以调用bucket.yaml
,如下所示。
trigger:
- main
extends:
template: bucket.yaml
如果有人在 bucket.yaml 中更新/添加/删除存储桶名称,则 template.yaml 应相应地更新这些名称。
没有任何简单的方法可以做到这一点。 您可以尝试编写一个脚本以在管道中运行以执行以下操作:
BucketName
的值列表进行比较,检查哪些存储桶需要添加,哪些存储桶需要删除。BucketName:
- test-bucket
- test-bucket2
- test-bucket3
这些要求意味着所有 S3 存储桶都将以相同的方式创建,并且不需要偏离给定的 Cloudformation 模板 ( AWS::S3::Bucket
)。
这些要求要求我们跟踪需要删除哪些 S3 存储桶。 Cloudformation 不会删除 S3 存储桶,因为 Cloudformation 模板片段包含保留的DeletionPolicy 。
解决方案:
可以以特定方式标记 S3 存储桶,以将它们标识为当前 CI/CD 管道所拥有。 可以列出 S3 存储桶,并以正确的方式标记所有 S3 存储桶,但在存储桶中不存在。然后可以删除bucket.yaml
。
我个人会使用 AWS SDK 创建 CI/CD 管道所需的 S3 存储桶并手动管理 S3 存储桶删除。 如果应用程序需要 S3 存储桶,那么他们应该在其应用程序的 Cloudformation 堆栈中自己创建它,以便他们可以!引用它并按照他们想要的方式对其进行自定义(例如 rest 的加密、版本控制、生命周期规则等)。
技术说明:
要删除 S3 存储桶,还需要删除其内容。 这将要求我们列出 S3 存储桶中的所有对象,然后将其删除。 Java SDK [这里]的一些文档。 只有随后调用 API 才能成功删除 S3 存储桶。
您可以让 Cloudformation 使用自定义资源删除您的 S3 对象。 也就是说,我没有找到有趣的自定义资源 - 所以如果您可以在 CI/CD 管道中使用 AWS SDK,我可能会使用它。
用于删除存储桶内容的自定义资源在 Cloudformation 中可能如下所示:(它是一个自定义资源,类似于 Lambda。如果自定义资源被取消配置,Lambda 将删除 S3 存储桶内容)
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/walkthrough-custom-resources-lambda-lookup-amiids.html
ExampleBucketOperationCustomResource:
Type: AWS::CloudFormation::CustomResource
DependsOn: [Bucket, ExampleBucketOperationLambdaFunction]
Properties:
ServiceToken: !GetAtt ExampleBucketOperationLambdaFunction.Arn
# Custom properties
BucketToUse: !Ref S3BucketName
ExampleBucketOperationLambdaFunctionExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: "ExampleBucketOperationLambda-ExecutionRole"
Path: "/"
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Principal:
Service:
- lambda.amazonaws.com
Policies:
- PolicyName: "ExampleBucketOperationLambda-CanAccessCloudwatchLogs"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
- PolicyName: "ExampleBucketOperationLambda-S3BucketLevelPermissions"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:ListBucket
Resource:
- !Sub "arn:aws:s3:::${S3BucketName}"
- PolicyName: "ExampleBucketOperationLambda-S3ObjectLevelPermissions"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:DeleteObject
- s3:PutObject
Resource:
- !Sub "arn:aws:s3:::${S3BucketName}/*"
# Test payload:
# {"RequestType":"Create","ResourceProperties":{"BucketToUse":"your-bucket-name"}}
ExampleBucketOperationLambdaFunction:
Type: AWS::Lambda::Function
DependsOn: ExampleBucketOperationLambdaFunctionExecutionRole
# DeletionPolicy: Retain
Properties:
FunctionName: "ExampleBucketOperationLambda"
Role: !GetAtt ExampleBucketOperationLambdaFunctionExecutionRole.Arn
Runtime: python3.8
Handler: index.handler
Timeout: 30
Code:
ZipFile: |
import boto3
import cfnresponse
def handler(event, context):
eventType = event["RequestType"]
print("The event type is: " + str(eventType));
bucketToUse = event["ResourceProperties"]["BucketToUse"]
print("The bucket to use: " + str(bucketToUse));
try:
# Requires s3:ListBucket permission
if (eventType in ["Delete"]):
print("Deleting everyting in bucket: " + str(bucketToUse));
s3Client = boto3.client("s3")
s3Bucket = boto3.resource("s3").Bucket(bucketToUse)
for currFile in s3Bucket.objects.all():
print("Deleting file: " + currFile.key);
s3Client.delete_object(Bucket=bucketToUse, Key=currFile.key)
print("All done")
responseData = {}
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
except Exception as e:
responseData = {}
errorDetail = "Exception: " + str(e)
errorDetail = errorDetail + "\n\t More detail can be found in CloudWatch Log Stream: " + context.log_stream_name
print(errorDetail)
cfnresponse.send(event=event, context=context, responseStatus=cfnresponse.FAILED, responseData=responseData, reason=errorDetail)
感谢以上回答。 我采取了不同的方式来解决这个问题。 我使用AWS CDK来实现我真正想要的。 我个人将 AWS CDK 用于 Python 并使用它创建了基础设施。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.