Skeleton of basic functionality, all as TODOs
This commit is contained in:
parent
11f1066619
commit
238d045691
14
shard.lock
Normal file
14
shard.lock
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
version: 2.0
|
||||||
|
shards:
|
||||||
|
commander:
|
||||||
|
git: https://github.com/mrrooijen/commander.git
|
||||||
|
version: 0.4.0
|
||||||
|
|
||||||
|
crystar:
|
||||||
|
git: https://github.com/naqvis/crystar.git
|
||||||
|
version: 0.4.0
|
||||||
|
|
||||||
|
docr:
|
||||||
|
git: https://github.com/marghidanu/docr.git
|
||||||
|
version: 0.1.1+git.commit.59fb466b748d5d29a8f2de88a54b71dbfe0285aa
|
||||||
|
|
@ -6,8 +6,15 @@ authors:
|
|||||||
|
|
||||||
targets:
|
targets:
|
||||||
faaso:
|
faaso:
|
||||||
main: src/faaso.cr
|
main: src/main.cr
|
||||||
|
|
||||||
crystal: '>= 1.12.2'
|
crystal: '>= 1.12.2'
|
||||||
|
|
||||||
license: MIT
|
license: MIT
|
||||||
|
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
docr:
|
||||||
|
github: marghidanu/docr
|
||||||
|
commander:
|
||||||
|
github: mrrooijen/commander
|
67
src/faaso.cr
67
src/faaso.cr
@ -1,6 +1,71 @@
|
|||||||
|
require "commander"
|
||||||
|
|
||||||
# TODO: Write documentation for `Faaso`
|
# TODO: Write documentation for `Faaso`
|
||||||
module Faaso
|
module Faaso
|
||||||
VERSION = "0.1.0"
|
VERSION = "0.1.0"
|
||||||
|
|
||||||
# TODO: Put your code here
|
module Commands
|
||||||
|
class Build
|
||||||
|
@arguments : Array(String) = [] of String
|
||||||
|
@options : Commander::Options
|
||||||
|
|
||||||
|
def initialize(options, arguments)
|
||||||
|
@options = options
|
||||||
|
@arguments = arguments
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
@arguments.each do |arg|
|
||||||
|
puts "Building function... #{arg}"
|
||||||
|
# A function is a folder with stuff in it
|
||||||
|
# TODO: decide template based on file extensions or other metadata
|
||||||
|
# TODO: copy template and add function files to it
|
||||||
|
# TODO: build Docker image
|
||||||
|
# TODO: push Docker image to registry
|
||||||
|
# TODO: return image name for testing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Up
|
||||||
|
@arguments : Array(String) = [] of String
|
||||||
|
@options : Commander::Options
|
||||||
|
|
||||||
|
def initialize(options, arguments)
|
||||||
|
@options = options
|
||||||
|
@arguments = arguments
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
@arguments.each do |arg|
|
||||||
|
puts "Starting function... #{arg}"
|
||||||
|
# TODO: Check that we have an image for the function
|
||||||
|
# TODO: Start a container with the image
|
||||||
|
# TODO: Run test for healthcheck
|
||||||
|
# TODO: Map route in reverse proxy to function
|
||||||
|
# TODO: Return function URL for testing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Down
|
||||||
|
@arguments : Array(String) = [] of String
|
||||||
|
@options : Commander::Options
|
||||||
|
|
||||||
|
def initialize(options, arguments)
|
||||||
|
@options = options
|
||||||
|
@arguments = arguments
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
@arguments.each do |arg|
|
||||||
|
puts "Stopping function... #{arg}"
|
||||||
|
# TODO: check if function is running
|
||||||
|
# TODO: stop function container
|
||||||
|
# TODO: delete function container
|
||||||
|
# TODO: remove route from reverse proxy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
36
src/main.cr
Normal file
36
src/main.cr
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
require "commander"
|
||||||
|
require "./faaso.cr"
|
||||||
|
|
||||||
|
cli = Commander::Command.new do |cmd|
|
||||||
|
cmd.use = "faaso"
|
||||||
|
cmd.long = "Functions as a Service, Open"
|
||||||
|
|
||||||
|
cmd.commands.add do |command|
|
||||||
|
command.use = "build"
|
||||||
|
command.short = "Build a function"
|
||||||
|
command.long = "Build a function's Docker image and optionally upload it to registry"
|
||||||
|
command.run do |options, arguments|
|
||||||
|
Faaso::Commands::Build.new(options, arguments).run
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
cmd.commands.add do |command|
|
||||||
|
command.use = "up"
|
||||||
|
command.short = "Start a function"
|
||||||
|
command.long = "Start a function in a container"
|
||||||
|
command.run do |options, arguments|
|
||||||
|
Faaso::Commands::Up.new(options, arguments).run
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
cmd.commands.add do |command|
|
||||||
|
command.use = "down"
|
||||||
|
command.short = "Stop a function"
|
||||||
|
command.long = "Stop a function in a container"
|
||||||
|
command.run do |options, arguments|
|
||||||
|
Faaso::Commands::Down.new(options, arguments).run
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Commander.run(cli, ARGV)
|
39
templates/crystal-http/Dockerfile
Normal file
39
templates/crystal-http/Dockerfile
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
FROM --platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/of-watchdog:0.9.10 as watchdog
|
||||||
|
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as build
|
||||||
|
ARG ADDITIONAL_PACKAGE
|
||||||
|
|
||||||
|
COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog
|
||||||
|
|
||||||
|
RUN apk update && apk upgrade && apk add crystal shards openssl-dev ${ADDITIONAL_PACKAGE} && apk cache clean
|
||||||
|
|
||||||
|
WORKDIR /home/app
|
||||||
|
|
||||||
|
COPY function/shard.yml shard.yml
|
||||||
|
RUN shards install
|
||||||
|
COPY . .
|
||||||
|
RUN crystal build main.cr -o handler --error-trace -p && rm -rf /root/.cache
|
||||||
|
|
||||||
|
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine as ship
|
||||||
|
ARG ADDITIONAL_PACKAGE
|
||||||
|
RUN apk update && apk upgrade && apk add openssl pcre2 libgcc gc libevent ${ADDITIONAL_PACKAGE} && apk cache clean
|
||||||
|
# Add non root user
|
||||||
|
# Add non root user
|
||||||
|
RUN addgroup -S app && adduser app -S -G app
|
||||||
|
|
||||||
|
WORKDIR /home/app
|
||||||
|
USER app
|
||||||
|
|
||||||
|
COPY --from=build /home/app/function/ .
|
||||||
|
COPY --from=build /home/app/handler .
|
||||||
|
COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog
|
||||||
|
|
||||||
|
ENV fprocess="./handler"
|
||||||
|
ENV exec_timeout=30
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=2s CMD [ -e /tmp/.lock ] || exit 1
|
||||||
|
|
||||||
|
ENV upstream_url="http://127.0.0.1:5000"
|
||||||
|
ENV mode="http"
|
||||||
|
|
||||||
|
CMD ["fwatchdog"]
|
12
templates/crystal-http/function/handler.cr
Normal file
12
templates/crystal-http/function/handler.cr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
require "http/request"
|
||||||
|
require "http/headers"
|
||||||
|
|
||||||
|
class Handler
|
||||||
|
def run(request : HTTP::Request)
|
||||||
|
{
|
||||||
|
body: "Hello, Crystal. You said: #{request.body.try(&.gets_to_end)}",
|
||||||
|
status_code: 200,
|
||||||
|
headers: HTTP::Headers{"Content-Type" => "text/plain"},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
2
templates/crystal-http/function/shard.yml
Normal file
2
templates/crystal-http/function/shard.yml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
name: crystal-http-template
|
||||||
|
version: 0.1.0
|
41
templates/crystal-http/main.cr
Normal file
41
templates/crystal-http/main.cr
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
require "http/server"
|
||||||
|
require "./function/handler"
|
||||||
|
|
||||||
|
server = HTTP::Server.new do |context|
|
||||||
|
response_triple : NamedTuple(body: String, headers: HTTP::Headers, status_code: Int32) |
|
||||||
|
NamedTuple(body: String, headers: HTTP::Headers) |
|
||||||
|
NamedTuple(body: String, status_code: Int32) |
|
||||||
|
NamedTuple(body: String) |
|
||||||
|
NamedTuple(headers: HTTP::Headers, status_code: Int32) |
|
||||||
|
NamedTuple(headers: HTTP::Headers) |
|
||||||
|
NamedTuple(status_code: Int32)
|
||||||
|
|
||||||
|
handler = Handler.new
|
||||||
|
response_triple = handler.run(context.request)
|
||||||
|
|
||||||
|
if response_triple.is_a?(NamedTuple(body: String, headers: HTTP::Headers, status_code: Int32) |
|
||||||
|
NamedTuple(body: String, status_code: Int32) |
|
||||||
|
NamedTuple(headers: HTTP::Headers, status_code: Int32) |
|
||||||
|
NamedTuple(status_code: Int32))
|
||||||
|
context.response.status_code = response_triple[:status_code]
|
||||||
|
end
|
||||||
|
|
||||||
|
if response_triple.is_a?(NamedTuple(body: String, headers: HTTP::Headers, status_code: Int32) |
|
||||||
|
NamedTuple(body: String, headers: HTTP::Headers) |
|
||||||
|
NamedTuple(headers: HTTP::Headers, status_code: Int32) |
|
||||||
|
NamedTuple(headers: HTTP::Headers))
|
||||||
|
response_triple[:headers].each do |key, value|
|
||||||
|
context.response.headers[key] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if response_triple.is_a?(NamedTuple(body: String, headers: HTTP::Headers, status_code: Int32) |
|
||||||
|
NamedTuple(body: String, headers: HTTP::Headers) |
|
||||||
|
NamedTuple(body: String, status_code: Int32) |
|
||||||
|
NamedTuple(body: String))
|
||||||
|
context.response.print(response_triple[:body])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
server.bind_tcp "0.0.0.0", 5000
|
||||||
|
server.listen
|
6
templates/crystal-http/template.yml
Normal file
6
templates/crystal-http/template.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
language: crystal
|
||||||
|
fprocess: ./handler
|
||||||
|
welcome_message: |
|
||||||
|
You have created a new function which uses crystal 1.0.0.
|
||||||
|
To include third-party dependencies, use a vendoring tool like shards:
|
||||||
|
shards documentation: https://github.com/crystal-lang/shards
|
Loading…
Reference in New Issue
Block a user