Skip to content

Merge changes for v1.15 release #105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ compile-lambda-linux-all:
make ARCH=old compile-lambda-linux

compile-with-docker:
docker run --env GOPROXY=direct -v $(shell pwd):/LambdaRuntimeLocal -w /LambdaRuntimeLocal golang:1.19 make ARCH=${ARCH} compile-lambda-linux
docker run --env GOPROXY=direct -v $(shell pwd):/LambdaRuntimeLocal -w /LambdaRuntimeLocal golang:1.20 make ARCH=${ARCH} compile-lambda-linux

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

tests:
go test ./...
Expand Down
5 changes: 3 additions & 2 deletions cmd/aws-lambda-rie/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"runtime/debug"

"github.com/jessevdk/go-flags"
"go.amzn.com/lambda/interop"
"go.amzn.com/lambda/rapidcore"

log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -103,7 +104,7 @@ func isBootstrapFileExist(filePath string) bool {
return !os.IsNotExist(err) && !file.IsDir()
}

func getBootstrap(args []string, opts options) (*rapidcore.Bootstrap, string) {
func getBootstrap(args []string, opts options) (interop.Bootstrap, string) {
var bootstrapLookupCmd []string
var handler string
currentWorkingDir := "/var/task" // default value
Expand Down Expand Up @@ -149,5 +150,5 @@ func getBootstrap(args []string, opts options) (*rapidcore.Bootstrap, string) {
log.Panic("insufficient arguments: bootstrap not provided")
}

return rapidcore.NewBootstrapSingleCmd(bootstrapLookupCmd, currentWorkingDir, ""), handler
return NewSimpleBootstrap(bootstrapLookupCmd, currentWorkingDir), handler
}
69 changes: 69 additions & 0 deletions cmd/aws-lambda-rie/simple_bootstrap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package main

import (
"fmt"
"os"
"path/filepath"

"go.amzn.com/lambda/fatalerror"
"go.amzn.com/lambda/interop"
"go.amzn.com/lambda/rapidcore/env"
)

// the type implement a simpler version of the Bootstrap
// this is useful in the Standalone Core implementation.
type simpleBootstrap struct {
cmd []string
workingDir string
}

func NewSimpleBootstrap(cmd []string, currentWorkingDir string) interop.Bootstrap {
if currentWorkingDir == "" {
// use the root directory as the default working directory
currentWorkingDir = "/"
}

// a single candidate command makes it automatically valid
return &simpleBootstrap{
cmd: cmd,
workingDir: currentWorkingDir,
}
}

func (b *simpleBootstrap) Cmd() ([]string, error) {
return b.cmd, nil
}

// Cwd returns the working directory of the bootstrap process
// The path is validated against the chroot identified by `root`
func (b *simpleBootstrap) Cwd() (string, error) {
if !filepath.IsAbs(b.workingDir) {
return "", fmt.Errorf("the working directory '%s' is invalid, it needs to be an absolute path", b.workingDir)
}

// evaluate the path relatively to the domain's mnt namespace root
if _, err := os.Stat(b.workingDir); os.IsNotExist(err) {
return "", fmt.Errorf("the working directory doesn't exist: %s", b.workingDir)
}

return b.workingDir, nil
}

// Env returns the environment variables available to
// the bootstrap process
func (b *simpleBootstrap) Env(e *env.Environment) map[string]string {
return e.RuntimeExecEnv()
}

// ExtraFiles returns the extra file descriptors apart from 1 & 2 to be passed to runtime
func (b *simpleBootstrap) ExtraFiles() []*os.File {
return make([]*os.File, 0)
}

func (b *simpleBootstrap) CachedFatalError(err error) (fatalerror.ErrorType, string, bool) {
// not implemented as it is not needed in Core but we need to fullfil the interface anyway
return fatalerror.ErrorType(""), "", false
}
78 changes: 78 additions & 0 deletions cmd/aws-lambda-rie/simple_bootstrap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package main

import (
"os"
"reflect"
"testing"

"go.amzn.com/lambda/rapidcore/env"

"github.com/stretchr/testify/assert"
)

func TestSimpleBootstrap(t *testing.T) {
tmpFile, err := os.CreateTemp("", "oci-test-bootstrap")
assert.NoError(t, err)
defer os.Remove(tmpFile.Name())

// Setup single cmd candidate
file := []string{tmpFile.Name(), "--arg1 s", "foo"}
cmdCandidate := file

// Setup working dir
cwd, err := os.Getwd()
assert.NoError(t, err)

// Setup environment
environment := env.NewEnvironment()
environment.StoreRuntimeAPIEnvironmentVariable("host:port")
environment.StoreEnvironmentVariablesFromInit(map[string]string{}, "", "", "", "", "", "")

// Test
b := NewSimpleBootstrap(cmdCandidate, cwd)
bCwd, err := b.Cwd()
assert.NoError(t, err)
assert.Equal(t, cwd, bCwd)
assert.True(t, reflect.DeepEqual(environment.RuntimeExecEnv(), b.Env(environment)))

cmd, err := b.Cmd()
assert.NoError(t, err)
assert.Equal(t, file, cmd)
}

func TestSimpleBootstrapCmdNonExistingCandidate(t *testing.T) {
// Setup inexistent single cmd candidate
file := []string{"/foo/bar", "--arg1 s", "foo"}
cmdCandidate := file

// Setup working dir
cwd, err := os.Getwd()
assert.NoError(t, err)

// Setup environment
environment := env.NewEnvironment()
environment.StoreRuntimeAPIEnvironmentVariable("host:port")
environment.StoreEnvironmentVariablesFromInit(map[string]string{}, "", "", "", "", "", "")

// Test
b := NewSimpleBootstrap(cmdCandidate, cwd)
bCwd, err := b.Cwd()
assert.NoError(t, err)
assert.Equal(t, cwd, bCwd)
assert.True(t, reflect.DeepEqual(environment.RuntimeExecEnv(), b.Env(environment)))

// No validations run against single candidates
cmd, err := b.Cmd()
assert.NoError(t, err)
assert.Equal(t, file, cmd)
}

func TestSimpleBootstrapCmdDefaultWorkingDir(t *testing.T) {
b := NewSimpleBootstrap([]string{}, "")
bCwd, err := b.Cwd()
assert.NoError(t, err)
assert.Equal(t, "/", bCwd)
}
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module go.amzn.com

go 1.19
go 1.20

require (
github.com/aws/aws-lambda-go v1.41.0
Expand All @@ -16,7 +16,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/net v0.18.0 // indirect
golang.org/x/sys v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
10 changes: 5 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
10 changes: 9 additions & 1 deletion lambda/agents/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,18 @@ func ListExternalAgentPaths(dir string, root string) []string {
}
fullDir := path.Join(root, dir)
files, err := os.ReadDir(fullDir)

if err != nil {
log.WithError(err).Warning("Cannot list external agents")
if os.IsNotExist(err) {
log.Infof("The extension's directory %q does not exist, assuming no extensions to be loaded.", fullDir)
} else {
// TODO - Should this return an error rather than ignore failing to load?
log.WithError(err).Error("Cannot list external agents")
}

return agentPaths
}

for _, file := range files {
if !file.IsDir() {
// The returned path is absolute wrt to `root`. This allows
Expand Down
7 changes: 5 additions & 2 deletions lambda/appctx/appctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ type Key int
type InitType int

const (
// AppCtxInvokeErrorResponseKey is used for storing deferred invoke error response.
// AppCtxInvokeErrorTraceDataKey is used for storing deferred invoke error cause header value.
// Only used by xray. TODO refactor xray interface so it doesn't use appctx
AppCtxInvokeErrorResponseKey Key = iota
AppCtxInvokeErrorTraceDataKey Key = iota

// AppCtxRuntimeReleaseKey is used for storing runtime release information (parsed from User_Agent Http header string).
AppCtxRuntimeReleaseKey

// AppCtxInteropServerKey is used to store a reference to the interop server.
AppCtxInteropServerKey

// AppCtxResponseSenderKey is used to store a reference to the response sender
AppCtxResponseSenderKey

// AppCtxFirstFatalErrorKey is used to store first unrecoverable error message encountered to propagate it to slicer with DONE(errortype) or DONEFAIL(errortype)
AppCtxFirstFatalErrorKey

Expand Down
28 changes: 21 additions & 7 deletions lambda/appctx/appctxutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,16 @@ func UpdateAppCtxWithRuntimeRelease(request *http.Request, appCtx ApplicationCon
return false
}

// StoreErrorResponse stores response in the applicaton context.
func StoreErrorResponse(appCtx ApplicationContext, errorResponse *interop.ErrorResponse) {
appCtx.Store(AppCtxInvokeErrorResponseKey, errorResponse)
// StoreInvokeErrorTraceData stores invocation error x-ray cause header in the applicaton context.
func StoreInvokeErrorTraceData(appCtx ApplicationContext, invokeError *interop.InvokeErrorTraceData) {
appCtx.Store(AppCtxInvokeErrorTraceDataKey, invokeError)
}

// LoadErrorResponse retrieves response from the application context.
func LoadErrorResponse(appCtx ApplicationContext) *interop.ErrorResponse {
v, ok := appCtx.Load(AppCtxInvokeErrorResponseKey)
// LoadInvokeErrorTraceData retrieves invocation error x-ray cause header from the application context.
func LoadInvokeErrorTraceData(appCtx ApplicationContext) *interop.InvokeErrorTraceData {
v, ok := appCtx.Load(AppCtxInvokeErrorTraceDataKey)
if ok {
return v.(*interop.ErrorResponse)
return v.(*interop.InvokeErrorTraceData)
}
return nil
}
Expand All @@ -147,6 +147,20 @@ func LoadInteropServer(appCtx ApplicationContext) interop.Server {
return nil
}

// StoreResponseSender stores a reference to the response sender
func StoreResponseSender(appCtx ApplicationContext, server interop.InvokeResponseSender) {
appCtx.Store(AppCtxResponseSenderKey, server)
}

// LoadResponseSender retrieves the response sender
func LoadResponseSender(appCtx ApplicationContext) interop.InvokeResponseSender {
v, ok := appCtx.Load(AppCtxResponseSenderKey)
if ok {
return v.(interop.InvokeResponseSender)
}
return nil
}

// StoreFirstFatalError stores unrecoverable error code in appctx once. This error is considered to be the rootcause of failure
func StoreFirstFatalError(appCtx ApplicationContext, err fatalerror.ErrorType) {
if existing := appCtx.StoreIfNotExists(AppCtxFirstFatalErrorKey, err); existing != nil {
Expand Down
Loading