marathon-api 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.cane +3 -0
- data/.gitignore +7 -0
- data/.simplecov +5 -0
- data/.travis.yml +10 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +91 -0
- data/Rakefile +34 -0
- data/TESTING.md +49 -0
- data/fixtures/marathon_docker_sample.json +14 -0
- data/fixtures/marathon_docker_sample_2.json +14 -0
- data/fixtures/vcr/Marathon/_info/returns_the_info_hash.yml +30 -0
- data/fixtures/vcr/Marathon/_ping/ping/.yml +35 -0
- data/fixtures/vcr/Marathon_App/_changes/changes_the_app.yml +57 -0
- data/fixtures/vcr/Marathon_App/_changes/fails_with_stange_attributes.yml +32 -0
- data/fixtures/vcr/Marathon_App/_delete/deletes_the_app.yml +30 -0
- data/fixtures/vcr/Marathon_App/_delete/fails_deleting_not_existing_app.yml +30 -0
- data/fixtures/vcr/Marathon_App/_get/fails_getting_not_existing_app.yml +30 -0
- data/fixtures/vcr/Marathon_App/_get/gets_the_app.yml +30 -0
- data/fixtures/vcr/Marathon_App/_list/lists_apps.yml +32 -0
- data/fixtures/vcr/Marathon_App/_restart/fails_restarting_not_existing_app.yml +30 -0
- data/fixtures/vcr/Marathon_App/_start/fails_getting_not_existing_app.yml +30 -0
- data/fixtures/vcr/Marathon_App/_start/starts_the_app.yml +32 -0
- data/fixtures/vcr/Marathon_App/_tasks/has_tasks.yml +30 -0
- data/fixtures/vcr/Marathon_App/_version/gets_a_version.yml +61 -0
- data/fixtures/vcr/Marathon_App/_versions/gets_versions.yml +32 -0
- data/fixtures/vcr/Marathon_Deployment/_delete/deletes_deployments.yml +61 -0
- data/fixtures/vcr/Marathon_Deployment/_list/lists_deployments.yml +90 -0
- data/fixtures/vcr/Marathon_EventSubscriptions/_list/lists_callbacks.yml +30 -0
- data/fixtures/vcr/Marathon_EventSubscriptions/_register/registers_callback.yml +30 -0
- data/fixtures/vcr/Marathon_EventSubscriptions/_unregister/unregisters_callback.yml +30 -0
- data/fixtures/vcr/Marathon_Leader/_delete/delete/.yml +30 -0
- data/fixtures/vcr/Marathon_Leader/_get/get/.yml +30 -0
- data/fixtures/vcr/Marathon_Queue/_list/lists_queue.yml +33 -0
- data/fixtures/vcr/Marathon_Task/_delete/kills_a_tasks_of_an_app.yml +57 -0
- data/fixtures/vcr/Marathon_Task/_delete_all/kills_all_tasks_of_an_app.yml +30 -0
- data/fixtures/vcr/Marathon_Task/_get/gets_tasks_of_an_app.yml +30 -0
- data/fixtures/vcr/Marathon_Task/_list/lists_running_tasks.yml +30 -0
- data/fixtures/vcr/Marathon_Task/_list/lists_tasks.yml +30 -0
- data/lib/marathon.rb +65 -0
- data/lib/marathon/app.rb +200 -0
- data/lib/marathon/connection.rb +97 -0
- data/lib/marathon/deployment.rb +60 -0
- data/lib/marathon/error.rb +62 -0
- data/lib/marathon/event_subscriptions.rb +33 -0
- data/lib/marathon/leader.rb +19 -0
- data/lib/marathon/queue.rb +36 -0
- data/lib/marathon/task.rb +85 -0
- data/lib/marathon/util.rb +35 -0
- data/lib/marathon/version.rb +3 -0
- data/marathon-api.gemspec +31 -0
- data/spec/marathon/app_spec.rb +334 -0
- data/spec/marathon/connection_spec.rb +40 -0
- data/spec/marathon/deployment_spec.rb +95 -0
- data/spec/marathon/error_spec.rb +40 -0
- data/spec/marathon/event_subscriptions_spec.rb +37 -0
- data/spec/marathon/leader_spec.rb +21 -0
- data/spec/marathon/marathon_spec.rb +47 -0
- data/spec/marathon/queue_spec.rb +62 -0
- data/spec/marathon/task_spec.rb +100 -0
- data/spec/marathon/util_spec.rb +44 -0
- data/spec/spec_helper.rb +34 -0
- metadata +271 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
# This class represents a Marathon API Connection.
|
2
|
+
class Marathon::Connection
|
3
|
+
|
4
|
+
include Marathon::Error
|
5
|
+
include HTTParty
|
6
|
+
|
7
|
+
headers(
|
8
|
+
'Content-Type' => 'application/json',
|
9
|
+
'Accept' => 'application/json',
|
10
|
+
'User-Agent' => "ub0r/Marathon-API #{Marathon::VERSION}"
|
11
|
+
)
|
12
|
+
|
13
|
+
default_timeout 5
|
14
|
+
maintain_method_across_redirects
|
15
|
+
|
16
|
+
attr_reader :url
|
17
|
+
|
18
|
+
# Create a new API connection.
|
19
|
+
# ++url++: URL of the marathon API.
|
20
|
+
def initialize(url)
|
21
|
+
@url = url
|
22
|
+
end
|
23
|
+
|
24
|
+
# Delegate all HTTP methods to the #request.
|
25
|
+
[:get, :put, :post, :delete].each do |method|
|
26
|
+
define_method(method) { |*args, &block| request(method, *args) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
"Marathon::Connection { :url => #{url} }"
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Create URL suffix for a hash of query parameters.
|
36
|
+
# URL escaping is done internally.
|
37
|
+
# ++query++: Hash of query parameters.
|
38
|
+
def query_params(query)
|
39
|
+
query = query.select { |k,v| !v.nil? }
|
40
|
+
URI.escape(query.map { |k,v| "#{k}=#{v}" }.join('&'))
|
41
|
+
end
|
42
|
+
|
43
|
+
# Create request object.
|
44
|
+
# ++http_method++: GET/POST/PUT/DELETE.
|
45
|
+
# ++path++: Relative path to connection's URL.
|
46
|
+
# ++query++: Optional query parameters.
|
47
|
+
# ++opts++: Optional options. Ex. opts[:body] is used for PUT/POST request.
|
48
|
+
def compile_request_params(http_method, path, query = nil, opts = nil)
|
49
|
+
query ||= {}
|
50
|
+
opts ||= {}
|
51
|
+
headers = opts.delete(:headers) || {}
|
52
|
+
opts[:body] = opts[:body].to_json unless opts[:body].nil?
|
53
|
+
{
|
54
|
+
:method => http_method,
|
55
|
+
:url => "#{@url}#{path}",
|
56
|
+
:query => query
|
57
|
+
}.merge(opts).reject { |_, v| v.nil? }
|
58
|
+
end
|
59
|
+
|
60
|
+
# Create full URL with query parameters.
|
61
|
+
# ++url++: Base URL.
|
62
|
+
# ++query++: Hash of query parameters.
|
63
|
+
def build_url(url, query)
|
64
|
+
url = URI.escape(url)
|
65
|
+
if query.size > 0
|
66
|
+
url += '?' + query_params(query)
|
67
|
+
end
|
68
|
+
url
|
69
|
+
end
|
70
|
+
|
71
|
+
# Send a request to the server and parse response.
|
72
|
+
# ++http_method++: GET/POST/PUT/DELETE.
|
73
|
+
# ++path++: Relative path to connection's URL.
|
74
|
+
# ++query++: Optional query parameters.
|
75
|
+
# ++opts++: Optional options. Ex. opts[:body] is used for PUT/POST request.
|
76
|
+
def request(*args)
|
77
|
+
request = compile_request_params(*args)
|
78
|
+
url = build_url(request[:url], request[:query])
|
79
|
+
response = self.class.send(request[:method], url, request)
|
80
|
+
if response.success?
|
81
|
+
response.parsed_response
|
82
|
+
else
|
83
|
+
raise Marathon::Error.from_response(response)
|
84
|
+
end
|
85
|
+
rescue MarathonError => e
|
86
|
+
raise e
|
87
|
+
rescue SocketError => e
|
88
|
+
raise IOError, "HTTP call failed: #{e.message}"
|
89
|
+
rescue SystemCallError => e
|
90
|
+
if e.class.name.start_with?('Errno::')
|
91
|
+
raise IOError, "HTTP call failed: #{e.message}"
|
92
|
+
else
|
93
|
+
raise e
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# This class represents a Marathon Deployment.
|
2
|
+
# See https://mesosphere.github.io/marathon/docs/rest-api.html#deployments for full list of API's methods.
|
3
|
+
class Marathon::Deployment
|
4
|
+
|
5
|
+
attr_reader :info
|
6
|
+
|
7
|
+
# Create a new deployment object.
|
8
|
+
# ++hash++: Hash including all attributes.
|
9
|
+
# See https://mesosphere.github.io/marathon/docs/rest-api.html#get-/v2/deployments for full details.
|
10
|
+
def initialize(hash = {})
|
11
|
+
@info = hash
|
12
|
+
end
|
13
|
+
|
14
|
+
# Shortcuts for reaching attributes
|
15
|
+
%w[ id affectedApps steps currentActions version currentStep totalSteps ].each do |method|
|
16
|
+
define_method(method) { |*args, &block| info[method] }
|
17
|
+
end
|
18
|
+
|
19
|
+
# Cancel the deployment.
|
20
|
+
# ++force++: If set to false (the default) then the deployment is canceled and a new deployment
|
21
|
+
# is created to restore the previous configuration. If set to true, then the deployment
|
22
|
+
# is still canceled but no rollback deployment is created.
|
23
|
+
def delete(force = false)
|
24
|
+
self.class.delete(id, force)
|
25
|
+
end
|
26
|
+
alias :cancel :delete
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
"Marathon::Deployment { " \
|
30
|
+
+ ":id => #{id} :affectedApps => #{affectedApps} :currentStep => #{currentStep} :totalSteps => #{totalSteps} }"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return deployment as JSON formatted string.
|
34
|
+
def to_json
|
35
|
+
info.to_json
|
36
|
+
end
|
37
|
+
|
38
|
+
class << self
|
39
|
+
|
40
|
+
# List running deployments.
|
41
|
+
def list
|
42
|
+
json = Marathon.connection.get('/v2/deployments')
|
43
|
+
json.map { |j| new(j) }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Cancel the deployment with id.
|
47
|
+
# ++id++: Deployment's id
|
48
|
+
# ++force++: If set to false (the default) then the deployment is canceled and a new deployment
|
49
|
+
# is created to restore the previous configuration. If set to true, then the deployment
|
50
|
+
# is still canceled but no rollback deployment is created.
|
51
|
+
def delete(id, force = false)
|
52
|
+
query = {}
|
53
|
+
query[:force] = true if force
|
54
|
+
json = Marathon.connection.delete("/v2/deployments/#{id}")
|
55
|
+
# TODO parse deploymentId + version
|
56
|
+
end
|
57
|
+
alias :cancel :delete
|
58
|
+
alias :remove :delete
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# This module holds the Errors for the gem.
|
2
|
+
module Marathon::Error
|
3
|
+
# The default error. It's never actually raised, but can be used to catch all
|
4
|
+
# gem-specific errors that are thrown as they all subclass from this.
|
5
|
+
class MarathonError < StandardError; end
|
6
|
+
|
7
|
+
# Raised when invalid arguments are passed to a method.
|
8
|
+
class ArgumentError < MarathonError; end
|
9
|
+
|
10
|
+
# Raised when a request returns a 400.
|
11
|
+
class ClientError < MarathonError; end
|
12
|
+
|
13
|
+
# Raised when a request returns a 404.
|
14
|
+
class NotFoundError < MarathonError; end
|
15
|
+
|
16
|
+
# Raised when there is an unexpected response code / body.
|
17
|
+
class UnexpectedResponseError < MarathonError; end
|
18
|
+
|
19
|
+
# Raised when a request times out.
|
20
|
+
class TimeoutError < MarathonError; end
|
21
|
+
|
22
|
+
# Raised when login fails.
|
23
|
+
class AuthenticationError < MarathonError; end
|
24
|
+
|
25
|
+
# Raised when an IO action fails.
|
26
|
+
class IOError < MarathonError; end
|
27
|
+
|
28
|
+
# Raise error specific to http response.
|
29
|
+
# ++response++: HTTParty response object.
|
30
|
+
def from_response(response)
|
31
|
+
error_class(response).new(error_message(response))
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Get reponse code specific error class.
|
37
|
+
# ++response++: HTTParty response object.
|
38
|
+
def error_class(response)
|
39
|
+
case response.code
|
40
|
+
when 400
|
41
|
+
ClientError
|
42
|
+
when 404
|
43
|
+
NotFoundError
|
44
|
+
else
|
45
|
+
UnexpectedResponseError
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get response code from http response.
|
50
|
+
# ++response++: HTTParty response object.
|
51
|
+
def error_message(response)
|
52
|
+
body = response.parsed_response
|
53
|
+
if body.is_a?(Hash)
|
54
|
+
body['message']
|
55
|
+
else
|
56
|
+
body
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module_function :error_class, :error_message, :from_response
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# This class represents a Marathon Event Subscriptions.
|
2
|
+
# See https://mesosphere.github.io/marathon/docs/rest-api.html#event-subscriptions for full list of API's methods.
|
3
|
+
class Marathon::EventSubscriptions
|
4
|
+
|
5
|
+
class << self
|
6
|
+
# List all event subscriber callback URLs.
|
7
|
+
# Returns a list of strings/URLs.
|
8
|
+
def list
|
9
|
+
json = Marathon.connection.get('/v2/eventSubscriptions')
|
10
|
+
json['callbackUrls']
|
11
|
+
end
|
12
|
+
|
13
|
+
# Register a callback URL as an event subscriber.
|
14
|
+
# ++callbackUrl++: URL to which events should be posted.
|
15
|
+
# Returns an event as hash.
|
16
|
+
def register(callbackUrl)
|
17
|
+
query = {}
|
18
|
+
query[:callbackUrl] = callbackUrl
|
19
|
+
json = Marathon.connection.post('/v2/eventSubscriptions', query)
|
20
|
+
json
|
21
|
+
end
|
22
|
+
|
23
|
+
# Unregister a callback URL from the event subscribers list.
|
24
|
+
# ++callbackUrl++: URL passed when the event subscription was created.
|
25
|
+
# Returns an event as hash.
|
26
|
+
def unregister(callbackUrl)
|
27
|
+
query = {}
|
28
|
+
query[:callbackUrl] = callbackUrl
|
29
|
+
json = Marathon.connection.delete('/v2/eventSubscriptions', query)
|
30
|
+
json
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This class represents a Marathon Leader.
|
2
|
+
# See https://mesosphere.github.io/marathon/docs/rest-api.html#get-/v2/leader for full list of API's methods.
|
3
|
+
class Marathon::Leader
|
4
|
+
|
5
|
+
class << self
|
6
|
+
# Returns the current leader. If no leader exists, raises NotFoundError.
|
7
|
+
def get
|
8
|
+
json = Marathon.connection.get('/v2/leader')
|
9
|
+
json['leader']
|
10
|
+
end
|
11
|
+
|
12
|
+
# Causes the current leader to abdicate, triggering a new election.
|
13
|
+
# If no leader exists, raises NotFoundError.
|
14
|
+
def delete
|
15
|
+
json = Marathon.connection.delete('/v2/leader')
|
16
|
+
json['message']
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# This class represents a Marathon Queue element.
|
2
|
+
# See https://mesosphere.github.io/marathon/docs/rest-api.html#queue for full list of API's methods.
|
3
|
+
class Marathon::Queue
|
4
|
+
|
5
|
+
attr_reader :app
|
6
|
+
attr_reader :delay
|
7
|
+
|
8
|
+
# Create a new queue element object.
|
9
|
+
# ++hash++: Hash returned by API, including 'app' and 'delay'
|
10
|
+
def initialize(hash = {})
|
11
|
+
@app = Marathon::App.new(hash['app'], true)
|
12
|
+
@delay = hash['delay']
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"Marathon::Queue { :appId => #{app.id} :delay => #{delay} }"
|
17
|
+
end
|
18
|
+
|
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
|
+
class << self
|
28
|
+
|
29
|
+
# Show content of the task queue.
|
30
|
+
# Returns Array of Queue objects.
|
31
|
+
def list
|
32
|
+
json = Marathon.connection.get('/v2/queue')['queue']
|
33
|
+
json.map { |j| new(j) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# This class represents a Marathon Task.
|
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
|
4
|
+
|
5
|
+
attr_reader :info
|
6
|
+
|
7
|
+
# Create a new task object.
|
8
|
+
# ++hash++: Hash including all attributes
|
9
|
+
def initialize(hash = {})
|
10
|
+
@info = hash
|
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] }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Kill the task that belongs to an application.
|
19
|
+
# ++scale++: Scale the app down (i.e. decrement its instances setting by the number of tasks killed)
|
20
|
+
# after killing the specified tasks.
|
21
|
+
def delete!(scale = false)
|
22
|
+
new_task = self.class.delete(appId, id, scale)
|
23
|
+
@info = new_task.info
|
24
|
+
end
|
25
|
+
alias :kill! :delete!
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"Marathon::Task { :id => #{self.id} :appId => #{appId} :host => #{host} }"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return task as JSON formatted string.
|
32
|
+
def to_json
|
33
|
+
info.to_json
|
34
|
+
end
|
35
|
+
|
36
|
+
class << self
|
37
|
+
|
38
|
+
# List tasks of all applications.
|
39
|
+
# ++status++: Return only those tasks whose status matches this parameter.
|
40
|
+
# If not specified, all tasks are returned. Possible values: running, staging.
|
41
|
+
def list(status = nil)
|
42
|
+
query = {}
|
43
|
+
Marathon::Util.add_choice(query, :status, status, %w[running staging])
|
44
|
+
json = Marathon.connection.get('/v2/tasks', query)['tasks']
|
45
|
+
json.map { |j| new(j) }
|
46
|
+
end
|
47
|
+
|
48
|
+
# List all running tasks for application appId.
|
49
|
+
# ++appId++: Application's id
|
50
|
+
def get(appId)
|
51
|
+
json = Marathon.connection.get("/v2/apps/#{appId}/tasks")['tasks']
|
52
|
+
json.map { |j| new(j) }
|
53
|
+
end
|
54
|
+
|
55
|
+
# Kill the task that belongs to the application appId.
|
56
|
+
# ++appId++: Application's id
|
57
|
+
# ++id++: Id of target task.
|
58
|
+
# ++scale++: Scale the app down (i.e. decrement its instances setting by the number of tasks killed)
|
59
|
+
# after killing the specified tasks.
|
60
|
+
def delete(appId, id, scale = false)
|
61
|
+
query = {}
|
62
|
+
query[:scale] = true if scale
|
63
|
+
json = Marathon.connection.delete("/v2/apps/#{appId}/tasks/#{id}", query)
|
64
|
+
new(json)
|
65
|
+
end
|
66
|
+
alias :remove :delete
|
67
|
+
alias :kill :delete
|
68
|
+
|
69
|
+
# Kill tasks that belong to the application appId.
|
70
|
+
# ++appId++: Application's id
|
71
|
+
# ++host++: Kill only those tasks running on host host.
|
72
|
+
# ++scale++: Scale the app down (i.e. decrement its instances setting by the number of tasks killed)
|
73
|
+
# after killing the specified tasks.
|
74
|
+
def delete_all(appId, host = nil, scale = false)
|
75
|
+
query = {}
|
76
|
+
query[:host] = host if host
|
77
|
+
query[:scale] = true if scale
|
78
|
+
json = Marathon.connection.delete("/v2/apps/#{appId}/tasks", query)['tasks']
|
79
|
+
json.map { |j| new(j) }
|
80
|
+
end
|
81
|
+
alias :remove_all :delete_all
|
82
|
+
alias :kill_all :delete_all
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Some helper things.
|
2
|
+
class Marathon::Util
|
3
|
+
class << self
|
4
|
+
|
5
|
+
# Checks if parameter is of allowed value.
|
6
|
+
# ++name++: parameter's name
|
7
|
+
# ++value++: parameter's value
|
8
|
+
# ++allowed++: array of allowd values
|
9
|
+
# ++nil_allowed++: allow nil values
|
10
|
+
def validate_choice(name, value, allowed, nil_allowed = true)
|
11
|
+
if value.nil?
|
12
|
+
unless nil_allowed
|
13
|
+
raise Marathon::Error::ArgumentError, "#{name} must not be nil"
|
14
|
+
end
|
15
|
+
else
|
16
|
+
# value is not nil
|
17
|
+
unless allowed.include?(value)
|
18
|
+
msg = nil_allowed ? "#{name} must be one of #{allowed}, or nil" : "#{name} must be one of #{allowed}"
|
19
|
+
raise Marathon::Error::ArgumentError, msg
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Check parameter and add it to hash if not nil.
|
25
|
+
# ++opts++: hash of parameters
|
26
|
+
# ++name++: parameter's name
|
27
|
+
# ++value++: parameter's value
|
28
|
+
# ++allowed++: array of allowd values
|
29
|
+
# ++nil_allowed++: allow nil values
|
30
|
+
def add_choice(opts, name, value, allowed, nil_allowed = true)
|
31
|
+
validate_choice(name, value, allowed, nil_allowed)
|
32
|
+
opts[name] = value if value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/marathon/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "marathon-api"
|
6
|
+
gem.version = Marathon::VERSION
|
7
|
+
gem.authors = ["Felix Bechstein"]
|
8
|
+
gem.email = %w{f@ub0r.de}
|
9
|
+
gem.description = %q{A simple REST client for the Marathon Remote API}
|
10
|
+
gem.summary = %q{A simple REST client for the Marathon Remote API}
|
11
|
+
gem.homepage = 'https://github.com/felixb/marathon-api'
|
12
|
+
gem.license = 'MIT'
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split($\)
|
15
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
|
+
gem.require_paths = %w{lib}
|
18
|
+
|
19
|
+
gem.add_dependency 'json'
|
20
|
+
gem.add_dependency "httparty", ">= 0.11"
|
21
|
+
|
22
|
+
gem.add_development_dependency 'rake'
|
23
|
+
gem.add_development_dependency 'rspec', '~> 3.0'
|
24
|
+
gem.add_development_dependency 'rspec-its'
|
25
|
+
gem.add_development_dependency 'vcr', '>= 2.7.0'
|
26
|
+
gem.add_development_dependency 'webmock'
|
27
|
+
gem.add_development_dependency 'pry'
|
28
|
+
gem.add_development_dependency 'cane'
|
29
|
+
gem.add_development_dependency 'simplecov'
|
30
|
+
gem.add_development_dependency 'codeclimate-test-reporter'
|
31
|
+
end
|