SAM Initialization
這邊使用 sam init
來初始化專案。
1$ sam init
2
3You can preselect a particular runtime or package type when using the `sam init` experience.
4Call `sam init --help` to learn more.
5
6Which template source would you like to use?
7 1 - AWS Quick Start Templates
8 2 - Custom Template Location
9Choice: 1
10
11Choose an AWS Quick Start application template
12 1 - Hello World Example
13 2 - Data processing
14 3 - Hello World Example with Powertools for AWS Lambda
15 4 - Multi-step workflow
16 5 - Scheduled task
17 6 - Standalone function
18 7 - Serverless API
19 8 - Infrastructure event management
20 9 - Lambda Response Streaming
21 10 - Serverless Connector Hello World Example
22 11 - Multi-step workflow with Connectors
23 12 - GraphQLApi Hello World Example
24 13 - Full Stack
25 14 - Lambda EFS example
26 15 - Hello World Example With Powertools for AWS Lambda
27 16 - DynamoDB Example
28 17 - Machine Learning
29Template: 1
30
31# 目前官方預設最常用的語言開發事 Python ,所以要選擇 N 以後,才可以選其他語言
32Use the most popular runtime and package type? (Python and zip) [y/N]: N
33
34Which runtime would you like to use?
35 1 - aot.dotnet7 (provided.al2)
36 2 - dotnet8
37 3 - dotnet6
38 4 - go1.x
39 5 - go (provided.al2)
40 6 - go (provided.al2023)
41 7 - graalvm.java11 (provided.al2)
42 8 - graalvm.java17 (provided.al2)
43 9 - java21
44 10 - java17
45 11 - java11
46 12 - java8.al2
47 13 - nodejs20.x
48 14 - nodejs18.x
49 15 - nodejs16.x
50 16 - python3.9
51 17 - python3.8
52 18 - python3.12
53 19 - python3.11
54 20 - python3.10
55 21 - ruby3.2
56 22 - rust (provided.al2)
57 23 - rust (provided.al2023)
58Runtime: 13
59
60What package type would you like to use?
61 1 - Zip
62 2 - Image
63Package type: 1
64
65Based on your selections, the only dependency manager available is npm.
66We will proceed copying the template using npm.
67
68Select your starter template
69 1 - Hello World Example
70 2 - Hello World Example TypeScript
71Template: 1
72
73Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: y
74X-Ray will incur an additional cost. View https://aws.amazon.com/xray/pricing/ for more details
75
76Would you like to enable monitoring using CloudWatch Application Insights?
77For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: N
78
79Would you like to set Structured Logging in JSON format on your Lambda functions? [y/N]: y
80Structured Logging in JSON format might incur an additional cost. View https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-pricing for more details
81
82Project name [sam-app]:
83
84 -----------------------
85 Generating application:
86 -----------------------
87 Name: sam-app
88 Runtime: nodejs20.x
89 Architectures: x86_64
90 Dependency Manager: npm
91 Application Template: hello-world
92 Output Directory: .
93 Configuration file: sam-app/samconfig.toml
94
95 Next steps can be found in the README file at sam-app/README.md
96
97
98Commands you can use next
99=========================
100[*] Create pipeline: cd sam-app && sam pipeline init --bootstrap
101[*] Validate SAM template: cd sam-app && sam validate
102[*] Test Function in the Cloud: cd sam-app && sam sync --stack-name {stack-name} --watch
檔案結構
- event.json: 用來測試 Labmda 的
- app.mjs: Lambda Function 原始碼
- package.json: NPM 用來管理 Package 的檔案
- test-handler: Lambda Unit Test
- samconfig.toml: SAM CLI 的設定檔案
- template.ymal: Infrastructure as code 架構的定義檔案
1.
2├── README.md
3├── __init__.py
4├── events
5│ └── event.json
6├── hello_world
7│ ├── __init__.py
8│ ├── app.py
9│ └── requirements.txt
10├── samconfig.toml
11├── template.yaml
12└── tests
13 ├── __init__.py
14 ├── integration
15 │ ├── __init__.py
16 │ └── test_api_gateway.py
17 ├── requirements.txt
18 └── unit
19 ├── __init__.py
20 └── test_handler.py
Template YAML
- AWSTemplateFormatVersion: AWS CloudFormation 的 Version
- Transform: 告訴 CloudFormation 這是 SAM 的格式 YAML
- Global: 這邊是針對某些服務資源,共同設定,像 Function 的
Tracing: Active
就是對全部的 Lambda 開啟 X-Ray - Reousrce: 這邊就是建立 AWS 上的資源, SAM 跟 CloudFormation 的定義有差別,下面會附上簡易差別圖,詳細資訊可參考官網
- Type 是 Function 就是我們實際的 Lambda Function
- CodeUri: 是 resource code 存放位置的路徑
- Handler: 這邊是
filename
.functionName
的格式
- Type 是 Function 就是我們實際的 Lambda Function
1AWSTemplateFormatVersion: '2010-09-09'
2Transform: AWS::Serverless-2016-10-31
3Description: >
4 sam-app
5 Sample SAM Template for sam-app
6
7Globals:
8 Function:
9 Timeout: 3
10 MemorySize: 128
11 Tracing: Active
12 LoggingConfig:
13 LogFormat: JSON
14 Api:
15 TracingEnabled: true
16Resources:
17 HelloWorldFunction:
18 Type: AWS::Serverless::Function
19 Properties:
20 CodeUri: hello_world/
21 Handler: app.lambda_handler
22 Runtime: python3.9
23 Architectures:
24 - x86_64
25 Events:
26 HelloWorld:
27 Type: Api
28 Properties:
29 Path: /hello
30 Method: get
31
32Outputs:
33 HelloWorldApi:
34 Description: API Gateway endpoint URL for Prod stage for Hello World function
35 Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
36 HelloWorldFunction:
37 Description: Hello World Lambda Function ARN
38 Value: !GetAtt HelloWorldFunction.Arn
39 HelloWorldFunctionIamRole:
40 Description: Implicit IAM Role created for Hello World function
41 Value: !GetAtt HelloWorldFunctionRole.Arn
CloudFormation vs SAM Resource
驗證 Template
AWS Sam 提供了 sam validate
去驗證 template 是否有問題
1$ sam validate
2
3/Users/allen/sam-app/template.yaml is a valid SAM Template
如果我故意在 template 裡面寫沒有存在的 Type,會出現以下錯誤
1$ sam validate
2
3E0001 Error transforming template: Resource with id [HelloWorldFunction] is invalid. Event with id [HelloWorld] is invalid. Resource dict has missing or invalid value for key Type. Event Type is: Api1.
4/Users/allen/sam-app/template.yaml:1:1
5
6Error: Linting failed. At least one linting rule was matched to the provided template.
Lambda Function
1export const lambdaHandler = async (event, context) => {
2 const response = {
3 statusCode: 200,
4 body: JSON.stringify({
5 message: 'hello world',
6 })
7 };
8
9 return response;
10 };
Build Package
這邊使用 sam build
來建立 package
1$ sam build
2
3Starting Build use cache
4Manifest file is changed (new hash: c0e83ff3ce1bd02a0c2a7c02974c24ec) or dependency folder (.aws-sam/deps/1d492548-0d35-49f3-af42-0252668aa785) is missing for (HelloWorldFunction), downloading
5dependencies and copying/building source
6Building codeuri: /Users/allen/sam-app/hello-world runtime: nodejs20.x metadata: {} architecture: x86_64 functions: HelloWorldFunction
7 Running NodejsNpmBuilder:NpmPack
8 Running NodejsNpmBuilder:CopyNpmrcAndLockfile
9 Running NodejsNpmBuilder:CopySource
10 Running NodejsNpmBuilder:NpmInstall
11 Running NodejsNpmBuilder:CleanUp
12 Running NodejsNpmBuilder:CopyDependencies
13 Running NodejsNpmBuilder:CleanUpNpmrc
14 Running NodejsNpmBuilder:LockfileCleanUp
15 Running NodejsNpmBuilder:LockfileCleanUp
16
17Build Succeeded
18
19Built Artifacts : .aws-sam/build
20Built Template : .aws-sam/build/template.yaml
21
22Commands you can use next
23=========================
24[*] Validate SAM template: sam validate
25[*] Invoke Function: sam local invoke
26[*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch
27[*] Deploy: sam deploy --guided
接著會在 local 產生 .aws-sam/build
資料夾。
在資料夾中,可以看到 node_modules 的資料,我們定義在 Package.json 的 modules 都會下載到這
1$ tree .aws-sam/build
2
3.aws-sam/build
4├── HelloWorldFunction
5│ ├── app.mjs
6│ ├── node_modules
7│ │ ├── asynckit
8│ │ │ ├── LICENSE
9│ │ │ ├── README.md
10│ │ │ ├── bench.js
11│ │ │ ├── index.js
12│ │ │ ├── lib
13│ │ │ │ ├── abort.js
14│ │ │ │ ├── async.js
15│ │ │ │ ├── defer.js
16│ │ │ │ ├── iterate.js
17│ │ │ │ ├── readable_asynckit.js
18│ │ │ │ ├── readable_parallel.js
19│ │ │ │ ├── readable_serial.js
20│ │ │ │ ├── readable_serial_ordered.js
21│ │ │ │ ├── state.js
22│ │ │ │ ├── streamify.js
23│ │ │ │ └── terminator.js
24│ │ │ ├── package.json
25│ │ │ ├── parallel.js
26│ │ │ ├── serial.js
27│ │ │ ├── serialOrdered.js
28│ │ │ └── stream.js
29│ │ ├── axios
30│ │ │ ├── CHANGELOG.md
31│ │ │ ├── LICENSE
32│ │ │ ├── MIGRATION_GUIDE.md
33│ │ │ ├── README.md
34│ │ │ ├── SECURITY.md
35│ │ │ ├── dist
36│ │ │ │ ├── axios.js
37│ │ │ │ ├── axios.js.map
38│ │ │ │ ├── axios.min.js
39│ │ │ │ ├── axios.min.js.map
40│ │ │ │ ├── browser
41│ │ │ │ │ ├── axios.cjs
42│ │ │ │ │ └── axios.cjs.map
43│ │ │ │ ├── esm
44│ │ │ │ │ ├── axios.js
45│ │ │ │ │ ├── axios.js.map
46│ │ │ │ │ ├── axios.min.js
47│ │ │ │ │ └── axios.min.js.map
48│ │ │ │ └── node
49│ │ │ │ ├── axios.cjs
50│ │ │ │ └── axios.cjs.map
51│ │ │ ├── index.d.cts
52│ │ │ ├── index.d.ts
53│ │ │ ├── index.js
54│ │ │ ├── lib
55│ │ │ │ ├── adapters
56│ │ │ │ │ ├── README.md
57│ │ │ │ │ ├── adapters.js
58│ │ │ │ │ ├── http.js
59│ │ │ │ │ └── xhr.js
60│ │ │ │ ├── axios.js
61│ │ │ │ ├── cancel
62│ │ │ │ │ ├── CancelToken.js
63│ │ │ │ │ ├── CanceledError.js
64│ │ │ │ │ └── isCancel.js
65│ │ │ │ ├── core
66│ │ │ │ │ ├── Axios.js
67│ │ │ │ │ ├── AxiosError.js
68│ │ │ │ │ ├── AxiosHeaders.js
69│ │ │ │ │ ├── InterceptorManager.js
70│ │ │ │ │ ├── README.md
71│ │ │ │ │ ├── buildFullPath.js
72│ │ │ │ │ ├── dispatchRequest.js
73│ │ │ │ │ ├── mergeConfig.js
74│ │ │ │ │ ├── settle.js
75│ │ │ │ │ └── transformData.js
76│ │ │ │ ├── defaults
77│ │ │ │ │ ├── index.js
78│ │ │ │ │ └── transitional.js
79│ │ │ │ ├── env
80│ │ │ │ │ ├── README.md
81│ │ │ │ │ ├── classes
82│ │ │ │ │ │ └── FormData.js
83│ │ │ │ │ └── data.js
84│ │ │ │ ├── helpers
85│ │ │ │ │ ├── AxiosTransformStream.js
86│ │ │ │ │ ├── AxiosURLSearchParams.js
87│ │ │ │ │ ├── HttpStatusCode.js
88│ │ │ │ │ ├── README.md
89│ │ │ │ │ ├── ZlibHeaderTransformStream.js
90│ │ │ │ │ ├── bind.js
91│ │ │ │ │ ├── buildURL.js
92│ │ │ │ │ ├── callbackify.js
93│ │ │ │ │ ├── combineURLs.js
94│ │ │ │ │ ├── cookies.js
95│ │ │ │ │ ├── deprecatedMethod.js
96│ │ │ │ │ ├── formDataToJSON.js
97│ │ │ │ │ ├── formDataToStream.js
98│ │ │ │ │ ├── fromDataURI.js
99│ │ │ │ │ ├── isAbsoluteURL.js
100│ │ │ │ │ ├── isAxiosError.js
101│ │ │ │ │ ├── isURLSameOrigin.js
102│ │ │ │ │ ├── null.js
103│ │ │ │ │ ├── parseHeaders.js
104│ │ │ │ │ ├── parseProtocol.js
105│ │ │ │ │ ├── readBlob.js
106│ │ │ │ │ ├── speedometer.js
107│ │ │ │ │ ├── spread.js
108│ │ │ │ │ ├── throttle.js
109│ │ │ │ │ ├── toFormData.js
110│ │ │ │ │ ├── toURLEncodedForm.js
111│ │ │ │ │ └── validator.js
112│ │ │ │ ├── platform
113│ │ │ │ │ ├── browser
114│ │ │ │ │ │ ├── classes
115│ │ │ │ │ │ │ ├── Blob.js
116│ │ │ │ │ │ │ ├── FormData.js
117│ │ │ │ │ │ │ └── URLSearchParams.js
118│ │ │ │ │ │ └── index.js
119│ │ │ │ │ ├── common
120│ │ │ │ │ │ └── utils.js
121│ │ │ │ │ ├── index.js
122│ │ │ │ │ └── node
123│ │ │ │ │ ├── classes
124│ │ │ │ │ │ ├── FormData.js
125│ │ │ │ │ │ └── URLSearchParams.js
126│ │ │ │ │ └── index.js
127│ │ │ │ └── utils.js
128│ │ │ └── package.json
129│ │ ├── combined-stream
130│ │ │ ├── License
131│ │ │ ├── Readme.md
132│ │ │ ├── lib
133│ │ │ │ └── combined_stream.js
134│ │ │ ├── package.json
135│ │ │ └── yarn.lock
136│ │ ├── delayed-stream
137│ │ │ ├── License
138│ │ │ ├── Makefile
139│ │ │ ├── Readme.md
140│ │ │ ├── lib
141│ │ │ │ └── delayed_stream.js
142│ │ │ └── package.json
143│ │ ├── follow-redirects
144│ │ │ ├── LICENSE
145│ │ │ ├── README.md
146│ │ │ ├── debug.js
147│ │ │ ├── http.js
148│ │ │ ├── https.js
149│ │ │ ├── index.js
150│ │ │ └── package.json
151│ │ ├── form-data
152│ │ │ ├── License
153│ │ │ ├── README.md.bak
154│ │ │ ├── Readme.md
155│ │ │ ├── index.d.ts
156│ │ │ ├── lib
157│ │ │ │ ├── browser.js
158│ │ │ │ ├── form_data.js
159│ │ │ │ └── populate.js
160│ │ │ └── package.json
161│ │ ├── mime-db
162│ │ │ ├── HISTORY.md
163│ │ │ ├── LICENSE
164│ │ │ ├── README.md
165│ │ │ ├── db.json
166│ │ │ ├── index.js
167│ │ │ └── package.json
168│ │ ├── mime-types
169│ │ │ ├── HISTORY.md
170│ │ │ ├── LICENSE
171│ │ │ ├── README.md
172│ │ │ ├── index.js
173│ │ │ └── package.json
174│ │ └── proxy-from-env
175│ │ ├── LICENSE
176│ │ ├── README.md
177│ │ ├── index.js
178│ │ ├── package.json
179│ │ └── test.js
180│ └── package.json
181└── template.yaml
評論