Deploying an Event Function container Image using Terraform¶
This section describes on how to deploy an Event Function packed in a container image using Terraform.
Prerequisite¶
Terraform configured according to Prepare the Terraform environment
Image created as described in Creating an Event Function Using a Container Image Built with Go
Full sample can be found in samples-doc/container-event.
Terraform Scripts¶
Terraform deployment scripts can be found in: samples-doc/container-event/terraform
provider.tf¶
This script configures the OpenTelekomCloud provider for Terraform.
# ----------------------------------------------------------------------------
# Secret variables to be injected as envvar (capital letters for Windows systems)
# - no defaults
# - Declared as sensitive --> Not printed in console or log if used in resources
# ----------------------------------------------------------------------------
# set by environment variable TF_VAR_OTC_SDK_AK
variable "OTC_SDK_AK" {
description = "Personal access key"
type = string
sensitive = true
}
# set by environment variable TF_VAR_OTC_SDK_SK
variable "OTC_SDK_SK" {
description = "Personal secret key"
type = string
sensitive = true
}
# set by environment variable TF_VAR_OTC_SDK_DOMAIN_NAME
variable "OTC_SDK_DOMAIN_NAME" {
description = "Domain Name, eg. OTC-EU-DE-000000000010000XXXXX"
type = string
}
# set by environment variable TF_VAR_OTC_SDK_PROJECTID
variable "OTC_SDK_PROJECTID" {
description = "Project Id"
type = string
}
# set by environment variable TF_VAR_OTC_SDK_PROJECTNAME
variable "OTC_SDK_PROJECTNAME" {
description = "Project Name, eg. eu-de_MYPROJECT"
type = string
}
# set by environment variable TF_VAR_OTC_IAM_ENDPOINT
variable "OTC_IAM_ENDPOINT" {
description = "IAM Endpoint"
type = string
default = "https://iam.eu-de.otc.t-systems.com/v3"
}
terraform {
required_providers {
# specifies required provider, source and version
# see https://registry.terraform.io/providers/opentelekomcloud/opentelekomcloud/latest
opentelekomcloud = {
source = "opentelekomcloud/opentelekomcloud"
version = ">= 1.36.57"
}
}
backend "s3" {
# See: https://registry.terraform.io/providers/opentelekomcloud/opentelekomcloud/latest/docs/guides/backends
# (Required) Specifies the endpoint for OpenTelekomCloud OBS.
# The value is https://obs.{{region}}.otc.t-systems.com.
# This can also be sourced from the AWS_S3_ENDPOINT environment variable
endpoints = {
s3 = "https://obs.eu-de.otc.t-systems.com"
}
# (Required) Specifies the bucket name where to store the state.
# Make sure to create it before.
bucket = "<your-bucket-name>"
# (Required) Specifies the path to the state file inside the bucket.
key = "<path/to/your/terraform.tfstate>"
# (Required) Specifies the region where the bucket is located.
# This can also be sourced from the AWS_DEFAULT_REGION and
# AWS_REGION environment variables.
region = "<your-region>"
# (Required) Skip credentials validation via the STS API.
# It's mandatory for OpenTelekomCloud.
skip_credentials_validation = true
# (Required) Skip validation of provided region name.
# It's mandatory for OpenTelekomCloud.
skip_region_validation = true
skip_requesting_account_id = true
# (Required) Skip usage of EC2 Metadata API.
# It's mandatory for OpenTelekomCloud.
skip_metadata_api_check = true
# (Optional) Do not include checksum when uploading S3 Objects.
# Useful for some S3-Compatible APIs.
skip_s3_checksum = true
# Although the terraform block does not accept variables or locals and
# all backend configuration values must be hardcoded, you can provide
# the credentials via the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
# environment variables to access OBS, respectively:
#
# export AWS_ACCESS_KEY_ID="your accesskey"
# export AWS_SECRET_ACCESS_KEY="your secretkey"
#
# secret_key set env var: AWS_ACCESS_KEY_ID
# access_key set env var: AWS_SECRET_ACCESS_KEY
}
}
# ----------------------------------------------------------------------------
# Providers settings --> OTC
# We use the AKSK auth scheme
# See https://registry.terraform.io/providers/opentelekomcloud/opentelekomcloud/latest/docs
# ----------------------------------------------------------------------------
#
provider "opentelekomcloud" {
auth_url = var.OTC_IAM_ENDPOINT
access_key = var.OTC_SDK_AK
secret_key = var.OTC_SDK_SK
domain_name = var.OTC_SDK_DOMAIN_NAME
tenant_name = var.OTC_SDK_PROJECTNAME
}
variables.tf¶
This script defines the variables used in the Terraform scripts.
# prefix will be prepended to all resource names
variable "prefix" {
type = string
default = "sample"
}
# FunctionGraph: Function name
variable "function_name" {
type = string
default = "function_name"
}
variable "image_url" {
type = string
default = "your_image_url_here"
}
# Resource tag:
variable "tag_app_group" {
type = string
default = "go-doc-sample-container-event"
}
variables.tfvars¶
This file provides values for the variables defined in variables.tf.
function_name = "go-doc-sample-container-event"
prefix = "go"
tag_app_group = "go-doc-sample-container-event"
agency.tf¶
This script creates an agency with required permissions to allow FunctionGraph to pull images from SWR.
##########################################################
# Agency for FunctionGraph
# Attention: Creating agency will take some time.
# Calls to function after creating agency will fail until
# agency is set up.
##########################################################
resource "opentelekomcloud_identity_agency_v3" "agency" {
delegated_domain_name = "op_svc_cff"
name = format("%s-%s-agency", var.prefix, var.function_name)
description = "Agency for FunctionGraph to access SWR"
project_role {
all_projects = true
roles = [
"SWR Administrator",
]
}
}
loggroup.tf¶
This script creates a log group and log stream in LTS.
##########################################################
# Create Log Group
##########################################################
resource "opentelekomcloud_lts_group_v2" "MyLogGroup" {
group_name = format("%s_%s_%s", var.prefix, var.function_name, "log_group")
ttl_in_days = 1
tags = {
"app_group" = var.tag_app_group
}
}
##########################################################
# Create Log Stream
##########################################################
resource "opentelekomcloud_lts_stream_v2" "MyLogStream" {
group_id = opentelekomcloud_lts_group_v2.MyLogGroup.id
stream_name = format("%s_%s_%s", var.prefix, var.function_name, "log_stream")
tags = {
"app_group" = var.tag_app_group
}
}
function.tf¶
This script creates the Event Function using the container image.
##########################################################
# Create event function using container image
##########################################################
resource "opentelekomcloud_fgs_function_v2" "MyFunction" {
name = format("%s_%s", var.prefix, var.function_name)
app = "default"
agency = opentelekomcloud_identity_agency_v3.agency.name
handler = "-"
code_type = "Custom-Image-Swr"
runtime = "Custom Image"
custom_image {
url = var.image_url
}
description = "Sample on how use container with go"
memory_size = 512
timeout = 30
max_instance_num = 1
# if you need security access key, security secret key and security token
# to access other OTC services, set enable_auth_in_header to true
enable_auth_in_header = false
log_group_id = opentelekomcloud_lts_group_v2.MyLogGroup.id
log_group_name = opentelekomcloud_lts_group_v2.MyLogGroup.group_name
log_topic_id = opentelekomcloud_lts_stream_v2.MyLogStream.id
log_topic_name = opentelekomcloud_lts_stream_v2.MyLogStream.stream_name
# set some environment variables
user_data = jsonencode({
"RUNTIME_LOG_LEVEL" : "DEBUG",
})
tags = {
"app_group" = var.tag_app_group
}
}
testevent.tf¶
This script creates a test event to test the Event Function.
##########################################################
# Create Test Event
##########################################################
resource "opentelekomcloud_fgs_event_v2" "test_event" {
function_urn = opentelekomcloud_fgs_function_v2.MyFunction.urn
name = "TestEvent"
content = base64encode(jsonencode({
"key" = "Hello World of FunctionGraph!"
}))
}
Deployment¶
MakefileTF¶
To simplify the development and testing process, see MakefileTF in the container-event folder:
# Makefile for Terraform deployment of the Container Event Function sample
# Include Makefile for build and docker tasks
include ./Makefile
# Terraform backend configuration
BACKEND_CONFIG_BUCKET := "doc-samples-tf-backend"
BACKEND_CONFIG_KEY := "terraform_state/go/go-container-sample.tf"
BACKEND_CONFIG_REGION := "eu-de"
BACKEND_CONFIG_ENDPOINTS := "endpoints={s3=\"https://obs.eu-de.otc.t-systems.com\"}"
CURRENT_MAKEFILE := $(firstword $(MAKEFILE_LIST))
tf_init:
terraform -chdir=terraform \
init \
-backend-config=$(BACKEND_CONFIG_ENDPOINTS) \
-backend-config="bucket=$(BACKEND_CONFIG_BUCKET)" \
-backend-config="key=$(BACKEND_CONFIG_KEY)" \
-backend-config="region=$(BACKEND_CONFIG_REGION)"
tf_plan:
if [ ! -f "terraform/.terraform.lock.hcl" ]; then \
$(MAKE) -f $(CURRENT_MAKEFILE) initTerraform; \
fi
terraform -chdir=terraform \
plan \
-var-file="variables.tfvars" \
-var="image_url=$(OTC_SWR_ENDPOINT)/$(OTC_SWR_ORGANIZATION)/$(IMAGE_NAME):latest"
tf_apply: docker_push
if [ ! -f "terraform/.terraform.lock.hcl" ]; then \
$(MAKE) -f $(CURRENT_MAKEFILE) initTerraform; \
fi
terraform -chdir=terraform \
apply -auto-approve \
-var-file="variables.tfvars" \
-var="image_url=$(OTC_SWR_ENDPOINT)/$(OTC_SWR_ORGANIZATION)/$(IMAGE_NAME):latest"
tf_destroy:
terraform -chdir=terraform \
destroy -auto-approve \
-var-file="variables.tfvars" \
-var="image_url=$(OTC_SWR_ENDPOINT)/$(OTC_SWR_ORGANIZATION)/$(IMAGE_NAME):latest"
test_deployed:
# getting Token for authentication from Username/Password...
$(eval OTC_X_AUTH_TOKEN := $(shell ../../utils/tokenFromUsername.sh))
# getting the Function URN from terraform output...
$(eval MY_FUNCTION_URN := $(shell terraform -chdir=terraform output -raw MY_FUNCTION_URN))
# calling the deployed function via FunctionGraph API...
@curl -X POST \
-H "Content-Type: application/json" \
-H "x-auth-token: $(OTC_X_AUTH_TOKEN)" \
-d '{"key":"Hello World of FunctionGraph"}' \
https://functiongraph.$(OTC_SDK_REGION).otc.t-systems.com/v2/$(OTC_SDK_PROJECTID)/fgs/functions/$(MY_FUNCTION_URN):latest/invocations
@echo ""
# finished
.PHONY: tf_init tf_plan tf_apply tf_destroy test_deployed
This MakefileTF imports all targets from the build Makefile and provides additional targets for Terraform deployment.
Initialize Terraform¶
To initialize Terraform, run following command in the container-event folder:
make -f MakefileTF tf_init
Plan Terraform deployment¶
To plan the Terraform deployment, run following command in the container-event folder:
make -f MakefileTF tf_plan
Deploy using Terraform¶
To deploy the Event Function using Terraform, run following command in the container-event folder:
make -f MakefileTF tf_apply
Test deployed Function¶
To test the deployed Event Function using the Invokation API, run following command in the container-event folder:
make -f MakefileTF test_deployed
This target makes use of the script tokenFromUsername.sh to obtain an authentication token using username and password for the API call.
#!/bin/bash
# Script to get an authentication token
# from OTC IAM using username and password
# to be passed as x-auth-token header in API requests.
# Script outputs the token to
# - stdout
# - and to the environment variable OTC_X_AUTH_TOKEN (if called using current shell "source ...")
# see: https://docs.otc.t-systems.com/identity-access-management/api-ref/calling_apis/authentication.html#iam-02-0510
# see: https://docs.otc.t-systems.com/identity-access-management/api-ref/apis/token_management/obtaining_a_user_token_through_password_authentication.html
# Following environment variables must be set:
# OTC_USER_NAME
# OTC_USER_PASSWORD
# OTC_DOMAIN_NAME
# OTC_SDK_PROJECTNAME
# OTC_SDK_PROJECTID
# OTC_IAM_ENDPOINT e.g. https://iam.eu-de.otc.t-systems.com/v3
# If DEBUG is not set in the environment, it defaults to 0 (off)
DEBUG=${DEBUG:-0}
payload=$(cat <<EOF
{
"auth": {
"identity": {
"methods": [
"password"
],
"password": {
"user": {
"name": "${OTC_USER_NAME}",
"password": "${OTC_USER_PASSWORD}",
"domain": { "name": "${OTC_DOMAIN_NAME}" }
}
}
},
"scope": {
"project": {
"id": "${OTC_SDK_PROJECTID}",
"domain": { "name": "${OTC_DOMAIN_NAME}" }
}
}
}
}
EOF
)
if [ "$DEBUG" -eq 1 ]; then
# for debugging, print the payload to stderr
echo "################# Payload for token request: #################" >&2
echo ${payload} >&2
echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" >&2
fi
# Make the API call
# and extract the X-Subject-Token from the response headers
token=$(curl -i -s \
-H 'Content-Type: application/json' \
-d "${payload}" \
-o /dev/null \
--dump-header /dev/stdout \
${OTC_IAM_ENDPOINT}/auth/tokens?nocatalog=true \
| grep -i ^X-Subject-Token: | cut -d' ' -f2)
if [ "$DEBUG" -eq 1 ]; then
# for debugging, print the token to stderr
echo "################# Token #################" >&2
echo "${token}" >&2
echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" >&2
fi
# export the token to environment variable OTC_X_AUTH_TOKEN
export OTC_X_AUTH_TOKEN=${token}
# print the token to stdout
echo ${token}
This file needs execution permissions, e.g. set using:
chmod +x tokenFromUsername.sh
Cleanup deployed resources¶
Note
To destroy the deployed resources, run following command in the container-event folder:
make -f MakefileTF tf_destroy