af-addon-tester 0.0.2 → 0.0.3
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 +3 -1
- data/README.md +3 -3
- data/bin/af-addon-tester +95 -69
- data/config/manifest.example.json +5 -5
- data/lib/af-addon-tester.rb +0 -1
- data/lib/af-addon-tester/version.rb +1 -1
- metadata +3 -4
- data/lib/af-addon-tester/rest.rb +0 -106
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@ af-addon-tester
|
|
3
3
|
|
4
4
|
<img src="http://appfog.com/images/logo.png" />
|
5
5
|
|
6
|
-
Allows developers to test App Fog
|
6
|
+
Allows developers to test add-ons compatible with App Fog
|
7
7
|
|
8
8
|
## Setup ##
|
9
9
|
|
@@ -46,9 +46,9 @@ If cloned:
|
|
46
46
|
|
47
47
|
$ bin/af-addon-tester <path to manifest>
|
48
48
|
|
49
|
-
If Gem
|
49
|
+
If Gem:
|
50
50
|
|
51
|
-
$
|
51
|
+
$ af-addon-tester <path to manifest>
|
52
52
|
|
53
53
|
|
54
54
|
## Meta ##
|
data/bin/af-addon-tester
CHANGED
@@ -7,8 +7,12 @@ require 'rubygems'
|
|
7
7
|
require 'json'
|
8
8
|
require 'digest/sha1'
|
9
9
|
require 'af-addon-tester'
|
10
|
+
require 'restclient'
|
10
11
|
|
11
|
-
manifest_path = ARGV.
|
12
|
+
manifest_path = ARGV.last
|
13
|
+
|
14
|
+
do_asyc = ARGV.include?('-a')
|
15
|
+
username = nil
|
12
16
|
|
13
17
|
begin
|
14
18
|
manifest_file = File.open(File.expand_path(manifest_path), 'r')
|
@@ -16,11 +20,11 @@ begin
|
|
16
20
|
manifest = JSON.parse(manifest_json)
|
17
21
|
|
18
22
|
raise "Missing id" if manifest['id'].nil?
|
23
|
+
username = manifest['api']['username'] || manifest['id']
|
19
24
|
raise "Missing api section" if manifest['api'].nil?
|
20
|
-
raise "Missing api password" if manifest['api']['username'].nil?
|
21
25
|
raise "Missing api password" if manifest['api']['password'].nil?
|
22
26
|
raise "Missing apt test url" if manifest['api']['test'].nil?
|
23
|
-
raise "Manifest must have atleast one plan" if manifest['
|
27
|
+
raise "Manifest must have atleast one plan" if manifest['plans'].nil? || manifest['plans'][0].nil? || manifest['plans'][0]['id'].nil?
|
24
28
|
raise "missing api config_vars" if manifest['api']['config_vars'].nil?
|
25
29
|
raise "Missing api sso_salt" if manifest['api']['sso_salt'].nil?
|
26
30
|
|
@@ -34,18 +38,26 @@ config_prefix = manifest['id'].gsub('-','_').upcase + '_'
|
|
34
38
|
bad_user = 'bad_user'
|
35
39
|
bad_password = 'bad_pass'
|
36
40
|
|
37
|
-
addon =
|
41
|
+
addon = RestClient::Resource.new manifest['api']['test'], {:user => username, :password => manifest['api']['password']}
|
42
|
+
headers = { :accept => "application/json", :content_type => "application/json", "User-Agent" => "af-addon-tester/#{VERSION}" }
|
43
|
+
|
38
44
|
resp = nil
|
45
|
+
code = nil
|
39
46
|
|
40
47
|
validate "Provisioning" do
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
48
|
+
payload = { 'customer_id' => manifest['id'], 'plan' => manifest['plans'][0]['id'], 'callback_url' => callback_url, 'options' => '{}' }
|
49
|
+
begin
|
50
|
+
resp = addon['/provider/resources'].post JSON.generate(payload), headers
|
51
|
+
failed("response code: #{resp.code}") if resp.code != 200
|
52
|
+
code = 200
|
53
|
+
rescue RestClient::ExceptionWithResponse => rest_err
|
54
|
+
code = rest_err.http_code
|
55
|
+
failed("response code: #{rest_err.message}")
|
56
|
+
end
|
45
57
|
passed
|
46
58
|
end
|
47
59
|
|
48
|
-
if
|
60
|
+
if code == 200
|
49
61
|
provision_info = nil
|
50
62
|
validate "Valid JSON response" do
|
51
63
|
begin
|
@@ -90,81 +102,91 @@ end
|
|
90
102
|
resource_id = provision_info['id']
|
91
103
|
unless resource_id.nil?
|
92
104
|
validate "Update resource" do
|
93
|
-
|
94
|
-
payload = { 'plan' => 'paid', 'callback_url' => callback_url, 'options' => '{}' }
|
95
|
-
resp = addon.put(manifest['api']['test'] + "/#{resource_id}", params, JSON.generate(payload))
|
96
|
-
failed("response code: #{resp.code}") if resp.code != "200"
|
97
|
-
passed
|
98
|
-
end
|
99
|
-
|
100
|
-
READLEN = 1024 * 10
|
101
|
-
reader, writer = IO.pipe
|
102
|
-
out = nil
|
103
|
-
validate "Callback" do
|
104
|
-
child = fork do
|
105
|
-
reader.close
|
106
|
-
server = TCPServer.open(9990)
|
107
|
-
client = server.accept
|
108
|
-
writer.write(client.readpartial(READLEN))
|
109
|
-
client.write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n")
|
110
|
-
client.close
|
111
|
-
writer.close
|
112
|
-
end
|
113
|
-
sleep(1)
|
114
|
-
out = reader.readpartial(READLEN)
|
115
|
-
passed
|
116
|
-
end
|
117
|
-
|
118
|
-
callback_info = nil
|
119
|
-
isValidCallback = false
|
120
|
-
validate "Valid callback response" do
|
121
|
-
_, json = out.split("\r\n\r\n")
|
105
|
+
payload = { 'customer_id' => manifest['id'], 'plan' => 'sandbox' }
|
122
106
|
begin
|
123
|
-
|
124
|
-
|
125
|
-
|
107
|
+
resp = addon["/provider/resources/#{resource_id}"].put JSON.generate(payload), headers
|
108
|
+
failed("response code: #{resp.code}") if resp.code != 200
|
109
|
+
rescue RestClient::ExceptionWithResponse => rest_err
|
110
|
+
failed("response code: #{rest_err.message}")
|
126
111
|
end
|
127
|
-
isValidCallback = true
|
128
112
|
passed
|
129
113
|
end
|
130
114
|
|
131
|
-
if
|
132
|
-
|
133
|
-
|
134
|
-
|
115
|
+
if do_asyc
|
116
|
+
READLEN = 1024 * 10
|
117
|
+
reader, writer = IO.pipe
|
118
|
+
out = nil
|
119
|
+
validate "Callback" do
|
120
|
+
child = fork do
|
121
|
+
reader.close
|
122
|
+
server = TCPServer.open(9990)
|
123
|
+
client = server.accept
|
124
|
+
writer.write(client.readpartial(READLEN))
|
125
|
+
client.write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n")
|
126
|
+
client.close
|
127
|
+
writer.close
|
135
128
|
end
|
129
|
+
sleep(1)
|
130
|
+
out = reader.readpartial(READLEN)
|
131
|
+
passed
|
136
132
|
end
|
137
133
|
|
138
|
-
|
139
|
-
|
140
|
-
|
134
|
+
callback_info = nil
|
135
|
+
isValidCallback = false
|
136
|
+
validate "Valid callback response" do
|
137
|
+
_, json = out.split("\r\n\r\n")
|
138
|
+
begin
|
139
|
+
callback_info = JSON.parse(json)
|
140
|
+
rescue Exception => e
|
141
|
+
failed e.message
|
141
142
|
end
|
143
|
+
isValidCallback = true
|
144
|
+
passed
|
142
145
|
end
|
143
146
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
+
if isValidCallback
|
148
|
+
validate "All callback config keys are in manifest" do
|
149
|
+
callback_info['config'].each do |key, value|
|
150
|
+
unless manifest['api']['config_vars'].include? key; failed "#{key} not found in config"; end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
validate "All callback manifest config keys are in response" do
|
155
|
+
manifest['api']['config_vars'].each do |key, value|
|
156
|
+
unless callback_info['config'].include? key; failed "#{key} not found in manifest"; end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
validate "All callback config keys are prefixed with addon name" do
|
161
|
+
callback_info['config'].each do |key, value|
|
162
|
+
unless key.start_with? config_prefix; failed "#{key} does not begin with #{config_prefix}"; end
|
163
|
+
end
|
164
|
+
passed
|
147
165
|
end
|
148
|
-
passed
|
149
166
|
end
|
150
167
|
end
|
151
|
-
|
168
|
+
|
152
169
|
validate "SSO link" do
|
153
170
|
timestamp = Time.now.to_i
|
154
171
|
authstring = resource_id.to_s + ':' + manifest['api']['sso_salt'] + ':' + timestamp.to_s
|
155
172
|
token = Digest::SHA1.hexdigest(authstring)
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
failed("response code: #{resp.code}") if resp.code != "200"
|
173
|
+
addon_sso = RestClient::Resource.new manifest['api']['test']
|
174
|
+
sso_headers = { :accept => "text/html", :content_type => "text/html", "User-Agent" => "af-addon-tester/#{VERSION}" }
|
175
|
+
begin
|
176
|
+
resp = addon_sso["/provider/resources/#{resource_id}?token=#{token}×tamp=#{timestamp}"].get sso_headers
|
177
|
+
failed("response code: #{resp.code}") if resp.code != 200
|
178
|
+
rescue RestClient::ExceptionWithResponse => rest_err
|
179
|
+
failed("response code: #{rest_err.message}")
|
180
|
+
end
|
165
181
|
passed
|
166
182
|
end
|
167
183
|
|
184
|
+
# validate "Deprovision" do
|
185
|
+
# resp = addon["/provider/resources/#{resource_id}"].delete
|
186
|
+
# failed("response code: #{resp.code}") if resp.code != 200
|
187
|
+
# passed
|
188
|
+
#end
|
189
|
+
|
168
190
|
end
|
169
191
|
end
|
170
192
|
|
@@ -173,12 +195,16 @@ else
|
|
173
195
|
end
|
174
196
|
|
175
197
|
validate "Bad credentials test" do
|
176
|
-
|
177
|
-
payload = { 'customer_id' => manifest['id'], 'plan' => manifest['api']['plans'][0]['id'], 'callback_url' => callback_url, 'options' => '{}' }
|
198
|
+
payload = { 'customer_id' => manifest['id'], 'plan' => manifest['plans'][0]['id'], 'callback_url' => callback_url, 'options' => '{}' }
|
178
199
|
|
179
|
-
addon_bad_auth =
|
180
|
-
resp = addon.post(manifest['api']['test'], params, JSON.generate(payload))
|
200
|
+
addon_bad_auth = RestClient::Resource.new manifest['api']['test'], { :username => bad_user, :password => bad_password }
|
181
201
|
|
182
|
-
|
183
|
-
|
202
|
+
code = nil
|
203
|
+
begin
|
204
|
+
resp = addon_bad_auth["/provider/resources"].post JSON.generate(payload), headers
|
205
|
+
code = resp.code
|
206
|
+
rescue RestClient::ExceptionWithResponse => rest_err
|
207
|
+
code = rest_err.http_code
|
208
|
+
end
|
209
|
+
passed unless code == 200
|
184
210
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
{
|
2
2
|
"id":"myaddon",
|
3
|
+
"plans":[
|
4
|
+
{"id":"free"}
|
5
|
+
],
|
3
6
|
"api":{
|
4
|
-
"plans":[
|
5
|
-
{"id":"free"}
|
6
|
-
],
|
7
7
|
"config_vars": {
|
8
8
|
"MYADDON_URL":"http://some.url.com",
|
9
9
|
"MYADDON_VAR1":"cats",
|
10
10
|
"MYADDON_VAR2":"dogs"
|
11
11
|
},
|
12
|
-
"test":"http://localhost:4567
|
12
|
+
"test":"http://localhost:4567",
|
13
13
|
"username":"myaddon",
|
14
|
-
"password":"
|
14
|
+
"password":"NVUQ1OqNtuc74HiE",
|
15
15
|
"sso_salt":"8ouy3ayLEyOA7HLAKO2Yo"
|
16
16
|
}
|
17
17
|
}
|
data/lib/af-addon-tester.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Tim Santeford
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-01-
|
17
|
+
date: 2012-01-15 00:00:00 -08:00
|
18
18
|
default_executable: af-addon-tester
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -48,7 +48,6 @@ files:
|
|
48
48
|
- config/manifest.example.json
|
49
49
|
- lib/af-addon-tester.rb
|
50
50
|
- lib/af-addon-tester/colorize.rb
|
51
|
-
- lib/af-addon-tester/rest.rb
|
52
51
|
- lib/af-addon-tester/test.rb
|
53
52
|
- lib/af-addon-tester/version.rb
|
54
53
|
has_rdoc: true
|
data/lib/af-addon-tester/rest.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
require 'net/https'
|
3
|
-
require 'uri'
|
4
|
-
require 'cgi'
|
5
|
-
|
6
|
-
class Rest
|
7
|
-
|
8
|
-
$user = nil
|
9
|
-
$password = nil
|
10
|
-
$http = nil
|
11
|
-
$cookies = {}
|
12
|
-
$last_resp = nil
|
13
|
-
$last_params = nil
|
14
|
-
|
15
|
-
$useragent = ''
|
16
|
-
|
17
|
-
def initialize(url, user = nil, password = nil)
|
18
|
-
$user = user
|
19
|
-
$password = password
|
20
|
-
|
21
|
-
uri = URI(url)
|
22
|
-
$http = Net::HTTP.new(uri.host, uri.port)
|
23
|
-
|
24
|
-
if uri.scheme == 'https'
|
25
|
-
$http.use_ssl = true
|
26
|
-
$http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
27
|
-
else
|
28
|
-
$http.use_ssl = false
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def get(url, params = nil, additional_header = nil)
|
33
|
-
header = { 'Cookie' => cookie_to_s, 'User-Agent' => $useragent }
|
34
|
-
header = header.merge(additional_header) unless additional_header.nil?
|
35
|
-
req = Net::HTTP::Get.new(url, header)
|
36
|
-
make_request(req, params)
|
37
|
-
end
|
38
|
-
|
39
|
-
def post(url, params, payload = nil, additional_header = nil)
|
40
|
-
header = { 'Cookie' => cookie_to_s, 'User-Agent' => $useragent }
|
41
|
-
header = header.merge(additional_header) unless additional_header.nil?
|
42
|
-
req = Net::HTTP::Post.new(url, { 'Cookie' => cookie_to_s, 'User-Agent' => $useragent })
|
43
|
-
make_request(req, params, payload)
|
44
|
-
end
|
45
|
-
|
46
|
-
def put(url, params, payload = nil)
|
47
|
-
req = Net::HTTP::Put.new(url, { 'Cookie' => cookie_to_s, 'User-Agent' => $useragent })
|
48
|
-
make_request(req, params, payload)
|
49
|
-
end
|
50
|
-
|
51
|
-
def delete(url, params = nil, payload = nil)
|
52
|
-
req = Net::HTTP::Delete.new(url, { 'Cookie' => cookie_to_s, 'User-Agent' => $useragent })
|
53
|
-
make_request(req, params, payload)
|
54
|
-
end
|
55
|
-
|
56
|
-
def cookies
|
57
|
-
$cookies
|
58
|
-
end
|
59
|
-
def cookies=(dough)
|
60
|
-
$cookies = dough
|
61
|
-
end
|
62
|
-
|
63
|
-
def inspect
|
64
|
-
puts "#{bwhite(resp.code)} - #{$last_resp.message}"
|
65
|
-
puts $last_params.inspect
|
66
|
-
puts "Cookies: " + $cookies.inspect
|
67
|
-
puts $last_resp.body
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def cookie_to_s
|
73
|
-
cookiestr = ''
|
74
|
-
$cookies.each do |key, value|
|
75
|
-
cookiestr += "#{key}=#{value}, "
|
76
|
-
end
|
77
|
-
cookiestr[0..-2]
|
78
|
-
end
|
79
|
-
|
80
|
-
def make_request(req, params = nil, payload = nil)
|
81
|
-
$last_params = params
|
82
|
-
req.basic_auth($user, $password) unless $user.nil?
|
83
|
-
req.set_form_data(params, ';') unless params.nil?
|
84
|
-
|
85
|
-
unless payload.nil?
|
86
|
-
req.body = payload
|
87
|
-
req.set_content_type('multipart/form-data')
|
88
|
-
end
|
89
|
-
|
90
|
-
begin
|
91
|
-
$last_resp = $http.request(req)
|
92
|
-
|
93
|
-
unless $last_resp['set-cookie'].nil?
|
94
|
-
$last_resp['set-cookie'].split(', ').each do |cookie|
|
95
|
-
key, value = cookie.split('=')
|
96
|
-
$cookies[key] = value
|
97
|
-
end
|
98
|
-
end
|
99
|
-
rescue NoMethodError
|
100
|
-
return Net::HTTPInternalServerError.new '1.1', '500', 'Internal server error'
|
101
|
-
end
|
102
|
-
|
103
|
-
$last_resp
|
104
|
-
end
|
105
|
-
|
106
|
-
end
|