heroku-api 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -11
- data/Rakefile +1 -1
- data/changelog.txt +11 -0
- data/heroku-api.gemspec +1 -1
- data/lib/heroku-api.rb +1 -1
- data/lib/heroku/api.rb +14 -0
- data/lib/heroku/api/addons.rb +6 -5
- data/lib/heroku/api/apps.rb +1 -1
- data/lib/heroku/api/mock.rb +15 -1
- data/lib/heroku/api/mock/addons.rb +22 -22
- data/lib/heroku/api/mock/apps.rb +9 -9
- data/lib/heroku/api/mock/cache/get_user.json +1 -0
- data/lib/heroku/api/mock/collaborators.rb +4 -4
- data/lib/heroku/api/mock/config_vars.rb +3 -3
- data/lib/heroku/api/mock/domains.rb +3 -3
- data/lib/heroku/api/mock/keys.rb +1 -1
- data/lib/heroku/api/mock/logs.rb +1 -1
- data/lib/heroku/api/mock/processes.rb +12 -12
- data/lib/heroku/api/mock/releases.rb +9 -9
- data/lib/heroku/api/mock/stacks.rb +5 -5
- data/lib/heroku/api/mock/user.rb +16 -0
- data/lib/heroku/api/user.rb +14 -0
- data/lib/heroku/api/vendor/okjson.rb +120 -69
- data/lib/heroku/api/version.rb +1 -1
- data/test/test_addons.rb +13 -0
- data/test/test_apps.rb +13 -0
- data/test/test_processes.rb +2 -2
- data/test/test_user.rb +13 -0
- metadata +15 -10
data/README.md
CHANGED
@@ -12,9 +12,9 @@ Usage
|
|
12
12
|
|
13
13
|
Start by creating a connection to Heroku with your credentials:
|
14
14
|
|
15
|
-
require 'heroku-
|
15
|
+
require 'heroku-api'
|
16
16
|
|
17
|
-
heroku = Heroku.new(:api_key => API_KEY)
|
17
|
+
heroku = Heroku::API.new(:api_key => API_KEY)
|
18
18
|
|
19
19
|
NOTE: You can leave out the `:api_key` if `ENV['HEROKU_API_KEY']` is set instead.
|
20
20
|
|
@@ -37,17 +37,17 @@ For additional details about any of the commands, see the [API docs](http://api-
|
|
37
37
|
|
38
38
|
### Apps
|
39
39
|
|
40
|
-
heroku.delete_app('app')
|
41
|
-
heroku.
|
42
|
-
heroku.
|
43
|
-
heroku.
|
44
|
-
|
45
|
-
heroku.
|
40
|
+
heroku.delete_app('app') # delete an app named 'app'
|
41
|
+
heroku.get_apps # get a list of your apps
|
42
|
+
heroku.get_app('app') # get info about an app named 'app'
|
43
|
+
heroku.post_app # create an app with a generated name and the default stack
|
44
|
+
heroku.post_app('name' => 'app') # create an app with a specified name
|
45
|
+
heroku.post_app_maintenance('app', '1') # toggle maintenance mode
|
46
46
|
|
47
47
|
### Collaborators
|
48
48
|
|
49
49
|
delete_collaborator('app', 'email@example.com') # remove 'email@example.com' collaborator from 'app' app
|
50
|
-
|
50
|
+
get_collaborators('app') # list collaborators for 'app' app
|
51
51
|
post_collaborator('app', 'email@example.com') # add 'email@example.com' collaborator to 'app' app
|
52
52
|
|
53
53
|
### Config Variables
|
@@ -97,15 +97,18 @@ For additional details about any of the commands, see the [API docs](http://api-
|
|
97
97
|
get_stack('app') # list available stacks
|
98
98
|
put_stack('app', 'stack') # migrate 'app' app to 'stack' stack
|
99
99
|
|
100
|
+
### User
|
101
|
+
|
102
|
+
get_user # list user info
|
100
103
|
|
101
104
|
Mock
|
102
105
|
----
|
103
106
|
|
104
107
|
For practice or testing you can also use a simulated Heroku:
|
105
108
|
|
106
|
-
require 'heroku-
|
109
|
+
require 'heroku-api'
|
107
110
|
|
108
|
-
heroku = Heroku.new(:api_key => API_KEY, :mock => true)
|
111
|
+
heroku = Heroku::API.new(:api_key => API_KEY, :mock => true)
|
109
112
|
|
110
113
|
After that commands should still behave the same, but they will only modify some local data instead of updating the state of things on Heroku.
|
111
114
|
|
data/Rakefile
CHANGED
@@ -14,7 +14,7 @@ task :cache, [:api_key] do |task, args|
|
|
14
14
|
puts('cache requires an api key, please call as `cache[api_key]`')
|
15
15
|
else
|
16
16
|
require "#{File.dirname(__FILE__)}/lib/heroku/api"
|
17
|
-
heroku = Heroku.new(:api_key => args.api_key)
|
17
|
+
heroku = Heroku::API.new(:api_key => args.api_key)
|
18
18
|
data = Heroku::API::OkJson.encode(heroku.get_addons.body)
|
19
19
|
File.open("#{File.dirname(__FILE__)}/lib/heroku/stubs/cache/get_addons.json", 'w') do |file|
|
20
20
|
file.write(data)
|
data/changelog.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
0.1.1 04/06/2012
|
2
|
+
================
|
3
|
+
|
4
|
+
readme/docs updates and fixes
|
5
|
+
add get_user method
|
6
|
+
request/use gzip responses
|
7
|
+
update vendored okjson
|
8
|
+
allow passing config data to addon install
|
9
|
+
fix STACK usage in mocks
|
10
|
+
bump excon dep
|
11
|
+
|
1
12
|
0.1.0 02/02/2012
|
2
13
|
================
|
3
14
|
|
data/heroku-api.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
|
19
|
-
s.add_runtime_dependency 'excon', '~>0.
|
19
|
+
s.add_runtime_dependency 'excon', '~>0.13.3'
|
20
20
|
|
21
21
|
s.add_development_dependency 'minitest'
|
22
22
|
s.add_development_dependency 'rake'
|
data/lib/heroku-api.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require "heroku
|
1
|
+
require(File.join(File.dirname(__FILE__), "heroku", "api"))
|
data/lib/heroku/api.rb
CHANGED
@@ -2,6 +2,13 @@ require "base64"
|
|
2
2
|
require "cgi"
|
3
3
|
require "excon"
|
4
4
|
require "securerandom"
|
5
|
+
require "stringio"
|
6
|
+
require "zlib"
|
7
|
+
|
8
|
+
__LIB_DIR__ = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
9
|
+
unless $LOAD_PATH.include?(__LIB_DIR__)
|
10
|
+
$LOAD_PATH.unshift(__LIB_DIR__)
|
11
|
+
end
|
5
12
|
|
6
13
|
require "heroku/api/vendor/okjson"
|
7
14
|
|
@@ -19,6 +26,7 @@ require "heroku/api/logs"
|
|
19
26
|
require "heroku/api/processes"
|
20
27
|
require "heroku/api/releases"
|
21
28
|
require "heroku/api/stacks"
|
29
|
+
require "heroku/api/user"
|
22
30
|
|
23
31
|
srand
|
24
32
|
|
@@ -35,6 +43,8 @@ module Heroku
|
|
35
43
|
}.merge(options)
|
36
44
|
options[:headers] = {
|
37
45
|
'Accept' => 'application/json',
|
46
|
+
'Accept-Encoding' => 'gzip',
|
47
|
+
#'Accept-Language' => 'en-US, en;q=0.8',
|
38
48
|
'Authorization' => "Basic #{Base64.encode64(user_pass).gsub("\n", '')}",
|
39
49
|
'User-Agent' => "heroku-rb/#{Heroku::API::VERSION}",
|
40
50
|
'X-Heroku-API-Version' => '3',
|
@@ -58,6 +68,7 @@ module Heroku
|
|
58
68
|
end
|
59
69
|
|
60
70
|
if response.body && !response.body.empty?
|
71
|
+
response.body = Zlib::GzipReader.new(StringIO.new(response.body)).read
|
61
72
|
begin
|
62
73
|
response.body = Heroku::API::OkJson.decode(response.body)
|
63
74
|
rescue
|
@@ -81,5 +92,8 @@ module Heroku
|
|
81
92
|
app_params
|
82
93
|
end
|
83
94
|
|
95
|
+
def addon_params(params)
|
96
|
+
{:config => params}
|
97
|
+
end
|
84
98
|
end
|
85
99
|
end
|
data/lib/heroku/api/addons.rb
CHANGED
@@ -26,22 +26,23 @@ module Heroku
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# POST /apps/:app/addons/:addon
|
29
|
-
def post_addon(app, addon)
|
29
|
+
def post_addon(app, addon, config = {})
|
30
30
|
request(
|
31
31
|
:expects => 200,
|
32
32
|
:method => :post,
|
33
|
-
:path => "/apps/#{app}/addons/#{addon}"
|
33
|
+
:path => "/apps/#{app}/addons/#{addon}",
|
34
|
+
:query => addon_params(config)
|
34
35
|
)
|
35
36
|
end
|
36
37
|
|
37
38
|
# PUT /apps/:app/addons/:addon
|
38
|
-
def put_addon(app, addon)
|
39
|
+
def put_addon(app, addon, config = {})
|
39
40
|
request(
|
40
41
|
:expects => 200,
|
41
42
|
:method => :put,
|
42
|
-
:path => "/apps/#{app}/addons/#{addon}"
|
43
|
+
:path => "/apps/#{app}/addons/#{addon}",
|
44
|
+
:query => addon_params(config)
|
43
45
|
)
|
44
46
|
end
|
45
|
-
|
46
47
|
end
|
47
48
|
end
|
data/lib/heroku/api/apps.rb
CHANGED
data/lib/heroku/api/mock.rb
CHANGED
@@ -8,6 +8,7 @@ require 'heroku/api/mock/logs'
|
|
8
8
|
require 'heroku/api/mock/processes'
|
9
9
|
require 'heroku/api/mock/releases'
|
10
10
|
require 'heroku/api/mock/stacks'
|
11
|
+
require 'heroku/api/mock/user'
|
11
12
|
|
12
13
|
module Heroku
|
13
14
|
class API
|
@@ -26,7 +27,8 @@ module Heroku
|
|
26
27
|
:keys => [],
|
27
28
|
:maintenance_mode => [],
|
28
29
|
:ps => {},
|
29
|
-
:releases => {}
|
30
|
+
:releases => {},
|
31
|
+
:user => {}
|
30
32
|
}
|
31
33
|
end
|
32
34
|
|
@@ -120,6 +122,18 @@ module Heroku
|
|
120
122
|
end
|
121
123
|
end
|
122
124
|
|
125
|
+
def self.gzip(string)
|
126
|
+
io = StringIO.new
|
127
|
+
gzip = Zlib::GzipWriter.new(io)
|
128
|
+
gzip.write(string)
|
129
|
+
gzip.close
|
130
|
+
io.string
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.json_gzip(string)
|
134
|
+
gzip(Heroku::API::OkJson.encode(string))
|
135
|
+
end
|
136
|
+
|
123
137
|
def self.parse_stub_params(params)
|
124
138
|
api_key = Base64.decode64(params[:headers]['Authorization']).split(':').last
|
125
139
|
|
@@ -14,24 +14,24 @@ module Heroku
|
|
14
14
|
# addon is currently installed
|
15
15
|
remove_mock_app_addon(mock_data, app, addon)
|
16
16
|
{
|
17
|
-
:body => Heroku::API::
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
:body => Heroku::API::Mock::json_gzip({
|
18
|
+
"message" => nil,
|
19
|
+
"price" => get_mock_addon_price(mock_data, addon),
|
20
|
+
"status" => 'Uninstalled'
|
21
21
|
}),
|
22
22
|
:status => 200
|
23
23
|
}
|
24
24
|
else
|
25
25
|
# addon is not currently installed
|
26
26
|
{
|
27
|
-
:body => Heroku::API::
|
27
|
+
:body => Heroku::API::Mock.json_gzip({'error' => "The add-on #{addon} is not installed for this app. Did you mean:\n\t#{addon_names.join("\n\t")}"}),
|
28
28
|
:status => 422
|
29
29
|
}
|
30
30
|
end
|
31
31
|
else
|
32
32
|
# addon does not exist
|
33
33
|
{
|
34
|
-
:body => Heroku::API::
|
34
|
+
:body => Heroku::API::Mock.json_gzip({'error' => "Could not find add-on #{addon}. Did you mean:\n\t#{addon_names.join("\n\t")}"}),
|
35
35
|
:status => 422
|
36
36
|
}
|
37
37
|
end
|
@@ -42,7 +42,7 @@ module Heroku
|
|
42
42
|
Excon.stub(:expects => 200, :method => :get, :path => "/addons") do |params|
|
43
43
|
request_params, mock_data = parse_stub_params(params)
|
44
44
|
{
|
45
|
-
:body => File.read("#{File.dirname(__FILE__)}/cache/get_addons.json"),
|
45
|
+
:body => Heroku::API::Mock.gzip(File.read("#{File.dirname(__FILE__)}/cache/get_addons.json")),
|
46
46
|
:status => 200
|
47
47
|
}
|
48
48
|
end
|
@@ -53,7 +53,7 @@ module Heroku
|
|
53
53
|
app, _ = request_params[:captures][:path]
|
54
54
|
with_mock_app(mock_data, app) do
|
55
55
|
{
|
56
|
-
:body => Heroku::API::
|
56
|
+
:body => Heroku::API::Mock.json_gzip(mock_data[:addons][app].map {|addon| addon['configured'] = true; addon}),
|
57
57
|
:status => 200
|
58
58
|
}
|
59
59
|
end
|
@@ -72,31 +72,31 @@ module Heroku
|
|
72
72
|
# addon is not currently installed
|
73
73
|
add_mock_app_addon(mock_data, app, addon)
|
74
74
|
{
|
75
|
-
:body => Heroku::API::
|
76
|
-
|
77
|
-
|
78
|
-
|
75
|
+
:body => Heroku::API::Mock.json_gzip({
|
76
|
+
"message" => nil,
|
77
|
+
"price" => get_mock_addon_price(mock_data, addon),
|
78
|
+
"status" => 'Installed'
|
79
79
|
}),
|
80
80
|
:status => 200
|
81
81
|
}
|
82
82
|
else
|
83
83
|
# addon is currently installed
|
84
84
|
{
|
85
|
-
:body => Heroku::API::
|
85
|
+
:body => Heroku::API::Mock.json_gzip({'error' => "Add-on already installed."}),
|
86
86
|
:status => 422
|
87
87
|
}
|
88
88
|
end
|
89
89
|
else
|
90
90
|
# addon of same type exists
|
91
91
|
{
|
92
|
-
:body => Heroku::API::
|
92
|
+
:body => Heroku::API::Mock.json_gzip({'error' => "#{app_addon_type_data['name']} add-on already added.\nTo upgrade, use addons:upgrade instead.\n"}),
|
93
93
|
:status => 422
|
94
94
|
}
|
95
95
|
end
|
96
96
|
else
|
97
97
|
# addon does not exist
|
98
98
|
{
|
99
|
-
:body => Heroku::API::
|
99
|
+
:body => Heroku::API::Mock.json_gzip({'error' => "Add-on not found."}),
|
100
100
|
:status => 422
|
101
101
|
}
|
102
102
|
end
|
@@ -117,31 +117,31 @@ module Heroku
|
|
117
117
|
mock_data[:addons][app].delete(app_addon_data)
|
118
118
|
add_mock_app_addon(mock_data, app, addon)
|
119
119
|
{
|
120
|
-
:body => Heroku::API::
|
121
|
-
|
122
|
-
|
123
|
-
|
120
|
+
:body => Heroku::API::Mock.json_gzip({
|
121
|
+
"message" => nil,
|
122
|
+
"price" => get_mock_addon_price(mock_data, addon),
|
123
|
+
"status" => 'Updated'
|
124
124
|
}),
|
125
125
|
:status => 200
|
126
126
|
}
|
127
127
|
else
|
128
128
|
# addon is currently installed
|
129
129
|
{
|
130
|
-
:body => Heroku::API::
|
130
|
+
:body => Heroku::API::Mock.json_gzip({'error' => "Add-on already installed."}),
|
131
131
|
:status => 422
|
132
132
|
}
|
133
133
|
end
|
134
134
|
else
|
135
135
|
# addon of same type not installed
|
136
136
|
{
|
137
|
-
:body => Heroku::API::
|
137
|
+
:body => Heroku::API::Mock.json_gzip({'error' => "Can't upgrade, no #{addon.split(':').join(' ')} add-on has been added.\nTo add, use addons:add instead.\n"}),
|
138
138
|
:status => 422
|
139
139
|
}
|
140
140
|
end
|
141
141
|
else
|
142
142
|
# addon does not exist
|
143
143
|
{
|
144
|
-
:body => Heroku::API::
|
144
|
+
:body => Heroku::API::Mock.json_gzip({'error' => "Add-on not found."}),
|
145
145
|
:status => 422
|
146
146
|
}
|
147
147
|
end
|
data/lib/heroku/api/mock/apps.rb
CHANGED
@@ -15,7 +15,7 @@ module Heroku
|
|
15
15
|
mock_data[:ps].delete(app)
|
16
16
|
mock_data[:releases].delete(app)
|
17
17
|
{
|
18
|
-
:body => Heroku::API::
|
18
|
+
:body => Heroku::API::Mock.json_gzip({}),
|
19
19
|
:status => 200
|
20
20
|
}
|
21
21
|
end
|
@@ -25,7 +25,7 @@ module Heroku
|
|
25
25
|
Excon.stub(:expects => 200, :method => :get, :path => '/apps') do |params|
|
26
26
|
request_params, mock_data = parse_stub_params(params)
|
27
27
|
{
|
28
|
-
:body => Heroku::API::
|
28
|
+
:body => Heroku::API::Mock.json_gzip(mock_data[:apps]),
|
29
29
|
:status => 200
|
30
30
|
}
|
31
31
|
end
|
@@ -36,7 +36,7 @@ module Heroku
|
|
36
36
|
app, _ = request_params[:captures][:path]
|
37
37
|
with_mock_app(mock_data, app) do |app_data|
|
38
38
|
{
|
39
|
-
:body => Heroku::API::
|
39
|
+
:body => Heroku::API::Mock.json_gzip(app_data),
|
40
40
|
:status => 200
|
41
41
|
}
|
42
42
|
end
|
@@ -49,7 +49,7 @@ module Heroku
|
|
49
49
|
|
50
50
|
if get_mock_app(mock_data, app)
|
51
51
|
{
|
52
|
-
:body => Heroku::API::
|
52
|
+
:body => Heroku::API::Mock.json_gzip('error' => 'Name is already taken'),
|
53
53
|
:status => 422
|
54
54
|
}
|
55
55
|
else
|
@@ -61,7 +61,7 @@ module Heroku
|
|
61
61
|
'name' => app,
|
62
62
|
'owner_email' => 'email@example.com',
|
63
63
|
'slug_size' => nil,
|
64
|
-
'stack' =>
|
64
|
+
'stack' => stack,
|
65
65
|
'requested_stack' => nil,
|
66
66
|
'git_url' => "git@heroku.com:#{app}.git",
|
67
67
|
'repo_migrate_status' => 'complete',
|
@@ -112,7 +112,7 @@ module Heroku
|
|
112
112
|
end
|
113
113
|
|
114
114
|
{
|
115
|
-
:body => Heroku::API::
|
115
|
+
:body => Heroku::API::Mock.json_gzip(app_data),
|
116
116
|
:status => 202
|
117
117
|
}
|
118
118
|
end
|
@@ -154,12 +154,12 @@ module Heroku
|
|
154
154
|
end
|
155
155
|
if email && !collaborator
|
156
156
|
{
|
157
|
-
:body => Heroku::API::
|
157
|
+
:body => Heroku::API::Mock.json_gzip('error' => 'Only existing collaborators can receive ownership for an app'),
|
158
158
|
:status => 422
|
159
159
|
}
|
160
160
|
else
|
161
161
|
{
|
162
|
-
:body => Heroku::API::
|
162
|
+
:body => Heroku::API::Mock.json_gzip('name' => app_data['name']),
|
163
163
|
:status => 200
|
164
164
|
}
|
165
165
|
end
|
@@ -173,7 +173,7 @@ module Heroku
|
|
173
173
|
|
174
174
|
with_mock_app(mock_data, app) do |app_data|
|
175
175
|
{
|
176
|
-
:body => Heroku::API::
|
176
|
+
:body => Heroku::API::Mock.json_gzip({}),
|
177
177
|
:status => 201
|
178
178
|
}
|
179
179
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"created_at":"2011/10/24 12:23:54 -0700","last_login":"2012/03/01 18:09:06 -0800","id":"123456@users.heroku.com","email":"user@example.com"}
|
@@ -10,11 +10,11 @@ module Heroku
|
|
10
10
|
if collaborator_data = get_mock_collaborator(mock_data, app, email)
|
11
11
|
mock_data[:collaborators][app].delete(collaborator_data)
|
12
12
|
{
|
13
|
-
:body => "#{email} has been removed as collaborator on #{app}",
|
13
|
+
:body => Heroku::API::Mock.gzip("#{email} has been removed as collaborator on #{app}"),
|
14
14
|
:status => 200
|
15
15
|
}
|
16
16
|
else
|
17
|
-
{ :body => 'User not found.', :status => 404 }
|
17
|
+
{ :body => Heroku::API::Mock.gzip('User not found.'), :status => 404 }
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -25,7 +25,7 @@ module Heroku
|
|
25
25
|
app, _ = request_params[:captures][:path]
|
26
26
|
with_mock_app(mock_data, app) do
|
27
27
|
{
|
28
|
-
:body => Heroku::API::
|
28
|
+
:body => Heroku::API::Mock.json_gzip(mock_data[:collaborators][app]),
|
29
29
|
:status => 200
|
30
30
|
}
|
31
31
|
end
|
@@ -39,7 +39,7 @@ module Heroku
|
|
39
39
|
with_mock_app(mock_data, app) do
|
40
40
|
mock_data[:collaborators][app] |= [{'access' => 'edit', 'email' => email}]
|
41
41
|
{
|
42
|
-
:body => "#{email} added as a collaborator on #{app}.",
|
42
|
+
:body => Heroku::API::Mock.gzip("#{email} added as a collaborator on #{app}."),
|
43
43
|
:status => 200
|
44
44
|
}
|
45
45
|
# Existing user response
|