[小ネタ]Pulumiで指定した名前でS3バケットを作成する

2022.04.01

こんにちは!DA(データアナリティクス)事業本部 サービスソリューション部の大高です。

先日、PulumiのGet Startedを試したのですが、その中で少し気になることがありました。

このエントリでは最終的に以下のようなコードとしており、その中でS3のバケット名も指定しています。

index.ts

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

// Create an AWS resource (S3 Bucket)
const bucket = new aws.s3.Bucket("cm-ootaka-get-started-with-pulumi", {
  website: {
    indexDocument: "index.html",
  },
});

const bucketObject = new aws.s3.BucketObject("index.html", {
  acl: "public-read",
  contentType: "text/html",
  bucket: bucket,
  source: new pulumi.asset.FileAsset("index.html"),
});

// Export the name of the bucket
export const bucketName = bucket.id;
export const bucketEndpoint = pulumi.interpolate`http://${bucket.websiteEndpoint}`;

一方で、このときに実際に作成されたS3バケットは cm-ootaka-get-started-with-pulumi-484d188 でした。

これについて、調査と対応方法を調べてみました。

先に結論

aws.s3.Bucketbucketプロパティを使います。

サフィックス(接尾辞)について

これは、PulumiのFAQにも記載がされています。

To ensure that as many logical Pulumi resources and stacks can be stood up side-by-side without them conflicting, Pulumi automatically creates each resource’s name by combining the logical name with a random suffix appended afterwards.

ここに記載されているとおり、Pulumiで複数のスタックを作成した場合にリソース名の競合が起きないように自動でサフィックスを付けてくれているそうです。

サフィックスを付けたくない!

これはこれで便利な機能なのですが、一方で実際にはサフィックスを付けたくないケースもあります。

このような場合の対応としては、以下に記載のように name プロパティを指定することで指定の名前でリソースを作成することが可能です。

let role = new aws.iam.Role("my-role", {
    name: "my-role-001",
});

一方でS3バケットの場合には、 name プロパティは指定できません。

index.ts

// Create an AWS resource (S3 Bucket)
const bucket = new aws.s3.Bucket("cm-ootaka-get-started-with-pulumi", {
  website: {
    indexDocument: "index.html",
  },
  name: ''
});

上記のようなコードにすると、以下のエラーが表示されます。

型 '{ website: { indexDocument: string; }; name: string; }' の引数を型 'BucketArgs' のパラメーターに割り当てることはできません。
  オブジェクト リテラルは既知のプロパティのみ指定できます。'name' は型 'BucketArgs' に存在しません。ts(2345)

S3バケットの場合には下記のドキュメントにあるようにbucketプロパティを指定します。

従って、コード全体としては以下のようになります。

index.ts

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

// Create an AWS resource (S3 Bucket)
const bucket = new aws.s3.Bucket("cm-ootaka-get-started-with-pulumi", {
  website: {
    indexDocument: "index.html",
  },
  bucket: "cm-ootaka-get-started-with-pulumi",
});

const bucketObject = new aws.s3.BucketObject("index.html", {
  acl: "public-read",
  contentType: "text/html",
  bucket: bucket,
  source: new pulumi.asset.FileAsset("index.html"),
});

// Export the name of the bucket
export const bucketName = bucket.id;
export const bucketEndpoint = pulumi.interpolate`http://${bucket.websiteEndpoint}`;

このコードでpulumi upでデプロイすると、以下のように表示されます。bucketNameがサフィックスが付いていない指定したバケット名になっていますね。

Do you want to perform this update? yes
Updating (dev)

View Live: https://app.pulumi.com/ootaka-daisuke/quickstart/dev/updates/1

     Type                    Name                               Status      Info
 +   pulumi:pulumi:Stack     quickstart-dev                     created     
 +   ├─ aws:s3:Bucket        cm-ootaka-get-started-with-pulumi  created     
 +   └─ aws:s3:BucketObject  index.html                         created     2 warnings
 
Diagnostics:
  aws:s3:BucketObject (index.html):
    warning: urn:pulumi:dev::quickstart::aws:s3/bucketObject:BucketObject::index.html verification warning: Argument is deprecated
    warning: urn:pulumi:dev::quickstart::aws:s3/bucketObject:BucketObject::index.html verification warning: Argument is deprecated
 
Outputs:
    bucketEndpoint: "http://cm-ootaka-get-started-with-pulumi.s3-website-ap-northeast-1.amazonaws.com"
    bucketName    : "cm-ootaka-get-started-with-pulumi"

Resources:
    + 3 created

Duration: 6s

AWS CLIでも確認できました。

% aws s3 ls cm-ootaka-get-started-with-pulumi --profile pulumi
2022-04-01 17:30:46         69 index.html

まとめ

以上、Pulumiで指定した名前でS3バケットを作成してみました。

特に本番環境へのリソースデプロイでは、サフィックス無しの指定した名前でリソースを作りたいというケースが多いと思いますので、今回のポイントに気をつけて作成をしたいと思います。

どなたかのお役に立てば幸いです。それでは!