polytrix 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.groc.json +7 -0
- data/.rspec +11 -0
- data/.rspec_parallel +10 -0
- data/Gemfile +23 -0
- data/README.md +48 -0
- data/Rakefile +143 -0
- data/Vagrantfile +41 -0
- data/features/0_identity_spec.rb +40 -0
- data/features/1_cloud_files_spec.rb +48 -0
- data/features/2_servers_spec.rb +19 -0
- data/features/features_helper.rb +46 -0
- data/features/helpers/cloudfiles_helper.rb +31 -0
- data/features/helpers/pacto_helper.rb +33 -0
- data/features/helpers/teardown_helper.rb +49 -0
- data/features/pacto/extensions/loaders/api_blueprint_loader.rb +63 -0
- data/features/pacto/extensions/loaders/simple_loader.rb +55 -0
- data/features/pacto/extensions/loaders/yaml_or_json_loader.rb +17 -0
- data/features/pacto/extensions/matchers.rb +38 -0
- data/features/phase2/feature_coverage_report.rb +109 -0
- data/features/phase2/run_all_features.rb +14 -0
- data/features/static_site/fixtures/index.html +6 -0
- data/lib/polytrix/challenge.rb +27 -0
- data/lib/polytrix/challenge_builder.rb +16 -0
- data/lib/polytrix/challenge_runner.rb +87 -0
- data/lib/polytrix/configuration.rb +31 -0
- data/lib/polytrix/core/file_finder.rb +43 -0
- data/lib/polytrix/core/implementor.rb +17 -0
- data/lib/polytrix/core/result_tracker.rb +25 -0
- data/lib/polytrix/documentation_generator.rb +18 -0
- data/lib/polytrix/manifest.rb +46 -0
- data/lib/polytrix/result.rb +9 -0
- data/lib/polytrix/rspec/documentation_formatter.rb +41 -0
- data/lib/polytrix/rspec.rb +75 -0
- data/lib/polytrix/runners/linux_challenge_runner.rb +22 -0
- data/lib/polytrix/runners/middleware/change_directory.rb +20 -0
- data/lib/polytrix/runners/middleware/feature_executor.rb +23 -0
- data/lib/polytrix/runners/middleware/pacto.rb +59 -0
- data/lib/polytrix/runners/middleware/setup_env_vars.rb +38 -0
- data/lib/polytrix/runners/windows_challenge_runner.rb +25 -0
- data/lib/polytrix/version.rb +3 -0
- data/lib/polytrix.rb +56 -0
- data/packer/.gitignore +3 -0
- data/packer/Berksfile +15 -0
- data/packer/Gemfile +5 -0
- data/packer/Vagrantfile +128 -0
- data/packer/cookbooks/drg/metadata.rb +27 -0
- data/packer/cookbooks/drg/recipes/admins.rb +22 -0
- data/packer/cookbooks/drg/recipes/default.rb +9 -0
- data/packer/cookbooks/drg/recipes/dotnet.rb +4 -0
- data/packer/cookbooks/drg/recipes/golang.rb +4 -0
- data/packer/cookbooks/drg/recipes/java.rb +5 -0
- data/packer/cookbooks/drg/recipes/php.rb +10 -0
- data/packer/cookbooks/drg/recipes/ruby.rb +29 -0
- data/packer/cookbooks/drg/recipes/system.rb +13 -0
- data/packer/create_box.sh +10 -0
- data/packer/http/preseed.cfg +87 -0
- data/packer/packer.json +91 -0
- data/packer/scripts/root_setup.sh +37 -0
- data/packer/scripts/setup.sh +32 -0
- data/pacto/config/pacto_server.rb +40 -0
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/extensions.json +64 -0
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/flavors/id.json +100 -0
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/images/id.json +176 -0
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers/id.json +189 -0
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers.json +63 -0
- data/pacto/contracts/dns.api.rackspacecloud.com/v1.0/_tenant_id/domains.json +62 -0
- data/pacto/contracts/identity.api.rackspacecloud.com/v2.0/tokens.json +192 -0
- data/pacto/contracts/monitoring.api.rackspacecloud.com/v1.0/_tenant_id/account.json +39 -0
- data/pacto/contracts/ord.autoscale.api.rackspacecloud.com/v1.0/_tenant_id/groups.json +38 -0
- data/pacto/contracts/ord.blockstorage.api.rackspacecloud.com/v1/_tenant_id/volumes.json +30 -0
- data/pacto/contracts/ord.databases.api.rackspacecloud.com/v1.0/_tenant_id/instances.json +30 -0
- data/pacto/contracts/ord.loadbalancers.api.rackspacecloud.com/v1.0/_tenant_id/loadbalancers.json +114 -0
- data/pacto/contracts/ord.queues.api.rackspacecloud.com/v1/_tenant_id/queues.json +13 -0
- data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/os-networksv2.json +46 -0
- data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/servers/detail.json +230 -0
- data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account/container/object.json +15 -0
- data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account.json +43 -0
- data/pacto/contracts/storage101.ord1.clouddrive.com/v1/_mosso_id.json +44 -0
- data/pacto/pacto_server.rb +100 -0
- data/pacto/rackspace_uri_map.yaml +229 -0
- data/polytrix.gemspec +27 -0
- data/scripts/bootstrap +10 -0
- data/scripts/cibuild +4 -0
- data/sdks/fog/.gitignore +1 -0
- data/sdks/fog/Gemfile +5 -0
- data/sdks/fog/challenges/all_connections.rb +45 -0
- data/sdks/fog/challenges/authenticate_token.rb +15 -0
- data/sdks/fog/challenges/cdn_enable_container.rb +20 -0
- data/sdks/fog/challenges/create_a_container.rb +17 -0
- data/sdks/fog/challenges/create_server.rb +36 -0
- data/sdks/fog/challenges/get_object_metadata.rb +13 -0
- data/sdks/fog/challenges/list_containers.rb +10 -0
- data/sdks/fog/challenges/provision_scalable_webapp.rb +30 -0
- data/sdks/fog/challenges/upload_folder.rb +25 -0
- data/sdks/fog/scripts/bootstrap +4 -0
- data/sdks/fog/scripts/bootstrap.ps1 +1 -0
- data/sdks/fog/scripts/wrapper +2 -0
- data/sdks/fog/scripts/wrapper.ps1 +1 -0
- data/sdks/gophercloud/.gitignore +2 -0
- data/sdks/gophercloud/challenges/authenticate_token.go +23 -0
- data/sdks/gophercloud/scripts/bootstrap +6 -0
- data/sdks/gophercloud/scripts/wrapper +10 -0
- data/sdks/jclouds/.gitignore +1 -0
- data/sdks/jclouds/challenges/AuthenticateToken.java +115 -0
- data/sdks/jclouds/pom.xml +34 -0
- data/sdks/jclouds/scripts/bootstrap +3 -0
- data/sdks/jclouds/scripts/wrapper +7 -0
- data/sdks/openstack.net/.gitignore +4 -0
- data/sdks/openstack.net/.nuget/Microsoft.Build.dll +0 -0
- data/sdks/openstack.net/.nuget/NuGet.Config +6 -0
- data/sdks/openstack.net/.nuget/NuGet.exe +0 -0
- data/sdks/openstack.net/.nuget/NuGet.targets +136 -0
- data/sdks/openstack.net/Challenge.cs +10 -0
- data/sdks/openstack.net/RunChallenge.cs +19 -0
- data/sdks/openstack.net/challenges/AuthenticateToken.cs +24 -0
- data/sdks/openstack.net/challenges/Weird.cs +133 -0
- data/sdks/openstack.net/openstack.net.csproj +58 -0
- data/sdks/openstack.net/openstack.net.sln +27 -0
- data/sdks/openstack.net/openstack.net.userprefs +8 -0
- data/sdks/openstack.net/packages.config +6 -0
- data/sdks/openstack.net/scripts/bootstrap +2 -0
- data/sdks/openstack.net/scripts/bootstrap.ps1 +2 -0
- data/sdks/openstack.net/scripts/wrapper +7 -0
- data/sdks/openstack.net/scripts/wrapper.ps1 +1 -0
- data/sdks/php-opencloud/.gitignore +4 -0
- data/sdks/php-opencloud/challenges/all_connections.php +64 -0
- data/sdks/php-opencloud/challenges/authenticate_token.php +14 -0
- data/sdks/php-opencloud/challenges/create_server.php +39 -0
- data/sdks/php-opencloud/challenges/get_object_metadata.php +19 -0
- data/sdks/php-opencloud/composer.json +5 -0
- data/sdks/php-opencloud/scripts/bootstrap +4 -0
- data/sdks/php-opencloud/scripts/bootstrap.ps1 +2 -0
- data/sdks/php-opencloud/scripts/wrapper +2 -0
- data/sdks/php-opencloud/scripts/wrapper.ps1 +1 -0
- data/sdks/pkgcloud/.gitignore +1 -0
- data/sdks/pkgcloud/challenges/authenticate_token.js +17 -0
- data/sdks/pkgcloud/challenges/get_object_metadata.js +18 -0
- data/sdks/pkgcloud/scripts/bootstrap +2 -0
- data/sdks/pkgcloud/scripts/bootstrap.ps1 +1 -0
- data/sdks/pkgcloud/scripts/wrapper +2 -0
- data/sdks/pkgcloud/scripts/wrapper.ps1 +1 -0
- data/sdks/pyrax/.gitignore +2 -0
- data/sdks/pyrax/challenges/all_connections.py +61 -0
- data/sdks/pyrax/challenges/authenticate_token.py +17 -0
- data/sdks/pyrax/challenges/cdn_enable_container.py +22 -0
- data/sdks/pyrax/challenges/create_a_container.py +21 -0
- data/sdks/pyrax/challenges/create_server.py +35 -0
- data/sdks/pyrax/challenges/get_object_metadata.py +17 -0
- data/sdks/pyrax/challenges/upload_folder.py +32 -0
- data/sdks/pyrax/requirements.txt +21 -0
- data/sdks/pyrax/scripts/bootstrap +9 -0
- data/sdks/pyrax/scripts/bootstrap.ps1 +7 -0
- data/sdks/pyrax/scripts/wrapper +3 -0
- data/sdks/pyrax/scripts/wrapper.ps1 +2 -0
- data/spec/fixtures/factorial.py +18 -0
- data/spec/fixtures/polytrix.yml +16 -0
- data/spec/fixtures/src-doc/quine.md.erb +20 -0
- data/spec/polytrix/challenge_builder_spec.rb +16 -0
- data/spec/polytrix/challenge_runner_spec.rb +14 -0
- data/spec/polytrix/challenge_spec.rb +20 -0
- data/spec/polytrix/configuration_spec.rb +10 -0
- data/spec/polytrix/documentation_generator_spec.rb +36 -0
- data/spec/polytrix/file_finder_spec.rb +24 -0
- data/spec/polytrix/manifest_spec.rb +26 -0
- data/spec/polytrix/middleware/feature_executor_spec.rb +48 -0
- data/spec/polytrix_spec.rb +13 -0
- data/spec/rspec_spec.rb +17 -0
- data/spec/spec_helper.rb +7 -0
- 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
data/.groc.json
ADDED
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')
|