Skip to content
This repository was archived by the owner on Dec 11, 2023. It is now read-only.

Commit fe8063b

Browse files
committed
Node 10 buildtemplate, triggermesh/aws-custom-runtime#6
Signed-off-by: tzununbekov <t.zununbekov@gmail.com>
1 parent aabed7c commit fe8063b

File tree

5 files changed

+255
-9
lines changed

5 files changed

+255
-9
lines changed

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
### AWS Lambda Python buildtemplates
1+
### AWS Lambda buildtemplates
22

3-
Knative buildtemplate based on [LambCI](https://github.com/lambci/docker-lambda) Python runtimes.
3+
Knative buildtemplate based on [LambCI](https://github.com/lambci/docker-lambda) runtimes.
44
Function deployment example using [tm](https://github.com/triggermesh/tm) CLI:
55

6-
#### Example
7-
8-
Python 3.7
6+
#### Python
97

108
1. Install buildtemplate
119

node-10.x/bootstrap

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
#!/usr/local/bin/node --expose-gc
2+
3+
const http = require('http')
4+
5+
const RUNTIME_PATH = '/2018-06-01/runtime'
6+
7+
const {
8+
AWS_LAMBDA_FUNCTION_NAME,
9+
AWS_LAMBDA_FUNCTION_VERSION,
10+
AWS_LAMBDA_FUNCTION_MEMORY_SIZE,
11+
AWS_LAMBDA_LOG_GROUP_NAME,
12+
AWS_LAMBDA_LOG_STREAM_NAME,
13+
LAMBDA_TASK_ROOT,
14+
_HANDLER,
15+
AWS_LAMBDA_RUNTIME_API,
16+
} = process.env
17+
18+
const [HOST, PORT] = AWS_LAMBDA_RUNTIME_API.split(':')
19+
20+
start()
21+
22+
async function start() {
23+
let handler
24+
try {
25+
handler = getHandler()
26+
} catch (e) {
27+
await initError(e)
28+
return process.exit(1)
29+
}
30+
try {
31+
await processEvents(handler)
32+
} catch (e) {
33+
console.error(e)
34+
return process.exit(1)
35+
}
36+
}
37+
38+
async function processEvents(handler) {
39+
while (true) {
40+
const { event, context } = await nextInvocation()
41+
let result
42+
try {
43+
result = await handler(event, context)
44+
} catch (e) {
45+
await invokeError(e, context)
46+
continue
47+
}
48+
await invokeResponse(result, context)
49+
}
50+
}
51+
52+
async function initError(err) {
53+
return postError(`${RUNTIME_PATH}/init/error`, err)
54+
}
55+
56+
async function nextInvocation() {
57+
const res = await request({ path: `${RUNTIME_PATH}/invocation/next` })
58+
59+
if (res.statusCode !== 200) {
60+
throw new Error(`Unexpected /invocation/next response: ${JSON.stringify(res)}`)
61+
}
62+
63+
if (res.headers['lambda-runtime-trace-id']) {
64+
process.env._X_AMZN_TRACE_ID = res.headers['lambda-runtime-trace-id']
65+
} else {
66+
delete process.env._X_AMZN_TRACE_ID
67+
}
68+
69+
const deadlineMs = +res.headers['lambda-runtime-deadline-ms']
70+
71+
let context = {
72+
awsRequestId: res.headers['lambda-runtime-aws-request-id'],
73+
invokedFunctionArn: res.headers['lambda-runtime-invoked-function-arn'],
74+
logGroupName: AWS_LAMBDA_LOG_GROUP_NAME,
75+
logStreamName: AWS_LAMBDA_LOG_STREAM_NAME,
76+
functionName: AWS_LAMBDA_FUNCTION_NAME,
77+
functionVersion: AWS_LAMBDA_FUNCTION_VERSION,
78+
memoryLimitInMB: AWS_LAMBDA_FUNCTION_MEMORY_SIZE,
79+
getRemainingTimeInMillis: () => deadlineMs - Date.now(),
80+
}
81+
82+
if (res.headers['lambda-runtime-client-context']) {
83+
context.clientContext = JSON.parse(res.headers['lambda-runtime-client-context'])
84+
}
85+
86+
if (res.headers['lambda-runtime-cognito-identity']) {
87+
context.identity = JSON.parse(res.headers['lambda-runtime-cognito-identity'])
88+
}
89+
90+
var event
91+
if (res.body) {
92+
event = JSON.parse(res.body)
93+
}
94+
95+
return { event, context }
96+
}
97+
98+
async function invokeResponse(result, context) {
99+
const res = await request({
100+
method: 'POST',
101+
path: `${RUNTIME_PATH}/invocation/${context.awsRequestId}/response`,
102+
body: JSON.stringify(result),
103+
})
104+
if (res.statusCode !== 202) {
105+
throw new Error(`Unexpected /invocation/response response: ${JSON.stringify(res)}`)
106+
}
107+
}
108+
109+
async function invokeError(err, context) {
110+
return postError(`${RUNTIME_PATH}/invocation/${context.awsRequestId}/error`, err)
111+
}
112+
113+
async function postError(path, err) {
114+
const lambdaErr = toLambdaErr(err)
115+
const res = await request({
116+
method: 'POST',
117+
path,
118+
headers: {
119+
'Content-Type': 'application/json',
120+
'Lambda-Runtime-Function-Error-Type': lambdaErr.errorType,
121+
},
122+
body: JSON.stringify(lambdaErr),
123+
})
124+
if (res.statusCode !== 202) {
125+
throw new Error(`Unexpected ${path} response: ${JSON.stringify(res)}`)
126+
}
127+
}
128+
129+
function getHandler() {
130+
const appParts = _HANDLER.split('.')
131+
132+
if (appParts.length !== 2) {
133+
throw new Error(`Bad handler ${_HANDLER}`)
134+
}
135+
136+
const [modulePath, handlerName] = appParts
137+
138+
let app
139+
try {
140+
app = require(LAMBDA_TASK_ROOT + '/' + modulePath)
141+
} catch (e) {
142+
if (e.code === 'MODULE_NOT_FOUND') {
143+
throw new Error(`Unable to import module '${modulePath}'`)
144+
}
145+
throw e
146+
}
147+
148+
const userHandler = app[handlerName]
149+
150+
if (userHandler == null) {
151+
throw new Error(`Handler '${handlerName}' missing on module '${modulePath}'`)
152+
} else if (typeof userHandler !== 'function') {
153+
throw new Error(`Handler '${handlerName}' from '${modulePath}' is not a function`)
154+
}
155+
156+
return userHandler
157+
}
158+
159+
async function request(options) {
160+
options.host = HOST
161+
options.port = PORT
162+
163+
return new Promise((resolve, reject) => {
164+
let req = http.request(options, res => {
165+
let bufs = []
166+
res.on('data', data => bufs.push(data))
167+
res.on('end', () => resolve({
168+
statusCode: res.statusCode,
169+
headers: res.headers,
170+
body: Buffer.concat(bufs).toString(),
171+
}))
172+
res.on('error', reject)
173+
})
174+
req.on('error', reject)
175+
req.end(options.body)
176+
})
177+
}
178+
179+
function toLambdaErr({ name, message, stack }) {
180+
return {
181+
errorType: name,
182+
errorMessage: message,
183+
stackTrace: (stack || '').split('\n').slice(1),
184+
}
185+
}

node-10.x/buildtemplate.yaml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright 2018 TriggerMesh, Inc
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
apiVersion: build.knative.dev/v1alpha1
16+
kind: BuildTemplate
17+
metadata:
18+
name: aws-nodejs10-runtime
19+
spec:
20+
parameters:
21+
- name: IMAGE
22+
description: The URI of the image to push, including registry host
23+
- name: TAG
24+
description: Tag of the image being pushed
25+
default: latest
26+
- name: DIRECTORY
27+
description: The subdirectory of the workspace/repo
28+
default: ""
29+
- name: HANDLER
30+
default: "function.handler"
31+
steps:
32+
- name: dockerfile
33+
image: gcr.io/kaniko-project/executor@sha256:30ba460a034a8051b3222a32e20cb6049741e58384e3adf8c8987c004e2f2ab9
34+
command:
35+
- /busybox/sh
36+
args:
37+
- -c
38+
- |
39+
cd /workspace/${DIRECTORY}
40+
cat <<EOF > Dockerfile
41+
FROM node:10-alpine
42+
WORKDIR /opt
43+
44+
RUN apk --no-cache add curl \
45+
&& curl -sL https://github.com/triggermesh/aws-custom-runtime/releases/download/0.0.1/aws-custom-runtime > aws-custom-runtime \
46+
&& chmod +x aws-custom-runtime \
47+
&& curl -sL https://github.com/triggermesh/aws-lambda-runtime/archive/0.0.1.tar.gz | tar -xz aws-lambda-runtime-0.0.1/node-10.x \
48+
&& mv aws-lambda-runtime-0.0.1/node-10.x/* .
49+
50+
51+
ENV LAMBDA_TASK_ROOT "/opt"
52+
ENV _HANDLER "${HANDLER}"
53+
54+
COPY . .
55+
56+
ENTRYPOINT ["/opt/aws-custom-runtime"]
57+
EOF
58+
- name: export
59+
image: gcr.io/kaniko-project/executor@sha256:30ba460a034a8051b3222a32e20cb6049741e58384e3adf8c8987c004e2f2ab9
60+
args:
61+
- --context=/workspace/${DIRECTORY}
62+
- --dockerfile=/workspace/${DIRECTORY}/Dockerfile
63+
- --destination=${IMAGE}:${TAG}

python-2.7/buildtemplate.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ spec:
4444
RUN apk --no-cache add curl \
4545
&& curl -sL https://github.com/triggermesh/aws-custom-runtime/releases/download/0.0.1/aws-custom-runtime > aws-custom-runtime \
4646
&& chmod +x aws-custom-runtime \
47-
&& curl -sL https://github.com/triggermesh/aws-python-runtime/archive/0.0.1.tar.gz | tar -xz aws-python-runtime-0.0.1/python-2.7 \
48-
&& mv aws-python-runtime-0.0.1/python-2.7/* .
47+
&& curl -sL https://github.com/triggermesh/aws-lambda-runtime/archive/0.0.1.tar.gz | tar -xz aws-lambda-runtime-0.0.1/python-2.7 \
48+
&& mv aws-lambda-runtime-0.0.1/python-2.7/* .
4949
5050
ENV LAMBDA_TASK_ROOT "/opt"
5151
ENV _HANDLER "${HANDLER}"

python-3.7/buildtemplate.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ spec:
4444
RUN apk --no-cache add curl \
4545
&& curl -sL https://github.com/triggermesh/aws-custom-runtime/releases/download/0.0.1/aws-custom-runtime > aws-custom-runtime \
4646
&& chmod +x aws-custom-runtime \
47-
&& curl -sL https://github.com/triggermesh/aws-python-runtime/archive/0.0.1.tar.gz | tar -xz aws-python-runtime-0.0.1/python-3.7 \
48-
&& mv aws-python-runtime-0.0.1/python-3.7/* .
47+
&& curl -sL https://github.com/triggermesh/aws-lambda-runtime/archive/0.0.1.tar.gz | tar -xz aws-lambda-runtime-0.0.1/python-3.7 \
48+
&& mv aws-lambda-runtime-0.0.1/python-3.7/* .
4949
5050
ENV LAMBDA_TASK_ROOT "/opt"
5151
ENV _HANDLER "${HANDLER}"

0 commit comments

Comments
 (0)