Skip to content

Commit

Permalink
add experimental scheduled cloud function module
Browse files Browse the repository at this point in the history
  • Loading branch information
ludoo committed Mar 22, 2020
1 parent 9f70c96 commit dc22224
Show file tree
Hide file tree
Showing 8 changed files with 312 additions and 178 deletions.
42 changes: 42 additions & 0 deletions modules/__experimental/cloud-function-scheduled/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Scheduled Google Cloud Function Module

This module manages a background Cloud Function scheduled via a recurring Cloud Scheduler job. It also manages the required dependencies: a service account for the cloud function with optional IAM bindings, the PubSub topic used for the function trigger, and optionally the GCS bucket used for the code bundle.

## Example

```hcl
module "function" {
source = "./modules/cloud-function-scheduled"
project_id = "myproject"
name = "myfunction"
bundle_config = {
source_dir = "../cf"
output_path = "../bundle.zip"
}
}
```

<!-- BEGIN TFDOC -->
## Variables

| name | description | type | required | default |
|---|---|:---: |:---:|:---:|
| bundle_config | Cloud function code bundle configuration, output path is a zip file. | <code title="object&#40;&#123;&#10;source_dir &#61; string&#10;output_path &#61; string&#10;&#125;&#41;">object({...})</code> || |
| name | Name used for resources (schedule, topic, etc.). | <code title="">string</code> || |
| project_id | Project id used for all resources. | <code title="">string</code> || |
| *bucket_name* | Name of the bucket that will be used for the function code, leave null to create one. | <code title="">string</code> | | <code title="">null</code> |
| *function_config* | Cloud function configuration. | <code title="object&#40;&#123;&#10;entry_point &#61; string&#10;instances &#61; number&#10;memory &#61; number&#10;runtime &#61; string&#10;timeout &#61; number&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;entry_point &#61; &#34;main&#34;&#10;instances &#61; 1&#10;memory &#61; 256&#10;runtime &#61; &#34;python37&#34;&#10;timeout &#61; 180&#10;&#125;">...</code> |
| *prefixes* | Optional prefixes for resource ids, null prefixes will be ignored. | <code title="object&#40;&#123;&#10;bucket &#61; string&#10;function &#61; string&#10;job &#61; string&#10;service_account &#61; string&#10;topic &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="">null</code> |
| *region* | Region used for all resources. | <code title="">string</code> | | <code title="">us-central1</code> |
| *schedule_config* | Cloud function scheduler job configuration, leave data null to pass the name variable. | <code title="object&#40;&#123;&#10;pubsub_data &#61; string&#10;schedule &#61; string&#10;time_zone &#61; string&#10;&#125;&#41;">object({...})</code> | | <code title="&#123;&#10;schedule &#61; &#34;&#42;&#47;10 &#42; &#42; &#42; &#42;&#34;&#10;pubsub_data &#61; null&#10;time_zone &#61; &#34;UTC&#34;&#10;&#125;">...</code> |
| *service_account_iam_roles* | IAM roles assigned to the service account at the project level. | <code title="list&#40;string&#41;">list(string)</code> | | <code title="">[]</code> |

## Outputs

| name | description | sensitive |
|---|---|:---:|
| bucket_name | Bucket name. | |
| function_name | Cloud function name. | |
| service_account_email | Service account email. | |
| topic_id | PubSub topic id. | |
<!-- END TFDOC -->
132 changes: 132 additions & 0 deletions modules/__experimental/cloud-function-scheduled/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/**
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

locals {
bucket = (
var.bucket_name != null
? var.bucket_name
: google_storage_bucket.bucket[0].name
)
job_data = (
var.schedule_config.pubsub_data == null || var.schedule_config.pubsub_data == ""
? var.name
: var.schedule_config.pubsub_data
)
prefixes = (
var.prefixes == null
? {}
: {
for k, v in var.prefixes :
k => v != null && v != "" ? "${v}-${var.name}" : var.name
}
)
service_account = "serviceAccount:${google_service_account.service_account.email}"
}

###############################################################################
# Scheduler / PubSub #
###############################################################################

resource "google_pubsub_topic" "topic" {
project = var.project_id
name = lookup(local.prefixes, "topic", var.name)
}

resource "google_cloud_scheduler_job" "job" {
project = var.project_id
region = var.region
name = lookup(local.prefixes, "job", var.name)
schedule = var.schedule_config.schedule
time_zone = var.schedule_config.time_zone

pubsub_target {
attributes = {}
topic_name = google_pubsub_topic.topic.id
data = base64encode(local.job_data)
}
}

###############################################################################
# Cloud Function service account and IAM #
###############################################################################

resource "google_service_account" "service_account" {
project = var.project_id
account_id = lookup(local.prefixes, "service_account", var.name)
display_name = "Terraform-managed"
}

resource "google_project_iam_member" "service_account" {
for_each = toset(var.service_account_iam_roles)
project = var.project_id
role = each.value
member = local.service_account
}

###############################################################################
# Cloud Function and GCS code bundle #
###############################################################################

resource "google_cloudfunctions_function" "function" {
project = var.project_id
region = var.region
name = lookup(local.prefixes, "function", var.name)
description = "Terraform managed."
runtime = var.function_config.runtime
available_memory_mb = var.function_config.memory
max_instances = var.function_config.instances
timeout = var.function_config.timeout
entry_point = var.function_config.entry_point
service_account_email = google_service_account.service_account.email

# source_repository {
# url = var.source_repository_url
# }

event_trigger {
event_type = "providers/cloud.pubsub/eventTypes/topic.publish"
resource = google_pubsub_topic.topic.id
}

source_archive_bucket = local.bucket
source_archive_object = google_storage_bucket_object.bundle.name
}

resource "google_storage_bucket" "bucket" {
count = var.bucket_name == null ? 1 : 0
project = var.project_id
name = lookup(local.prefixes, "bucket", var.name)
lifecycle_rule {
action {
type = "Delete"
}
condition {
age = "30"
}
}
}

resource "google_storage_bucket_object" "bundle" {
name = "bundle-${data.archive_file.bundle.output_md5}.zip"
bucket = local.bucket
source = data.archive_file.bundle.output_path
}

data "archive_file" "bundle" {
type = "zip"
source_dir = var.bundle_config.source_dir
output_path = var.bundle_config.output_path
}
35 changes: 35 additions & 0 deletions modules/__experimental/cloud-function-scheduled/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

output "bucket_name" {
description = "Bucket name."
value = local.bucket
}

output "function_name" {
description = "Cloud function name."
value = google_cloudfunctions_function.function.name
}

output "service_account_email" {
description = "Service account email."
value = google_service_account.service_account.email
}

output "topic_id" {
description = "PubSub topic id."
value = google_pubsub_topic.topic.id
}
100 changes: 100 additions & 0 deletions modules/__experimental/cloud-function-scheduled/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

variable "bucket_name" {
description = "Name of the bucket that will be used for the function code, leave null to create one."
type = string
default = null
}

variable "bundle_config" {
description = "Cloud function code bundle configuration, output path is a zip file."
type = object({
source_dir = string
output_path = string
})
}

variable "function_config" {
description = "Cloud function configuration."
type = object({
entry_point = string
instances = number
memory = number
runtime = string
timeout = number
})
default = {
entry_point = "main"
instances = 1
memory = 256
runtime = "python37"
timeout = 180
}
}

variable "name" {
description = "Name used for resources (schedule, topic, etc.)."
type = string
}

variable "prefixes" {
description = "Optional prefixes for resource ids, null prefixes will be ignored."
type = object({
bucket = string
function = string
job = string
service_account = string
topic = string
})
default = null
}

variable "project_id" {
description = "Project id used for all resources."
type = string
}

variable "region" {
description = "Region used for all resources."
type = string
default = "us-central1"
}

variable "schedule_config" {
description = "Cloud function scheduler job configuration, leave data null to pass the name variable."
type = object({
pubsub_data = string
schedule = string
time_zone = string
})
default = {
schedule = "*/10 * * * *"
pubsub_data = null
time_zone = "UTC"
}
}

variable "service_account_iam_roles" {
description = "IAM roles assigned to the service account at the project level."
type = list(string)
default = []
}

# variable "source_repository_url" {
# type = string
# default = ""
# }
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2019 Google LLC
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,12 +14,6 @@
* limitations under the License.
*/

output "folder" {
description = "Folder resource."
value = google_folder.folder
}

output "folder_name" {
description = "Folder name."
value = google_folder.folder.name
terraform {
required_version = ">= 0.12.6"
}
46 changes: 0 additions & 46 deletions modules/__sandbox/playground/README.md

This file was deleted.

Loading

0 comments on commit dc22224

Please sign in to comment.