tugboat 1.3.1 → 2.0.0.RC1
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 +1 -1
- data/CHANGELOG.md +12 -8
- data/lib/tugboat/cli.rb +8 -7
- data/lib/tugboat/config.rb +8 -12
- data/lib/tugboat/middleware/add_key.rb +9 -6
- data/lib/tugboat/middleware/ask_for_credentials.rb +7 -8
- data/lib/tugboat/middleware/check_configuration.rb +1 -1
- data/lib/tugboat/middleware/check_credentials.rb +4 -2
- data/lib/tugboat/middleware/config.rb +3 -4
- data/lib/tugboat/middleware/create_droplet.rb +32 -26
- data/lib/tugboat/middleware/destroy_droplet.rb +6 -6
- data/lib/tugboat/middleware/destroy_image.rb +6 -6
- data/lib/tugboat/middleware/find_droplet.rb +20 -16
- data/lib/tugboat/middleware/find_image.rb +17 -10
- data/lib/tugboat/middleware/halt_droplet.rb +8 -8
- data/lib/tugboat/middleware/info_droplet.rb +38 -25
- data/lib/tugboat/middleware/info_image.rb +5 -5
- data/lib/tugboat/middleware/inject_client.rb +3 -9
- data/lib/tugboat/middleware/list_droplets.rb +6 -4
- data/lib/tugboat/middleware/list_images.rb +28 -23
- data/lib/tugboat/middleware/list_regions.rb +3 -3
- data/lib/tugboat/middleware/list_sizes.rb +3 -3
- data/lib/tugboat/middleware/list_ssh_keys.rb +5 -4
- data/lib/tugboat/middleware/password_reset.rb +7 -7
- data/lib/tugboat/middleware/rebuild_droplet.rb +8 -8
- data/lib/tugboat/middleware/resize_droplet.rb +7 -7
- data/lib/tugboat/middleware/restart_droplet.rb +8 -8
- data/lib/tugboat/middleware/snapshot_droplet.rb +6 -6
- data/lib/tugboat/middleware/ssh_droplet.rb +3 -1
- data/lib/tugboat/middleware/start_droplet.rb +6 -6
- data/lib/tugboat/middleware/wait_for_state.rb +6 -6
- data/lib/tugboat/version.rb +1 -1
- data/spec/cli/add_key_spec.rb +16 -9
- data/spec/cli/authorize_cli_spec.rb +24 -29
- data/spec/cli/config_cli_spec.rb +57 -0
- data/spec/cli/create_cli_spec.rb +18 -28
- data/spec/cli/debug_cli_spec.rb +8 -14
- data/spec/cli/destroy_cli_spec.rb +39 -50
- data/spec/cli/destroy_image_cli_spec.rb +33 -39
- data/spec/cli/droplets_cli_spec.rb +15 -12
- data/spec/cli/halt_cli_spec.rb +50 -46
- data/spec/cli/images_cli_spec.rb +134 -58
- data/spec/cli/info_cli_spec.rb +139 -139
- data/spec/cli/info_image_cli_spec.rb +113 -26
- data/spec/cli/keys_cli_spec.rb +7 -5
- data/spec/cli/password_reset_cli_spec.rb +46 -44
- data/spec/cli/rebuild_cli_spec.rb +187 -101
- data/spec/cli/regions_cli_spec.rb +13 -6
- data/spec/cli/resize_cli_spec.rb +51 -48
- data/spec/cli/restart_cli_spec.rb +41 -39
- data/spec/cli/sizes_cli_spec.rb +13 -8
- data/spec/cli/snapshot_cli_spec.rb +36 -37
- data/spec/cli/ssh_cli_spec.rb +7 -15
- data/spec/cli/start_cli_spec.rb +39 -35
- data/spec/cli/verify_cli_spec.rb +20 -12
- data/spec/cli/wait_cli_spec.rb +43 -27
- data/spec/config_spec.rb +19 -25
- data/spec/fixtures/create_droplet.json +44 -0
- data/spec/fixtures/create_ssh_key.json +4 -4
- data/spec/fixtures/create_ssh_key_from_file.json +8 -0
- data/spec/fixtures/droplet_start_response.json +13 -0
- data/spec/fixtures/not_found.json +4 -0
- data/spec/fixtures/password_reset_response.json +13 -0
- data/spec/fixtures/power_cycle_response.json +13 -0
- data/spec/fixtures/resize_droplet.json +13 -0
- data/spec/fixtures/restart_response.json +13 -0
- data/spec/fixtures/show_coreos_image.json +23 -0
- data/spec/fixtures/show_droplet.json +90 -11
- data/spec/fixtures/show_droplet_inactive.json +90 -11
- data/spec/fixtures/show_droplets.json +249 -30
- data/spec/fixtures/show_droplets_empty.json +5 -2
- data/spec/fixtures/show_image.json +14 -7
- data/spec/fixtures/show_images.json +1075 -13
- data/spec/fixtures/show_images_global.json +25 -16
- data/spec/fixtures/show_keys.json +15 -7
- data/spec/fixtures/show_redmine_image.json +24 -0
- data/spec/fixtures/show_regions.json +181 -12
- data/spec/fixtures/show_sizes.json +178 -9
- data/spec/fixtures/shutdown_response.json +13 -0
- data/spec/fixtures/snapshot_response.json +13 -0
- data/spec/fixtures/ubuntu_image_9801951.json +24 -0
- data/spec/middleware/check_credentials_spec.rb +4 -3
- data/spec/middleware/inject_client_spec.rb +2 -2
- data/spec/shared/environment.rb +6 -7
- data/spec/spec_helper.rb +1 -1
- data/tugboat.gemspec +39 -19
- metadata +50 -14
- data/spec/fixtures/show_droplet_fuzzy.json +0 -13
- data/spec/fixtures/show_droplets_fuzzy.json +0 -35
- data/spec/fixtures/show_droplets_inactive.json +0 -37
    
        data/spec/cli/start_cli_spec.rb
    CHANGED
    
    | @@ -5,72 +5,76 @@ describe Tugboat::CLI do | |
| 5 5 |  | 
| 6 6 | 
             
              describe "start" do
         | 
| 7 7 | 
             
                it "starts the droplet with a fuzzy name" do
         | 
| 8 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets? | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
                    to_return(:headers => {'Content-Type' => 'application/json'}, :status => 200, :body => fixture("show_droplet"))
         | 
| 8 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200").
         | 
| 9 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 10 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplets'), :headers => {})
         | 
| 12 11 |  | 
| 13 | 
            -
                   | 
| 12 | 
            +
                  stub_request(:post, "https://api.digitalocean.com/v2/droplets/3164444/actions").
         | 
| 13 | 
            +
                     with(:body => "{\"type\":\"power_on\"}",
         | 
| 14 | 
            +
                          :headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 15 | 
            +
                     to_return(:status => 200, :body => fixture('droplet_start_response'), :headers => {})
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  @cli.start("example3.com")
         | 
| 14 18 |  | 
| 15 19 | 
             
                  expect($stdout.string).to eq <<-eos
         | 
| 16 | 
            -
            Droplet fuzzy name provided. Finding droplet ID...done\e[0m,  | 
| 17 | 
            -
            Queuing start for  | 
| 20 | 
            +
            Droplet fuzzy name provided. Finding droplet ID...done\e[0m, 3164444 (example3.com)
         | 
| 21 | 
            +
            Queuing start for 3164444 (example3.com)...Start complete!
         | 
| 18 22 | 
             
                  eos
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  expect(a_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
         | 
| 21 | 
            -
                  expect(a_request(:put, "https://api.digitalocean.com/droplets/100823/power_on?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
         | 
| 22 23 | 
             
                end
         | 
| 23 24 |  | 
| 24 25 | 
             
                it "starts the droplet with an id" do
         | 
| 25 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 26 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets/3164494?per_page=200").
         | 
| 27 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 28 | 
            +
                     to_return(:headers => {'Content-Type' => 'application/json'}, :status => 200, :body => fixture("show_droplet_inactive"))
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  stub_request(:post, "https://api.digitalocean.com/v2/droplets/3164494/actions").
         | 
| 31 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 32 | 
            +
                     to_return(:headers => {'Content-Type' => 'application/json'}, :status => 200, :body => fixture("show_droplet_inactive"))
         | 
| 33 | 
            +
             | 
| 29 34 |  | 
| 30 | 
            -
                  @cli.options = @cli.options.merge(:id =>  | 
| 35 | 
            +
                  @cli.options = @cli.options.merge(:id => '3164494')
         | 
| 31 36 | 
             
                  @cli.start
         | 
| 32 37 |  | 
| 33 38 | 
             
                  expect($stdout.string).to eq <<-eos
         | 
| 34 | 
            -
            Droplet id provided. Finding Droplet...done\e[0m,  | 
| 35 | 
            -
            Queuing start for  | 
| 39 | 
            +
            Droplet id provided. Finding Droplet...done\e[0m, 3164494 (example.com)
         | 
| 40 | 
            +
            Queuing start for 3164494 (example.com)...Start complete!
         | 
| 36 41 | 
             
                  eos
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  expect(a_request(:get, "https://api.digitalocean.com/droplets/#{droplet_id}?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
         | 
| 39 | 
            -
                  expect(a_request(:put, "https://api.digitalocean.com/droplets/100823/power_on?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
         | 
| 40 42 | 
             
                end
         | 
| 41 43 |  | 
| 42 44 |  | 
| 43 45 | 
             
                it "starts the droplet with a name" do
         | 
| 44 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets? | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 46 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200").
         | 
| 47 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 48 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplets'), :headers => {})
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  stub_request(:post, "https://api.digitalocean.com/v2/droplets/3164444/actions").
         | 
| 51 | 
            +
                     with(:body => "{\"type\":\"power_on\"}",
         | 
| 52 | 
            +
                          :headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 53 | 
            +
                     to_return(:status => 200, :body => fixture('droplet_start_response'), :headers => {})
         | 
| 48 54 |  | 
| 49 | 
            -
                  @cli.options = @cli.options.merge(:name =>  | 
| 55 | 
            +
                  @cli.options = @cli.options.merge(:name => 'example3.com')
         | 
| 50 56 | 
             
                  @cli.start
         | 
| 51 57 |  | 
| 52 58 | 
             
                  expect($stdout.string).to eq <<-eos
         | 
| 53 | 
            -
            Droplet name provided. Finding droplet ID...done\e[0m,  | 
| 54 | 
            -
            Queuing start for  | 
| 59 | 
            +
            Droplet name provided. Finding droplet ID...done\e[0m, 3164444 (example3.com)
         | 
| 60 | 
            +
            Queuing start for 3164444 (example3.com)...Start complete!
         | 
| 55 61 | 
             
                  eos
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                  expect(a_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
         | 
| 58 | 
            -
                  expect(a_request(:put, "https://api.digitalocean.com/droplets/100823/power_on?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
         | 
| 59 62 | 
             
                end
         | 
| 60 63 |  | 
| 61 64 | 
             
                it "does not start a droplet that is inactive" do
         | 
| 62 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets? | 
| 63 | 
            -
             | 
| 65 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200").
         | 
| 66 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 67 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplets'), :headers => {})
         | 
| 64 68 |  | 
| 65 | 
            -
                  @cli.options = @cli.options.merge(:name =>  | 
| 69 | 
            +
                  @cli.options = @cli.options.merge(:name => 'example.com')
         | 
| 66 70 | 
             
                  expect {@cli.start}.to raise_error(SystemExit)
         | 
| 67 71 |  | 
| 68 72 | 
             
                  expect($stdout.string).to eq <<-eos
         | 
| 69 | 
            -
            Droplet name provided. Finding droplet ID...done\e[0m,  | 
| 73 | 
            +
            Droplet name provided. Finding droplet ID...done\e[0m, 6918990 (example.com)
         | 
| 70 74 | 
             
            Droplet must be off for this operation to be successful.
         | 
| 71 75 | 
             
                  eos
         | 
| 72 76 |  | 
| 73 | 
            -
             | 
| 77 | 
            +
             | 
| 74 78 | 
             
                end
         | 
| 75 79 | 
             
              end
         | 
| 76 80 | 
             
            end
         | 
    
        data/spec/cli/verify_cli_spec.rb
    CHANGED
    
    | @@ -5,27 +5,35 @@ describe Tugboat::CLI do | |
| 5 5 |  | 
| 6 6 | 
             
              describe "verify" do
         | 
| 7 7 | 
             
                it "returns confirmation text when verify passes" do
         | 
| 8 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets? | 
| 9 | 
            -
             | 
| 8 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200").
         | 
| 9 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 10 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplets'), :headers => {})
         | 
| 11 | 
            +
             | 
| 10 12 | 
             
                  @cli.verify
         | 
| 11 13 | 
             
                  expect($stdout.string).to eq "Authentication with DigitalOcean was successful.\n"
         | 
| 12 | 
            -
                  expect(a_request(:get, "https://api.digitalocean.com/droplets? | 
| 14 | 
            +
                  expect(a_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200")).to have_been_made
         | 
| 13 15 | 
             
                end
         | 
| 14 16 |  | 
| 15 | 
            -
                it "returns error  | 
| 16 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets? | 
| 17 | 
            -
             | 
| 17 | 
            +
                it "returns error when verify fails" do
         | 
| 18 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200").
         | 
| 19 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 20 | 
            +
                     to_return(:headers => {'Content-Type' => 'text/html'}, :status => 500, :body => fixture('500','html'))
         | 
| 21 | 
            +
             | 
| 18 22 | 
             
                  expect { @cli.verify }.to raise_error(SystemExit)
         | 
| 19 | 
            -
                  expect($stdout.string).to  | 
| 20 | 
            -
                  expect(a_request(:get, "https://api.digitalocean.com/droplets? | 
| 23 | 
            +
                  expect($stdout.string).to include "Authentication with DigitalOcean failed."
         | 
| 24 | 
            +
                  expect(a_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200")).to have_been_made
         | 
| 21 25 | 
             
                end
         | 
| 22 26 |  | 
| 23 27 | 
             
                it "returns error string when verify fails and a non-json reponse is given" do
         | 
| 24 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets? | 
| 25 | 
            -
             | 
| 28 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200").
         | 
| 29 | 
            +
                    with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 30 | 
            +
                    to_return(:headers => {'Content-Type' => 'text/html'}, :status => 500, :body => fixture('500','html'))
         | 
| 31 | 
            +
             | 
| 26 32 | 
             
                  expect { @cli.verify }.to raise_error(SystemExit)
         | 
| 27 | 
            -
                  expect($stdout.string).to  | 
| 28 | 
            -
                  expect( | 
| 33 | 
            +
                  expect($stdout.string).to include "Authentication with DigitalOcean failed."
         | 
| 34 | 
            +
                  expect($stdout.string).to include "<title>DigitalOcean - Seems we've encountered a problem!</title>"
         | 
| 35 | 
            +
                  # TODO: Make it so this doesnt barf up a huge HTML file...
         | 
| 36 | 
            +
                  expect(a_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200")).to have_been_made
         | 
| 29 37 | 
             
                end
         | 
| 30 38 |  | 
| 31 39 | 
             
              end
         | 
    
        data/spec/cli/wait_cli_spec.rb
    CHANGED
    
    | @@ -5,60 +5,76 @@ describe Tugboat::CLI do | |
| 5 5 |  | 
| 6 6 | 
             
              describe "wait" do
         | 
| 7 7 | 
             
                it "waits for a droplet with a fuzzy name" do
         | 
| 8 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets? | 
| 9 | 
            -
             | 
| 8 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200").
         | 
| 9 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 10 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplets'), :headers => {})
         | 
| 10 11 |  | 
| 11 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets/ | 
| 12 | 
            -
             | 
| 12 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets/6918990?per_page=200").
         | 
| 13 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 14 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplet'), :headers => {})
         | 
| 13 15 |  | 
| 14 16 | 
             
                  @cli.options = @cli.options.merge(:state => "active")
         | 
| 15 | 
            -
                  @cli.wait(" | 
| 17 | 
            +
                  @cli.wait("example.com")
         | 
| 16 18 |  | 
| 17 19 | 
             
                  expect($stdout.string).to eq <<-eos
         | 
| 18 | 
            -
            Droplet fuzzy name provided. Finding droplet ID...done\e[0m,  | 
| 20 | 
            +
            Droplet fuzzy name provided. Finding droplet ID...done\e[0m, 6918990 (example.com)
         | 
| 19 21 | 
             
            Waiting for droplet to become active..done\e[0m (0s)
         | 
| 20 22 | 
             
            eos
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                it "loops whilst it waits for state" do
         | 
| 26 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200").
         | 
| 27 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 28 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplets'), :headers => {})
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets/6918990?per_page=200").
         | 
| 31 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 32 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplet_inactive'), :headers => {})
         | 
| 33 | 
            +
             | 
| 34 | 
            +
             | 
| 35 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets/6918990?per_page=200").
         | 
| 36 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 37 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplet'), :headers => {})
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  @cli.options = @cli.options.merge(:state => "active")
         | 
| 40 | 
            +
                  @cli.wait("example.com")
         | 
| 21 41 |  | 
| 22 | 
            -
                  expect( | 
| 23 | 
            -
             | 
| 42 | 
            +
                  expect($stdout.string).to eq <<-eos
         | 
| 43 | 
            +
            Droplet fuzzy name provided. Finding droplet ID...done\e[0m, 6918990 (example.com)
         | 
| 44 | 
            +
            Waiting for droplet to become active..done\e[0m (0s)
         | 
| 45 | 
            +
            eos
         | 
| 24 46 | 
             
                end
         | 
| 25 47 |  | 
| 26 48 | 
             
                it "waits for a droplet with an id" do
         | 
| 27 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets | 
| 28 | 
            -
             | 
| 49 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets/6918990?per_page=200").
         | 
| 50 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 51 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplet'), :headers => {})
         | 
| 29 52 |  | 
| 30 | 
            -
                   | 
| 31 | 
            -
                       to_return(:headers => {'Content-Type' => 'application/json'}, :status => 200, :body => fixture("show_droplet"))
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                  @cli.options = @cli.options.merge(:id => droplet_id, :state => "active")
         | 
| 53 | 
            +
                  @cli.options = @cli.options.merge(:id => '6918990', :state => "active")
         | 
| 34 54 | 
             
                  @cli.wait
         | 
| 35 55 |  | 
| 36 56 | 
             
                  expect($stdout.string).to eq <<-eos
         | 
| 37 | 
            -
            Droplet id provided. Finding Droplet...done\e[0m,  | 
| 57 | 
            +
            Droplet id provided. Finding Droplet...done\e[0m, 6918990 (example.com)
         | 
| 38 58 | 
             
            Waiting for droplet to become active..done\e[0m (0s)
         | 
| 39 59 | 
             
                  eos
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                  expect(a_request(:get, "https://api.digitalocean.com/droplets/100823?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
         | 
| 42 | 
            -
                  expect(a_request(:get, "https://api.digitalocean.com/droplets/#{droplet_id}?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
         | 
| 43 60 | 
             
                end
         | 
| 44 61 |  | 
| 45 62 | 
             
                it "waits for a droplet with a name" do
         | 
| 46 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets? | 
| 47 | 
            -
             | 
| 63 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets?per_page=200").
         | 
| 64 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 65 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplets'), :headers => {})
         | 
| 48 66 |  | 
| 49 | 
            -
                  stub_request(:get, "https://api.digitalocean.com/droplets/ | 
| 50 | 
            -
             | 
| 67 | 
            +
                  stub_request(:get, "https://api.digitalocean.com/v2/droplets/6918990?per_page=200").
         | 
| 68 | 
            +
                     with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'Bearer foo', 'Content-Type'=>'application/json', 'User-Agent'=>'Faraday v0.9.2'}).
         | 
| 69 | 
            +
                     to_return(:status => 200, :body => fixture('show_droplet'), :headers => {})
         | 
| 51 70 |  | 
| 52 | 
            -
                  @cli.options = @cli.options.merge(:name =>  | 
| 71 | 
            +
                  @cli.options = @cli.options.merge(:name => 'example.com', :state => "active")
         | 
| 53 72 | 
             
                  @cli.wait
         | 
| 54 73 |  | 
| 55 74 | 
             
                  expect($stdout.string).to eq <<-eos
         | 
| 56 | 
            -
            Droplet name provided. Finding droplet ID...done\e[0m,  | 
| 75 | 
            +
            Droplet name provided. Finding droplet ID...done\e[0m, 6918990 (example.com)
         | 
| 57 76 | 
             
            Waiting for droplet to become active..done\e[0m (0s)
         | 
| 58 77 | 
             
            eos
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                  expect(a_request(:get, "https://api.digitalocean.com/droplets/100823?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
         | 
| 61 | 
            -
                  expect(a_request(:get, "https://api.digitalocean.com/droplets?api_key=#{api_key}&client_id=#{client_key}")).to have_been_made
         | 
| 62 78 | 
             
                end
         | 
| 63 79 |  | 
| 64 80 | 
             
              end
         | 
    
        data/spec/config_spec.rb
    CHANGED
    
    | @@ -23,23 +23,22 @@ describe Tugboat::Configuration do | |
| 23 23 | 
             
              end
         | 
| 24 24 |  | 
| 25 25 | 
             
              describe "the file" do
         | 
| 26 | 
            -
                let(: | 
| 27 | 
            -
                let(: | 
| 28 | 
            -
                let(: | 
| 29 | 
            -
                let(: | 
| 30 | 
            -
                let(: | 
| 31 | 
            -
                let(: | 
| 32 | 
            -
                let(: | 
| 33 | 
            -
                let(:size)               { "66" }
         | 
| 26 | 
            +
                let(:access_token)       { 'foo' }
         | 
| 27 | 
            +
                let(:ssh_user)           { 'root' }
         | 
| 28 | 
            +
                let(:ssh_key_path)       { '~/.ssh/id_rsa2' }
         | 
| 29 | 
            +
                let(:ssh_port)           { '22' }
         | 
| 30 | 
            +
                let(:region)             { 'lon1' }
         | 
| 31 | 
            +
                let(:image)              { 'ubuntu-14-04-x64' }
         | 
| 32 | 
            +
                let(:size)               { '512mb' }
         | 
| 34 33 | 
             
                let(:ssh_key_id)         { '1234' }
         | 
| 35 | 
            -
                let(:private_networking) { ' | 
| 36 | 
            -
                let(:backups_enabled)    { ' | 
| 34 | 
            +
                let(:private_networking) { 'false' }
         | 
| 35 | 
            +
                let(:backups_enabled)    { 'false' }
         | 
| 37 36 |  | 
| 38 37 | 
             
                let(:config)           { config = Tugboat::Configuration.instance }
         | 
| 39 38 |  | 
| 40 39 | 
             
                before :each do
         | 
| 41 40 | 
             
                  # Create a temporary file
         | 
| 42 | 
            -
                  config.create_config_file( | 
| 41 | 
            +
                  config.create_config_file(access_token, ssh_key_path, ssh_user, ssh_port, region, image, size, ssh_key_id, private_networking, backups_enabled)
         | 
| 43 42 | 
             
                end
         | 
| 44 43 |  | 
| 45 44 | 
             
                it "can be created" do
         | 
| @@ -62,14 +61,9 @@ describe Tugboat::Configuration do | |
| 62 61 | 
             
                  expect(data).to have_key("ssh")
         | 
| 63 62 | 
             
                end
         | 
| 64 63 |  | 
| 65 | 
            -
                it "should have  | 
| 64 | 
            +
                it "should have an access token" do
         | 
| 66 65 | 
             
                  auth = data["authentication"]
         | 
| 67 | 
            -
                  expect(auth).to have_key(" | 
| 68 | 
            -
                end
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                it "should have an api key" do
         | 
| 71 | 
            -
                  auth = data["authentication"]
         | 
| 72 | 
            -
                  expect(auth).to have_key("api_key")
         | 
| 66 | 
            +
                  expect(auth).to have_key("access_token")
         | 
| 73 67 | 
             
                end
         | 
| 74 68 |  | 
| 75 69 | 
             
                it "should have an ssh key path" do
         | 
| @@ -98,11 +92,11 @@ describe Tugboat::Configuration do | |
| 98 92 | 
             
                end
         | 
| 99 93 | 
             
              end
         | 
| 100 94 | 
             
              describe "backwards compatible" do
         | 
| 101 | 
            -
                let(:client_key)       {  | 
| 102 | 
            -
                let(:api_key)          {  | 
| 103 | 
            -
                let(:ssh_user)         {  | 
| 104 | 
            -
                let(:ssh_key_path)     {  | 
| 105 | 
            -
                let(:ssh_port)         {  | 
| 95 | 
            +
                let(:client_key)       { 'foo' }
         | 
| 96 | 
            +
                let(:api_key)          { 'bar' }
         | 
| 97 | 
            +
                let(:ssh_user)         { 'baz' }
         | 
| 98 | 
            +
                let(:ssh_key_path)     { '~/.ssh/id_rsa2' }
         | 
| 99 | 
            +
                let(:ssh_port)         { '22' }
         | 
| 106 100 |  | 
| 107 101 | 
             
                let(:config)                    { config = Tugboat::Configuration.instance }
         | 
| 108 102 | 
             
                let(:config_default_region)     { Tugboat::Configuration::DEFAULT_REGION }
         | 
| @@ -113,8 +107,8 @@ describe Tugboat::Configuration do | |
| 113 107 | 
             
                let(:config_default_backups)    { Tugboat::Configuration::DEFAULT_BACKUPS_ENABLED }
         | 
| 114 108 | 
             
                let(:backwards_config) {
         | 
| 115 109 | 
             
                  {
         | 
| 116 | 
            -
                             | 
| 117 | 
            -
                             | 
| 110 | 
            +
                            'authentication' => { 'client_key' => client_key, 'api_key' => api_key },
         | 
| 111 | 
            +
                            'ssh' => { 'ssh_user' => ssh_user, 'ssh_key_path' => ssh_key_path , 'ssh_port' => ssh_port},
         | 
| 118 112 | 
             
                  }
         | 
| 119 113 | 
             
                }
         | 
| 120 114 |  | 
| @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
              "droplet": {
         | 
| 3 | 
            +
                "id": 3164494,
         | 
| 4 | 
            +
                "name": "example.com",
         | 
| 5 | 
            +
                "memory": 512,
         | 
| 6 | 
            +
                "vcpus": 1,
         | 
| 7 | 
            +
                "disk": 20,
         | 
| 8 | 
            +
                "locked": true,
         | 
| 9 | 
            +
                "status": "new",
         | 
| 10 | 
            +
                "kernel": {
         | 
| 11 | 
            +
                  "id": 2233,
         | 
| 12 | 
            +
                  "name": "Ubuntu 14.04 x64 vmlinuz-3.13.0-37-generic",
         | 
| 13 | 
            +
                  "version": "3.13.0-37-generic"
         | 
| 14 | 
            +
                },
         | 
| 15 | 
            +
                "created_at": "2014-11-14T16:36:31Z",
         | 
| 16 | 
            +
                "features": [
         | 
| 17 | 
            +
                  "virtio"
         | 
| 18 | 
            +
                ],
         | 
| 19 | 
            +
                "backup_ids": [
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                ],
         | 
| 22 | 
            +
                "snapshot_ids": [
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                ],
         | 
| 25 | 
            +
                "image": {
         | 
| 26 | 
            +
                },
         | 
| 27 | 
            +
                "size": {
         | 
| 28 | 
            +
                },
         | 
| 29 | 
            +
                "size_slug": "512mb",
         | 
| 30 | 
            +
                "networks": {
         | 
| 31 | 
            +
                },
         | 
| 32 | 
            +
                "region": {
         | 
| 33 | 
            +
                }
         | 
| 34 | 
            +
              },
         | 
| 35 | 
            +
              "links": {
         | 
| 36 | 
            +
                "actions": [
         | 
| 37 | 
            +
                  {
         | 
| 38 | 
            +
                    "id": 36805096,
         | 
| 39 | 
            +
                    "rel": "create",
         | 
| 40 | 
            +
                    "href": "https://api.digitalocean.com/v2/actions/36805096"
         | 
| 41 | 
            +
                  }
         | 
| 42 | 
            +
                ]
         | 
| 43 | 
            +
              }
         | 
| 44 | 
            +
            }
         | 
| @@ -1,8 +1,8 @@ | |
| 1 1 | 
             
            {
         | 
| 2 | 
            -
              "status": "OK",
         | 
| 3 2 | 
             
              "ssh_key": {
         | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 3 | 
            +
                  "fingerprint": "f5:de:eb:64:2d:6a:b6:d5:bb:06:47:7f:04:4b:f8:e2",
         | 
| 4 | 
            +
                  "id": 3,
         | 
| 5 | 
            +
                  "name": "macbook_pro",
         | 
| 6 | 
            +
                  "public_key": "ssh-dss A123= user@host"
         | 
| 7 7 | 
             
              }
         | 
| 8 8 | 
             
            }
         | 
| @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
              "action": {
         | 
| 3 | 
            +
                "id": 3164494,
         | 
| 4 | 
            +
                "status": "in-progress",
         | 
| 5 | 
            +
                "type": "power_on",
         | 
| 6 | 
            +
                "started_at": "2014-11-14T16:31:19Z",
         | 
| 7 | 
            +
                "completed_at": null,
         | 
| 8 | 
            +
                "resource_id": 3164450,
         | 
| 9 | 
            +
                "resource_type": "droplet",
         | 
| 10 | 
            +
                "region": "nyc3",
         | 
| 11 | 
            +
                "region_slug": "nyc3"
         | 
| 12 | 
            +
              }
         | 
| 13 | 
            +
            }
         | 
| @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
              "action": {
         | 
| 3 | 
            +
                "id": 36804760,
         | 
| 4 | 
            +
                "status": "in-progress",
         | 
| 5 | 
            +
                "type": "password_reset",
         | 
| 6 | 
            +
                "started_at": "2014-11-14T16:31:25Z",
         | 
| 7 | 
            +
                "completed_at": null,
         | 
| 8 | 
            +
                "resource_id": 6918990,
         | 
| 9 | 
            +
                "resource_type": "droplet",
         | 
| 10 | 
            +
                "region": "nyc3",
         | 
| 11 | 
            +
                "region_slug": "nyc3"
         | 
| 12 | 
            +
              }
         | 
| 13 | 
            +
            }
         | 
| @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
              "action": {
         | 
| 3 | 
            +
                "id": 36804748,
         | 
| 4 | 
            +
                "status": "in-progress",
         | 
| 5 | 
            +
                "type": "reboot",
         | 
| 6 | 
            +
                "started_at": "2014-11-14T16:31:00Z",
         | 
| 7 | 
            +
                "completed_at": null,
         | 
| 8 | 
            +
                "resource_id": 6918990,
         | 
| 9 | 
            +
                "resource_type": "droplet",
         | 
| 10 | 
            +
                "region": "nyc3",
         | 
| 11 | 
            +
                "region_slug": "nyc3"
         | 
| 12 | 
            +
              }
         | 
| 13 | 
            +
            }
         | 
| @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
             "action": {
         | 
| 3 | 
            +
                "id": 36804888,
         | 
| 4 | 
            +
                "status": "in-progress",
         | 
| 5 | 
            +
                "type": "resize",
         | 
| 6 | 
            +
                "started_at": "2014-11-14T16:33:17Z",
         | 
| 7 | 
            +
                "completed_at": null,
         | 
| 8 | 
            +
                "resource_id": 6918990,
         | 
| 9 | 
            +
                "resource_type": "droplet",
         | 
| 10 | 
            +
                "region": "nyc3",
         | 
| 11 | 
            +
                "region_slug": "nyc3"
         | 
| 12 | 
            +
              }
         | 
| 13 | 
            +
            }
         | 
| @@ -0,0 +1,13 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
              "action": {
         | 
| 3 | 
            +
                "id": 36804748,
         | 
| 4 | 
            +
                "status": "in-progress",
         | 
| 5 | 
            +
                "type": "reboot",
         | 
| 6 | 
            +
                "started_at": "2014-11-14T16:31:00Z",
         | 
| 7 | 
            +
                "completed_at": null,
         | 
| 8 | 
            +
                "resource_id": 6918990,
         | 
| 9 | 
            +
                "resource_type": "droplet",
         | 
| 10 | 
            +
                "region": "nyc3",
         | 
| 11 | 
            +
                "region_slug": "nyc3"
         | 
| 12 | 
            +
              }
         | 
| 13 | 
            +
            }
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
                "image": {
         | 
| 3 | 
            +
                    "id": 12789325,
         | 
| 4 | 
            +
                    "name": "745.1.0 (alpha)",
         | 
| 5 | 
            +
                    "distribution": "CoreOS",
         | 
| 6 | 
            +
                    "slug": "coreos-alpha",
         | 
| 7 | 
            +
                    "public": true,
         | 
| 8 | 
            +
                    "regions": [
         | 
| 9 | 
            +
                    "nyc1",
         | 
| 10 | 
            +
                    "sfo1",
         | 
| 11 | 
            +
                    "nyc2",
         | 
| 12 | 
            +
                    "ams2",
         | 
| 13 | 
            +
                    "sgp1",
         | 
| 14 | 
            +
                    "lon1",
         | 
| 15 | 
            +
                    "nyc3",
         | 
| 16 | 
            +
                    "ams3",
         | 
| 17 | 
            +
                    "fra1"
         | 
| 18 | 
            +
                    ],
         | 
| 19 | 
            +
                    "created_at": "2015-07-17T13:34:11Z",
         | 
| 20 | 
            +
                    "min_disk_size": 20,
         | 
| 21 | 
            +
                    "type": "snapshot"
         | 
| 22 | 
            +
                }
         | 
| 23 | 
            +
            }
         | 
| @@ -1,14 +1,93 @@ | |
| 1 1 | 
             
            {
         | 
| 2 | 
            -
              "status": "OK",
         | 
| 3 2 | 
             
              "droplet": {
         | 
| 4 | 
            -
                " | 
| 5 | 
            -
                " | 
| 6 | 
            -
                " | 
| 7 | 
            -
                " | 
| 8 | 
            -
                " | 
| 9 | 
            -
                " | 
| 10 | 
            -
                " | 
| 11 | 
            -
                " | 
| 12 | 
            -
             | 
| 3 | 
            +
                "id": 6918990,
         | 
| 4 | 
            +
                "name": "example.com",
         | 
| 5 | 
            +
                "memory": 512,
         | 
| 6 | 
            +
                "vcpus": 1,
         | 
| 7 | 
            +
                "disk": 20,
         | 
| 8 | 
            +
                "locked": false,
         | 
| 9 | 
            +
                "status": "active",
         | 
| 10 | 
            +
                "kernel": {
         | 
| 11 | 
            +
                  "id": 2233,
         | 
| 12 | 
            +
                  "name": "Ubuntu 14.04 x64 vmlinuz-3.13.0-37-generic",
         | 
| 13 | 
            +
                  "version": "3.13.0-37-generic"
         | 
| 14 | 
            +
                },
         | 
| 15 | 
            +
                "created_at": "2014-11-14T16:36:31Z",
         | 
| 16 | 
            +
                "features": [
         | 
| 17 | 
            +
                  "ipv6",
         | 
| 18 | 
            +
                  "virtio"
         | 
| 19 | 
            +
                ],
         | 
| 20 | 
            +
                "backup_ids": [
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                ],
         | 
| 23 | 
            +
                "snapshot_ids": [
         | 
| 24 | 
            +
                  7938206
         | 
| 25 | 
            +
                ],
         | 
| 26 | 
            +
                "image": {
         | 
| 27 | 
            +
                  "id": 6918990,
         | 
| 28 | 
            +
                  "name": "14.04 x64",
         | 
| 29 | 
            +
                  "distribution": "Ubuntu",
         | 
| 30 | 
            +
                  "slug": "ubuntu-14-04-x64",
         | 
| 31 | 
            +
                  "public": true,
         | 
| 32 | 
            +
                  "regions": [
         | 
| 33 | 
            +
                    "nyc1",
         | 
| 34 | 
            +
                    "ams1",
         | 
| 35 | 
            +
                    "sfo1",
         | 
| 36 | 
            +
                    "nyc2",
         | 
| 37 | 
            +
                    "ams2",
         | 
| 38 | 
            +
                    "sgp1",
         | 
| 39 | 
            +
                    "lon1",
         | 
| 40 | 
            +
                    "nyc3",
         | 
| 41 | 
            +
                    "ams3",
         | 
| 42 | 
            +
                    "nyc3"
         | 
| 43 | 
            +
                  ],
         | 
| 44 | 
            +
                  "created_at": "2014-10-17T20:24:33Z",
         | 
| 45 | 
            +
                  "type": "snapshot",
         | 
| 46 | 
            +
                  "min_disk_size": 20
         | 
| 47 | 
            +
                },
         | 
| 48 | 
            +
                "size": {
         | 
| 49 | 
            +
                },
         | 
| 50 | 
            +
                "size_slug": "512mb",
         | 
| 51 | 
            +
                "networks": {
         | 
| 52 | 
            +
                  "v4": [
         | 
| 53 | 
            +
                    {
         | 
| 54 | 
            +
                      "ip_address": "104.131.186.241",
         | 
| 55 | 
            +
                      "netmask": "255.255.240.0",
         | 
| 56 | 
            +
                      "gateway": "104.131.176.1",
         | 
| 57 | 
            +
                      "type": "public"
         | 
| 58 | 
            +
                    }
         | 
| 59 | 
            +
                  ],
         | 
| 60 | 
            +
                  "v6": [
         | 
| 61 | 
            +
                    {
         | 
| 62 | 
            +
                      "ip_address": "2604:A880:0800:0010:0000:0000:031D:2001",
         | 
| 63 | 
            +
                      "netmask": 64,
         | 
| 64 | 
            +
                      "gateway": "2604:A880:0800:0010:0000:0000:0000:0001",
         | 
| 65 | 
            +
                      "type": "public"
         | 
| 66 | 
            +
                    }
         | 
| 67 | 
            +
                  ]
         | 
| 68 | 
            +
                },
         | 
| 69 | 
            +
                "region": {
         | 
| 70 | 
            +
                  "name": "New York 3",
         | 
| 71 | 
            +
                  "slug": "nyc3",
         | 
| 72 | 
            +
                  "sizes": [
         | 
| 73 | 
            +
                    "32gb",
         | 
| 74 | 
            +
                    "16gb",
         | 
| 75 | 
            +
                    "2gb",
         | 
| 76 | 
            +
                    "1gb",
         | 
| 77 | 
            +
                    "4gb",
         | 
| 78 | 
            +
                    "8gb",
         | 
| 79 | 
            +
                    "512mb",
         | 
| 80 | 
            +
                    "64gb",
         | 
| 81 | 
            +
                    "48gb"
         | 
| 82 | 
            +
                  ],
         | 
| 83 | 
            +
                  "features": [
         | 
| 84 | 
            +
                    "virtio",
         | 
| 85 | 
            +
                    "private_networking",
         | 
| 86 | 
            +
                    "backups",
         | 
| 87 | 
            +
                    "ipv6",
         | 
| 88 | 
            +
                    "metadata"
         | 
| 89 | 
            +
                  ],
         | 
| 90 | 
            +
                  "available": true
         | 
| 91 | 
            +
                }
         | 
| 13 92 | 
             
              }
         | 
| 14 | 
            -
            }
         | 
| 93 | 
            +
            }
         |