

初探 Pulumi 上傳靜態網站到 AWS S3 (二)
source link: https://blog.wu-boy.com/2021/02/upload-static-content-to-aws-s3-using-pulumi-02/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

初探 Pulumi 上傳靜態網站到 AWS S3 (二)
上一篇『初探 Pulumi 上傳靜態網站到 AWS S3 (一)』主要介紹 Pulumi 基本使用方式,而本篇會延續上一篇教學把剩下的章節教完,底下是本篇會涵蓋的章節內容:
- 設定 Pulumi Stack 環境變數
- 建立第二個 Pulumi Stack 環境
- 刪除 Pulumi Stack 環境
讓開發者可以自由新增各種不同環境,像是 Testing 或 Develop 環境,以及該如何動態帶入不同環境的變數內容,最後可以透過單一指令將全部資源刪除。
設定 Pulumi Stack 環境變數
大家可以看到,現在所有 main.go
的程式碼,都是直接 hardcode 的,那怎麼透過一些環境變數來動態改變設定呢?這時候可以透過 pulumi config 指令來調整喔,底下來看看怎麼實作,假設我們要讀取的 index.html 放在其他目錄底下,該怎麼動態調整?
步驟一: 撰寫讀取 Config 函式
func getEnv(ctx *pulumi.Context, key string, fallback ...string) string {
if value, ok := ctx.GetConfig(key); ok {
return value
}
if len(fallback) > 0 {
return fallback[0]
}
return ""
}
pulumi 的 context 內有一個讀取環境變數函式叫 GetConfig
,接著我們在設計一個 fallback 當作 default 回傳值。底下設定一個變數 s3:siteDir
pulumi config set s3:siteDir production
打開 Pulumi.dev.yaml
可以看到
config:
aws:profile: demo
aws:region: ap-northeast-1
s3:siteDir: production
接著將程式碼改成如下:
site := getEnv(ctx, "s3:siteDir", "content")
index := path.Join(site, "index.html")
_, err = s3.NewBucketObject(ctx, "index.html", &s3.BucketObjectArgs{
Bucket: bucket.Bucket,
Source: pulumi.NewFileAsset(index),
Acl: pulumi.String("public-read"),
ContentType: pulumi.String(mime.TypeByExtension(path.Ext(index))),
})
步驟二: 更新 Infrastructure
$ pulumi up
Previewing update (dev)
View Live: https://app.pulumi.com/appleboy/demo/dev/previews/d76d2f9b-16c8-4bfd-820d-d5368d29f592
Type Name Plan Info
pulumi:pulumi:Stack demo-dev
~ └─ aws:s3:BucketObject index.html update [diff: ~source]
Resources:
~ 1 to update
2 unchanged
Do you want to perform this update? details
pulumi:pulumi:Stack: (same)
[urn=urn:pulumi:dev::demo::pulumi:pulumi:Stack::demo-dev]
~ aws:s3/bucketObject:BucketObject: (update)
[id=index.html]
[urn=urn:pulumi:dev::demo::aws:s3/bucketObject:BucketObject::index.html]
- source: asset(file:77aab46) { content/index.html }
+ source: asset(file:01c09f4) { production/index.html }
可以看到 source 會被換成 production/index.html
步驟三: 讀取更多檔案
整個 Web 專案肯定不止一個檔案,所以再來改一下原本的讀取檔案列表流程
site := getEnv(ctx, "s3:siteDir", "content")
files, err := ioutil.ReadDir(site)
if err != nil {
return err
}
for _, item := range files {
name := item.Name()
if _, err = s3.NewBucketObject(ctx, name, &s3.BucketObjectArgs{
Bucket: bucket.Bucket,
Source: pulumi.NewFileAsset(filepath.Join(site, name)),
Acl: pulumi.String("public-read"),
ContentType: pulumi.String(mime.TypeByExtension(path.Ext(filepath.Join(site, name)))),
}); err != nil {
return err
}
}
Type Name Status Info
pulumi:pulumi:Stack demo-dev
+ ├─ aws:s3:BucketObject about.html created
~ └─ aws:s3:BucketObject index.html updated [diff: ~source]
Outputs:
bucketEndpoint: "foobar-1234.s3-website-ap-northeast-1.amazonaws.com"
bucketID : "foobar-1234"
bucketName : "foobar-1234"
Resources:
+ 1 created
~ 1 updated
2 changes. 2 unchanged
Duration: 9s
完整程式碼如下:
package main
import (
"io/ioutil"
"mime"
"path"
"path/filepath"
"github.com/pulumi/pulumi-aws/sdk/v3/go/aws/s3"
"github.com/pulumi/pulumi/sdk/v2/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Create an AWS resource (S3 Bucket)
bucket, err := s3.NewBucket(ctx, "my-bucket", &s3.BucketArgs{
Bucket: pulumi.String("foobar-1234"),
Website: s3.BucketWebsiteArgs{
IndexDocument: pulumi.String("index.html"),
},
})
if err != nil {
return err
}
site := getEnv(ctx, "s3:siteDir", "content")
files, err := ioutil.ReadDir(site)
if err != nil {
return err
}
for _, item := range files {
name := item.Name()
if _, err = s3.NewBucketObject(ctx, name, &s3.BucketObjectArgs{
Bucket: bucket.Bucket,
Source: pulumi.NewFileAsset(filepath.Join(site, name)),
Acl: pulumi.String("public-read"),
ContentType: pulumi.String(mime.TypeByExtension(path.Ext(filepath.Join(site, name)))),
}); err != nil {
return err
}
}
// Export the name of the bucket
ctx.Export("bucketID", bucket.ID())
ctx.Export("bucketName", bucket.Bucket)
ctx.Export("bucketEndpoint", bucket.WebsiteEndpoint)
return nil
})
}
func getEnv(ctx *pulumi.Context, key string, fallback ...string) string {
if value, ok := ctx.GetConfig(key); ok {
return value
}
if len(fallback) > 0 {
return fallback[0]
}
return ""
}
建立第二個 Pulumi Stack 環境
在 Pulumi 可以很簡單的建立多種環境,像是 Testing 或 Production,只要將動態變數抽出來設定成 config 即可。底下來看看怎麼建立全先的環境,這步驟在 Pulumi 叫做 Stack。前面已經建立一個 dev 環境,現在我們要建立一個全新環境來部署 Testing 或 Production 該如何做呢?
步驟一: 建立全新 Stack 環境
透過 pulumi stack 可以建立全新環境
$ pulumi stack ls
NAME LAST UPDATE RESOURCE COUNT URL
dev* 1 minute ago 5 https://app.pulumi.com/appleboy/demo/dev
建立 stack
$ pulumi stack init prod
Created stack 'prod'
$ pulumi stack ls
NAME LAST UPDATE RESOURCE COUNT URL
dev 1 minute ago 5 https://app.pulumi.com/appleboy/demo/dev
prod* n/a n/a https://app.pulumi.com/appleboy/demo/prod
pulumi config set s3:siteDir www
pulumi config set aws:profile demo
pulumi config set aws:region ap-northeast-1
步驟二: 建立 www 內容
建立 content/www
目錄,一樣放上 index.htm + about.html
<html>
<body>
<h1>Hello Pulumi S3 Bucket From New Stack</h1>
</body>
</html>
about.html
<html>
<body>
<h1>About us From New Stack</h1>
</body>
</html>
步驟三: 部署 New Stack
先看看 Preview 結果
$ pulumi up
Previewing update (prod)
View Live: https://app.pulumi.com/appleboy/demo/prod/previews/3b85a340-0e71-455e-9b96-48dc38538d18
Type Name Plan
+ pulumi:pulumi:Stack demo-prod create
+ ├─ aws:s3:Bucket my-bucket create
+ ├─ aws:s3:BucketObject index.html create
+ └─ aws:s3:BucketObject about.html create
Resources:
+ 4 to create
Do you want to perform this update? details
+ pulumi:pulumi:Stack: (create)
[urn=urn:pulumi:prod::demo::pulumi:pulumi:Stack::demo-prod]
+ aws:s3/bucket:Bucket: (create)
[urn=urn:pulumi:prod::demo::aws:s3/bucket:Bucket::my-bucket]
acl : "private"
bucket : "my-bucket-ba8088c"
forceDestroy: false
website : {
indexDocument: "index.html"
}
+ aws:s3/bucketObject:BucketObject: (create)
[urn=urn:pulumi:prod::demo::aws:s3/bucketObject:BucketObject::index.html]
acl : "public-read"
bucket : "my-bucket-ba8088c"
contentType : "text/html; charset=utf-8"
forceDestroy: false
key : "index.html"
source : asset(file:460188b) { www/index.html }
+ aws:s3/bucketObject:BucketObject: (create)
[urn=urn:pulumi:prod::demo::aws:s3/bucketObject:BucketObject::about.html]
acl : "public-read"
bucket : "my-bucket-ba8088c"
contentType : "text/html; charset=utf-8"
forceDestroy: false
key : "about.html"
source : asset(file:376c42a) { www/about.html }
如果看起來沒問題,就可以直接執行了
Updating (prod)
View Live: https://app.pulumi.com/appleboy/demo/prod/updates/1
Type Name Status
+ pulumi:pulumi:Stack demo-prod created
+ ├─ aws:s3:Bucket my-bucket created
+ ├─ aws:s3:BucketObject about.html created
+ └─ aws:s3:BucketObject index.html created
Outputs:
bucketEndpoint: "my-bucket-a7044ab.s3-website-ap-northeast-1.amazonaws.com"
bucketID : "my-bucket-a7044ab"
bucketName : "my-bucket-a7044ab"
Resources:
+ 4 created
Duration: 18s
最後用 curl 執行看看
$ curl -v $(pulumi stack output bucketEndpoint)
* Trying 52.219.8.20...
* TCP_NODELAY set
* Connected to my-bucket-a7044ab.s3-website-ap-northeast-1.amazonaws.com (52.219.8.20) port 80 (#0)
> GET / HTTP/1.1
> Host: my-bucket-a7044ab.s3-website-ap-northeast-1.amazonaws.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< x-amz-id-2: oGxc+rLPi3kLOZslMsOmJqPY/WGeMoxX9sXJDRj4wlJlGVq+7pMx3ers71jxnDiDkeM9JRrd+T8=
< x-amz-request-id: 528235DDFF40F365
< Date: Thu, 11 Feb 2021 04:49:21 GMT
< Last-Modified: Thu, 11 Feb 2021 04:48:41 GMT
< ETag: "ae41d1b3f0aeef6a490e1b2edc74d2b5"
< Content-Type: text/html; charset=utf-8
< Content-Length: 85
< Server: AmazonS3
<
<html>
<body>
<h1>Hello Pulumi S3 Bucket From New Stack</h1>
</body>
</html>
* Connection #0 to host my-bucket-a7044ab.s3-website-ap-northeast-1.amazonaws.com left intact
* Closing connection 0
刪除 Pulumi Stack 環境
最後步驟就是要學習怎麼一鍵刪除整個 Infrastructure 環境。現在我們已經建立兩個 Stack 環境,該怎麼移除?
步驟一: 刪除所有資源
用底下指令可以刪除全部資源
Previewing destroy (prod)
View Live: https://app.pulumi.com/appleboy/demo/prod/previews/92f9c4a4-f4a9-464d-be27-5040aff295ae
Type Name Plan
- pulumi:pulumi:Stack demo-prod delete
- ├─ aws:s3:BucketObject about.html delete
- ├─ aws:s3:BucketObject index.html delete
- └─ aws:s3:Bucket my-bucket delete
Outputs:
- bucketEndpoint: "my-bucket-a7044ab.s3-website-ap-northeast-1.amazonaws.com"
- bucketID : "my-bucket-a7044ab"
- bucketName : "my-bucket-a7044ab"
Resources:
- 4 to delete
Do you want to perform this destroy? details
- aws:s3/bucketObject:BucketObject: (delete)
[id=about.html]
[urn=urn:pulumi:prod::demo::aws:s3/bucketObject:BucketObject::about.html]
- aws:s3/bucketObject:BucketObject: (delete)
[id=index.html]
[urn=urn:pulumi:prod::demo::aws:s3/bucketObject:BucketObject::index.html]
- aws:s3/bucket:Bucket: (delete)
[id=my-bucket-a7044ab]
[urn=urn:pulumi:prod::demo::aws:s3/bucket:Bucket::my-bucket]
- pulumi:pulumi:Stack: (delete)
[urn=urn:pulumi:prod::demo::pulumi:pulumi:Stack::demo-prod]
--outputs:--
- bucketEndpoint: "my-bucket-a7044ab.s3-website-ap-northeast-1.amazonaws.com"
- bucketID : "my-bucket-a7044ab"
- bucketName : "my-bucket-a7044ab"
選擇 yse
移除所以資源
Destroying (prod)
View Live: https://app.pulumi.com/appleboy/demo/prod/updates/2
Type Name Status
- pulumi:pulumi:Stack demo-prod deleted
- ├─ aws:s3:BucketObject index.html deleted
- ├─ aws:s3:BucketObject about.html deleted
- └─ aws:s3:Bucket my-bucket deleted
Outputs:
- bucketEndpoint: "my-bucket-a7044ab.s3-website-ap-northeast-1.amazonaws.com"
- bucketID : "my-bucket-a7044ab"
- bucketName : "my-bucket-a7044ab"
Resources:
- 4 deleted
Duration: 7s
步驟二: 移除 Stack 設定
上面步驟只是把所有資源移除,但是你還是保留了所以 stack history 操作,請看
$ pulumi stack history
Version: 2
UpdateKind: destroy
Status: succeeded
Message: chore(pulumi): 設定 Pulumi Stack 環境變數
+0-4~0 0 Updated 1 minute ago took 8s
exec.kind: cli
git.author: Bo-Yi Wu
git.author.email: [email protected]
git.committer: Bo-Yi Wu
git.committer.email: [email protected]
git.dirty: true
git.head: 9d9f8182abefb0e90656ca45065bc07a8a3431f4
git.headName: refs/heads/main
vcs.kind: github.com
vcs.owner: go-training
vcs.repo: infrastructure-as-code-workshop
Version: 1
UpdateKind: update
Status: succeeded
Message: chore(pulumi): 設定 Pulumi Stack 環境變數
+4-0~0 0 Updated 8 minutes ago took 18s
exec.kind: cli
git.author: Bo-Yi Wu
git.author.email: [email protected]
git.committer: Bo-Yi Wu
git.committer.email: [email protected]
git.dirty: true
git.head: 437e94e130ee3d31eb80075dd237cc17d09255d1
git.headName: refs/heads/main
vcs.kind: github.com
vcs.owner: go-training
vcs.repo: infrastructure-as-code-workshop
要整個完整移除,請務必要執行底下指令
pulumi stack rm
最後的確認
$ pulumi stack rm
This will permanently remove the 'prod' stack!
Please confirm that this is what you'd like to do by typing ("prod"):
移除其他的 Stack
按照上面的步驟重新移除其他的 Stack,先使用底下指令列出還有哪些 Stack:
$ pulumi stack ls
NAME LAST UPDATE RESOURCE COUNT URL
dev 24 minutes ago 5 https://app.pulumi.com/appleboy/demo/dev
選擇 Stack
pulumi stack select dev
接著重複上面一跟二步驟即可
本篇跟上一篇教學剛好涵蓋了整個 Pulumi 的基本使用方式,如果你還在選擇要用 Terraform 還是 Pulumi,甚至 AWS 所推出的 CDK,很推薦你嘗試看看 Pulumi,未來會介紹更多 Pulumi 進階的使用方式,或者像是部署 Kubernetes .. 等,能使用自己喜歡的語言寫 Infra 是一件令人舒服的事情。
Author appleboyPosted on 2021/02/112021/02/11Categories DevOps, GolangTags golang, pulumi
Recommend
-
4
初探 Infrastructure as Code 工具 Terraform vs Pulumi 想必大家對於 Infrastructure as Code 簡稱 (IaC) 並不陌生,而這個名詞在很早以前就很火熱,本篇最主要介紹為什麼我們要...
-
13
初探 Pulumi 上傳靜態網站到 AWS S3 (一) 上一篇作者提到了兩套 Infrastructure as Code 工具,分別是 Terraform 跟
-
10
Announcing the Pulumi AWS Native ProviderPosted on Thursday, Sep 30, 2021We are excited to announce the release of the new
-
9
Infrastructure as Code on AWS using Go and Pulumi When we talk about Infrastructure as Code or IaC, the first tool that comes to min...
-
7
Pulumi Announces AWS Native Provider Nov 17, 2021 2 min...
-
7
Using AWS Quick Starts with the Pulumi RegistryPosted on Wednesday, Jan 5, 2022As somebody who works on AWS projects across numerous projects, teams, and indus...
-
4
Announcing v5.0.0 of the Pulumi AWS Provider Posted on Monday, Mar 28, 2022 We are excited to announce v5.0.0 of the Pulumi AWS Classic provider. The AWS Classic pr...
-
4
AWS Enterprise Container Management with PulumiPosted on Thursday, Apr 14, 2022Managing containers and Kubernetes clusters are consistently popular topic areas on the Pulumi blog and in our docs. Our customers regularly cite t...
-
7
Deploy WordPress to AWS using Pulumi and AnsiblePosted on Monday, Jun 27, 2022There are two primary kinds of infrastructure as code tools: configuration management, like Ansible, Chef, and Puppet, which config...
-
7
AWS Lambda Response Streaming with PulumiPosted on Thursday, Apr 6, 2023Since its introduction in 2014, AWS Lambda has rapidly expanded its capabilities from simple “functions in the cloud” at launch to a comprehensive...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK