marathon-api 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +2 -2
  3. data/.travis.yml +1 -1
  4. data/README.md +40 -14
  5. data/bin/marathon +242 -0
  6. data/fixtures/marathon_docker_sample_2.json +2 -1
  7. data/fixtures/vcr/Marathon_App/_restart/restarts_an_app.yml +32 -0
  8. data/fixtures/vcr/Marathon_Group/_changes/changes_the_group.yml +61 -0
  9. data/fixtures/vcr/Marathon_Group/_delete/deletes_the_group.yml +32 -0
  10. data/fixtures/vcr/Marathon_Group/_delete/fails_deleting_not_existing_app.yml +32 -0
  11. data/fixtures/vcr/Marathon_Group/_get/fails_getting_not_existing_app.yml +32 -0
  12. data/fixtures/vcr/Marathon_Group/_get/gets_the_group.yml +32 -0
  13. data/fixtures/vcr/Marathon_Group/_list/lists_apps.yml +33 -0
  14. data/fixtures/vcr/Marathon_Group/_start/fails_getting_not_existing_group.yml +32 -0
  15. data/fixtures/vcr/Marathon_Group/_start/starts_the_group.yml +35 -0
  16. data/lib/marathon.rb +33 -5
  17. data/lib/marathon/app.rb +72 -22
  18. data/lib/marathon/base.rb +32 -0
  19. data/lib/marathon/connection.rb +32 -22
  20. data/lib/marathon/constraint.rb +39 -0
  21. data/lib/marathon/container.rb +41 -0
  22. data/lib/marathon/container_docker.rb +33 -0
  23. data/lib/marathon/container_docker_port_mapping.rb +32 -0
  24. data/lib/marathon/container_volume.rb +31 -0
  25. data/lib/marathon/deployment.rb +5 -15
  26. data/lib/marathon/deployment_info.rb +20 -0
  27. data/lib/marathon/error.rb +8 -2
  28. data/lib/marathon/group.rb +166 -0
  29. data/lib/marathon/health_check.rb +35 -0
  30. data/lib/marathon/queue.rb +4 -13
  31. data/lib/marathon/task.rb +15 -12
  32. data/lib/marathon/util.rb +47 -3
  33. data/lib/marathon/version.rb +1 -1
  34. data/marathon-api.gemspec +4 -3
  35. data/spec/marathon/app_spec.rb +108 -50
  36. data/spec/marathon/base_spec.rb +53 -0
  37. data/spec/marathon/connection_spec.rb +1 -1
  38. data/spec/marathon/constraint_spec.rb +27 -0
  39. data/spec/marathon/container_docker_port_mapping_spec.rb +55 -0
  40. data/spec/marathon/container_docker_spec.rb +42 -0
  41. data/spec/marathon/container_spec.rb +40 -0
  42. data/spec/marathon/container_volume_spec.rb +50 -0
  43. data/spec/marathon/deployment_info_spec.rb +43 -0
  44. data/spec/marathon/deployment_spec.rb +15 -16
  45. data/spec/marathon/error_spec.rb +17 -0
  46. data/spec/marathon/group_spec.rb +172 -0
  47. data/spec/marathon/health_check_spec.rb +50 -0
  48. data/spec/marathon/marathon_spec.rb +31 -0
  49. data/spec/marathon/queue_spec.rb +2 -2
  50. data/spec/marathon/task_spec.rb +24 -11
  51. data/spec/marathon/util_spec.rb +21 -1
  52. metadata +58 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 43d4d0f2016049fc44bde4ee4ffe6789de4631c0
4
- data.tar.gz: 03579636a8d4577d7e8dc2ba1098eeb67b099ad2
3
+ metadata.gz: 23bb47d2d3c76218c3aa461968660ac5551e3f76
4
+ data.tar.gz: ce1149c5f48884ecd403b69e61fb9ab12f8e0b3b
5
5
  SHA512:
6
- metadata.gz: fe8feb603efd0ebe26e33ccd4cc3a406906a3dcef67e15e8f4b14393a239a8a01995de5e2d77fc89cc980d900319e1ee011b77caca1c7894bd03850be697a484
7
- data.tar.gz: c0f7768067d89be77eb44e179636e40e9533722697555bc65fbe84c090d7307e0980016f0dcd52533bc965e4599af4cbcd9ade1b7ebb389933dc8358ddabe08b
6
+ metadata.gz: 7fca9778495fc930fe67d956a7db8e749f08c56e2e0bcce4320bac3dfbf94ac6d1025909135c573e06938fa2c27705b1a2d7f774a8713830192d768c27990faa
7
+ data.tar.gz: 6301fea04cd2a18a89aa6dd59a52c46b79d2ee8a6a580131783661c249021e75750aa758c19c7efad99dad13621e24243f64270654f29b6d3aa672c75f00684d
data/.simplecov CHANGED
@@ -1,5 +1,5 @@
1
1
  SimpleCov.start do
2
2
  add_group 'Library', 'lib'
3
- add_group 'Specs', 'spec'
4
- add_filter '/vendor/'
3
+ add_filter '/vendor'
4
+ add_filter '/spec'
5
5
  end
@@ -6,5 +6,5 @@ rvm:
6
6
  - 2.2.0
7
7
  env:
8
8
  global:
9
- - CODECLIMATE_REPO_TOKEN=8e7c316d892f832fa3de24bc2e88bf0d243e09947ea95319afcafcdb10f5eb3c
9
+ - CODECLIMATE_REPO_TOKEN=a0f25c19629dd353c43aef0cbbd886a7a4079c2238711fa4f932e1477b818195
10
10
  script: bundle exec rake
data/README.md CHANGED
@@ -1,46 +1,72 @@
1
1
  marathon-api
2
2
  ============
3
3
 
4
- [![travis-ci](https://travis-ci.org/felixb/marathon-api.png?branch=master)](https://travis-ci.org/felixb/marathon-api) [![Code Climate](https://codeclimate.com/github/felixb/marathon-api/badges/gpa.svg)](https://codeclimate.com/github/felixb/marathon-api) [![Test Coverage](https://codeclimate.com/github/felixb/marathon-api/badges/coverage.svg)](https://codeclimate.com/github/felixb/marathon-api)
4
+ [![Gem Version](https://badge.fury.io/rb/marathon-api.svg)](http://badge.fury.io/rb/marathon-api) [![travis-ci](https://travis-ci.org/otto-de/marathon-api.png?branch=master)](https://travis-ci.org/otto-de/marathon-api) [![Code Climate](https://codeclimate.com/github/otto-de/marathon-api/badges/gpa.svg)](https://codeclimate.com/github/otto-de/marathon-api) [![Test Coverage](https://codeclimate.com/github/otto-de/marathon-api/badges/coverage.svg)](https://codeclimate.com/github/otto-de/marathon-api)
5
5
 
6
6
  This gem provides an object oriented interface to the [Marathon Remote API][1]. At the time if this writing, marathon-api is meant to interface with Marathon version 0.8.0.
7
7
 
8
8
  Installation
9
9
  ------------
10
10
 
11
- Add this line to your application's Gemfile=>
11
+ Add this line to your application's Gemfile:
12
12
 
13
13
  ```ruby
14
- gem 'docker-api', =>require => 'docker', =>git => 'https=>//github.com/felixb/marathon-api.git'
14
+ gem 'marathon-api', :require => 'marathon'
15
15
  ```
16
16
 
17
- And then run=>
17
+ And then run:
18
18
 
19
19
  ```shell
20
20
  $ bundle install
21
21
  ```
22
22
 
23
- Finally, just add `require 'marathon'` to the top of the file using this gem.
23
+ Alternatively, if you wish to just use the gem in a script, you can run:
24
+
25
+ ```shell
26
+ $ gem install marathon-api
27
+ ```
28
+
29
+ Finally, just add `require 'marathon'` to the top of the file using this gem.
24
30
 
25
31
  Usage
26
32
  -----
27
33
 
28
34
  marathon-api is designed to be very lightweight. Only little state is cached to ensure that each method call's information is up to date. As such, just about every external method represents an API call.
29
35
 
30
- If you're running Marathon locally on port 8080, there is no setup to do in Ruby. If you're not or change the path or port, you'll have to point the gem to your socket or local/remote port. For example=>
36
+ If you're running Marathon locally on port 8080, there is no setup to do in Ruby. If you're not or change the path or port, you'll have to point the gem to your socket or local/remote port. For example:
37
+
38
+ ```ruby
39
+ Marathon.url = 'http://example.com:8080'
40
+ ```
41
+
42
+ It's possible to use `ENV` variables to configure the endpoint as well:
43
+
44
+ ```shell
45
+ $ MARATHON_URL=http://remote.marathon.example.com:8080 irb
46
+ irb(main):001:0> require 'marathon'
47
+ => true
48
+ irb(main):002:0> Marathon.url
49
+ => "http://remote.marathon.example.com:8080"
50
+ ```
51
+
52
+ ## Authentification
53
+
54
+ You have two options to set authentification if your Marathon API requires it:
31
55
 
32
56
  ```ruby
33
- Marathon.url = 'http=>//example.com=>8080'
57
+ Marathon.options = {:username => 'your-user-name', :password => 'your-secret-password'}
34
58
  ```
35
59
 
36
- It's possible to use `ENV` variables to configure the endpoint as well=>
60
+ or
37
61
 
38
62
  ```shell
39
- $ MARATHON_URL=http=>//remote.marathon.example.com=>8080 irb
40
- irb(main)=>001=>0> require 'marathon'
63
+ $ export MARATHON_USER=your-user-name
64
+ $ export MARATHON_PASSWORD=your-secret-password
65
+ $ irb
66
+ irb(main):001:0> require 'marathon'
41
67
  => true
42
- irb(main)=>002=>0> Marathon.url
43
- => "http=>//remote.marathon.example.com=>8080"
68
+ irb(main):002:0> Marathon.options
69
+ => {:username => "your-user-name", :password => "your-secret-password"}
44
70
  ```
45
71
 
46
72
  ## Global calls
@@ -50,7 +76,7 @@ require 'marathon'
50
76
  # => true
51
77
 
52
78
  Marathon.info
53
- # => {"name"=>"marathon", "http_config"=>{"assets_path"=>null, "http_port"=>8080, "https_port"=>8443}, "frameworkId"=>"20150228-110436-16842879-5050-2169-0001", "leader"=>null, "event_subscriber"=>null, "marathon_config"=>{"local_port_max"=>20000, "local_port_min"=>10000, "hostname"=>"mesos", "master"=>"zk=>//localhost=>2181/mesos", "reconciliation_interval"=>300000, "mesos_role"=>null, "task_launch_timeout"=>300000, "reconciliation_initial_delay"=>15000, "ha"=>true, "failover_timeout"=>604800, "checkpoint"=>true, "executor"=>"//cmd", "marathon_store_timeout"=>2000, "mesos_user"=>"root"}, "version"=>"0.8.0", "zookeeper_config"=>{"zk_path"=>"/marathon", "zk"=>null, "zk_timeout"=>10, "zk_hosts"=>"localhost=>2181", "zk_future_timeout"=>{"duration"=>10}}, "elected"=>false}
79
+ # => {"name"=>"marathon", "http_config"=>{"assets_path"=>null, "http_port"=>8080, "https_port"=>8443}, "frameworkId"=>"20150228-110436-16842879-5050-2169-0001", "leader"=>null, "event_subscriber"=>null, "marathon_config"=>{"local_port_max"=>20000, "local_port_min"=>10000, "hostname"=>"mesos", "master"=>"zk://localhost:2181/mesos", "reconciliation_interval"=>300000, "mesos_role"=>null, "task_launch_timeout"=>300000, "reconciliation_initial_delay"=>15000, "ha"=>true, "failover_timeout"=>604800, "checkpoint"=>true, "executor"=>"//cmd", "marathon_store_timeout"=>2000, "mesos_user"=>"root"}, "version"=>"0.8.0", "zookeeper_config"=>{"zk_path"=>"/marathon", "zk"=>null, "zk_timeout"=>10, "zk_hosts"=>"localhost:2181", "zk_future_timeout"=>{"duration"=>10}}, "elected"=>false}
54
80
 
55
81
  Docker.ping
56
82
  # => 'pong'
@@ -88,4 +114,4 @@ This program is licensed under the MIT license. See LICENSE for details.
88
114
 
89
115
  [1]: https://mesosphere.github.io/marathon/docs/rest-api.html
90
116
  [2]: https://github.com/mesosphere/marathon_client
91
- [3]: https://github.com/swipely/docker-api
117
+ [3]: https://github.com/swipely/docker-api
@@ -0,0 +1,242 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'marathon'))
4
+ require 'trollop'
5
+ require 'json'
6
+
7
+ SUB_COMMANDS = %w[kill kill_tasks start scale list list_tasks search]
8
+ ATTRIBUTES = [:id, :cmd, :executor, :instances, :cpus, :mem, :uris]
9
+ DEFAULT_APP_OPTS = {
10
+ :instances => 1,
11
+ :cpus => 1,
12
+ :mem => 10,
13
+ }
14
+
15
+ # print a list of apps to STDOUT
16
+ def print_apps(apps)
17
+ if apps.empty?
18
+ puts "No apps currently running"
19
+ else
20
+ apps.each do |app|
21
+ puts app.to_pretty_s
22
+ puts
23
+ end
24
+ end
25
+ end
26
+
27
+ # print a list of tasks to STDOUT
28
+ def print_tasks(tasks)
29
+ if tasks.empty?
30
+ puts "No tasks currently running"
31
+ else
32
+ tasks.each do |task|
33
+ puts task.to_pretty_s
34
+ puts
35
+ end
36
+ end
37
+ end
38
+
39
+ def subcmd_list(cmd_opts)
40
+ apps = Marathon::App.list(cmd_opts[:command], 'apps.tasks')
41
+ print_apps(apps)
42
+ end
43
+
44
+ def subcmd_start(cmd_opts)
45
+ begin
46
+ if cmd_opts[:json]
47
+ path = cmd_opts[:json]
48
+ if path == '-'
49
+ app_opts = Marathon::Util.keywordize_hash(JSON.parse($stdin.read))
50
+ elsif File.exists?(path)
51
+ app_opts = Marathon::Util.keywordize_hash(JSON.parse(File.read(cmd_opts[:json])))
52
+ else
53
+ raise Marathon::Error::ArgumentError, "File '#{path}' does not exist"
54
+ end
55
+ else
56
+ app_opts = DEFAULT_APP_OPTS
57
+ end
58
+ app_opts.merge!(cmd_opts.select { |k,_| ATTRIBUTES.include?(k) and cmd_opts["#{k.id2name}_given".to_sym] })
59
+ if cmd_opts[:env]
60
+ app_opts[:env] = Hash[cmd_opts[:env].map { |e| e.split('=', 2) }]
61
+ end
62
+ if cmd_opts[:constraints]
63
+ app_opts[:constraints] = cmd_opts[:constraint].map { |c| c.split(':') }
64
+ end
65
+ app = Marathon::App.new(app_opts)
66
+ puts "Starting app '#{app}'"
67
+ app.start!
68
+ print_apps([app])
69
+ rescue Marathon::Error::MarathonError => e
70
+ puts "#{e.class}: #{e.message}"
71
+ exit 1
72
+ end
73
+ end
74
+
75
+ def subcmd_scale(cmd_opts)
76
+ begin
77
+ app = Marathon::App.get(cmd_opts[:id])
78
+ puts "Scaling app '#{app.id}' from #{app.instances} to #{cmd_opts[:instances]}"
79
+ puts app.scale!(cmd_opts[:instances], cmd_opts[:force])
80
+ rescue Marathon::Error::NotFoundError => e
81
+ puts "#{e.class}: #{e.message}"
82
+ exit 1
83
+ end
84
+ end
85
+
86
+ def subcmd_kill(cmd_opts)
87
+ begin
88
+ puts "Removing app '#{cmd_opts[:id]}'"
89
+ Marathon::App.delete(cmd_opts[:id])
90
+ puts 'done'
91
+ rescue Marathon::Error::NotFoundError => e
92
+ puts "#{e.class}: #{e.message}"
93
+ exit 1
94
+ end
95
+ end
96
+
97
+ def subcmd_list_tasks(cmd_opts)
98
+ if cmd_opts[:id]
99
+ tasks = Marathon::Task.get(cmd_opts[:id])
100
+ else
101
+ tasks = Marathon::Task.list
102
+ end
103
+ print_tasks(tasks)
104
+ end
105
+
106
+ def subcmd_kill_tasks(cmd_opts)
107
+ if cmd_opts[:task_id]
108
+ puts "Killing task of '#{cmd_opts[:id]}' with id '#{cmd_opts[:task_id]}'"
109
+ tasks = [Marathon::Task.delete(cmd_opts[:id], cmd_opts[:task_id], cmd_opts[:scale])]
110
+ elsif cmd_opts[:host]
111
+ puts "Killing tasks of '#{cmd_opts[:id]}' on host '#{cmd_opts[:host]}'"
112
+ tasks = Marathon::Task.delete_all(cmd_opts[:id], cmd_opts[:host], cmd_opts[:scale])
113
+ else
114
+ puts "Killing tasks of '#{cmd_opts[:id]}'"
115
+ tasks = Marathon::Task.delete_all(cmd_opts[:id], nil, cmd_opts[:scale])
116
+ end
117
+ print_tasks(tasks)
118
+ end
119
+
120
+ # parse global options
121
+ def parse_global_opts
122
+ global_opts = Trollop.options do
123
+ version Marathon::VERSION
124
+ banner <<-EOS
125
+ Usage: marathon [global options] [command] [options]
126
+
127
+ Available commands:
128
+
129
+ kill Kill an app and remove it from Marathon.
130
+ kill_tasks Kill a task or tasks belonging to a specified app.
131
+ list Show a list of running apps and their options.
132
+ list_tasks Show a list of an app's running tasks.
133
+ scale Scale the number of app instances.
134
+ search Search the current list of apps.
135
+ start Start a new app.
136
+
137
+ Global options:
138
+ EOS
139
+
140
+ opt :url, 'Marathon host (default http://localhost:8080, or MARATHON_HOST)',
141
+ :short => '-M', :type => String
142
+ opt :username, 'User name to authenticate against Marathon (optional, default unset, or MARATHON_USER).',
143
+ :short => '-U', :type => String
144
+ opt :password, 'Password to authenticate against Marathon (optional, default unset, or MARATHON_PASSWORD).',
145
+ :short => '-P', :type => String
146
+ stop_on SUB_COMMANDS
147
+ end
148
+ return global_opts
149
+ end
150
+
151
+ # set global options to Marathon API
152
+ def set_global_opts(global_opts)
153
+ # Set client's URL
154
+ Marathon.url = global_opts[:url] if global_opts[:url]
155
+ global_opts.delete(:url)
156
+ # Set client's options
157
+ Marathon.options = global_opts if global_opts.size > 0
158
+ end
159
+
160
+ # get the subcommand
161
+ def parse_subcmd
162
+ cmd = ARGV.shift
163
+ return cmd
164
+ end
165
+
166
+ # parse subcommand specific options
167
+ def parse_subcmd_opts(cmd)
168
+ cmd_opts = case cmd
169
+ when 'list'
170
+ Trollop.options do
171
+ opt :command, 'The command for the app.', :short => '-C', :type => String
172
+ end
173
+ when 'start'
174
+ Trollop.options do
175
+ opt :json, 'A json formatted file to read application details from. (use - to read from stdin)', :short => '-j', :type => String
176
+ opt :id, 'A unique identifier for the app.', :short => '-i', :type => String
177
+ opt :cmd, 'The command to start the app.', :short => '-C', :type => String
178
+ opt :executor, 'The mesos executor to be used to launch the app.', :short => '-X', :type => String
179
+ opt :instances, 'The number of instances to run (default 1).', :default => 1, :short => '-n'
180
+ opt :cpus, 'The number of CPUs to give to this app, can be a fraction (default 1.0).', :short => '-c'
181
+ opt :mem, 'The memory limit for this app, in MB, can be a fraction (default 10.0).', :short => '-m'
182
+ opt :uri, 'URIs to download and unpack into the working directory.', :short => '-u', :type => :strings
183
+ opt :env, 'Environment variables to add to the process, as NAME=VALUE.', :short => '-e', :type => :strings
184
+ opt :constraint, 'Placement constraint for tasks, e.g. hostname:UNIQUE or rackid:CLUSTER', :type => :strings
185
+ end
186
+ when 'scale'
187
+ Trollop.options do
188
+ opt :id, 'A unique identifier for the app.', :short => '-i', :type => String, :required => true
189
+ opt :instances, 'The number of instances to run.', :short => '-n', :type => Integer, :required => true
190
+ opt :force, 'The current deployment can be overridden by setting the `force`.', :short => '-f'
191
+ end
192
+ when 'kill'
193
+ Trollop.options do
194
+ opt :id, 'A unique identifier for the app.', :short => '-i', :type => String, :required => true
195
+ end
196
+ when 'list_tasks'
197
+ Trollop.options do
198
+ opt :id, 'A unique identifier for the app.', :short => '-i', :type => String, :default => nil
199
+ end
200
+ when 'kill_tasks'
201
+ Trollop.options do
202
+ opt :host, 'Scope task killing to the given host.', :short => '-H', :type => String
203
+ opt :id, 'A unique identifier for the app.', :short => '-i', :type => String, :required => true
204
+ opt :scale, 'If true, the app is scaled down after killing tasks', :short => '-s'
205
+ opt :task_id, 'A unique identifier for the task.', :short => '-t', :type => String
206
+ end
207
+ else
208
+ {}
209
+ end
210
+
211
+ return cmd_opts
212
+ end
213
+
214
+ # Run selected subcmd
215
+ def run_subcmd(cmd, cmd_opts)
216
+ case cmd
217
+ when 'list'
218
+ subcmd_list(cmd_opts)
219
+ when 'start'
220
+ subcmd_start(cmd_opts)
221
+ when 'scale'
222
+ subcmd_scale(cmd_opts)
223
+ when 'kill'
224
+ subcmd_kill(cmd_opts)
225
+ when 'list_tasks'
226
+ subcmd_list_tasks(cmd_opts)
227
+ when 'kill_tasks'
228
+ subcmd_kill_tasks(cmd_opts)
229
+ else
230
+ Trollop.die "unknown subcommand #{cmd.inspect}"
231
+ end
232
+ end
233
+
234
+ if __FILE__ == $0
235
+ global_opts = parse_global_opts
236
+ set_global_opts(global_opts)
237
+
238
+ cmd = parse_subcmd
239
+ cmd_opts = parse_subcmd_opts(cmd)
240
+
241
+ run_subcmd(cmd, cmd_opts)
242
+ end
@@ -10,5 +10,6 @@
10
10
  "cpus": 0.1,
11
11
  "mem": 64,
12
12
  "uris": [],
13
- "cmd": "while sleep 10; do date -u +%T; done"
13
+ "cmd": "while sleep 10; do date -u +%T; done",
14
+ "constraints": [["hostname", "GROUP_BY"]]
14
15
  }
@@ -0,0 +1,32 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://localhost:8080/v2/apps//ubuntu2/restart
6
+ body:
7
+ encoding: UTF-8
8
+ string: ''
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ Accept:
13
+ - application/json
14
+ User-Agent:
15
+ - ub0r/Marathon-API 0.9.0
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Content-Type:
22
+ - application/json
23
+ Transfer-Encoding:
24
+ - chunked
25
+ Server:
26
+ - Jetty(8.y.z-SNAPSHOT)
27
+ body:
28
+ encoding: UTF-8
29
+ string: '{"version":"2015-03-07T14:15:30.159Z","deploymentId":"d38f8d55-b8b0-4893-ab16-ae474e282263"}'
30
+ http_version:
31
+ recorded_at: Sat, 07 Mar 2015 14:15:30 GMT
32
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,61 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: put
5
+ uri: http://localhost:8080/v2/groups//ubuntu2
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"instances":2}'
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ Accept:
13
+ - application/json
14
+ User-Agent:
15
+ - ub0r/Marathon-API 0.9.0
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Content-Type:
22
+ - application/json
23
+ Transfer-Encoding:
24
+ - chunked
25
+ Server:
26
+ - Jetty(8.y.z-SNAPSHOT)
27
+ body:
28
+ encoding: UTF-8
29
+ string: '{"version":"2015-03-09T10:33:40.511Z","deploymentId":"4186c1d4-80a8-4cf2-a606-cc9e93680c13"}'
30
+ http_version:
31
+ recorded_at: Mon, 09 Mar 2015 10:33:40 GMT
32
+ - request:
33
+ method: put
34
+ uri: http://localhost:8080/v2/groups//ubuntu2?force=true
35
+ body:
36
+ encoding: UTF-8
37
+ string: '{"instances":1}'
38
+ headers:
39
+ Content-Type:
40
+ - application/json
41
+ Accept:
42
+ - application/json
43
+ User-Agent:
44
+ - ub0r/Marathon-API 0.9.0
45
+ response:
46
+ status:
47
+ code: 200
48
+ message: OK
49
+ headers:
50
+ Content-Type:
51
+ - application/json
52
+ Transfer-Encoding:
53
+ - chunked
54
+ Server:
55
+ - Jetty(8.y.z-SNAPSHOT)
56
+ body:
57
+ encoding: UTF-8
58
+ string: '{"version":"2015-03-09T10:33:40.730Z","deploymentId":"72ad642f-90ba-4fec-8470-9abec46c47c3"}'
59
+ http_version:
60
+ recorded_at: Mon, 09 Mar 2015 10:33:40 GMT
61
+ recorded_with: VCR 2.9.3