marathon_deploy 0.1.48 → 0.1.49
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/lib/marathon_deploy/deployment.rb +73 -69
- data/lib/marathon_deploy/version.rb +1 -1
- metadata +21 -21
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NDliMzdkMWNiY2ZhZTk4ZTcwOTc2NjY3NTZiYzZiMWZkMTA3ZTQ5MA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: af24963806cfffb04b82861400c985fca4c9cfaa
|
4
|
+
data.tar.gz: e4dbe7a9e5d3acb2499ee78d905bc1feb0036fbb
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
NDNkYWEwZTEzZGMyODA2OWY4ZjA0MTIzNzkwOGJhYTdkZTNlMGMwZDY5NTgw
|
11
|
-
NTJkNzYwZmUwN2U0NmFlOTQzMjVmYjNmZTMwYTRhNTU4ZjRiMzA=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
N2YzNTlhZTA0YjhmMDc3ZmMyN2E0ODRjNDBkMzNmOTllMGVhYTYxZTk3NjAx
|
14
|
-
ODllZjk1OWQ5YzA3YWNmYzZjMGY0ZmZkYjM5OWIxMmY2ZmU5MzAyNzUzYzhl
|
15
|
-
NDUxYmJmYjE1YmUxODcyODdiYmIzOTRmYTk5YTQ0NTViMmVlM2U=
|
6
|
+
metadata.gz: cf2fe646b04ceb3bc049a2a68afda61c630412ec37974bbaa99796978da30b3c04b42e0da0ce302ecd1fd34a52b0bfae1a1e6d0e1b110293c2fa7df35d6a7794
|
7
|
+
data.tar.gz: 99d2747a8644b75ea057ca580bdfab2be430501f485b81db6a392c9af42b6c285306443f3a50979d2ae391926e86a9e94874c40eeb8e3fb5e8f97d93358cdfbf
|
@@ -5,43 +5,47 @@ require 'timeout'
|
|
5
5
|
|
6
6
|
module MarathonDeploy
|
7
7
|
class Deployment
|
8
|
-
|
8
|
+
|
9
9
|
DEPLOYMENT_RECHECK_INTERVAL = MarathonDefaults::DEPLOYMENT_RECHECK_INTERVAL
|
10
10
|
DEPLOYMENT_TIMEOUT = MarathonDefaults::DEPLOYMENT_TIMEOUT
|
11
11
|
HEALTHY_WAIT_TIMEOUT = MarathonDefaults::HEALTHY_WAIT_TIMEOUT
|
12
12
|
HEALTHY_WAIT_RECHECK_INTERVAL = MarathonDefaults::HEALTHY_WAIT_RECHECK_INTERVAL
|
13
|
-
|
13
|
+
|
14
14
|
attr_reader :url, :application, :deploymentId
|
15
|
-
|
15
|
+
|
16
16
|
def initialize(url, application)
|
17
17
|
raise ArgumentError, "second argument to deployment object must be an Application", caller unless (!application.nil? && application.class == Application)
|
18
|
-
raise Error::BadURLError, "invalid url => #{url}", caller if (!HttpUtil.valid_url(url))
|
18
|
+
raise Error::BadURLError, "invalid url => #{url}", caller if (!HttpUtil.valid_url(url))
|
19
19
|
@url = HttpUtil.clean_url(url)
|
20
20
|
@application = application
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def timeout
|
24
24
|
return DEPLOYMENT_TIMEOUT
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def healthcheck_timeout
|
28
28
|
return HEALTHY_WAIT_TIMEOUT
|
29
29
|
end
|
30
|
-
|
31
|
-
def versions
|
32
|
-
if (!applicationExists?)
|
33
|
-
response = HttpUtil.get(@url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id + '/versions')
|
30
|
+
|
31
|
+
def versions
|
32
|
+
if (!applicationExists?)
|
33
|
+
response = HttpUtil.get(@url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id + '/versions')
|
34
34
|
response_body = Utils.response_body(response)
|
35
35
|
return response_body[:versions]
|
36
36
|
else
|
37
37
|
return Array.new
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def wait_for_deployment_id(message = "Deployment with deploymentId #{@deploymentId} in progress")
|
42
42
|
startTime = Time.now
|
43
|
-
deployment_seen = false
|
43
|
+
deployment_seen = false
|
44
44
|
Timeout::timeout(DEPLOYMENT_TIMEOUT) do
|
45
|
+
while !deployment_running?
|
46
|
+
sleep(DEPLOYMENT_RECHECK_INTERVAL)
|
47
|
+
$LOG.info("Waiting for Marathon to start deployment")
|
48
|
+
end
|
45
49
|
while running_for_deployment_id?
|
46
50
|
|
47
51
|
deployment_seen = true
|
@@ -52,19 +56,19 @@ module MarathonDeploy
|
|
52
56
|
deployments = deployments_for_deployment_id
|
53
57
|
deployments.each do |item|
|
54
58
|
$LOG.debug(deployment_string(item))
|
55
|
-
end
|
59
|
+
end
|
56
60
|
sleep(DEPLOYMENT_RECHECK_INTERVAL)
|
57
|
-
end
|
61
|
+
end
|
58
62
|
#STDOUT.puts "" if ( $LOG.level == 1 )
|
59
63
|
if (deployment_seen)
|
60
64
|
elapsedTime = '%.2f' % (Time.now - startTime)
|
61
|
-
$LOG.info("Deployment with deploymentId #{@deploymentId} ended (Total deployment time #{elapsedTime}s)")
|
65
|
+
$LOG.info("Deployment with deploymentId #{@deploymentId} ended (Total deployment time #{elapsedTime}s)")
|
62
66
|
end
|
63
67
|
end
|
64
68
|
end
|
65
|
-
|
69
|
+
|
66
70
|
def wait_for_application(message = "Deployment of application #{@application.id} in progress")
|
67
|
-
deployment_seen = false
|
71
|
+
deployment_seen = false
|
68
72
|
Timeout::timeout(DEPLOYMENT_TIMEOUT) do
|
69
73
|
while running_for_application_id?
|
70
74
|
deployment_seen = true
|
@@ -74,18 +78,18 @@ module MarathonDeploy
|
|
74
78
|
deployments_for_application_id.each do |item|
|
75
79
|
$LOG.debug(deployment_string(item))
|
76
80
|
end
|
77
|
-
#$LOG.debug(JSON.pretty_generate(JSON.parse(response.body)))
|
81
|
+
#$LOG.debug(JSON.pretty_generate(JSON.parse(response.body)))
|
78
82
|
sleep(DEPLOYMENT_RECHECK_INTERVAL)
|
79
|
-
end
|
83
|
+
end
|
80
84
|
#STDOUT.puts "" if ( $LOG.level == 1 )
|
81
85
|
if (deployment_seen)
|
82
|
-
$LOG.info("Deployment of application #{@application.id} ended")
|
86
|
+
$LOG.info("Deployment of application #{@application.id} ended")
|
83
87
|
end
|
84
|
-
end
|
88
|
+
end
|
85
89
|
end
|
86
|
-
|
87
|
-
def wait_until_healthy
|
88
|
-
startTime = Time.now
|
90
|
+
|
91
|
+
def wait_until_healthy
|
92
|
+
startTime = Time.now
|
89
93
|
Timeout::timeout(HEALTHY_WAIT_TIMEOUT) do
|
90
94
|
loop do
|
91
95
|
break if (!health_checks_defined?)
|
@@ -94,7 +98,7 @@ module MarathonDeploy
|
|
94
98
|
if (!sick.empty?)
|
95
99
|
$LOG.info("#{sick.size}/#{@application.instances} instances are not healthy, retrying in #{HEALTHY_WAIT_RECHECK_INTERVAL}s (elapsed time #{elapsedTime}s)")
|
96
100
|
$LOG.debug("Sick instances: " + sick.join(','))
|
97
|
-
else
|
101
|
+
else
|
98
102
|
healthy = get_alive(true)
|
99
103
|
if (healthy.size == @application.instances)
|
100
104
|
elapsedTime = '%.2f' % (Time.now - startTime)
|
@@ -104,12 +108,12 @@ module MarathonDeploy
|
|
104
108
|
else
|
105
109
|
$LOG.info("#{healthy.size} healthy instances seen, #{@application.instances} healthy instances expected, retrying in #{HEALTHY_WAIT_RECHECK_INTERVAL}s")
|
106
110
|
end
|
107
|
-
end
|
111
|
+
end
|
108
112
|
sleep(HEALTHY_WAIT_RECHECK_INTERVAL)
|
109
|
-
end
|
110
|
-
end
|
113
|
+
end
|
114
|
+
end
|
111
115
|
end
|
112
|
-
|
116
|
+
|
113
117
|
def cancel(deploymentId,force=false)
|
114
118
|
raise ArgumentError, "deploymentId must be specified to cancel deployment", caller if (deploymentId.empty?)
|
115
119
|
if (running_for_deployment_id?)
|
@@ -118,7 +122,7 @@ module MarathonDeploy
|
|
118
122
|
end
|
119
123
|
return response
|
120
124
|
end
|
121
|
-
|
125
|
+
|
122
126
|
def applicationExists?
|
123
127
|
response = list_app
|
124
128
|
if (response.code.to_i == 200)
|
@@ -126,18 +130,18 @@ module MarathonDeploy
|
|
126
130
|
end
|
127
131
|
return false
|
128
132
|
end
|
129
|
-
|
133
|
+
|
130
134
|
def create_app
|
131
135
|
response = HttpUtil.post(@url + MarathonDefaults::MARATHON_APPS_REST_PATH,@application.json)
|
132
136
|
@deploymentId = get_deployment_id
|
133
137
|
return response
|
134
138
|
end
|
135
|
-
|
139
|
+
|
136
140
|
def update_app(force=false)
|
137
141
|
url = @url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id
|
138
142
|
url += force ? '?force=true' : ''
|
139
143
|
$LOG.debug("Updating app #{@application.id} #{url}")
|
140
|
-
response = HttpUtil.put(url,@application.json)
|
144
|
+
response = HttpUtil.put(url,@application.json)
|
141
145
|
begin
|
142
146
|
@deploymentId = Utils.response_body(response)[:deploymentId]
|
143
147
|
rescue Exception=>e
|
@@ -145,28 +149,28 @@ module MarathonDeploy
|
|
145
149
|
end
|
146
150
|
return response
|
147
151
|
end
|
148
|
-
|
152
|
+
|
149
153
|
def rolling_restart
|
150
154
|
url = @url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id + '/restart'
|
151
|
-
$LOG.debug("Calling marathon api with url: #{url}")
|
155
|
+
$LOG.debug("Calling marathon api with url: #{url}")
|
152
156
|
response = HttpUtil.post(url,{})
|
153
157
|
$LOG.info("Restart of #{@application.id} returned status code: #{response.code}")
|
154
158
|
$LOG.info(JSON.pretty_generate(JSON.parse(response.body)))
|
155
|
-
end
|
156
|
-
|
159
|
+
end
|
160
|
+
|
157
161
|
def health_checks_defined?
|
158
162
|
health_checks = @application.health_checks
|
159
163
|
return true unless health_checks.nil? or health_checks.empty?
|
160
164
|
return false
|
161
|
-
end
|
162
|
-
|
165
|
+
end
|
166
|
+
|
163
167
|
####### PRIVATE METHODS ##########
|
164
168
|
private
|
165
169
|
|
166
170
|
# returns an array of taskIds which are alive
|
167
|
-
def get_alive(value)
|
168
|
-
raise ArgumentError, "value must be boolean true or false" unless (!!value == value)
|
169
|
-
if (health_checks_defined?)
|
171
|
+
def get_alive(value)
|
172
|
+
raise ArgumentError, "value must be boolean true or false" unless (!!value == value)
|
173
|
+
if (health_checks_defined?)
|
170
174
|
apps = Array.new
|
171
175
|
begin
|
172
176
|
apps = Utils.getValue(@url,@application,:app)
|
@@ -180,28 +184,28 @@ module MarathonDeploy
|
|
180
184
|
tasks = Hash.new
|
181
185
|
task_ids = Array.new
|
182
186
|
check_results = get_healthcheck_results.flatten
|
183
|
-
check_results.each do |task|
|
184
|
-
next if task.nil?
|
185
|
-
tasks[task[:taskId].to_s] ||= []
|
187
|
+
check_results.each do |task|
|
188
|
+
next if task.nil?
|
189
|
+
tasks[task[:taskId].to_s] ||= []
|
186
190
|
tasks[task[:taskId].to_s] << task[:alive]
|
187
191
|
end
|
188
|
-
|
189
|
-
tasks.each do |k,v|
|
192
|
+
|
193
|
+
tasks.each do |k,v|
|
190
194
|
if (value)
|
191
195
|
# if there are only alive=true for all healthchecks for this instance
|
192
196
|
if (v.uniq.length == 1 && v.uniq.first == value)
|
193
197
|
task_ids << k
|
194
|
-
end
|
198
|
+
end
|
195
199
|
else
|
196
200
|
# if alive=false is seen for any healthchecks for this instance
|
197
201
|
if (v.include?(value))
|
198
202
|
task_ids << k
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
202
206
|
end
|
203
207
|
else
|
204
|
-
$LOG.info("No health checks defined. Cannot determine application health of #{@application.id}.")
|
208
|
+
$LOG.info("No health checks defined. Cannot determine application health of #{@application.id}.")
|
205
209
|
end
|
206
210
|
return task_ids
|
207
211
|
end
|
@@ -223,7 +227,7 @@ module MarathonDeploy
|
|
223
227
|
$LOG.info "EXCEPTION: #{e} Cannot determine healthcheck_result"
|
224
228
|
end
|
225
229
|
end
|
226
|
-
|
230
|
+
|
227
231
|
def get_deployment_id
|
228
232
|
begin
|
229
233
|
a = Utils.getValue(@url,@application,:app,:deployments,0)[:id]
|
@@ -232,48 +236,48 @@ module MarathonDeploy
|
|
232
236
|
$LOG.info "EXCEPTION: #{e} Cannot determine deployment_id"
|
233
237
|
end
|
234
238
|
end
|
235
|
-
|
239
|
+
|
236
240
|
def list_all
|
237
241
|
HttpUtil.get(@url + MarathonDefaults::MARATHON_DEPLOYMENT_REST_PATH)
|
238
|
-
end
|
239
|
-
|
242
|
+
end
|
243
|
+
|
240
244
|
def running_for_application_id?
|
241
245
|
if (deployment_running? && !deployments_for_application_id.empty?)
|
242
246
|
return true
|
243
247
|
end
|
244
248
|
return false
|
245
249
|
end
|
246
|
-
|
250
|
+
|
247
251
|
def running_for_deployment_id?
|
248
252
|
if (deployment_running? && !deployments_for_deployment_id.empty?)
|
249
253
|
return true
|
250
254
|
end
|
251
255
|
return false
|
252
256
|
end
|
253
|
-
|
257
|
+
|
254
258
|
def deployment_running?
|
255
259
|
response = list_all
|
256
260
|
body = JSON.parse(response.body)
|
257
261
|
return false if body.empty?
|
258
262
|
return true
|
259
|
-
end
|
260
|
-
|
263
|
+
end
|
264
|
+
|
261
265
|
def get_deployment_ids
|
262
266
|
response = list_all
|
263
267
|
payload = JSON.parse(response.body)
|
264
268
|
return payload.collect { |d| d['id'] }
|
265
269
|
end
|
266
|
-
|
270
|
+
|
267
271
|
def list_app
|
268
272
|
HttpUtil.get(@url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id)
|
269
273
|
end
|
270
|
-
|
274
|
+
|
271
275
|
# DONT USE: the response seems to be broken in marathon for /v2/apps/application-id/tasks
|
272
276
|
#def get_tasks
|
273
277
|
# HttpUtil.get(@url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id + '/tasks')
|
274
278
|
#end
|
275
|
-
|
276
|
-
def deployment_string(deploymentJsonObject)
|
279
|
+
|
280
|
+
def deployment_string(deploymentJsonObject)
|
277
281
|
string = "\n" + "+-" * 25 + " DEPLOYMENT INFO " + "+-" * 25 + "\n"
|
278
282
|
deploymentJsonObject.sort.each do |k,v|
|
279
283
|
case v
|
@@ -286,21 +290,21 @@ module MarathonDeploy
|
|
286
290
|
else
|
287
291
|
string += "#{k} + #{v}\n"
|
288
292
|
end
|
289
|
-
end
|
290
|
-
return string
|
293
|
+
end
|
294
|
+
return string
|
291
295
|
end
|
292
|
-
|
296
|
+
|
293
297
|
def deployments_for_deployment_id
|
294
298
|
response = list_all
|
295
299
|
payload = JSON.parse(response.body)
|
296
300
|
return payload.find_all { |d| d['id'] == @deploymentId }
|
297
301
|
end
|
298
|
-
|
302
|
+
|
299
303
|
def deployments_for_application_id
|
300
304
|
response = list_all
|
301
305
|
payload = JSON.parse(response.body)
|
302
306
|
return payload.find_all { |d| d['affectedApps'].include?('/' + @application.id) }
|
303
307
|
end
|
304
|
-
|
308
|
+
|
305
309
|
end
|
306
310
|
end
|
metadata
CHANGED
@@ -1,111 +1,111 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: marathon_deploy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.49
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Colby
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logger
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.7'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.7'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '10.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '10.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: minitest
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - ~>
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '5.7'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - ~>
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '5.7'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: yard
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: travis
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
description: Pushes a yaml or json file to the Marathon API.
|
@@ -118,8 +118,8 @@ executables:
|
|
118
118
|
extensions: []
|
119
119
|
extra_rdoc_files: []
|
120
120
|
files:
|
121
|
-
- .gitignore
|
122
|
-
- .travis.yml
|
121
|
+
- ".gitignore"
|
122
|
+
- ".travis.yml"
|
123
123
|
- Gemfile
|
124
124
|
- LICENSE.txt
|
125
125
|
- NOTES
|
@@ -203,17 +203,17 @@ require_paths:
|
|
203
203
|
- lib
|
204
204
|
required_ruby_version: !ruby/object:Gem::Requirement
|
205
205
|
requirements:
|
206
|
-
- -
|
206
|
+
- - ">="
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '0'
|
209
209
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
210
210
|
requirements:
|
211
|
-
- -
|
211
|
+
- - ">="
|
212
212
|
- !ruby/object:Gem::Version
|
213
213
|
version: '0'
|
214
214
|
requirements: []
|
215
215
|
rubyforge_project:
|
216
|
-
rubygems_version: 2.4.
|
216
|
+
rubygems_version: 2.4.6
|
217
217
|
signing_key:
|
218
218
|
specification_version: 4
|
219
219
|
summary: Mesos/Marathon deployment tool.
|