At the heart of Cdev is the Serverless Function
. This is the most powerful resource available through the framework because it is where you have to freedom to create what you want. We have made many optimizations to create the best experience for creating and maintaining Serverless Functions
.
For a more in depth discussion about the capabilities and limits of Serverless Functions
checkout our architecture documentation
from cdev.resources.simple.xlambda import simple_function_annotation @simple_function_annotation("hello_function") def hello_world(event, context): print('Hello World')
The component that contains the function is registered in src/cdev_project.py.
# Generated as part of Quick Start project template
import os
from cdev.default.cloudmapper import DefaultMapper
from cdev.default.components import Cdev_FileSystem_Component
from cdev import Project as cdev_project
myProject = cdev_project.instance()
myProject.add_mapper(DefaultMapper())
# register hello_world component
myProject.add_component(
Cdev_FileSystem_Component(os.path.join("src", "hello_world"), "hello_world_comp")
)
Once your function is deployed, you can execute it with the cdev run function.execute
command.
cdev run function.execute <component_name>.hello_function
You can then look at the logs from the deployed function
cdev run function.logs <component_name>.hello_function
As you are working on a Function
, you can use the --watch
flag to have live updated feed of your logs
cdev run function.logs <component_name>.hello_function --watch
Note that it may take a second for the logs to show up since they are being pulled from the cloud.
You can get the available commands for Serverless Functions
by running:
cdev run function -h
One of the most important aspects of Serverless Functions is that they can be triggered by different Events
. By passing an Event
construct into the args of your Serverless Function
, your deployed Serverless Function
will be triggered by the event in the Cloud. The following demonstrates a Serverless Function
being hooked up to an API Route Event
.
import json from cdev.resources.simple.xlambda import simple_function_annotation from cdev.resources.simple.api import Api, route_verb myApi = Api("demo") hello_route = myApi.route("/hello", route_verb.GET) @simple_function_annotation("hello_function", events=[hello_route.event()]) def hello_world(event, context): print(event) message = "Hello!" return { "isBase64Encoded": False, "statusCode": 200, "body": json.dumps(message), "headers": { "content-type": "application/json" } }
You can now get the url of the created API
and execute your function by going to the /hello
route.
cdev output <component_name>.api.demo.endpoint
You can use the command line tool curl
to test your live url or
curl <api_endpoint>/hello
You can even go to the url in your favorite web browser!
After visiting the url you can also checkout the logs of your Function
to see the information that is passed to your Function
about the Event
that triggered it.
cdev run function.logs <component_name>.hello_function
By default, a created Function
has no permissions to access other resources, so you have to provide permissions to your Function
for it to be able to access other resources. Other resources will have properties that define the set of Permissions
available to be granted to a Function
.
import boto3 from cdev.resources.simple.xlambda import simple_function_annotation from cdev.resources.simple.object_store import Bucket myBucket = Bucket("demo_bucket") s3_client = boto3.client('s3') @simple_function_annotation("hello_function", permissions=[myBucket.available_permissions.READ_AND_WRITE_BUCKET]) def hello_world(event, context): bucket_name = "BUCKET_NAME" print( s3_client.list_objects( Bucket=bucket_name ).get('Contents') )
Although the above Function
has permission to access the Bucket
, it does not by default know the name of the Bucket
. All functions have a set of Environment Variables that can be set. To access these variables within the Serverless Function
use the os.environ
variable.
import boto3 import os from cdev.resources.simple.xlambda import simple_function_annotation from cdev.resources.simple.object_store import Bucket myBucket = Bucket("demo_bucket") s3_client = boto3.client('s3') @simple_function_annotation("hello_function", permissions=[myBucket.available_permissions.READ_AND_WRITE_BUCKET], environment={"BUCKET_NAME": myBucket.output.bucket_name}) def hello_world(event, context): bucket_name = os.environ.get("BUCKET_NAME") print(bucket_name) print( s3_client.list_objects( Bucket=bucket_name ).get('Contents') )
Third Party Packages are an important part of modern software development. To use a third party package, simple install it with pip
(we highly recommend using a virtual python environment) and then use the package in a function.
pip install pandas
import pandas from cdev.resources.simple.xlambda import simple_function_annotation from cdev.resources.simple.object_store import Bucket @simple_function_annotation("hello_function") def hello_world(event, context): print(pandas) print("Hey friends")
It might take a few seconds to upload a copy of the dependency to the cloud when first used, but when using the package in other functions in the same component, it will simply link to the already deployed version.
import pandas from cdev.resources.simple.xlambda import simple_function_annotation from cdev.resources.simple.object_store import Bucket @simple_function_annotation("hello_function") def hello_world(event, context): print(pandas) print("Hey friends") @simple_function_annotation("hello_function2") def hello_world2(event, context): print(pandas) print("Hey friends from a different function")