agent-starter-pack 0.7.0__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/METADATA +5 -5
- {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/RECORD +57 -55
- agents/README.md +7 -0
- agents/adk_base/notebooks/adk_app_testing.ipynb +8 -6
- agents/adk_base/template/.templateconfig.yaml +3 -1
- agents/adk_gemini_fullstack/notebooks/adk_app_testing.ipynb +8 -6
- agents/adk_gemini_fullstack/template/.templateconfig.yaml +2 -1
- agents/agentic_rag/notebooks/adk_app_testing.ipynb +8 -6
- agents/agentic_rag/template/.templateconfig.yaml +2 -1
- agents/crewai_coding_crew/template/.templateconfig.yaml +1 -1
- llm.txt +22 -9
- src/base_template/.gitignore +0 -1
- src/base_template/README.md +5 -2
- src/base_template/deployment/cd/deploy-to-prod.yaml +1 -16
- src/base_template/deployment/cd/staging.yaml +4 -19
- src/base_template/deployment/terraform/apis.tf +2 -2
- src/base_template/deployment/terraform/build_triggers.tf +5 -5
- src/base_template/deployment/terraform/dev/apis.tf +8 -1
- src/base_template/deployment/terraform/dev/variables.tf +3 -1
- src/base_template/deployment/terraform/iam.tf +8 -8
- src/base_template/deployment/terraform/locals.tf +9 -2
- src/base_template/deployment/terraform/log_sinks.tf +2 -2
- src/base_template/deployment/terraform/service_accounts.tf +3 -3
- src/base_template/deployment/terraform/storage.tf +7 -7
- src/base_template/deployment/terraform/variables.tf +3 -0
- src/base_template/pyproject.toml +4 -3
- src/cli/commands/create.py +38 -0
- src/cli/commands/setup_cicd.py +2 -2
- src/cli/utils/cicd.py +6 -3
- src/cli/utils/template.py +34 -9
- src/deployment_targets/agent_engine/app/agent_engine_app.py +7 -7
- src/deployment_targets/agent_engine/tests/load_test/README.md +1 -6
- src/deployment_targets/agent_engine/tests/load_test/load_test.py +13 -3
- src/deployment_targets/cloud_run/Dockerfile +3 -0
- src/deployment_targets/cloud_run/app/server.py +18 -0
- src/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +231 -0
- src/deployment_targets/cloud_run/deployment/terraform/service.tf +360 -0
- src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +8 -5
- src/deployment_targets/cloud_run/tests/load_test/README.md +2 -2
- src/deployment_targets/cloud_run/tests/load_test/load_test.py +21 -17
- src/frontends/adk_gemini_fullstack/frontend/src/App.tsx +2 -3
- src/resources/docs/adk-cheatsheet.md +1 -1
- src/resources/locks/uv-adk_base-agent_engine.lock +805 -200
- src/resources/locks/uv-adk_base-cloud_run.lock +1085 -234
- src/resources/locks/uv-adk_gemini_fullstack-agent_engine.lock +805 -200
- src/resources/locks/uv-adk_gemini_fullstack-cloud_run.lock +1085 -234
- src/resources/locks/uv-agentic_rag-agent_engine.lock +386 -283
- src/resources/locks/uv-agentic_rag-cloud_run.lock +513 -349
- src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +492 -497
- src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +671 -613
- src/resources/locks/uv-langgraph_base_react-agent_engine.lock +500 -391
- src/resources/locks/uv-langgraph_base_react-cloud_run.lock +682 -510
- src/resources/locks/uv-live_api-cloud_run.lock +686 -486
- src/resources/setup_cicd/github.tf +2 -2
- src/deployment_targets/cloud_run/uv.lock +0 -6952
- {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/WHEEL +0 -0
- {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/entry_points.txt +0 -0
- {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,231 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# Get project information to access the project number
|
16
|
+
data "google_project" "project" {
|
17
|
+
project_id = var.dev_project_id
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
22
|
+
|
23
|
+
# VPC Network for AlloyDB
|
24
|
+
resource "google_compute_network" "default" {
|
25
|
+
name = "${var.project_name}-alloydb-network"
|
26
|
+
project = var.dev_project_id
|
27
|
+
auto_create_subnetworks = false
|
28
|
+
depends_on = [resource.google_project_service.services]
|
29
|
+
}
|
30
|
+
|
31
|
+
# Subnet for AlloyDB
|
32
|
+
resource "google_compute_subnetwork" "default" {
|
33
|
+
name = "${var.project_name}-alloydb-network"
|
34
|
+
ip_cidr_range = "10.0.0.0/24"
|
35
|
+
region = var.region
|
36
|
+
network = google_compute_network.default.id
|
37
|
+
project = var.dev_project_id
|
38
|
+
|
39
|
+
# This is required for Cloud Run VPC connectors
|
40
|
+
purpose = "PRIVATE"
|
41
|
+
|
42
|
+
private_ip_google_access = true
|
43
|
+
}
|
44
|
+
|
45
|
+
# Private IP allocation for AlloyDB
|
46
|
+
resource "google_compute_global_address" "private_ip_alloc" {
|
47
|
+
name = "${var.project_name}-private-ip"
|
48
|
+
project = var.dev_project_id
|
49
|
+
address_type = "INTERNAL"
|
50
|
+
purpose = "VPC_PEERING"
|
51
|
+
prefix_length = 16
|
52
|
+
network = google_compute_network.default.id
|
53
|
+
|
54
|
+
depends_on = [resource.google_project_service.services]
|
55
|
+
}
|
56
|
+
|
57
|
+
# VPC connection for AlloyDB
|
58
|
+
resource "google_service_networking_connection" "vpc_connection" {
|
59
|
+
network = google_compute_network.default.id
|
60
|
+
service = "servicenetworking.googleapis.com"
|
61
|
+
reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name]
|
62
|
+
}
|
63
|
+
|
64
|
+
# AlloyDB Cluster
|
65
|
+
resource "google_alloydb_cluster" "session_db_cluster" {
|
66
|
+
project = var.dev_project_id
|
67
|
+
cluster_id = "${var.project_name}-alloydb-cluster"
|
68
|
+
location = var.region
|
69
|
+
|
70
|
+
network_config {
|
71
|
+
network = google_compute_network.default.id
|
72
|
+
}
|
73
|
+
|
74
|
+
depends_on = [
|
75
|
+
google_service_networking_connection.vpc_connection
|
76
|
+
]
|
77
|
+
}
|
78
|
+
|
79
|
+
# AlloyDB Instance
|
80
|
+
resource "google_alloydb_instance" "session_db_instance" {
|
81
|
+
cluster = google_alloydb_cluster.session_db_cluster.name
|
82
|
+
instance_id = "${var.project_name}-alloydb-instance"
|
83
|
+
instance_type = "PRIMARY"
|
84
|
+
|
85
|
+
availability_type = "REGIONAL" # Regional redundancy
|
86
|
+
|
87
|
+
machine_config {
|
88
|
+
cpu_count = 2
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
# Generate a random password for the database user
|
93
|
+
resource "random_password" "db_password" {
|
94
|
+
length = 16
|
95
|
+
special = true
|
96
|
+
override_special = "!#$%&*()-_=+[]{}<>:?"
|
97
|
+
}
|
98
|
+
|
99
|
+
# Store the password in Secret Manager
|
100
|
+
resource "google_secret_manager_secret" "db_password" {
|
101
|
+
project = var.dev_project_id
|
102
|
+
secret_id = "${var.project_name}-db-password"
|
103
|
+
|
104
|
+
replication {
|
105
|
+
auto {}
|
106
|
+
}
|
107
|
+
|
108
|
+
depends_on = [resource.google_project_service.services]
|
109
|
+
}
|
110
|
+
|
111
|
+
resource "google_secret_manager_secret_version" "db_password" {
|
112
|
+
secret = google_secret_manager_secret.db_password.id
|
113
|
+
secret_data = random_password.db_password.result
|
114
|
+
}
|
115
|
+
|
116
|
+
resource "google_alloydb_user" "db_user" {
|
117
|
+
cluster = google_alloydb_cluster.session_db_cluster.name
|
118
|
+
user_id = "postgres"
|
119
|
+
user_type = "ALLOYDB_BUILT_IN"
|
120
|
+
password = random_password.db_password.result
|
121
|
+
database_roles = ["alloydbsuperuser"]
|
122
|
+
|
123
|
+
depends_on = [google_alloydb_instance.session_db_instance]
|
124
|
+
}
|
125
|
+
|
126
|
+
{%- endif %}
|
127
|
+
|
128
|
+
|
129
|
+
resource "google_cloud_run_v2_service" "app" {
|
130
|
+
name = var.project_name
|
131
|
+
location = var.region
|
132
|
+
project = var.dev_project_id
|
133
|
+
deletion_protection = false
|
134
|
+
ingress = "INGRESS_TRAFFIC_ALL"
|
135
|
+
|
136
|
+
template {
|
137
|
+
containers {
|
138
|
+
image = "us-docker.pkg.dev/cloudrun/container/hello"
|
139
|
+
|
140
|
+
resources {
|
141
|
+
limits = {
|
142
|
+
cpu = "4"
|
143
|
+
memory = "8Gi"
|
144
|
+
}
|
145
|
+
}
|
146
|
+
{%- if cookiecutter.data_ingestion %}
|
147
|
+
{%- if cookiecutter.datastore_type == "vertex_ai_search" %}
|
148
|
+
|
149
|
+
env {
|
150
|
+
name = "DATA_STORE_ID"
|
151
|
+
value = resource.google_discovery_engine_data_store.data_store_dev.data_store_id
|
152
|
+
}
|
153
|
+
|
154
|
+
env {
|
155
|
+
name = "DATA_STORE_REGION"
|
156
|
+
value = var.data_store_region
|
157
|
+
}
|
158
|
+
{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
|
159
|
+
env {
|
160
|
+
name = "VECTOR_SEARCH_INDEX"
|
161
|
+
value = resource.google_vertex_ai_index.vector_search_index.id
|
162
|
+
}
|
163
|
+
|
164
|
+
env {
|
165
|
+
name = "VECTOR_SEARCH_INDEX_ENDPOINT"
|
166
|
+
value = resource.google_vertex_ai_index_endpoint.vector_search_index_endpoint.id
|
167
|
+
}
|
168
|
+
|
169
|
+
env {
|
170
|
+
name = "VECTOR_SEARCH_BUCKET"
|
171
|
+
value = "gs://${resource.google_storage_bucket.data_ingestion_PIPELINE_GCS_ROOT.name}"
|
172
|
+
}
|
173
|
+
{%- endif %}
|
174
|
+
{%- endif %}
|
175
|
+
|
176
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
177
|
+
|
178
|
+
env {
|
179
|
+
name = "DB_HOST"
|
180
|
+
value = google_alloydb_instance.session_db_instance.ip_address
|
181
|
+
}
|
182
|
+
|
183
|
+
env {
|
184
|
+
name = "DB_PASS"
|
185
|
+
value_source {
|
186
|
+
secret_key_ref {
|
187
|
+
secret = google_secret_manager_secret.db_password.secret_id
|
188
|
+
version = "latest"
|
189
|
+
}
|
190
|
+
}
|
191
|
+
}
|
192
|
+
{%- endif %}
|
193
|
+
}
|
194
|
+
|
195
|
+
service_account = google_service_account.cloud_run_app_sa.email
|
196
|
+
max_instance_request_concurrency = 40
|
197
|
+
|
198
|
+
scaling {
|
199
|
+
min_instance_count = 1
|
200
|
+
max_instance_count = 10
|
201
|
+
}
|
202
|
+
|
203
|
+
session_affinity = true
|
204
|
+
|
205
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
206
|
+
# VPC access for AlloyDB connectivity
|
207
|
+
vpc_access {
|
208
|
+
network_interfaces {
|
209
|
+
network = google_compute_network.default.id
|
210
|
+
subnetwork = google_compute_subnetwork.default.id
|
211
|
+
}
|
212
|
+
}
|
213
|
+
{%- endif %}
|
214
|
+
}
|
215
|
+
|
216
|
+
traffic {
|
217
|
+
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
|
218
|
+
percent = 100
|
219
|
+
}
|
220
|
+
|
221
|
+
# This lifecycle block prevents Terraform from overwriting the container image when it's
|
222
|
+
# updated by Cloud Run deployments outside of Terraform (e.g., via CI/CD pipelines)
|
223
|
+
lifecycle {
|
224
|
+
ignore_changes = [
|
225
|
+
template[0].containers[0].image,
|
226
|
+
]
|
227
|
+
}
|
228
|
+
|
229
|
+
# Make dependencies conditional to avoid errors.
|
230
|
+
depends_on = [resource.google_project_service.services]
|
231
|
+
}
|
@@ -0,0 +1,360 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# Get project information to access the project number
|
16
|
+
data "google_project" "project" {
|
17
|
+
for_each = local.deploy_project_ids
|
18
|
+
|
19
|
+
project_id = local.deploy_project_ids[each.key]
|
20
|
+
}
|
21
|
+
|
22
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
23
|
+
|
24
|
+
# VPC Network for AlloyDB
|
25
|
+
resource "google_compute_network" "default" {
|
26
|
+
for_each = local.deploy_project_ids
|
27
|
+
|
28
|
+
name = "${var.project_name}-alloydb-network"
|
29
|
+
project = local.deploy_project_ids[each.key]
|
30
|
+
auto_create_subnetworks = false
|
31
|
+
|
32
|
+
depends_on = [google_project_service.deploy_project_services]
|
33
|
+
}
|
34
|
+
|
35
|
+
# Subnet for AlloyDB
|
36
|
+
resource "google_compute_subnetwork" "default" {
|
37
|
+
for_each = local.deploy_project_ids
|
38
|
+
|
39
|
+
name = "${var.project_name}-alloydb-network"
|
40
|
+
ip_cidr_range = "10.0.0.0/24"
|
41
|
+
region = var.region
|
42
|
+
network = google_compute_network.default[each.key].id
|
43
|
+
project = local.deploy_project_ids[each.key]
|
44
|
+
|
45
|
+
# This is required for Cloud Run VPC connectors
|
46
|
+
purpose = "PRIVATE"
|
47
|
+
|
48
|
+
private_ip_google_access = true
|
49
|
+
}
|
50
|
+
|
51
|
+
# Private IP allocation for AlloyDB
|
52
|
+
resource "google_compute_global_address" "private_ip_alloc" {
|
53
|
+
for_each = local.deploy_project_ids
|
54
|
+
|
55
|
+
name = "${var.project_name}-private-ip"
|
56
|
+
project = local.deploy_project_ids[each.key]
|
57
|
+
address_type = "INTERNAL"
|
58
|
+
purpose = "VPC_PEERING"
|
59
|
+
prefix_length = 16
|
60
|
+
network = google_compute_network.default[each.key].id
|
61
|
+
|
62
|
+
depends_on = [google_project_service.deploy_project_services]
|
63
|
+
}
|
64
|
+
|
65
|
+
# VPC connection for AlloyDB
|
66
|
+
resource "google_service_networking_connection" "vpc_connection" {
|
67
|
+
for_each = local.deploy_project_ids
|
68
|
+
|
69
|
+
network = google_compute_network.default[each.key].id
|
70
|
+
service = "servicenetworking.googleapis.com"
|
71
|
+
reserved_peering_ranges = [google_compute_global_address.private_ip_alloc[each.key].name]
|
72
|
+
}
|
73
|
+
|
74
|
+
# AlloyDB Cluster
|
75
|
+
resource "google_alloydb_cluster" "session_db_cluster" {
|
76
|
+
for_each = local.deploy_project_ids
|
77
|
+
|
78
|
+
project = local.deploy_project_ids[each.key]
|
79
|
+
cluster_id = "${var.project_name}-alloydb-cluster"
|
80
|
+
location = var.region
|
81
|
+
|
82
|
+
network_config {
|
83
|
+
network = google_compute_network.default[each.key].id
|
84
|
+
}
|
85
|
+
|
86
|
+
depends_on = [
|
87
|
+
google_service_networking_connection.vpc_connection
|
88
|
+
]
|
89
|
+
}
|
90
|
+
|
91
|
+
# AlloyDB Instance
|
92
|
+
resource "google_alloydb_instance" "session_db_instance" {
|
93
|
+
for_each = local.deploy_project_ids
|
94
|
+
|
95
|
+
cluster = google_alloydb_cluster.session_db_cluster[each.key].name
|
96
|
+
instance_id = "${var.project_name}-alloydb-instance"
|
97
|
+
instance_type = "PRIMARY"
|
98
|
+
|
99
|
+
availability_type = "REGIONAL" # Regional redundancy
|
100
|
+
|
101
|
+
machine_config {
|
102
|
+
cpu_count = 2
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
# Generate a random password for the database user
|
107
|
+
resource "random_password" "db_password" {
|
108
|
+
for_each = local.deploy_project_ids
|
109
|
+
|
110
|
+
length = 16
|
111
|
+
special = true
|
112
|
+
override_special = "!#$%&*()-_=+[]{}<>:?"
|
113
|
+
}
|
114
|
+
|
115
|
+
# Store the password in Secret Manager
|
116
|
+
resource "google_secret_manager_secret" "db_password" {
|
117
|
+
for_each = local.deploy_project_ids
|
118
|
+
|
119
|
+
project = local.deploy_project_ids[each.key]
|
120
|
+
secret_id = "${var.project_name}-db-password"
|
121
|
+
|
122
|
+
replication {
|
123
|
+
auto {}
|
124
|
+
}
|
125
|
+
|
126
|
+
depends_on = [google_project_service.deploy_project_services]
|
127
|
+
}
|
128
|
+
|
129
|
+
resource "google_secret_manager_secret_version" "db_password" {
|
130
|
+
for_each = local.deploy_project_ids
|
131
|
+
|
132
|
+
secret = google_secret_manager_secret.db_password[each.key].id
|
133
|
+
secret_data = random_password.db_password[each.key].result
|
134
|
+
}
|
135
|
+
|
136
|
+
resource "google_alloydb_user" "db_user" {
|
137
|
+
for_each = local.deploy_project_ids
|
138
|
+
|
139
|
+
cluster = google_alloydb_cluster.session_db_cluster[each.key].name
|
140
|
+
user_id = "postgres"
|
141
|
+
user_type = "ALLOYDB_BUILT_IN"
|
142
|
+
password = random_password.db_password[each.key].result
|
143
|
+
database_roles = ["alloydbsuperuser"]
|
144
|
+
|
145
|
+
depends_on = [google_alloydb_instance.session_db_instance]
|
146
|
+
}
|
147
|
+
|
148
|
+
{%- endif %}
|
149
|
+
|
150
|
+
resource "google_cloud_run_v2_service" "app_staging" {
|
151
|
+
name = var.project_name
|
152
|
+
location = var.region
|
153
|
+
project = var.staging_project_id
|
154
|
+
deletion_protection = false
|
155
|
+
ingress = "INGRESS_TRAFFIC_ALL"
|
156
|
+
|
157
|
+
template {
|
158
|
+
containers {
|
159
|
+
# Placeholder, will be replaced by the CI/CD pipeline
|
160
|
+
image = "us-docker.pkg.dev/cloudrun/container/hello"
|
161
|
+
|
162
|
+
resources {
|
163
|
+
limits = {
|
164
|
+
cpu = "4"
|
165
|
+
memory = "8Gi"
|
166
|
+
}
|
167
|
+
cpu_idle = false
|
168
|
+
}
|
169
|
+
{%- if cookiecutter.data_ingestion %}
|
170
|
+
{%- if cookiecutter.datastore_type == "vertex_ai_search" %}
|
171
|
+
|
172
|
+
env {
|
173
|
+
name = "DATA_STORE_ID"
|
174
|
+
value = resource.google_discovery_engine_data_store.data_store_staging.data_store_id
|
175
|
+
}
|
176
|
+
|
177
|
+
env {
|
178
|
+
name = "DATA_STORE_REGION"
|
179
|
+
value = var.data_store_region
|
180
|
+
}
|
181
|
+
{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
|
182
|
+
env {
|
183
|
+
name = "VECTOR_SEARCH_INDEX"
|
184
|
+
value = resource.google_vertex_ai_index.vector_search_index_staging.id
|
185
|
+
}
|
186
|
+
|
187
|
+
env {
|
188
|
+
name = "VECTOR_SEARCH_INDEX_ENDPOINT"
|
189
|
+
value = resource.google_vertex_ai_index_endpoint.vector_search_index_endpoint_staging.id
|
190
|
+
}
|
191
|
+
|
192
|
+
env {
|
193
|
+
name = "VECTOR_SEARCH_BUCKET"
|
194
|
+
value = resource.google_storage_bucket.vector_search_data_bucket["staging"].url
|
195
|
+
}
|
196
|
+
{%- endif %}
|
197
|
+
{%- endif %}
|
198
|
+
|
199
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
200
|
+
|
201
|
+
env {
|
202
|
+
name = "DB_HOST"
|
203
|
+
value = google_alloydb_instance.session_db_instance["staging"].ip_address
|
204
|
+
}
|
205
|
+
|
206
|
+
env {
|
207
|
+
name = "DB_PASS"
|
208
|
+
value_source {
|
209
|
+
secret_key_ref {
|
210
|
+
secret = google_secret_manager_secret.db_password["staging"].secret_id
|
211
|
+
version = "latest"
|
212
|
+
}
|
213
|
+
}
|
214
|
+
}
|
215
|
+
{%- endif %}
|
216
|
+
}
|
217
|
+
|
218
|
+
service_account = google_service_account.cloud_run_app_sa["staging"].email
|
219
|
+
max_instance_request_concurrency = 40
|
220
|
+
|
221
|
+
scaling {
|
222
|
+
min_instance_count = 1
|
223
|
+
max_instance_count = 10
|
224
|
+
}
|
225
|
+
|
226
|
+
session_affinity = true
|
227
|
+
|
228
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
229
|
+
# VPC access for AlloyDB connectivity
|
230
|
+
vpc_access {
|
231
|
+
network_interfaces {
|
232
|
+
network = google_compute_network.default["staging"].id
|
233
|
+
subnetwork = google_compute_subnetwork.default["staging"].id
|
234
|
+
}
|
235
|
+
}
|
236
|
+
{%- endif %}
|
237
|
+
}
|
238
|
+
|
239
|
+
traffic {
|
240
|
+
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
|
241
|
+
percent = 100
|
242
|
+
}
|
243
|
+
|
244
|
+
# This lifecycle block prevents Terraform from overwriting the container image when it's
|
245
|
+
# updated by Cloud Run deployments outside of Terraform (e.g., via CI/CD pipelines)
|
246
|
+
lifecycle {
|
247
|
+
ignore_changes = [
|
248
|
+
template[0].containers[0].image,
|
249
|
+
]
|
250
|
+
}
|
251
|
+
|
252
|
+
# Make dependencies conditional to avoid errors.
|
253
|
+
depends_on = [google_project_service.deploy_project_services]
|
254
|
+
}
|
255
|
+
|
256
|
+
resource "google_cloud_run_v2_service" "app_prod" {
|
257
|
+
name = var.project_name
|
258
|
+
location = var.region
|
259
|
+
project = var.prod_project_id
|
260
|
+
deletion_protection = false
|
261
|
+
ingress = "INGRESS_TRAFFIC_ALL"
|
262
|
+
|
263
|
+
template {
|
264
|
+
containers {
|
265
|
+
# Placeholder, will be replaced by the CI/CD pipeline
|
266
|
+
image = "us-docker.pkg.dev/cloudrun/container/hello"
|
267
|
+
|
268
|
+
resources {
|
269
|
+
limits = {
|
270
|
+
cpu = "4"
|
271
|
+
memory = "8Gi"
|
272
|
+
}
|
273
|
+
cpu_idle = false
|
274
|
+
}
|
275
|
+
{%- if cookiecutter.data_ingestion %}
|
276
|
+
{%- if cookiecutter.datastore_type == "vertex_ai_search" %}
|
277
|
+
|
278
|
+
env {
|
279
|
+
name = "DATA_STORE_ID"
|
280
|
+
value = resource.google_discovery_engine_data_store.data_store_prod.data_store_id
|
281
|
+
}
|
282
|
+
|
283
|
+
env {
|
284
|
+
name = "DATA_STORE_REGION"
|
285
|
+
value = var.data_store_region
|
286
|
+
}
|
287
|
+
{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
|
288
|
+
env {
|
289
|
+
name = "VECTOR_SEARCH_INDEX"
|
290
|
+
value = resource.google_vertex_ai_index.vector_search_index_prod.id
|
291
|
+
}
|
292
|
+
|
293
|
+
env {
|
294
|
+
name = "VECTOR_SEARCH_INDEX_ENDPOINT"
|
295
|
+
value = resource.google_vertex_ai_index_endpoint.vector_search_index_endpoint_prod.id
|
296
|
+
}
|
297
|
+
|
298
|
+
env {
|
299
|
+
name = "VECTOR_SEARCH_BUCKET"
|
300
|
+
value = resource.google_storage_bucket.vector_search_data_bucket["prod"].url
|
301
|
+
}
|
302
|
+
{%- endif %}
|
303
|
+
{%- endif %}
|
304
|
+
|
305
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
306
|
+
|
307
|
+
env {
|
308
|
+
name = "DB_HOST"
|
309
|
+
value = google_alloydb_instance.session_db_instance["prod"].ip_address
|
310
|
+
}
|
311
|
+
|
312
|
+
env {
|
313
|
+
name = "DB_PASS"
|
314
|
+
value_source {
|
315
|
+
secret_key_ref {
|
316
|
+
secret = google_secret_manager_secret.db_password["prod"].secret_id
|
317
|
+
version = "latest"
|
318
|
+
}
|
319
|
+
}
|
320
|
+
}
|
321
|
+
{%- endif %}
|
322
|
+
}
|
323
|
+
|
324
|
+
service_account = google_service_account.cloud_run_app_sa["prod"].email
|
325
|
+
max_instance_request_concurrency = 40
|
326
|
+
|
327
|
+
scaling {
|
328
|
+
min_instance_count = 1
|
329
|
+
max_instance_count = 10
|
330
|
+
}
|
331
|
+
|
332
|
+
session_affinity = true
|
333
|
+
|
334
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
335
|
+
# VPC access for AlloyDB connectivity
|
336
|
+
vpc_access {
|
337
|
+
network_interfaces {
|
338
|
+
network = google_compute_network.default["prod"].id
|
339
|
+
subnetwork = google_compute_subnetwork.default["prod"].id
|
340
|
+
}
|
341
|
+
}
|
342
|
+
{%- endif %}
|
343
|
+
}
|
344
|
+
|
345
|
+
traffic {
|
346
|
+
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
|
347
|
+
percent = 100
|
348
|
+
}
|
349
|
+
|
350
|
+
# This lifecycle block prevents Terraform from overwriting the container image when it's
|
351
|
+
# updated by Cloud Run deployments outside of Terraform (e.g., via CI/CD pipelines)
|
352
|
+
lifecycle {
|
353
|
+
ignore_changes = [
|
354
|
+
template[0].containers[0].image,
|
355
|
+
]
|
356
|
+
}
|
357
|
+
|
358
|
+
# Make dependencies conditional to avoid errors.
|
359
|
+
depends_on = [google_project_service.deploy_project_services]
|
360
|
+
}
|
@@ -122,16 +122,19 @@ def test_chat_stream(server_fixture: subprocess.Popen[str]) -> None:
|
|
122
122
|
logger.info("Starting chat stream test")
|
123
123
|
{% if "adk" in cookiecutter.tags %}
|
124
124
|
# Create session first
|
125
|
-
user_id = "
|
126
|
-
|
127
|
-
|
125
|
+
user_id = "test_user_123"
|
126
|
+
session_data = {"state": {"preferred_language": "English", "visit_count": 1}}
|
127
|
+
|
128
|
+
session_url = f"{BASE_URL}/apps/app/users/{user_id}/sessions"
|
128
129
|
session_response = requests.post(
|
129
|
-
|
130
|
+
session_url,
|
130
131
|
headers=HEADERS,
|
131
132
|
json=session_data,
|
132
|
-
timeout=
|
133
|
+
timeout=60,
|
133
134
|
)
|
134
135
|
assert session_response.status_code == 200
|
136
|
+
logger.info(f"Session creation response: {session_response.json()}")
|
137
|
+
session_id = session_response.json()["id"]
|
135
138
|
|
136
139
|
# Then send chat message
|
137
140
|
data = {
|
@@ -18,7 +18,7 @@ uv run uvicorn app.server:app --host 0.0.0.0 --port 8000 --reload
|
|
18
18
|
Using another terminal tab, This is suggested to avoid conflicts with the existing application python environment.
|
19
19
|
|
20
20
|
```bash
|
21
|
-
python3 -m venv .locust_env && source locust_env/bin/activate && pip install locust==2.31.1
|
21
|
+
python3 -m venv .locust_env && source .locust_env/bin/activate && pip install locust==2.31.1
|
22
22
|
```
|
23
23
|
|
24
24
|
**3. Execute the Load Test:**
|
@@ -69,7 +69,7 @@ export _ID_TOKEN=$(gcloud auth print-identity-token -q)
|
|
69
69
|
**3. Execute the Load Test:**
|
70
70
|
Create virtual environment with Locust:
|
71
71
|
```bash
|
72
|
-
python3 -m venv .locust_env && source locust_env/bin/activate && pip install locust==2.31.1
|
72
|
+
python3 -m venv .locust_env && source .locust_env/bin/activate && pip install locust==2.31.1
|
73
73
|
```
|
74
74
|
|
75
75
|
Execute load tests. The following command executes the same load test parameters as the local test but targets your remote Cloud Run instance.
|