marathon-api 0.9.0 → 1.0.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.
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
@@ -0,0 +1,32 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: delete
5
+ uri: http://localhost:8080/v2/groups//test-group?force=true
6
+ body:
7
+ encoding: US-ASCII
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-09T10:33:40.335Z","deploymentId":"c5ad3775-a422-48f0-99ee-e7e7f098a832"}'
30
+ http_version:
31
+ recorded_at: Mon, 09 Mar 2015 10:33:40 GMT
32
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,32 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: delete
5
+ uri: http://localhost:8080/v2/groups/fooo%20group
6
+ body:
7
+ encoding: US-ASCII
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: 404
19
+ message: Not Found
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: '{"message":"Group ''/fooo group'' does not exist"}'
30
+ http_version:
31
+ recorded_at: Mon, 09 Mar 2015 10:33:40 GMT
32
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,32 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://localhost:8080/v2/groups/fooo%20group
6
+ body:
7
+ encoding: US-ASCII
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: 404
19
+ message: Not Found
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: '{"message":"Group ''/fooo group'' does not exist"}'
30
+ http_version:
31
+ recorded_at: Mon, 09 Mar 2015 10:33:40 GMT
32
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,32 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://localhost:8080/v2/groups//test-group
6
+ body:
7
+ encoding: US-ASCII
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: '{"id":"/test-group","apps":[{"id":"/test-group/app","cmd":"sleep 30","args":null,"user":null,"env":{},"instances":1,"cpus":1.0,"mem":128.0,"disk":0.0,"executor":"","constraints":[],"uris":[],"storeUrls":[],"ports":[10000],"requirePorts":false,"backoffSeconds":1,"backoffFactor":1.15,"maxLaunchDelaySeconds":3600,"container":null,"healthChecks":[],"dependencies":[],"upgradeStrategy":{"minimumHealthCapacity":1.0,"maximumOverCapacity":0.0},"labels":{},"version":"2015-03-09T10:33:39.889Z"}],"groups":[],"dependencies":[],"version":"2015-03-09T10:33:39.889Z"}'
30
+ http_version:
31
+ recorded_at: Mon, 09 Mar 2015 10:33:40 GMT
32
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,33 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://localhost:8080/v2/groups
6
+ body:
7
+ encoding: US-ASCII
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: '{"id":"/","apps":[],"groups":[{"id":"/ubuntu2","apps":[],"groups":[],"dependencies":[],"version":"2015-03-09T10:33:39.889Z"},{"id":"/test-group","apps":[{"id":"/test-group/app","cmd":"sleep
30
+ 30","args":null,"user":null,"env":{},"instances":1,"cpus":1.0,"mem":128.0,"disk":0.0,"executor":"","constraints":[],"uris":[],"storeUrls":[],"ports":[10000],"requirePorts":false,"backoffSeconds":1,"backoffFactor":1.15,"maxLaunchDelaySeconds":3600,"container":null,"healthChecks":[],"dependencies":[],"upgradeStrategy":{"minimumHealthCapacity":1.0,"maximumOverCapacity":0.0},"labels":{},"version":"2015-03-09T10:33:39.889Z"}],"groups":[],"dependencies":[],"version":"2015-03-09T10:33:39.889Z"}],"dependencies":[],"version":"2015-03-09T10:33:39.889Z"}'
31
+ http_version:
32
+ recorded_at: Mon, 09 Mar 2015 10:33:40 GMT
33
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,32 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://localhost:8080/v2/groups/fooo%20group
6
+ body:
7
+ encoding: US-ASCII
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: 404
19
+ message: Not Found
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: '{"message":"Group ''/fooo group'' does not exist"}'
30
+ http_version:
31
+ recorded_at: Mon, 09 Mar 2015 10:33:40 GMT
32
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,35 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://localhost:8080/v2/groups
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"id":"/test-group","apps":[{"backoffFactor":1.15,"backoffSeconds":1,"maxLaunchDelaySeconds":3600,"cmd":"sleep
9
+ 30","constraints":[],"cpus":1.0,"dependencies":[],"disk":0.0,"env":{},"executor":"","id":"app","instances":1,"mem":128.0,"ports":[10000],"requirePorts":false,"storeUrls":[],"upgradeStrategy":{"minimumHealthCapacity":1.0},"tasks":[]}],"dependencies":[],"groups":[]}'
10
+ headers:
11
+ Content-Type:
12
+ - application/json
13
+ Accept:
14
+ - application/json
15
+ User-Agent:
16
+ - ub0r/Marathon-API 0.9.0
17
+ response:
18
+ status:
19
+ code: 201
20
+ message: Created
21
+ headers:
22
+ Location:
23
+ - http://localhost:8080/v2/groups/test-group
24
+ Content-Type:
25
+ - application/json
26
+ Transfer-Encoding:
27
+ - chunked
28
+ Server:
29
+ - Jetty(8.y.z-SNAPSHOT)
30
+ body:
31
+ encoding: UTF-8
32
+ string: '{"version":"2015-03-09T10:33:39.889Z","deploymentId":"ad618509-e8ee-4949-8267-ef35a619426f"}'
33
+ http_version:
34
+ recorded_at: Mon, 09 Mar 2015 10:33:40 GMT
35
+ recorded_with: VCR 2.9.3
@@ -9,16 +9,25 @@ module Marathon
9
9
 
10
10
  attr_accessor :logger
11
11
 
12
+ require 'marathon/version'
12
13
  require 'marathon/util'
13
14
  require 'marathon/error'
14
15
  require 'marathon/connection'
16
+ require 'marathon/base'
17
+ require 'marathon/constraint'
18
+ require 'marathon/container_docker_port_mapping'
19
+ require 'marathon/container_docker'
20
+ require 'marathon/container_volume'
21
+ require 'marathon/container'
22
+ require 'marathon/health_check'
23
+ require 'marathon/deployment_info'
24
+ require 'marathon/group'
15
25
  require 'marathon/app'
16
26
  require 'marathon/deployment'
17
27
  require 'marathon/event_subscriptions'
18
28
  require 'marathon/leader'
19
29
  require 'marathon/queue'
20
30
  require 'marathon/task'
21
- require 'marathon/version'
22
31
 
23
32
  DEFAULT_URL = 'http://localhost:8080'
24
33
 
@@ -27,21 +36,40 @@ module Marathon
27
36
  ENV['MARATHON_URL']
28
37
  end
29
38
 
30
- # Get the marathon url
39
+ # Get marathon options from environment
40
+ def env_options
41
+ opts = {}
42
+ opts[:username] = ENV['MARATHON_USER'] if ENV['MARATHON_USER']
43
+ opts[:password] = ENV['MARATHON_PASSWORD'] if ENV['MARATHON_PASSWORD']
44
+ opts
45
+ end
46
+
47
+ # Get the marathon API URL
31
48
  def url
32
49
  @url ||= env_url || DEFAULT_URL
33
50
  @url
34
51
  end
35
52
 
53
+ # Get options for connecting to marathon API
54
+ def options
55
+ @options ||= env_options
56
+ end
57
+
36
58
  # Set a new url
37
59
  def url=(new_url)
38
60
  @url = new_url
39
61
  reset_connection!
40
62
  end
41
63
 
64
+ # Set new options
65
+ def options=(new_options)
66
+ @options = env_options.merge(new_options || {})
67
+ reset_connection!
68
+ end
69
+
42
70
  # Set a new connection
43
71
  def connection
44
- @connection ||= Connection.new(url)
72
+ @connection ||= Connection.new(url, options)
45
73
  end
46
74
 
47
75
  # Reset the connection
@@ -59,7 +87,7 @@ module Marathon
59
87
  connection.get('/ping')
60
88
  end
61
89
 
62
- module_function :connection, :env_url, :info, :logger, :logger=,
63
- :ping, :url, :url= ,:reset_connection!
90
+ module_function :connection, :env_options, :env_url, :info, :logger, :logger=, :ping,
91
+ :options, :options=, :url, :url= ,:reset_connection!
64
92
 
65
93
  end
@@ -1,24 +1,29 @@
1
1
  # This class represents a Marathon App.
2
2
  # See https://mesosphere.github.io/marathon/docs/rest-api.html#apps for full list of API's methods.
3
- class Marathon::App
3
+ class Marathon::App < Marathon::Base
4
4
 
5
- attr_reader :info, :read_only
5
+ ACCESSORS = %w[ id args cmd cpus disk env executor instances mem ports requirePorts
6
+ storeUris tasksRunning tasksStaged uris user version ]
7
+
8
+ DEFAULTS = {
9
+ :constraints => [],
10
+ :env => {},
11
+ :ports => [],
12
+ :uris => []
13
+ }
14
+
15
+ attr_reader :read_only
6
16
 
7
17
  # Create a new application object.
8
18
  # ++hash++: Hash including all attributes.
9
19
  # See https://mesosphere.github.io/marathon/docs/rest-api.html#post-/v2/apps for full details.
10
20
  # ++read_only++: prevent actions on this application
11
- def initialize(hash = {}, read_only = false)
12
- @info = hash
21
+ def initialize(hash, read_only = false)
22
+ super(Marathon::Util.merge_keywordized_hash(DEFAULTS, hash), ACCESSORS)
23
+ raise ArgumentError, 'App must have an id' unless id
13
24
  @read_only = read_only
14
25
  end
15
26
 
16
- # Shortcuts for reaching attributes
17
- %w[ id args cmd cpus disk env executor instances mem ports requirePorts
18
- storeUris tasksRunning tasksStaged uris user version ].each do |method|
19
- define_method(method) { |*args, &block| info[method] }
20
- end
21
-
22
27
  # Prevent actions on read only instances.
23
28
  # Raises an ArgumentError when triying to change read_only instances.
24
29
  def check_read_only
@@ -27,17 +32,38 @@ class Marathon::App
27
32
  end
28
33
  end
29
34
 
35
+ # Get container info.
36
+ # This is read only!
37
+ def container
38
+ if @info[:container]
39
+ Marathon::Container.new(@info[:container])
40
+ else
41
+ nil
42
+ end
43
+ end
44
+
45
+ # Get constrains.
46
+ # This is read only!
47
+ def constraints
48
+ @info[:constraints].map { |e| Marathon::Constraint.new(e) }
49
+ end
50
+
51
+ # Get health checks.
52
+ # This is read only!
53
+ def healthChecks
54
+ @info[:healthChecks].map { |e| Marathon::HealthCheck.new(e) }
55
+ end
56
+
30
57
  # List all running tasks for the application.
31
- # Returns an Array of Task objects.
58
+ # This is read only!
32
59
  def tasks
33
60
  check_read_only
34
- unless @info['tasks']
61
+ unless @info[:tasks]
35
62
  refresh
36
63
  end
37
64
 
38
- raise Marathon::Error::UnexpectedResponseError, "Expected to find tasks element in app's info" unless @info['tasks']
39
-
40
- @info['tasks'].map { |e| Marathon::Task.new(e) }
65
+ raise UnexpectedResponseError, "Expected to find tasks element in app's info" unless @info[:tasks]
66
+ @info[:tasks].map { |e| Marathon::Task.new(e) }
41
67
  end
42
68
 
43
69
  # List the versions of the application.
@@ -111,12 +137,36 @@ class Marathon::App
111
137
  end
112
138
 
113
139
  def to_s
114
- "Marathon::App { :id => #{self.id} }"
140
+ "Marathon::App { :id => #{id} }"
141
+ end
142
+
143
+ # Returns a string for listing the application.
144
+ def to_pretty_s
145
+ %Q[
146
+ App ID: #{id}
147
+ Instances: #{tasks.size}/#{instances}
148
+ Command: #{cmd}
149
+ CPUs: #{cpus}
150
+ Memory: #{mem} MB
151
+ #{pretty_uris()}
152
+ #{pretty_env()}
153
+ #{pretty_constraints()}
154
+ Version: #{version}
155
+ ].gsub(/\n\n+/, "\n").strip
156
+ end
157
+
158
+ private
159
+
160
+ def pretty_env
161
+ env.map { |k,v| "ENV: #{k}=#{v}" }.join("\n")
162
+ end
163
+
164
+ def pretty_uris
165
+ uris.map { |e| "URI: #{e}" }.join("\n")
115
166
  end
116
167
 
117
- # Return application as JSON formatted string.
118
- def to_json
119
- info.to_json
168
+ def pretty_constraints
169
+ constraints.map { |e| "Constraint: #{e.to_pretty_s}" }.join("\n")
120
170
  end
121
171
 
122
172
  class << self
@@ -166,7 +216,7 @@ class Marathon::App
166
216
  query = {}
167
217
  query[:force] = true if force
168
218
  json = Marathon.connection.post("/v2/apps/#{id}/restart", query)
169
- # TODO parse deploymentId + version
219
+ Marathon::DeploymentInfo.new(json)
170
220
  end
171
221
 
172
222
  # Change parameters of a running application. The new application parameters apply only to subsequently
@@ -179,7 +229,7 @@ class Marathon::App
179
229
  query = {}
180
230
  query[:force] = true if force
181
231
  json = Marathon.connection.put("/v2/apps/#{id}", query, :body => hash)
182
- # TODO parse deploymentId + version
232
+ Marathon::DeploymentInfo.new(json)
183
233
  end
184
234
 
185
235
  # List the versions of the application with id.
@@ -197,4 +247,4 @@ class Marathon::App
197
247
  new(json, true)
198
248
  end
199
249
  end
200
- end
250
+ end