Deploying Azure Functions
We’re going to try to move the main random password code from the previous blog post to Azure ‘Functions’ - the Azure serverless offering.
- We define a trigger for each function. The most simple might be time, where it just runs once per day. But new data in a blob is a common example; as is HTTP request. We’ll use the HTTP trigger to convert the password function.
- Consumption based pricing. With Azure Web Services we are paying for the running server all the time, even though it’s a PaaS offering. The Azure Functions framework is able to scale up and down as needed as we just pay when our function runs.
- Depending on the plan you choose, you get a stack of free executions per month (up to 1M). Payment is based on execution time though, so there is benefit in keeping execution times down with efficient code.
- There are options to use docker containers.
- It’s sometimes called FaaS - Functions as a Service (ewww)
- There are ‘function apps’ available to group sets of Azure functions together.
- There are templates for the trigger types making it much easier to get going. For example HTTP trigger, Queue Trigger, Blob trigger, Timer Trigger. You download them for the preferred language and start coding.
Redeploying the Service with Functions
Looking at the original relevant function:
@app.route('/password', methods=['GET']) def password(): lines = open('pwds.txt').read().splitlines() return random.choice(lines) + "\n"
The first challenge is replacing simple read file against local storage with something that reads the bad password possibilities from azure. We don’t really need strong authentication since the data is open source (although thats not the only consideration). We would also like to to be fast, and relatively cheap. We could probably just read the file from the public GitHub repo as well, although that seems slow and a little risky in case it moves.
I’m going to start out with the storage account that gets created when you create an Azure function; I’ll work with it using Azure Storage Explorer. Expand out ‘Blob Containers’ in the storage account that was created for the function and create a new blob container called ‘data’; copy the passwords file to the new blob.
From here i’ll just right click on the new file and choose to create a “Shared Access Signature”.
Then I’ll modify the application to use the url rather than the local text file. I’m just going to use requests for now, leaving aside that there are more efficient and secure techniques available on the azure platform for now - I’ll come back and iterate with them later.
The simplest way to get the application template to use Azure functions is to choose New - Azure Function from the azure section of visual studio code. It’ll ask you which language to use. Then you’ll be able to just paste in the modified function code.
Once i modified the previous example to use the azure storage I end up with an Azure Function that looks like this:
import logging import random import requests import azure.functions as func def main(req: func.HttpRequest) -> func.HttpResponse: logging.info('Python HTTP trigger function processed a request.') source = 'https://passwordfunctionexample.blob.core.windows.net/data/pwds.txt?sv=2019-02-02&st=2020-06-24T13%3A27%3A01Z&se=2030-01-01T16%3A00%3A00Z&sr=b&sp=r&sig=7vQ9lzdataV60EpalaXeRGV6mNtzBOCZDCGWG3mjF1Y%3D' response = requests.get(source) data = response.text lines = data.splitlines() if lines: return func.HttpResponse(random.choice(lines) + "\n") else: return func.HttpResponse( "We've hit a speedbump. Please bear with us.", status_code=400 )
A small note here: Python Azure functions use a requirements.txt the same way you might with a flask project. So to add support for the requests library we add it in the requirements file.
Once we’re ready we can go down to the Azure part of VS code and choose “deploy to function app”
Then, if you’ve forgotten the url you configured for the function app, or you want to see stats about execution, you can see them in the azure portal:
We’re done. We’ve converted a flask website running as an azure application to a self contained function running with Azure functions.