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

Add a module to encapsulate some of our Go service best practices. #41

Merged
merged 1 commit into from
Dec 24, 2023
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
1 change: 1 addition & 0 deletions .github/workflows/documentation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
- cloudevent-broker
- cloudevent-trigger
- cloudevent-recorder
- regional-go-service
- otel-collector
- networking
- dashboard/service
Expand Down
49 changes: 17 additions & 32 deletions cloudevent-broker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,35 +39,25 @@ module "foo-emits-events" {

// Run a cloud run service as the "foo" service account, and pass in the address
// of the regional ingress endpoint.
resource "google_cloud_run_v2_service" "foo-service" {
for_each = module.networking.regional-networks

project = var.project_id
name = "foo"
location = each.key

launch_stage = "BETA"
module "foo-service" {
source = "chainguard-dev/glue/cloudrun//regional-go-service"

template {
vpc_access {
network_interfaces {
network = each.value.network
subnetwork = each.value.subnet
}
// Egress through VPC so we can talk to the private ingress endpoint.
egress = "PRIVATE_RANGES_ONLY"
}

service_account = google_service_account.foo.email

containers {
image = "..."
project_id = var.project_id
name = "foo"
regions = module.networking.regional-networks

// Pass the resolved regional URI to the service in this region.
env {
name = "EVENT_INGRESS_URL"
value = module.foo-emits-events[each.key].uri
service_account = google_service_account.foo.email
containers = {
"foo" = {
source = {
working_dir = path.module
importpath = "./cmd/foo"
}
ports = [{ container_port = 8080 }]
regional-env = [{
name = "PUBSUB_TOPIC"
value = { for k, v in module.foo-emits-events : k => v.uri }
}]
}
}
}
Expand All @@ -82,9 +72,7 @@ No requirements.

| Name | Version |
|------|---------|
| <a name="provider_cosign"></a> [cosign](#provider\_cosign) | n/a |
| <a name="provider_google"></a> [google](#provider\_google) | n/a |
| <a name="provider_ko"></a> [ko](#provider\_ko) | n/a |

## Modules

Expand All @@ -93,22 +81,19 @@ No requirements.
| <a name="module_http"></a> [http](#module\_http) | ../dashboard/sections/http | n/a |
| <a name="module_layout"></a> [layout](#module\_layout) | ../dashboard/sections/layout | n/a |
| <a name="module_logs"></a> [logs](#module\_logs) | ../dashboard/sections/logs | n/a |
| <a name="module_otel-collector"></a> [otel-collector](#module\_otel-collector) | ../otel-collector | n/a |
| <a name="module_resources"></a> [resources](#module\_resources) | ../dashboard/sections/resources | n/a |
| <a name="module_this"></a> [this](#module\_this) | ../regional-go-service | n/a |
| <a name="module_topic"></a> [topic](#module\_topic) | ../dashboard/sections/topic | n/a |
| <a name="module_width"></a> [width](#module\_width) | ../dashboard/sections/width | n/a |

## Resources

| Name | Type |
|------|------|
| [cosign_sign.this](https://registry.terraform.io/providers/chainguard-dev/cosign/latest/docs/resources/sign) | resource |
| [google_cloud_run_v2_service.this](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloud_run_v2_service) | resource |
| [google_monitoring_dashboard.dashboard](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/monitoring_dashboard) | resource |
| [google_pubsub_topic.this](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/pubsub_topic) | resource |
| [google_pubsub_topic_iam_binding.ingress-publishes-events](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/pubsub_topic_iam_binding) | resource |
| [google_service_account.this](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account) | resource |
| [ko_build.this](https://registry.terraform.io/providers/ko-build/ko/latest/docs/resources/build) | resource |

## Inputs

Expand Down
72 changes: 14 additions & 58 deletions cloudevent-broker/ingress.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,69 +21,25 @@ resource "google_pubsub_topic_iam_binding" "ingress-publishes-events" {
members = ["serviceAccount:${google_service_account.this.email}"]
}

// Build the ingress image using our minimal hardened base image.
resource "ko_build" "this" {
base_image = "cgr.dev/chainguard/static:latest-glibc"
importpath = "./cmd/ingress"
working_dir = path.module
}

// Sign the image, assuming a keyless signing identity is available.
resource "cosign_sign" "this" {
image = ko_build.this.image_ref

# Only keep the latest signature.
conflict = "REPLACE"
}

module "otel-collector" {
source = "../otel-collector"
module "this" {
source = "../regional-go-service"
project_id = var.project_id
name = var.name
regions = var.regions

project_id = var.project_id
service_account = google_service_account.this.email
}

resource "google_cloud_run_v2_service" "this" {
for_each = var.regions

// Explicitly wait for the iam binding before provisioning the service,
// since the service functionally depends on being able to publish events
// to the topic. In practice, GCP IAM is "eventually consistent" and there
// will still invariably be some latency after even the service is created
// where publishing may fail.
depends_on = [google_pubsub_topic_iam_binding.ingress-publishes-events]

project = var.project_id
name = var.name
location = each.key

// The ingress service is an internal service, and so it should only
// be exposed to the internal network.
ingress = "INGRESS_TRAFFIC_INTERNAL_ONLY"

launch_stage = "BETA" // Needed for vpc_access below

template {
vpc_access {
network_interfaces {
network = each.value.network
subnetwork = each.value.subnet
containers = {
"ingress" = {
source = {
working_dir = path.module
importpath = "./cmd/ingress"
}
egress = "ALL_TRAFFIC" // This should not egress
}

service_account = google_service_account.this.email
containers {
image = cosign_sign.this.signed_ref

ports { container_port = 8080 }

env {
ports = [{ container_port = 8080 }]
regional-env = [{
name = "PUBSUB_TOPIC"
value = google_pubsub_topic.this[each.key].name
}
value = { for k, v in google_pubsub_topic.this : k => v.name }
}]
}
containers { image = module.otel-collector.image }
}
}

Expand Down
2 changes: 1 addition & 1 deletion cloudevent-broker/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
output "ingress" {
depends_on = [google_cloud_run_v2_service.this]
depends_on = [module.this]
description = "An object holding the name of the ingress service, which can be used to authorize callers to publish cloud events."
value = {
name = var.name
Expand Down
10 changes: 1 addition & 9 deletions cloudevent-recorder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,27 +52,21 @@ No requirements.

| Name | Version |
|------|---------|
| <a name="provider_cosign"></a> [cosign](#provider\_cosign) | n/a |
| <a name="provider_google"></a> [google](#provider\_google) | n/a |
| <a name="provider_google-beta"></a> [google-beta](#provider\_google-beta) | n/a |
| <a name="provider_ko"></a> [ko](#provider\_ko) | n/a |
| <a name="provider_random"></a> [random](#provider\_random) | n/a |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_otel-collector"></a> [otel-collector](#module\_otel-collector) | ../otel-collector | n/a |
| <a name="module_recorder-dashboard"></a> [recorder-dashboard](#module\_recorder-dashboard) | ../dashboard/cloudevent-receiver | n/a |
| <a name="module_this"></a> [this](#module\_this) | ../regional-go-service | n/a |
| <a name="module_triggers"></a> [triggers](#module\_triggers) | ../cloudevent-trigger | n/a |

## Resources

| Name | Type |
|------|------|
| [cosign_sign.logrotate-image](https://registry.terraform.io/providers/chainguard-dev/cosign/latest/docs/resources/sign) | resource |
| [cosign_sign.recorder-image](https://registry.terraform.io/providers/chainguard-dev/cosign/latest/docs/resources/sign) | resource |
| [google-beta_google_cloud_run_v2_service.recorder-service](https://registry.terraform.io/providers/hashicorp/google-beta/latest/docs/resources/google_cloud_run_v2_service) | resource |
| [google_bigquery_data_transfer_config.import-job](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/bigquery_data_transfer_config) | resource |
| [google_bigquery_dataset.this](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/bigquery_dataset) | resource |
| [google_bigquery_table.types](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/bigquery_table) | resource |
Expand All @@ -84,8 +78,6 @@ No requirements.
| [google_storage_bucket.recorder](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket) | resource |
| [google_storage_bucket_iam_member.import-reads-from-gcs-buckets](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket_iam_member) | resource |
| [google_storage_bucket_iam_member.recorder-writes-to-gcs-buckets](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket_iam_member) | resource |
| [ko_build.logrotate-image](https://registry.terraform.io/providers/ko-build/ko/latest/docs/resources/build) | resource |
| [ko_build.recorder-image](https://registry.terraform.io/providers/ko-build/ko/latest/docs/resources/build) | resource |
| [random_id.suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource |
| [random_id.trigger-suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource |
| [google_project.project](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/project) | data source |
Expand Down
118 changes: 34 additions & 84 deletions cloudevent-recorder/recorder.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,100 +16,52 @@ resource "google_storage_bucket_iam_member" "recorder-writes-to-gcs-buckets" {
member = "serviceAccount:${google_service_account.recorder.email}"
}

resource "ko_build" "recorder-image" {
base_image = "cgr.dev/chainguard/static:latest-glibc"
importpath = "./cmd/recorder"
working_dir = path.module
}

resource "cosign_sign" "recorder-image" {
image = ko_build.recorder-image.image_ref

# Only keep the latest signature.
conflict = "REPLACE"
}

resource "ko_build" "logrotate-image" {
base_image = "cgr.dev/chainguard/static:latest-glibc"
importpath = "./cmd/logrotate"
working_dir = path.module
}

resource "cosign_sign" "logrotate-image" {
image = ko_build.logrotate-image.image_ref

# Only keep the latest signature.
conflict = "REPLACE"
}

module "otel-collector" {
source = "../otel-collector"
module "this" {
source = "../regional-go-service"
project_id = var.project_id
name = var.name
regions = var.regions

project_id = var.project_id
service_account = google_service_account.recorder.email
}

resource "google_cloud_run_v2_service" "recorder-service" {
for_each = var.regions

provider = google-beta # For empty_dir
project = var.project_id
name = var.name
location = each.key
// This service should only be called by our Pub/Sub
// subscription, so flag it as internal only.
ingress = "INGRESS_TRAFFIC_INTERNAL_ONLY"

launch_stage = "BETA"

template {
vpc_access {
network_interfaces {
network = each.value.network
subnetwork = each.value.subnet
}
egress = "ALL_TRAFFIC" // This should not egress
}

service_account = google_service_account.recorder.email
containers {
image = cosign_sign.recorder-image.signed_ref

ports {
container_port = 8080
containers = {
"recorder" = {
source = {
working_dir = path.module
importpath = "./cmd/recorder"
}

env {
ports = [{ container_port = 8080 }]
env = [{
name = "LOG_PATH"
value = "/logs"
}
volume_mounts {
}]
volume_mounts = [{
name = "logs"
mount_path = "/logs"
}
}]
}
containers {
image = cosign_sign.logrotate-image.signed_ref

env {
name = "BUCKET"
value = google_storage_bucket.recorder[each.key].url
"logrotate" = {
source = {
working_dir = path.module
importpath = "./cmd/logrotate"
}
env {
env = [{
name = "LOG_PATH"
value = "/logs"
}
volume_mounts {
}]
regional-env = [{
name = "BUCKET"
value = { for k, v in google_storage_bucket.recorder : k => v.url }
}]
volume_mounts = [{
name = "logs"
mount_path = "/logs"
}
}
containers { image = module.otel-collector.image }
volumes {
name = "logs"
empty_dir {}
}]
}
}
volumes = [{
name = "logs"
empty_dir = {}
}]
}

resource "random_id" "trigger-suffix" {
Expand All @@ -128,20 +80,18 @@ module "triggers" {
broker = var.broker[each.value.region]
filter = { "type" : each.value.type }

depends_on = [google_cloud_run_v2_service.recorder-service]
depends_on = [module.this]
private-service = {
region = each.value.region
name = google_cloud_run_v2_service.recorder-service[each.value.region].name
name = var.name
}
}

module "recorder-dashboard" {
source = "../dashboard/cloudevent-receiver"
service_name = var.name

labels = {
for type, schema in var.types : replace(type, ".", "_") => ""
}
labels = { for type, schema in var.types : replace(type, ".", "_") => "" }

triggers = {
for type, schema in var.types : "type: ${type}" => "${var.name}-${random_id.trigger-suffix[type].hex}"
Expand Down
Loading
Loading