Deploying an HTTP Function container Image using Terraform¶
This section describes on how to deploy an HTTP Function packed in a container image using Terraform.
Prerequisite¶
Terraform configured according to Prepare the Terraform environment
Image created as described in Creating an HTTP Function Using a Container Image Built with Go
Exiting API Gateway instance to create the trigger for the HTTP Function. see section variables.tfvars below.
Full sample can be found in samples-doc/container-http.
Terraform Scripts¶
Terraform deployment scripts can be found in: samples-doc/container-http/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 = "your_tag_app_group_here"
}
variable "API_GATEWAY_INSTANCE_ID" {
type = string
default = "your_api_gateway_instance_id"
}
variables.tfvars¶
This file provides values for the variables defined in variables.tf.
function_name = "go-doc-sample-container-http"
prefix = "go"
tag_app_group = "go-doc-sample-container-http"
# change to your API Gateway instance ID
# set as env var TF_VAR_API_GATEWAY_INSTANCE_ID or uncomment and set here
#API_GATEWAY_INSTANCE_ID="YOUR_API_GATEWAY_INSTANCE_ID"
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 HTTP 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 = "http"
custom_image {
url = var.image_url
}
description = "Sample on how use container with go and http"
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
}
}
In the function.tf script, the relevant part to create the HTTP Function using a custom container image is as follows:
handler = "-"
code_type = "Custom-Image-Swr"
runtime = "http"
custom_image {
url = var.image_url
}
were var.image_url is the address of the container image in SWR. in the format:
swr.<REGION>.otc.t-systems.com/<SWR-ORGANIZATION>/<IMAGE_NAME>:<TAG>
api_trigger.tf¶
This script creates an API Gateway trigger and all relevant resources to invoke the HTTP Function:
API gateway group (opentelekomcloud_apigw_group_v2)
API resource (opentelekomcloud_apigw_api_v2) that connects this API to the FunctionGraph function
publish API using (opentelekomcloud_apigw_api_publishment_v2)
locals {
API_GATEWAY_INSTANCE_ID = var.API_GATEWAY_INSTANCE_ID
ENV_NAME = "RELEASE"
ENV_ID = "DEFAULT_ENVIRONMENT_RELEASE_ID"
}
##########################################################
# opentelekomcloud_apigw_group_v2.group
##########################################################
resource "opentelekomcloud_apigw_group_v2" "group1" {
# depends_on = [ opentelekomcloud_fgs_function_v2.MyFunction ]
name = replace(format("%s_%s_api_group", var.prefix, var.function_name), "-", "_")
instance_id = local.API_GATEWAY_INSTANCE_ID
description = format("API Group for %s, %s", var.prefix, var.function_name)
}
##########################################################
# opentelekomcloud_apigw_api_v2.api1
# This is used to create the API Gateway trigger for the
# FunctionGraph function.
##########################################################
resource "opentelekomcloud_apigw_api_v2" "api1" {
# TRIGGER-INSTANCE_id
gateway_id = local.API_GATEWAY_INSTANCE_ID
# TRIGGER-GROUP_id
group_id = opentelekomcloud_apigw_group_v2.group1.id
# TRIGGER-Name
name = replace(format("%s_%s_apig_trigger", var.prefix, var.function_name), "-", "_")
# TRIGGER-TYPE:1
type = "Public"
# TRIGGER-PROTOCOL: HTTPS
request_protocol = "HTTPS"
# TRIGGER-REG_METHOD: HTTPS
request_method = "ANY"
# TRIGGER-PATH
request_uri = "/"
# TRIGGER-AUTH: NONE
security_authentication_type = "NONE"
# TRIGGER-MATCH_MODE: SWA
match_mode = "PREFIX"
success_response = "Success response"
failure_response = "Failed response"
description = format("Created by script for %s-%s", var.prefix, var.function_name)
func_graph {
function_urn = opentelekomcloud_fgs_function_v2.MyFunction.urn
version = "latest"
timeout = 5000
invocation_type = "sync"
network_type = "NON-VPC"
}
}
##########################################################
# Publish API to specific environment
##########################################################
resource "opentelekomcloud_apigw_api_publishment_v2" "default" {
gateway_id = local.API_GATEWAY_INSTANCE_ID
environment_id = local.ENV_ID
api_id = opentelekomcloud_apigw_api_v2.api1.id
version_id = opentelekomcloud_apigw_api_v2.api1.version
}
output "API_GATEWAY_TRIGGER_URL" {
description = "The URL of the API Gateway triggering the FunctionGraph function"
value = format("https://%s.apic.%s.otc.t-systems.com",
opentelekomcloud_apigw_group_v2.group1.id ,
opentelekomcloud_apigw_group_v2.group1.region)
}
Note
To have full control over resources being created this sample does not use opentelekomcloud_fgs_trigger_v2 for APIG Trigger creation,
testevent.tf¶
This script creates a test event to test the HTTP Function.
##########################################################
# Create Test Event
##########################################################
resource "opentelekomcloud_fgs_event_v2" "test_event" {
function_urn = opentelekomcloud_fgs_function_v2.MyFunction.urn
name = "TestEvent"
content = filebase64("../resources/apig_post_index.json")
}
Deployment¶
MakefileTF¶
To simplify the development and testing process, see MakefileTF in the container-http folder:
# Makefile for Terraform deployment of the Container HTTP 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-http.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:
# get the API Gateway URL from terraform output
$(eval API_GATEWAY_TRIGGER_URL := $(shell terraform -chdir=terraform output -raw API_GATEWAY_TRIGGER_URL))
@echo "Using API Gateway URL: $(API_GATEWAY_TRIGGER_URL)"
# execute a curl request against the deployed function via API Gateway
curl -X POST -H 'Content-Type: application/json' -d @./resources/apig_post_index.json $(API_GATEWAY_TRIGGER_URL)/index
.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-http folder:
make -f MakefileTF tf_init
Plan Terraform deployment¶
To plan the Terraform deployment, run following command in the container-http folder:
make -f MakefileTF tf_plan
Deploy using Terraform¶
To deploy the HTTP Function using Terraform, run following command in the container-http folder:
make -f MakefileTF tf_apply
Test deployed Function¶
To test the deployed HTTP Function using the API Gateway trigger, run following command in the container-http folder:
make -f MakefileTF test_deployed
Cleanup deployed resources¶
Note
To destroy the deployed resources, run following command in the container-http folder:
make -f MakefileTF tf_destroy