Skip to content
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
3 changes: 1 addition & 2 deletions .mockery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,4 @@ packages:
inpackage: True
dir: "{{.InterfaceDir}}"
interfaces:
Dispatcher:
# testonly: True
Dispatcher:
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ GLOBAL OPTIONS:
--log-level value set the log level. Options: debug, info, warn, error, panic, fatal. [$LOG_LEVEL]
--version print the version

auth

--auth-key value, -k value the authentication key to use for incoming requests. [$AUTH_KEY]

function

--arg value, -a value [ --arg value, -a value ] additional arguments for to the worker process. [$FUNCTION_ARGS]
Expand Down
5 changes: 3 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package app

import (
"github.com/urfave/cli/v2"
"go.uber.org/fx"

"github.com/lambda-feedback/shimmy/config"
"github.com/lambda-feedback/shimmy/internal/shell"
"github.com/lambda-feedback/shimmy/runtime"
"github.com/lambda-feedback/shimmy/util/conf"
"github.com/lambda-feedback/shimmy/util/logging"
"github.com/urfave/cli/v2"
"go.uber.org/fx"
)

func New(ctx *cli.Context) (*shell.Shell, error) {
Expand Down
3 changes: 2 additions & 1 deletion app/lambda/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (

"github.com/aws/aws-lambda-go/lambda"
"github.com/awslabs/aws-lambda-go-api-proxy/httpadapter"
"github.com/lambda-feedback/shimmy/internal/server"
"go.uber.org/fx"
"go.uber.org/zap"

"github.com/lambda-feedback/shimmy/internal/server"
)

// LambdaHandlerParams represents the parameters required for
Expand Down
3 changes: 2 additions & 1 deletion app/lambda/module.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package lambda

import (
"go.uber.org/fx"

"github.com/lambda-feedback/shimmy/handler"
"github.com/lambda-feedback/shimmy/util/logging"
"go.uber.org/fx"
)

func Module(config Config) fx.Option {
Expand Down
3 changes: 2 additions & 1 deletion app/standalone/module.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package standalone

import (
"go.uber.org/fx"

"github.com/lambda-feedback/shimmy/handler"
"github.com/lambda-feedback/shimmy/internal/server"
"github.com/lambda-feedback/shimmy/util/logging"
"go.uber.org/fx"
)

func Module(config Config) fx.Option {
Expand Down
3 changes: 2 additions & 1 deletion cmd/lambda.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package cmd

import (
"github.com/urfave/cli/v2"

"github.com/lambda-feedback/shimmy/app"
"github.com/lambda-feedback/shimmy/app/lambda"
"github.com/lambda-feedback/shimmy/util/conf"
"github.com/lambda-feedback/shimmy/util/logging"
"github.com/urfave/cli/v2"
)

var (
Expand Down
13 changes: 11 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (
"os"
"time"

"github.com/urfave/cli/v2"
"go.uber.org/zap"

"github.com/lambda-feedback/shimmy/config"
"github.com/lambda-feedback/shimmy/util/conf"
"github.com/lambda-feedback/shimmy/util/logging"
"github.com/urfave/cli/v2"
"go.uber.org/zap"
)

var (
Expand All @@ -35,6 +36,13 @@ functions on arbitrary, serverless platforms.`
Usage: "set the log format. Options: production, development.",
EnvVars: []string{"LOG_FORMAT"},
},
// auth flags
&cli.StringFlag{
Name: "auth-key",
Usage: "the secret key for the application.",
Category: "auth",
EnvVars: []string{"AUTH_KEY"},
},
// shim flags
&cli.StringFlag{
Name: "interface",
Expand Down Expand Up @@ -241,6 +249,7 @@ func parseRootConfig(ctx *cli.Context) (config.Config, error) {

// map cli flags to config fields
cliMap := map[string]string{
"auth-key": "auth.key",
"max-workers": "runtime.max_workers",
"command": "runtime.cmd",
"cwd": "runtime.cwd",
Expand Down
3 changes: 2 additions & 1 deletion cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package cmd
import (
"os"

"github.com/lambda-feedback/shimmy/util/logging"
"github.com/urfave/cli/v2"

"github.com/lambda-feedback/shimmy/util/logging"
)

var (
Expand Down
3 changes: 2 additions & 1 deletion cmd/serve.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package cmd

import (
"github.com/urfave/cli/v2"

"github.com/lambda-feedback/shimmy/app"
"github.com/lambda-feedback/shimmy/app/standalone"
"github.com/lambda-feedback/shimmy/util/conf"
"github.com/lambda-feedback/shimmy/util/logging"
"github.com/urfave/cli/v2"
)

var (
Expand Down
8 changes: 8 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ const (
JSON MessageEncoding = "json"
)

type AuthConfig struct {
// Key is the secret key for the application
Key string `conf:"key"`
}

type Config struct {
// LogLevel is the log level for the application
LogLevel string `conf:"log_level"`
Expand All @@ -17,4 +22,7 @@ type Config struct {

// Runtime is the runtime configuration
Runtime runtime.Config `conf:"runtime"`

// Auth is the authentication configuration
Auth AuthConfig `conf:"auth"`
}
14 changes: 13 additions & 1 deletion handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,32 @@ import (
"io"
"net/http"

"github.com/lambda-feedback/shimmy/runtime"
"go.uber.org/fx"
"go.uber.org/zap"

"github.com/lambda-feedback/shimmy/config"
"github.com/lambda-feedback/shimmy/runtime"
)

type CommandHandlerParams struct {
fx.In

Handler runtime.Handler
Config config.Config
Log *zap.Logger
}

func NewCommandHandler(params CommandHandlerParams) *CommandHandler {
return &CommandHandler{
handler: params.Handler,
config: params.Config,
log: params.Log,
}
}

type CommandHandler struct {
handler runtime.Handler
config config.Config
log *zap.Logger
}

Expand All @@ -34,6 +39,13 @@ func (h *CommandHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
zap.String("method", r.Method),
)

// Check for authorization
if h.config.Auth.Key != "" && r.Header.Get("api-key") != h.config.Auth.Key {
log.Debug("unauthorized request")
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}

body, err := io.ReadAll(r.Body)
if err != nil {
log.Debug("failed to read body", zap.Error(err))
Expand Down
102 changes: 102 additions & 0 deletions handler/handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package handler

import (
"bytes"
"context"
"github.com/lambda-feedback/shimmy/config"
"github.com/lambda-feedback/shimmy/runtime"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"go.uber.org/zap"
"io"
"net/http"
"net/http/httptest"
"testing"
)

// --- Mock handler ---
type MockHandler struct {
mock.Mock
}

func (m *MockHandler) Handle(ctx context.Context, req runtime.Request) runtime.Response {
args := m.Called(ctx, req)
return args.Get(0).(runtime.Response)
}

// --- Test ---
func TestServeHTTP_Success(t *testing.T) {
mockHandler := new(MockHandler)

reqBody := []byte(`{"example": "value"}`)
req := httptest.NewRequest(http.MethodPost, "/test", bytes.NewReader(reqBody))
req.Header.Set("api-key", "secret")

w := httptest.NewRecorder()

expectedResponse := runtime.Response{
StatusCode: http.StatusOK,
Header: http.Header{"Content-Type": []string{"application/json"}},
Body: []byte(`{"ok":true}`),
}

mockHandler.On("Handle", mock.Anything, mock.MatchedBy(func(r runtime.Request) bool {
return r.Path == "/test" &&
r.Method == http.MethodPost &&
bytes.Equal(r.Body, reqBody)
})).Return(expectedResponse)

handler := &CommandHandler{
handler: mockHandler,
log: zap.NewNop(), // or zaptest.NewLogger(t)
config: config.Config{
LogLevel: "debug",
Runtime: runtime.Config{},
Auth: config.AuthConfig{Key: "secret"},
},
}

handler.ServeHTTP(w, req)

res := w.Result()
defer res.Body.Close()

body, _ := io.ReadAll(res.Body)

assert.Equal(t, http.StatusOK, res.StatusCode)
assert.Equal(t, "application/json", res.Header.Get("Content-Type"))
assert.Equal(t, `{"ok":true}`, string(body))
mockHandler.AssertExpectations(t)
}

func TestServeHTTP_Unauthorized(t *testing.T) {
mockHandler := new(MockHandler)

req := httptest.NewRequest(http.MethodPost, "/test", bytes.NewReader([]byte(`{"example": "value"}`)))
req.Header.Set("api-key", "wrong-key") // wrong key

w := httptest.NewRecorder()

handler := &CommandHandler{
handler: mockHandler, // won't be called
log: zap.NewNop(),
config: config.Config{
LogLevel: "debug",
Runtime: runtime.Config{},
Auth: config.AuthConfig{Key: "Secret"},
},
}

handler.ServeHTTP(w, req)

res := w.Result()
defer res.Body.Close()

body, _ := io.ReadAll(res.Body)

assert.Equal(t, http.StatusUnauthorized, res.StatusCode)
assert.Contains(t, string(body), "unauthorized")

// Ensure handler was not called
mockHandler.AssertNotCalled(t, "Handle", mock.Anything, mock.Anything)
}
3 changes: 2 additions & 1 deletion internal/execution/dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package execution
import (
"context"

"go.uber.org/zap"

"github.com/lambda-feedback/shimmy/internal/execution/dispatcher"
"github.com/lambda-feedback/shimmy/internal/execution/supervisor"
"go.uber.org/zap"
)

type Dispatcher dispatcher.Dispatcher
Expand Down
3 changes: 2 additions & 1 deletion internal/execution/dispatcher/dispatcher_dedicated.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import (
"context"
"fmt"

"github.com/lambda-feedback/shimmy/internal/execution/supervisor"
"go.uber.org/zap"

"github.com/lambda-feedback/shimmy/internal/execution/supervisor"
)

type DedicatedDispatcher struct {
Expand Down
3 changes: 2 additions & 1 deletion internal/execution/dispatcher/dispatcher_pooled.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
"runtime"

"github.com/jackc/puddle/v2"
"github.com/lambda-feedback/shimmy/internal/execution/supervisor"
"go.uber.org/zap"

"github.com/lambda-feedback/shimmy/internal/execution/supervisor"
)

type PooledDispatcher struct {
Expand Down
5 changes: 3 additions & 2 deletions internal/execution/dispatcher/dispatcher_pooled_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import (
"testing"
"time"

"github.com/lambda-feedback/shimmy/internal/execution/dispatcher"
"github.com/lambda-feedback/shimmy/internal/execution/supervisor"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"go.uber.org/zap"

"github.com/lambda-feedback/shimmy/internal/execution/dispatcher"
"github.com/lambda-feedback/shimmy/internal/execution/supervisor"
)

func TestPooledDispatcher_New_UsesCPUCoreFallback(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion internal/execution/supervisor/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import (
"context"
"time"

"github.com/lambda-feedback/shimmy/internal/execution/worker"
"go.uber.org/zap"

"github.com/lambda-feedback/shimmy/internal/execution/worker"
)

// AdapterWorkerFactoryFn is a type alias for a function that creates a worker
Expand Down
3 changes: 2 additions & 1 deletion internal/execution/supervisor/adapter_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import (
"sync"
"time"

"github.com/lambda-feedback/shimmy/internal/execution/worker"
"go.uber.org/zap"

"github.com/lambda-feedback/shimmy/internal/execution/worker"
)

// fileAdapter is an adapter that allows supervisors to use files to
Expand Down
Loading
Loading