Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ module "localhost_function" {
| project\_id | The ID of the project to which resources will be applied. | `string` | n/a | yes |
| region | The region in which resources will be applied. | `string` | n/a | yes |
| runtime | The runtime in which the function will be executed. | `string` | n/a | yes |
| secret\_environment\_variables | A list of maps which contains key, project\_id, secret\_name (not the full secret id) and version to assign to the function as a set of secret environment variables. | `list(map(string))` | `[]` | no |
| service\_account\_email | The service account to run the function as. | `string` | `""` | no |
| source\_dependent\_files | A list of any Terraform created `local_file`s that the module will wait for before creating the archive. | <pre>list(object({<br> filename = string<br> id = string<br> }))</pre> | `[]` | no |
| source\_directory | The pathname of the directory which contains the function source code. | `string` | n/a | yes |
Expand Down Expand Up @@ -111,6 +112,7 @@ the following IAM roles:

- Cloud Functions Developer: `roles/cloudfunctions.developer`
- Storage Admin: `roles/storage.admin`
- Secret Manager Accessor: `roles/secretmanager.secretAccessor`

### APIs

Expand All @@ -119,6 +121,7 @@ following APIs enabled:

- Cloud Functions API: `cloudfunctions.googleapis.com`
- Cloud Storage API: `storage-component.googleapis.com`
- Secret Manager API: `secretmanager.googleapis.com`

The [Project Factory module][project-factory-module-site] can be used to
provision projects with specific APIs activated.
Expand Down
8 changes: 6 additions & 2 deletions examples/dynamic-files/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

This example demonstrates how to use the
[root module][root-module] that will contain source
code files generated from Terraform itself.
code files generated from Terraform itself and
environment variable stored in the Secrets Manager.

## Usage

Expand All @@ -29,6 +30,7 @@ this directory:
| function\_name | The name of the function created |
| project\_id | The project in which resources are applied. |
| random\_file\_string | The content of the terraform created file in the source directory. |
| random\_secret\_string | The value of the secret variable. |
| region | The region in which resources are applied. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Expand All @@ -46,7 +48,7 @@ must also be met.
The following software dependencies must be installed on the system
from which this module will be invoked:

- [Terraform][terraform-site] v0.12
- [Terraform][terraform-site] v0.13

### IAM Roles

Expand All @@ -56,6 +58,7 @@ the following IAM roles:
- Logs Configuration Writer: `roles/logging.configWriter`
- Pub/Sub Admin: `roles/pubsub.admin`
- Service Account User: `roles/iam.serviceAccountUser`
- Secret Manager Admin: `roles/secretmanager.admin`

- Default AppSpot user: `roles/owner`
- Your user: `roles/resourcemanager.projectCreator`
Expand All @@ -67,6 +70,7 @@ following APIs enabled:

- Cloud Pub/Sub API: `pubsub.googleapis.com`
- Stackdriver Logging API: `logging.googleapis.com`
- Secret Manager API: `secretmanager.googleapis.com`

[event-folder-log-entry-submodule-requirements]: ../../modules/event-folder-log-entry/README.md#requirements
[event-folder-log-entry-submodule]: ../../modules/event-folder-log-entry
Expand Down
3 changes: 2 additions & 1 deletion examples/dynamic-files/function_source/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ const filePath = path.join(__dirname, "terraform_created_file.txt");
exports.fileContent = (data, context, callback) => {
console.log("Received event");

console.log("Value from KEY env variable: " + process.env.KEY);
fs.readFile(filePath, { encoding: "utf-8" }, function(err, data) {
if (!err) {
callback(null, data);
callback(null, data + "\n" + process.env.KEY);
} else {
callback(err);
}
Expand Down
47 changes: 46 additions & 1 deletion examples/dynamic-files/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
* limitations under the License.
*/

locals {
secret_key_name = "random_secret_key"
}

resource "random_pet" "main" {
length = 2
separator = "-"
Expand All @@ -28,12 +32,43 @@ resource "google_storage_bucket" "trigger_bucket" {
}

resource "random_string" "random" {
count = 2
length = 16
special = false
}

resource "google_secret_manager_secret" "secret_key" {
project = var.project_id
secret_id = local.secret_key_name

replication {
user_managed {
replicas {
location = var.region
}
}
}
}

resource "google_secret_manager_secret_version" "secret_key_version" {
secret = google_secret_manager_secret.secret_key.id
secret_data = random_string.random[0].result
depends_on = [
google_secret_manager_secret.secret_key
]
}

resource "google_secret_manager_secret_iam_member" "iam_access_policy" {
secret_id = google_secret_manager_secret.secret_key.id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${var.project_id}@appspot.gserviceaccount.com"
depends_on = [
google_secret_manager_secret.secret_key
]
}

resource "local_file" "file" {
content = random_string.random.result
content = random_string.random[1].result
filename = "${path.module}/function_source/terraform_created_file.txt"
}

Expand All @@ -48,13 +83,23 @@ module "localhost_function" {
resource = google_storage_bucket.trigger_bucket.name
}

secret_environment_variables = [
{
key = "KEY"
project_id = var.project_id
secret_name = local.secret_key_name
version = "1"
}
]

name = random_pet.main.id
project_id = var.project_id
region = var.region
source_directory = "${path.module}/function_source"
runtime = "nodejs10"

source_dependent_files = [local_file.file]
depends_on = [google_secret_manager_secret_version.secret_key_version]
}

resource "null_resource" "wait_for_function" {
Expand Down
7 changes: 6 additions & 1 deletion examples/dynamic-files/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ output "function_name" {
description = "The name of the function created"
}

output "random_secret_string" {
value = random_string.random[0].result
description = "The value of the secret variable."
}

output "random_file_string" {
value = random_string.random.result
value = random_string.random[1].result
description = "The content of the terraform created file in the source directory."
}
3 changes: 2 additions & 1 deletion examples/dynamic-files/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ terraform {
required_version = ">= 0.13"
required_providers {
google = {
source = "hashicorp/google"
source = "hashicorp/google"
version = ">= 4.11"
}
local = {
source = "hashicorp/local"
Expand Down
18 changes: 18 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ data "archive_file" "main" {
excludes = var.files_to_exclude_in_source_dir
}


resource "google_storage_bucket" "main" {
count = var.create_bucket ? 1 : 0
name = coalesce(var.bucket_name, var.name)
Expand Down Expand Up @@ -87,6 +88,12 @@ resource "google_storage_bucket_object" "main" {
content_type = "application/zip"
}

// todo(bharathkkb): remove workaround after https://github.com/hashicorp/terraform-provider-google/issues/11383
data "google_project" "nums" {
for_each = toset(concat(compact([for item in var.secret_environment_variables : lookup(item, "project_id", "")]), [var.project_id]))
project_id = each.value
}

resource "google_cloudfunctions_function" "main" {
name = var.name
description = var.description
Expand All @@ -112,6 +119,17 @@ resource "google_cloudfunctions_function" "main" {
}
}

dynamic "secret_environment_variables" {
for_each = { for item in var.secret_environment_variables : item.key => item }

content {
key = secret_environment_variables.value["key"]
project_id = data.google_project.nums[lookup(secret_environment_variables.value, "project_id", var.project_id)].number
secret = secret_environment_variables.value["secret_name"]
version = lookup(secret_environment_variables.value, "version", "latest")
}
}

labels = var.labels
runtime = var.runtime
environment_variables = var.environment_variables
Expand Down
6 changes: 4 additions & 2 deletions test/integration/dynamic-files/dynamic_files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@ func TestDynamicFiles(t *testing.T) {
region := bpt.GetStringOutput("region")
functionName := bpt.GetStringOutput("function_name")
randomFileString := bpt.GetStringOutput("random_file_string")
randomSecretString := bpt.GetStringOutput("random_secret_string")

// call the function directly
op := gcloud.Run(t,
fmt.Sprintf("functions call %s", functionName),
gcloud.WithCommonArgs([]string{"--data", "{}", "--format", "json", "--project", project, "--region", region}),
)
// assert random string is contained in function response
assert.Contains(op.Get("result").String(), randomFileString, "contains random string")
// assert file random string and secret random string is contained in function response
assert.Contains(op.Get("result").String(), randomFileString, "contains file random string")
assert.Contains(op.Get("result").String(), randomSecretString, "contains secret random string")
})

bpt.Test()
Expand Down
1 change: 1 addition & 0 deletions test/setup/iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ locals {
"roles/logging.configWriter",
"roles/source.admin",
"roles/iam.serviceAccountUser",
"roles/secretmanager.admin",
]

int_required_folder_roles = [
Expand Down
14 changes: 8 additions & 6 deletions test/setup/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ module "project" {
source = "terraform-google-modules/project-factory/google"
version = "~> 10.0"

name = local.project_name
random_project_id = true
org_id = var.org_id
folder_id = var.folder_id
billing_account = var.billing_account
name = local.project_name
random_project_id = true
org_id = var.org_id
folder_id = var.folder_id
billing_account = var.billing_account
default_service_account = "keep"

activate_apis = [
"cloudresourcemanager.googleapis.com",
Expand All @@ -46,7 +47,8 @@ module "project" {
"cloudfunctions.googleapis.com",
"storage-component.googleapis.com",
"sourcerepo.googleapis.com",
"compute.googleapis.com"
"compute.googleapis.com",
"secretmanager.googleapis.com",
]
}

Expand Down
7 changes: 6 additions & 1 deletion variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ variable "runtime" {
description = "The runtime in which the function will be executed."
}

variable "secret_environment_variables" {
type = list(map(string))
default = []
description = "A list of maps which contains key, project_id, secret_name (not the full secret id) and version to assign to the function as a set of secret environment variables."
}

variable "source_directory" {
type = string
description = "The pathname of the directory which contains the function source code."
Expand Down Expand Up @@ -172,4 +178,3 @@ variable "log_object_prefix" {
default = null
description = "Log object prefix"
}

2 changes: 1 addition & 1 deletion versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ terraform {

google = {
source = "hashicorp/google"
version = ">= 3.53, < 5.0"
version = ">= 4.11, < 5.0"
}
}

Expand Down