Easily extend your storage workflows with serverless functions.
IBM Cloud Functions, IBM's polyglot Functions-as-a-Service (FaaS) programming platform, comes with support for triggers. With triggers, you can react to external events, like a new entry in a database, a message on a queue, or a commit in GitHub. Triggers can trigger sequences of actions.
A recent addition to the list of built-in triggers allows you to extend Cloud Functions by integrating with IBM Cloud Object Storage (COS). The COS trigger type lets you run custom code logic when a new object is stored, updated, or deleted from a designated bucket in COS.
The blog post "Cloud Object Storage Event Provider Enables "Hello, Serverless" and More" introduced the trigger and listed several use cases, such as data ingestion and cleansing, map/reduce jobs, image auto-sharpening, and transcribing audio files with ML models into text.
Thumbnail generation infused with AI
Today, I'll focus on the thumbnail generation use case. It is a simple use case where we want to generate a smaller, optimized version of an image. This can be useful in content management systems (CMS) backed by Cloud Object Storage buckets. Whenever a user uploads a new image, an asynchronous task can be triggered to generate a thumbnail for the image. It could generate different sizes based on your needs (e.g., showing an image gallery, using the image as a poster or a vertical banner). Additionally, you may want to analyze the image with AI to understand what is the image about.
Let's define the requirements for our use case:
- When the user adds a new image (JPG, PNG, or GIF files) to the CMS, the system should do the following:
- Generate a thumbnail (a smaller version of the image). The width of the image should be 160px and it should keep the aspect ratio of the original image.
- Analyse the image to identify what is the image about (e.g., objects or people) and store the metadata for later use.
- When the user removes the image, the system should remove the generated thumbnail and metadata.
To implement this use case, images will be stored in Cloud Object Storage and processing will be done with code running in Cloud Functions. To analyze the image, you can use IBM Cloud Visual Recognition. It comes with default classification and can be trained with your own custom models.
Thumbnail and image analysis flows
The requirements give two flows to consider—when the user adds a new image and when the user removes the image.
Adding an image
- The user uploads an image to the Cloud Object Storage bucket (directly or through a tool like a CMS).
- Cloud Object Storage sends an event to Cloud Functions.
- This event triggers a sequence of actions:
- A filter ensures the filename has one of the supported file extensions (.jpg, .jpeg, .gif, .png).
- A thumbnail is generated and stored under the thumbnails/ prefix in the bucket.
- Visual Recognition is called on the image and the results are stored in a separate file under the metadata/ prefix in the bucket.
Deleting an image
- The user deletes an image.
- Cloud Object Storage sends an event to Cloud Functions.
- The event triggers the delete action to remove the generated thumbnail and visual recognition metadata.
Deploying the sample code
The source code implementing these flows is available in GitHub. It comes with scripts to set up Cloud Object Storage and deploy the Cloud Functions triggers and actions. Detailed instructions can be found in the README.
Once you have configured your environment with the local.env file, you can start running the scripts. You will need the IBM Cloud CLI, the Cloud Object Storage plugin, the Cloud Functions plugin, and the
jq command line utility.
000-prereqs.sh performs basic checks about the target resource group, the target region, the required IBM Cloud plugins, and external tools.
010-create-services.sh creates a Cloud Object Storage service, a bucket, and a Visual Recognition service. It also sets up service keys. The service keys are used by Cloud Functions actions to access COS and Visual Recognition services.
020-create-functions.sh configures Cloud Functions. It creates an authorization between Cloud Functions and Cloud Object Storage, allowing Cloud Functions to be notified by COS. Then, it adds two Cloud Functions triggers: one to react to files added to the COS bucket and one to process deleted files. Each trigger is connected to a sequence of actions. Actions are initialized with the needed credentials (API keys, endpoints) to access COS and Visual Recognition.
Test the setup
At that stage, you can start testing the system.
030-test.sh downloads an image from Unsplash.com and uploads it to Cloud Object Storage. It uses the Cloud Object Storage plugin for the IBM Cloud CLI to interact with COS. The script shows the content of the bucket before the upload, waits for 10 seconds, and lists the content again where you should see the thumbnail and metadata appear in the list.
You can also test the setup manually by going to the IBM Cloud console, selecting the Cloud Object Storage service, and uploading an image file to the bucket.
Try to delete the image you uploaded. This will trigger the other event flow and automatically remove the thumbnail and the metadata.
About the source code
The shell scripts show how to configure COS and Cloud Functions using the IBM Cloud CLI. Another option would have been to use the IBM Cloud console but I like to automate my projects as it is less error prone.
Solutions with the COS trigger for IBM Cloud Functions
The COS trigger for Cloud Functions makes it very easy to build a data-driven solution. With a simple trigger configuration, you can start a sequence of actions to process file addition or removal. Once in your action, the COS SDKs for Node.js, Java, Python, Go become very handy to deal with the bucket content.
This sample is only a starting point. There are several addition options when configuring a trigger, such as specifying a filter to only receive events for objects with keys starting with or ending with a specific text. Also in the sample, if you upload two files with the same name, the second one will override the first. A more robust implementation may use unique IDs for the file names in order to prevent this.
If you have feedback, suggestions, or questions about this post, please reach out to me on Twitter (@L2FProd).