Skip to content

Commit 49c35f6

Browse files
authored
v1.3 release
Merge changes for v1.3 release
2 parents b57d8f4 + 2ca3e4a commit 49c35f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1528
-388
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ compile-lambda-linux-all:
2121
make ARCH=old compile-lambda-linux
2222

2323
compile-with-docker:
24-
docker run --env GOPROXY=direct -v $(shell pwd):/LambdaRuntimeLocal -w /LambdaRuntimeLocal golang:1.14 make ARCH=${ARCH} compile-lambda-linux
24+
docker run --env GOPROXY=direct -v $(shell pwd):/LambdaRuntimeLocal -w /LambdaRuntimeLocal golang:1.17 make ARCH=${ARCH} compile-lambda-linux
2525

2626
compile-lambda-linux:
2727
CGO_ENABLED=0 GOOS=linux GOARCH=${GO_ARCH_${ARCH}} go build -ldflags "${RELEASE_BUILD_LINKER_FLAGS}" -o ${DESTINATION_${ARCH}} ./cmd/aws-lambda-rie

cmd/aws-lambda-rie/main.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ const (
2121
)
2222

2323
type options struct {
24-
LogLevel string `long:"log-level" default:"info" description:"log level"`
24+
LogLevel string `long:"log-level" default:"info" description:"log level"`
25+
InitCachingEnabled bool `long:"enable-init-caching" description:"Enable support for Init Caching"`
2526
}
2627

2728
func main() {
@@ -32,7 +33,11 @@ func main() {
3233
rapidcore.SetLogLevel(opts.LogLevel)
3334

3435
bootstrap, handler := getBootstrap(args, opts)
35-
sandbox := rapidcore.NewSandboxBuilder(bootstrap).AddShutdownFunc(context.CancelFunc(func() { os.Exit(0) })).SetExtensionsFlag(true)
36+
sandbox := rapidcore.
37+
NewSandboxBuilder(bootstrap).
38+
AddShutdownFunc(context.CancelFunc(func() { os.Exit(0) })).
39+
SetExtensionsFlag(true).
40+
SetInitCachingFlag(opts.InitCachingEnabled)
3641

3742
if len(handler) > 0 {
3843
sandbox.SetHandler(handler)
@@ -72,7 +77,7 @@ func getBootstrap(args []string, opts options) (*rapidcore.Bootstrap, string) {
7277
fmt.Sprintf("%s/bootstrap", currentWorkingDir),
7378
}
7479

75-
if !isBootstrapFileExist(bootstrapLookupCmd[0]) {
80+
if !isBootstrapFileExist(bootstrapLookupCmd[0]) {
7681
var bootstrapCmdCandidates = []string{
7782
optBootstrap,
7883
runtimeBootstrap,

go.mod

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
module go.amzn.com
22

3-
go 1.13
3+
go 1.17
44

55
require (
66
github.com/aws/aws-lambda-go v1.20.0
77
github.com/go-chi/chi v4.1.2+incompatible
88
github.com/go-chi/render v1.0.1
99
github.com/google/uuid v1.1.2
1010
github.com/jessevdk/go-flags v1.4.0
11-
github.com/pkg/errors v0.9.1
1211
github.com/sirupsen/logrus v1.6.0
13-
github.com/stretchr/objx v0.3.0 // indirect
1412
github.com/stretchr/testify v1.6.1
1513
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
1614
)
15+
16+
require (
17+
github.com/davecgh/go-spew v1.1.1 // indirect
18+
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
19+
github.com/pmezard/go-difflib v1.0.0 // indirect
20+
github.com/stretchr/objx v0.3.0 // indirect
21+
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a // indirect
22+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da // indirect
23+
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
24+
)

go.sum

+11-4
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
1414
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
1515
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
1616
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
17+
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
1718
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
18-
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
19-
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
2019
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2120
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2221
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -26,16 +25,24 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf
2625
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
2726
github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As=
2827
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
29-
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
3028
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
3129
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
3230
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
3331
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
3432
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
33+
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a h1:c83jeVQW0KGKNaKBRfelNYNHaev+qawl9yaA825s8XE=
34+
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
3535
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
3636
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
37-
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
3837
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
38+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
39+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
40+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
41+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
42+
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
43+
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
44+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
45+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
3946
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4047
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
4148
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

lambda/agents/agent.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,12 @@ type ExternalAgentProcess struct {
2525
}
2626

2727
// NewExternalAgentProcess returns a new external agent process
28-
func NewExternalAgentProcess(path string, env []string, logWriter io.Writer) ExternalAgentProcess {
28+
func NewExternalAgentProcess(path string, env []string, stdoutWriter io.Writer, stderrWriter io.Writer) ExternalAgentProcess {
2929
command := exec.Command(path)
3030
command.Env = env
3131

32-
w := NewNewlineSplitWriter(logWriter)
33-
command.Stdout = w
34-
command.Stderr = w
32+
command.Stdout = NewNewlineSplitWriter(stdoutWriter)
33+
command.Stderr = NewNewlineSplitWriter(stderrWriter)
3534
command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
3635

3736
return ExternalAgentProcess{

lambda/agents/agent_test.go

+54-8
Original file line numberDiff line numberDiff line change
@@ -204,30 +204,76 @@ func TestFindAgentMixed(t *testing.T) {
204204
// Test our ability to start agents
205205
func TestAgentStart(t *testing.T) {
206206
assert := assert.New(t)
207-
agent := NewExternalAgentProcess("../testdata/agents/bash_true.sh", []string{}, &mockWriter{})
207+
agent := NewExternalAgentProcess("../testdata/agents/bash_true.sh", []string{}, &mockWriter{}, &mockWriter{})
208208
assert.Nil(agent.Start())
209209
assert.Nil(agent.Wait())
210210
}
211211

212212
// Test that execution of invalid agents is correctly reported
213213
func TestInvalidAgentStart(t *testing.T) {
214214
assert := assert.New(t)
215-
agent := NewExternalAgentProcess("/bin/none", []string{}, &mockWriter{})
215+
agent := NewExternalAgentProcess("/bin/none", []string{}, &mockWriter{}, &mockWriter{})
216216
assert.True(os.IsNotExist(agent.Start()))
217217
}
218218

219-
// Test that execution of invalid agents is correctly reported
220-
func TestAgentTelemetry(t *testing.T) {
219+
func TestAgentStdoutWriter(t *testing.T) {
220+
// Given
221+
assert := assert.New(t)
222+
223+
stdout := &mockWriter{}
224+
stderr := &mockWriter{}
225+
expectedStdout := "stdout line 1\nstdout line 2\nstdout line 3\n"
226+
expectedStderr := ""
227+
228+
agent := NewExternalAgentProcess("../testdata/agents/bash_stdout.sh", []string{}, stdout, stderr)
229+
230+
// When
231+
assert.NoError(agent.Start())
232+
assert.NoError(agent.Wait())
233+
234+
// Then
235+
assert.Equal(expectedStdout, string(bytes.Join(stdout.bytesReceived, []byte(""))))
236+
assert.Equal(expectedStderr, string(bytes.Join(stderr.bytesReceived, []byte(""))))
237+
}
238+
239+
func TestAgentStderrWriter(t *testing.T) {
240+
// Given
221241
assert := assert.New(t)
222-
buffer := &mockWriter{}
223242

224-
agent := NewExternalAgentProcess("../testdata/agents/bash_echo.sh", []string{}, buffer)
243+
stdout := &mockWriter{}
244+
stderr := &mockWriter{}
245+
expectedStdout := ""
246+
expectedStderr := "stderr line 1\nstderr line 2\nstderr line 3\n"
247+
248+
agent := NewExternalAgentProcess("../testdata/agents/bash_stderr.sh", []string{}, stdout, stderr)
249+
250+
// When
251+
assert.NoError(agent.Start())
252+
assert.NoError(agent.Wait())
253+
254+
// Then
255+
assert.Equal(expectedStdout, string(bytes.Join(stdout.bytesReceived, []byte(""))))
256+
assert.Equal(expectedStderr, string(bytes.Join(stderr.bytesReceived, []byte(""))))
257+
}
258+
259+
func TestAgentStdoutAndStderrSeperateWriters(t *testing.T) {
260+
// Given
261+
assert := assert.New(t)
262+
263+
stdout := &mockWriter{}
264+
stderr := &mockWriter{}
265+
expectedStdout := "stdout line 1\nstdout line 2\nstdout line 3\n"
266+
expectedStderr := "stderr line 1\nstderr line 2\nstderr line 3\n"
267+
268+
agent := NewExternalAgentProcess("../testdata/agents/bash_stdout_and_stderr.sh", []string{}, stdout, stderr)
225269

270+
// When
226271
assert.NoError(agent.Start())
227272
assert.NoError(agent.Wait())
228273

229-
message := "hello world\n|barbaz\n|hello world\n|barbaz2"
230-
assert.Equal(message, string(bytes.Join(buffer.bytesReceived, []byte("|"))))
274+
// Then
275+
assert.Equal(expectedStdout, string(bytes.Join(stdout.bytesReceived, []byte(""))))
276+
assert.Equal(expectedStderr, string(bytes.Join(stderr.bytesReceived, []byte(""))))
231277
}
232278

233279
type mockWriter struct {

lambda/appctx/appctxutil.go

+72-16
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ package appctx
55

66
import (
77
"context"
8-
"net/http"
9-
"strings"
10-
118
"go.amzn.com/lambda/fatalerror"
129
"go.amzn.com/lambda/interop"
10+
"net/http"
11+
"strings"
1312

1413
log "github.com/sirupsen/logrus"
1514
)
@@ -24,6 +23,9 @@ type ReqCtxKey int
2423
// context object into request context.
2524
const ReqCtxApplicationContextKey ReqCtxKey = iota
2625

26+
// MaxRuntimeReleaseLength Max length for user agent string.
27+
const MaxRuntimeReleaseLength = 128
28+
2729
// FromRequest retrieves application context from the request context.
2830
func FromRequest(request *http.Request) ApplicationContext {
2931
return request.Context().Value(ReqCtxApplicationContextKey).(ApplicationContext)
@@ -39,24 +41,78 @@ func GetRuntimeRelease(appCtx ApplicationContext) string {
3941
return appCtx.GetOrDefault(AppCtxRuntimeReleaseKey, "").(string)
4042
}
4143

42-
// UpdateAppCtxWithRuntimeRelease extracts runtime release info from user agent header and put it into appCtx.
44+
// GetUserAgentFromRequest Returns the first token -seperated by a space-
45+
// from request header 'User-Agent'.
46+
func GetUserAgentFromRequest(request *http.Request) string {
47+
runtimeRelease := ""
48+
userAgent := request.Header.Get("User-Agent")
49+
// Split around spaces and use only the first token.
50+
if fields := strings.Fields(userAgent); len(fields) > 0 && len(fields[0]) > 0 {
51+
runtimeRelease = fields[0]
52+
}
53+
return runtimeRelease
54+
}
55+
56+
// CreateRuntimeReleaseFromRequest Gets runtime features from request header
57+
// 'Lambda-Runtime-Features', and append it to the given runtime release.
58+
func CreateRuntimeReleaseFromRequest(request *http.Request, runtimeRelease string) string {
59+
lambdaRuntimeFeaturesHeader := request.Header.Get("Lambda-Runtime-Features")
60+
61+
// "(", ")" are not valid token characters, and potentially could invalidate runtime_release
62+
lambdaRuntimeFeaturesHeader = strings.ReplaceAll(lambdaRuntimeFeaturesHeader, "(", "")
63+
lambdaRuntimeFeaturesHeader = strings.ReplaceAll(lambdaRuntimeFeaturesHeader, ")", "")
64+
65+
numberOfAppendedFeatures := 0
66+
// Available length is a maximum length available for runtime features (including delimiters). From maximal runtime
67+
// release length we subtract what we already have plus 3 additional bytes for a space and a pair of brackets for
68+
// list of runtime features that is added later.
69+
runtimeReleaseLength := len(runtimeRelease)
70+
if runtimeReleaseLength == 0 {
71+
runtimeReleaseLength = len("Unknown")
72+
}
73+
availableLength := MaxRuntimeReleaseLength - runtimeReleaseLength - 3
74+
var lambdaRuntimeFeatures []string
75+
76+
for _, feature := range strings.Fields(lambdaRuntimeFeaturesHeader) {
77+
featureLength := len(feature)
78+
// If featureLength <= availableLength - numberOfAppendedFeatures
79+
// (where numberOfAppendedFeatures is equal to number of delimiters needed).
80+
if featureLength <= availableLength-numberOfAppendedFeatures {
81+
availableLength -= featureLength
82+
lambdaRuntimeFeatures = append(lambdaRuntimeFeatures, feature)
83+
numberOfAppendedFeatures++
84+
}
85+
}
86+
// Append valid features to runtime release.
87+
if len(lambdaRuntimeFeatures) > 0 {
88+
if runtimeRelease == "" {
89+
runtimeRelease = "Unknown"
90+
}
91+
runtimeRelease += " (" + strings.Join(lambdaRuntimeFeatures, " ") + ")"
92+
}
93+
94+
return runtimeRelease
95+
}
96+
97+
// UpdateAppCtxWithRuntimeRelease extracts runtime release info from user agent & lambda runtime features
98+
// headers and update it into appCtx.
4399
// Sample UA:
44100
// Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0
45101
func UpdateAppCtxWithRuntimeRelease(request *http.Request, appCtx ApplicationContext) bool {
46-
// If appCtx has runtime release value already, skip updating for consistency.
47-
if len(GetRuntimeRelease(appCtx)) > 0 {
48-
return false
49-
}
50-
51-
userAgent := request.Header.Get("User-Agent")
52-
if len(userAgent) == 0 {
102+
// If appCtx has runtime release value already, just append the runtime features.
103+
if appCtxRuntimeRelease := GetRuntimeRelease(appCtx); len(appCtxRuntimeRelease) > 0 {
104+
// if the runtime features are not appended before append them, otherwise ignore
105+
if runtimeReleaseWithFeatures := CreateRuntimeReleaseFromRequest(request, appCtxRuntimeRelease); len(runtimeReleaseWithFeatures) > len(appCtxRuntimeRelease) &&
106+
appCtxRuntimeRelease[len(appCtxRuntimeRelease)-1] != ')' {
107+
appCtx.Store(AppCtxRuntimeReleaseKey, runtimeReleaseWithFeatures)
108+
return true
109+
}
53110
return false
54111
}
55-
56-
// Split around spaces and use only the first token.
57-
if fields := strings.Fields(userAgent); len(fields) > 0 && len(fields[0]) > 0 {
58-
appCtx.Store(AppCtxRuntimeReleaseKey,
59-
fields[0])
112+
// If appCtx doesn't have runtime release value, update it with user agent and runtime features.
113+
if runtimeReleaseWithFeatures := CreateRuntimeReleaseFromRequest(request,
114+
GetUserAgentFromRequest(request)); runtimeReleaseWithFeatures != "" {
115+
appCtx.Store(AppCtxRuntimeReleaseKey, runtimeReleaseWithFeatures)
60116
return true
61117
}
62118
return false

0 commit comments

Comments
 (0)