Skip to content

Commit

Permalink
Merge pull request #5 from glasnt/feat/crj
Browse files Browse the repository at this point in the history
(minor): Cloud Run Jobs, cleanup
  • Loading branch information
glasnt committed Nov 14, 2022
2 parents bed9fd2 + cca5acc commit cfd073f
Show file tree
Hide file tree
Showing 19 changed files with 211 additions and 49 deletions.
4 changes: 2 additions & 2 deletions client/firebase.json
Expand Up @@ -8,9 +8,9 @@
],
"rewrites": [
{
"source": "/api/**",
"source": "/server/**",
"run": {
"serviceId": "api",
"serviceId": "server",
"region": "us-central1"
}
}
Expand Down
2 changes: 1 addition & 1 deletion client/rollup.config.js
Expand Up @@ -38,7 +38,7 @@ export default {
replace({
include: ['src/utils/config.js'],
preventAssignment: false,
__api_url__: '/api', // set set in firebase.json
__api_url__: '/server', // set in firebase.json
}),
/** Enable using HTML as rollup entrypoint */
html({
Expand Down
2 changes: 1 addition & 1 deletion client/web-dev-server.config.mjs
Expand Up @@ -35,7 +35,7 @@ export default ({
replace({
include: ['src/utils/config.js'],
preventAssignment: false,
'__api_url__': (process.env.API_URL || 'http://localhost:8000') + "/api"
'__api_url__': (process.env.API_URL || 'http://localhost:8000') + "/server"
}),
]
});
15 changes: 10 additions & 5 deletions cloudbuild.yaml
Expand Up @@ -34,13 +34,16 @@ steps:
dir: provisioning/terraform
env:
- PROJECT_ID=$PROJECT_ID
- REGION=$_REGION
script: |
#!/bin/sh
terraform init
terraform apply -var project=${PROJECT_ID} -auto-approve
# Since the client is also node-based, the firebase image can be used for this step.
terraform apply -auto-approve -no-color \
-var project=${PROJECT_ID} \
-var region=${REGION}
# Only since the client is also node-based can the firebase image can be used for this step.
- id: client deploy
name: gcr.io/$PROJECT_ID/firebase
dir: client
Expand All @@ -51,8 +54,10 @@ steps:
npm i
npm run build
sed -i "s/__api_url__/\/api/g" dist/*.js
sed -i "s/__api_url__/\/server/g" dist/*.js
firebase deploy --project $PROJECT_ID --only hosting
timeout: 1800s

timeout: 1800s
substitutions:
_REGION: us-central1
2 changes: 1 addition & 1 deletion docs/admin/README.md
Expand Up @@ -5,7 +5,7 @@ As a infrastructure administartor, I want to:
* [manually setup Firebase against my project.](firebase-manual-setup.md)
* [have terraform deploy the latest version of my container.](terraform-latest.md)
* [have Django know it's own host URL for CSRF purposes.](django-self-csrf.md)

* [extend this example application.](extending-example.md)


*Want more options? [Request some new docs!](https://github.com/GoogleCloudPlatform/avocano/issues/new/choose)*
4 changes: 1 addition & 3 deletions docs/admin/django-self-csrf.md
@@ -1,9 +1,7 @@
# Django self-determined URL for CSRF

For Django's CSRF protections, you need to have Django know the host it's being served on.
For Django's CSRF protections, you need to have Django know the host it's being served on.

You can set this manually with environment variables, but you can also interrogate the [metadata server](https://cloud.google.com/run/docs/container-contract#metadata-server) and [environment variables](https://cloud.google.com/run/docs/container-contract#services-env-vars) available by default to determine this information.



The implementation of this can be found in the [`get_service_url`](https://github.com/GoogleCloudPlatform/avocano/search?q=get_service_url) method. It also requires the service has [permissions to view it's own metadata](server_introspection).
88 changes: 88 additions & 0 deletions docs/admin/extending-example.md
@@ -0,0 +1,88 @@
# Extending the example

If you are wanting to extend this example application, there are some development steps you're going to need to take.

## Forking the repo, and GitHub actions

Please feel free to fork the repo, but know that there are GitHub Actions attached to the parent repo
that probably won't automatically work with your setup.

To disable:

* Go to your fork's Settings
* Go to Code and Automation > Actions > General
* Under "Actions permissions", select "Disable actions".
* Click **Save**.

## Terraform needs `state.tf` file

If you're running the examples in an environment outside of Cloud Shell, you'll need to be aware that
the `setup.sh` created a Terraform backend state configuration for you. It's a file that's `.gitignore`d,
so you might have missed it.

Be sure to create a `provisioning/terraform/state.tf` file with the following contents:

*Note*: The `PROJECT_ID` is a literal replacement, and must be hardcoded (`backend` doesn't accept variables)

```
terraform {
backend gcs {
bucket = "terraform-PROJECT_ID"
}
}
```


## Creating migrations

When automatically generating Django migrations, you'll need to run these on your local machine so you can commit the
results to source.

To do this, you'll need a connection to your Cloud SQL database, and your settings locally.

### Setup Cloud SQL Auth Proxy

Follow the [Install instructions](https://cloud.google.com/sql/docs/postgres/sql-proxy#install) for your platform.

Saving this into your `$PATH` is a useful administration step so you can take advantage of this executable in other projects.

### Start Cloud SQL Auth Proxy

In a new terminal, start the proxy:

```
cloud_sql_proxy -instances="${PROJECT_ID}:us-central1:psql"=tcp:5432
```

This will redirect this Cloud SQL instance to localhost. Because of this, you'll need to change where Django knows your database to be.

### Copy and edit settings

1. Navigate to the server config:

```
cd server
```

1. Copy the Django settings from Secret Manager to your local `.env` file.
Note: this file is `.gitignore`d.

```
gcloud secrets versions access latest --secret django_settings > .env
```

1. Edit the `DATABASE_URL` line to replace the `cloudsql` config to `localhost`:

```diff
-DATABASE_URL="postgres://server:password@//cloudsql/yourproject:us-central1:psql/django"
+DATABASE_URL="postgres://server:password@localhost/django"
```

1. Run your code on your local machine:

```
python manage.py runserver
```


From here, you should be able to run `makemigrations` and other tasks.
1 change: 1 addition & 0 deletions docs/django/README.md
Expand Up @@ -5,6 +5,7 @@ As a Django administrator, I want to:
* [log into the Django Admin.](login-django-admin.md)
* [update the product listing.](update-product-listing.md)
* [change the look and feel of the website.](update-site-config.md)
* [apply database migrations](apply-migrations.md)


*Want more options? [Request some new docs!](https://github.com/GoogleCloudPlatform/avocano/issues/new/choose)*
24 changes: 24 additions & 0 deletions docs/django/apply-migrations.md
@@ -0,0 +1,24 @@
# Applying database migrations

If you want to apply database migrations, a convenience Cloud Run job has been created for you.

To run migrations:

```
gcloud beta run jobs execute migrate-database \
--region us-central1 --wait
```

To run migrations as part of the Cloud Build, add a step to the `cloudbuild.yaml` file:

```
- id: server migrate
name: "gcr.io/google.com/cloudsdktool/cloud-sdk:slim"
entrypoint: gcloud
args: ["beta", "run", "jobs", "execute", "migrate-database",
"--region", $_REGION, "--wait"]
```

This step must be after the image push step, but can be before or after Terraform (the terraform step
updates the Cloud Run service to the latest image). If your database changes must be made **before**
the application is updated, put it before the terraform step.
2 changes: 1 addition & 1 deletion docs/user/view-products.md
Expand Up @@ -13,4 +13,4 @@ If on any product listing you click "Buy", you'll be told "Oops! Sorry! This is

**This is expected**. This application isn't designed as a full retail store, merely an "April's Fools Day" "fake product" listing site.

Yes, we wish there were such things as Sparkly Avocadoes, too.
Yes, we wish there were such things as Sparkly Avocados, too.
4 changes: 2 additions & 2 deletions provisioning/terraform/container.tf
Expand Up @@ -13,8 +13,8 @@ data "google_client_config" "default" {}

locals {
# these match the values in /cloudbuild.yaml
gcr_hostname = "gcr.io"
server_image = "server"
gcr_hostname = "gcr.io"
server_image = var.service_name
image_registry = "${local.gcr_hostname}/${var.project}"
}

Expand Down
5 changes: 2 additions & 3 deletions provisioning/terraform/database.tf
Expand Up @@ -16,17 +16,16 @@ resource "google_sql_database_instance" "postgres" {
}

## Database

resource "google_sql_database" "database" {
name = "django"
name = var.database_name
instance = google_sql_database_instance.postgres.name
}

## Database User
## Details used in Django config settings
# NOTE: users created this way automatically gain cloudsqladmin rights.
resource "google_sql_user" "django" {
name = "server"
name = var.database_username
instance = google_sql_database_instance.postgres.name
password = random_password.database_user_password.result
}
Expand Down
2 changes: 1 addition & 1 deletion provisioning/terraform/secrets.tf
Expand Up @@ -41,7 +41,7 @@ resource "google_secret_manager_secret" "django_settings" {

## Django configuration settings
resource "google_secret_manager_secret_version" "django_settings" {
secret = google_secret_manager_secret.django_settings.id
secret = google_secret_manager_secret.django_settings.id
secret_data = <<EOF
DATABASE_URL="postgres://${google_sql_user.django.name}:${google_sql_user.django.password}@//cloudsql/${google_sql_database_instance.postgres.project}:${google_sql_database_instance.postgres.region}:${google_sql_database_instance.postgres.name}/${google_sql_database.database.name}"
GS_BUCKET_NAME="${google_storage_bucket.media.name}"
Expand Down
14 changes: 8 additions & 6 deletions provisioning/terraform/service.tf
@@ -1,7 +1,5 @@


resource "google_cloud_run_service" "server" {
name = "api"
name = var.service_name
location = var.region
autogenerate_revision_name = true
template {
Expand All @@ -22,16 +20,20 @@ resource "google_cloud_run_service" "server" {
}
metadata {
annotations = {
"autoscaling.knative.dev/maxScale" = "100"
"run.googleapis.com/cloudsql-instances" = google_sql_database_instance.postgres.connection_name
"run.googleapis.com/client-name" = "terraform"
"autoscaling.knative.dev/maxScale" = "100"
"run.googleapis.com/cloudsql-instances" = google_sql_database_instance.postgres.connection_name
"run.googleapis.com/client-name" = "terraform"
}
}
}
traffic {
percent = 100
latest_revision = true
}

depends_on = [
google_secret_manager_secret.django_settings
]
}


Expand Down
27 changes: 23 additions & 4 deletions provisioning/terraform/variables.tf
Expand Up @@ -3,15 +3,34 @@ variable "project" {
description = "Google Cloud Project ID"
}

# Customisable, but note some values may be hardcoded in docs, other configs.
variable "region" {
default = "us-central1"
type = string
default = "us-central1"
type = string
description = "Google Cloud Region"

}

variable "instance_name" {
type = string
default = "psql"
description = "Cloud SQL Instance name"
}
}

variable "service_name" {
type = string
default = "server"
description = "Cloud Run service name"
}

variable "database_name" {
type = string
default = "django"
description = "Cloud SQL database name"
}


variable "database_username" {
type = string
default = "server"
description = "Cloud SQL database name"
}
5 changes: 2 additions & 3 deletions server/Procfile
@@ -1,5 +1,4 @@
web: gunicorn --bind 0.0.0.0:$PORT avocano_api.wsgi:application
migrate: python3 manage.py migrate
collectstatic: python3 manage.py collectstatic --noinput
migrate: python3 manage.py migrate && python3 manage.py collectstatic --noinput --clear

firstload: bash scripts/prime_database.sh
setup: bash scripts/prime_database.sh
7 changes: 2 additions & 5 deletions server/scripts/prime_database.sh
Expand Up @@ -16,17 +16,14 @@

# This script should be run first time the server is deployed to prime the database.

# Create database elements
# Run migrations and static.
python3 manage.py migrate

# Populate storage
python3 manage.py collectstatic --noinput --clear

# Load configurations
python3 manage.py loaddata demo_config.yaml

# Create products through management commands.

ls store/fixtures/media

python3 manage.py create_new_product \
Expand All @@ -51,7 +48,6 @@ python3 manage.py create_new_product \
--price "12.49" \
--inventory_count 71


# Last added entry is the active product
python3 manage.py create_new_product \
--name "Sparkly Avocado" \
Expand All @@ -61,4 +57,5 @@ python3 manage.py create_new_product \
--discount "14" \
--inventory_count 42

# Generate some random testimonials
python3 manage.py generate_testimonials
@@ -0,0 +1,18 @@
# Generated by Django 4.1.3 on 2022-11-14 02:09

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("store", "0002_initial"),
]

operations = [
migrations.AlterField(
model_name="testimonial",
name="reviewer_location",
field=models.CharField(max_length=100),
),
]

0 comments on commit cfd073f

Please sign in to comment.