From 0abf021f0466f8c004decdf77ca7fa08950f527a Mon Sep 17 00:00:00 2001 From: Luca Prete Date: Mon, 20 Apr 2026 15:15:29 +0200 Subject: [PATCH] Add more context and tests to agent-engine module (#3886) --- modules/agent-engine/README.md | 73 ++++++++++++++++--- modules/agent-engine/agent-managed.tf | 22 ++++-- modules/agent-engine/agent-unmanaged.tf | 22 ++++-- modules/agent-engine/variables.tf | 14 ++-- .../agent_engine/examples/context.yaml | 63 ++++++++++++++++ 5 files changed, 168 insertions(+), 26 deletions(-) create mode 100644 tests/modules/agent_engine/examples/context.yaml diff --git a/modules/agent-engine/README.md b/modules/agent-engine/README.md index 615b112a7..39240f9de 100644 --- a/modules/agent-engine/README.md +++ b/modules/agent-engine/README.md @@ -384,24 +384,77 @@ module "agent_engine" { ## Getting values from context -The module allows you to dynamically reference context values for resources created outside this module, through the `context` variable. This includes the definition of custom roles, iam_principals, locations, kms_keys, models and project ids. +The module allows you to dynamically reference context values for resources created outside this module, through the `context` variable. This includes the definition of custom roles, iam_principals, locations, networks, psc_network_attachments, kms_keys, models and project ids. + +```hcl +module "agent_engine" { + source = "./fabric/modules/agent-engine" + name = "my-agent" + project_id = "$project_ids:main-project" + region = "$locations:primary" + agent_engine_config = { + agent_framework = "google-adk" + } + deployment_files = { + source_config = { + source_path = "assets/src/source.tar.gz" + } + } + networking_config = { + network_attachment_id = "$psc_network_attachments:primary" + dns_peering_configs = { + "example.com" = { + target_network_name = "$networks:vpc-1" + } + "my-company.local" = { + target_network_name = "$networks:vpc-2" + target_project_id = "$project_ids:dns-project" + } + } + } + service_account_config = { + create = false + email = "$iam_principals:my-custom-sa" + } + context = { + iam_principals = { + my-custom-sa = "my-sa@$test-project-1.iam.gserviceaccount.com" + } + locations = { + primary = "europe-west1" + } + networks = { + vpc-1 = "my-vpc-1" + vpc-2 = "my-vpc-2" + } + project_ids = { + main-project = "test-project-1" + dns-project = "company-dns-project" + } + psc_network_attachments = { + primary = "projects/test-project-1/regions/europe-west1/networkAttachments/core-service" + } + } +} +# tftest inventory=context.yaml +``` ## Variables | name | description | type | required | default | |---|---|:---:|:---:|:---:| | [agent_engine_config](variables.tf#L17) | The agent configuration. | object({…}) | ✓ | | -| [name](variables.tf#L146) | The name of the agent. | string | ✓ | | -| [project_id](variables.tf#L165) | The id of the project where to deploy the agent. | string | ✓ | | -| [region](variables.tf#L171) | The region where to deploy the agent. | string | ✓ | | +| [name](variables.tf#L148) | The name of the agent. | string | ✓ | | +| [project_id](variables.tf#L167) | The id of the project where to deploy the agent. | string | ✓ | | +| [region](variables.tf#L173) | 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#L66) | The to source files path and names. | object({…}) | | {…} | -| [description](variables.tf#L103) | The Agent Engine description. | string | | "Terraform managed." | -| [encryption_key](variables.tf#L110) | The full resource name of the Cloud KMS CryptoKey. | string | | null | -| [managed](variables.tf#L116) | Whether the Terraform module should control the code updates. | bool | | true | -| [memory_bank_config](variables.tf#L123) | Configuration for the memory bank. | object({…}) | | null | -| [networking_config](variables.tf#L152) | Networking configuration. | object({…}) | | null | +| [deployment_files](variables.tf#L68) | The to source files path and names. | object({…}) | | {…} | +| [description](variables.tf#L105) | The Agent Engine description. | string | | "Terraform managed." | +| [encryption_key](variables.tf#L112) | The full resource name of the Cloud KMS CryptoKey. | string | | null | +| [managed](variables.tf#L118) | Whether the Terraform module should control the code updates. | bool | | true | +| [memory_bank_config](variables.tf#L125) | Configuration for the memory bank. | object({…}) | | null | +| [networking_config](variables.tf#L154) | Networking configuration. | object({…}) | | null | | [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 7fc524307..a68c2812a 100644 --- a/modules/agent-engine/agent-managed.tf +++ b/modules/agent-engine/agent-managed.tf @@ -75,18 +75,30 @@ resource "google_vertex_ai_reasoning_engine" "managed" { for_each = var.networking_config == null ? {} : { 1 = 1 } content { - network_attachment = var.networking_config.network_attachment_id + network_attachment = lookup( + local.ctx.psc_network_attachments, + var.networking_config.network_attachment_id, + var.networking_config.network_attachment_id + ) dynamic "dns_peering_configs" { for_each = var.networking_config.dns_peering_configs content { - domain = dns_peering_configs.key - target_network = dns_peering_configs.value.target_network_name + domain = dns_peering_configs.key + target_network = lookup( + local.ctx.networks, + dns_peering_configs.value.target_network_name, + dns_peering_configs.value.target_network_name + ) target_project = ( dns_peering_configs.value.target_project_id == null - ? var.project_id - : dns_peering_configs.value.target_project_id + ? local.project_id + : lookup( + local.ctx.project_ids, + dns_peering_configs.value.target_project_id, + dns_peering_configs.value.target_project_id + ) ) } } diff --git a/modules/agent-engine/agent-unmanaged.tf b/modules/agent-engine/agent-unmanaged.tf index 23b4523e4..d9701e2a8 100644 --- a/modules/agent-engine/agent-unmanaged.tf +++ b/modules/agent-engine/agent-unmanaged.tf @@ -75,18 +75,30 @@ resource "google_vertex_ai_reasoning_engine" "unmanaged" { for_each = var.networking_config == null ? {} : { 1 = 1 } content { - network_attachment = var.networking_config.network_attachment_id + network_attachment = lookup( + local.ctx.psc_network_attachments, + var.networking_config.network_attachment_id, + var.networking_config.network_attachment_id + ) dynamic "dns_peering_configs" { for_each = var.networking_config.dns_peering_configs content { - domain = dns_peering_configs.key - target_network = dns_peering_configs.value.target_network_name + domain = dns_peering_configs.key + target_network = lookup( + local.ctx.networks, + dns_peering_configs.value.target_network_name, + dns_peering_configs.value.target_network_name + ) target_project = ( dns_peering_configs.value.target_project_id == null - ? var.project_id - : dns_peering_configs.value.target_project_id + ? local.project_id + : lookup( + local.ctx.project_ids, + dns_peering_configs.value.target_project_id, + dns_peering_configs.value.target_project_id + ) ) } } diff --git a/modules/agent-engine/variables.tf b/modules/agent-engine/variables.tf index 5f4800a54..9a1c9477c 100644 --- a/modules/agent-engine/variables.tf +++ b/modules/agent-engine/variables.tf @@ -52,12 +52,14 @@ variable "bucket_config" { variable "context" { description = "Context-specific interpolations." type = object({ - custom_roles = optional(map(string), {}) - iam_principals = optional(map(string), {}) - locations = optional(map(string), {}) - kms_keys = optional(map(string), {}) - models = optional(map(string), {}) - project_ids = optional(map(string), {}) + custom_roles = optional(map(string), {}) + iam_principals = optional(map(string), {}) + locations = optional(map(string), {}) + kms_keys = optional(map(string), {}) + models = optional(map(string), {}) + networks = optional(map(string), {}) + project_ids = optional(map(string), {}) + psc_network_attachments = optional(map(string), {}) }) nullable = false default = {} diff --git a/tests/modules/agent_engine/examples/context.yaml b/tests/modules/agent_engine/examples/context.yaml new file mode 100644 index 000000000..8431d37c6 --- /dev/null +++ b/tests/modules/agent_engine/examples/context.yaml @@ -0,0 +1,63 @@ +# 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_vertex_ai_reasoning_engine.managed[0]: + context_spec: [] + deletion_policy: null + description: Terraform managed. + display_name: my-agent + encryption_spec: [] + project: test-project-1 + region: europe-west1 + spec: + - agent_framework: google-adk + class_methods: null + deployment_spec: + - env: [] + psc_interface_config: + - dns_peering_configs: + - domain: example.com + target_network: my-vpc-1 + target_project: test-project-1 + - domain: my-company.local + target_network: my-vpc-2 + target_project: company-dns-project + network_attachment: projects/test-project-1/regions/europe-west1/networkAttachments/core-service + secret_env: [] + identity_type: null + package_spec: [] + service_account: my-sa@$test-project-1.iam.gserviceaccount.com + source_code_spec: + - developer_connect_source: [] + inline_source: + - source_archive: H4sIAMCUSmkAA+1Y727bNhB3CwzbtM/b55v7oQmQyPprJyk8QE2y1ahrZ7HTriiKgJFom4skqhRV2yj6Hvu8PdL2AgP2CHuAHWXZiZP+C5C4WKsfQNjiHY+/I3l3og7I5AElARU1/VjQFxkTNKKxTHU5kZVrgmEYdceBSiMHVCy34Vo2qP4ZXAdM17Qs1eomGJZp160KTK6LwLuQpZIIpBJmPkkElfQteolgERHToeBZ8ib5zBNY/P5PYDqQsaC5ZWw5DUuzDYgki2jTbNTrzrbrGNt6fatuGbhljvaxuZa4ftxc1J9hHv+24dqGbVyKf8uxl+PfbNgNtwLG9VO5jM88/itffPdl5Xal8oj40O3BL1BA9VW+xmZhe4FNPf/xYSa9fv+w+KtG/Ibtmwsqt876v/V5pJMkCameCP6SxiT2aeXW7cpf//z+1b9/b/15DU6WeBsOFvX/5vLA++o/Bv3F+m869bL+rwJXqf9uA9qt+97h7oPW4319QqQU+puCt+n93PLMbo/tHvRH3c4jzdmGHg5qP33XoHMRX75prAw3X/3fX//Ni/FvNsy6Udb/VWDI+TCkm37Is2CTsCQkcsBF9IwM8UQc03jIYpo+/6Fp6qZl6IZW6JPgNO9zdVPLxybMPw1ps2nrSutje1XiQ3Fw7v6f77meTK97jivc/03LdVX8u65R1v9V4J3139natnXbMvA2ZrlbZVR/gri5qD/DFe7/Rfy7bt0u6/9KUN7/P2uc1f+bywNXuP/P679tO2X9XwWuUv/L+/+nh5uv/u+t/5btXIx/13adsv6vAne+r2WpqJ2wuEbjl5BM5YjHtqbdgV2eTAUbjiSoz3/wU37xh3Z7V7uD0jbzaZzSALIYiwfIEQUvIT7+FJINeExFyngMlm7AmlKoFqLq+j20MOUZRGQKMZeQpRRNsBQGDOegE58mElgMmCiSkKn0AGMmR/k0hREdTTwtTPATSVCboH6CT4PzekBkTlhhJGWS7tRq4/EY849iq3MxrIUzzbTWbu3ud3r7m8g4H3MUhzRNofhGFsDJFFTaYj45QZohGQMXQIaCokxyRXgsmGTxcANSPpBjIihaCVgqBTvJ5NJqzemh0+cVcL1IDFWvB61eFe57vVZvA208afUfdI/68MQ7PPQ6/dZ+D7qHsNvt7LX6rW4Hn34Er/MUHrY6extAca1wGjrBA438kSRT60gDtWg9SpcIDPiMUJpQnw2Yj37FwwzzAgwxN4sY3YGEioilajdTpBeglZBFTBKZ91xySte0geARzD4W6SQ41fM8kyoeXEhoh5GnOmZqOIukE8L0pY9Oc10vOPWSRNO0gA5gSFE+8UdIkR4LIumapjbWz4SgsT89VvZ2AJcTmlA96u1VN5blki+k+0eHF6UBGlzIQ3xIJaqs76BWQUYdBexNsQeXNuFqAZuLXh3pzQgBDKrz00YSpg8EiU8HGfopVOWrvVqa83VBBCAhgkRp85UGC1SVT9WdZR83zitIfl4seSF7rZTWc6YyE/GCsP5ryuO1dS0PckFxfvD2HkK++EWYcR6mmuBczm6H6OJ8x2buRTygYbM6pBGLGYaLuzkISToq3GAxLmHmq8PRrKoYxTjA4BzRMBlkIRA8SJh0Y1moxwRfOO4u+C+2N5/67kwnZ9R8dmn7n+P2aNqc5OyorOWPzTP66+X7RIkSJUpcwn+2Vos4ACgAAA== + python_spec: + - entrypoint_module: agent + entrypoint_object: agent + requirements_file: requirements.txt + version: '3.13' + timeouts: null + module.agent_engine.time_sleep.wait_5_minutes: + create_duration: 5m + destroy_duration: null + triggers: null + +counts: + google_vertex_ai_reasoning_engine: 1 + modules: 1 + resources: 2 + time_sleep: 1 + +outputs: {}