Skip to content

Commit 44a2680

Browse files
dylanratcliffeactions-user
authored andcommitted
[ENG-3222] Add GCP Dataflow Job adapter with comprehensive link rules (#4302)
## Summary - Add a GCP Dataflow Job dynamic adapter that discovers Dataflow jobs and links them to Pub/Sub topics/subscriptions, BigQuery tables/datasets, Spanner instances, Bigtable instances, Compute networks/subnetworks, IAM service accounts, and KMS crypto keys - This is the first step toward detecting outages like ISSUE-7070 where a missing Pub/Sub subscription caused a Dataflow job failure — the Pub/Sub links are the most critical piece - Adds `roles/dataflow.viewer` to all IAM role configuration surfaces and enables `dataflow.googleapis.com` in deployment config ## Linear Ticket - **Ticket**: [ENG-3222](https://linear.app/overmind/issue/ENG-3222/gcp-dataflow-job-adapter) — GCP Dataflow Job Adapter - **Purpose**: Enable infrastructure discovery for GCP Dataflow jobs so Overmind can map their dependencies and detect blast radius from changes to connected resources - **Related**: [ENG-3217](https://linear.app/overmind/issue/ENG-3217) — the original outage where a missing Pub/Sub subscription broke a Dataflow job ## Changes **New files:** - `sources/gcp/dynamic/adapters/dataflow-job.go` — Dynamic adapter with 12 link rules across Pub/Sub, BigQuery, Spanner, Bigtable, networking, and IAM - `sources/gcp/dynamic/adapters/dataflow-job_test.go` — Tests for Get, Search, ErrorHandling, and StaticTests validating all link rules - `docs.overmind.tech/docs/sources/gcp/Types/gcp-dataflow-job.md` — Type documentation page - `docs.overmind.tech/docs/sources/gcp/data/gcp-dataflow-job.json` — Type metadata **Modified files:** - `sources/gcp/shared/models.go` — `Dataflow` API and `Job` resource constants - `sources/gcp/shared/item-types.go` — `DataflowJob` item type - `sources/gcp/shared/predefined-roles.go` — `roles/dataflow.viewer` with permissions - `deploy/modules/ovm-services/gke.tf` — Enable `dataflow.googleapis.com` - `docs.overmind.tech/docs/sources/gcp/configuration.md` — Role in docs table and services list - `services/frontend/src/features/settings/sources/details/gcp-scripts.ts` — Role in setup scripts - `sources/gcp/setup/scripts/overmind-gcp-roles.sh` — Role in shell script **Known limitation:** `spannerDetails.databaseId` and `bigTableDetails.tableId` return plain names (not resource URIs) in the Dataflow API, so those links won't auto-resolve for compound-key target types. Link rules are kept for documentation and `PotentialLinks` registration. The critical Pub/Sub links work correctly. ## Approved Plan - **Plan approver**: Elliot - **Linear ticket**: [ENG-3222](https://linear.app/overmind/issue/ENG-3222/gcp-dataflow-job-adapter) (contains the approved plan) > Deviation analysis and reviewer assignment are handled automatically by the > pre-approved PR review automation (see docs/PREAPPROVED_CHANGES.md). ## Pre-PR Review <details> <summary>Review findings: 0 Blocking, 1 Warning, 4 Advisories, 0 Failed</summary> ### Security Review (P0) **Blocking: 0 | Warning: 0** No security findings. URL construction uses fixed `dataflow.googleapis.com` host. No new endpoints, no secrets, no auth changes. ### Architecture / Scope Review (P1) **Advisory: 3** 1. Cross-cutting scope — PR touches 4 top-level directories (sources/, deploy/, docs.overmind.tech/, services/frontend/) 2. New adapter is not behind a feature flag — acceptable for additive discovery capability 3. Existing customers who already ran setup will need to re-grant `roles/dataflow.viewer` to discover Dataflow jobs ### DevOps / Deployment Review (P1) **Warning: 1 | Advisory: 1** 1. (Warning) Infrastructure change without documented rollback — enabling `dataflow.googleapis.com` is low-risk and revertible via PR revert + terraform apply 2. (Advisory) Consider validating in dogfood before production rollout </details> Made with [Cursor](https://cursor.com) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adds a new GCP discovery adapter plus new IAM role and API enablement across setup surfaces; risk is mainly around permission rollout and correctness of new link rules affecting dependency mapping (no write access or auth flow changes). > > **Overview** > Adds support for discovering **GCP Dataflow Jobs** via a new dynamic adapter (`gcp-dataflow-job`) with `GET` and location-scoped `SEARCH`, plus link rules to map job dependencies to Pub/Sub, BigQuery, Spanner, Bigtable, networking, IAM service accounts, and KMS keys. > > Wires this new resource into the system by introducing the `Dataflow` API / `Job` resource constants and `DataflowJob` item type, adding `roles/dataflow.viewer` (and required permissions) to predefined roles and all customer setup script surfaces (frontend templates, shell scripts, and docs), and enabling `dataflow.googleapis.com` in Terraform deployment config. Includes comprehensive adapter tests and new type metadata/docs for the Dataflow Job resource. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit d203d8485f5af18538afd47a02e6ab1ba6f153a7. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> GitOrigin-RevId: f5918383aeae36e45e60c5f3f3abc7ec0b129bc3
1 parent ae22b3a commit 44a2680

9 files changed

Lines changed: 475 additions & 1 deletion

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
title: GCP Dataflow Job
3+
sidebar_label: gcp-dataflow-job
4+
---
5+
6+
A **Google Cloud Dataflow Job** is a managed Apache Beam pipeline that processes streaming or batch data at scale. Dataflow handles resource provisioning, autoscaling, and fault tolerance, allowing you to run data processing workloads without managing the underlying infrastructure. Jobs can read from and write to Pub/Sub, BigQuery, Spanner, Bigtable, and other GCP services. See the official documentation for full details: https://cloud.google.com/dataflow/docs.
7+
8+
**Terraform Mappings:**
9+
10+
- `google_dataflow_job.job_id`
11+
- `google_dataflow_flex_template_job.job_id`
12+
13+
## Supported Methods
14+
15+
- `GET`: Get a gcp-dataflow-job by its "locations|jobs"
16+
- ~~`LIST`~~
17+
- `SEARCH`: Search for gcp-dataflow-job by location
18+
19+
## Possible Links
20+
21+
### [`gcp-big-query-dataset`](/sources/gcp/Types/gcp-big-query-dataset)
22+
23+
Dataflow jobs that read from or write to BigQuery reference the dataset containing the tables they use. If the dataset is deleted or misconfigured, the job may fail to access data.
24+
25+
### [`gcp-big-query-table`](/sources/gcp/Types/gcp-big-query-table)
26+
27+
Dataflow jobs can read from or write to specific BigQuery tables. If a table is deleted or its schema changes, the job may fail.
28+
29+
### [`gcp-big-table-admin-instance`](/sources/gcp/Types/gcp-big-table-admin-instance)
30+
31+
Dataflow jobs that use Bigtable as a source or sink reference the Bigtable instance. If the instance is deleted or misconfigured, the job may fail.
32+
33+
### [`gcp-cloud-kms-crypto-key`](/sources/gcp/Types/gcp-cloud-kms-crypto-key)
34+
35+
When customer-managed encryption keys (CMEK) are enabled for the Dataflow job environment, the job references the Cloud KMS Crypto Key used for encryption.
36+
37+
### [`gcp-compute-network`](/sources/gcp/Types/gcp-compute-network)
38+
39+
Dataflow worker VMs are attached to a VPC network. If the network is deleted or misconfigured, workers may lose connectivity or fail to start.
40+
41+
### [`gcp-compute-subnetwork`](/sources/gcp/Types/gcp-compute-subnetwork)
42+
43+
Dataflow workers run in a specific subnetwork. If the subnetwork is deleted or misconfigured, workers may lose connectivity or fail to start.
44+
45+
### [`gcp-iam-service-account`](/sources/gcp/Types/gcp-iam-service-account)
46+
47+
Dataflow workers run under a service account that grants them permissions to access other GCP services. If the service account is deleted or its permissions change, the job may fail.
48+
49+
### [`gcp-pub-sub-subscription`](/sources/gcp/Types/gcp-pub-sub-subscription)
50+
51+
Dataflow jobs that consume messages from Pub/Sub reference the subscription. If the subscription is deleted or misconfigured, the job may fail to consume messages.
52+
53+
### [`gcp-pub-sub-topic`](/sources/gcp/Types/gcp-pub-sub-topic)
54+
55+
Dataflow jobs that publish to or consume from Pub/Sub reference the topic. If the topic is deleted or misconfigured, the job may fail to read or write messages.
56+
57+
### [`gcp-spanner-instance`](/sources/gcp/Types/gcp-spanner-instance)
58+
59+
Dataflow jobs that use Spanner reference the Spanner instance. If the instance is deleted or misconfigured, the job may fail.

docs.overmind.tech/docs/sources/gcp/configuration.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ Overmind requires read-only access to discover and map your GCP infrastructure.
360360

361361
**Read-only viewer roles** for GCP services including:
362362

363-
- Compute Engine, GKE, Cloud Run, Cloud Functions
363+
- Compute Engine, GKE, Cloud Run, Cloud Functions, Dataflow
364364
- Cloud SQL, BigQuery, Spanner, Cloud Storage
365365
- IAM, networking, monitoring, and logging resources
366366
- And other GCP services
@@ -408,6 +408,7 @@ Here are all the predefined GCP roles that Overmind requires, plus the custom ro
408408
| `roles/dataform.viewer` | Dataform resource discovery [GCP Docs](https://cloud.google.com/iam/docs/roles-permissions/dataform#dataform.viewer) |
409409
| `roles/dataplex.catalogViewer` | Dataplex catalog resource discovery [GCP Docs](https://cloud.google.com/iam/docs/roles-permissions/dataplex#dataplex.catalogViewer) |
410410
| `roles/dataplex.viewer` | Dataplex resource discovery [GCP Docs](https://cloud.google.com/iam/docs/roles-permissions/dataplex#dataplex.viewer) |
411+
| `roles/dataflow.viewer` | Dataflow job discovery [GCP Docs](https://cloud.google.com/iam/docs/roles-permissions/dataflow#dataflow.viewer) |
411412
| `roles/dataproc.viewer` | Dataproc cluster discovery [GCP Docs](https://cloud.google.com/iam/docs/roles-permissions/dataproc#dataproc.viewer) |
412413
| `roles/dns.reader` | Cloud DNS resource discovery [GCP Docs](https://cloud.google.com/iam/docs/roles-permissions/dns#dns.reader) |
413414
| `roles/essentialcontacts.viewer` | Essential Contacts discovery [GCP Docs](https://cloud.google.com/iam/docs/roles-permissions/essentialcontacts#essentialcontacts.viewer) |
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"type": "gcp-dataflow-job",
3+
"category": 7,
4+
"potentialLinks": [
5+
"gcp-big-query-dataset",
6+
"gcp-big-query-table",
7+
"gcp-big-table-admin-instance",
8+
"gcp-cloud-kms-crypto-key",
9+
"gcp-compute-network",
10+
"gcp-compute-subnetwork",
11+
"gcp-iam-service-account",
12+
"gcp-pub-sub-subscription",
13+
"gcp-pub-sub-topic",
14+
"gcp-spanner-instance"
15+
],
16+
"descriptiveName": "GCP Dataflow Job",
17+
"supportedQueryMethods": {
18+
"get": true,
19+
"getDescription": "Get a gcp-dataflow-job by its \"locations|jobs\"",
20+
"search": true,
21+
"searchDescription": "Search for gcp-dataflow-job by location"
22+
},
23+
"terraformMappings": [
24+
{
25+
"terraformQueryMap": "google_dataflow_job.job_id"
26+
},
27+
{
28+
"terraformQueryMap": "google_dataflow_flex_template_job.job_id"
29+
}
30+
]
31+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package adapters
2+
3+
import (
4+
"github.com/overmindtech/cli/go/sdp-go"
5+
gcpshared "github.com/overmindtech/cli/sources/gcp/shared"
6+
)
7+
8+
// Dataflow Job adapter for Google Cloud Dataflow jobs.
9+
// Reference: https://cloud.google.com/dataflow/docs/reference/rest/v1b3/projects.locations.jobs#Job
10+
// GET: https://dataflow.googleapis.com/v1b3/projects/{project}/locations/{location}/jobs/{jobId}
11+
// LIST: https://dataflow.googleapis.com/v1b3/projects/{project}/locations/{location}/jobs
12+
var _ = registerableAdapter{
13+
sdpType: gcpshared.DataflowJob,
14+
meta: gcpshared.AdapterMeta{
15+
SDPAdapterCategory: sdp.AdapterCategory_ADAPTER_CATEGORY_COMPUTE_APPLICATION,
16+
LocationLevel: gcpshared.ProjectLevel,
17+
GetEndpointFunc: gcpshared.ProjectLevelEndpointFuncWithTwoQueries(
18+
"https://dataflow.googleapis.com/v1b3/projects/%s/locations/%s/jobs/%s",
19+
),
20+
SearchEndpointFunc: gcpshared.ProjectLevelEndpointFuncWithSingleQuery(
21+
"https://dataflow.googleapis.com/v1b3/projects/%s/locations/%s/jobs",
22+
),
23+
UniqueAttributeKeys: []string{"locations", "jobs"},
24+
IAMPermissions: []string{"dataflow.jobs.get", "dataflow.jobs.list"},
25+
PredefinedRole: "roles/dataflow.viewer",
26+
},
27+
linkRules: map[string]*gcpshared.Impact{
28+
// Pub/Sub links (critical for ENG-3217 outage detection)
29+
"jobMetadata.pubsubDetails.topic": {
30+
ToSDPItemType: gcpshared.PubSubTopic,
31+
Description: "If the Pub/Sub Topic is deleted or misconfigured: The Dataflow job may fail to read/write messages. If the Dataflow job changes: The topic remains unaffected.",
32+
},
33+
"jobMetadata.pubsubDetails.subscription": {
34+
ToSDPItemType: gcpshared.PubSubSubscription,
35+
Description: "If the Pub/Sub Subscription is deleted or misconfigured: The Dataflow job may fail to consume messages. If the Dataflow job changes: The subscription remains unaffected.",
36+
},
37+
38+
// BigQuery links
39+
"jobMetadata.bigqueryDetails.table": {
40+
ToSDPItemType: gcpshared.BigQueryTable,
41+
Description: "If the BigQuery Table is deleted or misconfigured: The Dataflow job may fail to read/write data. If the Dataflow job changes: The table remains unaffected.",
42+
},
43+
"jobMetadata.bigqueryDetails.dataset": {
44+
ToSDPItemType: gcpshared.BigQueryDataset,
45+
Description: "If the BigQuery Dataset is deleted or misconfigured: The Dataflow job may fail to access tables. If the Dataflow job changes: The dataset remains unaffected.",
46+
},
47+
48+
// Spanner links
49+
"jobMetadata.spannerDetails.instanceId": {
50+
ToSDPItemType: gcpshared.SpannerInstance,
51+
Description: "If the Spanner Instance is deleted or misconfigured: The Dataflow job may fail to read/write data. If the Dataflow job changes: The instance remains unaffected.",
52+
},
53+
// Bigtable links
54+
"jobMetadata.bigTableDetails.instanceId": {
55+
ToSDPItemType: gcpshared.BigTableAdminInstance,
56+
Description: "If the Bigtable Instance is deleted or misconfigured: The Dataflow job may fail to read/write data. If the Dataflow job changes: The instance remains unaffected.",
57+
},
58+
// Environment/infra links
59+
"environment.serviceAccountEmail": gcpshared.IAMServiceAccountImpactInOnly,
60+
"environment.serviceKmsKeyName": gcpshared.CryptoKeyImpactInOnly,
61+
"environment.workerPools.network": gcpshared.ComputeNetworkImpactInOnly,
62+
"environment.workerPools.subnetwork": {
63+
ToSDPItemType: gcpshared.ComputeSubnetwork,
64+
Description: "If the Compute Subnetwork is deleted or misconfigured: Dataflow workers may lose connectivity or fail to start. If the Dataflow job changes: The subnetwork remains unaffected.",
65+
},
66+
},
67+
terraformMapping: gcpshared.TerraformMapping{
68+
Reference: "https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/dataflow_job",
69+
Mappings: []*sdp.TerraformMapping{
70+
{
71+
TerraformMethod: sdp.QueryMethod_GET,
72+
TerraformQueryMap: "google_dataflow_job.job_id",
73+
},
74+
{
75+
TerraformMethod: sdp.QueryMethod_GET,
76+
TerraformQueryMap: "google_dataflow_flex_template_job.job_id",
77+
},
78+
},
79+
},
80+
}.Register()

0 commit comments

Comments
 (0)