【问题标题】:create folder inside S3 bucket using Cloudformation使用 Cloudformation 在 S3 存储桶内创建文件夹
【发布时间】:2016-08-23 09:52:18
【问题描述】:

我可以使用 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>
)

【问题讨论】:

    标签: amazon-s3 amazon-cloudformation


    【解决方案1】:

    使用 AWS CloudFormation 模板无法做到这一点。

    需要指出的是,文件夹实际上并不存在于 Amazon S3 中。而是将对象的路径添加到对象的名称 (key) 之前。

    因此,存储在名为foo 的文件夹中的文件bar.txt 实际上存储的密钥为:foo/bar.txt

    您还可以将文件复制到不存在的文件夹中,并且该文件夹将被自动创建(实际上并非如此,因为该文件夹本身不存在)。但是,管理控制台会提供此类文件夹的外观,并且路径会提示它存储在此类文件夹中。

    底线:无需预先创建文件夹。就像它已经存在一样使用它。

    【讨论】:

    • 实际上我需要从 Lambda 函数调用放置在 S3 存储桶下的文件夹中的 cloudformation jsons...所以如果不需要预先创建文件夹,我应该将我的 jsons 放在哪里???跨度>
    • 您能否提供更多关于您的实际需求的信息(例如,“调用 cloudformation jsons”是什么意思)?最好的方法是用您尝试过的方法和遇到的问题的示例来更新原始问题。
    • 更新了我的问题,请检查!!!..我正在尝试使用调用 create_stack api 的 AWS lambda 创建多个资源(SNS、EC2 等),其中nestedstack.json 是参数之一。 ..
    • 我想将 nestedstack.json 放在 s3 存储桶中的文件夹中
    • 您还没有解释您打算如何将文件放在那里,但答案是......放在那里!如果您使用“templates/nestedstack.json”之类的路径将文件复制到存储桶,则该文件将成为对象的名称(键)。它“看起来”就像它在一个文件夹中,但它不是。无需预先创建文件夹 - 只需存储文件即可。
    【解决方案2】:

    AWS 不提供官方 CloudFormation 资源来在 S3 存储桶中创建对象。但是,您可以创建一个 Lambda-backed Custom Resource 来使用 AWS 开发工具包执行此功能,事实上,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/"
      }
    },
    

    除了BucketKey(参见docs)之外,您还可以通过添加Body 参数来使用相同的自定义资源来编写基于字符串的S3 对象。

    【讨论】:

      【解决方案3】:

      我们不能(至少现在)在 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/
      

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

      希望对你有帮助。

      【讨论】:

        【解决方案4】:

        我最终得到了一个小的 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']
        )
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-07-29
          • 2020-10-28
          • 2016-12-09
          • 1970-01-01
          • 2016-12-22
          • 1970-01-01
          • 2021-09-17
          相关资源
          最近更新 更多