This commit is contained in:
johnpccd 2025-05-23 22:54:02 +02:00
parent ae219c8111
commit f1c41a074d
12 changed files with 950 additions and 0 deletions

4
.gitignore vendored
View File

@ -49,3 +49,7 @@ htmlcov/
.coverage.*
coverage.xml
*.cover
# Terraform
*.tfvars
.terraform

64
deployment/README.md Normal file
View File

@ -0,0 +1,64 @@
# Deployment Options for Sereact
This directory contains multiple options for deploying the Sereact application:
## Terraform Infrastructure (`/terraform`)
The Terraform configuration automates the provisioning of all required Google Cloud resources:
- Google Cloud Run service
- Google Container Registry (GCR)
- Cloud Firestore
- Cloud Storage buckets
See [terraform/README.md](terraform/README.md) for detailed instructions.
## Cloud Run Deployment (`/cloud-run`)
The `service.yaml` file defines the Cloud Run service configuration which can be deployed using:
```bash
gcloud run services replace deployment/cloud-run/service.yaml --region=us-central1
```
## Deployment Script (`deploy.sh`)
For convenience, a deployment script is provided to handle the entire deployment workflow:
```bash
# Provision infrastructure with Terraform
./deployment/deploy.sh --provision
# Build and push Docker image
./deployment/deploy.sh --build
# Deploy to Cloud Run
./deployment/deploy.sh --deploy
# Do everything (provision, build, deploy)
./deployment/deploy.sh --all
```
## CI/CD Pipelines
For CI/CD integration, consider using:
1. **GitHub Actions**: Sample workflow included in terraform/README.md
2. **Cloud Build**: Configure a `cloudbuild.yaml` in your repository
3. **Jenkins**: Use the `deploy.sh` script in your pipeline
## Managing Secrets
Sensitive data should be managed using Google Secret Manager:
```bash
# Create a secret
gcloud secrets create sereact-db-uri --replication-policy="automatic"
# Add a secret version
echo -n "your-mongodb-uri" | gcloud secrets versions add sereact-db-uri --data-file=-
# Update Cloud Run service to use the secret
gcloud run services update sereact \
--update-secrets=DATABASE_URI=sereact-db-uri:latest
```

View File

@ -0,0 +1,54 @@
steps:
# Build the container image
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/$PROJECT_ID/sereact:$COMMIT_SHA', '.']
# Push the container image to Container Registry
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/sereact:$COMMIT_SHA']
# Tag the image as latest
- name: 'gcr.io/cloud-builders/docker'
args: ['tag', 'gcr.io/$PROJECT_ID/sereact:$COMMIT_SHA', 'gcr.io/$PROJECT_ID/sereact:latest']
# Push the latest tag
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/sereact:latest']
# Deploy to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud
args:
- 'run'
- 'deploy'
- 'sereact'
- '--image=gcr.io/$PROJECT_ID/sereact:$COMMIT_SHA'
- '--region=us-central1'
- '--platform=managed'
- '--allow-unauthenticated'
- '--set-env-vars=GCS_BUCKET_NAME=${_GCS_BUCKET_NAME},DATABASE_NAME=${_DATABASE_NAME},VECTOR_DB_ENVIRONMENT=${_VECTOR_DB_ENVIRONMENT},VECTOR_DB_INDEX_NAME=${_VECTOR_DB_INDEX_NAME},LOG_LEVEL=INFO'
- '--set-secrets=DATABASE_URI=sereact-db-uri:latest,API_KEY_SECRET=sereact-api-key-secret:latest,VECTOR_DB_API_KEY=sereact-vector-db-key:latest'
# Optional: Run tests after deployment
# - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
# entrypoint: /bin/bash
# args:
# - '-c'
# - |
# SERVICE_URL=$(gcloud run services describe sereact --region=us-central1 --format='value(status.url)')
# curl -s -o /dev/null -w "%{http_code}" $${SERVICE_URL}/health | grep 200
# Store images in Container Registry
images:
- 'gcr.io/$PROJECT_ID/sereact:$COMMIT_SHA'
- 'gcr.io/$PROJECT_ID/sereact:latest'
# Substitution variables to be set in the Cloud Build trigger
substitutions:
_GCS_BUCKET_NAME: 'your-app-storage-bucket'
_DATABASE_NAME: 'imagedb'
_VECTOR_DB_ENVIRONMENT: 'your-pinecone-env'
_VECTOR_DB_INDEX_NAME: 'image-embeddings'
# Increase timeout to 30 minutes
timeout: '1800s'

142
deployment/deploy.sh Normal file
View File

@ -0,0 +1,142 @@
#!/bin/bash
set -e
# Configuration
PROJECT_ID=$(gcloud config get-value project)
IMAGE_NAME="sereact"
REGION="us-central1"
SERVICE_NAME="sereact"
# Help function
function show_help {
echo "Usage: $0 [options]"
echo "Options:"
echo " --provision Run Terraform to provision cloud resources"
echo " --build Build and push Docker image"
echo " --deploy Deploy to Cloud Run"
echo " --all Do all of the above"
echo " --help Show this help message"
exit 0
}
# Check if any arguments were provided
if [ $# -eq 0 ]; then
show_help
fi
# Process arguments
PROVISION=false
BUILD=false
DEPLOY=false
while [[ $# -gt 0 ]]; do
case "$1" in
--provision)
PROVISION=true
shift
;;
--build)
BUILD=true
shift
;;
--deploy)
DEPLOY=true
shift
;;
--all)
PROVISION=true
BUILD=true
DEPLOY=true
shift
;;
--help)
show_help
;;
*)
echo "Unknown option: $1"
show_help
;;
esac
done
# Ensure gcloud is configured
if [ -z "$PROJECT_ID" ]; then
echo "ERROR: No Google Cloud project is set. Run 'gcloud config set project YOUR_PROJECT_ID'"
exit 1
fi
echo "Using Google Cloud project: $PROJECT_ID"
echo "==================================="
# Provision resources with Terraform
if [ "$PROVISION" = true ]; then
echo "Provisioning cloud resources with Terraform..."
cd "$(dirname "$0")/terraform"
# Check if terraform.tfvars exists, if not copy from example
if [ ! -f terraform.tfvars ]; then
echo "Creating terraform.tfvars from example..."
cp terraform.tfvars.example terraform.tfvars
# Replace project ID in tfvars file
sed -i "s/your-gcp-project-id/$PROJECT_ID/g" terraform.tfvars
echo "Please review and edit terraform.tfvars with your desired values"
exit 0
fi
terraform init
terraform apply
cd - > /dev/null
echo "Provisioning completed."
fi
# Build and push Docker image
if [ "$BUILD" = true ]; then
echo "Building and pushing Docker image..."
# Enable Docker to authenticate to GCR
gcloud auth configure-docker gcr.io
# Build the image with timestamp tag
TAG=$(date +%Y%m%d-%H%M%S)
FULL_IMAGE_NAME="gcr.io/$PROJECT_ID/$IMAGE_NAME:$TAG"
LATEST_IMAGE_NAME="gcr.io/$PROJECT_ID/$IMAGE_NAME:latest"
echo "Building image: $FULL_IMAGE_NAME"
docker build -t "$FULL_IMAGE_NAME" -t "$LATEST_IMAGE_NAME" .
echo "Pushing images to Container Registry..."
docker push "$FULL_IMAGE_NAME"
docker push "$LATEST_IMAGE_NAME"
echo "Image built and pushed successfully."
fi
# Deploy to Cloud Run
if [ "$DEPLOY" = true ]; then
echo "Deploying to Cloud Run..."
# Deploy using the latest image
LATEST_IMAGE_NAME="gcr.io/$PROJECT_ID/$IMAGE_NAME:latest"
# Check if we have an existing service.yaml to use
if [ -f "$(dirname "$0")/cloud-run/service.yaml" ]; then
echo "Deploying using service.yaml configuration..."
gcloud run services replace "$(dirname "$0")/cloud-run/service.yaml" --region="$REGION"
else
echo "Deploying directly..."
gcloud run deploy "$SERVICE_NAME" \
--image="$LATEST_IMAGE_NAME" \
--platform="managed" \
--region="$REGION" \
--allow-unauthenticated
fi
# Get service URL
SERVICE_URL=$(gcloud run services describe "$SERVICE_NAME" --region="$REGION" --format='value(status.url)')
echo "Deployment completed successfully."
echo "Service URL: $SERVICE_URL"
fi
echo "All operations completed."

21
deployment/terraform/.terraform.lock.hcl generated Normal file
View File

@ -0,0 +1,21 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/google" {
version = "6.36.1"
hashes = [
"h1:rj3g00i0dH4VxXYO5xXJg188i6OXWbFUT6WmLbO5orY=",
"zh:161d054bda352a286a997f80f3d59366d072377abc6777bfe8abacc2e10ac2bf",
"zh:314c38d8050036176031f691b533184c3578036085483fed877b3b139f887047",
"zh:503c9807312feb9766f0da207d5ac149aa6f5a669144c60da38a33d072ebe2c2",
"zh:897abe484c44c625b301e828a4967c9f781fbf33b5bb50afe226410ebbfd0137",
"zh:97bcdc879b48f5f8bee98316234a1eed3c2e440e356631066d07b5d85ccfe288",
"zh:b273e940da85c5d673cbb3cafe36fb70dd8536e2d8812e617191196c312dac3b",
"zh:ba294699ca7082d394498ce62ecb55501c6a141fd1c43db00a6abdaebc92fa2e",
"zh:c50be96b5c8df5124f18ccdef473eed0bc3a2452e674c19f58fbf7ee14195af4",
"zh:d5a8fda3abda57d912be020e22bab3568facc729756e5339af9a3e56ca277cbc",
"zh:dddbfed09dff01fe538830714a13e71d7581cf2ccfba15acc0a6bb7266147bed",
"zh:e65e8c2e97d1e23c9380516b1d37e111cc700b538d8fca6b9e28ebb89e305ee0",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
]
}

View File

@ -0,0 +1,95 @@
# Terraform Configuration for Sereact
This directory contains Terraform configurations to provision the required Google Cloud resources for Sereact:
- Google Cloud Run service
- Google Container Registry (GCR)
- Firestore database
- Cloud Storage bucket
## Prerequisites
1. Install [Terraform](https://www.terraform.io/downloads) (v1.0.0+)
2. Install [Google Cloud SDK](https://cloud.google.com/sdk/docs/install)
3. Authenticate with Google Cloud:
```bash
gcloud auth login
gcloud auth application-default login
```
4. Create or select a Google Cloud project:
```bash
gcloud projects create PROJECT_ID --name="Sereact Project" # optional
gcloud config set project PROJECT_ID
```
## Setup and Usage
1. Copy the example variables file and edit it with your values:
```bash
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with your project-specific values
```
2. Initialize Terraform:
```bash
terraform init
```
3. Preview the changes:
```bash
terraform plan
```
4. Apply the configuration:
```bash
terraform apply
```
5. After provisioning, you'll see outputs including:
- Cloud Run service URL
- Storage bucket name
- Firestore database ID
- Container Registry URL
## Managing Secrets
Secrets for environment variables (DATABASE_URI, API_KEY_SECRET, etc.) should be managed separately using Google Secret Manager:
```bash
# Create secrets
gcloud secrets create sereact-db-uri --replication-policy="automatic"
gcloud secrets create sereact-api-key-secret --replication-policy="automatic"
gcloud secrets create sereact-vector-db-key --replication-policy="automatic"
# Add secret versions
echo -n "your-secret-value" | gcloud secrets versions add sereact-db-uri --data-file=-
echo -n "your-secret-value" | gcloud secrets versions add sereact-api-key-secret --data-file=-
echo -n "your-secret-value" | gcloud secrets versions add sereact-vector-db-key --data-file=-
# Update Cloud Run service to use secrets
gcloud run services update sereact \
--update-secrets=DATABASE_URI=sereact-db-uri:latest,API_KEY_SECRET=sereact-api-key-secret:latest,VECTOR_DB_API_KEY=sereact-vector-db-key:latest
```
## CI/CD Integration
To integrate this with CI/CD, store the `terraform.tfvars` securely in your CI/CD system and run Terraform as part of your deployment pipeline:
```yaml
# Example GitHub Actions step
- name: Terraform Apply
run: |
cd deployment/terraform
terraform init
terraform apply -auto-approve
env:
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GCP_SA_KEY }}
```
## Destroying Resources
To destroy all provisioned resources:
```bash
terraform destroy
```

View File

@ -0,0 +1,94 @@
provider "google" {
project = var.project_id
region = var.region
zone = var.zone
}
# Enable required APIs
resource "google_project_service" "services" {
for_each = toset([
"cloudresourcemanager.googleapis.com",
"containerregistry.googleapis.com",
"run.googleapis.com",
"firestore.googleapis.com",
"storage.googleapis.com"
])
project = var.project_id
service = each.key
disable_on_destroy = false
}
# Cloud Storage bucket
resource "google_storage_bucket" "app_bucket" {
name = var.storage_bucket_name
location = var.region
uniform_bucket_level_access = true
depends_on = [google_project_service.services]
}
# Firestore Database
resource "google_firestore_database" "database" {
name = var.firestore_db_name
location_id = var.region
type = "FIRESTORE_NATIVE"
depends_on = [google_project_service.services]
}
# Container Registry - no explicit resource needed, just enable the API
# You'll push images to gcr.io/${var.project_id}/sereact
# Cloud Run service
resource "google_cloud_run_service" "sereact" {
name = "sereact"
location = var.region
template {
spec {
containers {
# Using a public placeholder image that exists to avoid deployment failure
# You'll need to update this later with your actual image
image = "gcr.io/google-samples/hello-app:1.0"
ports {
container_port = 8080
}
resources {
limits = {
cpu = "1"
memory = "512Mi"
}
}
env {
name = "DATABASE_NAME"
value = var.firestore_db_name
}
env {
name = "GCS_BUCKET_NAME"
value = var.storage_bucket_name
}
env {
name = "LOG_LEVEL"
value = "INFO"
}
}
}
}
depends_on = [google_project_service.services]
}
# Make the Cloud Run service publicly accessible
resource "google_cloud_run_service_iam_member" "public_access" {
service = google_cloud_run_service.sereact.name
location = google_cloud_run_service.sereact.location
role = "roles/run.invoker"
member = "allUsers"
}

View File

@ -0,0 +1,19 @@
output "cloud_run_url" {
value = google_cloud_run_service.sereact.status[0].url
description = "The URL of the deployed Cloud Run service"
}
output "storage_bucket_name" {
value = google_storage_bucket.app_bucket.name
description = "The name of the provisioned Cloud Storage bucket"
}
output "firestore_database_id" {
value = google_firestore_database.database.id
description = "The ID of the provisioned Firestore database"
}
output "container_registry_url" {
value = "gcr.io/${var.project_id}/sereact"
description = "The URL of the Container Registry repository"
}

View File

@ -0,0 +1,9 @@
{
"version": 4,
"terraform_version": "1.10.1",
"serial": 28,
"lineage": "a183cd95-f987-8698-c6dd-84e933c394a5",
"outputs": {},
"resources": [],
"check_results": null
}

View File

@ -0,0 +1,416 @@
{
"version": 4,
"terraform_version": "1.10.1",
"serial": 18,
"lineage": "a183cd95-f987-8698-c6dd-84e933c394a5",
"outputs": {
"cloud_run_url": {
"value": "https://sereact-p64zpdtkta-uc.a.run.app",
"type": "string"
},
"container_registry_url": {
"value": "gcr.io/gen-lang-client-0424120530/sereact",
"type": "string"
},
"firestore_database_id": {
"value": "projects/gen-lang-client-0424120530/databases/imagedb",
"type": "string"
},
"storage_bucket_name": {
"value": "sereact-storage-bucket",
"type": "string"
}
},
"resources": [
{
"mode": "managed",
"type": "google_cloud_run_service",
"name": "sereact",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [
{
"schema_version": 2,
"attributes": {
"autogenerate_revision_name": false,
"id": "locations/us-central1/namespaces/gen-lang-client-0424120530/services/sereact",
"location": "us-central1",
"metadata": [
{
"annotations": {},
"effective_annotations": {
"run.googleapis.com/ingress": "all",
"run.googleapis.com/ingress-status": "all",
"run.googleapis.com/operation-id": "0982194f-b3e8-45b8-a33f-7ed5fd529307",
"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"
},
"effective_labels": {
"cloud.googleapis.com/location": "us-central1"
},
"generation": 1,
"labels": {},
"namespace": "gen-lang-client-0424120530",
"resource_version": "AAY108GXDwM",
"self_link": "/apis/serving.knative.dev/v1/namespaces/761163285547/services/sereact",
"terraform_labels": {},
"uid": "5b695749-5095-4fb5-86bd-4d86f77dc7da"
}
],
"name": "sereact",
"project": "gen-lang-client-0424120530",
"status": [
{
"conditions": [
{
"message": "",
"reason": "",
"status": "True",
"type": "Ready"
},
{
"message": "",
"reason": "",
"status": "True",
"type": "ConfigurationsReady"
},
{
"message": "",
"reason": "",
"status": "True",
"type": "RoutesReady"
}
],
"latest_created_revision_name": "sereact-00001-bt2",
"latest_ready_revision_name": "sereact-00001-bt2",
"observed_generation": 1,
"traffic": [
{
"latest_revision": true,
"percent": 100,
"revision_name": "sereact-00001-bt2",
"tag": "",
"url": ""
}
],
"url": "https://sereact-p64zpdtkta-uc.a.run.app"
}
],
"template": [
{
"metadata": [
{
"annotations": {
"autoscaling.knative.dev/maxScale": "3"
},
"generation": 0,
"labels": {
"run.googleapis.com/startupProbeType": "Default"
},
"name": "",
"namespace": "",
"resource_version": "",
"self_link": "",
"uid": ""
}
],
"spec": [
{
"container_concurrency": 80,
"containers": [
{
"args": null,
"command": null,
"env": [
{
"name": "DATABASE_NAME",
"value": "imagedb",
"value_from": []
},
{
"name": "GCS_BUCKET_NAME",
"value": "sereact-storage-bucket",
"value_from": []
},
{
"name": "LOG_LEVEL",
"value": "INFO",
"value_from": []
}
],
"env_from": [],
"image": "gcr.io/google-samples/hello-app:1.0",
"liveness_probe": [],
"name": "",
"ports": [
{
"container_port": 8080,
"name": "http1",
"protocol": ""
}
],
"resources": [
{
"limits": {
"cpu": "1",
"memory": "512Mi"
},
"requests": null
}
],
"startup_probe": [
{
"failure_threshold": 1,
"grpc": [],
"http_get": [],
"initial_delay_seconds": 0,
"period_seconds": 240,
"tcp_socket": [
{
"port": 8080
}
],
"timeout_seconds": 240
}
],
"volume_mounts": [],
"working_dir": ""
}
],
"node_selector": null,
"service_account_name": "761163285547-compute@developer.gserviceaccount.com",
"serving_state": "",
"timeout_seconds": 300,
"volumes": []
}
]
}
],
"timeouts": null,
"traffic": [
{
"latest_revision": true,
"percent": 100,
"revision_name": "",
"tag": "",
"url": ""
}
]
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH0sInNjaGVtYV92ZXJzaW9uIjoiMiJ9",
"dependencies": [
"google_project_service.services"
]
}
]
},
{
"mode": "managed",
"type": "google_cloud_run_service_iam_member",
"name": "public_access",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"condition": [],
"etag": "BwY108GyUf0=",
"id": "v1/projects/gen-lang-client-0424120530/locations/us-central1/services/sereact/roles/run.invoker/allUsers",
"location": "us-central1",
"member": "allUsers",
"project": "gen-lang-client-0424120530",
"role": "roles/run.invoker",
"service": "v1/projects/gen-lang-client-0424120530/locations/us-central1/services/sereact"
},
"sensitive_attributes": [],
"private": "bnVsbA==",
"dependencies": [
"google_cloud_run_service.sereact",
"google_project_service.services"
]
}
]
},
{
"mode": "managed",
"type": "google_firestore_database",
"name": "database",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"app_engine_integration_mode": "DISABLED",
"cmek_config": [],
"concurrency_mode": "PESSIMISTIC",
"create_time": "",
"database_edition": "STANDARD",
"delete_protection_state": "DELETE_PROTECTION_DISABLED",
"deletion_policy": "ABANDON",
"earliest_version_time": "2025-05-23T20:47:31.801717Z",
"etag": "IIelp4e8uo0DMPX0nai7uo0D",
"id": "projects/gen-lang-client-0424120530/databases/imagedb",
"key_prefix": "",
"location_id": "us-central1",
"name": "imagedb",
"point_in_time_recovery_enablement": "POINT_IN_TIME_RECOVERY_DISABLED",
"project": "gen-lang-client-0424120530",
"timeouts": null,
"type": "FIRESTORE_NATIVE",
"uid": "177e30f2-9b67-428c-9979-22e625b929c4",
"update_time": "",
"version_retention_period": "3600s"
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19",
"dependencies": [
"google_project_service.services"
]
}
]
},
{
"mode": "managed",
"type": "google_project_service",
"name": "services",
"provider": "provider[\"registry.terraform.io/hashicorp/google\"]",
"instances": [
{
"index_key": "cloudresourcemanager.googleapis.com",
"schema_version": 0,
"attributes": {
"disable_dependent_services": null,
"disable_on_destroy": false,
"id": "gen-lang-client-0424120530/cloudresourcemanager.googleapis.com",
"project": "gen-lang-client-0424120530",
"service": "cloudresourcemanager.googleapis.com",
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
},
{
"index_key": "containerregistry.googleapis.com",
"schema_version": 0,
"attributes": {
"disable_dependent_services": null,
"disable_on_destroy": false,
"id": "gen-lang-client-0424120530/containerregistry.googleapis.com",
"project": "gen-lang-client-0424120530",
"service": "containerregistry.googleapis.com",
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
},
{
"index_key": "firestore.googleapis.com",
"schema_version": 0,
"attributes": {
"disable_dependent_services": null,
"disable_on_destroy": false,
"id": "gen-lang-client-0424120530/firestore.googleapis.com",
"project": "gen-lang-client-0424120530",
"service": "firestore.googleapis.com",
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
},
{
"index_key": "run.googleapis.com",
"schema_version": 0,
"attributes": {
"disable_dependent_services": null,
"disable_on_destroy": false,
"id": "gen-lang-client-0424120530/run.googleapis.com",
"project": "gen-lang-client-0424120530",
"service": "run.googleapis.com",
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
},
{
"index_key": "storage.googleapis.com",
"schema_version": 0,
"attributes": {
"disable_dependent_services": null,
"disable_on_destroy": false,
"id": "gen-lang-client-0424120530/storage.googleapis.com",
"project": "gen-lang-client-0424120530",
"service": "storage.googleapis.com",
"timeouts": null
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjEyMDAwMDAwMDAwMDAsInJlYWQiOjYwMDAwMDAwMDAwMCwidXBkYXRlIjoxMjAwMDAwMDAwMDAwfX0="
}
]
},
{
"mode": "managed",
"type": "google_storage_bucket",
"name": "app_bucket",
"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": "sereact-storage-bucket",
"labels": {},
"lifecycle_rule": [],
"location": "US-CENTRAL1",
"logging": [],
"name": "sereact-storage-bucket",
"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/sereact-storage-bucket",
"soft_delete_policy": [
{
"effective_time": "2025-05-23T20:47:26.788Z",
"retention_duration_seconds": 604800
}
],
"storage_class": "STANDARD",
"terraform_labels": {
"goog-terraform-provisioned": "true"
},
"time_created": "2025-05-23T20:47:26.788Z",
"timeouts": null,
"uniform_bucket_level_access": true,
"updated": "2025-05-23T20:47:26.788Z",
"url": "gs://sereact-storage-bucket",
"versioning": [],
"website": []
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsInJlYWQiOjI0MDAwMDAwMDAwMCwidXBkYXRlIjoyNDAwMDAwMDAwMDB9LCJzY2hlbWFfdmVyc2lvbiI6IjMifQ==",
"dependencies": [
"google_project_service.services"
]
}
]
}
],
"check_results": null
}

View File

@ -0,0 +1,5 @@
project_id = "your-gcp-project-id"
region = "us-central1"
zone = "us-central1-a"
storage_bucket_name = "your-app-storage-bucket"
firestore_db_name = "imagedb"

View File

@ -0,0 +1,27 @@
variable "project_id" {
description = "The Google Cloud project ID"
type = string
}
variable "region" {
description = "The Google Cloud region"
type = string
default = "us-central1"
}
variable "zone" {
description = "The Google Cloud zone"
type = string
default = "us-central1-a"
}
variable "storage_bucket_name" {
description = "The name of the Cloud Storage bucket"
type = string
}
variable "firestore_db_name" {
description = "The name of the Firestore database"
type = string
default = "imagedb"
}