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.
- checksums.yaml +4 -4
- data/.simplecov +2 -2
- data/.travis.yml +1 -1
- data/README.md +40 -14
- data/bin/marathon +242 -0
- data/fixtures/marathon_docker_sample_2.json +2 -1
- data/fixtures/vcr/Marathon_App/_restart/restarts_an_app.yml +32 -0
- data/fixtures/vcr/Marathon_Group/_changes/changes_the_group.yml +61 -0
- data/fixtures/vcr/Marathon_Group/_delete/deletes_the_group.yml +32 -0
- data/fixtures/vcr/Marathon_Group/_delete/fails_deleting_not_existing_app.yml +32 -0
- data/fixtures/vcr/Marathon_Group/_get/fails_getting_not_existing_app.yml +32 -0
- data/fixtures/vcr/Marathon_Group/_get/gets_the_group.yml +32 -0
- data/fixtures/vcr/Marathon_Group/_list/lists_apps.yml +33 -0
- data/fixtures/vcr/Marathon_Group/_start/fails_getting_not_existing_group.yml +32 -0
- data/fixtures/vcr/Marathon_Group/_start/starts_the_group.yml +35 -0
- data/lib/marathon.rb +33 -5
- data/lib/marathon/app.rb +72 -22
- data/lib/marathon/base.rb +32 -0
- data/lib/marathon/connection.rb +32 -22
- data/lib/marathon/constraint.rb +39 -0
- data/lib/marathon/container.rb +41 -0
- data/lib/marathon/container_docker.rb +33 -0
- data/lib/marathon/container_docker_port_mapping.rb +32 -0
- data/lib/marathon/container_volume.rb +31 -0
- data/lib/marathon/deployment.rb +5 -15
- data/lib/marathon/deployment_info.rb +20 -0
- data/lib/marathon/error.rb +8 -2
- data/lib/marathon/group.rb +166 -0
- data/lib/marathon/health_check.rb +35 -0
- data/lib/marathon/queue.rb +4 -13
- data/lib/marathon/task.rb +15 -12
- data/lib/marathon/util.rb +47 -3
- data/lib/marathon/version.rb +1 -1
- data/marathon-api.gemspec +4 -3
- data/spec/marathon/app_spec.rb +108 -50
- data/spec/marathon/base_spec.rb +53 -0
- data/spec/marathon/connection_spec.rb +1 -1
- data/spec/marathon/constraint_spec.rb +27 -0
- data/spec/marathon/container_docker_port_mapping_spec.rb +55 -0
- data/spec/marathon/container_docker_spec.rb +42 -0
- data/spec/marathon/container_spec.rb +40 -0
- data/spec/marathon/container_volume_spec.rb +50 -0
- data/spec/marathon/deployment_info_spec.rb +43 -0
- data/spec/marathon/deployment_spec.rb +15 -16
- data/spec/marathon/error_spec.rb +17 -0
- data/spec/marathon/group_spec.rb +172 -0
- data/spec/marathon/health_check_spec.rb +50 -0
- data/spec/marathon/marathon_spec.rb +31 -0
- data/spec/marathon/queue_spec.rb +2 -2
- data/spec/marathon/task_spec.rb +24 -11
- data/spec/marathon/util_spec.rb +21 -1
- metadata +58 -6
@@ -0,0 +1,35 @@
|
|
1
|
+
# This class represents a Marathon HealthCheck.
|
2
|
+
# See https://mesosphere.github.io/marathon/docs/health-checks.html for full details.
|
3
|
+
class Marathon::HealthCheck < Marathon::Base
|
4
|
+
|
5
|
+
DEFAULTS = {
|
6
|
+
:gracePeriodSeconds => 300,
|
7
|
+
:intervalSeconds => 60,
|
8
|
+
:maxConsecutiveFailures => 3,
|
9
|
+
:path => '/',
|
10
|
+
:portIndex => 0,
|
11
|
+
:protocol => 'HTTP',
|
12
|
+
:timeoutSeconds => 20
|
13
|
+
}
|
14
|
+
|
15
|
+
ACCESSORS = %w[ command gracePeriodSeconds intervalSeconds maxConsecutiveFailures
|
16
|
+
path portIndex protocol timeoutSeconds ]
|
17
|
+
|
18
|
+
# Create a new health check object.
|
19
|
+
# ++hash++: Hash returned by API.
|
20
|
+
def initialize(hash)
|
21
|
+
super(Marathon::Util.merge_keywordized_hash(DEFAULTS, hash), ACCESSORS)
|
22
|
+
Marathon::Util.validate_choice(:protocol, protocol, %w[HTTP TCP COMMAND])
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
if protocol == 'COMMAND'
|
27
|
+
"Marathon::HealthCheck { :protocol => #{protocol} :command => #{command} }"
|
28
|
+
elsif protocol == 'HTTP'
|
29
|
+
"Marathon::HealthCheck { :protocol => #{protocol} :portIndex => #{portIndex} :path => #{path} }"
|
30
|
+
else
|
31
|
+
"Marathon::HealthCheck { :protocol => #{protocol} :portIndex => #{portIndex} }"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/marathon/queue.rb
CHANGED
@@ -1,29 +1,20 @@
|
|
1
1
|
# This class represents a Marathon Queue element.
|
2
2
|
# See https://mesosphere.github.io/marathon/docs/rest-api.html#queue for full list of API's methods.
|
3
|
-
class Marathon::Queue
|
3
|
+
class Marathon::Queue < Marathon::Base
|
4
4
|
|
5
5
|
attr_reader :app
|
6
|
-
attr_reader :delay
|
7
6
|
|
8
7
|
# Create a new queue element object.
|
9
8
|
# ++hash++: Hash returned by API, including 'app' and 'delay'
|
10
|
-
def initialize(hash
|
11
|
-
|
12
|
-
@
|
9
|
+
def initialize(hash)
|
10
|
+
super(hash, %w[delay])
|
11
|
+
@app = Marathon::App.new(info[:app], true)
|
13
12
|
end
|
14
13
|
|
15
14
|
def to_s
|
16
15
|
"Marathon::Queue { :appId => #{app.id} :delay => #{delay} }"
|
17
16
|
end
|
18
17
|
|
19
|
-
# Return queue element as JSON formatted string.
|
20
|
-
def to_json
|
21
|
-
{
|
22
|
-
'app' => @app.info,
|
23
|
-
'delay' => @delay
|
24
|
-
}.to_json
|
25
|
-
end
|
26
|
-
|
27
18
|
class << self
|
28
19
|
|
29
20
|
# Show content of the task queue.
|
data/lib/marathon/task.rb
CHANGED
@@ -1,18 +1,13 @@
|
|
1
1
|
# This class represents a Marathon Task.
|
2
2
|
# See https://mesosphere.github.io/marathon/docs/rest-api.html#get-/v2/tasks for full list of API's methods.
|
3
|
-
class Marathon::Task
|
3
|
+
class Marathon::Task < Marathon::Base
|
4
4
|
|
5
|
-
|
5
|
+
ACCESSORS = %w[ id appId host ports servicePorts version stagedAt startedAt ]
|
6
6
|
|
7
7
|
# Create a new task object.
|
8
8
|
# ++hash++: Hash including all attributes
|
9
|
-
def initialize(hash
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
# Shortcuts for reaching attributes
|
14
|
-
%w[ id appId host ports servicePorts version stagedAt startedAt ].each do |method|
|
15
|
-
define_method(method) { |*args, &block| info[method] }
|
9
|
+
def initialize(hash)
|
10
|
+
super(hash, ACCESSORS)
|
16
11
|
end
|
17
12
|
|
18
13
|
# Kill the task that belongs to an application.
|
@@ -28,9 +23,17 @@ class Marathon::Task
|
|
28
23
|
"Marathon::Task { :id => #{self.id} :appId => #{appId} :host => #{host} }"
|
29
24
|
end
|
30
25
|
|
31
|
-
#
|
32
|
-
def
|
33
|
-
|
26
|
+
# Returns a string for listing the task.
|
27
|
+
def to_pretty_s
|
28
|
+
%Q[
|
29
|
+
Task ID: #{id}
|
30
|
+
App ID: #{appId}
|
31
|
+
Host: #{host}
|
32
|
+
Ports: #{(ports || []).join(',')}
|
33
|
+
Staged at: #{stagedAt}
|
34
|
+
Started at: #{startedAt}
|
35
|
+
Version: #{version}
|
36
|
+
].strip
|
34
37
|
end
|
35
38
|
|
36
39
|
class << self
|
data/lib/marathon/util.rb
CHANGED
@@ -8,6 +8,7 @@ class Marathon::Util
|
|
8
8
|
# ++allowed++: array of allowd values
|
9
9
|
# ++nil_allowed++: allow nil values
|
10
10
|
def validate_choice(name, value, allowed, nil_allowed = true)
|
11
|
+
value = value[name] if value.is_a?(Hash)
|
11
12
|
if value.nil?
|
12
13
|
unless nil_allowed
|
13
14
|
raise Marathon::Error::ArgumentError, "#{name} must not be nil"
|
@@ -15,8 +16,13 @@ class Marathon::Util
|
|
15
16
|
else
|
16
17
|
# value is not nil
|
17
18
|
unless allowed.include?(value)
|
18
|
-
|
19
|
-
|
19
|
+
if nil_allowed
|
20
|
+
raise Marathon::Error::ArgumentError,
|
21
|
+
"#{name} must be one of #{allowed.join(', ')} or nil, but is '#{value}'"
|
22
|
+
else
|
23
|
+
raise Marathon::Error::ArgumentError,
|
24
|
+
"#{name} must be one of #{allowed.join(', ')} or nil, but is '#{value}'"
|
25
|
+
end
|
20
26
|
end
|
21
27
|
end
|
22
28
|
end
|
@@ -31,5 +37,43 @@ class Marathon::Util
|
|
31
37
|
validate_choice(name, value, allowed, nil_allowed)
|
32
38
|
opts[name] = value if value
|
33
39
|
end
|
40
|
+
|
41
|
+
# Swap keys of the hash against their symbols.
|
42
|
+
# ++hash++: the hash
|
43
|
+
def keywordize_hash(hash)
|
44
|
+
if hash.is_a?(Hash)
|
45
|
+
new_hash = {}
|
46
|
+
hash.each do |k,v|
|
47
|
+
key = k.to_sym
|
48
|
+
if key == :env and v.is_a?(Hash)
|
49
|
+
# ignore :env => {} to prevent renameing environment variables
|
50
|
+
new_hash[key] = hash[k]
|
51
|
+
else
|
52
|
+
new_hash[key] = keywordize_hash(hash[k])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
new_hash
|
56
|
+
elsif hash.is_a?(Array)
|
57
|
+
hash.map { |e| keywordize_hash(e) }
|
58
|
+
else
|
59
|
+
hash
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Merge two hashes but keywordize both.
|
64
|
+
def merge_keywordized_hash(h1, h2)
|
65
|
+
keywordize_hash(h1).merge(keywordize_hash(h2))
|
66
|
+
end
|
67
|
+
|
68
|
+
# Stringify an item or an array of items.
|
69
|
+
def items_to_pretty_s(item)
|
70
|
+
if item.nil?
|
71
|
+
nil
|
72
|
+
elsif item.is_a?(Array)
|
73
|
+
item.map {|e| e.to_pretty_s}.join(',')
|
74
|
+
else
|
75
|
+
item.to_pretty_s
|
76
|
+
end
|
77
|
+
end
|
34
78
|
end
|
35
|
-
end
|
79
|
+
end
|
data/lib/marathon/version.rb
CHANGED
data/marathon-api.gemspec
CHANGED
@@ -5,10 +5,10 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.name = "marathon-api"
|
6
6
|
gem.version = Marathon::VERSION
|
7
7
|
gem.authors = ["Felix Bechstein"]
|
8
|
-
gem.email = %w{
|
8
|
+
gem.email = %w{felix.bechstein@otto.de}
|
9
9
|
gem.description = %q{A simple REST client for the Marathon Remote API}
|
10
10
|
gem.summary = %q{A simple REST client for the Marathon Remote API}
|
11
|
-
gem.homepage = 'https://github.com/
|
11
|
+
gem.homepage = 'https://github.com/otto-de/marathon-api'
|
12
12
|
gem.license = 'MIT'
|
13
13
|
|
14
14
|
gem.files = `git ls-files`.split($\)
|
@@ -17,7 +17,8 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.require_paths = %w{lib}
|
18
18
|
|
19
19
|
gem.add_dependency 'json'
|
20
|
-
gem.add_dependency
|
20
|
+
gem.add_dependency 'httparty', '>= 0.11'
|
21
|
+
gem.add_dependency 'trollop', '>= 2.0'
|
21
22
|
|
22
23
|
gem.add_development_dependency 'rake'
|
23
24
|
gem.add_development_dependency 'rspec', '~> 3.0'
|
data/spec/marathon/app_spec.rb
CHANGED
@@ -3,20 +3,42 @@ require 'spec_helper'
|
|
3
3
|
describe Marathon::App do
|
4
4
|
|
5
5
|
describe '#to_s' do
|
6
|
-
subject { described_class.new({
|
6
|
+
subject { described_class.new({
|
7
|
+
'id' => '/app/foo',
|
8
|
+
'instances' => 1,
|
9
|
+
'tasks' => [],
|
10
|
+
'env' => {'FOO' => 'BAR', 'blubb' => 'blah'},
|
11
|
+
'constraints' => [['hostname', 'UNIQUE']],
|
12
|
+
'uris' => ['http://example.com/big.tar'],
|
13
|
+
'version' => 'foo-version'
|
14
|
+
}) }
|
7
15
|
|
8
16
|
let(:expected_string) do
|
9
17
|
"Marathon::App { :id => /app/foo }"
|
10
18
|
end
|
11
19
|
|
20
|
+
let(:expected_pretty_string) do
|
21
|
+
"App ID: /app/foo\n" + \
|
22
|
+
"Instances: 0/1\n" + \
|
23
|
+
"Command: \n" + \
|
24
|
+
"CPUs: \n" + \
|
25
|
+
"Memory: MB\n" + \
|
26
|
+
"URI: http://example.com/big.tar\n" + \
|
27
|
+
"ENV: FOO=BAR\n" + \
|
28
|
+
"ENV: blubb=blah\n" + \
|
29
|
+
"Constraint: hostname:UNIQUE\n" + \
|
30
|
+
"Version: foo-version"
|
31
|
+
end
|
32
|
+
|
12
33
|
its(:to_s) { should == expected_string }
|
34
|
+
its(:to_pretty_s) { should == expected_pretty_string }
|
13
35
|
end
|
14
36
|
|
15
37
|
describe '#to_json' do
|
16
38
|
subject { described_class.new({ 'id' => '/app/foo' }) }
|
17
39
|
|
18
40
|
let(:expected_string) do
|
19
|
-
'{"id":"/app/foo"}'
|
41
|
+
'{"constraints":[],"env":{},"ports":[],"uris":[],"id":"/app/foo"}'
|
20
42
|
end
|
21
43
|
|
22
44
|
its(:to_json) { should == expected_string }
|
@@ -30,12 +52,41 @@ describe Marathon::App do
|
|
30
52
|
end
|
31
53
|
end
|
32
54
|
|
55
|
+
describe '#container' do
|
56
|
+
subject { described_class.new({
|
57
|
+
'id' => '/ubuntu2', 'container' => {'type'=>'DOCKER', 'docker'=>{'image'=>'felixb/yocto-httpd'}}
|
58
|
+
})}
|
59
|
+
|
60
|
+
it 'has container' do
|
61
|
+
expect(subject.container).to be_instance_of(Marathon::Container)
|
62
|
+
expect(subject.container.type).to eq('DOCKER')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#constraints' do
|
67
|
+
subject { described_class.new({ 'id' => '/ubuntu2', 'constraints' => [['hostname', 'UNIQUE']] }) }
|
68
|
+
|
69
|
+
it 'has constraints' do
|
70
|
+
expect(subject.constraints).to be_instance_of(Array)
|
71
|
+
expect(subject.constraints.first).to be_instance_of(Marathon::Constraint)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#constraints' do
|
76
|
+
subject { described_class.new({ 'id' => '/ubuntu2', 'healthChecks' => [{ 'path' => '/ping' }] }) }
|
77
|
+
|
78
|
+
it 'has healthChecks' do
|
79
|
+
expect(subject.healthChecks).to be_instance_of(Array)
|
80
|
+
expect(subject.healthChecks.first).to be_instance_of(Marathon::HealthCheck)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
33
84
|
describe '#tasks' do
|
34
85
|
subject { described_class.new({ 'id' => '/ubuntu2' }) }
|
35
86
|
|
36
87
|
it 'checks for read only' do
|
37
88
|
expect(subject).to receive(:check_read_only)
|
38
|
-
subject.info[
|
89
|
+
subject.info[:tasks] = []
|
39
90
|
subject.tasks
|
40
91
|
end
|
41
92
|
|
@@ -48,13 +99,13 @@ describe Marathon::App do
|
|
48
99
|
end
|
49
100
|
|
50
101
|
it 'loads tasks from API when not loaded already' do
|
51
|
-
subject.info[
|
52
|
-
expect(subject).to receive(:refresh) { subject.info[
|
102
|
+
subject.info[:tasks] = nil
|
103
|
+
expect(subject).to receive(:refresh) { subject.info[:tasks] = [] }
|
53
104
|
expect(subject.tasks).to eq([])
|
54
105
|
end
|
55
106
|
|
56
107
|
it 'shows already loaded tasks w/o API call' do
|
57
|
-
subject.info[
|
108
|
+
subject.info[:tasks] = []
|
58
109
|
expect(subject).not_to receive(:refresh)
|
59
110
|
expect(subject.tasks).to eq([])
|
60
111
|
end
|
@@ -77,29 +128,30 @@ describe Marathon::App do
|
|
77
128
|
end
|
78
129
|
|
79
130
|
describe '#start!' do
|
80
|
-
|
131
|
+
subject { described_class.new({ 'id' => '/app/foo' }) }
|
81
132
|
|
82
133
|
it 'checks for read only' do
|
83
134
|
expect(subject).to receive(:check_read_only)
|
84
|
-
expect(described_class).to receive(:start) { described_class.new }
|
135
|
+
expect(described_class).to receive(:start) { described_class.new('id' => subject.id) }
|
85
136
|
subject.start!
|
86
137
|
end
|
87
138
|
|
88
139
|
it 'starts the app' do
|
89
|
-
expect(described_class).to receive(:start)
|
90
|
-
|
140
|
+
expect(described_class).to receive(:start)
|
141
|
+
.with({:constraints=>[], :env=>{}, :ports=>[], :uris=>[], :id=>"/app/foo"}) do
|
142
|
+
described_class.new({ 'id' => '/app/foo', 'started' => true })
|
91
143
|
end
|
92
|
-
|
93
|
-
expect(
|
144
|
+
subject.start!
|
145
|
+
expect(subject.info[:started]).to be(true)
|
94
146
|
end
|
95
147
|
end
|
96
148
|
|
97
149
|
describe '#refresh' do
|
98
|
-
|
150
|
+
subject { described_class.new({ 'id' => '/app/foo' }) }
|
99
151
|
|
100
152
|
it 'checks for read only' do
|
101
153
|
expect(subject).to receive(:check_read_only)
|
102
|
-
expect(described_class).to receive(:get) { described_class.new }
|
154
|
+
expect(described_class).to receive(:get) { described_class.new('id' => subject.id) }
|
103
155
|
subject.refresh
|
104
156
|
end
|
105
157
|
|
@@ -107,13 +159,13 @@ describe Marathon::App do
|
|
107
159
|
expect(described_class).to receive(:get).with('/app/foo') do
|
108
160
|
described_class.new({ 'id' => '/app/foo', 'refreshed' => true })
|
109
161
|
end
|
110
|
-
|
111
|
-
expect(
|
162
|
+
subject.refresh
|
163
|
+
expect(subject.info[:refreshed]).to be(true)
|
112
164
|
end
|
113
165
|
end
|
114
166
|
|
115
167
|
describe '#restart!' do
|
116
|
-
|
168
|
+
subject { described_class.new({ 'id' => '/app/foo' }) }
|
117
169
|
|
118
170
|
it 'checks for read only' do
|
119
171
|
expect(subject).to receive(:check_read_only)
|
@@ -124,18 +176,18 @@ describe Marathon::App do
|
|
124
176
|
it 'restarts the app' do
|
125
177
|
expect(described_class).to receive(:restart)
|
126
178
|
.with('/app/foo', false)
|
127
|
-
|
179
|
+
subject.restart!
|
128
180
|
end
|
129
181
|
|
130
182
|
it 'restarts the app, force' do
|
131
183
|
expect(described_class).to receive(:restart)
|
132
184
|
.with('/app/foo', true)
|
133
|
-
|
185
|
+
subject.restart!(true)
|
134
186
|
end
|
135
187
|
end
|
136
188
|
|
137
189
|
describe '#change!' do
|
138
|
-
|
190
|
+
subject { described_class.new({ 'id' => '/app/foo' }) }
|
139
191
|
|
140
192
|
it 'checks for read only' do
|
141
193
|
expect(subject).to receive(:check_read_only)
|
@@ -145,12 +197,12 @@ describe Marathon::App do
|
|
145
197
|
|
146
198
|
it 'changes the app' do
|
147
199
|
expect(described_class).to receive(:change).with('/app/foo', {'instances' => 9000 }, false)
|
148
|
-
|
200
|
+
subject.change!('instances' => 9000)
|
149
201
|
end
|
150
202
|
end
|
151
203
|
|
152
204
|
describe '#roll_back!' do
|
153
|
-
|
205
|
+
subject { described_class.new({ 'id' => '/app/foo', 'instances' => 10 }) }
|
154
206
|
|
155
207
|
it 'checks for read only' do
|
156
208
|
expect(subject).to receive(:check_read_only)
|
@@ -159,18 +211,18 @@ describe Marathon::App do
|
|
159
211
|
end
|
160
212
|
|
161
213
|
it 'changes the app' do
|
162
|
-
expect(
|
163
|
-
|
214
|
+
expect(subject).to receive(:change!).with({'version' => 'old_version' }, false)
|
215
|
+
subject.roll_back!('old_version')
|
164
216
|
end
|
165
217
|
|
166
218
|
it 'changes the app with force' do
|
167
|
-
expect(
|
168
|
-
|
219
|
+
expect(subject).to receive(:change!).with({'version' => 'old_version' }, true)
|
220
|
+
subject.roll_back!('old_version', true)
|
169
221
|
end
|
170
222
|
end
|
171
223
|
|
172
224
|
describe '#scale!' do
|
173
|
-
|
225
|
+
subject { described_class.new({ 'id' => '/app/foo', 'instances' => 10 }) }
|
174
226
|
|
175
227
|
it 'checks for read only' do
|
176
228
|
expect(subject).to receive(:check_read_only)
|
@@ -179,18 +231,18 @@ describe Marathon::App do
|
|
179
231
|
end
|
180
232
|
|
181
233
|
it 'changes the app' do
|
182
|
-
expect(
|
183
|
-
|
234
|
+
expect(subject).to receive(:change!).with({'instances' => 9000 }, false)
|
235
|
+
subject.scale!(9000)
|
184
236
|
end
|
185
237
|
|
186
238
|
it 'changes the app with force' do
|
187
|
-
expect(
|
188
|
-
|
239
|
+
expect(subject).to receive(:change!).with({'instances' => 9000 }, true)
|
240
|
+
subject.scale!(9000, true)
|
189
241
|
end
|
190
242
|
end
|
191
243
|
|
192
244
|
describe '#suspend!' do
|
193
|
-
|
245
|
+
subject { described_class.new({ 'id' => '/app/foo', 'instances' => 10 }) }
|
194
246
|
|
195
247
|
it 'checks for read only' do
|
196
248
|
expect(subject).to receive(:check_read_only)
|
@@ -199,13 +251,13 @@ describe Marathon::App do
|
|
199
251
|
end
|
200
252
|
|
201
253
|
it 'scales the app to 0' do
|
202
|
-
expect(
|
203
|
-
|
254
|
+
expect(subject).to receive(:scale!).with(0, false)
|
255
|
+
subject.suspend!
|
204
256
|
end
|
205
257
|
|
206
258
|
it 'scales the app to 0 with force' do
|
207
|
-
expect(
|
208
|
-
|
259
|
+
expect(subject).to receive(:scale!).with(0, true)
|
260
|
+
subject.suspend!(true)
|
209
261
|
end
|
210
262
|
end
|
211
263
|
|
@@ -216,17 +268,17 @@ describe Marathon::App do
|
|
216
268
|
expect(Marathon.connection).to receive(:get)
|
217
269
|
.with('/v2/apps', {:cmd => 'foo', :embed => 'apps.tasks'})
|
218
270
|
.and_return({ 'apps' => [] })
|
219
|
-
|
271
|
+
subject.list('foo', 'apps.tasks')
|
220
272
|
end
|
221
273
|
|
222
274
|
it 'raises error when run with strange embed' do
|
223
275
|
expect {
|
224
|
-
|
276
|
+
subject.list(nil, 'foo')
|
225
277
|
}.to raise_error(Marathon::Error::ArgumentError)
|
226
278
|
end
|
227
279
|
|
228
280
|
it 'lists apps', :vcr do
|
229
|
-
apps =
|
281
|
+
apps = subject.list
|
230
282
|
expect(apps.size).not_to eq(0)
|
231
283
|
expect(apps.first).to be_instance_of(described_class)
|
232
284
|
expect(apps.first.cpus).to eq(0.1)
|
@@ -238,7 +290,7 @@ describe Marathon::App do
|
|
238
290
|
subject { described_class }
|
239
291
|
|
240
292
|
it 'starts the app', :vcr do
|
241
|
-
app =
|
293
|
+
app = subject.start({ :id => '/test', :cmd => 'sleep 10', :instances => 1, :cpus => 0.1, :mem => 32})
|
242
294
|
expect(app).to be_instance_of(described_class)
|
243
295
|
expect(app.id).to eq('/test')
|
244
296
|
expect(app.instances).to eq(1)
|
@@ -248,7 +300,7 @@ describe Marathon::App do
|
|
248
300
|
|
249
301
|
it 'fails getting not existing app', :vcr do
|
250
302
|
expect {
|
251
|
-
|
303
|
+
subject.get('fooo app')
|
252
304
|
}.to raise_error(Marathon::Error::NotFoundError)
|
253
305
|
end
|
254
306
|
end
|
@@ -257,7 +309,7 @@ describe Marathon::App do
|
|
257
309
|
subject { described_class }
|
258
310
|
|
259
311
|
it 'gets the app', :vcr do
|
260
|
-
app =
|
312
|
+
app = subject.get('/ubuntu')
|
261
313
|
expect(app).to be_instance_of(described_class)
|
262
314
|
expect(app.id).to eq('/ubuntu')
|
263
315
|
expect(app.instances).to eq(1)
|
@@ -267,7 +319,7 @@ describe Marathon::App do
|
|
267
319
|
|
268
320
|
it 'fails getting not existing app', :vcr do
|
269
321
|
expect {
|
270
|
-
|
322
|
+
subject.get('fooo app')
|
271
323
|
}.to raise_error(Marathon::Error::NotFoundError)
|
272
324
|
end
|
273
325
|
end
|
@@ -276,12 +328,12 @@ describe Marathon::App do
|
|
276
328
|
subject { described_class }
|
277
329
|
|
278
330
|
it 'deletes the app', :vcr do
|
279
|
-
|
331
|
+
subject.delete('/ubuntu')
|
280
332
|
end
|
281
333
|
|
282
334
|
it 'fails deleting not existing app', :vcr do
|
283
335
|
expect {
|
284
|
-
|
336
|
+
subject.delete('fooo app')
|
285
337
|
}.to raise_error(Marathon::Error::NotFoundError)
|
286
338
|
end
|
287
339
|
end
|
@@ -289,9 +341,13 @@ describe Marathon::App do
|
|
289
341
|
describe '.restart' do
|
290
342
|
subject { described_class }
|
291
343
|
|
344
|
+
it 'restarts an app', :vcr do
|
345
|
+
expect(subject.restart('/ubuntu2')).to be_instance_of(Marathon::DeploymentInfo)
|
346
|
+
end
|
347
|
+
|
292
348
|
it 'fails restarting not existing app', :vcr do
|
293
349
|
expect {
|
294
|
-
|
350
|
+
subject.restart('fooo app')
|
295
351
|
}.to raise_error(Marathon::Error::NotFoundError)
|
296
352
|
end
|
297
353
|
end
|
@@ -300,13 +356,15 @@ describe Marathon::App do
|
|
300
356
|
subject { described_class }
|
301
357
|
|
302
358
|
it 'changes the app', :vcr do
|
303
|
-
|
304
|
-
|
359
|
+
expect(subject.change('/ubuntu2', { 'instances' => 2 }))
|
360
|
+
.to be_instance_of(Marathon::DeploymentInfo)
|
361
|
+
expect(subject.change('/ubuntu2', { 'instances' => 1 }, true))
|
362
|
+
.to be_instance_of(Marathon::DeploymentInfo)
|
305
363
|
end
|
306
364
|
|
307
365
|
it 'fails with stange attributes', :vcr do
|
308
366
|
expect {
|
309
|
-
|
367
|
+
subject.change('/ubuntu2', { 'instances' => 'foo' })
|
310
368
|
}.to raise_error(Marathon::Error::ClientError)
|
311
369
|
end
|
312
370
|
end
|
@@ -331,4 +389,4 @@ describe Marathon::App do
|
|
331
389
|
expect(version.read_only).to be(true)
|
332
390
|
end
|
333
391
|
end
|
334
|
-
end
|
392
|
+
end
|