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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8655afabebaa23eba72bb5028b0efb5d22ecc7d7
4
+ data.tar.gz: 336634653e22e6b814edbb9fc00598fc32c431f5
5
+ SHA512:
6
+ metadata.gz: 16ee58b313175b50b7b446a9bbcfc3699b80261ab3502d26c2b785ce51e121b7d50ced60f72edd61396ec75c42167da7ca6ea4049799af9ce9eb531e8c47c39b
7
+ data.tar.gz: 4e0cdb6e135581bbdaee0eb5fb06d0771335448f4b944eb345cec16772e4a2447a28a3e3bc0d93dd256fd9f123e22e137ed50bd06784b7265e77b9a9ffe198ce
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ Gemfile.lock
2
+ pacto.log
3
+ **/.bundle/*.log
4
+ reports/
5
+ .rbenv-vars
6
+ .packer-creds.json
7
+ **/tmp/
8
+ node_modules/
9
+ .tokens.json
10
+ docs/
11
+ /polytrix/
12
+ pkg/
13
+ coverage/
data/.groc.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "glob": ["docs/src/*/challenges/**.*"],
3
+ "strip": ["docs/src"],
4
+ "github": false,
5
+ "index": "README.md",
6
+ "out": "docs/groc"
7
+ }
data/.rspec ADDED
@@ -0,0 +1,11 @@
1
+ -I features
2
+ --format MatrixFormatter::Formatters::JSONFormatter
3
+ --out reports/matrix<%= ENV['TEST_ENV_NUMBER'].to_i %>.json
4
+ --format MatrixFormatter::Formatters::HTMLFormatter
5
+ --out reports/matrix.html
6
+ --format html
7
+ --out reports/rspec.html
8
+ --format documentation
9
+ --color
10
+ --require features_helper.rb
11
+
data/.rspec_parallel ADDED
@@ -0,0 +1,10 @@
1
+ -I features
2
+ --format MatrixFormatter::Formatters::JSONFormatter --out reports/matrix<%= ENV['TEST_ENV_NUMBER'].to_i %>.json
3
+ --format ParallelTests::RSpec::SummaryLogger --out reports/spec_summary.log
4
+ --format ParallelTests::RSpec::FailuresLogger --out reports/failing_specs.log
5
+ --format RspecJunitFormatter --out reports/junit/rspec<%= ENV['TEST_ENV_NUMBER'].to_i %>.xml
6
+ --format documentation
7
+ --color
8
+ --require features_helper.rb
9
+ --failure-exit-code 0
10
+
data/Gemfile ADDED
@@ -0,0 +1,23 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+ gemspec
4
+
5
+ gem "pacto", :git => 'https://github.com/thoughtworks/pacto', :branch => 'uri_templates'
6
+ # uriTemplate support merged into webmock but not yet released - webmock#334
7
+ gem "webmock", :git => 'https://github.com/bblimke/webmock', :branch => 'master'
8
+ # optional param fix merged but not yet released - addressable#140
9
+ gem "addressable", :git => 'https://github.com/sporkmonger/addressable.git', :branch => 'master'
10
+ gem "fog", '~> 1.19'
11
+ gem "vcr"
12
+ gem "goliath"
13
+ gem "excon"
14
+ gem "em-http-request"
15
+ gem "rspec_junit_formatter"
16
+ gem "pry"
17
+ gem "matrix_formatter", :git => 'https://github.com/maxlinc/matrix_formatter', :branch => 'html5'
18
+ gem "highline"
19
+ gem "parallel_tests"
20
+ gem "rake-notes"
21
+ gem "simplecov"
22
+ gem "mixlib-shellout"
23
+
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # DRG Tests #
2
+
3
+ This repo contains smoke tests for Rackspace SDKs. In order to run it you'll either need:
4
+ - Lots of dependencies installed on your laptop
5
+ - VirtualBox & Vagrant, so you can install the necessary dependencies inside a local VM
6
+ - Packer and Vagrant-Rackspace, so you can build images and use images on the Rackspace cloud to run tests
7
+
8
+ The last option can also be combined with Jenkins JClouds plugin in order to setup CI builds using the images produced by Packer.
9
+
10
+ ## Dependencies
11
+
12
+ The tests will use package managers for each SDK where appropriate (e.g. bundler for fog, npm for pkgcloud, etc.) You need to be setup at least to the point where those package managers can run. You'll also need dnsmasq in order to intercept some of the HTTP transactions for testing purposes. It is possible to set this all up on your own machine - but the easiest way is to use Vagrant, Packer, or anything else that will let you use the Chef scripts in the project (targeted for Ubuntu).
13
+
14
+ ## Creating a DRG Image
15
+
16
+ ### Packer
17
+
18
+ The easiest way to create an image is with [Packer](http://www.packer.io).
19
+
20
+ ### Rackspace credentials
21
+
22
+ You need to create a `.rbenv-vars` file with your Rackspace credentials. These will be loaded as environment variables when the tests run. The file should contain:
23
+
24
+ ```
25
+ RAX_USERNAME=<your_rackspace_username>
26
+ RAX_API_KEY=<your_rackspace_api_key>
27
+ ```
28
+
29
+ ### Getting a DRG box
30
+
31
+ There is a Vagrantfile in the project. It uses a "DRG" box. There isn't currently a published DRG box, so you'll need to produce your own. You can:
32
+
33
+ * Comment out `config.vm.box = "drg"` and uncomment the other lines with an alternate box.
34
+ * Run `vagrant up`, `vagrant provision`, and then `vagrant package --output drg.box`. These steps will take a while.
35
+ * Run `vagrant box add drg drg.box`
36
+ * You now have a drg box, and can restore the Vagrant file to it's original state.
37
+
38
+ ### Running tests
39
+
40
+
41
+
42
+ ### (Tenative) Roadmap
43
+ * Use standard, shared images (travis-images? vagrantcloud?)
44
+ * Integrate with travis-build for .travis.yml support
45
+ * Separate Polytrix framework from reference tests
46
+
47
+ ### BHAG
48
+ * Run tests as an interactive course via a browser
data/Rakefile ADDED
@@ -0,0 +1,143 @@
1
+ require 'polytrix'
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+ require 'pacto/rake_task'
5
+ require 'rake/notes/rake_task'
6
+ require 'highline/import'
7
+ require 'json'
8
+
9
+ NOT_SETUP = "You need to set RAX_USERNAME and RAX_API_KEY env vars in order to run tests"
10
+
11
+ RSpec::Core::RakeTask.new('features') do |t|
12
+ t.rspec_opts = "-I features"
13
+ t.pattern = 'features/**/*_spec.rb'
14
+ end
15
+
16
+ RSpec::Core::RakeTask.new('spec') do |t|
17
+ t.rspec_opts = "-f documentation"
18
+ end
19
+
20
+ task :default => :spec
21
+
22
+ desc 'Run all the SDK tests'
23
+ task :features => [:check_setup]
24
+
25
+ desc 'Check pre-requisites'
26
+ task :check_setup do
27
+ fail NOT_SETUP unless ENV['RAX_USERNAME'] && ENV['RAX_API_KEY']
28
+ end
29
+
30
+ desc 'Remove reports and other generated artifacts'
31
+ task :clean do
32
+ FileUtils.rm_rf 'docs'
33
+ FileUtils.rm_rf 'reports'
34
+ end
35
+
36
+ desc 'Fetch dependencies for each SDK'
37
+ task :bootstrap do
38
+ Bundler.with_clean_env do
39
+ Dir['sdks/*'].each do |sdk_dir|
40
+ Dir.chdir sdk_dir do
41
+ if is_windows?
42
+ system "PowerShell -NoProfile -ExecutionPolicy Bypass .\\scripts\\bootstrap"
43
+ else
44
+ system "scripts/bootstrap"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ desc 'Configure the test framework'
52
+ task :setup do
53
+ username = ask "Enter your Rackspace Username: "
54
+ api_key = ask("Enter your Rackspace API KEY: "){|q| q.echo = "*"}
55
+ password = ask("Enter your Rackspace Password (for Packer): "){|q| q.echo = "*"}
56
+
57
+ puts "Creating .rbenv-vars"
58
+ File.open(".rbenv-vars", 'w') do |f|
59
+ f.puts "RAX_USERNAME=#{username}"
60
+ f.puts "RAX_API_KEY=#{api_key}"
61
+ f.puts
62
+ end
63
+
64
+ puts "Creating .packer-creds.json"
65
+ packer_creds = {
66
+ "RAX_USERNAME" => username,
67
+ "RAX_PASSWORD" => password
68
+ }
69
+ File.open(".packer-creds.json", "w") do |f|
70
+ f.puts JSON.pretty_generate packer_creds
71
+ end
72
+ end
73
+
74
+ namespace :documentation do
75
+ desc 'Generate annoted source code'
76
+ task :annotated do
77
+ system "groc"
78
+ end
79
+
80
+ task :copy_src do
81
+ sdks = Dir['sdks/*'].each do |sdk|
82
+ sdk = File.basename sdk
83
+ FileUtils.mkdir_p "docs/src/#{sdk}"
84
+ FileUtils.cp_r "sdks/#{sdk}/challenges/", "docs/src/#{sdk}"
85
+ end
86
+ end
87
+
88
+ desc 'Generate the Feature Matrix dashboard'
89
+ task :dashboard => [:copy_src, :annotated] do
90
+ $: << 'features'
91
+ require 'features_helper'
92
+ require "matrix_formatter/assets/generator"
93
+ require "matrix_formatter/formatters/html5_report_writer"
94
+ require 'fileutils'
95
+
96
+ asset_generator_options = {
97
+ :extra_resource_paths => ['lib/formatter/resources']
98
+ }
99
+ asset_generator = MatrixFormatter::Assets::Generator.new asset_generator_options
100
+ asset_generator.generate
101
+
102
+ output = File.open("docs/dashboard.html", 'w')
103
+ options = {:view => 'angular.html.slim', :layout => 'default_layout.html.slim'}
104
+ formatter = MatrixFormatter::Formatters::HTML5ReportWriter.new output, options
105
+ matrix = formatter.parse_results Dir['reports/matrix*.json']
106
+ # puts MultiJson.encode formatter.matrix
107
+ formatter.write_report
108
+ output.close
109
+
110
+ fail "Combined results contain failures - check the reports" if formatter.has_failures?
111
+ end
112
+ end
113
+
114
+ desc "Run the tests in parallel, split by SDK. Doesn't work on Windows, but you can use rspec_parallel to split by file instead."
115
+ task :parallel_spec do
116
+ tags = Dir['sdks/*'].map{|sdk| File.basename sdk}
117
+ puts "Detected SDKs: #{tags}"
118
+ threads = []
119
+ Thread.main[:results] = []
120
+ tags.each_with_index do | tag, index |
121
+ threads << Thread.new do
122
+ puts "Starting #{tag} on process #{index}"
123
+ Thread.main[:results] << {
124
+ :tag => tag,
125
+ :success => sh("TEST_ENV_NUMBER=#{index} bundle exec rspec --options .rspec_parallel -t #{tag} features")
126
+ }
127
+ end
128
+ end
129
+ threads.each do |thread|
130
+ thread.join
131
+ end
132
+ end
133
+
134
+ namespace :image do
135
+ desc 'Build a Rackspace image (using Packer)'
136
+ task :rackspace do
137
+ system "cd packer; packer build -var-file=../.packer-creds.json -only openstack packer.json"
138
+ end
139
+ end
140
+
141
+ def is_windows?
142
+ RbConfig::CONFIG['host_os'] =~ /mswin(\d+)|mingw/i
143
+ end
data/Vagrantfile ADDED
@@ -0,0 +1,41 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
5
+ VAGRANTFILE_API_VERSION = "2"
6
+
7
+ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
8
+ config.vm.box = "drg"
9
+
10
+ # Original box used to build pre-packaged DRG box
11
+ # config.vm.box = "ubuntu1310"
12
+ # config.vm.box_url = "https://dl.dropboxusercontent.com/s/ng79gg5bg24r38p/ubuntu1310.box?token_hash=AAGKH9rJTMozemrLMLw8n8Htvg8-gGhb7xo8cwh0TaYCaw&dl=1"
13
+
14
+ config.cache.auto_detect = true
15
+
16
+ config.vm.provision :shell, :inline => "curl -L https://opscode.com/chef/install.sh | bash"
17
+
18
+ config.vm.define :polytrix do |vm|
19
+ end
20
+
21
+ config.vm.provider :rackspace do |rs, override|
22
+ override.vm.box = "dummy"
23
+ override.ssh.private_key_path = '~/.ssh/id_rsa'
24
+ rs.public_key_path = '~/.ssh/id_rsa.pub'
25
+ rs.username = ENV['RAX_USERNAME']
26
+ rs.api_key = ENV['RAX_API_KEY']
27
+ rs.flavor = /2 GB Performance/
28
+ rs.image = "DRG" # image created by packer. See ./packer/
29
+ rs.rackspace_region = :ord
30
+ end
31
+
32
+ config.vm.provision :chef_solo do |chef|
33
+ chef.cookbooks_path = ["packer/cookbooks", "packer/vendor/cookbooks"]
34
+ chef.add_recipe "drg"
35
+ # chef.log_level = :debug
36
+ chef.json = {
37
+ :instance_role => "vagrant"
38
+ }
39
+ end
40
+
41
+ end
@@ -0,0 +1,40 @@
1
+ describe 'Getting Started', :markdown =>
2
+ """
3
+ Welcome to the SDK guide!
4
+
5
+ In this section, you will learn how to connect to OpenStack by authenticating against the [Identity service](http://docs.openstack.org/api/openstack-identity-service/2.0/content/).
6
+
7
+ By the end of the section, you will know:
8
+ - You have valid, working credentials
9
+ - You are able to load use the SDK of your choice
10
+
11
+ In the sections that follow, we will build the cloud infrastructure for a sample application using the OpenStack services.
12
+ """ do
13
+ code_sample 'authenticate token', """
14
+ Please use the SDK to [authenticate](http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/POST_authenticate_v2.0_tokens_Token_Calls.html) using a username and API key.
15
+ """, standard_env_vars, [:Authenticate] do
16
+ # Assertions
17
+ expect(Pacto).to have_validated_service('Identity', 'Authenticate')
18
+ expect(Pacto).to_not have_failed_validations
19
+ expect(Pacto).to_not have_unmatched_requests
20
+ end
21
+
22
+ code_sample 'all connections', """
23
+ Let's make a connection to each of the available OpenStack products
24
+ """, standard_env_vars, [] do
25
+ expect(Pacto).to have_validated_service('Identity', 'Authenticate')
26
+ expect(Pacto).to have_validated_service('Cloud Servers', 'List Servers')
27
+ expect(Pacto).to have_validated_service('Cloud Networks', 'List Networks')
28
+ expect(Pacto).to have_validated_service('Cloud Files', 'List Containers')
29
+ expect(Pacto).to have_validated_service('Cloud Load Balancers', 'List Load Balancers')
30
+ expect(Pacto).to have_validated_service('Cloud Databases', 'List Instances')
31
+ expect(Pacto).to have_validated_service('DNS', 'List Domains')
32
+ # Only a few SDKs have implemented monitoring
33
+ # expect(Pacto).to have_validated_service('Cloud Monitoring', 'Get Account')
34
+ expect(Pacto).to have_validated_service('Cloud Block Storage', 'List Volumes')
35
+ expect(Pacto).to have_validated_service('Autoscale', 'List Groups')
36
+ expect(Pacto).to have_validated_service('Cloud Queues', 'List Queues')
37
+ expect(Pacto).to_not have_failed_validations
38
+ # expect(Pacto).to_not have_unmatched_requests
39
+ end
40
+ end
@@ -0,0 +1,48 @@
1
+ describe 'Cloud Files', :markdown =>
2
+ """
3
+ In this section we'll cover Cloud Files. We'll start with a few simple services. In the final example for this section, we will upload static assets to a CDN-enabled Cloud Files container that will be used by our sample application.
4
+ """ do
5
+ env = standard_env_vars
6
+ file = build :file, env
7
+ env.merge!(
8
+ 'TEST_DIRECTORY' => file.directory.key,
9
+ 'TEST_FILE' => file.key
10
+ )
11
+
12
+ vars = standard_env_vars
13
+ code_sample "List Containers", """
14
+ Use the SDK to list your existing cloud Cloud Files containers.
15
+ """, vars, [] do |success|
16
+ # Assertions
17
+ expect(Pacto).to have_validated_service('Cloud Files', 'List Containers')
18
+ expect(Pacto).to_not have_failed_validations
19
+ expect(Pacto).to_not have_unmatched_requests
20
+ end
21
+
22
+ code_sample "Get object metadata", """
23
+ Now, use the SDK to retrieve a file from Cloud Files.
24
+ """, env, [] do
25
+ expect(Pacto).to have_validated_service('Cloud Files', 'Get Object Metadata')
26
+ # Not that we're validated it did *not* get the data
27
+ expect(Pacto).to_not have_validated('Cloud Files', 'Get Object Data')
28
+ end
29
+
30
+ code_sample "Upload a single file", """
31
+ Now, let's upload logo.png to Cloud Files so we can start building a website.
32
+ """, env, [] do
33
+ pending
34
+ end
35
+
36
+ code_sample "Upload static assets", """
37
+ Finally, let's upload static assets (javascript, css, images, fonts) for a website.
38
+ """, env, [] do
39
+ pending
40
+ end
41
+
42
+ code_sample "Upload static assets", """
43
+ Let's enable the CDN for our assets.
44
+ """, env, [] do
45
+ pending
46
+ end
47
+
48
+ end
@@ -0,0 +1,19 @@
1
+ describe 'Cloud Servers', :markdown =>
2
+ """
3
+
4
+ Scenarios using [Next Generation Cloud Servers API V2](http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_preface.html).
5
+ """ do
6
+ code_sample "Create Server", """
7
+ [Create a Server](http://docs.rackspace.com/servers/api/v2/cs-devguide/content/CreateServers.html)
8
+ using the image and flavor, and region specified in the environment.
9
+ """, standard_env_vars.merge({
10
+ 'RAX_REGION' => 'DFW',
11
+ 'SERVER1_IMAGE' => 'f70ed7c7-b42e-4d77-83d8-40fa29825b85',
12
+ 'SERVER1_FLAVOR' => 'performance1-1'
13
+ }), [] do |success|
14
+ # Assertions
15
+ expect(Pacto).to have_validated_service('Cloud Servers', 'Create Server')
16
+ expect(Pacto).to_not have_failed_validations
17
+ expect(Pacto).to_not have_unmatched_requests
18
+ end
19
+ end
@@ -0,0 +1,46 @@
1
+ $:.unshift File.expand_path('../pacto', File.dirname(__FILE__))
2
+ require 'polytrix/rspec'
3
+ require 'webmock/rspec'
4
+ require 'matrix_formatter'
5
+ require 'helpers/pacto_helper'
6
+ require 'pacto/extensions/matchers'
7
+ require 'pacto/extensions/loaders/simple_loader'
8
+ require 'pacto/extensions/loaders/api_blueprint_loader'
9
+ require 'helpers/teardown_helper'
10
+ require 'helpers/cloudfiles_helper'
11
+
12
+ SDKs = Dir['sdks/*'].map{|sdk| File.basename sdk}
13
+
14
+ Polytrix.implementors = SDKs.map{ |sdk|
15
+ Polytrix::Implementor.new :name => sdk #, :language => lang
16
+ }
17
+
18
+ require 'polytrix/runners/middleware/pacto'
19
+ Polytrix.configure do |c|
20
+ c.middleware.insert 0, Polytrix::Runners::Middleware::Pacto, {}
21
+ end
22
+
23
+ RSpec.configure do |c|
24
+ c.matrix_implementors = SDKs
25
+ c.treat_symbols_as_metadata_keys_with_true_values = true
26
+ c.include Polytrix::RSpec::Helper
27
+ end
28
+
29
+ def standard_env_vars
30
+ @standard_env_vars ||= {
31
+ 'RAX_USERNAME' => ENV['RAX_USERNAME'],
32
+ 'RAX_API_KEY' => ENV['RAX_API_KEY'],
33
+ 'RAX_REGION' => 'ORD', # FIXME: stubbing multiple hosts
34
+ # 'RAX_REGION' => ENV['RAX_REGION'] || %w{DFW ORD IAD SYD HKG}.sample, # omitted LON since it requires UK account
35
+ 'RAX_AUTH_URL' => PACTO_SERVER || 'https://identity.api.rackspacecloud.com'
36
+ }
37
+ end
38
+
39
+ def redact(data)
40
+ Hash[data.map do |k,v|
41
+ if k =~ /password|api_key/i
42
+ v = '******'
43
+ end
44
+ [k, v]
45
+ end]
46
+ end
@@ -0,0 +1,31 @@
1
+ require 'fog'
2
+
3
+ def build type, env = {}
4
+ case type
5
+ when :file
6
+ build_file env
7
+ else
8
+ raise ArgumentError.new "Don't know how to be a #{type}"
9
+ end
10
+ end
11
+
12
+ def build_file env
13
+ without_webmock do
14
+ service = Fog::Storage.new({
15
+ :provider => 'rackspace',
16
+ :rackspace_username => env['RAX_USERNAME'],
17
+ :rackspace_api_key => env['RAX_API_KEY'],
18
+ :rackspace_region => env['RAX_REGION']
19
+ })
20
+
21
+ directory = service.directories.create :key => 'asdf'
22
+ file = directory.files.create :key => 'asdf', :body => 'efgh'
23
+ end
24
+ end
25
+
26
+ def without_webmock
27
+ WebMock.disable!
28
+ ret_val = yield
29
+ WebMock.enable!
30
+ ret_val
31
+ end
@@ -0,0 +1,33 @@
1
+ require 'pacto'
2
+ require 'pacto/rspec'
3
+ require 'pacto_server'
4
+ require 'goliath/test_helper'
5
+
6
+ def test_env_number
7
+ ENV['TEST_ENV_NUMBER'].to_i
8
+ end
9
+
10
+ def pacto_port
11
+ @pacto_port ||= 9900 + test_env_number
12
+ end
13
+
14
+ COVERAGE_FILE = "reports/api_coverage#{test_env_number}.yaml"
15
+ PACTO_SERVER = "http://identity.api.rackspacecloud.dev:#{pacto_port}" unless ENV['NO_PACTO']
16
+
17
+ RSpec.configure do |c|
18
+ c.include Goliath::TestHelper
19
+ c.before(:each) { Pacto.clear! }
20
+ c.after(:each) { save_coverage }
21
+ end
22
+
23
+ def generate?
24
+ ENV['PACTO_GENERATE'] == 'true'
25
+ end
26
+
27
+ def save_coverage
28
+ data = YAML::load(File.read(COVERAGE_FILE)) if File.exists?(COVERAGE_FILE)
29
+ data ||= {}
30
+ validations = Pacto::ValidationRegistry.instance.validations
31
+ data[example.full_description] = validations.reject{|v| v.contract.nil?}.map{|v| v.contract.name }
32
+ File.open(COVERAGE_FILE, 'w') {|f| f.write data.to_yaml }
33
+ end
@@ -0,0 +1,49 @@
1
+ RSpec.configure do |c|
2
+ c.after(:each) { auto_teardown }
3
+ end
4
+
5
+ def auth_token
6
+ @auth_token ||= Pacto::ValidationRegistry.instance.validations.map do | val |
7
+ token = val.request.headers['X-Auth-Token']
8
+ end.compact.reject(&:empty?).first
9
+ end
10
+
11
+ def auto_teardown
12
+ # HACK: This should be simplified and moved to Pacto
13
+
14
+ created_resources = auto_find_prg
15
+ auto_delete created_resources, auth_token
16
+ end
17
+
18
+ REDIRECTS = [201, 202, (300...400).to_a.flatten]
19
+
20
+ def auto_find_prg
21
+ # Find URLs that were the "Get" part of a Post-Redirect-Get pattern
22
+ created_uris = Pacto::ValidationRegistry.instance.validations.map {|validation|
23
+ validation.response.headers['Location'] if validation.request.method == :post and REDIRECTS.include? validation.response.status
24
+ }.compact
25
+
26
+ created_uris.map do | created_uri |
27
+ Addressable::URI.parse created_uri
28
+ end
29
+ end
30
+
31
+ def auto_delete uris, auth_token
32
+ uris.group_by(&:site).each do | site, uris |
33
+ connection = Excon.new(site)
34
+ uris.each do | uri |
35
+ puts "Removing #{uri}"
36
+ connection.delete(:path => uri.path,
37
+ :debug_request => true,
38
+ :debug_response => true,
39
+ :expects => [204],
40
+ :headers => {
41
+ "User-Agent" => "fog/1.18.0",
42
+ "Content-Type" => "application/json",
43
+ "Accept" => "application/json",
44
+ "X-Auth-Token" => auth_token
45
+ }
46
+ )
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,63 @@
1
+ require 'multi_json'
2
+ require 'yaml'
3
+ require 'jsonpath'
4
+ require 'pacto'
5
+
6
+ module Pacto
7
+ module Extensions
8
+ module Loaders
9
+ class APIBlueprintLoader < YamlOrJsonLoader
10
+ def self.load(file)
11
+ data = super
12
+ contracts = []
13
+ resources = JsonPath.on(data, '$..resources[(@.uriTemplate)]')
14
+ resources.each do |resource|
15
+ resource['actions'].each do |action|
16
+ contract = load_action(action, resource, file)
17
+ Pacto.contract_registry.register(contract)
18
+ contracts << contract
19
+ end
20
+ end
21
+ Pacto::ContractList.new contracts
22
+ end
23
+
24
+ private
25
+
26
+ def self.load_action(action, resource, file)
27
+ # contract_definition = File.read(contract_path)
28
+ # definition = JSON.parse(contract_definition)
29
+ # schema.validate definition
30
+ # request = RequestClause.new(host, definition['request'])
31
+ # response = ResponseClause.new(definition['response'])
32
+ # Contract.new(request, response, contract_path, definition['name'])
33
+
34
+ # FIXME: Host info not available in blueprint.
35
+ host = 'http://localhost'
36
+ request_clause = RequestClause.new(host, {
37
+ 'method' => action['method'],
38
+ 'headers' => [], #not supporting this yet, probably needs conversion
39
+ 'path' => resource['uriTemplate']
40
+ })
41
+ response = action['examples'].first['responses'].first
42
+ response_clause = ResponseClause.new({
43
+ 'status' => response['name'],
44
+ 'headers' => [], #not supporting this yet, probably needs conversion
45
+ 'body' => schema_from(response)
46
+ })
47
+ Contract.new(request_clause, response_clause, file, resource['name'])
48
+ end
49
+
50
+ def self.schema_from(response)
51
+ schema = response['schema']
52
+ if schema.nil? or schema.empty?
53
+ {}
54
+ else
55
+ MultiJson.load schema
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ # contracts = Pacto::Extensions::Loaders::APIBlueprintLoader.load('pacto/blueprints/otter.json')