diff --git a/.gitignore b/.gitignore index 9be78d1..8aa620b 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ coverage.xml .terraform firestore-credentials.json + +# Deployment +function-source.zip diff --git a/deployment/cloud-function/README.md b/deployment/cloud-function/README.md new file mode 100644 index 0000000..7303c8b --- /dev/null +++ b/deployment/cloud-function/README.md @@ -0,0 +1,66 @@ +# Cloud Function for Image Processing + +This directory contains the source code for the Cloud Function that processes image embeddings. + +## Deployment + +**Note: This Cloud Function is now deployed via Terraform, not the previous bash script.** + +The Cloud Function is automatically deployed when you run: + +```bash +cd deployment/terraform +terraform apply +``` + +## What the Cloud Function Does + +1. **Triggered by Pub/Sub**: Listens to the `image-processing-topic` for new image processing tasks +2. **Downloads Images**: Retrieves images from Google Cloud Storage +3. **Generates Embeddings**: Uses Google Cloud Vision API to create image embeddings +4. **Stores Vectors**: Saves embeddings to the Qdrant vector database +5. **Updates Status**: Updates Firestore with processing status and embedding metadata + +## Environment Variables + +The following environment variables are automatically configured by Terraform: + +- `QDRANT_HOST`: IP address of the vector database VM +- `QDRANT_PORT`: Port for Qdrant (default: 6333) +- `QDRANT_API_KEY`: API key for Qdrant authentication +- `QDRANT_COLLECTION`: Collection name for storing vectors (default: image_vectors) + +## Function Configuration + +- **Runtime**: Python 3.11 +- **Memory**: 512MB +- **Timeout**: 540 seconds (9 minutes) +- **Max Instances**: 10 +- **Min Instances**: 0 (scales to zero when not in use) +- **Retry Policy**: Automatic retries on failure + +## Dependencies + +See `requirements.txt` for the complete list of Python dependencies. + +## Monitoring + +The function automatically logs to Google Cloud Logging. You can monitor: + +- Function executions +- Error rates +- Processing times +- Pub/Sub message handling + +## Manual Testing + +To manually trigger the function, publish a message to the Pub/Sub topic: + +```json +{ + "image_id": "test-image-123", + "storage_path": "your-bucket/path/to/image.jpg", + "team_id": "team-456", + "retry_count": 0 +} +``` \ No newline at end of file diff --git a/deployment/cloud-function/deploy.sh b/deployment/cloud-function/deploy.sh deleted file mode 100644 index 2223a52..0000000 --- a/deployment/cloud-function/deploy.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash - -# Cloud Function deployment script for image processing - -set -e - -# Configuration -PROJECT_ID=${GOOGLE_CLOUD_PROJECT:-"your-project-id"} -FUNCTION_NAME="process-image-embedding" -REGION=${REGION:-"us-central1"} -PUBSUB_TOPIC=${PUBSUB_TOPIC:-"image-processing-topic"} -MEMORY=${MEMORY:-"512MB"} -TIMEOUT=${TIMEOUT:-"540s"} - -# Environment variables for the function -QDRANT_HOST=${QDRANT_HOST:-""} -QDRANT_PORT=${QDRANT_PORT:-"6333"} -QDRANT_API_KEY=${QDRANT_API_KEY:-""} -QDRANT_COLLECTION=${QDRANT_COLLECTION:-"image_vectors"} - -echo "Deploying Cloud Function: $FUNCTION_NAME" -echo "Project: $PROJECT_ID" -echo "Region: $REGION" -echo "Pub/Sub Topic: $PUBSUB_TOPIC" - -# Check if required environment variables are set -if [ -z "$QDRANT_HOST" ]; then - echo "Warning: QDRANT_HOST not set. Function will not store embeddings." - echo "Please set QDRANT_HOST to your vector database VM's external IP address." -fi - -# Deploy the function -gcloud functions deploy $FUNCTION_NAME \ - --gen2 \ - --runtime=python311 \ - --region=$REGION \ - --source=. \ - --entry-point=process_image_embedding \ - --trigger-topic=$PUBSUB_TOPIC \ - --memory=$MEMORY \ - --timeout=$TIMEOUT \ - --set-env-vars="QDRANT_HOST=$QDRANT_HOST,QDRANT_PORT=$QDRANT_PORT,QDRANT_API_KEY=$QDRANT_API_KEY,QDRANT_COLLECTION=$QDRANT_COLLECTION" \ - --retry \ - --max-instances=10 \ - --min-instances=0 - -echo "Cloud Function deployed successfully!" -echo "Function name: $FUNCTION_NAME" -echo "Trigger: Pub/Sub topic '$PUBSUB_TOPIC'" -echo "Region: $REGION" -echo "Qdrant Host: $QDRANT_HOST" - -# Set up retry policy for the Pub/Sub subscription -SUBSCRIPTION_NAME="${PUBSUB_TOPIC}-subscription" - -echo "Configuring retry policy for subscription: $SUBSCRIPTION_NAME" - -# Check if subscription exists, create if not -if ! gcloud pubsub subscriptions describe $SUBSCRIPTION_NAME --project=$PROJECT_ID >/dev/null 2>&1; then - echo "Creating Pub/Sub subscription: $SUBSCRIPTION_NAME" - gcloud pubsub subscriptions create $SUBSCRIPTION_NAME \ - --topic=$PUBSUB_TOPIC \ - --project=$PROJECT_ID -fi - -# Update subscription with retry policy (max 3 retries) -gcloud pubsub subscriptions update $SUBSCRIPTION_NAME \ - --max-retry-delay=600s \ - --min-retry-delay=10s \ - --max-delivery-attempts=3 \ - --project=$PROJECT_ID - -echo "Retry policy configured: max 3 delivery attempts" -echo "Deployment complete!" \ No newline at end of file diff --git a/deployment/terraform/.terraform.lock.hcl b/deployment/terraform/.terraform.lock.hcl index c26d39f..28129ba 100644 --- a/deployment/terraform/.terraform.lock.hcl +++ b/deployment/terraform/.terraform.lock.hcl @@ -1,6 +1,25 @@ # This file is maintained automatically by "terraform init". # Manual edits may be lost in future updates. +provider "registry.terraform.io/hashicorp/archive" { + version = "2.7.1" + hashes = [ + "h1:RzToQiFwVaxcV0QmgbyaKgNOhqc6oLKiFyZTrQSGcog=", + "zh:19881bb356a4a656a865f48aee70c0b8a03c35951b7799b6113883f67f196e8e", + "zh:2fcfbf6318dd514863268b09bbe19bfc958339c636bcbcc3664b45f2b8bf5cc6", + "zh:3323ab9a504ce0a115c28e64d0739369fe85151291a2ce480d51ccbb0c381ac5", + "zh:362674746fb3da3ab9bd4e70c75a3cdd9801a6cf258991102e2c46669cf68e19", + "zh:7140a46d748fdd12212161445c46bbbf30a3f4586c6ac97dd497f0c2565fe949", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:875e6ce78b10f73b1efc849bfcc7af3a28c83a52f878f503bb22776f71d79521", + "zh:b872c6ed24e38428d817ebfb214da69ea7eefc2c38e5a774db2ccd58e54d3a22", + "zh:cd6a44f731c1633ae5d37662af86e7b01ae4c96eb8b04144255824c3f350392d", + "zh:e0600f5e8da12710b0c52d6df0ba147a5486427c1a2cc78f31eea37a47ee1b07", + "zh:f21b2e2563bbb1e44e73557bcd6cdbc1ceb369d471049c40eb56cb84b6317a60", + "zh:f752829eba1cc04a479cf7ae7271526b402e206d5bcf1fcce9f535de5ff9e4e6", + ] +} + provider "registry.terraform.io/hashicorp/google" { version = "6.36.1" hashes = [ diff --git a/deployment/terraform/README.md b/deployment/terraform/README.md index b4ec200..523908f 100644 --- a/deployment/terraform/README.md +++ b/deployment/terraform/README.md @@ -3,9 +3,12 @@ This directory contains Terraform configurations to provision the required Google Cloud resources for Sereact: - Google Cloud Run service +- Google Cloud Function for image processing - Google Container Registry (GCR) - Firestore database - Cloud Storage bucket +- Pub/Sub topics and subscriptions +- Qdrant vector database VM ## Prerequisites @@ -22,8 +25,53 @@ This directory contains Terraform configurations to provision the required Googl gcloud config set project PROJECT_ID ``` +## Architecture Overview + +The infrastructure includes: +- **Cloud Run Service**: Main application service +- **Cloud Function**: Image processing and embedding generation +- **Qdrant VM**: Vector database running on Compute Engine +- **Firestore**: Document database +- **Cloud Storage**: File storage +- **Pub/Sub**: Message queue for asynchronous image processing +- **Automatic IP Configuration**: Qdrant VM IP is automatically passed to Cloud Run and Cloud Function + +## Cloud Function Integration + +The Cloud Function is now fully integrated into Terraform and handles: + +1. **Image Processing**: Triggered by Pub/Sub messages +2. **Embedding Generation**: Uses Google Cloud Vision API +3. **Vector Storage**: Stores embeddings in Qdrant +4. **Status Updates**: Updates Firestore with processing results + +### Automatic Configuration + +The Cloud Function is automatically configured with: +- **Qdrant Connection**: VM IP address passed as environment variable +- **IAM Permissions**: Firestore, Storage, and Vision API access +- **Retry Policy**: Automatic retries on failure +- **Scaling**: 0-10 instances based on demand + ## Setup and Usage +### Option 1: Automated Deployment (Recommended) + +Use the provided script that handles API enablement and proper deployment order: + +```bash +cd deployment/terraform +./deploy-with-apis.sh +``` + +This script will: +1. Enable all required APIs +2. Wait for API propagation +3. Deploy infrastructure in the correct order +4. Handle Cloud Functions v2 dependencies + +### Option 2: Manual Deployment + 1. Copy the example variables file and edit it with your values: ```bash cp terraform.tfvars.example terraform.tfvars @@ -35,16 +83,33 @@ This directory contains Terraform configurations to provision the required Googl terraform init ``` -3. Preview the changes: +3. Enable APIs first (required for Cloud Functions v2): ```bash - terraform plan + terraform apply -target=google_project_service.services ``` -4. Apply the configuration: +4. Wait for APIs to propagate (2-3 minutes), then deploy everything: ```bash terraform apply ``` +## Required APIs + +The following APIs are automatically enabled by Terraform: + +- `cloudresourcemanager.googleapis.com` - Resource management +- `containerregistry.googleapis.com` - Container Registry +- `run.googleapis.com` - Cloud Run +- `firestore.googleapis.com` - Firestore database +- `storage.googleapis.com` - Cloud Storage +- `compute.googleapis.com` - Compute Engine (for Qdrant VM) +- `cloudfunctions.googleapis.com` - Cloud Functions +- `cloudbuild.googleapis.com` - Cloud Build (for function deployment) +- `eventarc.googleapis.com` - Eventarc (required for Cloud Functions v2) +- `pubsub.googleapis.com` - Pub/Sub messaging + +**Note**: If you get an Eventarc API error, use the automated deployment script or wait 2-3 minutes after enabling APIs before deploying the Cloud Function. + 5. After provisioning, you'll see outputs including: - Cloud Run service URL - Storage bucket name diff --git a/deployment/terraform/cloud-function.tf b/deployment/terraform/cloud-function.tf new file mode 100644 index 0000000..d531ffc --- /dev/null +++ b/deployment/terraform/cloud-function.tf @@ -0,0 +1,113 @@ +# Create a Cloud Storage bucket for Cloud Function source code +resource "google_storage_bucket" "function_source" { + name = "${var.project_id}-cloud-function-source" + location = var.region + uniform_bucket_level_access = true + + depends_on = [google_project_service.services] +} + +# Create a ZIP archive of the Cloud Function source code +data "archive_file" "function_source" { + type = "zip" + output_path = "${path.module}/function-source.zip" + source_dir = "${path.module}/../cloud-function" +} + +# Upload the ZIP file to Cloud Storage +resource "google_storage_bucket_object" "function_source" { + name = "function-source-${data.archive_file.function_source.output_md5}.zip" + bucket = google_storage_bucket.function_source.name + source = data.archive_file.function_source.output_path +} + +# Create the Cloud Function +resource "google_cloudfunctions2_function" "image_processor" { + name = "process-image-embedding" + location = var.region + description = "Process image embeddings and store in vector database" + + build_config { + runtime = "python311" + entry_point = "process_image_embedding" + + source { + storage_source { + bucket = google_storage_bucket.function_source.name + object = google_storage_bucket_object.function_source.name + } + } + } + + service_config { + max_instance_count = 10 + min_instance_count = 0 + available_memory = "512M" + timeout_seconds = 540 + + environment_variables = { + QDRANT_HOST = google_compute_instance.vector_db_vm.network_interface[0].access_config[0].nat_ip + QDRANT_PORT = "6333" + QDRANT_API_KEY = var.qdrant_api_key + QDRANT_COLLECTION = "image_vectors" + } + + service_account_email = local.cloud_function_service_account + } + + event_trigger { + trigger_region = var.region + event_type = "google.cloud.pubsub.topic.v1.messagePublished" + pubsub_topic = google_pubsub_topic.image_processing.id + retry_policy = "RETRY_POLICY_RETRY" + } + + depends_on = [ + google_project_service.services, + google_compute_instance.vector_db_vm, + google_pubsub_topic.image_processing + ] +} + +# Grant the Cloud Function service account necessary permissions +resource "google_project_iam_member" "function_firestore" { + project = var.project_id + role = "roles/datastore.user" + member = "serviceAccount:${local.cloud_function_service_account}" +} + +resource "google_project_iam_member" "function_storage" { + project = var.project_id + role = "roles/storage.objectViewer" + member = "serviceAccount:${local.cloud_function_service_account}" +} + +resource "google_project_iam_member" "function_vision" { + project = var.project_id + role = "roles/ml.developer" + member = "serviceAccount:${local.cloud_function_service_account}" +} + +# Additional permissions required for Cloud Functions v2 with Eventarc +resource "google_project_iam_member" "function_eventarc_receiver" { + project = var.project_id + role = "roles/eventarc.eventReceiver" + member = "serviceAccount:${local.cloud_function_service_account}" +} + +resource "google_project_iam_member" "function_pubsub_subscriber" { + project = var.project_id + role = "roles/pubsub.subscriber" + member = "serviceAccount:${local.cloud_function_service_account}" +} + +# Output the Cloud Function details +output "cloud_function_name" { + description = "Name of the deployed Cloud Function" + value = google_cloudfunctions2_function.image_processor.name +} + +output "cloud_function_url" { + description = "URL of the deployed Cloud Function" + value = google_cloudfunctions2_function.image_processor.service_config[0].uri +} \ No newline at end of file diff --git a/deployment/terraform/deploy-with-apis.sh b/deployment/terraform/deploy-with-apis.sh new file mode 100644 index 0000000..47d9edf --- /dev/null +++ b/deployment/terraform/deploy-with-apis.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# Deployment script that ensures APIs are enabled before deploying Cloud Functions +set -e + +echo "🚀 Starting Terraform deployment with API enablement..." + +# Get project ID from terraform.tfvars or environment +PROJECT_ID=${GOOGLE_CLOUD_PROJECT:-$(grep 'project_id' terraform.tfvars | cut -d'"' -f2)} + +if [ -z "$PROJECT_ID" ]; then + echo "❌ Error: PROJECT_ID not found. Set GOOGLE_CLOUD_PROJECT or ensure terraform.tfvars has project_id" + exit 1 +fi + +echo "📋 Project ID: $PROJECT_ID" + +# Step 1: Enable APIs first +echo "🔧 Step 1: Enabling required APIs..." +terraform apply -target=google_project_service.services -auto-approve + +# Step 2: Wait for APIs to propagate +echo "⏳ Step 2: Waiting for APIs to propagate (30 seconds)..." +sleep 30 + +# Step 3: Verify critical APIs are enabled +echo "✅ Step 3: Verifying API enablement..." +REQUIRED_APIS=( + "cloudfunctions.googleapis.com" + "eventarc.googleapis.com" + "pubsub.googleapis.com" + "cloudbuild.googleapis.com" +) + +for api in "${REQUIRED_APIS[@]}"; do + echo " Checking $api..." + if gcloud services list --enabled --project="$PROJECT_ID" --filter="name:$api" --format="value(name)" | grep -q "$api"; then + echo " ✅ $api is enabled" + else + echo " ❌ $api is not enabled yet, waiting longer..." + sleep 15 + fi +done + +# Step 4: Deploy infrastructure +echo "🏗️ Step 4: Deploying infrastructure..." +terraform apply -target=google_storage_bucket.app_bucket -target=google_firestore_database.database -target=google_compute_instance.vector_db_vm -auto-approve + +# Step 5: Deploy Pub/Sub resources +echo "📨 Step 5: Deploying Pub/Sub resources..." +terraform apply -target=google_pubsub_topic.image_processing -target=google_pubsub_topic.image_processing_dlq -auto-approve + +# Step 6: Deploy Cloud Function +echo "⚡ Step 6: Deploying Cloud Function..." +terraform apply -target=google_cloudfunctions2_function.image_processor -auto-approve + +# Step 7: Deploy remaining resources +echo "🎯 Step 7: Deploying remaining resources..." +terraform apply -auto-approve + +echo "🎉 Deployment completed successfully!" +echo "" +echo "📊 Deployment Summary:" +terraform output deployment_summary 2>/dev/null || echo " Run 'terraform output' to see all outputs" \ No newline at end of file diff --git a/deployment/terraform/main.tf b/deployment/terraform/main.tf index c884962..40fefbc 100644 --- a/deployment/terraform/main.tf +++ b/deployment/terraform/main.tf @@ -17,7 +17,11 @@ resource "google_project_service" "services" { "run.googleapis.com", "firestore.googleapis.com", "storage.googleapis.com", - "compute.googleapis.com" + "compute.googleapis.com", + "cloudfunctions.googleapis.com", + "cloudbuild.googleapis.com", + "eventarc.googleapis.com", + "pubsub.googleapis.com" ]) project = var.project_id diff --git a/deployment/terraform/pubsub.tf b/deployment/terraform/pubsub.tf index 87cdc2a..76247f1 100644 --- a/deployment/terraform/pubsub.tf +++ b/deployment/terraform/pubsub.tf @@ -15,37 +15,6 @@ resource "google_pubsub_topic" "image_processing" { } } -# Pub/Sub subscription with retry policy -resource "google_pubsub_subscription" "image_processing" { - name = "${var.pubsub_topic_name}-subscription" - topic = google_pubsub_topic.image_processing.name - - # Retry policy configuration - retry_policy { - minimum_backoff = "10s" - maximum_backoff = "600s" - } - - # Dead letter policy after 5 failed attempts - dead_letter_policy { - dead_letter_topic = google_pubsub_topic.image_processing_dlq.id - max_delivery_attempts = 5 - } - - # Message retention - message_retention_duration = "604800s" # 7 days - retain_acked_messages = false - - # Acknowledgment deadline - ack_deadline_seconds = 600 # 10 minutes - - labels = { - environment = var.environment - service = "sereact" - component = "image-processing" - } -} - # Dead letter queue for failed messages resource "google_pubsub_topic" "image_processing_dlq" { name = "${var.pubsub_topic_name}-dlq" @@ -73,7 +42,7 @@ resource "google_pubsub_subscription" "image_processing_dlq" { } } -# IAM binding for Cloud Function to publish to topic +# IAM binding for Cloud Run to publish to topic resource "google_pubsub_topic_iam_binding" "image_processing_publisher" { topic = google_pubsub_topic.image_processing.name role = "roles/pubsub.publisher" @@ -83,27 +52,12 @@ resource "google_pubsub_topic_iam_binding" "image_processing_publisher" { ] } -# IAM binding for Cloud Function to subscribe -resource "google_pubsub_subscription_iam_binding" "image_processing_subscriber" { - subscription = google_pubsub_subscription.image_processing.name - role = "roles/pubsub.subscriber" - - members = [ - "serviceAccount:${local.cloud_function_service_account}", - ] -} - # Output the topic and subscription names output "pubsub_topic_name" { description = "Name of the Pub/Sub topic for image processing" value = google_pubsub_topic.image_processing.name } -output "pubsub_subscription_name" { - description = "Name of the Pub/Sub subscription for image processing" - value = google_pubsub_subscription.image_processing.name -} - output "pubsub_dlq_topic_name" { description = "Name of the dead letter queue topic" value = google_pubsub_topic.image_processing_dlq.name diff --git a/deployment/terraform/terraform.tfstate b/deployment/terraform/terraform.tfstate index 219341c..efd4d4b 100644 --- a/deployment/terraform/terraform.tfstate +++ b/deployment/terraform/terraform.tfstate @@ -1,9 +1,17 @@ { "version": 4, "terraform_version": "1.10.1", - "serial": 369, + "serial": 388, "lineage": "a183cd95-f987-8698-c6dd-84e933c394a5", "outputs": { + "cloud_function_name": { + "value": "process-image-embedding", + "type": "string" + }, + "cloud_function_url": { + "value": "https://process-image-embedding-p64zpdtkta-uc.a.run.app", + "type": "string" + }, "cloud_run_qdrant_host": { "value": "34.71.6.1", "type": "string" @@ -49,10 +57,6 @@ "value": "image-processing-topic-dlq", "type": "string" }, - "pubsub_subscription_name": { - "value": "image-processing-topic-subscription", - "type": "string" - }, "pubsub_topic_name": { "value": "image-processing-topic", "type": "string" @@ -83,6 +87,38 @@ } }, "resources": [ + { + "mode": "data", + "type": "archive_file", + "name": "function_source", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "ebb70c54eaebd24049805bcc1425349f70bc582d", + "output_base64sha256": "+Q18L9q1o61gbnGJlSvTmwG9cRv1Qwzf8GI95No2Rb4=", + "output_base64sha512": "tK0wkH07eL77+ytrOI8lcHATsN/nP0f/CYq0uzrrlhaRbJ+wsO1/6y0tmeX1hF6xqxW5ZDYTrhrSnayA+2afwQ==", + "output_file_mode": null, + "output_md5": "95eb8ea5146b66f5b26bb830e3f0eab6", + "output_path": "./function-source.zip", + "output_sha": "ebb70c54eaebd24049805bcc1425349f70bc582d", + "output_sha256": "f90d7c2fdab5a3ad606e7189952bd39b01bd711bf5430cdff0623de4da3645be", + "output_sha512": "b4ad30907d3b78befbfb2b6b388f25707013b0dfe73f47ff098ab4bb3aeb9616916c9fb0b0ed7feb2d2d99e5f5845eb1ab15b9643613ae1ad29dac80fb669fc1", + "output_size": 4781, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./../cloud-function", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [] + } + ] + }, { "mode": "data", "type": "google_project", @@ -134,9 +170,11 @@ "run.googleapis.com/ingress": "all" }, "effective_annotations": { + "run.googleapis.com/client-name": "gcloud", + "run.googleapis.com/client-version": "431.0.0", "run.googleapis.com/ingress": "all", "run.googleapis.com/ingress-status": "all", - "run.googleapis.com/operation-id": "3653c984-38f6-42b8-b3c1-9a6814773095", + "run.googleapis.com/operation-id": "e4d7484f-39e4-4dde-8105-28d285eb927b", "run.googleapis.com/urls": "[\"https://sereact-761163285547.us-central1.run.app\",\"https://sereact-p64zpdtkta-uc.a.run.app\"]", "serving.knative.dev/creator": "johnpccd3@gmail.com", "serving.knative.dev/lastModifier": "johnpccd3@gmail.com" @@ -145,10 +183,10 @@ "cloud.googleapis.com/location": "us-central1", "goog-terraform-provisioned": "true" }, - "generation": 1, + "generation": 2, "labels": {}, "namespace": "gen-lang-client-0424120530", - "resource_version": "AAY16EtYS9U", + "resource_version": "AAY16Gy+yWQ", "self_link": "/apis/serving.knative.dev/v1/namespaces/761163285547/services/sereact", "terraform_labels": { "goog-terraform-provisioned": "true" @@ -180,14 +218,14 @@ "type": "RoutesReady" } ], - "latest_created_revision_name": "sereact-00001-hw9", - "latest_ready_revision_name": "sereact-00001-hw9", - "observed_generation": 1, + "latest_created_revision_name": "sereact-00002-cew", + "latest_ready_revision_name": "sereact-00002-cew", + "observed_generation": 2, "traffic": [ { "latest_revision": true, "percent": 100, - "revision_name": "sereact-00001-hw9", + "revision_name": "sereact-00002-cew", "tag": "", "url": "" } @@ -200,13 +238,15 @@ "metadata": [ { "annotations": { - "autoscaling.knative.dev/maxScale": "10" + "autoscaling.knative.dev/maxScale": "10", + "run.googleapis.com/client-name": "gcloud", + "run.googleapis.com/client-version": "431.0.0" }, "generation": 0, "labels": { "run.googleapis.com/startupProbeType": "Default" }, - "name": "", + "name": "sereact-00002-cew", "namespace": "", "resource_version": "", "self_link": "", @@ -417,6 +457,141 @@ } ] }, + { + "mode": "managed", + "type": "google_cloudfunctions2_function", + "name": "image_processor", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "build_config": [ + { + "automatic_update_policy": [ + {} + ], + "build": "projects/761163285547/locations/us-central1/builds/d3341e98-07e4-49de-8dc7-3d53e4d2570a", + "docker_repository": "projects/gen-lang-client-0424120530/locations/us-central1/repositories/gcf-artifacts", + "entry_point": "process_image_embedding", + "environment_variables": {}, + "on_deploy_update_policy": [], + "runtime": "python311", + "service_account": "projects/gen-lang-client-0424120530/serviceAccounts/761163285547-compute@developer.gserviceaccount.com", + "source": [ + { + "repo_source": [], + "storage_source": [ + { + "bucket": "gen-lang-client-0424120530-cloud-function-source", + "generation": 1748123369545880, + "object": "function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip" + } + ] + } + ], + "worker_pool": "" + } + ], + "description": "Process image embeddings and store in vector database", + "effective_labels": { + "goog-terraform-provisioned": "true" + }, + "environment": "GEN_2", + "event_trigger": [ + { + "event_filters": [], + "event_type": "google.cloud.pubsub.topic.v1.messagePublished", + "pubsub_topic": "projects/gen-lang-client-0424120530/topics/image-processing-topic", + "retry_policy": "RETRY_POLICY_RETRY", + "service_account_email": "761163285547-compute@developer.gserviceaccount.com", + "trigger": "projects/gen-lang-client-0424120530/locations/us-central1/triggers/process-image-embedding-422683", + "trigger_region": "us-central1" + } + ], + "id": "projects/gen-lang-client-0424120530/locations/us-central1/functions/process-image-embedding", + "kms_key_name": "", + "labels": null, + "location": "us-central1", + "name": "process-image-embedding", + "project": "gen-lang-client-0424120530", + "service_config": [ + { + "all_traffic_on_latest_revision": true, + "available_cpu": "0.3333", + "available_memory": "512M", + "binary_authorization_policy": "", + "environment_variables": { + "LOG_EXECUTION_ID": "true", + "QDRANT_API_KEY": "", + "QDRANT_COLLECTION": "image_vectors", + "QDRANT_HOST": "34.71.6.1", + "QDRANT_PORT": "6333" + }, + "gcf_uri": "", + "ingress_settings": "ALLOW_ALL", + "max_instance_count": 10, + "max_instance_request_concurrency": 1, + "min_instance_count": 0, + "secret_environment_variables": [], + "secret_volumes": [], + "service": "projects/gen-lang-client-0424120530/locations/us-central1/services/process-image-embedding", + "service_account_email": "761163285547-compute@developer.gserviceaccount.com", + "timeout_seconds": 540, + "uri": "https://process-image-embedding-p64zpdtkta-uc.a.run.app", + "vpc_connector": "", + "vpc_connector_egress_settings": "" + } + ], + "state": "ACTIVE", + "terraform_labels": { + "goog-terraform-provisioned": "true" + }, + "timeouts": null, + "update_time": "2025-05-24T21:52:26.933576416Z", + "url": "https://us-central1-gen-lang-client-0424120530.cloudfunctions.net/process-image-embedding" + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "service_config" + }, + { + "type": "index", + "value": { + "value": 0, + "type": "number" + } + }, + { + "type": "get_attr", + "value": "environment_variables" + }, + { + "type": "index", + "value": { + "value": "QDRANT_API_KEY", + "type": "string" + } + } + ] + ], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjozNjAwMDAwMDAwMDAwLCJkZWxldGUiOjM2MDAwMDAwMDAwMDAsInVwZGF0ZSI6MzYwMDAwMDAwMDAwMH19", + "dependencies": [ + "data.archive_file.function_source", + "data.google_project.current", + "google_compute_address.vector_db_static_ip", + "google_compute_instance.vector_db_vm", + "google_project_service.services", + "google_pubsub_topic.image_processing", + "google_service_account.vector_db_sa", + "google_storage_bucket.function_source", + "google_storage_bucket_object.function_source" + ] + } + ] + }, { "mode": "managed", "type": "google_compute_firewall", @@ -690,7 +865,7 @@ "delete_protection_state": "DELETE_PROTECTION_DISABLED", "deletion_policy": "ABANDON", "earliest_version_time": "2025-05-24T21:09:24.677010Z", - "etag": "IJCLh6eGvY0DMKrW4vCEvY0D", + "etag": "IOXfuveKvY0DMKrW4vCEvY0D", "id": "projects/gen-lang-client-0424120530/databases/sereact-imagedb", "key_prefix": "", "location_id": "us-central1", @@ -711,12 +886,160 @@ } ] }, + { + "mode": "managed", + "type": "google_project_iam_member", + "name": "function_eventarc_receiver", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "condition": [], + "etag": "BwY16K9kGDo=", + "id": "gen-lang-client-0424120530/roles/eventarc.eventReceiver/serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "member": "serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "project": "gen-lang-client-0424120530", + "role": "roles/eventarc.eventReceiver" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "data.google_project.current" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_project_iam_member", + "name": "function_firestore", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "condition": [], + "etag": "BwY16Kj5NHI=", + "id": "gen-lang-client-0424120530/roles/datastore.user/serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "member": "serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "project": "gen-lang-client-0424120530", + "role": "roles/datastore.user" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "data.google_project.current" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_project_iam_member", + "name": "function_pubsub_subscriber", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "condition": [], + "etag": "BwY16K9kGDo=", + "id": "gen-lang-client-0424120530/roles/pubsub.subscriber/serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "member": "serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "project": "gen-lang-client-0424120530", + "role": "roles/pubsub.subscriber" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "data.google_project.current" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_project_iam_member", + "name": "function_storage", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "condition": [], + "etag": "BwY16Kj5NHI=", + "id": "gen-lang-client-0424120530/roles/storage.objectViewer/serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "member": "serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "project": "gen-lang-client-0424120530", + "role": "roles/storage.objectViewer" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "data.google_project.current" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_project_iam_member", + "name": "function_vision", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "condition": [], + "etag": "BwY16Kj5NHI=", + "id": "gen-lang-client-0424120530/roles/ml.developer/serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "member": "serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "project": "gen-lang-client-0424120530", + "role": "roles/ml.developer" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "data.google_project.current" + ] + } + ] + }, { "mode": "managed", "type": "google_project_service", "name": "services", "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", "instances": [ + { + "index_key": "cloudbuild.googleapis.com", + "schema_version": 0, + "attributes": { + "disable_dependent_services": null, + "disable_on_destroy": false, + "id": "gen-lang-client-0424120530/cloudbuild.googleapis.com", + "project": "gen-lang-client-0424120530", + "service": "cloudbuild.googleapis.com", + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0=" + }, + { + "index_key": "cloudfunctions.googleapis.com", + "schema_version": 0, + "attributes": { + "disable_dependent_services": null, + "disable_on_destroy": false, + "id": "gen-lang-client-0424120530/cloudfunctions.googleapis.com", + "project": "gen-lang-client-0424120530", + "service": "cloudfunctions.googleapis.com", + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0=" + }, { "index_key": "cloudresourcemanager.googleapis.com", "schema_version": 0, @@ -759,6 +1082,20 @@ "sensitive_attributes": [], "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0=" }, + { + "index_key": "eventarc.googleapis.com", + "schema_version": 0, + "attributes": { + "disable_dependent_services": null, + "disable_on_destroy": false, + "id": "gen-lang-client-0424120530/eventarc.googleapis.com", + "project": "gen-lang-client-0424120530", + "service": "eventarc.googleapis.com", + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0=" + }, { "index_key": "firestore.googleapis.com", "schema_version": 0, @@ -773,6 +1110,20 @@ "sensitive_attributes": [], "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0=" }, + { + "index_key": "pubsub.googleapis.com", + "schema_version": 0, + "attributes": { + "disable_dependent_services": null, + "disable_on_destroy": false, + "id": "gen-lang-client-0424120530/pubsub.googleapis.com", + "project": "gen-lang-client-0424120530", + "service": "pubsub.googleapis.com", + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0=" + }, { "index_key": "run.googleapis.com", "schema_version": 0, @@ -803,73 +1154,6 @@ } ] }, - { - "mode": "managed", - "type": "google_pubsub_subscription", - "name": "image_processing", - "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", - "instances": [ - { - "schema_version": 0, - "attributes": { - "ack_deadline_seconds": 600, - "bigquery_config": [], - "cloud_storage_config": [], - "dead_letter_policy": [ - { - "dead_letter_topic": "projects/gen-lang-client-0424120530/topics/image-processing-topic-dlq", - "max_delivery_attempts": 5 - } - ], - "effective_labels": { - "component": "image-processing", - "environment": "dev", - "goog-terraform-provisioned": "true", - "service": "sereact" - }, - "enable_exactly_once_delivery": false, - "enable_message_ordering": false, - "expiration_policy": [ - { - "ttl": "2678400s" - } - ], - "filter": "", - "id": "projects/gen-lang-client-0424120530/subscriptions/image-processing-topic-subscription", - "labels": { - "component": "image-processing", - "environment": "dev", - "service": "sereact" - }, - "message_retention_duration": "604800s", - "name": "image-processing-topic-subscription", - "project": "gen-lang-client-0424120530", - "push_config": [], - "retain_acked_messages": false, - "retry_policy": [ - { - "maximum_backoff": "600s", - "minimum_backoff": "10s" - } - ], - "terraform_labels": { - "component": "image-processing", - "environment": "dev", - "goog-terraform-provisioned": "true", - "service": "sereact" - }, - "timeouts": null, - "topic": "projects/gen-lang-client-0424120530/topics/image-processing-topic" - }, - "sensitive_attributes": [], - "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19", - "dependencies": [ - "google_pubsub_topic.image_processing", - "google_pubsub_topic.image_processing_dlq" - ] - } - ] - }, { "mode": "managed", "type": "google_pubsub_subscription", @@ -926,36 +1210,6 @@ } ] }, - { - "mode": "managed", - "type": "google_pubsub_subscription_iam_binding", - "name": "image_processing_subscriber", - "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", - "instances": [ - { - "schema_version": 0, - "attributes": { - "condition": [], - "etag": "BwY16CF7/Zw=", - "id": "projects/gen-lang-client-0424120530/subscriptions/image-processing-topic-subscription/roles/pubsub.subscriber", - "members": [ - "serviceAccount:761163285547-compute@developer.gserviceaccount.com" - ], - "project": null, - "role": "roles/pubsub.subscriber", - "subscription": "image-processing-topic-subscription" - }, - "sensitive_attributes": [], - "private": "bnVsbA==", - "dependencies": [ - "data.google_project.current", - "google_pubsub_subscription.image_processing", - "google_pubsub_topic.image_processing", - "google_pubsub_topic.image_processing_dlq" - ] - } - ] - }, { "mode": "managed", "type": "google_pubsub_topic", @@ -1155,6 +1409,122 @@ ] } ] + }, + { + "mode": "managed", + "type": "google_storage_bucket", + "name": "function_source", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 3, + "attributes": { + "autoclass": [], + "cors": [], + "custom_placement_config": [], + "default_event_based_hold": false, + "effective_labels": { + "goog-terraform-provisioned": "true" + }, + "enable_object_retention": false, + "encryption": [], + "force_destroy": false, + "hierarchical_namespace": [ + { + "enabled": false + } + ], + "id": "gen-lang-client-0424120530-cloud-function-source", + "labels": {}, + "lifecycle_rule": [], + "location": "US-CENTRAL1", + "logging": [], + "name": "gen-lang-client-0424120530-cloud-function-source", + "project": "gen-lang-client-0424120530", + "project_number": 761163285547, + "public_access_prevention": "inherited", + "requester_pays": false, + "retention_policy": [], + "rpo": null, + "self_link": "https://www.googleapis.com/storage/v1/b/gen-lang-client-0424120530-cloud-function-source", + "soft_delete_policy": [ + { + "effective_time": "2025-05-24T21:47:35.399Z", + "retention_duration_seconds": 604800 + } + ], + "storage_class": "STANDARD", + "terraform_labels": { + "goog-terraform-provisioned": "true" + }, + "time_created": "2025-05-24T21:47:35.399Z", + "timeouts": null, + "uniform_bucket_level_access": true, + "updated": "2025-05-24T21:47:35.399Z", + "url": "gs://gen-lang-client-0424120530-cloud-function-source", + "versioning": [], + "website": [] + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsInJlYWQiOjI0MDAwMDAwMDAwMCwidXBkYXRlIjoyNDAwMDAwMDAwMDB9LCJzY2hlbWFfdmVyc2lvbiI6IjMifQ==", + "dependencies": [ + "google_project_service.services" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_storage_bucket_object", + "name": "function_source", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "bucket": "gen-lang-client-0424120530-cloud-function-source", + "cache_control": "", + "content": null, + "content_disposition": "", + "content_encoding": "", + "content_language": "", + "content_type": "application/zip", + "crc32c": "tbmr3A==", + "customer_encryption": [], + "detect_md5hash": "leuOpRRrZvWya7gw4/Dqtg==", + "event_based_hold": false, + "generation": 1748123256911890, + "id": "gen-lang-client-0424120530-cloud-function-source-function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip", + "kms_key_name": "", + "md5hash": "leuOpRRrZvWya7gw4/Dqtg==", + "md5hexhash": "95eb8ea5146b66f5b26bb830e3f0eab6", + "media_link": "https://storage.googleapis.com/download/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip?generation=1748123256911890\u0026alt=media", + "metadata": {}, + "name": "function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip", + "output_name": "function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip", + "retention": [], + "self_link": "https://www.googleapis.com/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip", + "source": "./function-source.zip", + "storage_class": "STANDARD", + "temporary_hold": false, + "timeouts": null + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "content" + } + ] + ], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoyNDAwMDAwMDAwMDAsImRlbGV0ZSI6MjQwMDAwMDAwMDAwLCJ1cGRhdGUiOjI0MDAwMDAwMDAwMH19", + "dependencies": [ + "data.archive_file.function_source", + "google_project_service.services", + "google_storage_bucket.function_source" + ] + } + ] } ], "check_results": null diff --git a/deployment/terraform/terraform.tfstate.backup b/deployment/terraform/terraform.tfstate.backup index e0b2db9..0bdfafe 100644 --- a/deployment/terraform/terraform.tfstate.backup +++ b/deployment/terraform/terraform.tfstate.backup @@ -1,9 +1,13 @@ { "version": 4, "terraform_version": "1.10.1", - "serial": 368, + "serial": 381, "lineage": "a183cd95-f987-8698-c6dd-84e933c394a5", "outputs": { + "cloud_function_name": { + "value": "process-image-embedding", + "type": "string" + }, "cloud_run_qdrant_host": { "value": "34.71.6.1", "type": "string" @@ -49,10 +53,6 @@ "value": "image-processing-topic-dlq", "type": "string" }, - "pubsub_subscription_name": { - "value": "image-processing-topic-subscription", - "type": "string" - }, "pubsub_topic_name": { "value": "image-processing-topic", "type": "string" @@ -83,6 +83,38 @@ } }, "resources": [ + { + "mode": "data", + "type": "archive_file", + "name": "function_source", + "provider": "provider[\"registry.terraform.io/hashicorp/archive\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "ebb70c54eaebd24049805bcc1425349f70bc582d", + "output_base64sha256": "+Q18L9q1o61gbnGJlSvTmwG9cRv1Qwzf8GI95No2Rb4=", + "output_base64sha512": "tK0wkH07eL77+ytrOI8lcHATsN/nP0f/CYq0uzrrlhaRbJ+wsO1/6y0tmeX1hF6xqxW5ZDYTrhrSnayA+2afwQ==", + "output_file_mode": null, + "output_md5": "95eb8ea5146b66f5b26bb830e3f0eab6", + "output_path": "./function-source.zip", + "output_sha": "ebb70c54eaebd24049805bcc1425349f70bc582d", + "output_sha256": "f90d7c2fdab5a3ad606e7189952bd39b01bd711bf5430cdff0623de4da3645be", + "output_sha512": "b4ad30907d3b78befbfb2b6b388f25707013b0dfe73f47ff098ab4bb3aeb9616916c9fb0b0ed7feb2d2d99e5f5845eb1ab15b9643613ae1ad29dac80fb669fc1", + "output_size": 4781, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./../cloud-function", + "source_file": null, + "type": "zip" + }, + "sensitive_attributes": [] + } + ] + }, { "mode": "data", "type": "google_project", @@ -134,9 +166,11 @@ "run.googleapis.com/ingress": "all" }, "effective_annotations": { + "run.googleapis.com/client-name": "gcloud", + "run.googleapis.com/client-version": "431.0.0", "run.googleapis.com/ingress": "all", "run.googleapis.com/ingress-status": "all", - "run.googleapis.com/operation-id": "3653c984-38f6-42b8-b3c1-9a6814773095", + "run.googleapis.com/operation-id": "e4d7484f-39e4-4dde-8105-28d285eb927b", "run.googleapis.com/urls": "[\"https://sereact-761163285547.us-central1.run.app\",\"https://sereact-p64zpdtkta-uc.a.run.app\"]", "serving.knative.dev/creator": "johnpccd3@gmail.com", "serving.knative.dev/lastModifier": "johnpccd3@gmail.com" @@ -145,10 +179,10 @@ "cloud.googleapis.com/location": "us-central1", "goog-terraform-provisioned": "true" }, - "generation": 1, + "generation": 2, "labels": {}, "namespace": "gen-lang-client-0424120530", - "resource_version": "AAY16EtYS9U", + "resource_version": "AAY16Gy+yWQ", "self_link": "/apis/serving.knative.dev/v1/namespaces/761163285547/services/sereact", "terraform_labels": { "goog-terraform-provisioned": "true" @@ -180,14 +214,14 @@ "type": "RoutesReady" } ], - "latest_created_revision_name": "sereact-00001-hw9", - "latest_ready_revision_name": "sereact-00001-hw9", - "observed_generation": 1, + "latest_created_revision_name": "sereact-00002-cew", + "latest_ready_revision_name": "sereact-00002-cew", + "observed_generation": 2, "traffic": [ { "latest_revision": true, "percent": 100, - "revision_name": "sereact-00001-hw9", + "revision_name": "sereact-00002-cew", "tag": "", "url": "" } @@ -200,13 +234,15 @@ "metadata": [ { "annotations": { - "autoscaling.knative.dev/maxScale": "10" + "autoscaling.knative.dev/maxScale": "10", + "run.googleapis.com/client-name": "gcloud", + "run.googleapis.com/client-version": "431.0.0" }, "generation": 0, "labels": { "run.googleapis.com/startupProbeType": "Default" }, - "name": "", + "name": "sereact-00002-cew", "namespace": "", "resource_version": "", "self_link": "", @@ -417,6 +453,13 @@ } ] }, + { + "mode": "managed", + "type": "google_compute_address", + "name": "vector_db_static_ip", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [] + }, { "mode": "managed", "type": "google_compute_firewall", @@ -637,7 +680,7 @@ }, { "type": "get_attr", - "value": "disk_encryption_key_rsa" + "value": "disk_encryption_key_raw" } ], [ @@ -654,7 +697,7 @@ }, { "type": "get_attr", - "value": "disk_encryption_key_raw" + "value": "disk_encryption_key_rsa" } ], [ @@ -690,7 +733,7 @@ "delete_protection_state": "DELETE_PROTECTION_DISABLED", "deletion_policy": "ABANDON", "earliest_version_time": "2025-05-24T21:09:24.677010Z", - "etag": "IIa6rZSGvY0DMKrW4vCEvY0D", + "etag": "IPvK9cCKvY0DMKrW4vCEvY0D", "id": "projects/gen-lang-client-0424120530/databases/sereact-imagedb", "key_prefix": "", "location_id": "us-central1", @@ -711,12 +754,112 @@ } ] }, + { + "mode": "managed", + "type": "google_project_iam_member", + "name": "function_firestore", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "condition": [], + "etag": "BwY16KjLzjY=", + "id": "gen-lang-client-0424120530/roles/datastore.user/serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "member": "serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "project": "gen-lang-client-0424120530", + "role": "roles/datastore.user" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "data.google_project.current" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_project_iam_member", + "name": "function_storage", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "condition": [], + "etag": "BwY16KjLzjY=", + "id": "gen-lang-client-0424120530/roles/storage.objectViewer/serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "member": "serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "project": "gen-lang-client-0424120530", + "role": "roles/storage.objectViewer" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "data.google_project.current" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_project_iam_member", + "name": "function_vision", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "condition": [], + "etag": "BwY16KjLzjY=", + "id": "gen-lang-client-0424120530/roles/ml.developer/serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "member": "serviceAccount:761163285547-compute@developer.gserviceaccount.com", + "project": "gen-lang-client-0424120530", + "role": "roles/ml.developer" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "data.google_project.current" + ] + } + ] + }, { "mode": "managed", "type": "google_project_service", "name": "services", "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", "instances": [ + { + "index_key": "cloudbuild.googleapis.com", + "schema_version": 0, + "attributes": { + "disable_dependent_services": null, + "disable_on_destroy": false, + "id": "gen-lang-client-0424120530/cloudbuild.googleapis.com", + "project": "gen-lang-client-0424120530", + "service": "cloudbuild.googleapis.com", + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0=" + }, + { + "index_key": "cloudfunctions.googleapis.com", + "schema_version": 0, + "attributes": { + "disable_dependent_services": null, + "disable_on_destroy": false, + "id": "gen-lang-client-0424120530/cloudfunctions.googleapis.com", + "project": "gen-lang-client-0424120530", + "service": "cloudfunctions.googleapis.com", + "timeouts": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0=" + }, { "index_key": "cloudresourcemanager.googleapis.com", "schema_version": 0, @@ -803,73 +946,6 @@ } ] }, - { - "mode": "managed", - "type": "google_pubsub_subscription", - "name": "image_processing", - "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", - "instances": [ - { - "schema_version": 0, - "attributes": { - "ack_deadline_seconds": 600, - "bigquery_config": [], - "cloud_storage_config": [], - "dead_letter_policy": [ - { - "dead_letter_topic": "projects/gen-lang-client-0424120530/topics/image-processing-topic-dlq", - "max_delivery_attempts": 5 - } - ], - "effective_labels": { - "component": "image-processing", - "environment": "dev", - "goog-terraform-provisioned": "true", - "service": "sereact" - }, - "enable_exactly_once_delivery": false, - "enable_message_ordering": false, - "expiration_policy": [ - { - "ttl": "2678400s" - } - ], - "filter": "", - "id": "projects/gen-lang-client-0424120530/subscriptions/image-processing-topic-subscription", - "labels": { - "component": "image-processing", - "environment": "dev", - "service": "sereact" - }, - "message_retention_duration": "604800s", - "name": "image-processing-topic-subscription", - "project": "gen-lang-client-0424120530", - "push_config": [], - "retain_acked_messages": false, - "retry_policy": [ - { - "maximum_backoff": "600s", - "minimum_backoff": "10s" - } - ], - "terraform_labels": { - "component": "image-processing", - "environment": "dev", - "goog-terraform-provisioned": "true", - "service": "sereact" - }, - "timeouts": null, - "topic": "projects/gen-lang-client-0424120530/topics/image-processing-topic" - }, - "sensitive_attributes": [], - "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19", - "dependencies": [ - "google_pubsub_topic.image_processing", - "google_pubsub_topic.image_processing_dlq" - ] - } - ] - }, { "mode": "managed", "type": "google_pubsub_subscription", @@ -926,36 +1002,6 @@ } ] }, - { - "mode": "managed", - "type": "google_pubsub_subscription_iam_binding", - "name": "image_processing_subscriber", - "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", - "instances": [ - { - "schema_version": 0, - "attributes": { - "condition": [], - "etag": "BwY16CF7/Zw=", - "id": "projects/gen-lang-client-0424120530/subscriptions/image-processing-topic-subscription/roles/pubsub.subscriber", - "members": [ - "serviceAccount:761163285547-compute@developer.gserviceaccount.com" - ], - "project": null, - "role": "roles/pubsub.subscriber", - "subscription": "image-processing-topic-subscription" - }, - "sensitive_attributes": [], - "private": "bnVsbA==", - "dependencies": [ - "data.google_project.current", - "google_pubsub_subscription.image_processing", - "google_pubsub_topic.image_processing", - "google_pubsub_topic.image_processing_dlq" - ] - } - ] - }, { "mode": "managed", "type": "google_pubsub_topic", @@ -1155,6 +1201,122 @@ ] } ] + }, + { + "mode": "managed", + "type": "google_storage_bucket", + "name": "function_source", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 3, + "attributes": { + "autoclass": [], + "cors": [], + "custom_placement_config": [], + "default_event_based_hold": false, + "effective_labels": { + "goog-terraform-provisioned": "true" + }, + "enable_object_retention": false, + "encryption": [], + "force_destroy": false, + "hierarchical_namespace": [ + { + "enabled": false + } + ], + "id": "gen-lang-client-0424120530-cloud-function-source", + "labels": null, + "lifecycle_rule": [], + "location": "US-CENTRAL1", + "logging": [], + "name": "gen-lang-client-0424120530-cloud-function-source", + "project": "gen-lang-client-0424120530", + "project_number": 761163285547, + "public_access_prevention": "inherited", + "requester_pays": false, + "retention_policy": [], + "rpo": null, + "self_link": "https://www.googleapis.com/storage/v1/b/gen-lang-client-0424120530-cloud-function-source", + "soft_delete_policy": [ + { + "effective_time": "2025-05-24T21:47:35.399Z", + "retention_duration_seconds": 604800 + } + ], + "storage_class": "STANDARD", + "terraform_labels": { + "goog-terraform-provisioned": "true" + }, + "time_created": "2025-05-24T21:47:35.399Z", + "timeouts": null, + "uniform_bucket_level_access": true, + "updated": "2025-05-24T21:47:35.399Z", + "url": "gs://gen-lang-client-0424120530-cloud-function-source", + "versioning": [], + "website": [] + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsInJlYWQiOjI0MDAwMDAwMDAwMCwidXBkYXRlIjoyNDAwMDAwMDAwMDB9LCJzY2hlbWFfdmVyc2lvbiI6IjMifQ==", + "dependencies": [ + "google_project_service.services" + ] + } + ] + }, + { + "mode": "managed", + "type": "google_storage_bucket_object", + "name": "function_source", + "provider": "provider[\"registry.terraform.io/hashicorp/google\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "bucket": "gen-lang-client-0424120530-cloud-function-source", + "cache_control": "", + "content": null, + "content_disposition": "", + "content_encoding": "", + "content_language": "", + "content_type": "application/zip", + "crc32c": "tbmr3A==", + "customer_encryption": [], + "detect_md5hash": "leuOpRRrZvWya7gw4/Dqtg==", + "event_based_hold": false, + "generation": 1748123256911890, + "id": "gen-lang-client-0424120530-cloud-function-source-function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip", + "kms_key_name": "", + "md5hash": "leuOpRRrZvWya7gw4/Dqtg==", + "md5hexhash": "95eb8ea5146b66f5b26bb830e3f0eab6", + "media_link": "https://storage.googleapis.com/download/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip?generation=1748123256911890\u0026alt=media", + "metadata": null, + "name": "function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip", + "output_name": "function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip", + "retention": [], + "self_link": "https://www.googleapis.com/storage/v1/b/gen-lang-client-0424120530-cloud-function-source/o/function-source-95eb8ea5146b66f5b26bb830e3f0eab6.zip", + "source": "./function-source.zip", + "storage_class": "STANDARD", + "temporary_hold": false, + "timeouts": null + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "content" + } + ] + ], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoyNDAwMDAwMDAwMDAsImRlbGV0ZSI6MjQwMDAwMDAwMDAwLCJ1cGRhdGUiOjI0MDAwMDAwMDAwMH19", + "dependencies": [ + "data.archive_file.function_source", + "google_project_service.services", + "google_storage_bucket.function_source" + ] + } + ] } ], "check_results": null