aptible-cli 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/README.md +1 -0
- data/lib/aptible/cli/helpers/database.rb +2 -2
- data/lib/aptible/cli/subcommands/db.rb +11 -1
- data/lib/aptible/cli/subcommands/ssh.rb +15 -15
- data/lib/aptible/cli/version.rb +1 -1
- data/spec/aptible/cli/agent_spec.rb +17 -13
- data/spec/aptible/cli/subcommands/apps_spec.rb +16 -14
- data/spec/aptible/cli/subcommands/db_spec.rb +60 -10
- data/spec/aptible/cli/subcommands/deploy_spec.rb +2 -2
- data/spec/aptible/cli/subcommands/domains_spec.rb +5 -3
- data/spec/aptible/cli/subcommands/logs_spec.rb +5 -3
- data/spec/aptible/cli/subcommands/ssh_spec.rb +27 -4
- data/spec/mock/ssh +1 -1
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: daac13a8f95ed0d51f55b1facdaf8fb7d6777253
         | 
| 4 | 
            +
              data.tar.gz: 289c5c14b294a2bc47ed05c6c51bd6dedcc8fb9d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 53d1ff2a1fd3987bf053c8779679eee38a369a1a0f39ed93e7880335d486e81f0ece0991e652276aab01554b1f3cb9eba4a3a794c74894cac9dd122b148ab1cb
         | 
| 7 | 
            +
              data.tar.gz: 4e813f1040e3677a3a96f14c3788b6ba3564443e370bbec606ca7c3e5b9f9a9fc65fc53a078ae43cddea6496dd0b25f7ded2981d943abcfbf13f41430db5cba4
         | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -50,6 +50,7 @@ Commands: | |
| 50 50 | 
             
              aptible db:reload HANDLE                                                                        # Reload a database
         | 
| 51 51 | 
             
              aptible db:restart HANDLE [--container-size SIZE_MB] [--size SIZE_GB]                           # Restart a database
         | 
| 52 52 | 
             
              aptible db:tunnel HANDLE                                                                        # Create a local tunnel to a database
         | 
| 53 | 
            +
              aptible db:url HANDLE                                                                           # Display a database URL
         | 
| 53 54 | 
             
              aptible deploy [OPTIONS] [VAR1=VAL1] [VAR=VAL2] ...                                             # Deploy an app
         | 
| 54 55 | 
             
              aptible domains                                                                                 # Print an app's current virtual domains
         | 
| 55 56 | 
             
              aptible help [COMMAND]                                                                          # Describe available commands or one specific command
         | 
| @@ -78,7 +78,7 @@ module Aptible | |
| 78 78 | 
             
                        raise Thor::Error, 'This command only works for PostgreSQL'
         | 
| 79 79 | 
             
                      end
         | 
| 80 80 |  | 
| 81 | 
            -
                      credential =  | 
| 81 | 
            +
                      credential = find_credential(database)
         | 
| 82 82 |  | 
| 83 83 | 
             
                      with_local_tunnel(credential) do |tunnel_helper|
         | 
| 84 84 | 
             
                        yield local_url(credential, tunnel_helper.port)
         | 
| @@ -93,7 +93,7 @@ module Aptible | |
| 93 93 | 
             
                      "localhost.aptible.in:#{local_port}#{uri.path}"
         | 
| 94 94 | 
             
                    end
         | 
| 95 95 |  | 
| 96 | 
            -
                    def  | 
| 96 | 
            +
                    def find_credential(database, type = nil)
         | 
| 97 97 | 
             
                      unless database.provisioned?
         | 
| 98 98 | 
             
                        raise Thor::Error, "Database #{database.handle} is not provisioned"
         | 
| 99 99 | 
             
                      end
         | 
| @@ -95,7 +95,7 @@ module Aptible | |
| 95 95 | 
             
                          desired_port = Integer(options[:port] || 0)
         | 
| 96 96 | 
             
                          database = ensure_database(options.merge(db: handle))
         | 
| 97 97 |  | 
| 98 | 
            -
                          credential =  | 
| 98 | 
            +
                          credential = find_credential(database, options[:type])
         | 
| 99 99 |  | 
| 100 100 | 
             
                          say "Creating #{credential.type} tunnel to #{database.handle}...",
         | 
| 101 101 | 
             
                              :green
         | 
| @@ -177,6 +177,16 @@ module Aptible | |
| 177 177 | 
             
                          op = database.create_operation!(opts)
         | 
| 178 178 | 
             
                          attach_to_operation_logs(op)
         | 
| 179 179 | 
             
                        end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                        desc 'db:url HANDLE', 'Display a database URL'
         | 
| 182 | 
            +
                        option :environment
         | 
| 183 | 
            +
                        option :type, type: :string
         | 
| 184 | 
            +
                        define_method 'db:url' do |handle|
         | 
| 185 | 
            +
                          database = ensure_database(options.merge(db: handle))
         | 
| 186 | 
            +
                          credential = find_credential(database, options[:type])
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                          say(credential.connection_url)
         | 
| 189 | 
            +
                        end
         | 
| 180 190 | 
             
                      end
         | 
| 181 191 | 
             
                    end
         | 
| 182 192 | 
             
                  end
         | 
| @@ -20,13 +20,6 @@ module Aptible | |
| 20 20 | 
             
                        def ssh(*args)
         | 
| 21 21 | 
             
                          app = ensure_app(options)
         | 
| 22 22 |  | 
| 23 | 
            -
                          op = app.create_operation!(type: 'execute',
         | 
| 24 | 
            -
                                                     command: command_from_args(*args),
         | 
| 25 | 
            -
                                                     status: 'succeeded')
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                          ENV['ACCESS_TOKEN'] = fetch_token
         | 
| 28 | 
            -
                          opts = ['-o', 'SendEnv=ACCESS_TOKEN']
         | 
| 29 | 
            -
             | 
| 30 23 | 
             
                          # SSH's default behavior is as follows:
         | 
| 31 24 | 
             
                          #
         | 
| 32 25 | 
             
                          # - If a TTY is forced, one is allocated.
         | 
| @@ -48,15 +41,22 @@ module Aptible | |
| 48 41 | 
             
                          #
         | 
| 49 42 | 
             
                          # End users can always override this behavior with the
         | 
| 50 43 | 
             
                          # --force-tty option.
         | 
| 51 | 
            -
                          tty_mode = if options[:force_tty]
         | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
                          opts << tty_mode
         | 
| 44 | 
            +
                          tty_mode, interactive = if options[:force_tty]
         | 
| 45 | 
            +
                                                    ['-tt', true]
         | 
| 46 | 
            +
                                                  elsif [STDIN, STDOUT].all?(&:tty?)
         | 
| 47 | 
            +
                                                    ['-t', true]
         | 
| 48 | 
            +
                                                  else
         | 
| 49 | 
            +
                                                    ['-T', false]
         | 
| 50 | 
            +
                                                  end
         | 
| 59 51 |  | 
| 52 | 
            +
                          op = app.create_operation!(
         | 
| 53 | 
            +
                            type: 'execute',
         | 
| 54 | 
            +
                            command: command_from_args(*args),
         | 
| 55 | 
            +
                            interactive: interactive
         | 
| 56 | 
            +
                          )
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                          ENV['ACCESS_TOKEN'] = fetch_token
         | 
| 59 | 
            +
                          opts = ['-o', 'SendEnv=ACCESS_TOKEN', tty_mode]
         | 
| 60 60 | 
             
                          exit_with_ssh_portal(op, *opts)
         | 
| 61 61 | 
             
                        end
         | 
| 62 62 |  | 
    
        data/lib/aptible/cli/version.rb
    CHANGED
    
    
| @@ -1,9 +1,11 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe Aptible::CLI::Agent do
         | 
| 4 | 
            -
              before  | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 4 | 
            +
              before do
         | 
| 5 | 
            +
                allow(subject).to receive(:ask)
         | 
| 6 | 
            +
                allow(subject).to receive(:save_token)
         | 
| 7 | 
            +
                allow(subject).to receive(:token_file).and_return 'some.json'
         | 
| 8 | 
            +
              end
         | 
| 7 9 |  | 
| 8 10 | 
             
              describe '#version' do
         | 
| 9 11 | 
             
                it 'should print the version' do
         | 
| @@ -32,20 +34,21 @@ describe Aptible::CLI::Agent do | |
| 32 34 | 
             
                before do
         | 
| 33 35 | 
             
                  m = -> (code) { @code = code }
         | 
| 34 36 | 
             
                  OAuth2::Error.send :define_method, :initialize, m
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  allow(token).to receive(:access_token).and_return 'access_token'
         | 
| 39 | 
            +
                  allow(token).to receive(:created_at).and_return created_at
         | 
| 40 | 
            +
                  allow(token).to receive(:expires_at).and_return expires_at
         | 
| 41 | 
            +
                  allow(subject).to receive(:puts) { |v| output << v }
         | 
| 35 42 | 
             
                end
         | 
| 36 | 
            -
                before { token.stub(:access_token) { 'access_token' } }
         | 
| 37 | 
            -
                before { token.stub(:created_at) { created_at } }
         | 
| 38 | 
            -
                before { token.stub(:expires_at) { expires_at } }
         | 
| 39 | 
            -
                before { allow(subject).to receive(:puts) { |m| output << m } }
         | 
| 40 43 |  | 
| 41 44 | 
             
                it 'should save a token to ~/.aptible/tokens' do
         | 
| 42 | 
            -
                  Aptible::Auth::Token. | 
| 45 | 
            +
                  allow(Aptible::Auth::Token).to receive(:create).and_return token
         | 
| 43 46 | 
             
                  expect(subject).to receive(:save_token).with('access_token')
         | 
| 44 47 | 
             
                  subject.login
         | 
| 45 48 | 
             
                end
         | 
| 46 49 |  | 
| 47 50 | 
             
                it 'should output the token location and token lifetime' do
         | 
| 48 | 
            -
                  Aptible::Auth::Token. | 
| 51 | 
            +
                  allow(Aptible::Auth::Token).to receive(:create).and_return token
         | 
| 49 52 | 
             
                  subject.login
         | 
| 50 53 | 
             
                  expect(output.size).to eq(3)
         | 
| 51 54 | 
             
                  expect(output[0]).to eq('')
         | 
| @@ -54,7 +57,8 @@ describe Aptible::CLI::Agent do | |
| 54 57 | 
             
                end
         | 
| 55 58 |  | 
| 56 59 | 
             
                it 'should raise an error if authentication fails' do
         | 
| 57 | 
            -
                  Aptible::Auth::Token. | 
| 60 | 
            +
                  allow(Aptible::Auth::Token).to receive(:create)
         | 
| 61 | 
            +
                    .and_raise(OAuth2::Error, 'foo')
         | 
| 58 62 | 
             
                  expect do
         | 
| 59 63 | 
             
                    subject.login
         | 
| 60 64 | 
             
                  end.to raise_error 'Could not authenticate with given credentials: foo'
         | 
| @@ -63,7 +67,7 @@ describe Aptible::CLI::Agent do | |
| 63 67 | 
             
                it 'should use command line arguments if passed' do
         | 
| 64 68 | 
             
                  options = { email: 'test@example.com', password: 'password',
         | 
| 65 69 | 
             
                              lifetime: '30 minutes' }
         | 
| 66 | 
            -
                  subject. | 
| 70 | 
            +
                  allow(subject).to receive(:options).and_return options
         | 
| 67 71 | 
             
                  args = { email: options[:email], password: options[:password],
         | 
| 68 72 | 
             
                           expires_in: 30.minutes.seconds }
         | 
| 69 73 | 
             
                  expect(Aptible::Auth::Token).to receive(:create).with(args) { token }
         | 
| @@ -72,7 +76,7 @@ describe Aptible::CLI::Agent do | |
| 72 76 |  | 
| 73 77 | 
             
                it 'should default to 1 week expiry when OTP is disabled' do
         | 
| 74 78 | 
             
                  options = { email: 'test@example.com', password: 'password' }
         | 
| 75 | 
            -
                  subject. | 
| 79 | 
            +
                  allow(subject).to receive(:options).and_return options
         | 
| 76 80 | 
             
                  args = options.dup.merge(expires_in: 1.week.seconds)
         | 
| 77 81 | 
             
                  expect(Aptible::Auth::Token).to receive(:create).with(args) { token }
         | 
| 78 82 | 
             
                  subject.login
         | 
| @@ -81,7 +85,7 @@ describe Aptible::CLI::Agent do | |
| 81 85 | 
             
                it 'should fail if the lifetime is invalid' do
         | 
| 82 86 | 
             
                  options = { email: 'test@example.com', password: 'password',
         | 
| 83 87 | 
             
                              lifetime: 'this is sparta' }
         | 
| 84 | 
            -
                  subject. | 
| 88 | 
            +
                  allow(subject).to receive(:options).and_return options
         | 
| 85 89 |  | 
| 86 90 | 
             
                  expect { subject.login }.to raise_error(/Invalid token lifetime/)
         | 
| 87 91 | 
             
                end
         | 
| @@ -17,10 +17,12 @@ def dummy_strategy_factory(app_handle, env_handle, usable, | |
| 17 17 | 
             
            end
         | 
| 18 18 |  | 
| 19 19 | 
             
            describe Aptible::CLI::Agent do
         | 
| 20 | 
            -
              before  | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 20 | 
            +
              before do
         | 
| 21 | 
            +
                allow(subject).to receive(:ask)
         | 
| 22 | 
            +
                allow(subject).to receive(:save_token)
         | 
| 23 | 
            +
                allow(subject).to receive(:attach_to_operation_logs)
         | 
| 24 | 
            +
                allow(subject).to receive(:fetch_token) { double 'token' }
         | 
| 25 | 
            +
              end
         | 
| 24 26 |  | 
| 25 27 | 
             
              let!(:account) { Fabricate(:account) }
         | 
| 26 28 | 
             
              let!(:app) { Fabricate(:app, handle: 'hello', account: account) }
         | 
| @@ -196,14 +198,14 @@ describe Aptible::CLI::Agent do | |
| 196 198 | 
             
              describe '#ensure_app' do
         | 
| 197 199 | 
             
                it 'fails if no usable strategy is found' do
         | 
| 198 200 | 
             
                  strategies = [dummy_strategy_factory(nil, nil, false)]
         | 
| 199 | 
            -
                  subject. | 
| 201 | 
            +
                  allow(subject).to receive(:handle_strategies) { strategies }
         | 
| 200 202 |  | 
| 201 203 | 
             
                  expect { subject.ensure_app }.to raise_error(/Could not find app/)
         | 
| 202 204 | 
             
                end
         | 
| 203 205 |  | 
| 204 206 | 
             
                it 'fails if an environment is specified but not found' do
         | 
| 205 207 | 
             
                  strategies = [dummy_strategy_factory('hello', 'aptible', true)]
         | 
| 206 | 
            -
                  subject. | 
| 208 | 
            +
                  allow(subject).to receive(:handle_strategies) { strategies }
         | 
| 207 209 |  | 
| 208 210 | 
             
                  expect(subject).to receive(:environment_from_handle).and_return(nil)
         | 
| 209 211 |  | 
| @@ -220,7 +222,7 @@ describe Aptible::CLI::Agent do | |
| 220 222 |  | 
| 221 223 | 
             
                  it 'scopes the app search to an environment if provided' do
         | 
| 222 224 | 
             
                    strategies = [dummy_strategy_factory('hello', 'aptible', true)]
         | 
| 223 | 
            -
                    subject. | 
| 225 | 
            +
                    allow(subject).to receive(:handle_strategies) { strategies }
         | 
| 224 226 |  | 
| 225 227 | 
             
                    expect(subject).to receive(:environment_from_handle).with('aptible')
         | 
| 226 228 | 
             
                      .and_return(account)
         | 
| @@ -230,7 +232,7 @@ describe Aptible::CLI::Agent do | |
| 230 232 |  | 
| 231 233 | 
             
                  it 'does not scope the app search to an environment if not provided' do
         | 
| 232 234 | 
             
                    strategies = [dummy_strategy_factory('hello', nil, true)]
         | 
| 233 | 
            -
                    subject. | 
| 235 | 
            +
                    allow(subject).to receive(:handle_strategies) { strategies }
         | 
| 234 236 |  | 
| 235 237 | 
             
                    expect(subject.ensure_app).to eq(apps.first)
         | 
| 236 238 | 
             
                  end
         | 
| @@ -239,7 +241,7 @@ describe Aptible::CLI::Agent do | |
| 239 241 | 
             
                    apps.pop
         | 
| 240 242 |  | 
| 241 243 | 
             
                    strategies = [dummy_strategy_factory('hello', nil, true)]
         | 
| 242 | 
            -
                    subject. | 
| 244 | 
            +
                    allow(subject).to receive(:handle_strategies) { strategies }
         | 
| 243 245 |  | 
| 244 246 | 
             
                    expect { subject.ensure_app }.to raise_error(/not find app hello/)
         | 
| 245 247 | 
             
                  end
         | 
| @@ -248,7 +250,7 @@ describe Aptible::CLI::Agent do | |
| 248 250 | 
             
                    apps.pop
         | 
| 249 251 |  | 
| 250 252 | 
             
                    strategies = [dummy_strategy_factory('hello', nil, true)]
         | 
| 251 | 
            -
                    subject. | 
| 253 | 
            +
                    allow(subject).to receive(:handle_strategies) { strategies }
         | 
| 252 254 |  | 
| 253 255 | 
             
                    expect { subject.ensure_app }.to raise_error(/from dummy/)
         | 
| 254 256 | 
             
                  end
         | 
| @@ -257,7 +259,7 @@ describe Aptible::CLI::Agent do | |
| 257 259 | 
             
                    apps.pop
         | 
| 258 260 |  | 
| 259 261 | 
             
                    strategies = [dummy_strategy_factory('hello', 'aptible', true)]
         | 
| 260 | 
            -
                    subject. | 
| 262 | 
            +
                    allow(subject).to receive(:handle_strategies) { strategies }
         | 
| 261 263 |  | 
| 262 264 | 
             
                    expect(subject).to receive(:environment_from_handle).with('aptible')
         | 
| 263 265 | 
             
                      .and_return(account)
         | 
| @@ -269,7 +271,7 @@ describe Aptible::CLI::Agent do | |
| 269 271 | 
             
                    apps << Fabricate(:app, handle: 'hello')
         | 
| 270 272 |  | 
| 271 273 | 
             
                    strategies = [dummy_strategy_factory('hello', nil, true)]
         | 
| 272 | 
            -
                    subject. | 
| 274 | 
            +
                    allow(subject).to receive(:handle_strategies) { strategies }
         | 
| 273 275 |  | 
| 274 276 | 
             
                    expect { subject.ensure_app }.to raise_error(/Multiple apps/)
         | 
| 275 277 | 
             
                  end
         | 
| @@ -279,7 +281,7 @@ describe Aptible::CLI::Agent do | |
| 279 281 | 
             
                      dummy_strategy_factory('hello', nil, false),
         | 
| 280 282 | 
             
                      dummy_strategy_factory('hello', nil, true)
         | 
| 281 283 | 
             
                    ]
         | 
| 282 | 
            -
                    subject. | 
| 284 | 
            +
                    allow(subject).to receive(:handle_strategies) { strategies }
         | 
| 283 285 |  | 
| 284 286 | 
             
                    expect(subject.ensure_app).to eq(apps.first)
         | 
| 285 287 | 
             
                  end
         | 
| @@ -287,7 +289,7 @@ describe Aptible::CLI::Agent do | |
| 287 289 | 
             
                  it 'passes options to the strategy' do
         | 
| 288 290 | 
             
                    receiver = []
         | 
| 289 291 | 
             
                    strategies = [dummy_strategy_factory('hello', nil, false, receiver)]
         | 
| 290 | 
            -
                    subject. | 
| 292 | 
            +
                    allow(subject).to receive(:handle_strategies) { strategies }
         | 
| 291 293 |  | 
| 292 294 | 
             
                    options = { app: 'foo', environment: 'bar' }
         | 
| 293 295 | 
             
                    expect { subject.ensure_app options }.to raise_error(/not find app/)
         | 
| @@ -4,9 +4,11 @@ class SocatHelperMock < OpenStruct | |
| 4 4 | 
             
            end
         | 
| 5 5 |  | 
| 6 6 | 
             
            describe Aptible::CLI::Agent do
         | 
| 7 | 
            -
              before  | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 7 | 
            +
              before do
         | 
| 8 | 
            +
                allow(subject).to receive(:ask)
         | 
| 9 | 
            +
                allow(subject).to receive(:save_token)
         | 
| 10 | 
            +
                allow(subject).to receive(:fetch_token) { double 'token' }
         | 
| 11 | 
            +
              end
         | 
| 10 12 |  | 
| 11 13 | 
             
              let(:handle) { 'foobar' }
         | 
| 12 14 | 
             
              let(:database) { Fabricate(:database, handle: handle) }
         | 
| @@ -20,7 +22,7 @@ describe Aptible::CLI::Agent do | |
| 20 22 | 
             
                before do
         | 
| 21 23 | 
             
                  allow(Aptible::Api::Account).to receive(:all).and_return([account])
         | 
| 22 24 | 
             
                  allow(db).to receive(:reload).and_return(db)
         | 
| 23 | 
            -
                  op. | 
| 25 | 
            +
                  allow(op).to receive(:errors).and_return(Aptible::Resource::Errors.new)
         | 
| 24 26 | 
             
                end
         | 
| 25 27 |  | 
| 26 28 | 
             
                it 'creates a new DB' do
         | 
| @@ -163,15 +165,17 @@ describe Aptible::CLI::Agent do | |
| 163 165 | 
             
                  end
         | 
| 164 166 |  | 
| 165 167 | 
             
                  it 'fails when the database is not provisioned' do
         | 
| 166 | 
            -
                    database. | 
| 168 | 
            +
                    allow(database).to receive(:status) { 'pending' }
         | 
| 167 169 |  | 
| 168 170 | 
             
                    expect { subject.send('db:tunnel', handle) }
         | 
| 169 171 | 
             
                      .to raise_error(/foobar is not provisioned/im)
         | 
| 170 172 | 
             
                  end
         | 
| 171 173 |  | 
| 172 174 | 
             
                  context 'v1 stack' do
         | 
| 173 | 
            -
                    before  | 
| 174 | 
            -
             | 
| 175 | 
            +
                    before do
         | 
| 176 | 
            +
                      allow(database.account.stack).to receive(:version) { 'v1' }
         | 
| 177 | 
            +
                      allow(subject).to receive(:say)
         | 
| 178 | 
            +
                    end
         | 
| 175 179 |  | 
| 176 180 | 
             
                    it 'falls back to the database itself if no type is given' do
         | 
| 177 181 | 
             
                      expect(subject).to receive(:with_local_tunnel).with(database, 0)
         | 
| @@ -180,7 +184,7 @@ describe Aptible::CLI::Agent do | |
| 180 184 |  | 
| 181 185 | 
             
                    it 'falls back to the database itself if type matches' do
         | 
| 182 186 | 
             
                      subject.options = { type: 'bar' }
         | 
| 183 | 
            -
                      database. | 
| 187 | 
            +
                      allow(database).to receive(:type) { 'bar' }
         | 
| 184 188 |  | 
| 185 189 | 
             
                      expect(subject).to receive(:with_local_tunnel).with(database, 0)
         | 
| 186 190 | 
             
                      subject.send('db:tunnel', handle)
         | 
| @@ -188,7 +192,7 @@ describe Aptible::CLI::Agent do | |
| 188 192 |  | 
| 189 193 | 
             
                    it 'does not fall back to the database itself if type mismatches' do
         | 
| 190 194 | 
             
                      subject.options = { type: 'bar' }
         | 
| 191 | 
            -
                      database. | 
| 195 | 
            +
                      allow(database).to receive(:type) { 'foo' }
         | 
| 192 196 |  | 
| 193 197 | 
             
                      expect { subject.send('db:tunnel', handle) }
         | 
| 194 198 | 
             
                        .to raise_error(/no credential with type bar/im)
         | 
| @@ -218,7 +222,7 @@ describe Aptible::CLI::Agent do | |
| 218 222 | 
             
                  end
         | 
| 219 223 |  | 
| 220 224 | 
             
                  token = 'the-token'
         | 
| 221 | 
            -
                  allow(subject).to receive(:fetch_token) | 
| 225 | 
            +
                  allow(subject).to receive(:fetch_token) { token }
         | 
| 222 226 | 
             
                  allow(Aptible::Api::Account).to receive(:all).with(token: token)
         | 
| 223 227 | 
             
                    .and_return([staging, prod])
         | 
| 224 228 | 
             
                end
         | 
| @@ -353,4 +357,50 @@ describe Aptible::CLI::Agent do | |
| 353 357 | 
             
                    .to raise_error(Thor::Error, 'Could not find database nope')
         | 
| 354 358 | 
             
                end
         | 
| 355 359 | 
             
              end
         | 
| 360 | 
            +
             | 
| 361 | 
            +
              describe '#db:url' do
         | 
| 362 | 
            +
                let(:databases) { [database] }
         | 
| 363 | 
            +
                before { expect(Aptible::Api::Database).to receive(:all) { databases } }
         | 
| 364 | 
            +
             | 
| 365 | 
            +
                it 'fails if the DB is not found' do
         | 
| 366 | 
            +
                  expect { subject.send('db:url', 'nope') }
         | 
| 367 | 
            +
                    .to raise_error(Thor::Error, 'Could not find database nope')
         | 
| 368 | 
            +
                end
         | 
| 369 | 
            +
             | 
| 370 | 
            +
                context 'valid database' do
         | 
| 371 | 
            +
                  it 'returns the URL of a specified DB' do
         | 
| 372 | 
            +
                    cred = Fabricate(:database_credential, default: true, type: 'foo',
         | 
| 373 | 
            +
                                                           database: database)
         | 
| 374 | 
            +
             | 
| 375 | 
            +
                    expect(subject).to receive(:say).with(cred.connection_url)
         | 
| 376 | 
            +
                    expect(database).not_to receive(:connection_url)
         | 
| 377 | 
            +
             | 
| 378 | 
            +
                    subject.send('db:url', handle)
         | 
| 379 | 
            +
                  end
         | 
| 380 | 
            +
             | 
| 381 | 
            +
                  it 'fails if multiple DBs are found' do
         | 
| 382 | 
            +
                    databases << database
         | 
| 383 | 
            +
             | 
| 384 | 
            +
                    expect { subject.send('db:url', handle) }
         | 
| 385 | 
            +
                      .to raise_error(/Multiple databases/)
         | 
| 386 | 
            +
                  end
         | 
| 387 | 
            +
             | 
| 388 | 
            +
                  context 'v1 stack' do
         | 
| 389 | 
            +
                    before do
         | 
| 390 | 
            +
                      allow(database.account.stack).to receive(:version) { 'v1' }
         | 
| 391 | 
            +
                      allow(subject).to receive(:say)
         | 
| 392 | 
            +
                    end
         | 
| 393 | 
            +
             | 
| 394 | 
            +
                    it 'returns the URL of a specified DB' do
         | 
| 395 | 
            +
                      connection_url = 'postgresql://aptible-v1:password@lega.cy:4242/db'
         | 
| 396 | 
            +
             | 
| 397 | 
            +
                      expect(subject).to receive(:say).with(connection_url)
         | 
| 398 | 
            +
                      expect(database).to receive(:connection_url)
         | 
| 399 | 
            +
                        .and_return(connection_url)
         | 
| 400 | 
            +
             | 
| 401 | 
            +
                      subject.send('db:url', handle)
         | 
| 402 | 
            +
                    end
         | 
| 403 | 
            +
                  end
         | 
| 404 | 
            +
                end
         | 
| 405 | 
            +
              end
         | 
| 356 406 | 
             
            end
         | 
| @@ -9,7 +9,7 @@ describe Aptible::CLI::Agent do | |
| 9 9 | 
             
                before do
         | 
| 10 10 | 
             
                  allow(Aptible::Api::App).to receive(:all) { [app] }
         | 
| 11 11 | 
             
                  allow(Aptible::Api::Account).to receive(:all) { [account] }
         | 
| 12 | 
            -
                  subject. | 
| 12 | 
            +
                  allow(subject).to receive(:fetch_token) { double'token' }
         | 
| 13 13 | 
             
                end
         | 
| 14 14 |  | 
| 15 15 | 
             
                context 'with app' do
         | 
| @@ -148,7 +148,7 @@ describe Aptible::CLI::Agent do | |
| 148 148 | 
             
                  it 'does not allow deploying nothing on an unprovisioned app' do
         | 
| 149 149 | 
             
                    stub_options
         | 
| 150 150 |  | 
| 151 | 
            -
                    app. | 
| 151 | 
            +
                    allow(app).to receive(:status) { 'pending' }
         | 
| 152 152 |  | 
| 153 153 | 
             
                    expect { subject.deploy }
         | 
| 154 154 | 
             
                      .to raise_error(/either from git.*docker/im)
         | 
| @@ -1,9 +1,11 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe Aptible::CLI::Agent do
         | 
| 4 | 
            -
              before  | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 4 | 
            +
              before do
         | 
| 5 | 
            +
                allow(subject).to receive(:ask)
         | 
| 6 | 
            +
                allow(subject).to receive(:save_token)
         | 
| 7 | 
            +
                allow(subject).to receive(:fetch_token) { double 'token' }
         | 
| 8 | 
            +
              end
         | 
| 7 9 |  | 
| 8 10 | 
             
              let!(:account) { Fabricate(:account) }
         | 
| 9 11 | 
             
              let!(:app) { Fabricate(:app, handle: 'hello', account: account) }
         | 
| @@ -1,9 +1,11 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe Aptible::CLI::Agent do
         | 
| 4 | 
            -
              before  | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 4 | 
            +
              before do
         | 
| 5 | 
            +
                allow(subject).to receive(:ask)
         | 
| 6 | 
            +
                allow(subject).to receive(:save_token)
         | 
| 7 | 
            +
                allow(subject).to receive(:fetch_token) { 'some token' }
         | 
| 8 | 
            +
              end
         | 
| 7 9 |  | 
| 8 10 | 
             
              let(:app) { Fabricate(:app, handle: 'foo') }
         | 
| 9 11 | 
             
              let(:database) { Fabricate(:database, handle: 'bar', status: 'provisioned') }
         | 
| @@ -6,22 +6,25 @@ describe Aptible::CLI::Agent do | |
| 6 6 | 
             
                let(:operation) { double('operation') }
         | 
| 7 7 |  | 
| 8 8 | 
             
                context 'TTY control' do
         | 
| 9 | 
            +
                  let(:args) { { type: 'execute', command: '/bin/bash' } }
         | 
| 10 | 
            +
             | 
| 9 11 | 
             
                  before do
         | 
| 10 12 | 
             
                    expect(subject).to receive(:ensure_app).and_return(app)
         | 
| 11 13 | 
             
                    expect(subject).to receive(:fetch_token).and_return('some token')
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                    expect(app).to receive(:create_operation!).with(
         | 
| 14 | 
            -
                      type: 'execute', command: '/bin/bash', status: 'succeeded'
         | 
| 15 | 
            -
                    ).and_return(operation)
         | 
| 16 14 | 
             
                  end
         | 
| 17 15 |  | 
| 18 16 | 
             
                  it 'allocates a TTY if STDIN and STDOUT are TTYs' do
         | 
| 19 17 | 
             
                    allow(STDIN).to receive(:tty?).and_return(true)
         | 
| 20 18 | 
             
                    allow(STDOUT).to receive(:tty?).and_return(true)
         | 
| 21 19 |  | 
| 20 | 
            +
                    expect(app).to receive(:create_operation!).with(
         | 
| 21 | 
            +
                      **args, interactive: true
         | 
| 22 | 
            +
                    ).and_return(operation)
         | 
| 23 | 
            +
             | 
| 22 24 | 
             
                    expect(subject).to receive(:exit_with_ssh_portal).with(
         | 
| 23 25 | 
             
                      operation, '-o', 'SendEnv=ACCESS_TOKEN', '-t'
         | 
| 24 26 | 
             
                    )
         | 
| 27 | 
            +
             | 
| 25 28 | 
             
                    subject.ssh
         | 
| 26 29 | 
             
                  end
         | 
| 27 30 |  | 
| @@ -30,9 +33,14 @@ describe Aptible::CLI::Agent do | |
| 30 33 | 
             
                    allow(STDOUT).to receive(:tty?).and_return(true)
         | 
| 31 34 | 
             
                    allow(STDERR).to receive(:tty?).and_return(false)
         | 
| 32 35 |  | 
| 36 | 
            +
                    expect(app).to receive(:create_operation!).with(
         | 
| 37 | 
            +
                      **args, interactive: true
         | 
| 38 | 
            +
                    ).and_return(operation)
         | 
| 39 | 
            +
             | 
| 33 40 | 
             
                    expect(subject).to receive(:exit_with_ssh_portal).with(
         | 
| 34 41 | 
             
                      operation, '-o', 'SendEnv=ACCESS_TOKEN', '-t'
         | 
| 35 42 | 
             
                    )
         | 
| 43 | 
            +
             | 
| 36 44 | 
             
                    subject.ssh
         | 
| 37 45 | 
             
                  end
         | 
| 38 46 |  | 
| @@ -40,9 +48,14 @@ describe Aptible::CLI::Agent do | |
| 40 48 | 
             
                    allow(STDIN).to receive(:tty?).and_return(false)
         | 
| 41 49 | 
             
                    allow(STDOUT).to receive(:tty?).and_return(true)
         | 
| 42 50 |  | 
| 51 | 
            +
                    expect(app).to receive(:create_operation!).with(
         | 
| 52 | 
            +
                      **args, interactive: false
         | 
| 53 | 
            +
                    ).and_return(operation)
         | 
| 54 | 
            +
             | 
| 43 55 | 
             
                    expect(subject).to receive(:exit_with_ssh_portal).with(
         | 
| 44 56 | 
             
                      operation, '-o', 'SendEnv=ACCESS_TOKEN', '-T'
         | 
| 45 57 | 
             
                    )
         | 
| 58 | 
            +
             | 
| 46 59 | 
             
                    subject.ssh
         | 
| 47 60 | 
             
                  end
         | 
| 48 61 |  | 
| @@ -50,9 +63,14 @@ describe Aptible::CLI::Agent do | |
| 50 63 | 
             
                    allow(STDIN).to receive(:tty?).and_return(true)
         | 
| 51 64 | 
             
                    allow(STDOUT).to receive(:tty?).and_return(false)
         | 
| 52 65 |  | 
| 66 | 
            +
                    expect(app).to receive(:create_operation!).with(
         | 
| 67 | 
            +
                      **args, interactive: false
         | 
| 68 | 
            +
                    ).and_return(operation)
         | 
| 69 | 
            +
             | 
| 53 70 | 
             
                    expect(subject).to receive(:exit_with_ssh_portal).with(
         | 
| 54 71 | 
             
                      operation, '-o', 'SendEnv=ACCESS_TOKEN', '-T'
         | 
| 55 72 | 
             
                    )
         | 
| 73 | 
            +
             | 
| 56 74 | 
             
                    subject.ssh
         | 
| 57 75 | 
             
                  end
         | 
| 58 76 |  | 
| @@ -62,9 +80,14 @@ describe Aptible::CLI::Agent do | |
| 62 80 | 
             
                    allow(STDIN).to receive(:tty?).and_return(false)
         | 
| 63 81 | 
             
                    allow(STDOUT).to receive(:tty?).and_return(false)
         | 
| 64 82 |  | 
| 83 | 
            +
                    expect(app).to receive(:create_operation!).with(
         | 
| 84 | 
            +
                      **args, interactive: true
         | 
| 85 | 
            +
                    ).and_return(operation)
         | 
| 86 | 
            +
             | 
| 65 87 | 
             
                    expect(subject).to receive(:exit_with_ssh_portal).with(
         | 
| 66 88 | 
             
                      operation, '-o', 'SendEnv=ACCESS_TOKEN', '-tt'
         | 
| 67 89 | 
             
                    )
         | 
| 90 | 
            +
             | 
| 68 91 | 
             
                    subject.ssh
         | 
| 69 92 | 
             
                  end
         | 
| 70 93 | 
             
                end
         | 
    
        data/spec/mock/ssh
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            ssh_mock.rb
         | 
| 1 | 
            +
            spec/mock/ssh_mock.rb
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: aptible-cli
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.12.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Frank Macreery
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2017- | 
| 11 | 
            +
            date: 2017-09-21 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: aptible-resource
         | 
| @@ -306,7 +306,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 306 306 | 
             
                  version: '0'
         | 
| 307 307 | 
             
            requirements: []
         | 
| 308 308 | 
             
            rubyforge_project: 
         | 
| 309 | 
            -
            rubygems_version: 2. | 
| 309 | 
            +
            rubygems_version: 2.6.13
         | 
| 310 310 | 
             
            signing_key: 
         | 
| 311 311 | 
             
            specification_version: 4
         | 
| 312 312 | 
             
            summary: Command-line interface for Aptible services
         |