Skip to content

Pull upstream changes into main #30

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 5 commits into from
Feb 1, 2024
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=arm64 compile-lambda-linux

compile-with-docker:
docker run --rm --env GOPROXY=direct -v $(shell pwd):/LambdaRuntimeLocal -w /LambdaRuntimeLocal golang:1.19 make ARCH=${ARCH} compile-lambda-linux
docker run --rm --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}" -gcflags="${GC_FLAGS}" -o ${DESTINATION_${ARCH}} ./cmd/localstack
CGO_ENABLED=0 GOOS=linux GOARCH=${GO_ARCH_${ARCH}} go build -buildvcs=false -ldflags "${RELEASE_BUILD_LINKER_FLAGS}" -gcflags="${GC_FLAGS}" -o ${DESTINATION_${ARCH}} ./cmd/localstack

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)
}
8 changes: 4 additions & 4 deletions cmd/localstack/awsutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"fmt"
log "github.com/sirupsen/logrus"
"go.amzn.com/lambda/interop"
"go.amzn.com/lambda/rapidcore"
"go.amzn.com/lambda/rapidcore/env"
"golang.org/x/sys/unix"
"io"
Expand All @@ -34,7 +33,7 @@ func isBootstrapFileExist(filePath string) bool {
return !os.IsNotExist(err) && !file.IsDir()
}

func getBootstrap(args []string) (*rapidcore.Bootstrap, string) {
func getBootstrap(args []string) (interop.Bootstrap, string) {
var bootstrapLookupCmd []string
var handler string
currentWorkingDir := "/var/task" // default value
Expand Down Expand Up @@ -89,7 +88,7 @@ func getBootstrap(args []string) (*rapidcore.Bootstrap, string) {
}
}

return rapidcore.NewBootstrapSingleCmd(bootstrapLookupCmd, currentWorkingDir, ""), handler
return NewSimpleBootstrap(bootstrapLookupCmd, currentWorkingDir), handler
}

func PrintEndReports(invokeId string, initDuration string, memorySize string, invokeStart time.Time, timeoutDuration time.Duration, w io.Writer) {
Expand Down Expand Up @@ -205,7 +204,7 @@ func getSubFoldersInList(prefix string, pathList []string) (oldFolders []string,
return
}

func InitHandler(sandbox Sandbox, functionVersion string, timeout int64, bs interop.Bootstrap) (time.Time, time.Time) {
func InitHandler(sandbox Sandbox, functionVersion string, timeout int64, bs interop.Bootstrap, accountId string) (time.Time, time.Time) {
additionalFunctionEnvironmentVariables := map[string]string{}

// Add default Env Vars if they were not defined. This is a required otherwise 1p Python2.7, Python3.6, and
Expand All @@ -231,6 +230,7 @@ func InitHandler(sandbox Sandbox, functionVersion string, timeout int64, bs inte
AwsKey: os.Getenv("AWS_ACCESS_KEY_ID"),
AwsSecret: os.Getenv("AWS_SECRET_ACCESS_KEY"),
AwsSession: os.Getenv("AWS_SESSION_TOKEN"),
AccountID: accountId,
XRayDaemonAddress: GetenvWithDefault("AWS_XRAY_DAEMON_ADDRESS", "127.0.0.1:2000"),
FunctionName: GetenvWithDefault("AWS_LAMBDA_FUNCTION_NAME", "test_function"),
FunctionVersion: functionVersion,
Expand Down
16 changes: 8 additions & 8 deletions cmd/localstack/custom_interop.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,23 +194,23 @@ func NewCustomInteropServer(lsOpts *LsOpts, delegate interop.Server, logCollecto
return server
}

func (c *CustomInteropServer) SendResponse(invokeID string, headers map[string]string, reader io.Reader, trailers http.Header, request *interop.CancellableRequest) error {
func (c *CustomInteropServer) SendResponse(invokeID string, resp *interop.StreamableInvokeResponse) error {
log.Traceln("SendResponse called")
return c.delegate.SendResponse(invokeID, headers, reader, trailers, request)
return c.delegate.SendResponse(invokeID, resp)
}

func (c *CustomInteropServer) SendErrorResponse(invokeID string, response *interop.ErrorResponse) error {
func (c *CustomInteropServer) SendErrorResponse(invokeID string, resp *interop.ErrorInvokeResponse) error {
log.Traceln("SendErrorResponse called")
return c.delegate.SendErrorResponse(invokeID, response)
return c.delegate.SendErrorResponse(invokeID, resp)
}

// SendInitErrorResponse writes error response during init to a shared memory and sends GIRD FAULT.
func (c *CustomInteropServer) SendInitErrorResponse(invokeID string, response *interop.ErrorResponse) error {
func (c *CustomInteropServer) SendInitErrorResponse(resp *interop.ErrorInvokeResponse) error {
log.Traceln("SendInitErrorResponse called")
if err := c.localStackAdapter.SendStatus(Error, response.Payload); err != nil {
if err := c.localStackAdapter.SendStatus(Error, resp.Payload); err != nil {
log.Fatalln("Failed to send init error to LocalStack " + err.Error() + ". Exiting.")
}
return c.delegate.SendInitErrorResponse(invokeID, response)
return c.delegate.SendInitErrorResponse(resp)
}

func (c *CustomInteropServer) GetCurrentInvokeID() string {
Expand Down Expand Up @@ -248,7 +248,7 @@ func (c *CustomInteropServer) Reset(reason string, timeoutMs int64) (*statejson.
return c.delegate.Reset(reason, timeoutMs)
}

func (c *CustomInteropServer) AwaitRelease() (*statejson.InternalStateDescription, error) {
func (c *CustomInteropServer) AwaitRelease() (*statejson.ReleaseResponse, error) {
log.Traceln("AwaitRelease called")
return c.delegate.AwaitRelease()
}
Expand Down
5 changes: 4 additions & 1 deletion cmd/localstack/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type LsOpts struct {
InteropPort string
RuntimeEndpoint string
RuntimeId string
AccountId string
InitTracingPort string
User string
CodeArchives string
Expand All @@ -41,6 +42,7 @@ func InitLsOpts() *LsOpts {
// required
RuntimeEndpoint: GetEnvOrDie("LOCALSTACK_RUNTIME_ENDPOINT"),
RuntimeId: GetEnvOrDie("LOCALSTACK_RUNTIME_ID"),
AccountId: GetenvWithDefault("LOCALSTACK_FUNCTION_ACCOUNT_ID", "000000000000"),
// optional with default
InteropPort: GetenvWithDefault("LOCALSTACK_INTEROP_PORT", "9563"),
InitTracingPort: GetenvWithDefault("LOCALSTACK_RUNTIME_TRACING_PORT", "9564"),
Expand Down Expand Up @@ -72,6 +74,7 @@ func UnsetLsEnvs() {
"LOCALSTACK_ENABLE_XRAY_TELEMETRY",
"LOCALSTACK_INIT_LOG_LEVEL",
"LOCALSTACK_POST_INVOKE_WAIT_MS",
"LOCALSTACK_FUNCTION_ACCOUNT_ID",

// Docker container ID
"HOSTNAME",
Expand Down Expand Up @@ -230,7 +233,7 @@ func main() {
// start runtime init. It is important to start `InitHandler` synchronously because we need to ensure the
// notification channels and status fields are properly initialized before `AwaitInitialized`
log.Debugln("Starting runtime init.")
InitHandler(sandbox.LambdaInvokeAPI(), GetEnvOrDie("AWS_LAMBDA_FUNCTION_VERSION"), int64(invokeTimeoutSeconds), bootstrap) // TODO: replace this with a custom init
InitHandler(sandbox.LambdaInvokeAPI(), GetEnvOrDie("AWS_LAMBDA_FUNCTION_VERSION"), int64(invokeTimeoutSeconds), bootstrap, lsOpts.AccountId) // TODO: replace this with a custom init

log.Debugln("Awaiting initialization of runtime init.")
if err := interopServer.delegate.AwaitInitialized(); err != nil {
Expand Down
69 changes: 69 additions & 0 deletions cmd/localstack/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
}
Loading