-
-
Notifications
You must be signed in to change notification settings - Fork 797
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: go-runner implementation (#1320)
- Loading branch information
1 parent
15916f3
commit 6bb54fd
Showing
13 changed files
with
305 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
import { EOL } from 'os' | ||
import { promises as fsPromises } from 'fs' | ||
import { sep, resolve, parse as pathParse } from 'path' | ||
import execa, { sync } from 'execa' | ||
|
||
const { writeFile, readFile, mkdir, rmdir } = fsPromises | ||
const { parse, stringify } = JSON | ||
const { cwd } = process | ||
|
||
const PAYLOAD_IDENTIFIER = 'offline_payload' | ||
|
||
export default class GoRunner { | ||
#env = null | ||
#handlerPath = null | ||
#tmpPath = null | ||
#tmpFile = null | ||
#goEnv = null | ||
|
||
constructor(funOptions, env, v3Utils) { | ||
const { handlerPath } = funOptions | ||
|
||
this.#env = env | ||
this.#handlerPath = handlerPath | ||
|
||
if (v3Utils) { | ||
this.log = v3Utils.log | ||
this.progress = v3Utils.progress | ||
this.writeText = v3Utils.writeText | ||
this.v3Utils = v3Utils | ||
} | ||
|
||
// Make sure we have the mock-lambda runner | ||
sync('go', ['get', 'github.com/icarus-sullivan/mock-lambda@e065469']) | ||
} | ||
|
||
async cleanup() { | ||
try { | ||
await rmdir(this.#tmpPath, { recursive: true }) | ||
} catch (e) { | ||
// @ignore | ||
} | ||
|
||
this.#tmpFile = null | ||
this.#tmpPath = null | ||
} | ||
|
||
_parsePayload(value) { | ||
const log = [] | ||
let payload | ||
|
||
for (const item of value.split(EOL)) { | ||
if (item.indexOf(PAYLOAD_IDENTIFIER) === -1) { | ||
log.push(item) | ||
} else if (item.indexOf(PAYLOAD_IDENTIFIER) !== -1) { | ||
try { | ||
const { | ||
offline_payload: { success, error }, | ||
} = parse(item) | ||
if (success) { | ||
payload = success | ||
} else if (error) { | ||
payload = error | ||
} | ||
} catch (err) { | ||
// @ignore | ||
} | ||
} | ||
} | ||
|
||
// Log to console in case engineers want to see the rest of the info | ||
if (this.log) { | ||
this.log(log.join(EOL)) | ||
} else { | ||
console.log(log.join(EOL)) | ||
} | ||
|
||
return payload | ||
} | ||
|
||
async run(event, context) { | ||
const { dir } = pathParse(this.#handlerPath) | ||
const handlerCodeRoot = dir.split(sep).slice(0, -1).join(sep) | ||
const handlerCode = await readFile(`${this.#handlerPath}.go`, 'utf8') | ||
this.#tmpPath = resolve(handlerCodeRoot, 'tmp') | ||
this.#tmpFile = resolve(this.#tmpPath, 'main.go') | ||
|
||
const out = handlerCode.replace( | ||
'"github.com/aws/aws-lambda-go/lambda"', | ||
'lambda "github.com/icarus-sullivan/mock-lambda"', | ||
) | ||
|
||
try { | ||
await mkdir(this.#tmpPath, { recursive: true }) | ||
} catch (e) { | ||
// @ignore | ||
} | ||
|
||
try { | ||
await writeFile(this.#tmpFile, out, 'utf8') | ||
} catch (e) { | ||
// @ignore | ||
} | ||
|
||
// Get go env to run this locally | ||
if (!this.#goEnv) { | ||
const goEnvResponse = await execa('go', ['env'], { | ||
stdio: 'pipe', | ||
encoding: 'utf-8', | ||
}) | ||
|
||
const goEnvString = goEnvResponse.stdout || goEnvResponse.stderr | ||
this.#goEnv = goEnvString.split(EOL).reduce((a, b) => { | ||
const [k, v] = b.split('="') | ||
// eslint-disable-next-line no-param-reassign | ||
a[k] = v ? v.slice(0, -1) : '' | ||
return a | ||
}, {}) | ||
} | ||
|
||
// Remove our root, since we want to invoke go relatively | ||
const cwdPath = `${this.#tmpFile}`.replace(`${cwd()}${sep}`, '') | ||
const { stdout, stderr } = await execa(`go`, ['run', cwdPath], { | ||
stdio: 'pipe', | ||
env: { | ||
...this.#env, | ||
...this.#goEnv, | ||
AWS_LAMBDA_LOG_GROUP_NAME: context.logGroupName, | ||
AWS_LAMBDA_LOG_STREAM_NAME: context.logStreamName, | ||
AWS_LAMBDA_FUNCTION_NAME: context.functionName, | ||
AWS_LAMBDA_FUNCTION_MEMORY_SIZE: context.memoryLimitInMB, | ||
AWS_LAMBDA_FUNCTION_VERSION: context.functionVersion, | ||
LAMBDA_EVENT: stringify(event), | ||
LAMBDA_TEST_EVENT: `${event}`, | ||
LAMBDA_CONTEXT: stringify(context), | ||
IS_LAMBDA_AUTHORIZER: | ||
event.type === 'REQUEST' || event.type === 'TOKEN', | ||
IS_LAMBDA_REQUEST_AUTHORIZER: event.type === 'REQUEST', | ||
IS_LAMBDA_TOKEN_AUTHORIZER: event.type === 'TOKEN', | ||
PATH: process.env.PATH, | ||
}, | ||
encoding: 'utf-8', | ||
}) | ||
|
||
// Clean up after we created the temporary file | ||
await this.cleanup() | ||
|
||
if (stderr) { | ||
return stderr | ||
} | ||
|
||
return this._parsePayload(stdout) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './GoRunner.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import execa from 'execa' | ||
|
||
export default async function checkGoVersion() { | ||
let goVersion | ||
try { | ||
const { stdout } = await execa('go', ['version']) | ||
if (stdout.match(/go1.\d+/g)) { | ||
goVersion = '1.x' | ||
} | ||
} catch (err) { | ||
// @ignore | ||
} | ||
|
||
return goVersion | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
bin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module serverless-offline-go1.x-test | ||
|
||
go 1.13 | ||
|
||
require ( | ||
github.com/aws/aws-lambda-go v1.28.0 | ||
github.com/icarus-sullivan/mock-lambda v0.0.0-20220115083805-e065469e964a // indirect | ||
github.com/urfave/cli v1.22.1 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||
github.com/aws/aws-lambda-go v1.13.2 h1:8lYuRVn6rESoUNZXdbCmtGB4bBk4vcVYojiHjE4mMrM= | ||
github.com/aws/aws-lambda-go v1.13.2/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= | ||
github.com/aws/aws-lambda-go v1.28.0 h1:fZiik1PZqW2IyAN4rj+Y0UBaO1IDFlsNo9Zz/XnArK4= | ||
github.com/aws/aws-lambda-go v1.28.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= | ||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= | ||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= | ||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/icarus-sullivan/mock-lambda v0.0.0-20220114085425-44091545252e h1:cPv6jHZPqHlu73UmtFEVPRNHGnSrd43OKwpQKVktLcs= | ||
github.com/icarus-sullivan/mock-lambda v0.0.0-20220114085425-44091545252e/go.mod h1:2iuLAENWZqxe/B6XUDWw/3ioQ9d1fwhgFTlwVeIBpzY= | ||
github.com/icarus-sullivan/mock-lambda v0.0.0-20220115083805-e065469e964a h1:gmFO6gLHZkdJlkZ41QiQ5tzH8LORPVJCuKk6YKyquU0= | ||
github.com/icarus-sullivan/mock-lambda v0.0.0-20220115083805-e065469e964a/go.mod h1:2iuLAENWZqxe/B6XUDWw/3ioQ9d1fwhgFTlwVeIBpzY= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | ||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | ||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | ||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= | ||
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | ||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { platform } from 'os' | ||
import { resolve } from 'path' | ||
import fetch from 'node-fetch' | ||
import { joinUrl, setup, teardown } from '../../_testHelpers/index.js' | ||
|
||
jest.setTimeout(180000) | ||
|
||
const _describe = | ||
process.env.GO1X_DETECTED && platform() !== 'win32' ? describe : describe.skip | ||
|
||
_describe('Go 1.x with GoRunner', () => { | ||
// init | ||
beforeAll(() => | ||
setup({ | ||
servicePath: resolve(__dirname), | ||
}), | ||
) | ||
|
||
// cleanup | ||
afterAll(() => teardown()) | ||
|
||
// | ||
;[ | ||
{ | ||
description: 'should work with go1.x', | ||
expected: { | ||
message: 'Hello Go 1.x!', | ||
}, | ||
path: '/dev/hello', | ||
}, | ||
].forEach(({ description, expected, path }) => { | ||
test(description, async () => { | ||
const url = joinUrl(TEST_BASE_URL, path) | ||
const response = await fetch(url) | ||
const json = await response.json() | ||
|
||
expect(json).toEqual(expected) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/aws/aws-lambda-go/events" | ||
"github.com/aws/aws-lambda-go/lambda" | ||
) | ||
|
||
func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { | ||
return events.APIGatewayProxyResponse{ | ||
Body: "{\"message\": \"Hello Go 1.x!\"}", | ||
StatusCode: 200, | ||
}, nil | ||
} | ||
|
||
func main() { | ||
lambda.Start(Handler) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
service: docker-go-1.x-tests | ||
|
||
plugins: | ||
- ../../../../ | ||
|
||
provider: | ||
memorySize: 128 | ||
name: aws | ||
region: us-east-1 # default | ||
runtime: go1.x | ||
stage: dev | ||
versionFunctions: false | ||
|
||
functions: | ||
hello: | ||
events: | ||
- http: | ||
method: get | ||
path: hello | ||
handler: hello/main.go |