From ecb92b508c4ec074f85b3eafdf10df628906a69b Mon Sep 17 00:00:00 2001 From: Luca Prete Date: Thu, 15 Jan 2026 16:39:05 +0000 Subject: [PATCH] Add ability to use existing source files in GCS. (#3653) --- modules/agent-engine/README.md | 45 ++++++++++-- modules/agent-engine/agent-managed.tf | 20 ++++-- modules/agent-engine/agent-unmanaged.tf | 20 ++++-- modules/agent-engine/main.tf | 15 +++- modules/agent-engine/variables.tf | 1 + .../agent_engine/examples/pickle-gcs.yaml | 72 +++++++++++++++++++ 6 files changed, 155 insertions(+), 18 deletions(-) create mode 100644 tests/modules/agent_engine/examples/pickle-gcs.yaml diff --git a/modules/agent-engine/README.md b/modules/agent-engine/README.md index eba288e52..5f85d7924 100644 --- a/modules/agent-engine/README.md +++ b/modules/agent-engine/README.md @@ -114,6 +114,37 @@ module "agent_engine" { # tftest inventory=minimal-pickle.yaml ``` +You may want to upload your files on the GCS bucket outside Terrafrom. +In this example, the module expects your package config files to be already present in the GCS bucket. + +```hcl +module "agent_engine" { + source = "./fabric/modules/agent-engine" + name = "my-agent" + project_id = var.project_id + region = var.region + + agent_engine_config = { + agent_framework = "google-adk" + } + + bucket_config = { + create = false + } + + deployment_files = { + package_config = { + are_paths_local = false + dependencies_path = "dependencies.tar.gz" + pickle_path = "pickle.pkl" + requirements_path = "requirements.txt" + } + source_config = null + } +} +# tftest inventory=pickle-gcs.yaml +``` + ### Unmanaged deployments By default, this module tracks and controls code updates. This means you can only the agent code via Terraform. @@ -269,15 +300,15 @@ The module allows you to dynamically reference context values for resources crea | name | description | type | required | default | |---|---|:---:|:---:|:---:| | [agent_engine_config](variables.tf#L17) | The agent configuration. | object({…}) | ✓ | | -| [name](variables.tf#L121) | The name of the agent. | string | ✓ | | -| [project_id](variables.tf#L127) | The id of the project where to deploy the agent. | string | ✓ | | -| [region](variables.tf#L133) | The region where to deploy the agent. | string | ✓ | | +| [name](variables.tf#L122) | The name of the agent. | string | ✓ | | +| [project_id](variables.tf#L128) | The id of the project where to deploy the agent. | string | ✓ | | +| [region](variables.tf#L134) | The region where to deploy the agent. | string | ✓ | | | [bucket_config](variables.tf#L40) | The GCS bucket configuration. | object({…}) | | {} | | [context](variables.tf#L52) | Context-specific interpolations. | object({…}) | | {} | -| [deployment_files](variables.tf#L65) | The to source files path and names. | object({…}) | | {…} | -| [description](variables.tf#L101) | The Agent Engine description. | string | | "Terraform managed." | -| [encryption_key](variables.tf#L108) | The full resource name of the Cloud KMS CryptoKey. | string | | null | -| [managed](variables.tf#L114) | Whether the Terraform module should control the code updates. | bool | | true | +| [deployment_files](variables.tf#L65) | The to source files path and names. | object({…}) | | {…} | +| [description](variables.tf#L102) | The Agent Engine description. | string | | "Terraform managed." | +| [encryption_key](variables.tf#L109) | The full resource name of the Cloud KMS CryptoKey. | string | | null | +| [managed](variables.tf#L115) | Whether the Terraform module should control the code updates. | bool | | true | | [service_account_config](variables-serviceaccount.tf#L18) | Service account configurations. | object({…}) | | {} | ## Outputs diff --git a/modules/agent-engine/agent-managed.tf b/modules/agent-engine/agent-managed.tf index 5c1a10948..e673e6952 100644 --- a/modules/agent-engine/agent-managed.tf +++ b/modules/agent-engine/agent-managed.tf @@ -88,10 +88,22 @@ resource "google_vertex_ai_reasoning_engine" "managed" { for_each = var.deployment_files.package_config != null ? { 1 = 1 } : {} content { - python_version = var.agent_engine_config.python_version - dependency_files_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.dependencies[0].name}" - requirements_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.requirements[0].name}" - pickle_object_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.pickle[0].name}" + python_version = var.agent_engine_config.python_version + dependency_files_gcs_uri = ( + var.deployment_files.package_config.are_paths_local + ? "gs://${local.bucket_name}/${google_storage_bucket_object.dependencies[0].name}" + : var.deployment_files.package_config.dependencies_path + ) + requirements_gcs_uri = ( + var.deployment_files.package_config.are_paths_local + ? "gs://${local.bucket_name}/${google_storage_bucket_object.requirements[0].name}" + : var.deployment_files.package_config.requirements_path + ) + pickle_object_gcs_uri = ( + var.deployment_files.package_config.are_paths_local + ? "gs://${local.bucket_name}/${google_storage_bucket_object.pickle[0].name}" + : var.deployment_files.package_config.pickle_path + ) } } diff --git a/modules/agent-engine/agent-unmanaged.tf b/modules/agent-engine/agent-unmanaged.tf index 9c7b5260d..8ba58c02a 100644 --- a/modules/agent-engine/agent-unmanaged.tf +++ b/modules/agent-engine/agent-unmanaged.tf @@ -88,10 +88,22 @@ resource "google_vertex_ai_reasoning_engine" "unmanaged" { for_each = var.deployment_files.package_config == null ? {} : { 1 = 1 } content { - python_version = var.agent_engine_config.python_version - dependency_files_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.dependencies[0].name}" - requirements_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.requirements[0].name}" - pickle_object_gcs_uri = "gs://${local.bucket_name}/${google_storage_bucket_object.pickle[0].name}" + python_version = var.agent_engine_config.python_version + dependency_files_gcs_uri = ( + var.deployment_files.package_config.are_paths_local + ? "gs://${local.bucket_name}/${google_storage_bucket_object.dependencies[0].name}" + : var.deployment_files.package_config.dependencies_path + ) + requirements_gcs_uri = ( + var.deployment_files.package_config.are_paths_local + ? "gs://${local.bucket_name}/${google_storage_bucket_object.requirements[0].name}" + : var.deployment_files.package_config.requirements_path + ) + pickle_object_gcs_uri = ( + var.deployment_files.package_config.are_paths_local + ? "gs://${local.bucket_name}/${google_storage_bucket_object.pickle[0].name}" + : var.deployment_files.package_config.pickle_path + ) } } diff --git a/modules/agent-engine/main.tf b/modules/agent-engine/main.tf index a700778c8..81e2a2ab5 100644 --- a/modules/agent-engine/main.tf +++ b/modules/agent-engine/main.tf @@ -67,7 +67,10 @@ resource "google_storage_bucket" "default" { } resource "google_storage_bucket_object" "dependencies" { - count = var.deployment_files.package_config != null ? 1 : 0 + count = ( + var.deployment_files.package_config != null + && var.deployment_files.package_config.are_paths_local ? 1 : 0 + ) name = "dependencies.tar.gz" bucket = local.bucket_name source = try(var.deployment_files.package_config.dependencies_path, null) @@ -77,7 +80,10 @@ resource "google_storage_bucket_object" "dependencies" { } resource "google_storage_bucket_object" "pickle" { - count = var.deployment_files.package_config != null ? 1 : 0 + count = ( + var.deployment_files.package_config != null + && var.deployment_files.package_config.are_paths_local ? 1 : 0 + ) name = "pickle.pkl" bucket = local.bucket_name source = try(var.deployment_files.package_config.pickle_path, null) @@ -87,7 +93,10 @@ resource "google_storage_bucket_object" "pickle" { } resource "google_storage_bucket_object" "requirements" { - count = var.deployment_files.package_config != null ? 1 : 0 + count = ( + var.deployment_files.package_config != null + && var.deployment_files.package_config.are_paths_local ? 1 : 0 + ) name = "requirements.txt" bucket = local.bucket_name source = try(var.deployment_files.package_config.requirements_path, null) diff --git a/modules/agent-engine/variables.tf b/modules/agent-engine/variables.tf index cf96bb908..f716325da 100644 --- a/modules/agent-engine/variables.tf +++ b/modules/agent-engine/variables.tf @@ -66,6 +66,7 @@ variable "deployment_files" { description = "The to source files path and names." type = object({ package_config = optional(object({ + are_paths_local = optional(bool, true) dependencies_path = optional(string, "./src/dependencies.tar.gz") pickle_path = optional(string, "./src/pickle.pkl") requirements_path = optional(string, "./src/requirements.txt") diff --git a/tests/modules/agent_engine/examples/pickle-gcs.yaml b/tests/modules/agent_engine/examples/pickle-gcs.yaml new file mode 100644 index 000000000..01b4fd8d7 --- /dev/null +++ b/tests/modules/agent_engine/examples/pickle-gcs.yaml @@ -0,0 +1,72 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.agent_engine.google_project_iam_member.default["roles/aiplatform.user"]: + condition: [] + member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com + project: project-id + role: roles/aiplatform.user + module.agent_engine.google_project_iam_member.default["roles/storage.objectViewer"]: + condition: [] + member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com + project: project-id + role: roles/storage.objectViewer + module.agent_engine.google_project_iam_member.default["roles/viewer"]: + condition: [] + member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com + project: project-id + role: roles/viewer + module.agent_engine.google_service_account.service_account[0]: + account_id: my-agent + create_ignore_already_exists: null + description: null + disabled: false + display_name: my-agent + email: my-agent@project-id.iam.gserviceaccount.com + member: serviceAccount:my-agent@project-id.iam.gserviceaccount.com + project: project-id + timeouts: null + module.agent_engine.google_vertex_ai_reasoning_engine.managed[0]: + description: Terraform managed. + display_name: my-agent + encryption_spec: [] + project: project-id + region: europe-west8 + spec: + - agent_framework: google-adk + class_methods: null + deployment_spec: [] + package_spec: + - dependency_files_gcs_uri: dependencies.tar.gz + pickle_object_gcs_uri: pickle.pkl + python_version: '3.12' + requirements_gcs_uri: requirements.txt + service_account: my-agent@project-id.iam.gserviceaccount.com + source_code_spec: [] + timeouts: null + module.agent_engine.time_sleep.wait_5_minutes: + create_duration: 5m + destroy_duration: null + triggers: null + +counts: + google_project_iam_member: 3 + google_service_account: 1 + google_vertex_ai_reasoning_engine: 1 + modules: 1 + resources: 6 + time_sleep: 1 + +outputs: {}