A python library to create local functions of OpenFaaS functions, allowing their transparent use
Get or build a function proxy to an existing OpenFaaS function. For example, for a fibonacci
function deployed in OpenFaaS:
- Create a
FaasConnection
:
from away import builder, FaasConnection
faas = FaasConnection(’my-faas-server.com’, port=8080, user=‘admin’, password=‘1234’)
- Decorate a stub function with
away.builder.faas_function
:
@builder.faas_function(faas)
def fibonacci(n):
pass
- Call your function as if it were local
fibonacci(10) # calls the function in OpenFaaS behind the scenes, returns 55
- Or create async versions transparently
@builder.faas_function(faas)
async def fibonacci(n):
pass
res = await fibonacci(10) # calls the function asynchronously in the background, returns 55
You can also create a function from a name, to for example avoid shadowing a local variable
fibonacci_with_a_different_name = builder.sync_from_name(’fibonacci’, faas)
fibonacci_with_a_different_name(55) # returns 139583862445
If you wish to handle errors in the FaaS functions manually you can use the option implicit_exception_handling=False
to make the function return the status code alongside the response. Otherwise, the function raises an exception.
@builder.faas_function(faas, implicit_exception_handling=False)
def fibonacci(name):
pass
fibonacci(10) # returns (55, 200)
First off that's great! This project is useful for someone!
Use the family of functions builder.*_with_protocol
:
a_function = builder.sync_from_name_with_protocol('a_function_name', faas)
@builder.faas_function_with_protocol(faas)
def some_function_in_faas():
pass
You can also use away.protocol
to access the unpacking and packing functions to communicate with an already published function that used away
's default protocol for finer control.
from away import protocol
packer_function = protocol.make_client_pack_args_fn(safe_args=True)
unpacker_function = protocol.make_client_unpack_args_fn(safe_args=True)
@builder.faas_function(faas, pack_args=packer_function, unpack_args=unpacker_function)
def fibonacci(n):
pass
This in fact also hints at the fact that, if you would like to use a different packing/unpacking procedure, or must adapt to an existing function with specific return format, you can pass pack_args
and unpack_args
to builder.faas_function
to override the default behaviour (no procedure).
The packer function must have a signature of type Iterable[Any] -> str
, and the unpacker str -> Tuple[Any]
You can also push a function to an OpenFaaS server with builder.publish
. You must be logged in to the FaaS server with enough privileges to deploy functions:
faas = FaasConnection(password=1234)
@builder.publish(faas) # builds a function container and pushes it to the `faas` server
def sum_two_numbers(A,B):
return A + B
res = sum_two_numbers(1,2) # executes in the OpenFaaS server and returns 3
Note: If the function uses any values outside of the scope, they will be captured with their current values and published as part of the function. This is useful for constant values, but has the limitation that it can obviously not modify them in the outside scope.
The decorator creates also a local proxy to call the newly published function locally. The proxy has the same characteristics as the defined function (i.e: async/sync)
@builder.publish(faas)
async def sum_all_numbers(l):
res = 0
for n in l:
res = res + n
return res
await sum_all_numbers([1,2,3,4]) # async-calls the function and returns 10
If you would like to still have a local copy of the function, for example to offload the function to OpenFaaS when the load on the client gets high, use builder.mirror_in_faas
. Like with builder.publish
, the published function will retain sync/async characteristics
secret = 123
def add_secret(n):
return n + secret
add_secret_in_faas = builder.mirror_in_faas(add_secret, faas)
add_secret(1) # Executes the function locally and returns 124
add_secret_in_faas(1) # Executes the function in OpenFaaS and returns 124
Away includes a lightweight serialization-deserialization protocol to communicate with published functions based on pyyaml
. By default, it only allows the use of safely unpickle-able objects. To use values that require unsafe, pickle
-based serialization, use the kwarg safe_args
:
Note: Non-builtin objects are not currently supported at the moment due to being unable to determine the type of the arg and to find the source to include.
@builder.publish(faas, safe_args=False):
def use_unsafe_arg(rang):
res = 0
for i in rang:
res += i
return res
To annotate a function, to for example bind to an Apache Kafka topic with the OpenFaaS Kafka connector, you can use the kwarg annotations
to define your own. annotations
should be of type dict[str, str]
:
@builder.publish(faas, annotations={'topic': 'my_topic', 'other_annotations': 'cool!'})
def some_function(n):
...
if your function requires a library, use the kwarg module_imports
. Note that you should make all required imports inside the body of the function:
@builder.publish(faas, module_imports=['requests'])
def uses_library(a):
import requests
...
Note that some libraries require a C compiler to install, such as numpy
. To enable this behaviour, pass the kwarg enable_dev_building=True
@builder.publish(faas, module_imports=['numpy'], enable_dev_building=True)
def uses_np(a, b):
import numpy as np
...
To install as a pip package run python -m pip install .
from away’s main directory
Away also needs the following external dependencies:
- OpenFaas CLI
- Docker