spanner/spec/spec_helper.rb (202 lines of code) (raw):

# Copyright 2020 Google, LLC # # 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. require "rspec" require "google/cloud/spanner" require "google/cloud/spanner/admin/instance" require "google/cloud/spanner/admin/database" require_relative "../spanner_samples" RSpec.configure do |config| config.before :all do if ENV["GOOGLE_CLOUD_SPANNER_TEST_INSTANCE"].nil? || ENV["GOOGLE_CLOUD_SPANNER_MR_TEST_INSTANCE"].nil? || ENV["GOOGLE_CLOUD_SPANNER_PROJECT"].nil? skip "GOOGLE_CLOUD_SPANNER_TEST_INSTANCE, GOOGLE_CLOUD_SPANNER_MR_TEST_INSTANCE and/or GOOGLE_CLOUD_SPANNER_PROJECT not defined" end @project_id = ENV["GOOGLE_CLOUD_SPANNER_PROJECT"] @instance_id = ENV["GOOGLE_CLOUD_SPANNER_TEST_INSTANCE"] @seed = SecureRandom.hex 8 @database_id = "test_db_#{seed}" @backup_id = "test_bu_#{seed}" @copied_backup_id = "test_cbu_#{seed}" @restored_database_id = "restored_db_#{seed}" @spanner = Google::Cloud::Spanner.new project: @project_id @instance = @spanner.instance @instance_id @mr_instance_id = ENV["GOOGLE_CLOUD_SPANNER_MR_TEST_INSTANCE"] @mr_instance = @spanner.instance @mr_instance_id @created_instance_ids = [] @created_instance_config_ids = [] # A list of KMS key names to be used with CMEK @kms_key_names = [ "projects/#{@project_id}/locations/us-central1/keyRings/spanner-test-keyring/cryptoKeys/spanner-test-cmek", "projects/#{@project_id}/locations/us-east1/keyRings/spanner-test-keyring/cryptoKeys/spanner-test-cmek", "projects/#{@project_id}/locations/us-east4/keyRings/spanner-test-keyring/cryptoKeys/spanner-test-cmek" ] end config.after :all do # cleanup_backup_resources cleanup_instance_resources end def seed $spanner_example_seed ||= SecureRandom.hex 8 end # Capture and return STDOUT output by block def capture real_stdout = $stdout $stdout = StringIO.new yield @captured_output = $stdout.string ensure $stdout = real_stdout end def captured_output @captured_output end def cleanup_instance_resources return unless @created_instance_ids @created_instance_ids.each do |instance_id| instance = @spanner.instance instance_id instance.delete if instance end @created_instance_ids.clear end def cleanup_database_resources return unless @instance with_retry do @test_database = @instance.database @database_id @test_database&.drop @test_database = @instance.database @restored_database_id @test_database&.drop end end def cleanup_backup_resources instance = @instance return unless instance @test_backup = instance.backup @backup_id @test_backup&.delete end def instance_admin_client @instance_admin_client ||= Google::Cloud::Spanner::Admin::Instance.instance_admin end def db_admin_client @db_admin_client ||= Google::Cloud::Spanner::Admin::Database.database_admin end def project_path instance_admin_client.project_path project: @project_id end def instance_config_path instance_config_id instance_admin_client.instance_config_path \ project: @project_id, instance_config: instance_config_id end def instance_path instance_id instance_admin_client.instance_path \ project: @project_id, instance: instance_id end def find_instance instance_id instance_admin_client.get_instance name: instance_path(instance_id) rescue Google::Cloud::NotFoundError nil end def create_test_database database_id, statements: [] db_admin_client = Google::Cloud::Spanner::Admin::Database.database_admin instance_path = db_admin_client.instance_path project: @project_id, instance: @instance_id job = db_admin_client.create_database \ parent: instance_path, create_statement: "CREATE DATABASE `#{database_id}`", extra_statements: Array(statements) job.wait_until_done! database = job.results end # Creates a temporary database with random ID (will be dropped after test) # (re-uses create_database to create database with Albums/Singers schema) def create_singers_albums_database instance = @instance capture do create_database project_id: @project_id, instance_id: instance.instance_id, database_id: @database_id @test_database = instance.database @database_id end @test_database end def create_dml_singers_albums_database capture do create_dml_database project_id: @project_id, instance_id: @instance.instance_id, database_id: @database_id @test_database = @instance.database @database_id end @test_database end def create_performances_table capture do create_table_with_timestamp_column project_id: @project_id, instance_id: @instance.instance_id, database_id: @database_id end end def create_venues_table capture do create_table_with_datatypes project_id: @project_id, instance_id: @instance.instance_id, database_id: @database_id end end def create_boxes_database job = @instance.create_database @database_id job.wait_until_done! @test_database = job.database end def create_database_with_data instance = @instance database = create_singers_albums_database instance capture do write_using_dml project_id: @project_id, instance_id: instance.instance_id, database_id: database.database_id @test_database = instance.database @database_id end @test_database end # Creates or return existing temporary backup with random ID (will be dropped # after test) def create_backup_with_data instance = @instance @test_backup = instance.backup @backup_id return @test_backup if @test_backup database = create_singers_albums_database instance capture do write_using_dml project_id: @project_id, instance_id: instance.instance_id, database_id: database.database_id end client = @spanner.client instance.instance_id, database.database_id version_time = client.execute("SELECT CURRENT_TIMESTAMP() as timestamp").rows.first[:timestamp] capture do create_backup project_id: @project_id, instance_id: instance.instance_id, database_id: database.database_id, backup_id: @backup_id, version_time: version_time @test_backup = instance.backup @backup_id end @test_backup end def create_copy_backup capture do copy_backup project_id: @project_id, instance_id: @instance.instance_id, backup_id: @copied_backup_id, source_backup_id: @backup_id end @instance.backup @copied_backup_id end def restore_database_from_backup backup = create_backup_with_data capture do restore_backup project_id: @project_id, instance_id: @instance.instance_id, database_id: @restored_database_id, backup_id: backup.backup_id @test_database = @instance.database @restored_database_id end @test_database end def with_retry retries: 5 max_retries = 10 Retriable.retriable( on: Google::Cloud::DeadlineExceededError, base_interval: 1, multiplier: 2, tries: [retries, max_retries].min ) do return yield end raise end end