azuki-api 0.0.2

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.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.travis.yml +16 -0
  4. data/Gemfile +4 -0
  5. data/README.md +128 -0
  6. data/Rakefile +41 -0
  7. data/azuki-api.gemspec +23 -0
  8. data/changelog.txt +204 -0
  9. data/lib/azuki-api.rb +1 -0
  10. data/lib/azuki/api.rb +146 -0
  11. data/lib/azuki/api/addons.rb +48 -0
  12. data/lib/azuki/api/apps.rb +71 -0
  13. data/lib/azuki/api/attachments.rb +14 -0
  14. data/lib/azuki/api/collaborators.rb +33 -0
  15. data/lib/azuki/api/config_vars.rb +33 -0
  16. data/lib/azuki/api/domains.rb +42 -0
  17. data/lib/azuki/api/errors.rb +26 -0
  18. data/lib/azuki/api/features.rb +45 -0
  19. data/lib/azuki/api/keys.rb +42 -0
  20. data/lib/azuki/api/login.rb +14 -0
  21. data/lib/azuki/api/logs.rb +18 -0
  22. data/lib/azuki/api/mock.rb +179 -0
  23. data/lib/azuki/api/mock/addons.rb +153 -0
  24. data/lib/azuki/api/mock/apps.rb +205 -0
  25. data/lib/azuki/api/mock/attachments.rb +19 -0
  26. data/lib/azuki/api/mock/cache/get_addons.json +1 -0
  27. data/lib/azuki/api/mock/cache/get_features.json +1 -0
  28. data/lib/azuki/api/mock/cache/get_user.json +1 -0
  29. data/lib/azuki/api/mock/collaborators.rb +55 -0
  30. data/lib/azuki/api/mock/config_vars.rb +49 -0
  31. data/lib/azuki/api/mock/domains.rb +80 -0
  32. data/lib/azuki/api/mock/features.rb +120 -0
  33. data/lib/azuki/api/mock/keys.rb +46 -0
  34. data/lib/azuki/api/mock/login.rb +22 -0
  35. data/lib/azuki/api/mock/logs.rb +20 -0
  36. data/lib/azuki/api/mock/processes.rb +198 -0
  37. data/lib/azuki/api/mock/releases.rb +69 -0
  38. data/lib/azuki/api/mock/stacks.rb +83 -0
  39. data/lib/azuki/api/mock/user.rb +16 -0
  40. data/lib/azuki/api/processes.rb +77 -0
  41. data/lib/azuki/api/releases.rb +33 -0
  42. data/lib/azuki/api/ssl_endpoints.rb +62 -0
  43. data/lib/azuki/api/stacks.rb +22 -0
  44. data/lib/azuki/api/user.rb +14 -0
  45. data/lib/azuki/api/vendor/okjson.rb +600 -0
  46. data/lib/azuki/api/version.rb +5 -0
  47. data/test/data/site.crt +19 -0
  48. data/test/data/site.key +27 -0
  49. data/test/test_addons.rb +193 -0
  50. data/test/test_apps.rb +147 -0
  51. data/test/test_attachments.rb +23 -0
  52. data/test/test_collaborators.rb +73 -0
  53. data/test/test_config_vars.rb +54 -0
  54. data/test/test_domains.rb +65 -0
  55. data/test/test_error_conditions.rb +11 -0
  56. data/test/test_features.rb +87 -0
  57. data/test/test_helper.rb +48 -0
  58. data/test/test_keys.rb +39 -0
  59. data/test/test_login.rb +20 -0
  60. data/test/test_logs.rb +29 -0
  61. data/test/test_processes.rb +245 -0
  62. data/test/test_releases.rb +73 -0
  63. data/test/test_ssl_endpoints.rb +132 -0
  64. data/test/test_stacks.rb +49 -0
  65. data/test/test_user.rb +13 -0
  66. metadata +168 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: afe6065c77aea82ac2829a163db1aa4b4d41ab64
4
+ data.tar.gz: a97499242dae8deb99b16754546300668a82380e
5
+ SHA512:
6
+ metadata.gz: f5a0b3f09c2b808c5344f9e1e67ccef35c3e78685ab05774285e44765d6fbddf4812c88b6920dcea0012e2ac243fd4efddd7e048ca65b4ae1a5cbf00f9a17b43
7
+ data.tar.gz: 1dae8a18e0af5d66c5440bab57a12e222376c122feeda30f44b12a4d16ee13e347bab9bec03a8a09118b4dff9f9b16944ff7d63bb8623d0e1f99c1094dac5589
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
@@ -0,0 +1,16 @@
1
+ language: ruby
2
+
3
+ notifications:
4
+ email: false
5
+ webhooks:
6
+ on_success: always
7
+ on_failure: always
8
+ urls:
9
+ - http://dx-helper.azukiapp.com/travis
10
+
11
+ rvm:
12
+ - 1.8.7
13
+ - 1.9.2
14
+ - 1.9.3
15
+
16
+ script: bundle exec rake
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in azuki-rb.gemspec
4
+ gemspec
@@ -0,0 +1,128 @@
1
+ Azuki Ruby Client
2
+ ==================
3
+
4
+ The Azuki Ruby Client is used to interact with the Azuki API from Ruby.
5
+
6
+ For more about the Azuki API see <http://api-docs.azukiapp.com>.
7
+
8
+ [![Build Status](https://travis-ci.org/azukiapp/azuki-api-ruby.png)](https://travis-ci.org/azukiapp/azuki-api-ruby)
9
+
10
+ Usage
11
+ -----
12
+
13
+ Start by creating a connection to Azuki with your credentials:
14
+
15
+ require 'azuki-api'
16
+
17
+ azuki = Azuki::API.new(:api_key => API_KEY) # use API Key
18
+ azuki = Azuki::API.new(:username => USERNAME, :password => PASSWORD) # use username and password
19
+ azuki = Azuki::API.new(:headers => {'User-Agent' => 'custom'}) # use custom header
20
+
21
+ NOTE: You can leave out the `:api_key` if `ENV['AZUKI_API_KEY']` is set instead.
22
+
23
+ Now you can make requests to the api.
24
+
25
+ Requests
26
+ --------
27
+
28
+ What follows is an overview of commands you can run for the client.
29
+
30
+ For additional details about any of the commands, see the [API docs](http://api-docs.azukiapp.com).
31
+
32
+ ### Add-ons
33
+
34
+ azuki.delete_addon(APP, ADD_ON) # remove the ADD_ON add-on from the app named APP
35
+ azuki.post_addon(APP, ADD_ON) # add ADD_ON add-on to an the app named APP
36
+ azuki.put_addon(APP, ADD_ON) # update the ADD_ON add-on on the app named APP
37
+ azuki.get_addons # see a listing of all available add-ons
38
+ azuki.get_addons(APP) # see listing of installed add-ons for the app named APP
39
+
40
+ ### Apps
41
+
42
+ azuki.delete_app(APP) # delete the app named APP
43
+ azuki.get_apps # get a list of your apps
44
+ azuki.get_app(APP) # get info about the app named APP
45
+ azuki.post_app # create an app with a generated name and the default stack
46
+ azuki.post_app_maintenance(APP, '1') # toggle maintenance mode for the app named APP
47
+ azuki.post_app('name' => 'app') # create an app with a specified name, APP
48
+ azuki.put_app('name' => 'myapp') # update an app to have a different name
49
+
50
+ ### Collaborators
51
+
52
+ azuki.delete_collaborator(APP, 'email@example.com') # remove 'email@example.com' collaborator from APP app
53
+ azuki.get_collaborators(APP) # list collaborators for APP app
54
+ azuki.post_collaborator(APP, 'email@example.com') # add 'email@example.com' collaborator to APP app
55
+
56
+ ### Config Variables
57
+
58
+ azuki.delete_config_var(APP, KEY) # remove KEY key from APP app
59
+ azuki.get_config_vars(APP) # get list of config vars for APP app
60
+ azuki.put_config_vars(APP, KEY => 'value') # set KEY key to 'value' for APP app
61
+
62
+ ### Domains
63
+
64
+ azuki.delete_domain(APP, 'example.com') # remove the 'example.com' domain from the APP app
65
+ azuki.get_domains(APP) # list configured domains for the APP app
66
+ azuki.post_domain(APP, 'example.com') # add 'example.com' domain to the APP app
67
+
68
+ ### Keys
69
+
70
+ azuki.delete_key('user@hostname.local') # remove the 'user@hostname.local' key
71
+ azuki.delete_keys # remove all keys
72
+ azuki.get_keys # list configured keys
73
+ azuki.post_key('key data') # add key defined by 'key data'
74
+
75
+ ### Logs
76
+
77
+ azuki.get_logs(APP) # return logs information for APP app
78
+
79
+ ### Processes
80
+
81
+ azuki.get_ps(APP) # list current processes for APP app
82
+ azuki.post_ps(APP, 'command') # run 'command' command in context of APP app
83
+ azuki.post_ps_restart(APP) # restart all processes for APP app
84
+ azuki.post_ps_scale(APP, TYPE, QTY) # scale TYPE type processes to QTY for APP app
85
+ azuki.post_ps_stop(APP, 'ps' => 'web.1') # stop 'web.1' process for APP app
86
+ azuki.post_ps_stop(APP, 'type' => 'web') # stop all 'web' processes for APP app
87
+ azuki.post_ps_restart(APP, 'ps' => 'web.1') # restart 'web.1' process for APP app
88
+ azuki.put_dynos(APP, DYNOS) # set number of dynos for bamboo app APP to DYNOS
89
+ azuki.put_workers(APP, WORKERS) # set number of workers for bamboo app APP to WORKERS
90
+ azuki.post_ps_scale(APP, 'worker', WORKERS) # set number of workers for cedar app APP to WORKERS
91
+
92
+ ### Releases
93
+
94
+ azuki.get_releases(APP) # list of releases for the APP app
95
+ azuki.get_release(APP, 'v#') # get details of 'v#' release for APP app
96
+ azuki.post_release(APP, 'v#') # rollback APP app to 'v#' release
97
+
98
+ ### Stacks
99
+
100
+ azuki.get_stack(APP) # list available stacks
101
+ azuki.put_stack(APP, STACK) # migrate APP app to STACK stack
102
+
103
+ ### User
104
+
105
+ azuki.get_user # list user info
106
+
107
+ Mock
108
+ ----
109
+
110
+ For testing (or practice) you can also use a simulated Azuki account:
111
+
112
+ require 'azuki-api'
113
+
114
+ azuki = Azuki::API.new(:api_key => API_KEY, :mock => true)
115
+
116
+ Commands will now behave as normal, however, instead of interacting with your actual Azuki account you'll be interacting with a **blank** test account. Note: test accounts will have NO apps to begin with. You'll need to create one:
117
+
118
+ azuki.post_app(:name => 'my-test-app')
119
+
120
+ Tests
121
+ -----
122
+
123
+ To run tests, first set `ENV['AZUKI_API_KEY']` to your api key. Then use `bundle exec rake` to run mock tests or `MOCK=false bundle exec rake` to run integration tests.
124
+
125
+ Meta
126
+ ----
127
+
128
+ Released under the [MIT license](http://www.opensource.org/licenses/mit-license.php).
@@ -0,0 +1,41 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ task :default => :test
6
+
7
+ Rake::TestTask.new do |task|
8
+ task.name = :test
9
+ task.test_files = FileList['test/test*.rb']
10
+ end
11
+
12
+ task :cache, [:api_key] do |task, args|
13
+ unless args.api_key
14
+ puts('cache requires an api key, please call as `cache[api_key]`')
15
+ else
16
+ require "#{File.dirname(__FILE__)}/lib/azuki/api"
17
+ azuki = Azuki::API.new(:api_key => args.api_key)
18
+
19
+ addons = Azuki::API::OkJson.encode(azuki.get_addons.body)
20
+ File.open("#{File.dirname(__FILE__)}/lib/azuki/api/mock/cache/get_addons.json", 'w') do |file|
21
+ file.write(addons)
22
+ end
23
+
24
+ app_name = "azuki-api-#{Time.now.to_i}"
25
+ app = azuki.post_app('name' => app_name)
26
+ features = Azuki::API::OkJson.encode(azuki.get_features(app_name).body)
27
+ File.open("#{File.dirname(__FILE__)}/lib/azuki/api/mock/cache/get_features.json", 'w') do |file|
28
+ file.write(features)
29
+ end
30
+ azuki.delete_app(app_name)
31
+
32
+ user = azuki.get_user.body
33
+ user["email"] = "user@example.com"
34
+ user["id"] = "123456@users.azukiapp.com"
35
+ user = Azuki::API::OkJson.encode(user)
36
+ File.open("#{File.dirname(__FILE__)}/lib/azuki/api/mock/cache/get_user.json", 'w') do |file|
37
+ file.write(user)
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "azuki/api/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "azuki-api"
7
+ s.version = Azuki::API::VERSION
8
+ s.authors = ["Éverton Ribeiro"]
9
+ s.email = ["everton@azukiapp.com"]
10
+ s.homepage = "https://github.com/azukiapp/azuki-api-ruby"
11
+ s.summary = %q{Ruby Client for the Azuki API}
12
+ s.description = %q{Ruby Client for the Azuki API}
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_runtime_dependency 'excon', '~>0.20.0'
20
+
21
+ s.add_development_dependency 'minitest'
22
+ s.add_development_dependency 'rake'
23
+ end
@@ -0,0 +1,204 @@
1
+ 0.3.8 02/27/2012
2
+ ================
3
+
4
+ document custom headers
5
+ remove SHARED_DATABASE from mocks
6
+ clarify cedar scaling
7
+ clarify README examples
8
+ return more helpful error for blank app
9
+ add legacy tier to mocks
10
+
11
+
12
+ 0.3.7 11/19/2012
13
+ ================
14
+
15
+ bump excon to get https proxy fixes
16
+
17
+ 0.3.6 10/31/2012
18
+ ================
19
+
20
+ bump excon to latest
21
+ allow username/password params to automagically lookup api_key
22
+ readme cleanup/fixes
23
+
24
+ 0.3.5 09/11/2012
25
+ ================
26
+
27
+ add get_attachments and mocks
28
+ update enable features usage and mocks to use 200/201 based on update/create
29
+
30
+ 0.3.4 08/15/2012
31
+ ================
32
+
33
+ update excon to get SSLv3 fix
34
+
35
+ 0.3.3 08/15/2012
36
+ ================
37
+
38
+ update to more realistic self signed cert in tests
39
+ update body format for delete_ssl_endpoint
40
+ vendor latest okjson
41
+ patch okjson to work around encoding bug
42
+ bump excon and use blocking requests
43
+
44
+ 0.3.2 08/01/2012
45
+ ================
46
+
47
+ don't request v3 apis
48
+ first pass at ssl_endpoints support (no mocks yet)
49
+ bump excon dep
50
+
51
+ 0.3.1 07/20/2012
52
+ ================
53
+
54
+ fix bug in maintenance mocks not being reset after app delet
55
+
56
+ 0.3.0 07/20/2012
57
+ ================
58
+
59
+ fixes for url segment escaping of config_vars, domains and keys
60
+ add get_app_maintenance
61
+
62
+ 0.2.13 07/18/2012
63
+ =================
64
+
65
+ bump excon to rescue nonblock errors from readline
66
+
67
+ 0.2.12 07/17/2012
68
+ =================
69
+
70
+ more last minute excon fixes (proxies are hard)
71
+
72
+ 0.2.11 07/17/2012
73
+ =================
74
+
75
+ excon bump for further fixes
76
+
77
+ 0.2.10 07/16/2012
78
+ =================
79
+
80
+ excon bump for fixes
81
+
82
+ 0.2.9 07/16/2012
83
+ ================
84
+
85
+ bump excon dep to get proxy fixes
86
+
87
+ 0.2.8 07/08/2012
88
+ ================
89
+
90
+ return to OkJson usage, as json breaks with some legacy toolbelt installs
91
+
92
+ 0.2.7 07/05/2012
93
+ ================
94
+
95
+ doc fixes (fixes delete_addon and improves consistency)
96
+ post_collaborator returns 201 when users does not yet exist
97
+ use json (instead of okjson) when available
98
+ update excon dependency
99
+
100
+ 0.2.6 06/21/2012
101
+ ================
102
+
103
+ processes scale mocks now more accurately update process list
104
+
105
+ 0.2.5 06/13/2012
106
+ ================
107
+
108
+ make post_release release param optional (defaults to latest)
109
+ fix for contructing addon_params
110
+ fail gracefully on non-http-status errors
111
+
112
+ 0.2.4 05/31/2012
113
+ ================
114
+
115
+ fix overly lax GET /user stub reveealed by changes in excon 0.14.0
116
+
117
+ 0.2.3 05/31/2012
118
+ ================
119
+
120
+ fix overly lax DELETE /user/keys stub revealed by changes in excon 0.14.0
121
+
122
+ 0.2.2 05/31/2012
123
+ ================
124
+
125
+ bump excon dep for improved stubs/instrumentation
126
+
127
+ 0.2.1 05/24/2012
128
+ ================
129
+
130
+ update post_ps to properly munge ps_env params
131
+
132
+ 0.2.0 05/23/2012
133
+ ================
134
+
135
+ fix mocks for stack requests
136
+ add features (labs) functionality
137
+
138
+ 0.1.8 05/21/2012
139
+ ================
140
+
141
+ fix tests to be individually runnable
142
+ update cache function to get user data
143
+ update domain tests to match new default plugins
144
+ update collaborators mocks to be more accurate
145
+ update domain tests to use random_domain
146
+ use better transfer targets in app tests
147
+ fix timestamp generation in mocks
148
+ fix release creation in mocks
149
+ fix release rollback mocks to rollback to last when no version is given
150
+ more accurate addons mocks
151
+ more accurate process mocks for attached processes
152
+
153
+
154
+ 0.1.7 05/15/2012
155
+ ================
156
+
157
+ consolidate NotFound error handling to work more like other errors
158
+ fixes for ps:scale mock accuracy
159
+ fix default command for cedar web process mocks
160
+
161
+ 0.1.6 05/09/2012
162
+ ================
163
+
164
+ fixes for GET /apps/:app/releases/:release mocks
165
+
166
+ 0.1.5 05/09/2012
167
+ ================
168
+
169
+ add support for GET /apps/:app/releases/current
170
+
171
+ 0.1.4 05/09/2012
172
+ ================
173
+
174
+ add DELETE /domains
175
+ add POST /login
176
+
177
+ 0.1.3 05/03/2012
178
+ ================
179
+
180
+ update README examples to include put_app
181
+ correct mocks to change git/web urls during app rename
182
+ split out known azuki errors into their own error classes
183
+
184
+ 0.1.2 04/10/2012
185
+ ================
186
+
187
+ less aggressive gzip usage (checks content-encoding)
188
+ update cache
189
+
190
+ 0.1.1 04/06/2012
191
+ ================
192
+
193
+ readme/docs updates and fixes
194
+ add get_user method
195
+ request/use gzip responses
196
+ update vendored okjson
197
+ allow passing config data to addon install
198
+ fix STACK usage in mocks
199
+ bump excon dep
200
+
201
+ 0.1.0 02/02/2012
202
+ ================
203
+
204
+ Initial release
@@ -0,0 +1 @@
1
+ require(File.join(File.dirname(__FILE__), "azuki", "api"))
@@ -0,0 +1,146 @@
1
+ require "base64"
2
+ require "excon"
3
+ require "securerandom"
4
+ require "uri"
5
+ require "zlib"
6
+
7
+ __LIB_DIR__ = File.expand_path(File.join(File.dirname(__FILE__), ".."))
8
+ unless $LOAD_PATH.include?(__LIB_DIR__)
9
+ $LOAD_PATH.unshift(__LIB_DIR__)
10
+ end
11
+
12
+ require "azuki/api/vendor/okjson"
13
+
14
+ require "azuki/api/errors"
15
+ require "azuki/api/mock"
16
+ require "azuki/api/version"
17
+
18
+ require "azuki/api/addons"
19
+ require "azuki/api/apps"
20
+ require "azuki/api/attachments"
21
+ require "azuki/api/collaborators"
22
+ require "azuki/api/config_vars"
23
+ require "azuki/api/domains"
24
+ require "azuki/api/features"
25
+ require "azuki/api/keys"
26
+ require "azuki/api/login"
27
+ require "azuki/api/logs"
28
+ require "azuki/api/processes"
29
+ require "azuki/api/releases"
30
+ require "azuki/api/ssl_endpoints"
31
+ require "azuki/api/stacks"
32
+ require "azuki/api/user"
33
+
34
+ srand
35
+
36
+ module Azuki
37
+ class API
38
+
39
+ HEADERS = {
40
+ 'Accept' => 'application/json',
41
+ 'Accept-Encoding' => 'gzip',
42
+ #'Accept-Language' => 'en-US, en;q=0.8',
43
+ 'User-Agent' => "azuki-rb/#{Azuki::API::VERSION}",
44
+ 'X-Ruby-Version' => RUBY_VERSION,
45
+ 'X-Ruby-Platform' => RUBY_PLATFORM
46
+ }
47
+
48
+ OPTIONS = {
49
+ :headers => {},
50
+ :host => 'api.azukiapp.com',
51
+ :nonblock => false,
52
+ :scheme => 'https'
53
+ }
54
+
55
+ def initialize(options={})
56
+ options = OPTIONS.merge(options)
57
+
58
+ @api_key = options.delete(:api_key) || ENV['AZUKI_API_KEY']
59
+ if !@api_key && options.has_key?(:username) && options.has_key?(:password)
60
+ @connection = Excon.new("#{options[:scheme]}://#{options[:host]}", options.merge(:headers => HEADERS))
61
+ @api_key = self.post_login(options[:username], options[:password]).body["api_key"]
62
+ end
63
+
64
+ user_pass = ":#{@api_key}"
65
+ options[:headers] = HEADERS.merge({
66
+ 'Authorization' => "Basic #{Base64.encode64(user_pass).gsub("\n", '')}",
67
+ }).merge(options[:headers])
68
+
69
+ @connection = Excon.new("#{options[:scheme]}://#{options[:host]}", options)
70
+ end
71
+
72
+ def request(params, &block)
73
+ begin
74
+ response = @connection.request(params, &block)
75
+ rescue Excon::Errors::HTTPStatusError => error
76
+ klass = case error.response.status
77
+ when 401 then Azuki::API::Errors::Unauthorized
78
+ when 402 then Azuki::API::Errors::VerificationRequired
79
+ when 403 then Azuki::API::Errors::Forbidden
80
+ when 404
81
+ if error.request[:path].match /\/apps\/\/.*/
82
+ Azuki::API::Errors::NilApp
83
+ else
84
+ Azuki::API::Errors::NotFound
85
+ end
86
+ when 408 then Azuki::API::Errors::Timeout
87
+ when 422 then Azuki::API::Errors::RequestFailed
88
+ when 423 then Azuki::API::Errors::Locked
89
+ when /50./ then Azuki::API::Errors::RequestFailed
90
+ else Azuki::API::Errors::ErrorWithResponse
91
+ end
92
+
93
+ reerror = klass.new(error.message, error.response)
94
+ reerror.set_backtrace(error.backtrace)
95
+ raise(reerror)
96
+ end
97
+
98
+ if response.body && !response.body.empty?
99
+ if response.headers['Content-Encoding'] == 'gzip'
100
+ response.body = Zlib::GzipReader.new(StringIO.new(response.body)).read
101
+ end
102
+ begin
103
+ response.body = Azuki::API::OkJson.decode(response.body)
104
+ rescue
105
+ # leave non-JSON body as is
106
+ end
107
+ end
108
+
109
+ # reset (non-persistent) connection
110
+ @connection.reset
111
+
112
+ response
113
+ end
114
+
115
+ private
116
+
117
+ def app_params(params)
118
+ app_params = {}
119
+ params.each do |key, value|
120
+ app_params["app[#{key}]"] = value
121
+ end
122
+ app_params
123
+ end
124
+
125
+ def addon_params(params)
126
+ params.inject({}) do |accum, (key, value)|
127
+ accum["config[#{key}]"] = value
128
+ accum
129
+ end
130
+ end
131
+
132
+ def escape(string)
133
+ CGI.escape(string).gsub('.', '%2E')
134
+ end
135
+
136
+ def ps_options(params)
137
+ if ps_env = params.delete(:ps_env) || params.delete('ps_env')
138
+ ps_env.each do |key, value|
139
+ params["ps_env[#{key}]"] = value
140
+ end
141
+ end
142
+ params
143
+ end
144
+
145
+ end
146
+ end