heroku-client 0.0.1
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.
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Guardfile +9 -0
- data/LICENSE +22 -0
- data/README.md +73 -0
- data/Rakefile +2 -0
- data/heroku-client.gemspec +25 -0
- data/lib/heroku-client.rb +15 -0
- data/lib/heroku-client/api.rb +49 -0
- data/lib/heroku-client/heroku_obj.rb +20 -0
- data/lib/heroku-client/http.rb +52 -0
- data/lib/heroku-client/version.rb +5 -0
- data/spec/heroku-client/api_spec.rb +117 -0
- data/spec/heroku-client/heroku_obj_spec.rb +17 -0
- data/spec/heroku-client/http_spec.rb +81 -0
- data/spec/heroku-client_spec.rb +15 -0
- data/spec/responses/api.rb +186 -0
- data/spec/spec_helper.rb +15 -0
- metadata +150 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Rodrigo Saito
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# Heroku::Client
|
2
|
+
|
3
|
+
Client for accessing heroku api from ruby applications
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'heroku-client'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install heroku-client
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Create a new client:
|
22
|
+
|
23
|
+
client = Heroku::Client.create "your_api_key"
|
24
|
+
|
25
|
+
Get all your apps:
|
26
|
+
|
27
|
+
client.apps
|
28
|
+
|
29
|
+
You can iterate over apps:
|
30
|
+
|
31
|
+
client.apps.each { |a| puts a.name }
|
32
|
+
|
33
|
+
Get one app by name:
|
34
|
+
|
35
|
+
client.apps "example_app"
|
36
|
+
|
37
|
+
Get colaborators for an app
|
38
|
+
|
39
|
+
client.collaborators "example_app"
|
40
|
+
|
41
|
+
Get config vars for an app
|
42
|
+
|
43
|
+
client.config_vars "example_app"
|
44
|
+
|
45
|
+
Get domains for an app
|
46
|
+
|
47
|
+
client.domains "example_app"
|
48
|
+
|
49
|
+
Get user keys
|
50
|
+
|
51
|
+
client.keys
|
52
|
+
|
53
|
+
Get processes for an app
|
54
|
+
|
55
|
+
client.processes "example_app"
|
56
|
+
|
57
|
+
Get releases for an app
|
58
|
+
|
59
|
+
client.releases "example_app"
|
60
|
+
|
61
|
+
Get available stacks for an app
|
62
|
+
|
63
|
+
client.stacks "example_app"
|
64
|
+
|
65
|
+
For more examples of usage, look at the spec folder: api_spec.rb
|
66
|
+
|
67
|
+
## Contributing
|
68
|
+
|
69
|
+
1. Fork it
|
70
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
71
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
72
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
73
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/heroku-client/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Rodrigo Saito"]
|
6
|
+
gem.email = ["rodrigo.saito@gmail.com"]
|
7
|
+
gem.description = %q{Client for Heroku api}
|
8
|
+
gem.summary = %q{Client for accessing heroku api}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "heroku-client"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Heroku::Client::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency "httparty"
|
19
|
+
gem.add_dependency "json"
|
20
|
+
|
21
|
+
gem.add_development_dependency "rspec"
|
22
|
+
gem.add_development_dependency "guard-rspec"
|
23
|
+
gem.add_development_dependency "fakeweb"
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "httparty"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
require "heroku-client/version"
|
5
|
+
require "heroku-client/heroku_obj"
|
6
|
+
require "heroku-client/http"
|
7
|
+
require "heroku-client/api"
|
8
|
+
|
9
|
+
module Heroku
|
10
|
+
module Client
|
11
|
+
def self.create(apikey)
|
12
|
+
Api.new(apikey)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Heroku
|
2
|
+
module Client
|
3
|
+
class Api
|
4
|
+
include Http
|
5
|
+
|
6
|
+
attr_reader :apikey
|
7
|
+
|
8
|
+
def apps(*args)
|
9
|
+
return get("apps") if args.size == 0
|
10
|
+
|
11
|
+
return get("apps/#{args[0]}") if args.size == 1
|
12
|
+
|
13
|
+
raise "Invalid number of parameters"
|
14
|
+
end
|
15
|
+
|
16
|
+
def collaborators(app_name)
|
17
|
+
return get("apps/#{app_name}/collaborators")
|
18
|
+
end
|
19
|
+
|
20
|
+
def config_vars(app_name)
|
21
|
+
return get("apps/#{app_name}/config_vars")
|
22
|
+
end
|
23
|
+
|
24
|
+
def domains(app_name)
|
25
|
+
return get("apps/#{app_name}/domains")
|
26
|
+
end
|
27
|
+
|
28
|
+
def keys
|
29
|
+
return get("user/keys")
|
30
|
+
end
|
31
|
+
|
32
|
+
def processes(app_name)
|
33
|
+
return get("apps/#{app_name}/ps")
|
34
|
+
end
|
35
|
+
|
36
|
+
def releases(app_name)
|
37
|
+
return get("apps/#{app_name}/releases")
|
38
|
+
end
|
39
|
+
|
40
|
+
def stacks(app_name)
|
41
|
+
get "apps/#{app_name}/stack"
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(apikey)
|
45
|
+
@apikey = apikey
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Heroku
|
2
|
+
module Client
|
3
|
+
class HerokuObj
|
4
|
+
|
5
|
+
def method_missing(method, *args)
|
6
|
+
attribute = method.to_s
|
7
|
+
|
8
|
+
attribute = attribute.to_s[0..-2] if attribute.end_with?('?')
|
9
|
+
|
10
|
+
super.method_missing(method, args) unless @json.has_key?(attribute)
|
11
|
+
|
12
|
+
@json["#{attribute}"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(json)
|
16
|
+
@json = json
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Heroku
|
2
|
+
module Client
|
3
|
+
module Http
|
4
|
+
def get(uri)
|
5
|
+
headers = { "Accept" => "application/json"}
|
6
|
+
resp = HTTParty.get "https://api.heroku.com/#{uri}", { basic_auth: { password: apikey }, headers: headers}
|
7
|
+
|
8
|
+
raise UnauthorizedError if resp.code == 401
|
9
|
+
raise PaymentRequiredError if resp.code == 402
|
10
|
+
raise ForbiddenError if resp.code == 403
|
11
|
+
raise NotFoundError if resp.code == 404
|
12
|
+
raise PreConditionFailedError if resp.code == 412
|
13
|
+
raise UnprocessableEntityError if resp.code == 422
|
14
|
+
raise LockedError if resp.code == 423
|
15
|
+
|
16
|
+
raise UnknownError unless resp.success?
|
17
|
+
|
18
|
+
parsed = JSON.parse(resp.body)
|
19
|
+
|
20
|
+
parsed = parsed.map { |o| HerokuObj.new(o) } if parsed.is_a? Array
|
21
|
+
|
22
|
+
parsed = HerokuObj.new parsed if parsed.is_a? Hash
|
23
|
+
|
24
|
+
parsed
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class UnauthorizedError < Exception
|
29
|
+
end
|
30
|
+
|
31
|
+
class PaymentRequiredError < Exception
|
32
|
+
end
|
33
|
+
|
34
|
+
class ForbiddenError < Exception
|
35
|
+
end
|
36
|
+
|
37
|
+
class NotFoundError < Exception
|
38
|
+
end
|
39
|
+
|
40
|
+
class PreConditionFailedError < Exception
|
41
|
+
end
|
42
|
+
|
43
|
+
class UnprocessableEntityError < Exception
|
44
|
+
end
|
45
|
+
|
46
|
+
class LockedError < Exception
|
47
|
+
end
|
48
|
+
|
49
|
+
class UnknownError < Exception
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Heroku::Client::Api do
|
4
|
+
|
5
|
+
let(:app_name) { "example" }
|
6
|
+
|
7
|
+
before do
|
8
|
+
FakeWeb.register_uri :get, Responses::Api.apps_url(api.apikey), body: Responses::Api.apps
|
9
|
+
FakeWeb.register_uri :get, Responses::Api.apps_by_name_url(api.apikey), body: Responses::Api.apps_by_name
|
10
|
+
FakeWeb.register_uri :get, Responses::Api.collaborators_url(api.apikey, app_name), body: Responses::Api.collaborators
|
11
|
+
FakeWeb.register_uri :get, Responses::Api.config_vars_url(api.apikey, app_name), body: Responses::Api.config_vars
|
12
|
+
FakeWeb.register_uri :get, Responses::Api.domains_url(api.apikey, app_name), body: Responses::Api.domains
|
13
|
+
FakeWeb.register_uri :get, Responses::Api.keys_url(api.apikey), body: Responses::Api.keys
|
14
|
+
FakeWeb.register_uri :get, Responses::Api.processes_url(api.apikey, app_name), body: Responses::Api.processes
|
15
|
+
FakeWeb.register_uri :get, Responses::Api.releases_url(api.apikey, app_name), body: Responses::Api.releases
|
16
|
+
FakeWeb.register_uri :get, Responses::Api.stacks_url(api.apikey, app_name), body: Responses::Api.stacks
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:api) { Heroku::Client::Api.new "apikey" }
|
20
|
+
|
21
|
+
describe "#apps" do
|
22
|
+
let(:apps) { api.apps }
|
23
|
+
|
24
|
+
it "returns 1 app" do
|
25
|
+
apps.size.should eq(1)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "has attribute stack" do
|
29
|
+
apps.first.stack.should eq("bamboo-ree-1.8.7")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#apps(name)" do
|
34
|
+
it "returns app" do
|
35
|
+
api.apps(app_name).name.should eq(app_name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#collaborators" do
|
40
|
+
let(:collaborators) { api.collaborators(app_name) }
|
41
|
+
|
42
|
+
it "returns collaborator for an app" do
|
43
|
+
collaborators.size.should eq(2)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "collaborator has email attribute" do
|
47
|
+
collaborators.first.email.should eq("editor@example.org")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "config_vars" do
|
52
|
+
it "returns config vars for an app" do
|
53
|
+
api.config_vars(app_name).KEY1.should eq("value1")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "domains" do
|
58
|
+
let(:domains) { api.domains(app_name) }
|
59
|
+
|
60
|
+
it "returns 1 domain" do
|
61
|
+
domains.size.should eq(1)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "domain has domain attribute" do
|
65
|
+
domains.first.domain.should eq("foo.exampleiii.org")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#keys" do
|
70
|
+
let(:keys) { api.keys }
|
71
|
+
|
72
|
+
it "returns 1 key" do
|
73
|
+
keys.size.should eq(1)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "keys has contents attribute" do
|
77
|
+
keys.first.contents.should eq("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz29znMi/UJX/nvkRSO5FFugKhU9DkkI53E0vXUnP8zeLFxMgyUqmXryPVjWtGzz2LRWqjm14SbqHAmM44pGHVfBIp6wCKBWSUYGv/FxOulwYgtWzz4moxWLZrFyWWgJAnehcVUifHNgzKwT2ovWm2ns52681Z8yFK3K8/uLStDjLIaPePEOaxaTvgIxZNsfyEoXoHcyTPwdR1GtQuDTuDYqYmjmPCoKybYnXrTQ1QFuQxDneBkswQYSl0H2aLf3uBK4F01hr+azXQuSe39eSV4I/TqzmNJlanpILT9Jz3/J1i4r6brpF3AxLnFnb9ufIbzQAIa/VZIulfrZkcBsUl david@carbon.local")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#processes" do
|
82
|
+
let(:processes) { api.processes(app_name) }
|
83
|
+
|
84
|
+
it "returns 1 process" do
|
85
|
+
processes.size.should eq(1)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "process has command attribute" do
|
89
|
+
processes.first.command.should eq("dyno")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#releases" do
|
94
|
+
let(:releases) { api.releases(app_name) }
|
95
|
+
|
96
|
+
it "returns 1 release" do
|
97
|
+
releases.size.should eq(1)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "release has attribute commit" do
|
101
|
+
releases.first.commit.should eq("0f0f0f0")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "#stacks" do
|
106
|
+
let(:stacks) { api.stacks(app_name) }
|
107
|
+
|
108
|
+
it "returns 1 stack" do
|
109
|
+
stacks.size.should eq(1)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "stack has attribute requested" do
|
113
|
+
stacks.first.requested?.should be_false
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Heroku::Client::HerokuObj do
|
4
|
+
|
5
|
+
let(:obj) { Heroku::Client::HerokuObj.new JSON.parse(Responses::Api.apps).first }
|
6
|
+
|
7
|
+
it "should have an attribute" do
|
8
|
+
obj.id.should eq(1000000)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should raise error for invalid attribute" do
|
12
|
+
expect {
|
13
|
+
obj.invalid
|
14
|
+
}.to raise_error(NoMethodError)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Heroku::Client::Http do
|
4
|
+
let :http do
|
5
|
+
# Helper class to test Http module
|
6
|
+
class Http
|
7
|
+
include Heroku::Client::Http
|
8
|
+
|
9
|
+
def apikey
|
10
|
+
"apikey"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
Http.new
|
15
|
+
end
|
16
|
+
|
17
|
+
describe ".get" do
|
18
|
+
context "success" do
|
19
|
+
before do
|
20
|
+
FakeWeb.register_uri :get, Responses::Api.apps_url(http.apikey), body: Responses::Api.apps
|
21
|
+
FakeWeb.register_uri :get, Responses::Api.apps_by_name_url(http.apikey), body: Responses::Api.apps_by_name
|
22
|
+
end
|
23
|
+
|
24
|
+
it "parses the response body" do
|
25
|
+
http.get("apps").should be_a(Array)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "parses the json hash to HerokuObj" do
|
29
|
+
http.get("apps").first.should be_a(Heroku::Client::HerokuObj)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "parses the json hash to HerokuObj" do
|
33
|
+
http.get("apps/example").should be_a(Heroku::Client::HerokuObj)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
shared_examples "http request error" do |http_code, http_msg, error_class|
|
38
|
+
before do
|
39
|
+
FakeWeb.register_uri :get, "https://:apikey@api.heroku.com/apps", status: [http_code, http_msg]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "raises #{error_class}" do
|
43
|
+
expect {
|
44
|
+
http.get("apps")
|
45
|
+
}.to raise_error(error_class)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "unauthorized" do
|
50
|
+
it_behaves_like "http request error", "401", "Unauthorized", Heroku::Client::UnauthorizedError
|
51
|
+
end
|
52
|
+
|
53
|
+
context "payment required" do
|
54
|
+
it_behaves_like "http request error", "402", "PaymentRequired", Heroku::Client::PaymentRequiredError
|
55
|
+
end
|
56
|
+
|
57
|
+
context "forbidden" do
|
58
|
+
it_behaves_like "http request error", "403", "Forbidden", Heroku::Client::ForbiddenError
|
59
|
+
end
|
60
|
+
|
61
|
+
context "not found" do
|
62
|
+
it_behaves_like "http request error", "404", "Not Found", Heroku::Client::NotFoundError
|
63
|
+
end
|
64
|
+
|
65
|
+
context "precondition failed" do
|
66
|
+
it_behaves_like "http request error", "412", "Precondition Failed", Heroku::Client::PreConditionFailedError
|
67
|
+
end
|
68
|
+
|
69
|
+
context "unprocessable entity" do
|
70
|
+
it_behaves_like "http request error", "422", "Unprocessable Entity", Heroku::Client::UnprocessableEntityError
|
71
|
+
end
|
72
|
+
|
73
|
+
context "locked" do
|
74
|
+
it_behaves_like "http request error", "423", "Locked Error", Heroku::Client::LockedError
|
75
|
+
end
|
76
|
+
|
77
|
+
context "unknown error" do
|
78
|
+
it_behaves_like "http request error", "500", "Unknown Error", Heroku::Client::UnknownError
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Heroku::Client do
|
4
|
+
|
5
|
+
describe ".create" do
|
6
|
+
it "creates an Api object to access heroku api" do
|
7
|
+
Heroku::Client.create("apikey").should_not be_nil
|
8
|
+
end
|
9
|
+
|
10
|
+
it "creates an Api object that has the apikey attribute" do
|
11
|
+
Heroku::Client.create("apikey").apikey.should eq("apikey")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
module Responses
|
2
|
+
module Api
|
3
|
+
def self.apps_url(apikey)
|
4
|
+
base_url(apikey, "apps")
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.apps
|
8
|
+
return <<-EJSON
|
9
|
+
[
|
10
|
+
{
|
11
|
+
"id": 1000000,
|
12
|
+
"name": "example",
|
13
|
+
"create_status": "complete",
|
14
|
+
"created_at": "2011/01/01 00:00:00 -0700",
|
15
|
+
"stack": "bamboo-ree-1.8.7",
|
16
|
+
"requested_stack": null,
|
17
|
+
"repo_migrate_status": "complete",
|
18
|
+
"slug_size": 1000000,
|
19
|
+
"repo_size": 1000000,
|
20
|
+
"dynos": 1,
|
21
|
+
"workers": 0
|
22
|
+
}
|
23
|
+
]
|
24
|
+
EJSON
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.apps_by_name_url(apikey)
|
28
|
+
base_url(apikey, "apps/example")
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.apps_by_name
|
32
|
+
return <<-EJSON
|
33
|
+
{
|
34
|
+
"id": 1000000,
|
35
|
+
"name": "example",
|
36
|
+
"create_status": "complete",
|
37
|
+
"created_at": "2011/01/01 00:00:00 -0700",
|
38
|
+
"stack": "cedar",
|
39
|
+
"requested_stack": null,
|
40
|
+
"repo_migrate_status": "complete",
|
41
|
+
"slug_size": 1000000,
|
42
|
+
"repo_size": 1000000,
|
43
|
+
"dynos": 1,
|
44
|
+
"workers": 0
|
45
|
+
}
|
46
|
+
EJSON
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.collaborators_url(apikey, app_name)
|
50
|
+
base_url(apikey, "apps/#{app_name}/collaborators")
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.collaborators
|
54
|
+
return <<-EJSON
|
55
|
+
[
|
56
|
+
{
|
57
|
+
"access": "edit",
|
58
|
+
"email": "editor@example.org"
|
59
|
+
},
|
60
|
+
{
|
61
|
+
"access": "invited",
|
62
|
+
"email": "invitee@heroku.com"
|
63
|
+
}
|
64
|
+
]
|
65
|
+
EJSON
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.config_vars_url(apikey, app_name)
|
69
|
+
base_url(apikey, "apps/#{app_name}/config_vars")
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.config_vars
|
73
|
+
return <<-EJSON
|
74
|
+
{
|
75
|
+
"KEY1": "value1",
|
76
|
+
"KEY2": "value2"
|
77
|
+
}
|
78
|
+
EJSON
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.domains_url(apikey, app_name)
|
82
|
+
base_url(apikey, "apps/#{app_name}/domains")
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.domains
|
86
|
+
return <<-EJSON
|
87
|
+
[
|
88
|
+
{
|
89
|
+
"id": 49458,
|
90
|
+
"app_id": 278620,
|
91
|
+
"domain": "foo.exampleiii.org",
|
92
|
+
"base_domain": "exampleiii.org",
|
93
|
+
"default": null,
|
94
|
+
"created_at": "2011/01/01 00:00:00 -0700",
|
95
|
+
"updated_at": "2011/01/01 00:00:00 -0700"
|
96
|
+
}
|
97
|
+
]
|
98
|
+
EJSON
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.keys_url(apikey)
|
102
|
+
base_url apikey, "user/keys"
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.keys
|
106
|
+
<<-EJSON
|
107
|
+
[
|
108
|
+
{
|
109
|
+
"contents": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz29znMi/UJX/nvkRSO5FFugKhU9DkkI53E0vXUnP8zeLFxMgyUqmXryPVjWtGzz2LRWqjm14SbqHAmM44pGHVfBIp6wCKBWSUYGv/FxOulwYgtWzz4moxWLZrFyWWgJAnehcVUifHNgzKwT2ovWm2ns52681Z8yFK3K8/uLStDjLIaPePEOaxaTvgIxZNsfyEoXoHcyTPwdR1GtQuDTuDYqYmjmPCoKybYnXrTQ1QFuQxDneBkswQYSl0H2aLf3uBK4F01hr+azXQuSe39eSV4I/TqzmNJlanpILT9Jz3/J1i4r6brpF3AxLnFnb9ufIbzQAIa/VZIulfrZkcBsUl david@carbon.local",
|
110
|
+
"email": "keyowner@example.org"
|
111
|
+
}
|
112
|
+
]
|
113
|
+
EJSON
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.processes_url(apikey, app_name)
|
117
|
+
base_url apikey, "apps/#{app_name}/ps"
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.processes
|
121
|
+
<<-EJSON
|
122
|
+
[
|
123
|
+
{
|
124
|
+
"upid": "10000000",
|
125
|
+
"process": "web.1",
|
126
|
+
"type": "Dyno",
|
127
|
+
"command": "dyno",
|
128
|
+
"app_name": "example",
|
129
|
+
"slug": "0000000_0000",
|
130
|
+
"action": "down",
|
131
|
+
"state": "idle",
|
132
|
+
"pretty_state": "idle for 2h",
|
133
|
+
"elapsed": 0,
|
134
|
+
"rendezvous_url": null,
|
135
|
+
"attached": false,
|
136
|
+
"transitioned_at": "2011/01/01 00:00:00 -0700"
|
137
|
+
}
|
138
|
+
]
|
139
|
+
EJSON
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.releases_url(apikey, app_name)
|
143
|
+
base_url apikey, "apps/#{app_name}/releases"
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.releases
|
147
|
+
<<-EJSON
|
148
|
+
[
|
149
|
+
{
|
150
|
+
"name": "v1",
|
151
|
+
"descr": "Add-on add example:addon",
|
152
|
+
"user": "releasing-user@example.org",
|
153
|
+
"commit": "0f0f0f0",
|
154
|
+
"env": { "FOO": "bar" },
|
155
|
+
"addons": [ "example:addon" ],
|
156
|
+
"pstable": { "web": "bin/web start" },
|
157
|
+
"created_at": "2011/01/01 00:00:00 -0700"
|
158
|
+
}
|
159
|
+
]
|
160
|
+
EJSON
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.stacks_url(apikey, app_name)
|
164
|
+
base_url apikey, "apps/#{app_name}/stack"
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.stacks
|
168
|
+
<<-EJSON
|
169
|
+
[
|
170
|
+
{
|
171
|
+
"name": "aspen-mri-1.8.6",
|
172
|
+
"current": false,
|
173
|
+
"requested": false,
|
174
|
+
"beta": false
|
175
|
+
}
|
176
|
+
]
|
177
|
+
EJSON
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.base_url(apikey, uri)
|
181
|
+
"https://:apikey@api.heroku.com/#{uri}"
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
end
|
186
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'fakeweb'
|
5
|
+
require 'heroku-client'
|
6
|
+
require 'responses/api'
|
7
|
+
|
8
|
+
FakeWeb.allow_net_connect = false
|
9
|
+
|
10
|
+
shared_examples "attribute" do |attr, expected|
|
11
|
+
it "should return #{attr} attribute" do
|
12
|
+
subject.send(attr).should eq(expected)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: heroku-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rodrigo Saito
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-27 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: json
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: guard-rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: fakeweb
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Client for Heroku api
|
95
|
+
email:
|
96
|
+
- rodrigo.saito@gmail.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- .rspec
|
103
|
+
- Gemfile
|
104
|
+
- Guardfile
|
105
|
+
- LICENSE
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- heroku-client.gemspec
|
109
|
+
- lib/heroku-client.rb
|
110
|
+
- lib/heroku-client/api.rb
|
111
|
+
- lib/heroku-client/heroku_obj.rb
|
112
|
+
- lib/heroku-client/http.rb
|
113
|
+
- lib/heroku-client/version.rb
|
114
|
+
- spec/heroku-client/api_spec.rb
|
115
|
+
- spec/heroku-client/heroku_obj_spec.rb
|
116
|
+
- spec/heroku-client/http_spec.rb
|
117
|
+
- spec/heroku-client_spec.rb
|
118
|
+
- spec/responses/api.rb
|
119
|
+
- spec/spec_helper.rb
|
120
|
+
homepage: ''
|
121
|
+
licenses: []
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
requirements: []
|
139
|
+
rubyforge_project:
|
140
|
+
rubygems_version: 1.8.24
|
141
|
+
signing_key:
|
142
|
+
specification_version: 3
|
143
|
+
summary: Client for accessing heroku api
|
144
|
+
test_files:
|
145
|
+
- spec/heroku-client/api_spec.rb
|
146
|
+
- spec/heroku-client/heroku_obj_spec.rb
|
147
|
+
- spec/heroku-client/http_spec.rb
|
148
|
+
- spec/heroku-client_spec.rb
|
149
|
+
- spec/responses/api.rb
|
150
|
+
- spec/spec_helper.rb
|