使用Cloudformation在S3存储桶内创建文件夹。

37
我可以使用CloudFormation创建一个S3存储桶,但我想在S3存储桶内创建一个文件夹,就像这样。
<mybucket>--><myfolder>

请告诉我在存储桶中创建文件夹所需使用的模板...两者应同时创建...
我正在使用以下AWS Lambda。
stackname = 'myStack'
client = boto3.client('cloudformation')
response = client.create_stack(
    StackName= (stackname),
    TemplateURL= 'https://s3.amazonaws.com/<myS3bucket>/<myfolder>/nestedstack.json',
    Parameters=<params>
)
5个回答

34
AWS没有提供官方的CloudFormation资源来创建S3存储桶内的对象。但是,您可以使用AWS SDK创建一个基于Lambda的自定义资源来执行此功能,实际上gilt/cloudformation-helpers GitHub存储库提供了一个现成的自定义资源来完成这个任务。
与任何自定义资源一样,设置有点冗长,因为您需要首先部署Lambda函数和IAM权限,然后在堆栈模板中将其作为自定义资源引用。
首先,在堆栈模板中添加Lambda :: Function和相关的IAM :: Role资源:
"S3PutObjectFunctionRole": {
  "Type": "AWS::IAM::Role",
  "Properties": {
    "AssumeRolePolicyDocument": {
      "Version" : "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": [ "lambda.amazonaws.com" ]
          },
          "Action": [ "sts:AssumeRole" ]
        }
      ]
    },
    "ManagedPolicyArns": [
      { "Ref": "RoleBasePolicy" }
    ],
    "Policies": [
      {
        "PolicyName": "S3Writer",
        "PolicyDocument": {
          "Version" : "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "s3:DeleteObject",
                "s3:ListBucket",
                "s3:PutObject"
              ],
              "Resource": "*"
            }
          ]
        }
      }
    ]
  }
},
"S3PutObjectFunction": {
  "Type": "AWS::Lambda::Function",
  "Properties": {
    "Code": {
      "S3Bucket": "com.gilt.public.backoffice",
      "S3Key": "lambda_functions/cloudformation-helpers.zip"
    },
    "Description": "Used to put objects into S3.",
    "Handler": "aws/s3.putObject",
    "Role": {"Fn::GetAtt" : [ "S3PutObjectFunctionRole", "Arn" ] },
    "Runtime": "nodejs",
    "Timeout": 30
  },
  "DependsOn": [
    "S3PutObjectFunctionRole"
  ]
},

然后,您可以将Lambda函数用作自定义资源来创建S3对象:
"MyFolder": {
  "Type": "Custom::S3PutObject",
  "Properties": {
    "ServiceToken": { "Fn::GetAtt" : ["S3PutObjectFunction", "Arn"] },
    "Bucket": "mybucket",
    "Key": "myfolder/"
  }
},

您也可以使用相同的自定义资源来编写基于字符串的S3对象,只需在BucketKey之外添加一个Body参数即可(请参阅文档)。


24

使用 AWS CloudFormation 模板无法实现这一点。

需要注意的是,Amazon S3 中实际上不存在文件夹。相反,对象的路径会被添加到对象的名称(key)前面。

因此,在名为 foo 的文件夹中存储的文件bar.txt 实际上使用键 foo/bar.txt 存储。

您也可以将文件复制到不存在的文件夹中,该文件夹将自动创建(但实际上并不存在)。然而,管理控制台将提供这样一个文件夹的外观,并且路径将表明它存储在这样一个文件夹中。

底线:没有必要预先创建一个文件夹。就像它已经存在一样使用即可。


1
实际上我需要从Lambda函数中调用存放在S3存储桶下文件夹内的CloudFormation JSON文件,如果不需要事先创建文件夹,我该把JSON文件放在哪里? - shiv455
请问您能否提供更多关于您实际需求的信息(例如,您所说的“调用CloudFormation JSON”是什么意思)?最好的方法是通过更新原始问题,提供您尝试过的示例以及遇到的问题。 - John Rotenstein
我更新了我的问题,请检查!!!..我正在尝试使用AWS Lambda创建多个资源(SNS、EC2等),它调用create_stack API,其中nestedstack.json是其中一个参数.... - shiv455
我想把nestedstack.json放在S3存储桶中的一个文件夹里。 - shiv455
4
你没有说明你打算如何把文件放在那里,但答案是...把它放在那里!如果你将一个文件复制到路径为"templates/nestedstack.json"的存储桶中,那么这将成为对象的名称(Key),它“看起来”像是在一个文件夹中,但实际上不是。不需要预先创建文件夹--只需存储文件即可正常工作。 - John Rotenstein
显示剩余4条评论

1

目前我们无法在S3存储桶内创建子文件夹。

您可以尝试使用以下命令:

 aws s3 mb s3://yavdhesh-bucket/inside-folder

然后尝试使用命令列出存储桶中的所有文件夹:

aws s3 ls s3://yavdhesh-bucket

您会发现子文件夹并未创建。

只有一种方法可以创建子文件夹,那就是在不存在的子文件夹或子目录(相对于存储桶)中创建/复制文件。

例如:

aws s3 cp demo.txt s3://yavdhesh-bucket/inside-folder/

现在,如果您列出子文件夹中存在的文件,它应该可以工作。
 aws s3 ls s3://yavdhesh-bucket/inside-folder/

它应该列出此子文件夹中存在的所有文件。

enter image description here

希望它有所帮助。

0

0

最终我写了一个小的Python脚本。虽然需要手动运行,但它可以自动同步。这是为那些不想创建Lambda支持的自定义资源的懒人准备的。

import subprocess
import json

STACK_NAME = ...
S3_RESOURCE = <name of your s3 resource, as in CloudFormation template file>
LOCAL_DIR = <path of your local dir>

res = subprocess.run(
    ['aws', 'cloudformation', 'describe-stack-resource', '--stack-name', STACK_NAME, '--logical-resource-id', S3_RESOURCE],
    capture_output=True,
)
out = res.stdout.decode('utf-8')
resource_details = json.loads(out)
resource_id = resource_details['StackResourceDetail']['PhysicalResourceId']

res = subprocess.run(
    ['aws', 's3', 'sync', LOCAL_DIR, f's3://{resource_id}/', '--acl', 'public-read']
)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接