sandwich-shop

command module
v0.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 13, 2021 License: MIT Imports: 13 Imported by: 0

README

Sandwich Shop

A containerless, serverless experiment using Go and GraphQL

Note! This is purely experimental and not meant for production use.

The purpose of this experiment is to explore other alternatives to the container-based, serverless pattern. We are hoping this solution will minimize the overhead needed for spinning up a new container on-demand and fully eliminate the idea of a "cold start”.

Usage

Build
gh repo clone suhay/sandwich-shop
cd sandwich-shop
make build

This will build directly from the source code. The compiled binary will be within the project directory. One benefit of doing it this way is the .env file path will default to the project's root. This means you will not need to specify it as an argument.

Install
go install github.com/suhay/sandwich-shop@latest
go install github.com/suhay/sandwich-shop/sandwiches/gowich@latest

Install the latest release of Sandwich Shop. This will add the binary to your GOPATH. The benefit of installing vs building is being able to run the binary within any directory. You will, however, need to specify a path to the .env file you want to use as an argument. Also, be sure to add $GOPATH/bin to your PATH,

Run
sandwich-shop [--env=<path>] [--port=<port>]

If you built the application from the source, you will need to execute the binary within the project directory.

Flag Description
--env Path to a local, or remote .env this process should use for default configurations.
--port The port number to run on. Default: 3002

Setting up Shop

Once you have the Sandwich Shop installed, and you have at least one Sandwich ready to go (gowich or nodewich), the next task is to set up your .env files. These can live anywhere and are included as CLI arguments when launching the Shop or Sandwich.

# .env

MONGODB_URL=cluster0.mongodb.net
MONGODB_USER=mango
MONGODB_PASSWD=1234password
JWT_SECRET=1234567890jwtsecretcode
TIMEOUT=60
TENANTS=~/sandwich-shop/tenants
Key Description
MONGODB_URL (optional) URL to the mongo database that stores tenant information including the Bearer token.
MONGODB_USER (optional) User for logging into the tenant info database.
MONGODB_PASSWD (optional) Password for the user above.
JWT_SECRET Used for signing a JWT payload while passing it through the shop as an order. This is used to verify the order came through a shop directly and that it was unchanged while in transit. This secret must be identical across all Sandwiches.
TIMEOUT Seconds to wait on the order to complete.
TENANTS The location where your shop tenants are stored. Think of these as project roots, function roots, or user roots of what will be using the Shop.
Registering a Sandwich

A Sandwich is what will handle the heavy lifting. Each Sandwich can be specialized in running one type of application (Node.js, Golang, Python, etc.), or they can do a mix of them, whichever you'd prefer. There are two ways you can register your Sandwiches. The first way is through a local sandiwches.json file. This is the more clunky way to maintain your Sandwich registry, but it cuts out a round trip to a MongoDB. The second way is through a MongoDB collection.

[
  {
    "_id": "rye",
    "name": "Rye",
    "host": "http://localhost",
    "port": 4006,
    "runtimes": [
      "node12"
    ]
  },
  {
    "_id": "ciabatta",
    "name": "Ciabatta",
    "host": "http://localhost",
    "port": 4007,
    "runtimes": [
      "go1_17",
      "node14",
      "node16",
      "python3"
    ]
  }
]
Key Description
_id Sandwich's id
name Human readable names for easily identifying when there is an error.
host URL the Sandwich will be reached by the Sandwich Shop process (how it will receive orders).
port The port on the designated host the Sandwich is reachable on
runtimes An array of runtime identifiers that show what this Sandwich is set to run.

Runtimes must be defined within the GraphQL resolver which means adding one will require a pull request. The above schema can also be stored within a MongoDB collection called sandwiches on the sandwich-shop database you are using to run this application.

Gowich

A Gowich is a Sandwich written in Go. You may have as many of these running as needed as long as they are all running on separate ports. Each Gowich should have a .env file supplied to it as a CLI argument.

# .gowich1.env

PORT=3001
TIMEOUT=60
JWT_SECRET=1234567890jwtsecretcode
GO1_13=/usr/local/go/bin/go
TENANTS=/path/to/tenants
Key Description
PORT Port to run this Sandwich on. This will be overridden if --port is supplied as a command argument.
TIMEOUT Timeout, in seconds, to wait for an order to finish.
JWT_SECRET Must be the same JWT_SECRET as specified in the Sandwich Shop’s .env variables. This is used to ensure the request was generated and not changed between Sandwich Shop and the Gowich.
GO1_13 Absolute path to the runtime’s executable.
TENANTS Absolute path to tenants directory.
Running
gowich [--env=<path>] [--port=<port>]
Flag Description
--env Path to a local, or remote .env this process should use for default configurations.
--port The port number to run on.
Nodewich

A Nodewich is a Sandwich written in Node. You may have as many of these running as needed as long as they are all running on separate ports. Each Nodewich should have a .env file supplied to it as a CLI argument.

#.nodewich1.env

PORT=4001
TIMEOUT=60
JWT_SECRET=1234567890jwtsecretcode
NODE9_10=/path/to/node9
NODE12_7=/path/to/node12
TENANTS=/path/to/tenants
Key Description
PORT Port to run this Sandwich on. This will be overridden if --port is supplied as a command argument.
TIMEOUT Timeout, in seconds, to wait for an order to finish.
JWT_SECRET Must be the same JWT_SECRET as specified in the Sandwich Shop’s .env variables. This is used to ensure the request was generated and not changed between Sandwich Shop and the Nodewich.
NODE9_10 Absolute path to the runtime’s executable.
TENANTS Absolute path to tenants directory.
Running
nodewich [--env=<path>] [--port=<port>]
Flag Description
--env Path to a local, or remote .env this process should use for default configurations.
--port The port number to run on.
Tenants

Tenants are the buckets where your functional code is placed. Within the tenant directory, you will place the different tenant directories. Along with the functions a tenant wishes to run, there also must be an orders.yml file to hold the function configurations. There can also either be an optional .key file to hold the API key for this particular tenant, or their API key must be stored within the tenants collection on your sandwich-shop MongoDB database.

tenants
└── b78682b3-36c8-4759-b8d1-5e62f029a1bc
    ├── .key (optional)
    ├── getSandwich.js
    ├── make_sandwich.go
    └── orders.yml
# order.yml
---
getSandwich: # order name, GET https://shop.example/{tenantid}/getSandwich  
  runtime: node9_10 # runtime needed, used to pick sandwich 
  path: getSandwich.js # path function is relative to tenant's root  
  env: [] # any variables to include
makeSandwich:  
  runtime: go1_13
  path: make_sandwich.go
  env: []

.key file

this-is-my-api-key

OR

sandwich-shop.tenants in your MongoDB cluster

{
  "_id": "tenant id",
  "key": "this-is-my-api-key"
}

TL;DR - sudo make me a gowich

mkdir ~/sandwich-shop
go install github.com/suhay/sandwich-shop@latest
go install github.com/suhay/sandwich-shop/sandwiches/gowich@latest

cd ~/sandwich-shop
printf "JWT_SECRET=1234567890jwtsecretcode\nTENANTS=~/sandwich-shop" > .env
printf "JWT_SECRET=1234567890jwtsecretcode\nGO1_17=/usr/local/go/bin/go" > .node1.env
echo '[{"_id": "ciabatta", "name": "Ciabatta", "host": "http://127.0.0.1", "port": 4007, "runtimes": ["go1_17"]}]' > sandwiches.json
mkdir myFunctions

cd myFunctions
echo "password1234" > .key
printf -- '---\nhello:\n  runtime: go1_17\n  path: hello.go' > orders.yml
printf 'package main\nimport "fmt"\nfunc main() {\nfmt.Printf("%%s", "Hello!")\n}' > hello.go
Run
sandwich-shop --env ~/sandwich-shop/.env &
gowich --env ~/sandwich-shop/.node1.env --port 4007 &
Use
curl -X POST --header "Authorization: Bearer password1234" http://localhost:3002/shop/myFunctions/hello

Current Development

  • Move tenant path into an environment variable
  • CLI for adding tenants, standing up and tearing down Sandwiches, and changing .key values.
  • A+B testing against a Serverless pattern (to see if this is even a thing or just something for fun)
  • Security audit on tenants
Developing for Sandwich Shop
make dev

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
sandwiches
tenants

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL