marathon-api 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +6 -0
- data/bin/marathon +7 -9
- data/lib/marathon/app.rb +29 -43
- data/lib/marathon/base.rb +11 -10
- data/lib/marathon/container.rb +5 -17
- data/lib/marathon/container_docker.rb +4 -7
- data/lib/marathon/group.rb +19 -16
- data/lib/marathon/util.rb +32 -9
- data/lib/marathon/version.rb +1 -1
- data/spec/marathon/app_spec.rb +29 -37
- data/spec/marathon/base_spec.rb +2 -2
- data/spec/marathon/deployment_spec.rb +22 -22
- data/spec/marathon/group_spec.rb +13 -6
- data/spec/marathon/util_spec.rb +31 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37c0d0ae7d91ddeaa7861bffa40b81e72a434e19
|
4
|
+
data.tar.gz: c5d165cf0d590a78fea207dfc705fa409174a8a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 941597d6ae53616a9931735f9a016606933df061115ff21eb1202325388d785e8e824dedc64e00d3fd64725f2560aac1bfdec0758d3b22ad57245b485f94dcdd
|
7
|
+
data.tar.gz: 56afa004de719231016576cba81c13f2553d50e7378e9b79a05f68f5b8664e0ac52b0fa25f2df69f7f29710598f64b5809dfdaff39e1263efd43e4cccb0c828e
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -102,6 +102,12 @@ apps.last.delete!
|
|
102
102
|
|
103
103
|
The other Marathon endpoints are available in the same way.
|
104
104
|
|
105
|
+
Contributing
|
106
|
+
------------
|
107
|
+
|
108
|
+
Please fork and send pull request.
|
109
|
+
Make sure to have test cases for your changes.
|
110
|
+
|
105
111
|
Credits
|
106
112
|
-------
|
107
113
|
|
data/bin/marathon
CHANGED
@@ -46,9 +46,9 @@ def subcmd_start(cmd_opts)
|
|
46
46
|
if cmd_opts[:json]
|
47
47
|
path = cmd_opts[:json]
|
48
48
|
if path == '-'
|
49
|
-
app_opts = Marathon::Util.keywordize_hash(JSON.parse($stdin.read))
|
49
|
+
app_opts = Marathon::Util.keywordize_hash!(JSON.parse($stdin.read))
|
50
50
|
elsif File.exists?(path)
|
51
|
-
app_opts = Marathon::Util.keywordize_hash(JSON.parse(File.read(cmd_opts[:json])))
|
51
|
+
app_opts = Marathon::Util.keywordize_hash!(JSON.parse(File.read(cmd_opts[:json])))
|
52
52
|
else
|
53
53
|
raise Marathon::Error::ArgumentError, "File '#{path}' does not exist"
|
54
54
|
end
|
@@ -231,12 +231,10 @@ def run_subcmd(cmd, cmd_opts)
|
|
231
231
|
end
|
232
232
|
end
|
233
233
|
|
234
|
-
|
235
|
-
|
236
|
-
set_global_opts(global_opts)
|
234
|
+
global_opts = parse_global_opts
|
235
|
+
set_global_opts(global_opts)
|
237
236
|
|
238
|
-
|
239
|
-
|
237
|
+
cmd = parse_subcmd
|
238
|
+
cmd_opts = parse_subcmd_opts(cmd)
|
240
239
|
|
241
|
-
|
242
|
-
end
|
240
|
+
run_subcmd(cmd, cmd_opts)
|
data/lib/marathon/app.rb
CHANGED
@@ -6,13 +6,12 @@ class Marathon::App < Marathon::Base
|
|
6
6
|
storeUris tasksRunning tasksStaged uris user version ]
|
7
7
|
|
8
8
|
DEFAULTS = {
|
9
|
-
:constraints => [],
|
10
9
|
:env => {},
|
11
10
|
:ports => [],
|
12
11
|
:uris => []
|
13
12
|
}
|
14
13
|
|
15
|
-
attr_reader :read_only
|
14
|
+
attr_reader :healthChecks, :constraints, :container, :read_only, :tasks
|
16
15
|
|
17
16
|
# Create a new application object.
|
18
17
|
# ++hash++: Hash including all attributes.
|
@@ -22,6 +21,7 @@ class Marathon::App < Marathon::Base
|
|
22
21
|
super(Marathon::Util.merge_keywordized_hash(DEFAULTS, hash), ACCESSORS)
|
23
22
|
raise ArgumentError, 'App must have an id' unless id
|
24
23
|
@read_only = read_only
|
24
|
+
refresh_attributes
|
25
25
|
end
|
26
26
|
|
27
27
|
# Prevent actions on read only instances.
|
@@ -32,40 +32,6 @@ class Marathon::App < Marathon::Base
|
|
32
32
|
end
|
33
33
|
end
|
34
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
|
-
|
57
|
-
# List all running tasks for the application.
|
58
|
-
# This is read only!
|
59
|
-
def tasks
|
60
|
-
check_read_only
|
61
|
-
unless @info[:tasks]
|
62
|
-
refresh
|
63
|
-
end
|
64
|
-
|
65
|
-
raise UnexpectedResponseError, "Expected to find tasks element in app's info" unless @info[:tasks]
|
66
|
-
@info[:tasks].map { |e| Marathon::Task.new(e) }
|
67
|
-
end
|
68
|
-
|
69
35
|
# List the versions of the application.
|
70
36
|
# ++version++: Get a specific versions
|
71
37
|
# Returns Array of Strings if ++version = nil++,
|
@@ -83,13 +49,14 @@ class Marathon::App < Marathon::Base
|
|
83
49
|
check_read_only
|
84
50
|
new_app = self.class.get(id)
|
85
51
|
@info = new_app.info
|
52
|
+
refresh_attributes
|
86
53
|
end
|
87
54
|
|
88
55
|
# Create and start the application.
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
56
|
+
# ++force++: If the app is affected by a running deployment, then the update operation will fail.
|
57
|
+
# The current deployment can be overridden by setting the `force` query parameter.
|
58
|
+
def start!(force = false)
|
59
|
+
change!(info, force)
|
93
60
|
end
|
94
61
|
|
95
62
|
# Initiates a rolling restart of all running tasks of the given app.
|
@@ -109,7 +76,14 @@ class Marathon::App < Marathon::Base
|
|
109
76
|
# The current deployment can be overridden by setting the `force` query parameter.
|
110
77
|
def change!(hash, force = false)
|
111
78
|
check_read_only
|
112
|
-
|
79
|
+
Marathon::Util.keywordize_hash!(hash)
|
80
|
+
if hash[:version] and hash.size > 1
|
81
|
+
# remove :version if it's not the only key
|
82
|
+
new_hash = Marathon::Util.remove_keys(hash, [:version])
|
83
|
+
else
|
84
|
+
new_hash = hash
|
85
|
+
end
|
86
|
+
self.class.change(id, new_hash, force)
|
113
87
|
end
|
114
88
|
|
115
89
|
# Create a new version with parameters of an old version.
|
@@ -118,7 +92,7 @@ class Marathon::App < Marathon::Base
|
|
118
92
|
# ++force++: If the app is affected by a running deployment, then the update operation will fail.
|
119
93
|
# The current deployment can be overridden by setting the `force` query parameter.
|
120
94
|
def roll_back!(version, force = false)
|
121
|
-
change!({
|
95
|
+
change!({:version => version}, force)
|
122
96
|
end
|
123
97
|
|
124
98
|
# Change the number of desired instances.
|
@@ -126,7 +100,7 @@ class Marathon::App < Marathon::Base
|
|
126
100
|
# ++force++: If the app is affected by a running deployment, then the update operation will fail.
|
127
101
|
# The current deployment can be overridden by setting the `force` query parameter.
|
128
102
|
def scale!(instances, force = false)
|
129
|
-
change!({
|
103
|
+
change!({:instances => instances}, force)
|
130
104
|
end
|
131
105
|
|
132
106
|
# Change the number of desired instances to 0.
|
@@ -169,6 +143,18 @@ Version: #{version}
|
|
169
143
|
constraints.map { |e| "Constraint: #{e.to_pretty_s}" }.join("\n")
|
170
144
|
end
|
171
145
|
|
146
|
+
# Rebuild attribute classes
|
147
|
+
def refresh_attributes
|
148
|
+
@healthChecks = (info[:healthChecks] || []).map { |e| Marathon::HealthCheck.new(e) }
|
149
|
+
@constraints = (info[:constraints] || []).map { |e| Marathon::Constraint.new(e) }
|
150
|
+
if info[:container]
|
151
|
+
@container = Marathon::Container.new(info[:container])
|
152
|
+
else
|
153
|
+
@container = nil
|
154
|
+
end
|
155
|
+
@tasks = (@info[:tasks] || []).map { |e| Marathon::Task.new(e) }
|
156
|
+
end
|
157
|
+
|
172
158
|
class << self
|
173
159
|
|
174
160
|
# List the application with id.
|
data/lib/marathon/base.rb
CHANGED
@@ -7,13 +7,13 @@ class Marathon::Base
|
|
7
7
|
|
8
8
|
# Create the object
|
9
9
|
# ++hash++: object returned from API. May be Hash or Array.
|
10
|
-
# ++
|
11
|
-
def initialize(hash,
|
12
|
-
raise ArgumentError, 'hash must be a Hash' if
|
10
|
+
# ++attr_accessors++: List of attribute accessors.
|
11
|
+
def initialize(hash, attr_accessors = [])
|
12
|
+
raise ArgumentError, 'hash must be a Hash' if attr_accessors and attr_accessors.size > 0 and not hash.is_a?(Hash)
|
13
13
|
raise ArgumentError, 'hash must be Hash or Array' unless hash.is_a?(Hash) or hash.is_a?(Array)
|
14
|
-
raise ArgumentError, '
|
15
|
-
@info = Marathon::Util.keywordize_hash(hash)
|
16
|
-
|
14
|
+
raise ArgumentError, 'attr_accessors must be an Array' unless attr_accessors.is_a?(Array)
|
15
|
+
@info = Marathon::Util.keywordize_hash!(hash)
|
16
|
+
attr_accessors.each { |e| add_attr_accessor(e) }
|
17
17
|
end
|
18
18
|
|
19
19
|
# Return application as JSON formatted string.
|
@@ -23,10 +23,11 @@ class Marathon::Base
|
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
|
-
# Create
|
26
|
+
# Create attr_accessor for @info[key].
|
27
27
|
# ++key++: key in @info
|
28
|
-
def
|
28
|
+
def add_attr_accessor(key)
|
29
29
|
sym = key.to_sym
|
30
|
-
self.class.send(:define_method, sym.id2name) {
|
30
|
+
self.class.send(:define_method, sym.id2name) { info[sym] }
|
31
|
+
self.class.send(:define_method, "#{sym.id2name}=") { |v| info[sym] = v }
|
31
32
|
end
|
32
|
-
end
|
33
|
+
end
|
data/lib/marathon/container.rb
CHANGED
@@ -10,27 +10,15 @@ class Marathon::Container < Marathon::Base
|
|
10
10
|
:volumes => []
|
11
11
|
}
|
12
12
|
|
13
|
+
attr_reader :docker, :volumes
|
14
|
+
|
13
15
|
# Create a new container object.
|
14
16
|
# ++hash++: Hash returned by API.
|
15
17
|
def initialize(hash)
|
16
18
|
super(Marathon::Util.merge_keywordized_hash(DEFAULTS, hash), ACCESSORS)
|
17
19
|
Marathon::Util.validate_choice('type', type, SUPPERTED_TYPES)
|
18
|
-
|
19
|
-
|
20
|
-
# Get container's docker information.
|
21
|
-
# This is read only!
|
22
|
-
def docker
|
23
|
-
if @info[:docker]
|
24
|
-
Marathon::ContainerDocker.new(@info[:docker])
|
25
|
-
else
|
26
|
-
nil
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Get container's volumes.
|
31
|
-
# This is read only!
|
32
|
-
def volumes
|
33
|
-
@info[:volumes].map { |e| Marathon::ContainerVolume.new(e) }
|
20
|
+
@docker = Marathon::ContainerDocker.new(info[:docker]) if info[:docker]
|
21
|
+
@volumes = info[:volumes].map { |e| Marathon::ContainerVolume.new(e) }
|
34
22
|
end
|
35
23
|
|
36
24
|
def to_s
|
@@ -38,4 +26,4 @@ class Marathon::Container < Marathon::Base
|
|
38
26
|
+ " :volumes => #{Marathon::Util.items_to_pretty_s(volumes)} }"
|
39
27
|
end
|
40
28
|
|
41
|
-
end
|
29
|
+
end
|
@@ -8,18 +8,15 @@ class Marathon::ContainerDocker < Marathon::Base
|
|
8
8
|
:portMappings => []
|
9
9
|
}
|
10
10
|
|
11
|
+
attr_reader :portMappings
|
12
|
+
|
11
13
|
# Create a new container docker object.
|
12
14
|
# ++hash++: Hash returned by API.
|
13
15
|
def initialize(hash)
|
14
16
|
super(Marathon::Util.merge_keywordized_hash(DEFAULTS, hash), ACCESSORS)
|
15
17
|
Marathon::Util.validate_choice('network', network, %w[BRIDGE HOST])
|
16
18
|
raise Marathon::Error::ArgumentError, 'image must not be nil' unless image
|
17
|
-
|
18
|
-
|
19
|
-
# Get container's port mappings.
|
20
|
-
# This is read only!
|
21
|
-
def portMappings
|
22
|
-
@info[:portMappings].map { |e| Marathon::ContainerDockerPortMapping.new(e) }
|
19
|
+
@portMappings = (info[:portMappings] || []).map { |e| Marathon::ContainerDockerPortMapping.new(e) }
|
23
20
|
end
|
24
21
|
|
25
22
|
def to_pretty_s
|
@@ -30,4 +27,4 @@ class Marathon::ContainerDocker < Marathon::Base
|
|
30
27
|
"Marathon::ContainerDocker { :image => #{image} }"
|
31
28
|
end
|
32
29
|
|
33
|
-
end
|
30
|
+
end
|
data/lib/marathon/group.rb
CHANGED
@@ -5,36 +5,26 @@ class Marathon::Group < Marathon::Base
|
|
5
5
|
ACCESSORS = %w[ id dependencies version ]
|
6
6
|
|
7
7
|
DEFAULTS = {
|
8
|
-
:
|
9
|
-
:dependencies => [],
|
10
|
-
:groups => []
|
8
|
+
:dependencies => []
|
11
9
|
}
|
12
10
|
|
11
|
+
attr_reader :apps, :groups
|
12
|
+
|
13
13
|
# Create a new group object.
|
14
14
|
# ++hash++: Hash including all attributes.
|
15
15
|
# See https://mesosphere.github.io/marathon/docs/rest-api.html#post-/v2/groups for full details.
|
16
16
|
def initialize(hash)
|
17
17
|
super(Marathon::Util.merge_keywordized_hash(DEFAULTS, hash), ACCESSORS)
|
18
18
|
raise ArgumentError, 'Group must have an id' unless id
|
19
|
+
refresh_attributes
|
19
20
|
raise ArgumentError, 'Group can have either groups or apps, not both' if apps.size > 0 and groups.size > 0
|
20
21
|
end
|
21
22
|
|
22
|
-
# Get apps.
|
23
|
-
# This is read only!
|
24
|
-
def apps
|
25
|
-
@info[:apps].map { |e| Marathon::App.new(e) }
|
26
|
-
end
|
27
|
-
|
28
|
-
# Get groups.
|
29
|
-
# This is read only!
|
30
|
-
def groups
|
31
|
-
@info[:groups].map { |e| Marathon::Group.new(e) }
|
32
|
-
end
|
33
|
-
|
34
23
|
# Reload attributes from marathon API.
|
35
24
|
def refresh
|
36
25
|
new_app = self.class.get(id)
|
37
26
|
@info = new_app.info
|
27
|
+
refresh_attributes
|
38
28
|
end
|
39
29
|
|
40
30
|
# Create and start a the application group. Application groups can contain other application groups.
|
@@ -65,7 +55,14 @@ class Marathon::Group < Marathon::Base
|
|
65
55
|
# ++force++: If the group is affected by a running deployment, then the update operation will fail.
|
66
56
|
# The current deployment can be overridden by setting the `force` query parameter.
|
67
57
|
def change!(hash, force = false)
|
68
|
-
|
58
|
+
Marathon::Util.keywordize_hash!(hash)
|
59
|
+
if hash[:version] and hash.size > 1
|
60
|
+
# remove :version if it's not the only key
|
61
|
+
new_hash = Marathon::Util.remove_keys(hash, [:version])
|
62
|
+
else
|
63
|
+
new_hash = hash
|
64
|
+
end
|
65
|
+
self.class.change(id, new_hash, force)
|
69
66
|
end
|
70
67
|
|
71
68
|
# Create a new version with parameters of an old version.
|
@@ -97,6 +94,12 @@ Version: #{version}
|
|
97
94
|
array.map { |e| e.to_pretty_s.split("\n").map { |e| " #{e}" }}.join("\n")
|
98
95
|
end
|
99
96
|
|
97
|
+
# Rebuild attribute classes
|
98
|
+
def refresh_attributes
|
99
|
+
@apps = (info[:apps] || []).map { |e| Marathon::App.new(e) }
|
100
|
+
@groups = (info[:groups] || []).map { |e| Marathon::Group.new(e) }
|
101
|
+
end
|
102
|
+
|
100
103
|
class << self
|
101
104
|
|
102
105
|
# List the group with the specified ID.
|
data/lib/marathon/util.rb
CHANGED
@@ -40,21 +40,33 @@ class Marathon::Util
|
|
40
40
|
|
41
41
|
# Swap keys of the hash against their symbols.
|
42
42
|
# ++hash++: the hash
|
43
|
-
|
43
|
+
# ++ignore_keys++: don't keywordize hashes under theses keys
|
44
|
+
def keywordize_hash!(hash, ignore_keys = [:env])
|
44
45
|
if hash.is_a?(Hash)
|
45
|
-
|
46
|
-
hash.each do |k,v|
|
46
|
+
hmap!(hash) do |k,v|
|
47
47
|
key = k.to_sym
|
48
|
-
if key
|
49
|
-
|
50
|
-
new_hash[key] = hash[k]
|
48
|
+
if ignore_keys.include?(key) and v.is_a?(Hash)
|
49
|
+
{ key => v }
|
51
50
|
else
|
52
|
-
|
51
|
+
{ key => keywordize_hash!(v) }
|
53
52
|
end
|
54
53
|
end
|
54
|
+
elsif hash.is_a?(Array)
|
55
|
+
hash.map! { |e| keywordize_hash!(e) }
|
56
|
+
end
|
57
|
+
hash
|
58
|
+
end
|
59
|
+
|
60
|
+
# Remove keys from hash and all it's sub hashes.
|
61
|
+
# ++hash++: the hash
|
62
|
+
# ++keys++: list of keys to remove
|
63
|
+
def remove_keys(hash, keys)
|
64
|
+
if hash.is_a?(Hash)
|
65
|
+
new_hash = {}
|
66
|
+
hash.each { |k,v| new_hash[k] = remove_keys(v, keys) unless keys.include?(k) }
|
55
67
|
new_hash
|
56
68
|
elsif hash.is_a?(Array)
|
57
|
-
hash.map { |e|
|
69
|
+
hash.map { |e| remove_keys(e, keys) }
|
58
70
|
else
|
59
71
|
hash
|
60
72
|
end
|
@@ -62,7 +74,7 @@ class Marathon::Util
|
|
62
74
|
|
63
75
|
# Merge two hashes but keywordize both.
|
64
76
|
def merge_keywordized_hash(h1, h2)
|
65
|
-
keywordize_hash(h1).merge(keywordize_hash(h2))
|
77
|
+
keywordize_hash!(h1).merge(keywordize_hash!(h2))
|
66
78
|
end
|
67
79
|
|
68
80
|
# Stringify an item or an array of items.
|
@@ -75,5 +87,16 @@ class Marathon::Util
|
|
75
87
|
item.to_pretty_s
|
76
88
|
end
|
77
89
|
end
|
90
|
+
|
91
|
+
# Implement map! on a hash
|
92
|
+
def hmap!(hash, &block)
|
93
|
+
hash.keys.each do |key|
|
94
|
+
new_hash = block.call(key, hash[key])
|
95
|
+
new_key = new_hash.keys.first
|
96
|
+
hash[new_key] = new_hash[new_key]
|
97
|
+
hash.delete(key) unless key == new_key
|
98
|
+
end
|
99
|
+
hash
|
100
|
+
end
|
78
101
|
end
|
79
102
|
end
|
data/lib/marathon/version.rb
CHANGED
data/spec/marathon/app_spec.rb
CHANGED
@@ -38,7 +38,7 @@ describe Marathon::App do
|
|
38
38
|
subject { described_class.new({ 'id' => '/app/foo' }) }
|
39
39
|
|
40
40
|
let(:expected_string) do
|
41
|
-
'{"
|
41
|
+
'{"env":{},"ports":[],"uris":[],"id":"/app/foo"}'
|
42
42
|
end
|
43
43
|
|
44
44
|
its(:to_json) { should == expected_string }
|
@@ -84,26 +84,6 @@ describe Marathon::App do
|
|
84
84
|
describe '#tasks' do
|
85
85
|
subject { described_class.new({ 'id' => '/ubuntu2' }) }
|
86
86
|
|
87
|
-
it 'checks for read only' do
|
88
|
-
expect(subject).to receive(:check_read_only)
|
89
|
-
subject.info[:tasks] = []
|
90
|
-
subject.tasks
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'has tasks', :vcr do
|
94
|
-
tasks = subject.tasks
|
95
|
-
expect(tasks).to be_instance_of(Array)
|
96
|
-
expect(tasks.size).to eq(1)
|
97
|
-
expect(tasks.first).to be_instance_of(Marathon::Task)
|
98
|
-
expect(tasks.first.appId).to eq(subject.id)
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'loads tasks from API when not loaded already' do
|
102
|
-
subject.info[:tasks] = nil
|
103
|
-
expect(subject).to receive(:refresh) { subject.info[:tasks] = [] }
|
104
|
-
expect(subject.tasks).to eq([])
|
105
|
-
end
|
106
|
-
|
107
87
|
it 'shows already loaded tasks w/o API call' do
|
108
88
|
subject.info[:tasks] = []
|
109
89
|
expect(subject).not_to receive(:refresh)
|
@@ -132,17 +112,22 @@ describe Marathon::App do
|
|
132
112
|
|
133
113
|
it 'checks for read only' do
|
134
114
|
expect(subject).to receive(:check_read_only)
|
135
|
-
expect(described_class).to receive(:
|
115
|
+
expect(described_class).to receive(:change).with(
|
116
|
+
'/app/foo',
|
117
|
+
{:env=>{}, :ports=>[], :uris=>[], :id=>"/app/foo"},
|
118
|
+
false
|
119
|
+
)
|
136
120
|
subject.start!
|
137
121
|
end
|
138
122
|
|
139
123
|
it 'starts the app' do
|
140
|
-
expect(described_class).to receive(:
|
141
|
-
.with(
|
142
|
-
|
143
|
-
|
124
|
+
expect(described_class).to receive(:change)
|
125
|
+
.with(
|
126
|
+
'/app/foo',
|
127
|
+
{:env=>{}, :ports=>[], :uris=>[], :id=>"/app/foo"},
|
128
|
+
false
|
129
|
+
)
|
144
130
|
subject.start!
|
145
|
-
expect(subject.info[:started]).to be(true)
|
146
131
|
end
|
147
132
|
end
|
148
133
|
|
@@ -196,13 +181,13 @@ describe Marathon::App do
|
|
196
181
|
end
|
197
182
|
|
198
183
|
it 'changes the app' do
|
199
|
-
expect(described_class).to receive(:change).with('/app/foo', {
|
200
|
-
subject.change!('instances' => 9000)
|
184
|
+
expect(described_class).to receive(:change).with('/app/foo', {:instances => 9000 }, false)
|
185
|
+
subject.change!('instances' => 9000, 'version' => 'old-version')
|
201
186
|
end
|
202
187
|
end
|
203
188
|
|
204
189
|
describe '#roll_back!' do
|
205
|
-
subject { described_class.new({
|
190
|
+
subject { described_class.new({:id => '/app/foo', :instances => 10}) }
|
206
191
|
|
207
192
|
it 'checks for read only' do
|
208
193
|
expect(subject).to receive(:check_read_only)
|
@@ -211,18 +196,18 @@ describe Marathon::App do
|
|
211
196
|
end
|
212
197
|
|
213
198
|
it 'changes the app' do
|
214
|
-
expect(subject).to receive(:change!).with({
|
199
|
+
expect(subject).to receive(:change!).with({:version => 'old_version' }, false)
|
215
200
|
subject.roll_back!('old_version')
|
216
201
|
end
|
217
202
|
|
218
203
|
it 'changes the app with force' do
|
219
|
-
expect(subject).to receive(:change!).with({
|
204
|
+
expect(subject).to receive(:change!).with({:version => 'old_version' }, true)
|
220
205
|
subject.roll_back!('old_version', true)
|
221
206
|
end
|
222
207
|
end
|
223
208
|
|
224
209
|
describe '#scale!' do
|
225
|
-
subject { described_class.new({
|
210
|
+
subject { described_class.new({:id => '/app/foo', :instances => 10}) }
|
226
211
|
|
227
212
|
it 'checks for read only' do
|
228
213
|
expect(subject).to receive(:check_read_only)
|
@@ -231,18 +216,18 @@ describe Marathon::App do
|
|
231
216
|
end
|
232
217
|
|
233
218
|
it 'changes the app' do
|
234
|
-
expect(subject).to receive(:change!).with({
|
219
|
+
expect(subject).to receive(:change!).with({:instances => 9000}, false)
|
235
220
|
subject.scale!(9000)
|
236
221
|
end
|
237
222
|
|
238
223
|
it 'changes the app with force' do
|
239
|
-
expect(subject).to receive(:change!).with({
|
224
|
+
expect(subject).to receive(:change!).with({:instances => 9000}, true)
|
240
225
|
subject.scale!(9000, true)
|
241
226
|
end
|
242
227
|
end
|
243
228
|
|
244
229
|
describe '#suspend!' do
|
245
|
-
subject { described_class.new({
|
230
|
+
subject { described_class.new({'id' => '/app/foo', :instances => 10}) }
|
246
231
|
|
247
232
|
it 'checks for read only' do
|
248
233
|
expect(subject).to receive(:check_read_only)
|
@@ -290,7 +275,14 @@ describe Marathon::App do
|
|
290
275
|
subject { described_class }
|
291
276
|
|
292
277
|
it 'starts the app', :vcr do
|
293
|
-
app = subject.start({
|
278
|
+
app = subject.start({
|
279
|
+
:id => '/test',
|
280
|
+
:cmd => 'sleep 10',
|
281
|
+
:instances => 1,
|
282
|
+
:cpus => 0.1,
|
283
|
+
:mem => 32,
|
284
|
+
:version => 'foo-version'
|
285
|
+
})
|
294
286
|
expect(app).to be_instance_of(described_class)
|
295
287
|
expect(app.id).to eq('/test')
|
296
288
|
expect(app.instances).to eq(1)
|
data/spec/marathon/base_spec.rb
CHANGED
@@ -22,7 +22,7 @@ describe Marathon::Base do
|
|
22
22
|
}) }
|
23
23
|
|
24
24
|
let(:expected_string) do
|
25
|
-
'{"app":{"id":"/app/foo"}
|
25
|
+
'{"foo":"blubb","bar":1,"app":{"id":"/app/foo"}}'
|
26
26
|
end
|
27
27
|
|
28
28
|
its(:to_json) { should == expected_string }
|
@@ -50,4 +50,4 @@ describe Marathon::Base do
|
|
50
50
|
its(:bar) { should == 1 }
|
51
51
|
end
|
52
52
|
|
53
|
-
end
|
53
|
+
end
|
@@ -1,25 +1,25 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
DEPLOYMENT_EXAMPLE = {
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
:affectedApps => ["/test"],
|
5
|
+
:id => "867ed450-f6a8-4d33-9b0e-e11c5513990b",
|
6
|
+
:steps => [
|
7
7
|
[
|
8
8
|
{
|
9
|
-
|
10
|
-
|
9
|
+
:action => "ScaleApplication",
|
10
|
+
:app => "/test"
|
11
11
|
}
|
12
12
|
]
|
13
13
|
],
|
14
|
-
|
14
|
+
:currentActions => [
|
15
15
|
{
|
16
|
-
|
17
|
-
|
16
|
+
:action => "ScaleApplication",
|
17
|
+
:app => "/test"
|
18
18
|
}
|
19
19
|
],
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
:version => "2014-08-26T08:18:03.595Z",
|
21
|
+
:currentStep => 1,
|
22
|
+
:totalSteps => 1
|
23
23
|
}
|
24
24
|
|
25
25
|
describe Marathon::Deployment do
|
@@ -44,23 +44,23 @@ describe Marathon::Deployment do
|
|
44
44
|
describe 'attributes' do
|
45
45
|
subject { described_class.new(DEPLOYMENT_EXAMPLE) }
|
46
46
|
|
47
|
-
its(:id) { should == DEPLOYMENT_EXAMPLE[
|
48
|
-
its(:affectedApps) { should == DEPLOYMENT_EXAMPLE[
|
49
|
-
its(:version) { should == DEPLOYMENT_EXAMPLE[
|
50
|
-
its(:currentStep) { should == DEPLOYMENT_EXAMPLE[
|
51
|
-
its(:totalSteps) { should == DEPLOYMENT_EXAMPLE[
|
47
|
+
its(:id) { should == DEPLOYMENT_EXAMPLE[:id] }
|
48
|
+
its(:affectedApps) { should == DEPLOYMENT_EXAMPLE[:affectedApps] }
|
49
|
+
its(:version) { should == DEPLOYMENT_EXAMPLE[:version] }
|
50
|
+
its(:currentStep) { should == DEPLOYMENT_EXAMPLE[:currentStep] }
|
51
|
+
its(:totalSteps) { should == DEPLOYMENT_EXAMPLE[:totalSteps] }
|
52
52
|
end
|
53
53
|
|
54
54
|
describe '#delete' do
|
55
55
|
subject { described_class.new(DEPLOYMENT_EXAMPLE) }
|
56
56
|
|
57
57
|
it 'deletes the deployment' do
|
58
|
-
expect(described_class).to receive(:delete).with(DEPLOYMENT_EXAMPLE[
|
58
|
+
expect(described_class).to receive(:delete).with(DEPLOYMENT_EXAMPLE[:id], false)
|
59
59
|
subject.delete
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'force deletes the deployment' do
|
63
|
-
expect(described_class).to receive(:delete).with(DEPLOYMENT_EXAMPLE[
|
63
|
+
expect(described_class).to receive(:delete).with(DEPLOYMENT_EXAMPLE[:id], true)
|
64
64
|
subject.delete(true)
|
65
65
|
end
|
66
66
|
end
|
@@ -70,9 +70,9 @@ describe Marathon::Deployment do
|
|
70
70
|
|
71
71
|
it 'lists deployments', :vcr do
|
72
72
|
# start a deployment
|
73
|
-
Marathon::App.change('/test', {
|
73
|
+
Marathon::App.change('/test', {:instances => 0})
|
74
74
|
sleep 1
|
75
|
-
Marathon::App.change('/test', {
|
75
|
+
Marathon::App.change('/test', {:instances => 2})
|
76
76
|
sleep 1
|
77
77
|
|
78
78
|
deployments = subject.list
|
@@ -86,9 +86,9 @@ describe Marathon::Deployment do
|
|
86
86
|
|
87
87
|
it 'deletes deployments', :vcr do
|
88
88
|
# start a deployment
|
89
|
-
info = Marathon::App.change('/test', {
|
89
|
+
info = Marathon::App.change('/test', {:instances => 1})
|
90
90
|
expect(subject.delete(info.deploymentId)).to be_instance_of(Marathon::DeploymentInfo)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
end
|
94
|
+
end
|
data/spec/marathon/group_spec.rb
CHANGED
@@ -23,11 +23,13 @@ EXAMPLE_GROUP = {
|
|
23
23
|
"upgradeStrategy" => {
|
24
24
|
"minimumHealthCapacity" => 1.0
|
25
25
|
},
|
26
|
-
"tasks" => []
|
26
|
+
"tasks" => [],
|
27
|
+
"version" => 'foo-version'
|
27
28
|
}
|
28
29
|
],
|
29
30
|
"dependencies" => [],
|
30
|
-
"groups" => []
|
31
|
+
"groups" => [],
|
32
|
+
"version" => 'foo-version'
|
31
33
|
}
|
32
34
|
|
33
35
|
describe Marathon::Group do
|
@@ -46,8 +48,8 @@ describe Marathon::Group do
|
|
46
48
|
" Command: sleep 30\n" + \
|
47
49
|
" CPUs: 1.0\n" + \
|
48
50
|
" Memory: 128.0 MB\n" + \
|
49
|
-
" Version
|
50
|
-
"Version:"
|
51
|
+
" Version: foo-version\n" + \
|
52
|
+
"Version: foo-version"
|
51
53
|
|
52
54
|
end
|
53
55
|
|
@@ -60,7 +62,7 @@ describe Marathon::Group do
|
|
60
62
|
|
61
63
|
it 'starts the group' do
|
62
64
|
expect(described_class).to receive(:start)
|
63
|
-
.with({:
|
65
|
+
.with({:dependencies=>[], :id=>'/group/foo'}) do
|
64
66
|
Marathon::DeploymentInfo.new({ 'version' => 'new-version' })
|
65
67
|
end
|
66
68
|
expect(subject.start!.version).to eq('new-version')
|
@@ -83,9 +85,14 @@ describe Marathon::Group do
|
|
83
85
|
subject { described_class.new({ 'id' => '/app/foo' }) }
|
84
86
|
|
85
87
|
it 'changes the group' do
|
86
|
-
expect(described_class).to receive(:change).with('/app/foo', {
|
88
|
+
expect(described_class).to receive(:change).with('/app/foo', {:instances => 9000 }, false)
|
87
89
|
subject.change!('instances' => 9000)
|
88
90
|
end
|
91
|
+
|
92
|
+
it 'changes the group and strips :version' do
|
93
|
+
expect(described_class).to receive(:change).with('/app/foo', {:instances => 9000 }, false)
|
94
|
+
subject.change!('instances' => 9000, :version => 'old-version')
|
95
|
+
end
|
89
96
|
end
|
90
97
|
|
91
98
|
describe '#roll_back!' do
|
data/spec/marathon/util_spec.rb
CHANGED
@@ -41,23 +41,46 @@ describe Marathon::Util do
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
describe '.keywordize_hash' do
|
44
|
+
describe '.keywordize_hash!' do
|
45
45
|
subject { described_class }
|
46
46
|
|
47
47
|
it 'keywordizes the hash' do
|
48
|
-
|
49
|
-
'foo'
|
50
|
-
'f00'
|
51
|
-
'bang'
|
52
|
-
'env'
|
53
|
-
'null'
|
54
|
-
}
|
48
|
+
hash = {
|
49
|
+
'foo' => 'bar',
|
50
|
+
'f00' => {'w00h00' => 'yeah'},
|
51
|
+
'bang' => [{'tricky' => 'one'}],
|
52
|
+
'env' => {'foo' => 'bar'},
|
53
|
+
'null' => nil
|
54
|
+
}
|
55
|
+
|
56
|
+
expect(subject.keywordize_hash!(hash)).to eq({
|
55
57
|
:foo => 'bar',
|
56
58
|
:f00 => {:w00h00 => 'yeah'},
|
57
59
|
:bang => [{:tricky => 'one'}],
|
58
60
|
:env => {'foo' => 'bar'},
|
59
61
|
:null => nil
|
60
62
|
})
|
63
|
+
# make sure, it changes the hash w/o creating a new one
|
64
|
+
expect(hash[:foo]).to eq('bar')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '.remove_keys' do
|
69
|
+
subject { described_class }
|
70
|
+
|
71
|
+
it 'removes keys from hash' do
|
72
|
+
hash = {
|
73
|
+
:foo => 'bar',
|
74
|
+
:deleteme => {'w00h00' => 'yeah'},
|
75
|
+
:blah => [{:deleteme => :foo}, 1]
|
76
|
+
}
|
77
|
+
|
78
|
+
expect(subject.remove_keys(hash, [:deleteme])).to eq({
|
79
|
+
:foo => 'bar',
|
80
|
+
:blah => [{}, 1]
|
81
|
+
})
|
82
|
+
# make sure, it does not changes the original hash
|
83
|
+
expect(hash.size).to eq(3)
|
61
84
|
end
|
62
85
|
end
|
63
86
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: marathon-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felix Bechstein
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|