#!/bin/bash # Copyright 2022 The Nomulus Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This script compares the actual schema in a Cloud SQL database with the golden # schema in the corresponding release. It detects schema changes made outside # the normal deployment process, e.g., those made during a troubleshooting # session that were not cleaned up. # # Mounted volumes and required files in them: # - /secrets/cloud_sql_credential.json: Cloud SQL proxy credential # - /secrets/schema_deployer_credential.dec the schema_deployer user's # database login credential. # - /schema/schema.jar: the jar with the golden schema. set -e read -r cloud_sql_instance db_user db_password \ <<<$(cat /secrets/schema_deployer_credential.dec | awk '{print $1, $2, $3}') # Unpack the golden schema from schema.jar unzip -p /schema/schema.jar sql/schema/nomulus.golden.sql \ > /schema/nomulus.golden.sql echo "$(date): Connecting to ${cloud_sql_instance}." # Set up connection to the Cloud SQL instance. # For now we use Cloud SQL Proxy to set up a SSL tunnel to the Cloud SQL # instance. This has two drawbacks: # - It starts a background process, which is an anti-pattern in Docker. # - The main job needs to wait for a while for the proxy to come up. # We will research for a better long-term solution. # # Other options considered: # - Connect using Socket Factory in this script. # * Drawback: need to manage version and transitive dependencies # of the postgres-socket-factory jar. # - Create a self-contained Java application that connects using socket factory # * Drawback: Seems an overkill trap "pkill cloud_sql_proxy" EXIT cloud_sql_proxy -instances="${cloud_sql_instance}"=tcp:5432 \ --credential_file=/secrets/cloud_sql_credential.json & set +e # Wait for cloud_sql_proxy to start: # first sleep 1 second for the process to launch, then loop until port is ready # or the proxy process dies. sleep 1 while ! netstat -an | grep ':5432 ' && pgrep cloud_sql_proxy; do sleep 1; done if ! pgrep cloud_sql_proxy; then echo "Cloud SQL Proxy failed to set up connection." exit 1 fi # Download the actual sql schema PGPASSWORD=${db_password} pg_dump -h localhost -U "${db_user}" \ -f /schema/nomulus.actual.sql --schema-only --no-owner --no-privileges \ --exclude-table flyway_schema_history \ postgres raw_diff=$(diff /schema/nomulus.golden.sql /schema/nomulus.actual.sql) # Clean up the raw_diff: # - Remove diff locations (e.g. "5,6c5,6): grep "^[<>]" # - Remove leading bracket for easier grepping later: sed -e "s/^[<>]\s//g" # - Remove comments and blank lines: grep -v -E "^--|^$" # - Remove patterns in allowed_diffs.txt, which are custom Cloud SQL configs we # cannot emulate in the golden schema. effective_diff=$(echo "${raw_diff}" \ | grep "^[<>]" | sed -e "s/^[<>]\s//g" \ | grep -v -E "^--|^$" \ | grep -v -f /allowed_diffs.txt ) if [[ ${effective_diff} == "" ]] then echo "Golden and actual schemas match." exit 0 else echo "Golden and actual schemas do not match. Diff is:" echo "${raw_diff}" exit 1 fi