marathon-api 1.0.0 → 1.1.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/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
|