azuki-api 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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