Skip to content

Add Cloud Run for GCP CI env #56

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

Merged
merged 12 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions cmd/gcp/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ RUN go build -o bin/sctfe-gcp ./cmd/gcp
FROM alpine:3.20.2@sha256:0a4eaa0eecf5f8c050e5bba433f58c052be7587ee8af3e8b3910ef9ab5fbe9f5

COPY --from=builder /build/bin/sctfe-gcp /bin/sctfe-gcp

ENTRYPOINT ["/bin/sctfe-gcp"]
12 changes: 12 additions & 0 deletions cmd/gcp/ci/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM sctfe-gcp:latest AS base

# Build release image
FROM alpine:3.20.2@sha256:0a4eaa0eecf5f8c050e5bba433f58c052be7587ee8af3e8b3910ef9ab5fbe9f5

# Copy the fake CA certificate into the container
COPY ./testdata/fake-ca.cert /bin/

# Copy the sctfe-gcp binary
COPY --from=base /bin/sctfe-gcp /bin/

ENTRYPOINT ["/bin/sctfe-gcp"]
41 changes: 41 additions & 0 deletions deployment/live/gcp/ci/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions deployment/live/gcp/ci/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# GCP SCTFE CI Environment

## Overview

This config uses the [gcp/conformance](/deployment/modules/gcp/conformance) module to
define a CI environment to run the SCTFE, backed by Trillian Tessera.

At a high level, this environment consists of:
- One Spanner instance with two databases:
- one for Tessera
- one for deduplication
- A GCS Bucket
- Secret Manager
- Cloud Run

### Manual Deployment

First authenticate via `gcloud` as a principle with sufficient ACLs for
the project:

```sh
gcloud auth application-default login
```

Set the required environment variables:

```sh
export GOOGLE_PROJECT={VALUE}
export GOOGLE_REGION={VALUE} # e.g: us-central1
```

TODO: Add the Artifact Registry which is in the Cloud Build pull request. The expected repository is `us-central1-docker.pkg.dev/${GOOGLE_PROJECT}/docker-ci`.

Build and push the Docker image to Artifact Registry repository:

```sh
docker build -f ./cmd/gcp/Dockerfile -t sctfe-gcp:latest .
docker build -f ./cmd/gcp/ci/Dockerfile -t conformance-gcp:latest .
docker tag conformance-gcp:latest us-central1-docker.pkg.dev/${GOOGLE_PROJECT}/docker-ci/conformance-gcp:latest
docker push us-central1-docker.pkg.dev/${GOOGLE_PROJECT}/docker-ci/conformance-gcp
```

Terraforming the project can be done by:
1. `cd` to the relevant directory (/deployment/live/gcp/ci/) for the environment to deploy/change.
2. Run `terragrunt apply`.

19 changes: 19 additions & 0 deletions deployment/live/gcp/ci/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
terraform {
source = "${get_repo_root()}/deployment/modules/gcp//conformance"
}

locals {
env = "ci"
base_name = "${local.env}-conformance"
server_docker_image = "us-central1-docker.pkg.dev/${include.root.locals.project_id}/docker-${local.env}/conformance-gcp:latest"
}

include "root" {
path = find_in_parent_folders()
expose = true
}

inputs = merge(
local,
include.root.locals,
)
21 changes: 21 additions & 0 deletions deployment/live/gcp/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
locals {
env = path_relative_to_include()
project_id = get_env("GOOGLE_PROJECT", "phboneff-dev")
location = get_env("GOOGLE_REGION", "us-central1")
base_name = get_env("TESSERA_BASE_NAME", "${local.env}-static-ct")
}

remote_state {
backend = "gcs"

config = {
project = local.project_id
location = local.location
bucket = "${local.project_id}-${local.base_name}-terraform-state"
prefix = "terraform.tfstate"

gcs_bucket_labels = {
name = "terraform_state_conformance"
}
}
}
11 changes: 6 additions & 5 deletions deployment/live/gcp/test/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# GCP SCTFE Configs
# GCP SCTFE Local Test Environment

## Prerequisites
You'll need to have a VM running in the same GCP project that you can SSH to,
Expand All @@ -8,14 +8,15 @@ installed, and your favourite terminal multiplexer.

## Overview

This config uses the [gcp/storage](/deployment/modules/gcp/conformance) module to
This config uses the [gcp/test](/deployment/modules/gcp/test) module to
define a test environment to run the SCTFE, backed by Trillian Tessera.

At a high level, this environment consists of:
- One Spanner instance with two databases:
- one for Tessera
- one for deduplication
- A GCS Bucket
- Secret Manager

## Manual deployment

Expand All @@ -31,12 +32,12 @@ Set the required environment variables:
```bash
export GOOGLE_PROJECT={VALUE}
export GOOGLE_REGION={VALUE} # e.g: us-central1
export TESSERA_BASE_NAME={VALUE} # e.g: staticct
export TESSERA_BASE_NAME={VALUE} # e.g: test-static-ct
```

Terraforming the project can be done by:
1. `cd` to the relevant directory for the environment to deploy/change (e.g. `ci`)
2. Run `terragrunt apply`
1. `cd` to the relevant directory for the environment to deploy/change (e.g. `ci`)
2. Run `terragrunt apply`

Store the Secret Manager resource ID of signer key pair into the environment variables:

Expand Down
30 changes: 11 additions & 19 deletions deployment/live/gcp/test/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
terraform {
source = "${get_repo_root()}/deployment/modules/gcp//conformance"
source = "${get_repo_root()}/deployment/modules/gcp//test"
}

locals {
project_id = get_env("GOOGLE_PROJECT", "phboneff-dev")
location = get_env("GOOGLE_REGION", "us-central1")
base_name = get_env("TESSERA_BASE_NAME", "tessera-staticct")
env = "test"
base_name = get_env("TESSERA_BASE_NAME", "${local.env}-static-ct")
}

inputs = local

remote_state {
backend = "gcs"

config = {
project = local.project_id
location = local.location
bucket = "${local.project_id}-${local.base_name}-terraform-state"
prefix = "terraform.tfstate"

gcs_bucket_labels = {
name = "terraform_state_conformance"
}
}
include "root" {
path = find_in_parent_folders()
expose = true
}

inputs = merge(
local,
include.root.locals,
)
119 changes: 119 additions & 0 deletions deployment/modules/gcp/cloudrun/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
terraform {
required_providers {
google = {
source = "registry.terraform.io/hashicorp/google"
version = "6.1.0"
}
}
}

# Cloud Run

resource "google_project_service" "cloudrun_api" {
service = "run.googleapis.com"
disable_on_destroy = false
}

resource "google_service_account" "cloudrun_service_account" {
account_id = "cloudrun-${var.env}-sa"
display_name = "Service Account for Cloud Run (${var.env})"
}

resource "google_project_iam_member" "monitoring_metric_writer" {
project = var.project_id
role = "roles/monitoring.metricWriter"
member = "serviceAccount:${google_service_account.cloudrun_service_account.email}"
}

resource "google_storage_bucket_iam_member" "member" {
bucket = var.bucket
role = "roles/storage.objectUser"
member = "serviceAccount:${google_service_account.cloudrun_service_account.email}"
}

resource "google_project_iam_member" "iam_secret_accessor" {
project = var.project_id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.cloudrun_service_account.email}"
}

resource "google_spanner_database_iam_member" "iam_log_spanner_database_user" {
instance = var.log_spanner_instance
database = var.log_spanner_db
role = "roles/spanner.databaseUser"
member = "serviceAccount:${google_service_account.cloudrun_service_account.email}"
}

resource "google_spanner_database_iam_member" "iam_dedup_spanner_database_user" {
instance = var.log_spanner_instance
database = var.dedup_spanner_db
role = "roles/spanner.databaseUser"
member = "serviceAccount:${google_service_account.cloudrun_service_account.email}"
}

locals {
spanner_log_db_path = "projects/${var.project_id}/instances/${var.log_spanner_instance}/databases/${var.log_spanner_db}"
spanner_dedup_db_path = "projects/${var.project_id}/instances/${var.log_spanner_instance}/databases/${var.dedup_spanner_db}"
}

resource "google_cloud_run_v2_service" "default" {
name = var.base_name
location = var.location
launch_stage = "GA"

template {
service_account = google_service_account.cloudrun_service_account.account_id
max_instance_request_concurrency = 700
timeout = "5s"

scaling {
max_instance_count = 3
}

containers {
image = var.server_docker_image
name = "conformance"
args = [
"--logtostderr",
"--v=1",
"--http_endpoint=:6962",
"--project_id=${var.project_id}",
"--bucket=${var.bucket}",
"--spanner_db_path=${local.spanner_log_db_path}",
"--spanner_dedup_db_path=${local.spanner_dedup_db_path}",
"--roots_pem_file=/bin/fake-ca.cert",
"--origin=${var.base_name}",
"--signer_public_key_secret_name=${var.signer_public_key_secret_name}",
"--signer_private_key_secret_name=${var.signer_private_key_secret_name}",
]
ports {
container_port = 6962
}

resources {
limits = {
cpu = "2"
memory = "1024Mi"
}
}

startup_probe {
initial_delay_seconds = 1
timeout_seconds = 1
period_seconds = 10
failure_threshold = 6
tcp_socket {
port = 6962
}
}
}
}

deletion_protection = false

client = "terraform"

depends_on = [
google_project_service.cloudrun_api,
]
}
Loading
Loading