Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GCP gen2 poc #749

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
2 changes: 2 additions & 0 deletions docs/gcp/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ Service Account Keys and activate Google Workspace APIs.

- [Cloud Functions Admin](https://cloud.google.com/iam/docs/understanding-roles#cloudfunctions.admin) -
proxy instances are deployed as GCP cloud functions
- [Cloud Run Admin](https://cloud.google.com/iam/docs/understanding-roles#cloudrun.admin) - cloud
function deployment requires Cloud Run Admin role
- [Cloud Storage Admin](https://cloud.google.com/iam/docs/understanding-roles#storage.admin) -
processing of bulk data (such as HRIS exports) uses GCS buckets
- [IAM Role Admin](https://cloud.google.com/iam/docs/understanding-roles#iam.roles.admin) - create
Expand Down
10 changes: 5 additions & 5 deletions infra/modules/gcp-psoxy-bulk/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,11 @@ resource "google_service_account_iam_member" "act_as" {
}

resource "google_cloudfunctions_function" "function" {
name = local.function_name
description = "Psoxy instance to process ${var.source_kind} files"
runtime = "java17"
project = var.project_id
region = var.region
name = local.function_name
description = "Psoxy instance to process ${var.source_kind} files"
runtime = "java17"
project = var.project_id
region = var.region

available_memory_mb = coalesce(var.available_memory_mb, 1024)
source_archive_bucket = var.artifacts_bucket_name
Expand Down
106 changes: 61 additions & 45 deletions infra/modules/gcp-psoxy-rest/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -54,42 +54,57 @@ resource "google_service_account_iam_member" "act_as" {
service_account_id = data.google_service_account.function.id
}

resource "google_cloudfunctions2_function" "function" {
project = var.project_id
name = "${var.environment_id_prefix}${var.instance_id}"
description = "Psoxy Connector - ${var.source_kind}"
location = var.region

# trigger_http = true
# https_trigger_security_level = "SECURE_ALWAYS"


resource "google_cloudfunctions_function" "function" {
name = "${var.environment_id_prefix}${var.instance_id}"
description = "Psoxy Connector - ${var.source_kind}"
runtime = "java17"
project = var.project_id
region = var.region

trigger_http = true
https_trigger_security_level = "SECURE_ALWAYS"
available_memory_mb = var.available_memory_mb
source_archive_bucket = var.artifacts_bucket_name
source_archive_object = var.deployment_bundle_object_name
entry_point = "co.worklytics.psoxy.Route"
service_account_email = var.service_account_email
labels = var.default_labels
docker_registry = "ARTIFACT_REGISTRY"
docker_repository = var.artifact_repository_id

environment_variables = merge(
local.required_env_vars,
var.path_to_config == null ? {} : yamldecode(file(var.path_to_config)),
var.environment_variables,
var.config_parameter_prefix == null ? {} : { PATH_TO_SHARED_CONFIG = var.config_parameter_prefix },
var.config_parameter_prefix == null ? {} : { PATH_TO_INSTANCE_CONFIG = "${var.config_parameter_prefix}${replace(upper(var.instance_id), "-", "_")}_" },
)

dynamic "secret_environment_variables" {
for_each = var.secret_bindings
iterator = secret_environment_variable

content {
key = secret_environment_variable.key
project_id = data.google_project.project.number
secret = secret_environment_variable.value.secret_id
version = secret_environment_variable.value.version_number

build_config {
runtime = "java17"
entry_point = "co.worklytics.psoxy.Route"
docker_repository = var.artifact_repository_id


source {
storage_source {
bucket = var.artifacts_bucket_name
object = var.deployment_bundle_object_name
}
}
}

service_config {
#available_cpu = # defaults based on memory; 1024M = 0.583 CPU
available_memory = "${var.available_memory_mb}M"
min_instance_count = 0
max_instance_count = 40
service_account_email = var.service_account_email

environment_variables = merge(
local.required_env_vars,
var.path_to_config == null ? {} : yamldecode(file(var.path_to_config)),
var.environment_variables,
var.config_parameter_prefix == null ? {} : { PATH_TO_SHARED_CONFIG = var.config_parameter_prefix },
var.config_parameter_prefix == null ? {} : { PATH_TO_INSTANCE_CONFIG = "${var.config_parameter_prefix}${replace(upper(var.instance_id), "-", "_")}_" },
)

dynamic "secret_environment_variables" {
for_each = var.secret_bindings
iterator = secret_environment_variable

content {
key = secret_environment_variable.key
project_id = data.google_project.project.number
secret = secret_environment_variable.value.secret_id
version = secret_environment_variable.value.version_number
}
}
}

Expand All @@ -103,42 +118,43 @@ resource "google_cloudfunctions_function" "function" {
google_secret_manager_secret_iam_member.grant_sa_accessor_on_secret,
google_service_account_iam_member.act_as
]

}

resource "google_cloudfunctions_function_iam_member" "invokers" {
resource "google_cloudfunctions2_function_iam_member" "invokers" {
for_each = toset(var.invoker_sa_emails)

cloud_function = google_cloudfunctions_function.function.id
cloud_function = google_cloudfunctions2_function.function.id
member = "serviceAccount:${each.value}"
role = "roles/cloudfunctions.invoker"
}

resource "google_cloudfunctions_function_iam_member" "testers" {
resource "google_cloudfunctions2_function_iam_member" "testers" {
for_each = toset(var.gcp_principals_authorized_to_test)

cloud_function = google_cloudfunctions_function.function.id
cloud_function = google_cloudfunctions2_function.function.id
member = each.value
role = "roles/cloudfunctions.invoker"
}

locals {
proxy_endpoint_url = "https://${google_cloudfunctions_function.function.region}-${google_cloudfunctions_function.function.project}.cloudfunctions.net/${google_cloudfunctions_function.function.name}"
proxy_endpoint_url = "https://${google_cloudfunctions2_function.function.location}-${google_cloudfunctions2_function.function.project}.cloudfunctions.net/${google_cloudfunctions2_function.function.name}"
impersonation_param = var.example_api_calls_user_to_impersonate == null ? "" : " -i \"${var.example_api_calls_user_to_impersonate}\""
command_npm_install = "npm --prefix ${var.path_to_repo_root}tools/psoxy-test install"
command_cli_call = "node ${var.path_to_repo_root}tools/psoxy-test/cli-call.js"
command_test_calls = [for path in var.example_api_calls :
"${local.command_cli_call} -u \"${local.proxy_endpoint_url}${path}\"${local.impersonation_param}"
]
command_test_logs = "node ${var.path_to_repo_root}tools/psoxy-test/cli-logs.js -p \"${google_cloudfunctions_function.function.project}\" -f \"${google_cloudfunctions_function.function.name}\""
command_test_logs = "node ${var.path_to_repo_root}tools/psoxy-test/cli-logs.js -p \"${google_cloudfunctions2_function.function.project}\" -f \"${google_cloudfunctions2_function.function.name}\""
}

locals {
todo_content = <<EOT
## Testing ${google_cloudfunctions_function.function.name}
## Testing ${google_cloudfunctions2_function.function.name}

Review the deployed Cloud function in GCP console:

[Function in GCP Console](https://console.cloud.google.com/functions/details/${google_cloudfunctions_function.function.region}/${google_cloudfunctions_function.function.name}?project=${google_cloudfunctions_function.function.project})
[Function in GCP Console](https://console.cloud.google.com/functions/details/${google_cloudfunctions2_function.function.location}/${google_cloudfunctions2_function.function.name}?project=${google_cloudfunctions2_function.function.project})

We provide some Node.js scripts to easily validate the deployment. To be able
to run the test commands below, you need Node.js (>=16) and npm (v >=8)
Expand Down Expand Up @@ -210,7 +226,7 @@ moved {
resource "local_file" "review" {
count = var.todos_as_local_files ? 1 : 0

filename = "TODO ${var.todo_step} - test ${google_cloudfunctions_function.function.name}.md"
filename = "TODO ${var.todo_step} - test ${google_cloudfunctions2_function.function.name}.md"
content = local.todo_content
}

Expand All @@ -224,11 +240,11 @@ output "instance_id" {
}

output "service_account_email" {
value = google_cloudfunctions_function.function.service_account_email
value = google_cloudfunctions2_function.function.service_config[0].service_account_email
}

output "cloud_function_name" {
value = google_cloudfunctions_function.function.name
value = google_cloudfunctions2_function.function.name
}

output "cloud_function_url" {
Expand Down
3 changes: 2 additions & 1 deletion infra/modules/gcp/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ resource "google_project_service" "gcp_infra_api" {
"cloudresourcemanager.googleapis.com",
"compute.googleapis.com", # seems required w newer Google provider versions, for resources we use
"iam.googleapis.com", # manage IAM via terraform (as of 2023-04-17, internal dev envs didn't have this; so really needed?)
"run.googleapis.com", # required for cloud functions gen2
"secretmanager.googleapis.com",
"artifactregistry.googleapis.com", # for GCP Artifact Registry, as required for new Cloud Functions since Feb 2024
# "serviceusage.googleapis.com", # manage service APIs via terraform (prob already
Expand Down Expand Up @@ -360,4 +361,4 @@ output "artifact_repository" {
# If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry., forbidden"
google_project_service.gcp_infra_api
]
}
}
Loading