Module: Aptible::CLI::Subcommands::DB
- Included in:
- Agent
- Defined in:
- lib/aptible/cli/subcommands/db.rb
Class Method Summary collapse
-
.included(thor) ⇒ Object
rubocop:disable MethodLength rubocop:disable CyclomaticComplexity.
Class Method Details
.included(thor) ⇒ Object
rubocop:disable MethodLength rubocop:disable CyclomaticComplexity
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/aptible/cli/subcommands/db.rb', line 7 def self.included(thor) thor.class_eval do include Helpers::Operation include Helpers::Token desc 'db:create HANDLE', 'Create a new database' option :type, default: 'postgresql' option :size, default: 10 option :account define_method 'db:create' do |handle| account = ensure_account() database = account.create_database(handle: handle, type: [:type]) if database.errors.any? fail Thor::Error, database.errors..first else op = database.create_operation(type: 'provision', disk_size: [:size]) poll_for_success(op) say database.reload.connection_url end end desc 'db:clone SOURCE DEST', 'Clone a database to create a new one' define_method 'db:clone' do |source_handle, dest_handle| source = database_from_handle(source_handle) unless source fail Thor::Error, "Could not find database #{source_handle}" end op = database.create_operation(type: clone, handle: dest_handle) poll_for_success(op) dest = database_from_handle(dest_handle) say dest.connection_url end desc 'db:dump HANDLE', 'Dump a remote database to file' define_method 'db:dump' do |handle| begin database = database_from_handle(handle) unless database fail Thor::Error, "Could not find database #{handle}" end unless database.type == 'postgresql' fail Thor::Error, 'db:dump only works for PostgreSQL' end local_port = random_port pid = fork { establish_connection(database, local_port) } # TODO: Better test for connection readiness sleep 10 filename = "#{handle}.dump" puts "Dumping to #{filename}" url = "aptible:#{database.passphrase}@localhost:#{local_port}" `pg_dump postgresql://#{url}/db > #{filename}` ensure Process.kill('HUP', pid) if pid end end desc 'db:tunnel HANDLE', 'Create a local tunnel to a database' option :port, type: :numeric define_method 'db:tunnel' do |handle| database = database_from_handle(handle) unless database fail Thor::Error, "Could not find database #{handle}" end local_port = [:port] || random_port puts "Creating tunnel at localhost:#{local_port}..." establish_connection(database, local_port) end private def establish_connection(database, local_port) host = database.account.bastion_host port = database.account.bastion_port ENV['ACCESS_TOKEN'] = fetch_token ENV['APTIBLE_DATABASE'] = database.handle tunnel_args = "-L #{local_port}:localhost:#{remote_port}" connection_args = "-o 'SendEnv=*' -p #{port} root@#{host}" opts = " -o 'SendEnv=*' -o StrictHostKeyChecking=no " \ '-o UserKnownHostsFile=/dev/null' command = "ssh #{opts} #{tunnel_args} #{connection_args}" Kernel.exec(command) end def database_from_handle(handle) Aptible::Api::Database.all(token: fetch_token).find do |a| a.handle == handle end end def random_port # Allocate a dummy server to discover an available port dummy = TCPServer.new('127.0.0.1', 0) port = dummy.addr[1] dummy.close port end def remote_port 8080 end end end |