Files
fn-serverless/docs/developers/fn-format.md
Reed Allman 3a9c48b8a3 http-stream format (#1202)
* POC code for inotify UDS-io-socket

* http-stream format

introducing the `http-stream` format support in fn. there are many details for
this, none of which can be linked from github :( -- docs are coming (I could
even try to add some here?). this is kinda MVP-ish level, but does not
implement the remaining spec, ie 'headers' fixing up / invoke fixing up. the
thinking being we can land this to test fdks / cli with and start splitting
work up on top of this. all other formats work the same as previous (no
breakage, only new stuff)

with the cli you can set `format: http-stream` and deploy, and then invoke a
function via the `http-stream` format. this uses unix domain socket (uds) on
the container instead of previous stdin/stdout, and fdks will have to support
this in a new fashion (will see about getting docs on here). fdk-go works,
which is here: https://github.com/fnproject/fdk-go/pull/30 . the output looks
the same as an http format function when invoking a function. wahoo.

there's some amount of stuff we can clean up here, enumerated:

* the cleanup of the sock files is iffy, high pri here

* permissions are a pain in the ass and i punted on dealing with them. you can
run `sudo ./fnserver` if running locally, it may/may not work in dind(?) ootb

* no pipe usage at all (yay), still could reduce buffer usage around the pipe
behavior, we could clean this up potentially before removal (and tests)

* my brain can’t figure out if dispatchOldFormats changes pipe behavior, but
tests work

* i marked XXX to do some clean up which will follow soon… need this to test fdk
tho so meh, any thoughts on those marked would be appreciated however (1 less
decision for me). mostly happy w/ general shape/plumbing tho

* there are no tests atm, this is a tricky dance indeed. attempts were made.
need to futz with the permission stuff before committing to adding any tests
here, which I don't like either. also, need to get the fdk-go based test image
updated according to the fdk-go, and there's a dance there too. rumba time..

* delaying the big big cleanup until we have good enough fdk support to kill
all the other formats.

open to ideas on how to maneuver landing stuff...

* fix unmount

* see if the tests work on ci...

* add call id header

* fix up makefile

* add configurable iofs opts

* add format file describing http-stream contract

* rm some cruft

* default iofs to /tmp, remove mounting

out of the box fn we can't mount. /tmp will provide a memory backed fs for us
on most systems, this will be fine for local developing and this can be
configured to be wherever for anyone that wants to make things more difficult
for themselves.

also removes the mounting, this has to be done as root. we can't do this in
the oss fn (short of requesting root, but no). in the future, we may want to
have a knob here to have a function that can be configured in fn that allows
further configuration here. since we don't know what we need in this dept
really, not doing that yet (it may be the case that it could be done
operationally outside of fn, eg, but not if each directory needs to be
configured itself, which seems likely, anyway...)

* add WIP note just in case...
2018-09-14 10:59:12 +01:00

3.9 KiB

Fn container contract

NOTE: THIS IS WORK IN PROGRESS AND ITS API IS SUBJECT TO CHANGE

This document will describe the details of how a function works, inputs/outputs, etc. (It is meant to replace (./function-format.md) - if the time has come, remove this line, for now it defines the 'http-stream' format option)

The basic idea is to handle http requests over a unix domain socket. Each container will only receive one request at a time, in that until a response is returned from a previous request, no new requests will be issued to a container's http server.

XXX(reed): motivation section for future us posterity?

FDK Contract outline

Function Development Kits (FDKs) are libraries for various languages that implement Fn's container contract for function input, output and configuration. In order to be a fully 'FDK compliant', below are the rules:

If FN_FORMAT variable is http-stream, then FDKs MUST parse FN_LISTENER environment variable.

FN_LISTENER must contain the listener address for FDKs to bind/listen to. Currently we only support unix-domain-socket (UDS) with SOCK_STREAM (TCP). This means FN_LISTENER prefix is always unix:/.

For example:

FN_LISTENER=unix:/var/run/fn/listener/listen.sock
FN_FORMAT=http-stream

If FN_FORMAT is http-stream, then absence of FN_LISTENER or "unix:" prefix in FN_LISTENER is an error and FDKs are REQUIRED to terminate/exit with error.

Before exiting, FDKs SHOULD remove the UDS file (from FN_LISTENER path).

FDKs upon creation of UDS file on disk with bind system call SHOULD be ready to receive and handle traffic. Upon bind call, the UDS file MUST be writable by fn-agent.

Path in FN_LISTENER (after "unix:" prefix) cannot be larger than 107 bytes.

FDKs MUST listen on the unix socket within 5 seconds of startup, Fn will enforce time limits and will terminate such FDK containers.

Once initialised the FDK should respond to HTTP requests by accepting connections on the created unix socket.

The FDK SHOULD NOT enforce any read or write timeouts on incoming requests or responses

The FDK SHOULD support HTTP/1.1 Keep alive behaviour

The agent MUST maintain no more than one concurrent HTTP connection to the FDK HTTP servers

Containers MUST implement HTTP/1.1

Any data sent to Stdout and Stderr will be logged by Fn and sent to any configured logging facility

Each function container is responsible for handling multiple function invocations against it, one at a time, for as long as the container lives.

Fn will make HTTP requests to the container on the /call URL of the containers HTTP UDS port using.

POST /call HTTP/1.1
Host: localhost:8080
Fn-Call-Id : <call_id>
Fn-Deadline: <date/time>
Content-type: application/cloudevent+json

<Body here>
HTTP/1.1 200 OK
Fn-Http-Status: 204
Fn-Http-H-My-Header: foo
Content-type: text/plain

<Body here>

Environment Variables

The below are the environment variables that a function can expect to use. FDKs SHOULD provide a facility to easily access these without having to use an OS library.

  • FN_ID - fn id
  • FN_APP_ID - app id of the fn
  • FN_NAME - name of the fn
  • FN_APP_NAME - the name of the application of the fn
  • FN_FORMAT - http-stream (DEPRECATED)
  • FN_LISTENER - the path where a unix socket file should accept
  • FN_MEMORY - a number representing the amount of memory available to the call, in MB
  • FN_TMPSIZE - a number representing the amount of writable disk space available under /tmp for the call, in MB

In addition to these, all config variables set on app.config or fn.config will be populated into the environment exactly as configured, for example if app.config = { "HAMMER": "TIME" } your environment will be populated with HAMMER=TIME.

Headers

  • Fn-Call-Id - id for the call
  • Fn-Deadline - RFC3339 timestamp indicating the deadline for a function call
  • Fn-* - reserved for future usage
  • * - any other headers, potentially rooted from an http trigger