docker-lambda
Advanced tools
+1
-1
| { | ||
| "name": "docker-lambda", | ||
| "version": "0.15.0", | ||
| "version": "0.15.1", | ||
| "description": "A Docker image and test runner that (very closely) mimics the live AWS Lambda environment", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
| FROM lambci/lambda-base:build | ||
| ENV PATH=/var/lang/bin:/usr/local/bin:/usr/bin/:/bin \ | ||
| LD_LIBRARY_PATH=/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib \ | ||
| AWS_EXECUTION_ENV=AWS_Lambda_dotnetcore2.0 \ | ||
| DOTNET_SDK_VERSION=2.1.3 \ | ||
| DOTNET_CLI_TELEMETRY_OPTOUT=1 \ | ||
| NUGET_XMLDOC_MODE=skip | ||
| RUN rm -rf /var/runtime /var/lang && \ | ||
| curl https://lambci.s3.amazonaws.com/fs/dotnetcore2.0.tgz | tar -zx -C / && \ | ||
| yum install -y libunwind && \ | ||
| curl https://dot.net/v1/dotnet-install.sh | bash -s -- -v $DOTNET_SDK_VERSION -i /var/lang/bin && \ | ||
| mkdir /tmp/warmup && \ | ||
| cd /tmp/warmup && \ | ||
| dotnet new && \ | ||
| cd / && \ | ||
| rm -rf /tmp/warmup /tmp/NuGetScratch | ||
| CMD ["dotnet", "build"] |
| FROM microsoft/dotnet:2.0-sdk | ||
| WORKDIR /source | ||
| # cache restore result | ||
| COPY MockBootstraps/*.csproj . | ||
| RUN dotnet restore | ||
| # copy the rest of the code | ||
| COPY MockBootstraps/ . | ||
| RUN dotnet publish --output /app/ --configuration Release | ||
| FROM lambci/lambda-base | ||
| ENV PATH=/var/lang/bin:/usr/local/bin:/usr/bin/:/bin \ | ||
| LD_LIBRARY_PATH=/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib \ | ||
| AWS_EXECUTION_ENV=AWS_Lambda_dotnetcore2.0 | ||
| RUN rm -rf /var/runtime /var/lang && \ | ||
| curl https://lambci.s3.amazonaws.com/fs/dotnetcore2.0.tgz | tar -zx -C / | ||
| COPY --from=0 /app/MockBootstraps.* /var/runtime/ | ||
| ENTRYPOINT ["/var/lang/bin/dotnet", "/var/runtime/MockBootstraps.dll"] |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>netcoreapp2.0</TargetFramework> | ||
| <RootNamespace>MockLambdaRuntime</RootNamespace> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Reference Include="Bootstrap"> | ||
| <HintPath>lib\Bootstrap.dll</HintPath> | ||
| </Reference> | ||
| <Reference Include="Amazon.Lambda.Core"> | ||
| <HintPath>lib\Amazon.Lambda.Core.dll</HintPath> | ||
| </Reference> | ||
| </ItemGroup> | ||
| </Project> |
Sorry, the diff of this file is not supported yet
| using System; | ||
| using System.Diagnostics; | ||
| using System.IO; | ||
| using System.Text; | ||
| namespace MockLambdaRuntime | ||
| { | ||
| public class MockLambdaContext | ||
| { | ||
| static Random random = new Random(); | ||
| /// Creates a mock context from a given Lambda handler and event | ||
| public MockLambdaContext(string handler, string eventBody) | ||
| { | ||
| RequestId = Guid.NewGuid().ToString(); | ||
| StartTime = DateTime.Now; | ||
| InputStream = new MemoryStream(); | ||
| OutputStream = new MemoryStream(); | ||
| var eventData = Encoding.UTF8.GetBytes(eventBody); | ||
| InputStream.Write(eventData, 0, eventData.Length); | ||
| InputStream.Position = 0; | ||
| Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_NAME", FunctionName); | ||
| Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_VERSION", FunctionVersion); | ||
| Environment.SetEnvironmentVariable("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", MemorySize.ToString()); | ||
| Environment.SetEnvironmentVariable("AWS_LAMBDA_LOG_GROUP_NAME", LogGroup); | ||
| Environment.SetEnvironmentVariable("AWS_LAMBDA_LOG_STREAM_NAME", LogStream); | ||
| Environment.SetEnvironmentVariable("AWS_REGION", Region); | ||
| Environment.SetEnvironmentVariable("AWS_DEFAULT_REGION", Region); | ||
| Environment.SetEnvironmentVariable("_HANDLER", handler); | ||
| } | ||
| /// Calculates the remaining time using current time and timeout | ||
| public TimeSpan RemainingTime() | ||
| { | ||
| return StartTime + TimeSpan.FromSeconds(Timeout) - DateTime.Now; | ||
| } | ||
| public long Duration => (long)(DateTime.Now - StartTime).TotalMilliseconds; | ||
| public long BilledDuration => (long)(Math.Ceiling((DateTime.Now - StartTime).TotalMilliseconds / 100)) * 100; | ||
| public long MemoryUsed => Process.GetCurrentProcess().WorkingSet64; | ||
| public Stream InputStream { get; } | ||
| public Stream OutputStream { get; } | ||
| public string OutputText | ||
| { | ||
| get | ||
| { | ||
| OutputStream.Position = 0; | ||
| using (TextReader reader = new StreamReader(OutputStream)) | ||
| { | ||
| return reader.ReadToEnd(); | ||
| } | ||
| } | ||
| } | ||
| public string RequestId { get; } | ||
| public DateTime StartTime { get; } | ||
| public int Timeout => Convert.ToInt32(EnvHelper.GetOrDefault("AWS_LAMBDA_FUNCTION_TIMEOUT", "300")); | ||
| public int MemorySize => Convert.ToInt32(EnvHelper.GetOrDefault("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "1536")); | ||
| public string FunctionName => EnvHelper.GetOrDefault("AWS_LAMBDA_FUNCTION_NAME", "test"); | ||
| public string FunctionVersion => EnvHelper.GetOrDefault("AWS_LAMBDA_FUNCTION_VERSION", "$LATEST"); | ||
| public string LogGroup => EnvHelper.GetOrDefault("AWS_LAMBDA_LOG_GROUP_NAME", $"/aws/lambda/{FunctionName}"); | ||
| public string LogStream => EnvHelper.GetOrDefault("AWS_LAMBDA_LOG_STREAM_NAME", RandomLogStreamName); | ||
| public string Region => EnvHelper.GetOrDefault("AWS_REGION", EnvHelper.GetOrDefault("AWS_DEFAULT_REGION", "us-east-1")); | ||
| public string AccountId => EnvHelper.GetOrDefault("AWS_ACCOUNT_ID", "000000000000"); | ||
| public string Arn => $"arn:aws:lambda:{Region}:{AccountId}:function:{FunctionName}"; | ||
| string RandomLogStreamName => $"{DateTime.Now.ToString("yyyy/MM/dd")}/[{FunctionVersion}]{random.Next().ToString("x") + random.Next().ToString("x")}"; | ||
| } | ||
| } |
Sorry, the diff of this file is not supported yet
| <?xml version="1.0" encoding="utf-8" standalone="no"?> | ||
| <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> | ||
| <RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess> | ||
| <RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool> | ||
| <ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">/Users/michael/github/docker-lambda/dotnetcore2.0/run/MockBootstraps/obj/project.assets.json</ProjectAssetsFile> | ||
| <NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">/Users/michael/.nuget/packages/</NuGetPackageRoot> | ||
| <NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">/Users/michael/.nuget/packages/;/usr/local/share/dotnet/sdk/NuGetFallbackFolder</NuGetPackageFolders> | ||
| <NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle> | ||
| <NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">4.3.1</NuGetToolVersion> | ||
| </PropertyGroup> | ||
| <PropertyGroup> | ||
| <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> | ||
| </PropertyGroup> | ||
| <ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> | ||
| <Import Project="$(NuGetPackageRoot)microsoft.netcore.app/2.0.0/build/netcoreapp2.0/Microsoft.NETCore.App.props" Condition="Exists('$(NuGetPackageRoot)microsoft.netcore.app/2.0.0/build/netcoreapp2.0/Microsoft.NETCore.App.props')" /> | ||
| </ImportGroup> | ||
| </Project> |
| <?xml version="1.0" encoding="utf-8" standalone="no"?> | ||
| <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <PropertyGroup> | ||
| <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> | ||
| </PropertyGroup> | ||
| <ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> | ||
| <Import Project="$(NuGetPackageRoot)netstandard.library/2.0.0/build/netstandard2.0/NETStandard.Library.targets" Condition="Exists('$(NuGetPackageRoot)netstandard.library/2.0.0/build/netstandard2.0/NETStandard.Library.targets')" /> | ||
| <Import Project="$(NuGetPackageRoot)microsoft.netcore.app/2.0.0/build/netcoreapp2.0/Microsoft.NETCore.App.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.netcore.app/2.0.0/build/netcoreapp2.0/Microsoft.NETCore.App.targets')" /> | ||
| </ImportGroup> | ||
| </Project> |
Sorry, the diff of this file is too big to display
| using System; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.Reflection; | ||
| using System.Runtime.Loader; | ||
| using AWSLambda.Internal.Bootstrap; | ||
| using AWSLambda.Internal.Bootstrap.Context; | ||
| namespace MockLambdaRuntime | ||
| { | ||
| class Program | ||
| { | ||
| /// Task root of lambda task | ||
| static string lambdaTaskRoot = EnvHelper.GetOrDefault("LAMBDA_TASK_ROOT", "/var/task"); | ||
| /// Program entry point | ||
| static void Main(string[] args) | ||
| { | ||
| AssemblyLoadContext.Default.Resolving += OnAssemblyResolving; | ||
| var handler = GetFunctionHandler(args); | ||
| var body = GetEventBody(args); | ||
| var lambdaContext = new MockLambdaContext(handler, body); | ||
| var userCodeLoader = new UserCodeLoader(handler, InternalLogger.NO_OP_LOGGER); | ||
| userCodeLoader.Init(Console.Error.WriteLine); | ||
| var lambdaContextInternal = new LambdaContextInternal(lambdaContext.RemainingTime, | ||
| LogAction, new Lazy<CognitoClientContextInternal>(), | ||
| lambdaContext.RequestId, | ||
| new Lazy<string>(lambdaContext.Arn), | ||
| new Lazy<string>(string.Empty), | ||
| new Lazy<string>(string.Empty), | ||
| Environment.GetEnvironmentVariables()); | ||
| Exception lambdaException = null; | ||
| LogRequestStart(lambdaContext); | ||
| try | ||
| { | ||
| userCodeLoader.Invoke(lambdaContext.InputStream, lambdaContext.OutputStream, lambdaContextInternal); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| lambdaException = ex; | ||
| } | ||
| LogRequestEnd(lambdaContext); | ||
| if (lambdaException == null) | ||
| { | ||
| Console.WriteLine(lambdaContext.OutputText); | ||
| } | ||
| else | ||
| { | ||
| Console.Error.WriteLine(lambdaException); | ||
| } | ||
| } | ||
| /// Called when an assembly could not be resolved | ||
| private static Assembly OnAssemblyResolving(AssemblyLoadContext context, AssemblyName assembly) | ||
| { | ||
| return context.LoadFromAssemblyPath(Path.Combine(lambdaTaskRoot, $"{assembly.Name}.dll")); | ||
| } | ||
| /// Try to log everything to stderr except the function result | ||
| private static void LogAction(string text) | ||
| { | ||
| Console.Error.WriteLine(text); | ||
| } | ||
| static void LogRequestStart(MockLambdaContext context) | ||
| { | ||
| Console.Error.WriteLine($"START RequestId: {context.RequestId} Version: {context.FunctionVersion}"); | ||
| } | ||
| static void LogRequestEnd(MockLambdaContext context) | ||
| { | ||
| Console.Error.WriteLine($"END RequestId: {context.RequestId}"); | ||
| Console.Error.WriteLine($"REPORT RequestId {context.RequestId}\t" + | ||
| $"Duration: {context.Duration} ms\t" + | ||
| $"Billed Duration: {context.BilledDuration} ms\t" + | ||
| $"Memory Size {context.MemorySize} MB\t" + | ||
| $"Max Memory Used: {context.MemoryUsed / (1024 * 1024)} MB"); | ||
| } | ||
| /// Gets the function handler from arguments or environment | ||
| static string GetFunctionHandler(string[] args) | ||
| { | ||
| return args.Length > 0 ? args[0] : EnvHelper.GetOrDefault("AWS_LAMBDA_FUNCTION_HANDLER", string.Empty); | ||
| } | ||
| /// Gets the event body from arguments or environment | ||
| static string GetEventBody(string[] args) | ||
| { | ||
| return args.Length > 1 ? args[1] : (Environment.GetEnvironmentVariable("AWS_LAMBDA_EVENT_BODY") ?? | ||
| (Environment.GetEnvironmentVariable("DOCKER_LAMBDA_USE_STDIN") != null ? Console.In.ReadToEnd() : "{}")); | ||
| } | ||
| } | ||
| class EnvHelper | ||
| { | ||
| /// Gets the given environment variable with a fallback if it doesn't exist | ||
| public static string GetOrDefault(string name, string fallback) | ||
| { | ||
| return Environment.GetEnvironmentVariable(name) ?? fallback; | ||
| } | ||
| } | ||
| } |
| #!/bin/sh | ||
| curl https://lambci.s3.amazonaws.com/fs/dotnetcore2.0.tgz | \ | ||
| tar -xz var/runtime/Amazon.Lambda.Core.dll var/runtime/Bootstrap.dll | ||
| mv ./var/runtime/*.dll ./MockBootstraps/lib/ | ||
| rm -rf ./var |
| FROM lambci/lambda-base:build | ||
| ENV GOLANG_VERSION=1.10 \ | ||
| GOPATH=/go \ | ||
| PATH=/go/bin:/usr/local/go/bin:$PATH | ||
| WORKDIR /go/src/handler | ||
| RUN rm -rf /var/runtime /var/lang && \ | ||
| curl https://lambci.s3.amazonaws.com/fs/go1.x.tgz | tar -zx -C / && \ | ||
| curl https://dl.google.com/go/go${GOLANG_VERSION}.linux-amd64.tar.gz | tar -zx -C /usr/local && \ | ||
| go get github.com/golang/dep/cmd/dep && \ | ||
| go install github.com/golang/dep/cmd/dep | ||
| CMD ["dep", "ensure"] |
| package main | ||
| import ( | ||
| "bufio" | ||
| "bytes" | ||
| "encoding/hex" | ||
| "encoding/json" | ||
| "fmt" | ||
| "github.com/aws/aws-lambda-go/lambda/messages" | ||
| "io/ioutil" | ||
| "math" | ||
| "math/rand" | ||
| "net" | ||
| "net/rpc" | ||
| "os" | ||
| "os/exec" | ||
| "reflect" | ||
| "regexp" | ||
| "strconv" | ||
| "syscall" | ||
| "time" | ||
| ) | ||
| func main() { | ||
| rand.Seed(time.Now().UTC().UnixNano()) | ||
| var handler string | ||
| if len(os.Args) > 1 { | ||
| handler = os.Args[1] | ||
| } else { | ||
| handler = getEnv("AWS_LAMBDA_FUNCTION_HANDLER", getEnv("_HANDLER", "handler")) | ||
| } | ||
| var eventBody string | ||
| if len(os.Args) > 2 { | ||
| eventBody = os.Args[2] | ||
| } else { | ||
| eventBody = os.Getenv("AWS_LAMBDA_EVENT_BODY") | ||
| if eventBody == "" { | ||
| if os.Getenv("DOCKER_LAMBDA_USE_STDIN") != "" { | ||
| stdin, _ := ioutil.ReadAll(os.Stdin) | ||
| eventBody = string(stdin) | ||
| } else { | ||
| eventBody = "{}" | ||
| } | ||
| } | ||
| } | ||
| mockContext := &MockLambdaContext{ | ||
| RequestId: fakeGuid(), | ||
| EventBody: eventBody, | ||
| FnName: getEnv("AWS_LAMBDA_FUNCTION_NAME", "test"), | ||
| Version: getEnv("AWS_LAMBDA_FUNCTION_VERSION", "$LATEST"), | ||
| MemSize: getEnv("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "1536"), | ||
| Timeout: getEnv("AWS_LAMBDA_FUNCTION_TIMEOUT", "300"), | ||
| Region: getEnv("AWS_REGION", getEnv("AWS_DEFAULT_REGION", "us-east-1")), | ||
| AccountId: getEnv("AWS_ACCOUNT_ID", strconv.FormatInt(int64(rand.Int31()), 10)), | ||
| Start: time.Now(), | ||
| Pid: 1, | ||
| } | ||
| mockContext.ParseTimeout() | ||
| awsAccessKey := getEnv("AWS_ACCESS_KEY", getEnv("AWS_ACCESS_KEY_ID", "SOME_ACCESS_KEY_ID")) | ||
| awsSecretKey := getEnv("AWS_SECRET_KEY", getEnv("AWS_SECRET_ACCESS_KEY", "SOME_SECRET_ACCESS_KEY")) | ||
| awsSessionToken := getEnv("AWS_SESSION_TOKEN", os.Getenv("AWS_SECURITY_TOKEN")) | ||
| port := getEnv("_LAMBDA_SERVER_PORT", "54321") | ||
| os.Setenv("AWS_LAMBDA_FUNCTION_NAME", mockContext.FnName) | ||
| os.Setenv("AWS_LAMBDA_FUNCTION_VERSION", mockContext.Version) | ||
| os.Setenv("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", mockContext.MemSize) | ||
| os.Setenv("AWS_LAMBDA_LOG_GROUP_NAME", "/aws/lambda/"+mockContext.FnName) | ||
| os.Setenv("AWS_LAMBDA_LOG_STREAM_NAME", logStreamName(mockContext.Version)) | ||
| os.Setenv("AWS_REGION", mockContext.Region) | ||
| os.Setenv("AWS_DEFAULT_REGION", mockContext.Region) | ||
| os.Setenv("_HANDLER", handler) | ||
| cmd := exec.Command("/var/task/" + handler) | ||
| cmd.Env = append(os.Environ(), | ||
| "_LAMBDA_SERVER_PORT="+port, | ||
| "AWS_ACCESS_KEY="+awsAccessKey, | ||
| "AWS_ACCESS_KEY_ID="+awsAccessKey, | ||
| "AWS_SECRET_KEY="+awsSecretKey, | ||
| "AWS_SECRET_ACCESS_KEY="+awsSecretKey, | ||
| ) | ||
| if len(awsSessionToken) > 0 { | ||
| cmd.Env = append(cmd.Env, | ||
| "AWS_SESSION_TOKEN="+awsSessionToken, | ||
| "AWS_SECURITY_TOKEN="+awsSessionToken, | ||
| ) | ||
| } | ||
| cmd.Stdout = os.Stderr | ||
| cmd.Stderr = os.Stderr | ||
| cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} | ||
| var err error | ||
| if err = cmd.Start(); err != nil { | ||
| defer abortRequest(mockContext, err) | ||
| return | ||
| } | ||
| mockContext.Pid = cmd.Process.Pid | ||
| defer syscall.Kill(-mockContext.Pid, syscall.SIGKILL) | ||
| var conn net.Conn | ||
| for { | ||
| conn, err = net.Dial("tcp", ":"+port) | ||
| if mockContext.HasExpired() { | ||
| defer abortRequest(mockContext, mockContext.TimeoutErr()) | ||
| return | ||
| } | ||
| if err == nil { | ||
| break | ||
| } | ||
| if oerr, ok := err.(*net.OpError); ok { | ||
| // Connection refused, try again | ||
| if oerr.Op == "dial" && oerr.Net == "tcp" { | ||
| time.Sleep(5 * time.Millisecond) | ||
| continue | ||
| } | ||
| } | ||
| defer abortRequest(mockContext, err) | ||
| return | ||
| } | ||
| client := rpc.NewClient(conn) | ||
| for { | ||
| err = client.Call("Function.Ping", messages.PingRequest{}, &messages.PingResponse{}) | ||
| if mockContext.HasExpired() { | ||
| defer abortRequest(mockContext, mockContext.TimeoutErr()) | ||
| return | ||
| } | ||
| if err == nil { | ||
| break | ||
| } | ||
| time.Sleep(5 * time.Millisecond) | ||
| } | ||
| // XXX: The Go runtime seems to amortize the startup time, reset it here | ||
| mockContext.Start = time.Now() | ||
| logStartRequest(mockContext) | ||
| err = client.Call("Function.Invoke", mockContext.Request(), &mockContext.Reply) | ||
| // We want the process killed before this, so defer it | ||
| defer logEndRequest(mockContext, err) | ||
| } | ||
| func abortRequest(mockContext *MockLambdaContext, err error) { | ||
| logStartRequest(mockContext) | ||
| logEndRequest(mockContext, err) | ||
| } | ||
| func logStartRequest(mockContext *MockLambdaContext) { | ||
| systemLog("START RequestId: " + mockContext.RequestId + " Version: " + mockContext.Version) | ||
| } | ||
| func logEndRequest(mockContext *MockLambdaContext, err error) { | ||
| curMem, _ := calculateMemoryInMb(mockContext.Pid) | ||
| diffMs := math.Min(float64(time.Now().Sub(mockContext.Start).Nanoseconds()), | ||
| float64(mockContext.TimeoutDuration.Nanoseconds())) / 1e6 | ||
| systemLog("END RequestId: " + mockContext.RequestId) | ||
| systemLog(fmt.Sprintf( | ||
| "REPORT RequestId: %s\t"+ | ||
| "Duration: %.2f ms\t"+ | ||
| "Billed Duration: %.f ms\t"+ | ||
| "Memory Size: %s MB\t"+ | ||
| "Max Memory Used: %d MB\t", | ||
| mockContext.RequestId, diffMs, math.Ceil(diffMs/100)*100, mockContext.MemSize, curMem)) | ||
| if err == nil && mockContext.HasExpired() { | ||
| err = mockContext.TimeoutErr() | ||
| } | ||
| if err != nil { | ||
| responseErr := messages.InvokeResponse_Error{ | ||
| Message: err.Error(), | ||
| Type: getErrorType(err), | ||
| } | ||
| if responseErr.Type == "errorString" { | ||
| responseErr.Type = "" | ||
| if responseErr.Message == "unexpected EOF" { | ||
| responseErr.Message = "RequestId: " + mockContext.RequestId + " Process exited before completing request" | ||
| } | ||
| } | ||
| systemErr(&responseErr) | ||
| os.Exit(1) | ||
| } | ||
| if mockContext.Reply.Error != nil { | ||
| systemErr(mockContext.Reply.Error) | ||
| os.Exit(1) | ||
| } | ||
| fmt.Println(string(mockContext.Reply.Payload)) | ||
| } | ||
| func getEnv(key, fallback string) string { | ||
| value := os.Getenv(key) | ||
| if value != "" { | ||
| return value | ||
| } | ||
| return fallback | ||
| } | ||
| func fakeGuid() string { | ||
| randBuf := make([]byte, 16) | ||
| rand.Read(randBuf) | ||
| hexBuf := make([]byte, hex.EncodedLen(len(randBuf))+4) | ||
| hex.Encode(hexBuf[0:8], randBuf[0:4]) | ||
| hexBuf[8] = '-' | ||
| hex.Encode(hexBuf[9:13], randBuf[4:6]) | ||
| hexBuf[13] = '-' | ||
| hex.Encode(hexBuf[14:18], randBuf[6:8]) | ||
| hexBuf[18] = '-' | ||
| hex.Encode(hexBuf[19:23], randBuf[8:10]) | ||
| hexBuf[23] = '-' | ||
| hex.Encode(hexBuf[24:], randBuf[10:]) | ||
| hexBuf[14] = '1' // Make it look like a v1 guid | ||
| return string(hexBuf) | ||
| } | ||
| func logStreamName(version string) string { | ||
| randBuf := make([]byte, 16) | ||
| rand.Read(randBuf) | ||
| hexBuf := make([]byte, hex.EncodedLen(len(randBuf))) | ||
| hex.Encode(hexBuf, randBuf) | ||
| return time.Now().Format("2006/01/02") + "/[" + version + "]" + string(hexBuf) | ||
| } | ||
| func arn(region string, accountId string, fnName string) string { | ||
| nonDigit := regexp.MustCompile(`[^\d]`) | ||
| return "arn:aws:lambda:" + region + ":" + nonDigit.ReplaceAllString(accountId, "") + ":function:" + fnName | ||
| } | ||
| // Thanks to https://stackoverflow.com/a/31881979 | ||
| func calculateMemoryInMb(pid int) (uint64, error) { | ||
| f, err := os.Open(fmt.Sprintf("/proc/%d/smaps", pid)) | ||
| if err != nil { | ||
| return 0, err | ||
| } | ||
| defer f.Close() | ||
| res := uint64(0) | ||
| pfx := []byte("Pss:") | ||
| r := bufio.NewScanner(f) | ||
| for r.Scan() { | ||
| line := r.Bytes() | ||
| if bytes.HasPrefix(line, pfx) { | ||
| var size uint64 | ||
| _, err := fmt.Sscanf(string(line[4:]), "%d", &size) | ||
| if err != nil { | ||
| return 0, err | ||
| } | ||
| res += size | ||
| } | ||
| } | ||
| if err := r.Err(); err != nil { | ||
| return 0, err | ||
| } | ||
| return res / 1024, nil | ||
| } | ||
| func getErrorType(err interface{}) string { | ||
| if errorType := reflect.TypeOf(err); errorType.Kind() == reflect.Ptr { | ||
| return errorType.Elem().Name() | ||
| } else { | ||
| return errorType.Name() | ||
| } | ||
| } | ||
| func systemLog(msg string) { | ||
| fmt.Fprintln(os.Stderr, "\033[32m"+msg+"\033[0m") | ||
| } | ||
| // Try to match the output of the Lambda web console | ||
| func systemErr(err *messages.InvokeResponse_Error) { | ||
| jsonBytes, _ := json.MarshalIndent(LambdaError{ | ||
| Message: err.Message, | ||
| Type: err.Type, | ||
| StackTrace: err.StackTrace, | ||
| }, "", " ") | ||
| fmt.Fprintln(os.Stderr, "\033[31m"+string(jsonBytes)+"\033[0m") | ||
| } | ||
| type LambdaError struct { | ||
| Message string `json:"errorMessage"` | ||
| Type string `json:"errorType,omitempty"` | ||
| StackTrace []*messages.InvokeResponse_Error_StackFrame `json:"stackTrace,omitempty"` | ||
| } | ||
| type MockLambdaContext struct { | ||
| RequestId string | ||
| EventBody string | ||
| FnName string | ||
| Version string | ||
| MemSize string | ||
| Timeout string | ||
| Region string | ||
| AccountId string | ||
| Start time.Time | ||
| TimeoutDuration time.Duration | ||
| Pid int | ||
| Reply *messages.InvokeResponse | ||
| } | ||
| func (mc *MockLambdaContext) ParseTimeout() { | ||
| timeoutDuration, err := time.ParseDuration(mc.Timeout + "s") | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| mc.TimeoutDuration = timeoutDuration | ||
| } | ||
| func (mc *MockLambdaContext) Deadline() time.Time { | ||
| return mc.Start.Add(mc.TimeoutDuration) | ||
| } | ||
| func (mc *MockLambdaContext) HasExpired() bool { | ||
| return time.Now().After(mc.Deadline()) | ||
| } | ||
| func (mc *MockLambdaContext) Request() *messages.InvokeRequest { | ||
| return &messages.InvokeRequest{ | ||
| Payload: []byte(mc.EventBody), | ||
| RequestId: mc.RequestId, | ||
| XAmznTraceId: getEnv("_X_AMZN_TRACE_ID", ""), | ||
| InvokedFunctionArn: arn(mc.Region, mc.AccountId, mc.FnName), | ||
| Deadline: messages.InvokeRequest_Timestamp{ | ||
| Seconds: mc.Deadline().Unix(), | ||
| Nanos: int64(mc.Deadline().Nanosecond()), | ||
| }, | ||
| } | ||
| } | ||
| func (mc *MockLambdaContext) TimeoutErr() error { | ||
| return fmt.Errorf("%s %s Task timed out after %s.00 seconds", time.Now().Format("2006-01-02T15:04:05.999Z"), | ||
| mc.RequestId, mc.Timeout) | ||
| } |
| FROM golang:1 | ||
| WORKDIR /go/src/github.com/lambci/docker-lambda | ||
| RUN curl -sSL -o /usr/local/bin/dep https://github.com/golang/dep/releases/download/v0.3.2/dep-linux-amd64 && chmod +x /usr/local/bin/dep | ||
| COPY aws-lambda-mock.go Gopkg.toml Gopkg.lock ./ | ||
| RUN dep ensure | ||
| RUN GOARCH=amd64 GOOS=linux go build aws-lambda-mock.go | ||
| FROM lambci/lambda-base | ||
| RUN rm -rf /var/runtime /var/lang && \ | ||
| curl https://lambci.s3.amazonaws.com/fs/go1.x.tgz | tar -zx -C / | ||
| COPY --from=0 /go/src/github.com/lambci/docker-lambda/aws-lambda-mock /var/runtime/aws-lambda-go | ||
| USER sbx_user1051 | ||
| ENTRYPOINT ["/var/runtime/aws-lambda-go"] |
| # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. | ||
| [[projects]] | ||
| name = "github.com/aws/aws-lambda-go" | ||
| packages = ["lambda/messages"] | ||
| revision = "6e2e37798efbb1dfd8e9c6681702e683a6046517" | ||
| version = "v1.0.1" | ||
| [solve-meta] | ||
| analyzer-name = "dep" | ||
| analyzer-version = 1 | ||
| inputs-digest = "2c19b35c52e708394e6cc46c177e57a8379c3ab6e44aab67e2f9074218f861e9" | ||
| solver-name = "gps-cdcl" | ||
| solver-version = 1 |
| [[constraint]] | ||
| name = "github.com/aws/aws-lambda-go" | ||
| version = "1.0.1" |
| FROM lambci/lambda-base:build | ||
| ENV AWS_EXECUTION_ENV=AWS_Lambda_java8 | ||
| WORKDIR / | ||
| RUN rm -rf /var/runtime /var/lang && \ | ||
| curl https://lambci.s3.amazonaws.com/fs/java8.tgz | tar -zx -C / && \ | ||
| yum install -y java-1.8.0-openjdk-devel |
| FROM openjdk:8-alpine | ||
| WORKDIR /src | ||
| COPY ./lambda-runtime-mock /src | ||
| RUN apk add --no-cache curl && ./build.sh | ||
| FROM lambci/lambda-base | ||
| ENV AWS_EXECUTION_ENV=AWS_Lambda_java8 | ||
| RUN rm -rf /var/runtime /var/lang && \ | ||
| curl https://lambci.s3.amazonaws.com/fs/java8.tgz | tar -zx -C / | ||
| COPY --from=0 /src/LambdaSandboxJava-1.0.jar /var/runtime/lib/ | ||
| WORKDIR / | ||
| USER sbx_user1051 | ||
| ENTRYPOINT ["/usr/bin/java", "-XX:MaxHeapSize=1336935k", "-XX:MaxMetaspaceSize=157286k", "-XX:ReservedCodeCacheSize=78643k", \ | ||
| "-XX:+UseSerialGC", "-Xshare:on", "-XX:-TieredCompilation", "-jar", "/var/runtime/lib/LambdaJavaRTEntry-1.0.jar"] |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| #!/bin/sh | ||
| cd $(dirname "$0") | ||
| mkdir -p ./target/classes | ||
| javac -target 1.8 -d ./target/classes ./src/main/java/lambdainternal/LambdaRuntime.java | ||
| curl -s https://lambci.s3.amazonaws.com/fs/java8.tgz | tar -zx -- var/runtime/lib/LambdaSandboxJava-1.0.jar | ||
| mv var/runtime/lib/LambdaSandboxJava-1.0.jar ./ | ||
| cp -R ./target/classes/lambdainternal ./ | ||
| jar uf LambdaSandboxJava-1.0.jar lambdainternal/LambdaRuntime*.class | ||
| rm -rf ./var ./lambdainternal |
| package lambdainternal; | ||
| import java.lang.reflect.Field; | ||
| import java.math.BigInteger; | ||
| import java.nio.charset.StandardCharsets; | ||
| import java.text.SimpleDateFormat; | ||
| import java.util.Collections; | ||
| import java.util.Date; | ||
| import java.util.Map; | ||
| import java.util.Random; | ||
| import java.util.Scanner; | ||
| import java.util.UUID; | ||
| import sun.misc.Unsafe; | ||
| public class LambdaRuntime { | ||
| private static Unsafe unsafe; | ||
| private static final String INVOKE_ID = UUID.randomUUID().toString(); | ||
| private static final String AWS_ACCESS_KEY_ID; | ||
| private static final String AWS_SECRET_ACCESS_KEY; | ||
| private static final String AWS_SESSION_TOKEN; | ||
| private static final String AWS_REGION; | ||
| private static final String HANDLER; | ||
| private static final String EVENT_BODY; | ||
| private static final int TIMEOUT; | ||
| private static final String X_AMZN_TRACE_ID; | ||
| private static final String CLIENT_CONTEXT = null; | ||
| private static final String COGNITO_IDENTITY_ID = ""; | ||
| private static final String COGNITO_IDENTITY_POOL_ID = ""; | ||
| private static final String TRACE_ID = ""; | ||
| private static final String PARENT_ID = ""; | ||
| private static final String FUNCTION_ARN; | ||
| private static final String ACCOUNT_ID; | ||
| private static boolean alreadyInvoked = false; | ||
| private static long invokeStart; | ||
| public static final int MEMORY_LIMIT; | ||
| public static final String LOG_GROUP_NAME; | ||
| public static final String LOG_STREAM_NAME; | ||
| public static final String FUNCTION_NAME; | ||
| public static final String FUNCTION_VERSION; | ||
| public static volatile boolean needsDebugLogs; | ||
| static { | ||
| try { | ||
| Field field = Unsafe.class.getDeclaredField("theUnsafe"); | ||
| field.setAccessible(true); | ||
| unsafe = (Unsafe) field.get(null); | ||
| } catch (Exception e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| TIMEOUT = Integer.parseInt(getEnvOrDefault("AWS_LAMBDA_FUNCTION_TIMEOUT", "300")); | ||
| MEMORY_LIMIT = Integer.parseInt(getEnvOrDefault("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "1536")); | ||
| FUNCTION_NAME = getEnvOrDefault("AWS_LAMBDA_FUNCTION_NAME", "test"); | ||
| FUNCTION_VERSION = getEnvOrDefault("AWS_LAMBDA_FUNCTION_VERSION", "$LATEST"); | ||
| LOG_GROUP_NAME = getEnvOrDefault("AWS_LAMBDA_LOG_GROUP_NAME", "/aws/lambda/" + FUNCTION_NAME); | ||
| LOG_STREAM_NAME = getEnvOrDefault("AWS_LAMBDA_LOG_STREAM_NAME", randomLogStreamName(FUNCTION_VERSION)); | ||
| AWS_ACCESS_KEY_ID = getEnvOrDefault("AWS_ACCESS_KEY_ID", "SOME_ACCESS_KEY_ID"); | ||
| AWS_SECRET_ACCESS_KEY = getEnvOrDefault("AWS_SECRET_ACCESS_KEY", "SOME_SECRET_ACCESS_KEY"); | ||
| AWS_SESSION_TOKEN = getEnv("AWS_SESSION_TOKEN"); | ||
| AWS_REGION = getEnvOrDefault("AWS_REGION", getEnvOrDefault("AWS_DEFAULT_REGION", "us-east-1")); | ||
| ACCOUNT_ID = getEnvOrDefault("AWS_ACCOUNT_ID", "000000000000"); | ||
| FUNCTION_ARN = "arn:aws:lambda:" + AWS_REGION + ":" + ACCOUNT_ID + ":function:" + FUNCTION_NAME; | ||
| X_AMZN_TRACE_ID = getEnvOrDefault("_X_AMZN_TRACE_ID", ""); | ||
| String[] args = getCmdLineArgs(); | ||
| HANDLER = args.length > 1 ? args[1] : getEnvOrDefault("AWS_LAMBDA_FUNCTION_HANDLER", getEnvOrDefault("_HANDLER", "index.Handler")); | ||
| EVENT_BODY = args.length > 2 ? args[2] : getEventBody(); | ||
| LambdaRuntime.needsDebugLogs = false; | ||
| setenv("AWS_LAMBDA_FUNCTION_NAME", FUNCTION_NAME, 1); | ||
| setenv("AWS_LAMBDA_FUNCTION_VERSION", FUNCTION_VERSION, 1); | ||
| setenv("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", Integer.toString(MEMORY_LIMIT), 1); | ||
| setenv("AWS_LAMBDA_LOG_GROUP_NAME", LOG_GROUP_NAME, 1); | ||
| setenv("AWS_LAMBDA_LOG_STREAM_NAME", LOG_STREAM_NAME, 1); | ||
| setenv("AWS_REGION", AWS_REGION, 1); | ||
| setenv("AWS_DEFAULT_REGION", AWS_REGION, 1); | ||
| setenv("_HANDLER", HANDLER, 1); | ||
| } | ||
| private static String getEventBody() { | ||
| String eventBody = getEnv("AWS_LAMBDA_EVENT_BODY"); | ||
| if (eventBody == null) { | ||
| eventBody = getEnv("DOCKER_LAMBDA_USE_STDIN") != null ? | ||
| new Scanner(System.in).useDelimiter("\\A").next() : "{}"; | ||
| } | ||
| return eventBody; | ||
| } | ||
| private static String getEnvOrDefault(String key, String defaultVal) { | ||
| String envVal = getEnv(key); | ||
| return envVal != null ? envVal : defaultVal; | ||
| } | ||
| private static String randomLogStreamName(String functionVersion) { | ||
| byte[] randomBuf = new byte[16]; | ||
| new Random().nextBytes(randomBuf); | ||
| return String.format("%s/[%s]%016x", new SimpleDateFormat("yyyy/MM/dd").format(new Date()), functionVersion, | ||
| new BigInteger(1, randomBuf)); | ||
| } | ||
| private static void systemLog(String str) { | ||
| System.err.println("\033[32m" + str + "\033[0m"); | ||
| } | ||
| private static void systemErr(String str) { | ||
| System.err.println("\033[31m" + str + "\033[0m"); | ||
| } | ||
| public static String getEnv(final String envVariableName) { | ||
| return System.getenv(envVariableName); | ||
| } | ||
| public static void initRuntime() { | ||
| } | ||
| public static void reportRunning(final String p0) { | ||
| } | ||
| public static void reportDone(final String invokeid, final byte[] result, final int resultLength, final int p3) { | ||
| if (!alreadyInvoked) { | ||
| return; | ||
| } | ||
| double durationMs = (System.nanoTime() - invokeStart) / 1_000_000d; | ||
| long billedMs = Math.min(100 * ((long) Math.floor(durationMs / 100) + 1), TIMEOUT * 1000); | ||
| long maxMemory = Math.round((Runtime.getRuntime().totalMemory() - | ||
| Runtime.getRuntime().freeMemory()) / (1024 * 1024)); | ||
| systemLog("END RequestId: " + invokeid); | ||
| systemLog(String.join("\t", | ||
| "REPORT RequestId: " + invokeid, | ||
| "Duration: " + String.format("%.2f", durationMs) + " ms", | ||
| "Billed Duration: " + billedMs + " ms", | ||
| "Memory Size: " + MEMORY_LIMIT + " MB", | ||
| "Max Memory Used: " + maxMemory + " MB", | ||
| "")); | ||
| if (result != null) { | ||
| System.out.println("\n" + new String(result, 0, resultLength)); | ||
| } | ||
| } | ||
| public static void reportException(final String p0) { | ||
| } | ||
| public static void reportUserInitStart() { | ||
| } | ||
| public static void reportUserInitEnd() { | ||
| } | ||
| public static void reportUserInvokeStart() { | ||
| } | ||
| public static void reportUserInvokeEnd() { | ||
| } | ||
| public static void reportFault(final String invokeid, final String msg, final String exceptionClass, | ||
| final String stack) { | ||
| systemErr(stack); | ||
| } | ||
| public static void setenv(final String key, final String val, final int p2) { | ||
| getMutableEnv().put(key, val); | ||
| } | ||
| public static void unsetenv(final String key) { | ||
| getMutableEnv().remove(key); | ||
| } | ||
| public static WaitForStartResult waitForStart() { | ||
| return new WaitForStartResult(INVOKE_ID, HANDLER, "event", AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, | ||
| AWS_SESSION_TOKEN, false); | ||
| } | ||
| public static InvokeRequest waitForInvoke() { | ||
| if (alreadyInvoked) { | ||
| System.exit(0); | ||
| } | ||
| alreadyInvoked = true; | ||
| long address = 0; | ||
| byte[] eventBodyBytes = EVENT_BODY.getBytes(StandardCharsets.UTF_8); | ||
| try { | ||
| address = unsafe.allocateMemory(eventBodyBytes.length); | ||
| for (int i = 0; i < eventBodyBytes.length; i++) { | ||
| unsafe.putByte(address + i, eventBodyBytes[i]); | ||
| } | ||
| } catch (Exception e) { | ||
| // Not sure, could happen if memory is exhausted? | ||
| throw new RuntimeException(e); | ||
| } | ||
| invokeStart = System.nanoTime(); | ||
| systemLog("START RequestId: " + INVOKE_ID + " Version: " + FUNCTION_VERSION); | ||
| return new InvokeRequest(-1, INVOKE_ID, X_AMZN_TRACE_ID, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, | ||
| AWS_SESSION_TOKEN, CLIENT_CONTEXT, COGNITO_IDENTITY_ID, COGNITO_IDENTITY_POOL_ID, address, | ||
| eventBodyBytes.length, false, FUNCTION_ARN, TRACE_ID, false, PARENT_ID); | ||
| } | ||
| public static int getRemainingTime() { | ||
| return (int) ((TIMEOUT * 1000) - Math.round((System.nanoTime() - invokeStart) / 1_000_000d)); | ||
| } | ||
| public static void sendContextLogs(final byte[] msg, final int length) { | ||
| System.err.print(new String(msg, 0, length, StandardCharsets.UTF_8)); | ||
| } | ||
| public static synchronized void streamLogsToSlicer(final byte[] p0, final int p1, final int p2) { | ||
| } | ||
| private static String[] getCmdLineArgs() { | ||
| return System.getProperty("sun.java.command").split(" ", 3); | ||
| } | ||
| private static Map<String, String> getMutableEnv() { | ||
| Class[] classes = Collections.class.getDeclaredClasses(); | ||
| Map<String, String> env = System.getenv(); | ||
| for (Class cl : classes) { | ||
| if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) { | ||
| try { | ||
| Field field = cl.getDeclaredField("m"); | ||
| field.setAccessible(true); | ||
| Object obj = field.get(env); | ||
| return (Map<String, String>) obj; | ||
| } catch (Exception e) { | ||
| // Should never happen on Lambda | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
| } | ||
| // Should never happen on Lambda | ||
| throw new RuntimeException("Could not find java.util.Collections$UnmodifiableMap class"); | ||
| } | ||
| public static class AWSCredentials { | ||
| public final String key; | ||
| public final String secret; | ||
| public final String session; | ||
| public AWSCredentials(final String key, final String secret, final String session) { | ||
| this.key = key; | ||
| this.secret = secret; | ||
| this.session = session; | ||
| } | ||
| } | ||
| public static class InvokeRequest { | ||
| public final int sockfd; | ||
| public final String invokeid; | ||
| public final String xAmznTraceId; | ||
| public final AWSCredentials credentials; | ||
| public final String clientContext; | ||
| public final String cognitoIdentityId; | ||
| public final String cognitoPoolId; | ||
| public final long eventBodyAddr; | ||
| public final int eventBodyLen; | ||
| public final boolean needsDebugLogs; | ||
| public final String invokedFunctionArn; | ||
| public final String traceId; | ||
| public final boolean isSampled; | ||
| public final String parentId; | ||
| public InvokeRequest(final int sockfd, final String invokeid, final String xAmznTraceId, final String awskey, | ||
| final String awssecret, final String awssession, final String clientcontext, | ||
| final String cognitoidentityid, final String cognitopoolid, final long addr, final int len, | ||
| final boolean needsDebugLogs, final String invokedFunctionArn, final String traceId, | ||
| final boolean isSampled, final String parentId) { | ||
| this.sockfd = sockfd; | ||
| this.invokeid = invokeid; | ||
| this.xAmznTraceId = xAmznTraceId; | ||
| this.eventBodyAddr = addr; | ||
| this.eventBodyLen = len; | ||
| this.clientContext = clientcontext; | ||
| this.cognitoIdentityId = cognitoidentityid; | ||
| this.cognitoPoolId = cognitopoolid; | ||
| this.traceId = traceId; | ||
| this.isSampled = isSampled; | ||
| this.parentId = parentId; | ||
| this.credentials = new AWSCredentials(awskey, awssecret, awssession); | ||
| this.needsDebugLogs = needsDebugLogs; | ||
| this.invokedFunctionArn = invokedFunctionArn; | ||
| } | ||
| } | ||
| public static class WaitForStartResult { | ||
| public final String invokeid; | ||
| public final String handler; | ||
| public final String mode; | ||
| public final AWSCredentials credentials; | ||
| public final boolean suppressInit; | ||
| public WaitForStartResult(final String invokeid, final String handler, final String mode, final String awskey, | ||
| final String awssecret, final String awssession, final boolean suppressInit) { | ||
| this.invokeid = invokeid; | ||
| this.handler = handler; | ||
| this.mode = mode; | ||
| this.credentials = new AWSCredentials(awskey, awssecret, awssession); | ||
| this.suppressInit = suppressInit; | ||
| } | ||
| } | ||
| } |
| # Java 8 Build Instructions | ||
| As the Java 8 Lambda libraries are statically compiled into jars, it's not | ||
| possible to just swap in a mock interface source file, as it is in the other | ||
| dynamic runtimes, without compiling first. | ||
| The `Dockerfile` here will build using a patched `LambdaSandboxJava-1.0.jar`, | ||
| which is checked into git. This jar was built using the jar from the Lambda runtime, | ||
| `/var/runtime/lib/LambdaSandboxJava-1.0.jar`, with a single class | ||
| (`lambdainternal/LambdaRuntime.class`) updated to use local/mock methods | ||
| instead of native ones. | ||
| The build script to perform this patch/update is at | ||
| [./lambda-runtime-mock/build.sh](./lambda-runtime-mock/build.sh) |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
17196
-95.08%6
-81.25%172
-94.4%