PulumiTypeScript,AWS:如何将多个文件上传到 S3,包括静态网站托管目录中的嵌套文件

问题描述

Create an AWS S3 Website in Under 5 Minutes YT videoHost a Static Website on Amazon S3 Pulumi tutorial 中有很好的解释如何使用 Pulumi 在 S3 上创建网站托管。

在示例代码中使用了 Pulumi 的 BucketBucketObject。第一个创建一个 S3 存储桶,后者创建对象,这些对象主要是用于公共访问的 index.html,如下所示:

const aws = require("@pulumi/aws");
const pulumi = require("@pulumi/pulumi");
const mime = require("mime");

// Create an S3 bucket
let siteBucket = new aws.s3.Bucket("s3-website-bucket");

let siteDir = "www"; // directory for content files

// For each file in the directory,create an S3 object stored in `siteBucket`
for (let item of require("fs").readdirsync(siteDir)) {
    let filePath = require("path").join(siteDir,item);
    let object = new aws.s3.Bucketobject(item,{
      bucket: siteBucket,source: new pulumi.asset.FileAsset(filePath),// use FileAsset to point to a file
      contentType: mime.getType(filePath) || undefined,// set the MIME type of the file
    });
}

exports.bucketName = siteBucket.bucket; // create a stack export for bucket name

现在使用基于 Vue.js / Nuxt.js 的应用程序,我需要上传多个生成文件,这些文件位于我的项目根目录的 dist 目录中。它们由 npm run build 生成生成以下文件

$ find dist
dist
dist/favicon.ico
dist/index.html
dist/.nojekyll
dist/200.html
dist/_nuxt
dist/_nuxt/LICENSES
dist/_nuxt/static
dist/_nuxt/static/1619685747
dist/_nuxt/static/1619685747/manifest.js
dist/_nuxt/static/1619685747/payload.js
dist/_nuxt/f3a11f3.js
dist/_nuxt/f179782.js
dist/_nuxt/fonts
dist/_nuxt/fonts/element-icons.4520188.ttf
dist/_nuxt/fonts/element-icons.313f7da.woff
dist/_nuxt/c25b1a7.js
dist/_nuxt/84fe6d0.js
dist/_nuxt/a93ae32.js
dist/_nuxt/7b77d06.js

我的问题是这些文件还包含嵌套在子目录中的文件,子目录本身也可以是子目录 - 例如dist/_nuxt/fonts/element-icons.4520188.ttf。教程中提供的方法不评估子目录,我不知道如何使用 Pulumi/TypeScript。

解决方法

我继续采用该方法并尝试构建递归 TypeScript 函数,该函数根据教程推荐的 Pulumi 的 BucketObject 创建文件或目录。 这让我陷入了复杂的困境!我需要使用 BucketObject 创建目录,使用 "/" 参数 (see this answer) 中附加的 key 可以实现。只是为了记录,它的功能看起来像这样:

function createS3BucketFolder(dirName: string) {
  new aws.s3.BucketObject(dirName,{
    bucket: nuxtBucket,acl: "public-read",key: dirName + "/",// an appended '/' will create a S3 Bucket prefix (see https://stackoverflow.com/a/57479653/4964553)
    contentType: "application/x-directory" // this content type is also needed for the S3 Bucket prefix
    // no source needed here!
  })
}

但这只是使用 TypeScript 递归遍历目录所需的大量代码中的一小部分(另请参阅 this huge amount of so answers on the topic,从同步版本到疯狂的 Node.js 11+ 异步解决方案)。我最终得到了大约 40-50 行代码,仅用于将静态站点生成的文件递归添加到 S3 - 感觉不太好,没有对此进行测试(我真的不明白,为什么Pulumi 不会support that use case somehow like Terraform)。

最后,我偶然发现了关于 Secure Static Website Using Amazon S3,CloudFront,Route53,and Certificate Manager 的 Pulumi 教程,其中有 a special paragraph about deployment speed 并附有一段有趣的引用:

此示例为从提供的每个文件创建一个 aws.S3.BucketObject 网站。在部署大型网站时,这可能会导致很长时间 检查每个单独的文件是否有任何更改时更新。 可能 更有效地不使用 Pulumi 和和 而只是使用 AWS CLI 将本地文件与 S3 存储桶同步 直接。

TLDR:对于非 hello world 用例,Pulumi 文档告诉我们不要使用 Pulumi 将文件上传到 S3,而是使用 AWS CLI!所以我重新编写了我的代码,只使用 Pulumi 创建 S3 Bucket,如下所示:

import * as aws from "@pulumi/aws";

// Create an AWS resource (S3 Bucket)
const nuxtBucket = new aws.s3.Bucket("microservice-ui-nuxt-js-hosting-bucket",{
  acl: "public-read",website: {
    indexDocument: "index.html",}
});

// Export the name of the bucket
export const bucketName = nuxtBucket.id;

这将创建一个启用静态站点托管的 S3 存储桶,并通过 Pulumi 访问 public-read。现在使用 AWS CLI,我们可以使用以下命令优雅地将文件复制/同步到存储桶:

aws s3 sync ../dist/ s3://$(pulumi stack output bucketName) --acl public-read

使用 $(pulumi stack output bucketName) 我们只需获取由 Pulumi 创建的 S3 存储桶名称。请注意最后的 --acl public-read 参数,因为您必须对 S3 中的每个静态 Web 文件启用公共读取访问权限,尽管 Bucket 本身已经具有公共读取访问权限!

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...