Skip to content
/ tf.yc Public

Terraform module for a Russian CSP's functions

License

Notifications You must be signed in to change notification settings

zaboal/tf.yc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cloud Function Terraform Module for Yandex.Cloud

Features

  • Create cloud function with lockbox secret, list of scaling policies and specific trigger type.
  • Integration with VPC can be added to cloud function.
  • Options for creating service account and/or logging group for the function.
  • Mounting the bucket for cloud function.

Cloud Function Definition

First, you need to define parameter zip_filename for the Cloud Function.

Notes:

  • you can use existing service_account_id or create new SA with bindings
  • you can use existing log_group_id or create new loggging group
  • lockbox secret is used by default for the function
  • you should use environment variables or tfvars-files to redefine lockbox_secret_key and lockbox_secret_value
  • you should create NAT gateway first, if you'd like to try Cloud Function's VPC integration. Variable network_id should be not null
  • you can mount S3 bucket to the function. Variable mount_bucket and section storage_mounts should be defined
  • you can use asynchronous invocation to message queue for the Cloud Function. Variable use_async_invocation and ymq_success_target, ymq_failure_target must be defined.
resource "yandex_function" "yc_function" {
  name               = coalesce(var.yc_function_name, "yc-function-example-${random_string.unique_id.result}")
  description        = coalesce(var.yc_function_description, "Cloud function from tf-module terraform-yc-function with scaling policy and specific trigger type yc-function-trigger.")
  user_hash          = var.user_hash
  runtime            = var.runtime
  entrypoint         = var.entrypoint
  memory             = var.memory
  execution_timeout  = var.execution_timeout
  service_account_id = local.create_service_account ? var.existing_service_account_id : yandex_iam_service_account.default_cloud_function_sa[0].id
  tags               = var.tags
  environment        = var.environment

  content {
    zip_filename = var.zip_filename
  }

  log_options {
    log_group_id = coalesce(var.existing_log_group_id, try(yandex_logging_group.default_log_group[0].id, ""))
    min_level    = var.min_level
  }

  dynamic "storage_mounts" {
    for_each = var.mount_bucket != true ? [] : tolist(1)
    content {
      mount_point_name = var.storage_mounts.mount_point_name
      bucket           = var.storage_mounts.bucket
      prefix           = var.storage_mounts.prefix
      read_only        = var.storage_mounts.read_only
    }
  }
  connectivity {
    network_id = var.network_id != null ? var.network_id : ""
  }

  secrets {
    id                   = yandex_lockbox_secret.yc_secret.id
    version_id           = yandex_lockbox_secret_version.yc_version.id
    key                  = var.lockbox_secret_key
    environment_variable = var.environment_variable
  }

  dynamic "async_invocation" {
    for_each = var.use_async_invocation != true ? [] : tolist(1)
    content {
      retries_count      = var.retries_count
      service_account_id = local.create_service_account ? var.existing_service_account_id : yandex_iam_service_account.default_cloud_function_sa[0].id
      ymq_failure_target {
        service_account_id = local.create_service_account ? var.existing_service_account_id : yandex_iam_service_account.default_cloud_function_sa[0].id
        arn                = var.ymq_failure_target
      }
      ymq_success_target {
        service_account_id = local.create_service_account ? var.existing_service_account_id : yandex_iam_service_account.default_cloud_function_sa[0].id
        arn                = var.ymq_success_target
      }
    }
  }

  depends_on = [
    yandex_resourcemanager_folder_iam_binding.editor,
    yandex_resourcemanager_folder_iam_binding.invoker,
    yandex_resourcemanager_folder_iam_binding.lockbox_payload_viewer,
    time_sleep.wait_for_iam
  ]
}

Cloud Function Scaling Policy Definition

Define the policy tag, zone_instances_limit and zone_requests_limit.

resource "yandex_function_scaling_policy" "yc_scaling_policy" {
  function_id = yandex_function.yc_function.id

  dynamic "policy" {
    for_each = var.scaling_policy
    content {
      tag                  = policy.value.tag
      zone_instances_limit = policy.value.zone_instances_limit
      zone_requests_limit  = policy.value.zone_requests_limit
    }
  }
}

Cloud Function Trigger Definition

Define parameter choosing_trigger_type to choose one of the trigger types:

  • logging
  • timer
  • object_storage
  • message_queue

Only one option is acceptable.

choosing_trigger_type can not have other options because of the validation condition.

Notes:

  • you can use existing service_account_id or create new SA with bindings
  • it's possible to change default values in variables for different trigger types
  • you can optionally create trigger for Cloud Function using variable create_trigger
resource "yandex_function_trigger" "yc_trigger" {
  count       = var.create_trigger ? 1 : 0
  name        = "yc-function-trigger-${random_string.unique_id.result}"
  description = "Specific cloud function trigger type yc-function-trigger for cloud function yc-function-example."

  dynamic "logging" {
    for_each = var.choosing_trigger_type == "logging" ? [yandex_function.yc_function.id] : []
    content {
      group_id       = var.logging.group_id
      resource_types = var.logging.resource_types
      levels         = var.logging.levels
      batch_cutoff   = var.logging.batch_cutoff
      batch_size     = var.logging.batch_size
    }
  }

  dynamic "timer" {
    for_each = var.choosing_trigger_type == "timer" ? [yandex_function.yc_function.id] : []
    content {
      cron_expression = var.timer.cron_expression
    }
  }

  dynamic "object_storage" {
    for_each = var.choosing_trigger_type == "object_storage" ? [yandex_function.yc_function.id] : []
    content {
      bucket_id    = var.object_storage.bucket_id
      create       = var.object_storage.create
      update       = var.object_storage.update
      delete       = var.object_storage.delete
      batch_cutoff = var.object_storage.batch_cutoff
      batch_size   = var.object_storage.batch_size
    }
  }

  dynamic "message_queue" {
    for_each = var.choosing_trigger_type == "message_queue" ? [yandex_function.yc_function.id] : []
    content {
      queue_id           = var.message_queue.queue_id
      service_account_id = local.create_service_account ? var.existing_service_account_id : yandex_iam_service_account.default_cloud_function_sa[0].id
      batch_cutoff       = var.message_queue.batch_cutoff
      batch_size         = var.message_queue.batch_size
      visibility_timeout = var.message_queue.visibility_timeout
    }
  }

  function {
    id                 = yandex_function.yc_function.id
    service_account_id = local.create_service_account ? var.existing_service_account_id : yandex_iam_service_account.default_cloud_function_sa[0].id
  }

  depends_on = [
    yandex_resourcemanager_folder_iam_binding.editor,
    yandex_resourcemanager_folder_iam_binding.invoker,
    yandex_resourcemanager_folder_iam_binding.lockbox_payload_viewer,
    time_sleep.wait_for_iam
  ]
}

Example Usage

module "cloud_function" {
  source = "../../"

  # Cloud Function Definition
  lockbox_secret_key   = var.lockbox_secret_key
  lockbox_secret_value = var.lockbox_secret_value

  zip_filename = "../../handler.zip"

  # storage_mounts = {
  #   mount_point_name = "yc-function"
  #   bucket           = "yandex-cloud-nnn"
  # }

  # Cloud Function Scaling Policy Definition
  scaling_policy = [{
    tag                  = "yc_tag"
    zone_instances_limit = 20
    zone_requests_limit  = 20
  }]

  # Cloud Function Trigger Definition
  choosing_trigger_type = "" # "logging"

  logging = {
    group_id     = "e23moaejmq8m74tssfu9"
    batch_cutoff = 1
    batch_size   = 1
  }

  # timer = {}

  # object_storage = {
  #   bucket_id    = "yandex-cloud-nnn"
  #   batch_cutoff = 1
  #   batch_size   = 1
  # }

  # message_queue = {
  #   queue_id     = "yrn:yc:ymq:ru-central1:b1gfl7u3a9ahaamt3ore:anana"
  #   batch_cutoff = 1
  #   batch_size   = 1
  # }
}

Configure Terraform for Yandex Cloud

  • Install YC CLI
  • Add environment variables for terraform authentication in Yandex Cloud
export YC_TOKEN=$(yc iam create-token)
export YC_CLOUD_ID=$(yc config get cloud-id)
export YC_FOLDER_ID=$(yc config get folder-id)
export TF_VAR_lockbox_secret_key=<yc-key>
export TF_VAR_lockbox_secret_value=<yc-value>

Requirements

Name Version
terraform >= 1.0.0
random > 3.3
time > 0.9
yandex >= 0.107.0

Providers

Name Version
random 3.6.2
time 0.11.2
yandex 0.123.0

Modules

No modules.

Resources

Name Type
random_string.unique_id resource
time_sleep.wait_for_iam resource
yandex_function.yc_function resource
yandex_function_iam_binding.function_iam resource
yandex_function_scaling_policy.yc_scaling_policy resource
yandex_function_trigger.yc_trigger resource
yandex_iam_service_account.default_cloud_function_sa resource
yandex_lockbox_secret.yc_secret resource
yandex_lockbox_secret_version.yc_version resource
yandex_logging_group.default_log_group resource
yandex_resourcemanager_folder_iam_binding.editor resource
yandex_resourcemanager_folder_iam_binding.invoker resource
yandex_resourcemanager_folder_iam_binding.lockbox_payload_viewer resource
yandex_client_config.client data source

Inputs

Name Description Type Default Required
choosing_trigger_type Choosing type for cloud function trigger. string n/a yes
create_trigger Create trigger for Cloud Function (true) or not (false).
If true parameter choosing_trigger_type must not be empty string.
If false trigger yc_trigger will not be created for Cloud Function.
bool false no
entrypoint Entrypoint for cloud function yc-function-example. string "handler.sh" no
environment A set of key/value environment variables for Yandex Cloud Function from tf-module map(string)
{
"name": "John",
"surname": "Wick"
}
no
environment_variable Function's environment variable in which secret's value will be stored. string "ENV_VARIABLE" no
execution_timeout Execution timeout in seconds for cloud function yc-function-example. number 10 no
existing_log_group_id Existing logging group id. string null no
existing_service_account_id Existing IAM service account id. string null no
existing_service_account_name Existing IAM service account name. string null no
folder_id The ID of the folder that the cloud function yc-function-example belongs to. string null no
lockbox_secret_key Lockbox secret key for cloud function yc-function-example. string n/a yes
lockbox_secret_value Lockbox secret value for cloud function yc-function-example. string n/a yes
logging Trigger type of logging.
object({
group_id = string
resource_ids = optional(list(string))
resource_types = optional(list(string), ["serverless.function"])
levels = optional(list(string), ["INFO"])
batch_cutoff = number
batch_size = number
stream_names = optional(list(string))
})
{
"batch_cutoff": 1,
"batch_size": 1,
"group_id": null
}
no
memory Memory in megabytes for cloud function yc-function-example. number 128 no
message_queue Trigger type of message queue.
object({
queue_id = string
service_account_id = optional(string)
batch_cutoff = number
batch_size = number
visibility_timeout = optional(number, 600)
})
{
"batch_cutoff": 1,
"batch_size": 1,
"queue_id": null,
"service_account_id": null
}
no
min_level Minimal level of logging for cloud function yc-function-example. string "ERROR" no
mount_bucket Mount bucket (true) or not (false). If true section storage_mounts{} should be defined. bool false no
network_id Cloud function's network id for VPC integration. string null no
object_storage Trigger type of object storage.
object({
bucket_id = string
prefix = optional(string)
suffix = optional(string)
create = optional(bool, true)
update = optional(bool, true)
delete = optional(bool, true)
batch_cutoff = number
batch_size = number
})
{
"batch_cutoff": 1,
"batch_size": 1,
"bucket_id": null
}
no
public_access Making cloud function public (true) or not (false). bool false no
retries_count Maximum number of retries for async invocation. number 3 no
runtime Runtime for cloud function yc-function-example. string "bash-2204" no
scaling_policy List of scaling policies for cloud function yc-function-example.
list(object({
tag = string
zone_instances_limit = number
zone_requests_limit = number
}))
n/a yes
storage_mounts Mounting s3 bucket.
object({
mount_point_name = string
bucket = string
prefix = optional(string)
read_only = optional(bool, true)
})
{
"bucket": null,
"mount_point_name": "yc-function"
}
no
tags List of tags for cloud function yc-function-example. list(string)
[
"yc_tag"
]
no
timer Trigger type of timer.
object({
cron_expression = optional(string, "*/30 * ? * * *")
payload = optional(string)
})
{
"cron_expression": "*/5 * ? * * *",
"payload": null
}
no
use_async_invocation Use asynchronous invocation to message queue (true) or not (false). If true, parameters ymq_success_target and ymq_failure_target must be set. bool false no
use_existing_log_group Use existing logging group (true) or not (false).
If true parameters existing_log_group_id must be set.
bool false no
use_existing_sa Use existing service accounts (true) or not (false).
If true parameters existing_service_account_id must be set.
bool false no
user_hash User-defined string for current function version.
User must change this string any times when function changed.
Function will be updated when hash is changed."
string "yc-defined-string-for-tf-module" no
yc_function_description Custom Cloud Function description from tf-module string "yc-custom-function-description" no
yc_function_name Custom Cloud Function name from tf-module string "yc-custom-function-name" no
ymq_failure_target Target for unsuccessful async invocation. string null no
ymq_success_target Target for successful async invocation. string null no
zip_filename Filename to zip archive for the version of cloud function's code. string "../../handler.zip" no

Outputs

Name Description
function_id Yandex cloud function ID.
function_name Yandex cloud function name.