Context
In some cases, it is convinient that a function can be invoked automatically by events. For example, if OSS can automatically trigger functions upon new image upload or update, it is not necessary to develop and maintain services to poll OSS events and invoke FC (Function Compute) functions. This document introduces how OSS events can be configured to automatically invoke FC functions.
Executions of a FC function are event-driven, currenly FC supports OSS, Log Service and Tablestore events, more event source support will be added. Unlike previous examples, FC functions are invoked by OSS event notifications instead of CLI commands. Similar to the database trigger concept, a FC trigger describes a set of rules. When an event matches these rules, the event source triggers the configured function. For example, OSS automatically invokes a configured function responding to OSS event related to objects with prefix source/
.
In this example, you can learn about:
- How to create a function by using a code package stored in OSS.
- How to use an OSS trigger to automatically process files stored in OSS by a FC function.
This example demostrates when an image with a source/
prefix is stored in OSS, a FC function is automatically triggered. The function scales the image and finally stored the output to OSS with a processed/
prefix. For example, an image source/serverless.png
is automatically processed and stored to processed/serverless.png
upon arriving at OSS.
This example modifies the function in Example 3. The input object is not an image instead an OSS event, and the processed image is not returned as a function execution result instead is stored in OSS.
This example assumes that:
- An
fc-code
bucket stores the function code. When creating a function, FC copies the code from this bucket. - An
image-album
bucket. The prefix of source images issource/
and that of processed images isprocessed/
.
Note:
In your own setup, you must replace the example buckets with your own buckets. You can also use a single bucket to perform the operations in this example. You can create a bucket in the OSS console, and replace the OSS endpoint with your own.
Update a Service Role (ServiceRole)
In Example 3, we have created an fc-logs
role, and permitted FC to assume this role and write logs to LogHub. In this example, this role is further granted with the following permissions:
- Read objects from
fc-code
bucket. Then FC is allowed to copy code packages from this bucket to create functions. - Read/Write objects from/to
image-album
bucket which allows functions can read images from this bucket and write execution results to it.
mkrp fc-copy-code-all -a '"oss:GetObject"' -r '"*"'
attach -p /ram/policies/fc-copy-code-all -r /ram/roles/fc-logs
mkrp fc-oss-rw -a '["oss:GetObject", "oss:PutObject"]' -r '"*"'
attach -p /ram/policies/fc-oss-rw -r /ram/roles/fc-logs
Note: If any problem occurs, click the last row of this page to view the complete demo shell operation video.
Create a Function
Upload Code to OSS
In the code directory, create an “oss_image_process.js” file and implement a “resize” function:
'use strict';
console.log('Loading function ...');
var oss = require('ali-oss').Wrapper;
var fs = require('fs');
var jimp = require("jimp");
module.exports.resize = function (eventBuf, ctx, callback) {
console.log('Received event:', eventBuf.toString());
var event = JSON.parse(eventBuf);
var ossEvent = event.events[0];
// Required by OSS sdk: OSS region is prefixed with "oss-", e.g. "oss-cn-shanghai"
var ossRegion = "oss-" + ossEvent.region;
// Create oss client.
var client = new oss({
region: ossRegion,
// Credentials can be retrieved from context
accessKeyId: ctx.credentials.accessKeyId,
accessKeySecret: ctx.credentials.accessKeySecret,
stsToken: ctx.credentials.securityToken
});
// Bucket name is from OSS event
client.useBucket(ossEvent.oss.bucket.name);
// Processed images are saved to processed/
var newKey = ossEvent.oss.object.key.replace("source/", "processed/");
var tmpFile = "/tmp/processed.png";
// Get object
console.log('Getting object: ', ossEvent.oss.object.key)
client.get(ossEvent.oss.object.key).then(function (val) {
// Read object from buffer
jimp.read(val.content, function (err, image) {
if (err) {
console.error("Failed to read image");
callback(err);
return;
}
// Resize the image and save it to a tmp file
image.resize(128, 128).write(tmpFile, function (err) {
if (err) {
console.error("Failed to write image locally");
callback(err);
return;
}
// Putting object back to OSS with the new key
console.log('Putting object: ', newKey);
client.put(newKey, tmpFile).then(function (val) {
console.log('Put object:', val);
callback(null, val);
return;
}).catch(function (err) {
console.error('Failed to put object: %j', err);
callback(err);
return
});
});
});
}).catch(function (err) {
console.error('Failed to get object: %j', err);
callback(err);
return
});
};
# -*- coding: utf-8 -*-
import oss2, json
from wand.image import Image
def resize(event, context):
evt = json.loads(event)
creds = context.credentials
# Required by OSS sdk
auth=oss2.StsAuth(
creds.access_key_id,
creds.access_key_secret,
creds.security_token)
evt = evt['events'][0]
bucket_name = evt['oss']['bucket']['name']
endpoint = 'oss-' + evt['region'] + '.aliyuncs.com'
bucket = oss2.Bucket(auth, endpoint, bucket_name)
objectName = evt['oss']['object']['key']
# Processed images are saved to processed/
newKey = objectName.replace("source/", "processed/")
remote_stream = bucket.get_object(objectName)
if not remote_stream:
return
remote_stream = remote_stream.read()
with Image(blob=remote_stream) as img:
with img.clone() as i:
i.resize(128, 128)
new_blob = i.make_blob()
bucket.put_object(newKey, new_blob)
Code packaging: As jimp has been installed in Example 3, skip its installation in this example. The Alibaba Cloud OSS JavaScript SDK, and the nodejs6 runtime of FC already contains this package. Therefore, it does not need to be installed either.
Upload the code package to OSS. The following uses ossutil as an example to describe how to upload the package by the CLI. If you have not installed ossutil in your system, go to the OSS console and upload code.zip
to the fc-code
bucket. (Note: The endpoint of this fc-code bucket must be the same as your preset endpoint.)
cd code
ls
# hello_world.js image_process.js node_modules oss_image_process.js
zip -r code.zip .
ossutil -e http://oss-cn-shanghai.aliyuncs.com cp code.zip oss://fc-code/code.zip
Note: The previous commands are normal Linux commands rather than the commands in the shell mode of the FC CLI.
Create a function.
mkf demo/resize_oss_image -t nodejs6 -h oss_image_process.resize -b fc-code -o code.zip
-b
specifies the bucket to store the code.
-o
specifies the object key of the code package in the bucket.
Create a Trigger
Before creating a trigger, create an invocation role. Then OSS assumes this role to invoke functions.
mkir fc-invoke-function
mkrp fc-invoke-all -a '"fc:InvokeFunction"' -r '"*"'
attach -p /ram/policies/fc-invoke-all -r /ram/roles/fc-invoke-function
Create a trigger.
cd demo/resize_oss_image
mkt resize_image -t oss -r acs:ram::12345:role/fc-invoke-function -s acs:oss:cn-shanghai:12345:image-album -c resize_image_config.yaml
-t
specifies the trigger type. Only OSS is supported currently.
-r
specifies the role that OSS plays to call functions. Change12345
to your Alibaba Cloud account ID.
-s
specifies the bucket ARN of the event source. Change12345
to your Alibaba Cloud account ID andimage-album
to your bucket name.
-c
specifies the configuration of the OSS trigger. The information of resize_image_config.yaml is as follows:
triggerConfig:
events:
- oss:ObjectCreated:PostObject
- oss:ObjectCreated:PutObject
filter:
key:
prefix: source/
Test a Trigger
Upload an image to image-album/source
. If ossutil is not installed, go to the OSS console to upload the image.
ossutil -e http://oss-cn-shanghai.aliyuncs.com cp data/serverless.png oss://image-album/source/serverless.png
ossutil -e http://oss-cn-shanghai.aliyuncs.com ls oss://image-album/processed/
Note that in the previous trigger configuration, OSS is configured to only trigger the FC function upon objects uploaded with the source
prefix and store execution results to objects with the processed
prefix. In is important that these two prefixes are different. For example, if you store the output object with the source
prefix, the output object triggers invocation to the function again, resulting in an infinite loop and causing unnecessary costs.
To view the complete demo operation video of example 4, click oss_image_process.