polytrix 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.groc.json +7 -0
  4. data/.rspec +11 -0
  5. data/.rspec_parallel +10 -0
  6. data/Gemfile +23 -0
  7. data/README.md +48 -0
  8. data/Rakefile +143 -0
  9. data/Vagrantfile +41 -0
  10. data/features/0_identity_spec.rb +40 -0
  11. data/features/1_cloud_files_spec.rb +48 -0
  12. data/features/2_servers_spec.rb +19 -0
  13. data/features/features_helper.rb +46 -0
  14. data/features/helpers/cloudfiles_helper.rb +31 -0
  15. data/features/helpers/pacto_helper.rb +33 -0
  16. data/features/helpers/teardown_helper.rb +49 -0
  17. data/features/pacto/extensions/loaders/api_blueprint_loader.rb +63 -0
  18. data/features/pacto/extensions/loaders/simple_loader.rb +55 -0
  19. data/features/pacto/extensions/loaders/yaml_or_json_loader.rb +17 -0
  20. data/features/pacto/extensions/matchers.rb +38 -0
  21. data/features/phase2/feature_coverage_report.rb +109 -0
  22. data/features/phase2/run_all_features.rb +14 -0
  23. data/features/static_site/fixtures/index.html +6 -0
  24. data/lib/polytrix/challenge.rb +27 -0
  25. data/lib/polytrix/challenge_builder.rb +16 -0
  26. data/lib/polytrix/challenge_runner.rb +87 -0
  27. data/lib/polytrix/configuration.rb +31 -0
  28. data/lib/polytrix/core/file_finder.rb +43 -0
  29. data/lib/polytrix/core/implementor.rb +17 -0
  30. data/lib/polytrix/core/result_tracker.rb +25 -0
  31. data/lib/polytrix/documentation_generator.rb +18 -0
  32. data/lib/polytrix/manifest.rb +46 -0
  33. data/lib/polytrix/result.rb +9 -0
  34. data/lib/polytrix/rspec/documentation_formatter.rb +41 -0
  35. data/lib/polytrix/rspec.rb +75 -0
  36. data/lib/polytrix/runners/linux_challenge_runner.rb +22 -0
  37. data/lib/polytrix/runners/middleware/change_directory.rb +20 -0
  38. data/lib/polytrix/runners/middleware/feature_executor.rb +23 -0
  39. data/lib/polytrix/runners/middleware/pacto.rb +59 -0
  40. data/lib/polytrix/runners/middleware/setup_env_vars.rb +38 -0
  41. data/lib/polytrix/runners/windows_challenge_runner.rb +25 -0
  42. data/lib/polytrix/version.rb +3 -0
  43. data/lib/polytrix.rb +56 -0
  44. data/packer/.gitignore +3 -0
  45. data/packer/Berksfile +15 -0
  46. data/packer/Gemfile +5 -0
  47. data/packer/Vagrantfile +128 -0
  48. data/packer/cookbooks/drg/metadata.rb +27 -0
  49. data/packer/cookbooks/drg/recipes/admins.rb +22 -0
  50. data/packer/cookbooks/drg/recipes/default.rb +9 -0
  51. data/packer/cookbooks/drg/recipes/dotnet.rb +4 -0
  52. data/packer/cookbooks/drg/recipes/golang.rb +4 -0
  53. data/packer/cookbooks/drg/recipes/java.rb +5 -0
  54. data/packer/cookbooks/drg/recipes/php.rb +10 -0
  55. data/packer/cookbooks/drg/recipes/ruby.rb +29 -0
  56. data/packer/cookbooks/drg/recipes/system.rb +13 -0
  57. data/packer/create_box.sh +10 -0
  58. data/packer/http/preseed.cfg +87 -0
  59. data/packer/packer.json +91 -0
  60. data/packer/scripts/root_setup.sh +37 -0
  61. data/packer/scripts/setup.sh +32 -0
  62. data/pacto/config/pacto_server.rb +40 -0
  63. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/extensions.json +64 -0
  64. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/flavors/id.json +100 -0
  65. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/images/id.json +176 -0
  66. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers/id.json +189 -0
  67. data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers.json +63 -0
  68. data/pacto/contracts/dns.api.rackspacecloud.com/v1.0/_tenant_id/domains.json +62 -0
  69. data/pacto/contracts/identity.api.rackspacecloud.com/v2.0/tokens.json +192 -0
  70. data/pacto/contracts/monitoring.api.rackspacecloud.com/v1.0/_tenant_id/account.json +39 -0
  71. data/pacto/contracts/ord.autoscale.api.rackspacecloud.com/v1.0/_tenant_id/groups.json +38 -0
  72. data/pacto/contracts/ord.blockstorage.api.rackspacecloud.com/v1/_tenant_id/volumes.json +30 -0
  73. data/pacto/contracts/ord.databases.api.rackspacecloud.com/v1.0/_tenant_id/instances.json +30 -0
  74. data/pacto/contracts/ord.loadbalancers.api.rackspacecloud.com/v1.0/_tenant_id/loadbalancers.json +114 -0
  75. data/pacto/contracts/ord.queues.api.rackspacecloud.com/v1/_tenant_id/queues.json +13 -0
  76. data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/os-networksv2.json +46 -0
  77. data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/servers/detail.json +230 -0
  78. data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account/container/object.json +15 -0
  79. data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account.json +43 -0
  80. data/pacto/contracts/storage101.ord1.clouddrive.com/v1/_mosso_id.json +44 -0
  81. data/pacto/pacto_server.rb +100 -0
  82. data/pacto/rackspace_uri_map.yaml +229 -0
  83. data/polytrix.gemspec +27 -0
  84. data/scripts/bootstrap +10 -0
  85. data/scripts/cibuild +4 -0
  86. data/sdks/fog/.gitignore +1 -0
  87. data/sdks/fog/Gemfile +5 -0
  88. data/sdks/fog/challenges/all_connections.rb +45 -0
  89. data/sdks/fog/challenges/authenticate_token.rb +15 -0
  90. data/sdks/fog/challenges/cdn_enable_container.rb +20 -0
  91. data/sdks/fog/challenges/create_a_container.rb +17 -0
  92. data/sdks/fog/challenges/create_server.rb +36 -0
  93. data/sdks/fog/challenges/get_object_metadata.rb +13 -0
  94. data/sdks/fog/challenges/list_containers.rb +10 -0
  95. data/sdks/fog/challenges/provision_scalable_webapp.rb +30 -0
  96. data/sdks/fog/challenges/upload_folder.rb +25 -0
  97. data/sdks/fog/scripts/bootstrap +4 -0
  98. data/sdks/fog/scripts/bootstrap.ps1 +1 -0
  99. data/sdks/fog/scripts/wrapper +2 -0
  100. data/sdks/fog/scripts/wrapper.ps1 +1 -0
  101. data/sdks/gophercloud/.gitignore +2 -0
  102. data/sdks/gophercloud/challenges/authenticate_token.go +23 -0
  103. data/sdks/gophercloud/scripts/bootstrap +6 -0
  104. data/sdks/gophercloud/scripts/wrapper +10 -0
  105. data/sdks/jclouds/.gitignore +1 -0
  106. data/sdks/jclouds/challenges/AuthenticateToken.java +115 -0
  107. data/sdks/jclouds/pom.xml +34 -0
  108. data/sdks/jclouds/scripts/bootstrap +3 -0
  109. data/sdks/jclouds/scripts/wrapper +7 -0
  110. data/sdks/openstack.net/.gitignore +4 -0
  111. data/sdks/openstack.net/.nuget/Microsoft.Build.dll +0 -0
  112. data/sdks/openstack.net/.nuget/NuGet.Config +6 -0
  113. data/sdks/openstack.net/.nuget/NuGet.exe +0 -0
  114. data/sdks/openstack.net/.nuget/NuGet.targets +136 -0
  115. data/sdks/openstack.net/Challenge.cs +10 -0
  116. data/sdks/openstack.net/RunChallenge.cs +19 -0
  117. data/sdks/openstack.net/challenges/AuthenticateToken.cs +24 -0
  118. data/sdks/openstack.net/challenges/Weird.cs +133 -0
  119. data/sdks/openstack.net/openstack.net.csproj +58 -0
  120. data/sdks/openstack.net/openstack.net.sln +27 -0
  121. data/sdks/openstack.net/openstack.net.userprefs +8 -0
  122. data/sdks/openstack.net/packages.config +6 -0
  123. data/sdks/openstack.net/scripts/bootstrap +2 -0
  124. data/sdks/openstack.net/scripts/bootstrap.ps1 +2 -0
  125. data/sdks/openstack.net/scripts/wrapper +7 -0
  126. data/sdks/openstack.net/scripts/wrapper.ps1 +1 -0
  127. data/sdks/php-opencloud/.gitignore +4 -0
  128. data/sdks/php-opencloud/challenges/all_connections.php +64 -0
  129. data/sdks/php-opencloud/challenges/authenticate_token.php +14 -0
  130. data/sdks/php-opencloud/challenges/create_server.php +39 -0
  131. data/sdks/php-opencloud/challenges/get_object_metadata.php +19 -0
  132. data/sdks/php-opencloud/composer.json +5 -0
  133. data/sdks/php-opencloud/scripts/bootstrap +4 -0
  134. data/sdks/php-opencloud/scripts/bootstrap.ps1 +2 -0
  135. data/sdks/php-opencloud/scripts/wrapper +2 -0
  136. data/sdks/php-opencloud/scripts/wrapper.ps1 +1 -0
  137. data/sdks/pkgcloud/.gitignore +1 -0
  138. data/sdks/pkgcloud/challenges/authenticate_token.js +17 -0
  139. data/sdks/pkgcloud/challenges/get_object_metadata.js +18 -0
  140. data/sdks/pkgcloud/scripts/bootstrap +2 -0
  141. data/sdks/pkgcloud/scripts/bootstrap.ps1 +1 -0
  142. data/sdks/pkgcloud/scripts/wrapper +2 -0
  143. data/sdks/pkgcloud/scripts/wrapper.ps1 +1 -0
  144. data/sdks/pyrax/.gitignore +2 -0
  145. data/sdks/pyrax/challenges/all_connections.py +61 -0
  146. data/sdks/pyrax/challenges/authenticate_token.py +17 -0
  147. data/sdks/pyrax/challenges/cdn_enable_container.py +22 -0
  148. data/sdks/pyrax/challenges/create_a_container.py +21 -0
  149. data/sdks/pyrax/challenges/create_server.py +35 -0
  150. data/sdks/pyrax/challenges/get_object_metadata.py +17 -0
  151. data/sdks/pyrax/challenges/upload_folder.py +32 -0
  152. data/sdks/pyrax/requirements.txt +21 -0
  153. data/sdks/pyrax/scripts/bootstrap +9 -0
  154. data/sdks/pyrax/scripts/bootstrap.ps1 +7 -0
  155. data/sdks/pyrax/scripts/wrapper +3 -0
  156. data/sdks/pyrax/scripts/wrapper.ps1 +2 -0
  157. data/spec/fixtures/factorial.py +18 -0
  158. data/spec/fixtures/polytrix.yml +16 -0
  159. data/spec/fixtures/src-doc/quine.md.erb +20 -0
  160. data/spec/polytrix/challenge_builder_spec.rb +16 -0
  161. data/spec/polytrix/challenge_runner_spec.rb +14 -0
  162. data/spec/polytrix/challenge_spec.rb +20 -0
  163. data/spec/polytrix/configuration_spec.rb +10 -0
  164. data/spec/polytrix/documentation_generator_spec.rb +36 -0
  165. data/spec/polytrix/file_finder_spec.rb +24 -0
  166. data/spec/polytrix/manifest_spec.rb +26 -0
  167. data/spec/polytrix/middleware/feature_executor_spec.rb +48 -0
  168. data/spec/polytrix_spec.rb +13 -0
  169. data/spec/rspec_spec.rb +17 -0
  170. data/spec/spec_helper.rb +7 -0
  171. metadata +325 -0
@@ -0,0 +1,114 @@
1
+ {
2
+ "request": {
3
+ "headers": {
4
+ },
5
+ "method": "get",
6
+ "path": "/v1.0/:tenant_id/loadbalancers"
7
+ },
8
+ "response": {
9
+ "headers": {
10
+ "Content-Type": "application/json"
11
+ },
12
+ "status": 200,
13
+ "body": {
14
+ "$schema": "http://json-schema.org/draft-03/schema#",
15
+ "description": "Generated from https://ord.loadbalancers.api.rackspacecloud.com/v1.0/:tenant_id/loadbalancers with shasum 20251c7e274236b680c1994d77dfc2e069ff1c21",
16
+ "type": "object",
17
+ "required": true,
18
+ "properties": {
19
+ "loadBalancers": {
20
+ "type": "array",
21
+ "required": true,
22
+ "minItems": 1,
23
+ "uniqueItems": true,
24
+ "items": {
25
+ "type": "object",
26
+ "required": true,
27
+ "properties": {
28
+ "name": {
29
+ "type": "string",
30
+ "required": true
31
+ },
32
+ "id": {
33
+ "type": "integer",
34
+ "required": true
35
+ },
36
+ "protocol": {
37
+ "type": "string",
38
+ "required": true
39
+ },
40
+ "port": {
41
+ "type": "integer",
42
+ "required": true
43
+ },
44
+ "algorithm": {
45
+ "type": "string",
46
+ "required": true
47
+ },
48
+ "status": {
49
+ "type": "string",
50
+ "required": true
51
+ },
52
+ "timeout": {
53
+ "type": "integer",
54
+ "required": true
55
+ },
56
+ "created": {
57
+ "type": "object",
58
+ "required": true,
59
+ "properties": {
60
+ "time": {
61
+ "type": "string",
62
+ "required": true
63
+ }
64
+ }
65
+ },
66
+ "virtualIps": {
67
+ "type": "array",
68
+ "required": true,
69
+ "minItems": 1,
70
+ "uniqueItems": true,
71
+ "items": {
72
+ "type": "object",
73
+ "required": true,
74
+ "properties": {
75
+ "address": {
76
+ "type": "string",
77
+ "required": true
78
+ },
79
+ "id": {
80
+ "type": "integer",
81
+ "required": true
82
+ },
83
+ "type": {
84
+ "type": "string",
85
+ "required": true
86
+ },
87
+ "ipVersion": {
88
+ "type": "string",
89
+ "required": true
90
+ }
91
+ }
92
+ }
93
+ },
94
+ "updated": {
95
+ "type": "object",
96
+ "required": true,
97
+ "properties": {
98
+ "time": {
99
+ "type": "string",
100
+ "required": true
101
+ }
102
+ }
103
+ },
104
+ "nodeCount": {
105
+ "type": "integer",
106
+ "required": true
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "request": {
3
+ "headers": {
4
+ },
5
+ "method": "get",
6
+ "path": "/v1/:tenant_id/queues"
7
+ },
8
+ "response": {
9
+ "headers": {
10
+ },
11
+ "status": 204
12
+ }
13
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "request": {
3
+ "headers": {
4
+ },
5
+ "method": "get",
6
+ "path": "/v2/:tenant_id/os-networksv2"
7
+ },
8
+ "response": {
9
+ "headers": {
10
+ "Content-Type": "application/json"
11
+ },
12
+ "status": 200,
13
+ "body": {
14
+ "$schema": "http://json-schema.org/draft-03/schema#",
15
+ "description": "Generated from https://ord.servers.api.rackspacecloud.com/v2/:tenant_id/os-networksv2 with shasum ef5650d153090855ea761c121171df3bfec67c9d",
16
+ "type": "object",
17
+ "required": true,
18
+ "properties": {
19
+ "networks": {
20
+ "type": "array",
21
+ "required": true,
22
+ "minItems": 1,
23
+ "uniqueItems": true,
24
+ "items": {
25
+ "type": "object",
26
+ "required": true,
27
+ "properties": {
28
+ "cidr": {
29
+ "type": "string",
30
+ "required": false
31
+ },
32
+ "id": {
33
+ "type": "string",
34
+ "required": true
35
+ },
36
+ "label": {
37
+ "type": "string",
38
+ "required": true
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,230 @@
1
+ {
2
+ "request": {
3
+ "headers": {
4
+ },
5
+ "method": "get",
6
+ "path": "/v2/:tenant_id/servers/detail"
7
+ },
8
+ "response": {
9
+ "headers": {
10
+ "Content-Type": "application/json"
11
+ },
12
+ "status": 200,
13
+ "body": {
14
+ "$schema": "http://json-schema.org/draft-03/schema#",
15
+ "description": "Generated from https://ord.servers.api.rackspacecloud.com/v2/:tenant_id/servers/detail with shasum 1c7341b036cda60e635ee836dd71c182f8f78712",
16
+ "type": "object",
17
+ "required": true,
18
+ "properties": {
19
+ "servers": {
20
+ "type": "array",
21
+ "required": true,
22
+ "minItems": 1,
23
+ "uniqueItems": true,
24
+ "items": {
25
+ "type": "object",
26
+ "required": true,
27
+ "properties": {
28
+ "status": {
29
+ "type": "string",
30
+ "required": true
31
+ },
32
+ "updated": {
33
+ "type": "string",
34
+ "required": true
35
+ },
36
+ "hostId": {
37
+ "type": "string",
38
+ "required": true
39
+ },
40
+ "addresses": {
41
+ "type": "object",
42
+ "required": true,
43
+ "properties": {
44
+ "public": {
45
+ "type": "array",
46
+ "required": true,
47
+ "minItems": 1,
48
+ "uniqueItems": true,
49
+ "items": {
50
+ "type": "object",
51
+ "required": true,
52
+ "properties": {
53
+ "version": {
54
+ "type": "integer",
55
+ "required": true
56
+ },
57
+ "addr": {
58
+ "type": "string",
59
+ "required": true
60
+ }
61
+ }
62
+ }
63
+ },
64
+ "private": {
65
+ "type": "array",
66
+ "required": true,
67
+ "minItems": 1,
68
+ "uniqueItems": true,
69
+ "items": {
70
+ "type": "object",
71
+ "required": true,
72
+ "properties": {
73
+ "version": {
74
+ "type": "integer",
75
+ "required": true
76
+ },
77
+ "addr": {
78
+ "type": "string",
79
+ "required": true
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ },
86
+ "links": {
87
+ "type": "array",
88
+ "required": true,
89
+ "minItems": 1,
90
+ "uniqueItems": true,
91
+ "items": {
92
+ "type": "object",
93
+ "required": true,
94
+ "properties": {
95
+ "href": {
96
+ "type": "string",
97
+ "required": true
98
+ },
99
+ "rel": {
100
+ "type": "string",
101
+ "required": true
102
+ }
103
+ }
104
+ }
105
+ },
106
+ "key_name": {
107
+ },
108
+ "image": {
109
+ "type": "object",
110
+ "required": true,
111
+ "properties": {
112
+ "id": {
113
+ "type": "string",
114
+ "required": true
115
+ },
116
+ "links": {
117
+ "type": "array",
118
+ "required": true,
119
+ "minItems": 1,
120
+ "uniqueItems": true,
121
+ "items": {
122
+ "type": "object",
123
+ "required": true,
124
+ "properties": {
125
+ "href": {
126
+ "type": "string",
127
+ "required": true
128
+ },
129
+ "rel": {
130
+ "type": "string",
131
+ "required": true
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+ },
138
+ "OS-EXT-STS:task_state": {
139
+ },
140
+ "OS-EXT-STS:vm_state": {
141
+ "type": "string",
142
+ "required": false
143
+ },
144
+ "flavor": {
145
+ "type": "object",
146
+ "required": true,
147
+ "properties": {
148
+ "id": {
149
+ "type": "string",
150
+ "required": true
151
+ },
152
+ "links": {
153
+ "type": "array",
154
+ "required": true,
155
+ "minItems": 1,
156
+ "uniqueItems": true,
157
+ "items": {
158
+ "type": "object",
159
+ "required": true,
160
+ "properties": {
161
+ "href": {
162
+ "type": "string",
163
+ "required": true
164
+ },
165
+ "rel": {
166
+ "type": "string",
167
+ "required": true
168
+ }
169
+ }
170
+ }
171
+ }
172
+ }
173
+ },
174
+ "id": {
175
+ "type": "string",
176
+ "required": true
177
+ },
178
+ "user_id": {
179
+ "type": "string",
180
+ "required": true
181
+ },
182
+ "name": {
183
+ "type": "string",
184
+ "required": true
185
+ },
186
+ "created": {
187
+ "type": "string",
188
+ "required": true
189
+ },
190
+ "tenant_id": {
191
+ "type": "string",
192
+ "required": true
193
+ },
194
+ "OS-DCF:diskConfig": {
195
+ "type": "string",
196
+ "required": false
197
+ },
198
+ "accessIPv4": {
199
+ "type": "string",
200
+ "required": true
201
+ },
202
+ "accessIPv6": {
203
+ "type": "string",
204
+ "required": true
205
+ },
206
+ "progress": {
207
+ "type": "integer",
208
+ "required": true
209
+ },
210
+ "OS-EXT-STS:power_state": {
211
+ "type": "integer",
212
+ "required": false
213
+ },
214
+ "config_drive": {
215
+ "type": "string",
216
+ "required": true
217
+ },
218
+ "metadata": {
219
+ "type": "object",
220
+ "required": true,
221
+ "properties": {
222
+ }
223
+ }
224
+ }
225
+ }
226
+ }
227
+ }
228
+ }
229
+ }
230
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "request": {
3
+ "headers": {
4
+ },
5
+ "method": "head",
6
+ "path": "/v1/:mosso_account/:container/:object"
7
+ },
8
+ "response": {
9
+ "headers": {
10
+ "Content-Type": "application/octet-stream",
11
+ "Accept-Ranges": "bytes"
12
+ },
13
+ "status": 200
14
+ }
15
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "request": {
3
+ "headers": {
4
+ },
5
+ "method": "get",
6
+ "params": {
7
+ },
8
+ "path": "/v1/:mosso"
9
+ },
10
+ "response": {
11
+ "headers": {
12
+ "Content-Type": "application/json; charset=utf-8",
13
+ "Accept-Ranges": "bytes"
14
+ },
15
+ "status": 200,
16
+ "body": {
17
+ "$schema": "http://json-schema.org/draft-03/schema#",
18
+ "description": "Generated from vcr with shasum 814f52c8c895e72dd1051188ee3a65704698033a",
19
+ "type": "array",
20
+ "required": true,
21
+ "minItems": 1,
22
+ "uniqueItems": true,
23
+ "items": {
24
+ "type": "object",
25
+ "required": true,
26
+ "properties": {
27
+ "count": {
28
+ "type": "integer",
29
+ "required": true
30
+ },
31
+ "bytes": {
32
+ "type": "integer",
33
+ "required": true
34
+ },
35
+ "name": {
36
+ "type": "string",
37
+ "required": true
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "request": {
3
+ "headers": {
4
+ },
5
+ "method": "get",
6
+ "params": {
7
+ "format": "json"
8
+ },
9
+ "path": "/v1/:mosso_id/"
10
+ },
11
+ "response": {
12
+ "headers": {
13
+ "Content-Type": "application/json; charset=utf-8",
14
+ "Accept-Ranges": "bytes"
15
+ },
16
+ "status": 200,
17
+ "body": {
18
+ "$schema": "http://json-schema.org/draft-03/schema#",
19
+ "description": "Generated from https://storage101.ord1.clouddrive.com/v1/:mosso_id/?format=json with shasum f8f6461144643dda6fc335e09f96a5930008b9d9",
20
+ "type": "array",
21
+ "required": true,
22
+ "minItems": 1,
23
+ "uniqueItems": true,
24
+ "items": {
25
+ "type": "object",
26
+ "required": true,
27
+ "properties": {
28
+ "count": {
29
+ "type": "integer",
30
+ "required": true
31
+ },
32
+ "bytes": {
33
+ "type": "integer",
34
+ "required": true
35
+ },
36
+ "name": {
37
+ "type": "string",
38
+ "required": true
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,100 @@
1
+ require 'goliath'
2
+ require 'em-synchrony'
3
+ require 'em-synchrony/em-http'
4
+
5
+ class PactoServer < Goliath::API
6
+ use ::Rack::ContentLength
7
+
8
+ def port
9
+ env.config[:port]
10
+ end
11
+
12
+ def on_body(env, data)
13
+ env.logger.info 'received data: ' + safe_log(data)
14
+ (env['async-body'] ||= '') << data
15
+ end
16
+
17
+ def response (env)
18
+ path = env[Goliath::Request::REQUEST_PATH]
19
+ host = env['HTTP_HOST'].gsub(".dev:#{port}", '.com')
20
+ headers = env['client-headers']
21
+ begin
22
+ uri = normalize_uri(env, "https://#{host}#{path}")
23
+ env.logger.info 'forwarding to: ' + uri
24
+ safe_headers = headers.reject {|k,v| ['host', 'content-length', 'transfer-encoding'].include? k.downcase }
25
+ env.logger.debug "filtered headers: #{safe_headers}"
26
+ # request_body = env[Goliath::Request::RACK_INPUT].read
27
+ request_body = env['async-body']
28
+ request_method = env['REQUEST_METHOD'].downcase
29
+ em_request_method = "a#{request_method}".to_sym
30
+ em_request_options = {:head => safe_headers, :query => env['QUERY_STRING']}
31
+ env.logger.debug "sending #{request_method} request"
32
+ unless request_body.nil?
33
+ em_request_options.merge!({:body => request_body})
34
+ env.logger.debug "with request body"
35
+ end
36
+
37
+ resp = EM::Synchrony.sync EventMachine::HttpRequest.new(uri).send(em_request_method, em_request_options)
38
+ raise resp.error if resp.error
39
+
40
+ code = resp.response_header.http_status
41
+ safe_response_headers = normalize_headers(resp.response_header).reject {|k,v| ['connection', 'content-encoding', 'content-length', 'transfer-encoding'].include? k.downcase}
42
+ body = proxy_rewrite(resp.response)
43
+
44
+ env.logger.debug "response headers: #{safe_response_headers}"
45
+ env.logger.debug "response body: #{safe_log(body)}"
46
+ [code, safe_response_headers, body]
47
+ rescue => e
48
+ env.logger.warn "responding with error: #{e.message}"
49
+ [500, {}, e.message]
50
+ end
51
+ end
52
+
53
+ def normalize_uri env, uri
54
+ if uri[-1] == '/'
55
+ env.logger.warn 'Normalizing uri with trailing /, this may be detected as a consistency issue in the future'
56
+ uri = uri[0..-2]
57
+ end
58
+ uri
59
+ end
60
+
61
+ def normalize_headers headers
62
+ headers.inject({}) do |res, elem|
63
+ key = elem.first.dup
64
+ value = elem.last
65
+ key.gsub!('_', '-')
66
+ key = key.split('-').map {|w| w.capitalize}.join '-'
67
+ res[key] = value
68
+ res
69
+ end
70
+ end
71
+
72
+ def proxy_rewrite body
73
+ # Make sure rels continue going through our proxy
74
+ body.gsub('.com', ".dev:#{port}").gsub(/https\:([\w\-\.\\\/]+).dev/, 'http:\1.dev')
75
+ end
76
+
77
+ def options_parser(opts, options)
78
+ options[:strict] ||= false
79
+ options[:directory] ||= "contracts"
80
+ opts.on('-l', '--live', 'Send requests to live services (instead of stubs)') { |val| options[:live] = true }
81
+ opts.on('-g', '--generate', 'Generate Contracts from requests') { |val| options[:generate] = true }
82
+ opts.on('-V', '--validate', 'Validate requests/responses against Contracts') { |val| options[:validate] = true }
83
+ opts.on('-m', '--match-strict', 'Enforce strict request matching rules') { |val| options[:strict] = true }
84
+ opts.on('-x', '--contracts_dir DIR', 'Directory that contains the contracts to be registered') { |val| options[:directory] = val }
85
+ opts.on('-H', '--host HOST', 'Host of the real service, for generating or validating live requests') { |val| options[:backend_host] = val }
86
+ end
87
+
88
+ def on_headers(env, headers)
89
+ env.logger.info 'proxying new request: ' + headers.inspect
90
+ env['client-headers'] = headers
91
+ end
92
+
93
+ def safe_log(string_to_log)
94
+ if string_to_log.ascii_only?
95
+ string_to_log
96
+ else
97
+ "(Supressed logging of non-ASCII content)"
98
+ end
99
+ end
100
+ end