Alibaba Cloud DevOps Cookbook Part 3 — Function Compute with Python 3.0
--
By John Hanley, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud’s incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.
Alibaba Cloud Function Compute is an event driven, serverless computing platform that enables developers to build and deploy their services without the need to manage any infrastructure. It seamlessly handles the resource management, auto scaling, and load balancing so you can focus on your business logic and increase your development velocity. You can also setup various event sources from other Alibaba services to automatically trigger your code to run. The best part is you only pay for the resources your code actually consumes to the nearest 100 milliseconds.
API Gateway is a managed service that makes it easy to publish secure APIs at scale. API Gateway interfaces with a number services such as ECS, Function Compute and web applications to name a few. API Gateway also integrates with DNS services to provide domain-name based APIs.
In today’s article we will be exploring Alibaba Cloud Function Compute for DevOps with some example programs using Python 3. Our ultimate goal is to combine API Gateway, Function Compute, and Direct Mail to provide a contact form suitable for a static website hosted on OSS.
Function Compute Interfaces
There are several methods to run your code in Function Compute. You can use “invoke” your function thru an SDK, via API Gateway or by Triggers. The function definition is different depending on what service will be invoking your function. We will cover two different styles of invocation in this article. The first method by an HTTP trigger and the second method by API Gateway. Note that the function definitions will be for Python. You can read more about Function Entry Definition.
For the HTTP Trigger function definition, we need to know what an HTTP Trigger is. An HTTP Trigger is just a URL that you assign to your function in the Function Compute Console so that your function can be called. The URL will look like this:
https://1234567891234567.ap-southeast-1.fc.aliyuncs.com/2016-08-15/proxy/service_name/function_name/
Function Definition when Called by an HTTP Trigger
def my_handler(environ, start_response):
context = environ['fc.context']
request_uri = environ['fc.request_uri']
for k, v in environ.items():
if k.startswith("HTTP_"):
# process custom request headers
pass # do something here status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return ["Hello World"]
Function Definition when Called by the Invoke API or by API Gateway
def my_handler(event, context):
body = 'hello world'
res = {
'isBase64Encoded': False,
'statusCode': 200,
'headers': {
'content-type' : 'text/plain'
},
'body': body
} return json.dumps(res)
Example Program That Will Return Parameter “environ” in HTML
This example is for a function that is called by an HTTP Trigger (HTTP URL).
Download example program to upload to Function Compute.
View the output that this program generates. Note that some of the data has been masked for security reasons.
############################################################
# Version 1.01
# Date Created: 2018-05-25
# Last Update: 2018-05-29
# https://www.neoprime.io
# Copyright (c) 2018, NeoPrime, LLC
############################################################""" Alibaba Cloud Function Compute Example """
""" This program will return the environment back to the caller as an HTML table """
""" This is useful to learn about the running environment in Function Compute """
""" This code is designed to be called thru HTTP URL via an HTTP Trigger """def handler(environ, start_response):
body = '<!DOCTYPE html>\n<html lang="en"><head>\n'
body = body + '<style>\n'
body = body + 'table, th, td {border: 1px solid black;}\n'
body = body + 'table {border-collapse: collapse;}\n'
body = body + 'th, td {border: 1px solid #ddd; padding 8px;}\n'
body = body + 'th {padding-top: 12px; padding-bottom: 12px;\n'
body = body + 'text-align: left; background-color: #4CAF50;color: white;}\n'
body = body + 'tr:nth-child(even){background-color: #f2f2f2;}\n'
body = body + 'tr:hover {background-color: #ddd;}\n'
body = body + '</style>\n'
body = body + '</head>\n<body><table width="%100%">\n'
body = body + "<thead>\n<tr><th>Name</th><th>Type</th><th>Value</th></tr>\n</thead>\n"
body = body + "<tbody>\n" for k, v in environ.items():
body = body + "<tr>"
body = body + "<td>" + k + "</td>"
body = body + "<td>" + type(v).__name__ + "</td>"
if isinstance(v, bool):
body = body + "<td>" + str(v) + "</td>"
if isinstance(v, str):
body = body + "<td>" + v + "</td>"
if isinstance(v, tuple):
body = body + "<td>" + str(v) + "</td>"
if isinstance(v, type):
body = body + "<td>" + str(v) + "</td>"
body = body + "</tr>\n" body = body + "</tbody>\n</table>\n</body></html>"
status = '200 OK'
response_headers = [('Content-type', 'text/html')]
start_response(status, response_headers)
return [bytes(body, "utf-8")]
Example Program That Will Return Parameter “context” in HTML
This example is for a function that is called by API Gateway.
Download example program to upload to Function Compute.
View the output that this program generates. Note that some of the data has been masked for security reasons.
############################################################
# Version 1.01
# Date Created: 2018-05-25
# Last Update: 2018-05-29
# https://www.neoprime.io
# Copyright (c) 2018, NeoPrime, LLC
############################################################""" Alibaba Cloud Function Compute Example """
""" This program will return the environment back to the caller as an HTML table """
""" This is useful to learn about the running environment in Function Compute """
""" This code is designed to be called thru API Gateway using an HTTP URL """import json# Add a row to the HTML table
def add_row(body, name, value):
""" body - the current HTML body string that we append to """
""" name - the name of the item. Added to the first column """
""" value - the value to add. The type is added to the second column, value to the third """
""" returns body """ # begin a new table row
body = body + '<tr>\n'
body = body + '<td>' + name + '</td>\n'
body = body + '<td>' + type(value).__name__ + '</td>\n' if isinstance(value, str):
# Keep the string length less than 85 characters
v = (value[:85] + ' ...') if len(value) > 85 else value
body = body + '<td>' + v + '</td>\n'
else:
body = body + '<td>' + str(value) + '</td>\n' return body + '</tr>\n'# Add a "dict" item to the table by parsing thru each item in the dictionary
def add_dict(body, name, item):
""" body - the current HTML body string that we append to """
""" name - the name of the item. """
""" item - The item to process """
for k in item:
if isinstance(item[k], dict):
body = add_dict(body, name + "." + k, item[k])
else:
body = add_row(body, name + "." + k, item[k])
return bodydef add_event(body, event):
j = json.loads(event.decode("utf-8"))
return add_dict(body, "event", j)def add_context(body, context):
body = add_row(body, 'context.request_id', context.request_id)
body = add_row(body, 'context.region', context.region)
body = add_row(body, 'context.account_id', context.account_id)
body = add_row(body, 'context.function.handler', context.function.handler)
body = add_row(body, 'context.function.memory', context.function.memory)
body = add_row(body, 'context.function.name', context.function.name)
body = add_row(body, 'context.function.timeout', context.function.timeout)
body = add_row(body, 'context.credentials.accessKeyId', context.credentials.accessKeyId)
body = add_row(body, 'context.credentials.accessKeySecret', context.credentials.accessKeySecret)
body = add_row(body, 'context.credentials.access_key_id', context.credentials.access_key_id)
body = add_row(body, 'context.credentials.access_key_secret', context.credentials.access_key_secret)
body = add_row(body, 'context.credentials.securityToken', context.credentials.securityToken)
body = add_row(body, 'context.credentials.security_token', context.credentials.security_token)
body = add_row(body, 'context.service.log_project', context.service.log_project)
body = add_row(body, 'context.service.log_store', context.service.log_store) return bodydef build_html(body, event, context):
body = '<!DOCTYPE html>\n<html lang="en"><head>\n'
body = body + '<style>\n'
body = body + 'table, th, td {border: 1px solid black;}\n'
body = body + 'table {border-collapse: collapse;}\n'
body = body + 'th, td {border: 1px solid #ddd; padding 8px;}\n'
body = body + 'th {padding-top: 12px; padding-bottom: 12px;\n'
body = body + 'text-align: left; background-color: #4CAF50;color: white;}\n'
body = body + 'tr:nth-child(even){background-color: #f2f2f2;}\n'
body = body + 'tr:hover {background-color: #ddd;}\n'
body = body + '</style>\n'
body = body + '</head>\n<body><table width="100%">\n'
body = body + '<thead>\n<tr><th>Name</th><th width="5%">Type</th><th>Value</th></tr>\n</thead>\n'
body = body + '<tbody>\n' body = add_event(body, event)
body = add_context(body, context) body = body + '</tbody>\n'
body = body + '</table>\n</body></html>' return bodydef handler(event, context):
body = ""
body = build_html(body, event, context) res = {
'isBase64Encoded': False,
'statusCode': 200,
'headers': {
'content-type' : 'text/html'
},
'body': body
} return json.dumps(res)
With the example programs, you will be able to display the function’s environment and any parameters that you pass in the function call (either thru HTTP or API Gateway).
In my next article, we will create code for DirectMail using the REST API with signing. In a following article, we will also integrate an HTML contact form, API Gateway, Function Compute, and DirectMail into a serverless system to provide a contact page for a website. The website can be either a dynamic or a static website on OSS.
Function Compute Access Keys
Let’s discuss a safe and secure method of managing access keys for Function Compute: RAM Roles. Roles allow you to create access keys via a role in the Alibaba Console and assign the role to your Function Compute service. This prevents keys from being required in your source code. The role credentials are made available to your function via the context.credentials parameter.
In the Resource Access Management console, create a role with the desired permissions. Then assign this role to your Function Compute service. Each function located under this service with them have this role assigned.
Alibaba Documentation
Function Compute:
Alibaba Function Compute Product Page
Alibaba Function Compute Documentation
Alibaba Function Compute Triggers
Alibaba Function Entry Definition
API Gateway:
Alibaba API Gateway Product Page
Alibaba API Gateway Documentation
Installing API Gateway SSL Certificates
Reference: