K2 Cloud and Azure Function Apps

If you are looking at K2 Cloud or already using it, you will most likely be aware that you cannot create or use custom service brokers in this version of K2 (you can still do this in K2 Five). So, what do you do if you need to execute some custom code in K2? Azure Functions could be your solution. 

Azure Functions enable you to run code-on-demand without having to provision your own infrastructure. Functions can be written in a variety of languages (e.g. C#, JavaScript, Python) and can respond to a variety of events (e.g. HTTP Trigger, Service Bus Queue Trigger). As a K2 Cloud customer, you have an Office 365 subscription, which means you will also have an Azure subscription so you can get started with Azure Functions without any setup (See An introduction to Azure Functions for more details, including information on pricing) 

So how can you incorporate Azure Functions into your K2 solution? 

K2 and REST 

K2 now has a REST Service broker that allows you to integrate K2 with REST-based web services. A good explanation of what REST (REpresentational State Transfer) web services are can be found here. 

The REST broker is the key to working with Azure Functions. The K2 REST service works by reading a service “descriptor” file, called a swagger or OpenAPI file. A swagger file describes the methods and properties that a web service exposes, allowing K2 to create matching SmartObjects. I will provide options below on how to create the swagger file for our function. 

Azure Function Example 

Let’s look at a simple function example. Say as part of a solution you need to convert a number to character/s. So, for example, 1 becomes “A”, “2” becomes “B”, “26” becomes “Z”, “27” becomes “AA” and so on. You could try and do this with functions and expressions in a K2 form or workflow, but it would get quite complex. Or, you could write some code that does this, deploy it as an Azure Function and call it from K2 as a SmartObject. 

Here is some code that does what we need. It looks for a query parameter named “Number” and then uses a while loop and the modulo function to convert the number to characters.  

using System.Net; 

 

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) 

{ 

 log.Info("C# HTTP trigger function processed a request."); 

 

 // parse query parameter 

 string strNumber = req.GetQueryNameValuePairs() 

 .FirstOrDefault(q => string.Compare(q.Key, "Number", true) == 0) 

 .Value; 

 

 int dividend = int.Parse(strNumber); 

 string columnName = String.Empty; 

 int modulo; 

 

 while (dividend > 0) 

 { 

 modulo = (dividend - 1) % 26; 

 columnName = Convert.ToChar(65 + modulo).ToString() + columnName; 

 dividend = (int)((dividend - modulo) / 26); 

 } 

 

 return req.CreateResponse(HttpStatusCode.OK,columnName); 

}  

So how do we use this code in an Azure Function?

The first thing to do is open your Azure Portal and click the “Create a resource” button and choose “Compute” and the “Function App” 

Add the Function “App name” and set the other details. The Function App is a container for a number of functions – you can add more functions to your Function App later. You may need to create a Resource Group (see Manage Azure resources through portal for more info) if you do not have one you can use. 

Once you hit “Create” Azure will provision you with your function app and you will see the following  

 

Select “Go to resource” and start to edit your function app. 

We are going to choose to use the “Webhook + API” and “CSharp” option. We are using the webhook as this will let us trigger the function by an HTTP call. You can use any programming language you are comfortable with. 

A default function is created for you. Replace this function with the code above. You can then test this function by clicking the “Run” button. Add a number into the “Number” Query Parameter, click the “Run” button at the bottom right and view the result in the Output pane. Note that the log file also shows some entries indicating if the execution was successful, and outputs our “Log.Info” line from the code. 

Ok great, our function works, now how do we consume it in K2? 

Create Swagger File 

There are two choices for creating the swagger file. You can create a template in Azure and then manually update it, or create one from scratch from a tool like REST United (see Resources for Working with the REST Service Broker). 

I will not go into detail on how to create the swagger file, but have include a definition for the GetCharOfNumber function at the end of this post. 

(For a more detailed walkthrough of these steps see Create an OpenAPI definition for a function) 

To get a swagger template for your function app, expand your function and select the Integrate option, and make sure the “Get” HTTP method is selected. Set your “Authorization level” to anonymous for this exercise, and click “Save”. 

Now click on your Function App and select the “API definition” menu item. 

Click “Generate API definition template”, and the swagger template is generated for you 

You can now copy the template out into another editor or edit it directly in the azure portal.  

Once you have created your swagger file, you can choose to host it back in the Azure portal, or in any other location accessible by your K2 Cloud instance. 

If you want to host it back in Azure, you can overwrite the template with your swagger and Save. The API Definition URL can then be used when creating your REST service instance.

Create REST Service Instance 

Open K2 Management and create a new REST Service instance. Add in the swagger location into the Descriptor location and use the Service Account as the Authentication Mode. All other settings can be left as default. Click the option to generate the SmartObjects (or leave unticked and create later) and then Ok to create the service instance. 

Once the SmartObject is created, it’s time to test it. Find it under the Categories in the Management site and execute the “GetCharOfNumber” method.  

{ 

"swagger": "2.0", 

"info": { 

"title": "Azurewebsites", 

"description": "API for <yourfunctionappname>.azurewebsites.net", 

"version": "0.0.0" 

}, 

"host": "<yourfunctionappname>.azurewebsites.net", 

"schemes": ["https"], 

"paths": { 

"/api/GetCharOfNumber": { 

"get": { 

"tags": ["Web"], 

"description": "Get char of number", 

"operationId": "GetCharOfNumber", 

"produces": ["application/json"], 

"parameters": [{ 

"name": "Number", 

"in": "query", 

"description": "Number", 

"required": false, 

"type": "string", 

"x-example": "445" 

}], 

"responses": { 

"200": { 

"description": "OK", 

"schema": { 

"type": "string" 

}, 

"examples": { 

"application/xml": "<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">QC</string>" 

} 

} 

}, 

"security": [] 

} 

} 

}, 

"securityDefinitions": { 

 

}, 

"security": [], 

"tags": [{ 

"name": "Web", 

"description": "Operations about Web" 

}] 

}

Leave a Reply

Your email address will not be published. Required fields are marked *