nucleus 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitattributes +1 -0
- data/.gitignore +19 -0
- data/.rspec +3 -0
- data/.rubocop.yml +44 -0
- data/.travis.yml +21 -0
- data/CHANGELOG.md +19 -0
- data/CONTRIBUTING.md +13 -0
- data/Gemfile +16 -0
- data/Guardfile +22 -0
- data/LICENSE +21 -0
- data/README.md +675 -0
- data/Rakefile +137 -0
- data/bin/nucleus +91 -0
- data/bin/nucleus.bat +1 -0
- data/config.ru +18 -0
- data/config/adapters/cloud_control.yml +32 -0
- data/config/adapters/cloud_foundry_v2.yml +61 -0
- data/config/adapters/heroku.yml +13 -0
- data/config/adapters/openshift_v2.yml +20 -0
- data/config/nucleus_config.rb +47 -0
- data/lib/nucleus.rb +13 -0
- data/lib/nucleus/adapter_resolver.rb +115 -0
- data/lib/nucleus/adapters/base_adapter.rb +109 -0
- data/lib/nucleus/adapters/buildpack_translator.rb +79 -0
- data/lib/nucleus/adapters/v1/cloud_control/application.rb +108 -0
- data/lib/nucleus/adapters/v1/cloud_control/authentication.rb +27 -0
- data/lib/nucleus/adapters/v1/cloud_control/buildpacks.rb +23 -0
- data/lib/nucleus/adapters/v1/cloud_control/cloud_control.rb +153 -0
- data/lib/nucleus/adapters/v1/cloud_control/data.rb +76 -0
- data/lib/nucleus/adapters/v1/cloud_control/domains.rb +68 -0
- data/lib/nucleus/adapters/v1/cloud_control/lifecycle.rb +27 -0
- data/lib/nucleus/adapters/v1/cloud_control/log_poller.rb +71 -0
- data/lib/nucleus/adapters/v1/cloud_control/logs.rb +103 -0
- data/lib/nucleus/adapters/v1/cloud_control/regions.rb +32 -0
- data/lib/nucleus/adapters/v1/cloud_control/scaling.rb +17 -0
- data/lib/nucleus/adapters/v1/cloud_control/semantic_errors.rb +31 -0
- data/lib/nucleus/adapters/v1/cloud_control/services.rb +162 -0
- data/lib/nucleus/adapters/v1/cloud_control/token.rb +17 -0
- data/lib/nucleus/adapters/v1/cloud_control/vars.rb +88 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/app_states.rb +28 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/application.rb +111 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/authentication.rb +17 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/buildpacks.rb +23 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/cloud_foundry_v2.rb +141 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/data.rb +97 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/domains.rb +149 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/lifecycle.rb +41 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/logs.rb +303 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/regions.rb +33 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/scaling.rb +15 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/semantic_errors.rb +27 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/services.rb +286 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/vars.rb +80 -0
- data/lib/nucleus/adapters/v1/heroku/app_states.rb +57 -0
- data/lib/nucleus/adapters/v1/heroku/application.rb +93 -0
- data/lib/nucleus/adapters/v1/heroku/authentication.rb +27 -0
- data/lib/nucleus/adapters/v1/heroku/buildpacks.rb +27 -0
- data/lib/nucleus/adapters/v1/heroku/data.rb +78 -0
- data/lib/nucleus/adapters/v1/heroku/domains.rb +43 -0
- data/lib/nucleus/adapters/v1/heroku/heroku.rb +146 -0
- data/lib/nucleus/adapters/v1/heroku/lifecycle.rb +51 -0
- data/lib/nucleus/adapters/v1/heroku/logs.rb +108 -0
- data/lib/nucleus/adapters/v1/heroku/regions.rb +42 -0
- data/lib/nucleus/adapters/v1/heroku/scaling.rb +28 -0
- data/lib/nucleus/adapters/v1/heroku/semantic_errors.rb +23 -0
- data/lib/nucleus/adapters/v1/heroku/services.rb +168 -0
- data/lib/nucleus/adapters/v1/heroku/vars.rb +65 -0
- data/lib/nucleus/adapters/v1/openshift_v2/app_states.rb +68 -0
- data/lib/nucleus/adapters/v1/openshift_v2/application.rb +108 -0
- data/lib/nucleus/adapters/v1/openshift_v2/authentication.rb +21 -0
- data/lib/nucleus/adapters/v1/openshift_v2/data.rb +96 -0
- data/lib/nucleus/adapters/v1/openshift_v2/domains.rb +37 -0
- data/lib/nucleus/adapters/v1/openshift_v2/lifecycle.rb +60 -0
- data/lib/nucleus/adapters/v1/openshift_v2/logs.rb +106 -0
- data/lib/nucleus/adapters/v1/openshift_v2/openshift_v2.rb +125 -0
- data/lib/nucleus/adapters/v1/openshift_v2/regions.rb +58 -0
- data/lib/nucleus/adapters/v1/openshift_v2/scaling.rb +39 -0
- data/lib/nucleus/adapters/v1/openshift_v2/semantic_errors.rb +40 -0
- data/lib/nucleus/adapters/v1/openshift_v2/services.rb +173 -0
- data/lib/nucleus/adapters/v1/openshift_v2/vars.rb +49 -0
- data/lib/nucleus/adapters/v1/stub_adapter.rb +464 -0
- data/lib/nucleus/core/adapter_authentication_inductor.rb +62 -0
- data/lib/nucleus/core/adapter_extensions/auth/auth_client.rb +44 -0
- data/lib/nucleus/core/adapter_extensions/auth/authentication_retry_wrapper.rb +79 -0
- data/lib/nucleus/core/adapter_extensions/auth/expiring_token_auth_client.rb +53 -0
- data/lib/nucleus/core/adapter_extensions/auth/http_basic_auth_client.rb +37 -0
- data/lib/nucleus/core/adapter_extensions/auth/o_auth2_auth_client.rb +95 -0
- data/lib/nucleus/core/adapter_extensions/auth/token_auth_client.rb +36 -0
- data/lib/nucleus/core/adapter_extensions/http_client.rb +177 -0
- data/lib/nucleus/core/adapter_extensions/http_tail_client.rb +26 -0
- data/lib/nucleus/core/adapter_extensions/tail_stopper.rb +25 -0
- data/lib/nucleus/core/common/errors/ambiguous_adapter_error.rb +7 -0
- data/lib/nucleus/core/common/errors/file_existence_error.rb +7 -0
- data/lib/nucleus/core/common/errors/startup_error.rb +12 -0
- data/lib/nucleus/core/common/exit_codes.rb +25 -0
- data/lib/nucleus/core/common/files/application_repo_sanitizer.rb +52 -0
- data/lib/nucleus/core/common/files/archive_extractor.rb +112 -0
- data/lib/nucleus/core/common/files/archiver.rb +91 -0
- data/lib/nucleus/core/common/link_generator.rb +46 -0
- data/lib/nucleus/core/common/logging/logging.rb +52 -0
- data/lib/nucleus/core/common/logging/multi_logger.rb +59 -0
- data/lib/nucleus/core/common/logging/request_log_formatter.rb +48 -0
- data/lib/nucleus/core/common/ssh_handler.rb +108 -0
- data/lib/nucleus/core/common/stream_callback.rb +27 -0
- data/lib/nucleus/core/common/thread_config_accessor.rb +85 -0
- data/lib/nucleus/core/common/url_converter.rb +28 -0
- data/lib/nucleus/core/enums/application_states.rb +26 -0
- data/lib/nucleus/core/enums/logfile_types.rb +28 -0
- data/lib/nucleus/core/error_messages.rb +127 -0
- data/lib/nucleus/core/errors/adapter_error.rb +13 -0
- data/lib/nucleus/core/errors/adapter_missing_implementation_error.rb +12 -0
- data/lib/nucleus/core/errors/adapter_request_error.rb +10 -0
- data/lib/nucleus/core/errors/adapter_resource_not_found_error.rb +10 -0
- data/lib/nucleus/core/errors/endpoint_authentication_error.rb +10 -0
- data/lib/nucleus/core/errors/platform_specific_semantic_error.rb +12 -0
- data/lib/nucleus/core/errors/platform_timeout_error.rb +10 -0
- data/lib/nucleus/core/errors/platform_unavailable_error.rb +10 -0
- data/lib/nucleus/core/errors/semantic_adapter_request_error.rb +19 -0
- data/lib/nucleus/core/errors/unknown_adapter_call_error.rb +10 -0
- data/lib/nucleus/core/file_handling/archive_converter.rb +29 -0
- data/lib/nucleus/core/file_handling/file_manager.rb +64 -0
- data/lib/nucleus/core/file_handling/git_deployer.rb +133 -0
- data/lib/nucleus/core/file_handling/git_repo_analyzer.rb +23 -0
- data/lib/nucleus/core/import/adapter_configuration.rb +53 -0
- data/lib/nucleus/core/import/vendor_parser.rb +28 -0
- data/lib/nucleus/core/import/version_detector.rb +18 -0
- data/lib/nucleus/core/models/abstract_model.rb +29 -0
- data/lib/nucleus/core/models/endpoint.rb +30 -0
- data/lib/nucleus/core/models/provider.rb +26 -0
- data/lib/nucleus/core/models/vendor.rb +22 -0
- data/lib/nucleus/ext/kernel.rb +5 -0
- data/lib/nucleus/ext/regexp.rb +49 -0
- data/lib/nucleus/os.rb +15 -0
- data/lib/nucleus/root_dir.rb +13 -0
- data/lib/nucleus/scripts/finalize.rb +8 -0
- data/lib/nucleus/scripts/initialize.rb +9 -0
- data/lib/nucleus/scripts/initialize_config_defaults.rb +26 -0
- data/lib/nucleus/scripts/load.rb +17 -0
- data/lib/nucleus/scripts/load_dependencies.rb +43 -0
- data/lib/nucleus/scripts/setup_config.rb +28 -0
- data/lib/nucleus/scripts/shutdown.rb +11 -0
- data/lib/nucleus/version.rb +3 -0
- data/nucleus.gemspec +88 -0
- data/public/robots.txt +2 -0
- data/public/swagger-ui/css/reset.css +125 -0
- data/public/swagger-ui/css/screen.css +1224 -0
- data/public/swagger-ui/images/apple-touch-icon-114x114.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-120x120.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-144x144.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-152x152.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-57x57.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-60x60.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-72x72.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-76x76.png +0 -0
- data/public/swagger-ui/images/explorer_icons.png +0 -0
- data/public/swagger-ui/images/favicon-128.png +0 -0
- data/public/swagger-ui/images/favicon-16x16.png +0 -0
- data/public/swagger-ui/images/favicon-196x196.png +0 -0
- data/public/swagger-ui/images/favicon-32x32.png +0 -0
- data/public/swagger-ui/images/favicon-96x96.png +0 -0
- data/public/swagger-ui/images/favicon.ico +0 -0
- data/public/swagger-ui/images/logo_small.png +0 -0
- data/public/swagger-ui/images/mstile-144x144.png +0 -0
- data/public/swagger-ui/images/mstile-150x150.png +0 -0
- data/public/swagger-ui/images/mstile-310x150.png +0 -0
- data/public/swagger-ui/images/mstile-310x310.png +0 -0
- data/public/swagger-ui/images/mstile-70x70.png +0 -0
- data/public/swagger-ui/images/pet_store_api.png +0 -0
- data/public/swagger-ui/images/throbber.gif +0 -0
- data/public/swagger-ui/images/wordnik_api.png +0 -0
- data/public/swagger-ui/index.html +107 -0
- data/public/swagger-ui/lib/backbone-min.js +38 -0
- data/public/swagger-ui/lib/handlebars-1.0.0.js +2278 -0
- data/public/swagger-ui/lib/highlight.7.3.pack.js +1 -0
- data/public/swagger-ui/lib/jquery-1.8.0.min.js +2 -0
- data/public/swagger-ui/lib/jquery.ba-bbq.min.js +18 -0
- data/public/swagger-ui/lib/jquery.slideto.min.js +1 -0
- data/public/swagger-ui/lib/jquery.wiggle.min.js +8 -0
- data/public/swagger-ui/lib/shred.bundle.js +2765 -0
- data/public/swagger-ui/lib/shred/content.js +193 -0
- data/public/swagger-ui/lib/swagger-oauth.js +211 -0
- data/public/swagger-ui/lib/swagger.js +1653 -0
- data/public/swagger-ui/lib/underscore-min.js +32 -0
- data/public/swagger-ui/o2c.html +15 -0
- data/public/swagger-ui/redirect.html +14 -0
- data/public/swagger-ui/swagger-ui.js +2324 -0
- data/public/swagger-ui/swagger-ui.min.js +1 -0
- data/schemas/api.adapter.schema.yml +31 -0
- data/schemas/api.requirements.schema.yml +17 -0
- data/spec/factories/models.rb +61 -0
- data/spec/integration/api/auth_spec.rb +58 -0
- data/spec/integration/api/endpoints_spec.rb +167 -0
- data/spec/integration/api/errors_spec.rb +47 -0
- data/spec/integration/api/providers_spec.rb +157 -0
- data/spec/integration/api/swagger_schema_spec.rb +64 -0
- data/spec/integration/api/vendors_spec.rb +45 -0
- data/spec/integration/integration_spec_helper.rb +27 -0
- data/spec/integration/test_data_generator.rb +55 -0
- data/spec/nucleus_git_key.pem +51 -0
- data/spec/spec_helper.rb +98 -0
- data/spec/support/shared_example_request_types.rb +99 -0
- data/spec/test_suites.rake +31 -0
- data/spec/unit/adapters/archive_converter_spec.rb +25 -0
- data/spec/unit/adapters/file_manager_spec.rb +93 -0
- data/spec/unit/adapters/git_deployer_spec.rb +262 -0
- data/spec/unit/adapters/v1/stub_spec.rb +14 -0
- data/spec/unit/common/helpers/auth_helper_spec.rb +73 -0
- data/spec/unit/common/oauth2_auth_client_spec.rb +108 -0
- data/spec/unit/common/regexp_spec.rb +33 -0
- data/spec/unit/common/request_log_formatter_spec.rb +108 -0
- data/spec/unit/common/thread_config_accessor_spec.rb +97 -0
- data/spec/unit/models/endpoint_spec.rb +83 -0
- data/spec/unit/models/provider_spec.rb +102 -0
- data/spec/unit/models/vendor_spec.rb +100 -0
- data/spec/unit/schemas/adapter_schema_spec.rb +16 -0
- data/spec/unit/schemas/adapter_validation_spec.rb +56 -0
- data/spec/unit/schemas/requirements_schema_spec.rb +16 -0
- data/spec/unit/unit_spec_helper.rb +11 -0
- data/tasks/compatibility.rake +113 -0
- data/tasks/evaluation.rake +162 -0
- data/wiki/adapter_tests.md +99 -0
- data/wiki/implement_new_adapter.md +155 -0
- metadata +836 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'spec/unit/unit_spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Nucleus::Vendor do
|
|
4
|
+
let(:id) { '12345' }
|
|
5
|
+
let(:name) { 'fake vendor name' }
|
|
6
|
+
let(:created_at) { Time.now }
|
|
7
|
+
let(:updated_at) { Time.now.to_s }
|
|
8
|
+
|
|
9
|
+
describe 'can be initialized with' do
|
|
10
|
+
context 'an empty hash and' do
|
|
11
|
+
before do
|
|
12
|
+
@vendor = Nucleus::Vendor.new({})
|
|
13
|
+
end
|
|
14
|
+
it 'providers are empty' do
|
|
15
|
+
expect(@vendor.providers).to eql([])
|
|
16
|
+
end
|
|
17
|
+
it 'fields are empty' do
|
|
18
|
+
expect(@vendor.id).to be_nil
|
|
19
|
+
expect(@vendor.name).to be_nil
|
|
20
|
+
expect(@vendor.created_at).to be_nil
|
|
21
|
+
expect(@vendor.updated_at).to be_nil
|
|
22
|
+
end
|
|
23
|
+
it 'to_s does not crash' do
|
|
24
|
+
expect { @vendor.to_s }.to_not raise_error
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'nil and' do
|
|
29
|
+
before do
|
|
30
|
+
@vendor = Nucleus::Vendor.new
|
|
31
|
+
end
|
|
32
|
+
it 'providers are empty' do
|
|
33
|
+
expect(@vendor.providers).to eql([])
|
|
34
|
+
end
|
|
35
|
+
it 'fields are empty' do
|
|
36
|
+
expect(@vendor.id).to be_nil
|
|
37
|
+
expect(@vendor.name).to be_nil
|
|
38
|
+
expect(@vendor.created_at).to be_nil
|
|
39
|
+
expect(@vendor.updated_at).to be_nil
|
|
40
|
+
end
|
|
41
|
+
it 'to_s does not crash' do
|
|
42
|
+
expect { @vendor.to_s }.to_not raise_error
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'hash properties and provider double' do
|
|
47
|
+
before do
|
|
48
|
+
provider = instance_double('Nucleus::Provider', name: 'provider name')
|
|
49
|
+
allow(provider).to receive(:is_a?).with(Nucleus::Provider).and_return(true)
|
|
50
|
+
@vendor = Nucleus::Vendor.new('providers' => [provider], 'id' => id, 'name' => name,
|
|
51
|
+
'created_at' => created_at, 'updated_at' => updated_at)
|
|
52
|
+
end
|
|
53
|
+
it 'has one provider' do
|
|
54
|
+
expect(@vendor.providers).to_not eql([])
|
|
55
|
+
expect(@vendor.providers.length).to eql(1)
|
|
56
|
+
end
|
|
57
|
+
it 'fields are not nil' do
|
|
58
|
+
expect(@vendor.id).to_not be_nil
|
|
59
|
+
expect(@vendor.name).to_not be_nil
|
|
60
|
+
end
|
|
61
|
+
it 'dates wont be applied' do
|
|
62
|
+
expect(@vendor.created_at).to be_nil
|
|
63
|
+
expect(@vendor.updated_at).to be_nil
|
|
64
|
+
end
|
|
65
|
+
it 'fields have the valid values assigned' do
|
|
66
|
+
expect(@vendor.id).to eql(id)
|
|
67
|
+
expect(@vendor.name).to eql(name)
|
|
68
|
+
end
|
|
69
|
+
it 'to_s does not crash' do
|
|
70
|
+
expect { @vendor.to_s }.to_not raise_error
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context 'hash properties and provider hash' do
|
|
75
|
+
before do
|
|
76
|
+
@vendor = Nucleus::Vendor.new('providers' => [{ 'name' => 'provider name' }], 'id' => id, 'name' => name,
|
|
77
|
+
'created_at' => created_at, 'updated_at' => updated_at)
|
|
78
|
+
end
|
|
79
|
+
it 'has one provider' do
|
|
80
|
+
expect(@vendor.providers).to_not eql([])
|
|
81
|
+
expect(@vendor.providers.length).to eql(1)
|
|
82
|
+
end
|
|
83
|
+
it 'fields are not nil' do
|
|
84
|
+
expect(@vendor.id).to_not be_nil
|
|
85
|
+
expect(@vendor.name).to_not be_nil
|
|
86
|
+
end
|
|
87
|
+
it 'dates wont be applied' do
|
|
88
|
+
expect(@vendor.created_at).to be_nil
|
|
89
|
+
expect(@vendor.updated_at).to be_nil
|
|
90
|
+
end
|
|
91
|
+
it 'fields have the valid values assigned' do
|
|
92
|
+
expect(@vendor.id).to eql(id)
|
|
93
|
+
expect(@vendor.name).to eql(name)
|
|
94
|
+
end
|
|
95
|
+
it 'to_s does not crash' do
|
|
96
|
+
expect { @vendor.to_s }.to_not raise_error
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'spec/unit/unit_spec_helper'
|
|
2
|
+
require 'kwalify'
|
|
3
|
+
|
|
4
|
+
describe 'YAML adapter schema' do
|
|
5
|
+
before :all do
|
|
6
|
+
meta_validator = Kwalify::MetaValidator.instance
|
|
7
|
+
@parser = Kwalify::Yaml::Parser.new(meta_validator)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'does not produce errors' do
|
|
11
|
+
# NOTE may not work with different working dir
|
|
12
|
+
@parser.parse_file(File.expand_path('schemas/api.adapter.schema.yml'))
|
|
13
|
+
errors = @parser.errors
|
|
14
|
+
expect(errors).to match_array([])
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'spec/unit/unit_spec_helper'
|
|
2
|
+
require 'kwalify'
|
|
3
|
+
|
|
4
|
+
describe 'Nucleus::Adapters' do
|
|
5
|
+
Nucleus::VersionDetector.api_versions.each do |api_version|
|
|
6
|
+
describe "API #{api_version}" do
|
|
7
|
+
it 'has valid adapter requirements' do
|
|
8
|
+
expect(Nucleus::API.requirements(api_version)).to_not be_nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe 'configuration' do
|
|
12
|
+
Nucleus::Adapters.configuration_files.each do |file|
|
|
13
|
+
adapter_clazz = Nucleus::Adapters.adapter_clazz(file, api_version)
|
|
14
|
+
# adapter must not be available for each version (!)
|
|
15
|
+
next unless adapter_clazz
|
|
16
|
+
describe File.basename(file) do
|
|
17
|
+
it 'is a valid adapter configuration' do
|
|
18
|
+
expect(Nucleus::VendorParser.parse(file)).to_not be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
let!(:adapter) { adapter_clazz.new 'https://api.example.org' }
|
|
22
|
+
if Nucleus::API.requirements(api_version)
|
|
23
|
+
Nucleus::API.requirements(api_version).methods.each do |required_method|
|
|
24
|
+
describe "method #{required_method.name}" do
|
|
25
|
+
it 'is implemented' do
|
|
26
|
+
expect(adapter).to respond_to(required_method.name)
|
|
27
|
+
end
|
|
28
|
+
it 'has required arity' do
|
|
29
|
+
expect(adapter).to respond_to(required_method.name).with(required_method.arguments).arguments
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe 'adapter stub' do
|
|
39
|
+
stub_clazz = Object.const_get('Nucleus').const_get('Adapters').const_get(api_version.upcase).const_get('Stub')
|
|
40
|
+
let!(:adapter) { stub_clazz.new 'https://api.example.org' }
|
|
41
|
+
if Nucleus::API.requirements(api_version)
|
|
42
|
+
Nucleus::API.requirements(api_version).methods.each do |required_method|
|
|
43
|
+
describe "method #{required_method.name}" do
|
|
44
|
+
it 'is implemented' do
|
|
45
|
+
expect(adapter).to respond_to(required_method.name)
|
|
46
|
+
end
|
|
47
|
+
it 'has required arity' do
|
|
48
|
+
expect(adapter).to respond_to(required_method.name).with(required_method.arguments).arguments
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'spec/unit/unit_spec_helper'
|
|
2
|
+
require 'kwalify'
|
|
3
|
+
|
|
4
|
+
describe 'YAML requirements schema' do
|
|
5
|
+
before :all do
|
|
6
|
+
meta_validator = Kwalify::MetaValidator.instance
|
|
7
|
+
@parser = Kwalify::Yaml::Parser.new(meta_validator)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'does not produce errors' do
|
|
11
|
+
# NOTE may not work with different working dir
|
|
12
|
+
@parser.parse_file(File.expand_path('schemas/api.requirements.schema.yml'))
|
|
13
|
+
errors = @parser.errors
|
|
14
|
+
expect(errors).to match_array([])
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
require 'rspec/core/rake_task'
|
|
2
|
+
|
|
3
|
+
namespace :evaluation do
|
|
4
|
+
namespace :compatibility do
|
|
5
|
+
task load: :environment do
|
|
6
|
+
# TODO: choose API version
|
|
7
|
+
api_version = 'v1'
|
|
8
|
+
stub = Nucleus::Adapters.const_get(api_version.upcase).const_get('Stub').new 'https://api.example.org'
|
|
9
|
+
|
|
10
|
+
adapter_dao = Nucleus::API::DB::AdapterDao.instance(api_version)
|
|
11
|
+
endpoint_dao = Nucleus::API::DB::EndpointDao.instance(api_version)
|
|
12
|
+
provider_dao = Nucleus::API::DB::ProviderDao.instance(api_version)
|
|
13
|
+
vendor_dao = Nucleus::API::DB::VendorDao.instance(api_version)
|
|
14
|
+
@vendor_results = {}
|
|
15
|
+
|
|
16
|
+
adapter_dao.all.each do |adapter_index_entry|
|
|
17
|
+
vendor_name = vendor_dao.get(provider_dao.get(endpoint_dao.get(adapter_index_entry.id).provider).vendor).name
|
|
18
|
+
next if @vendor_results.key?(vendor_name)
|
|
19
|
+
adapter_results = {}
|
|
20
|
+
adapter = adapter_index_entry.adapter_clazz.new('https://api.example.org', 'http://apps.example.org', true)
|
|
21
|
+
stub.public_methods(false).each do |method_name|
|
|
22
|
+
args = []
|
|
23
|
+
method = stub.method(method_name)
|
|
24
|
+
method.arity.times { |time| args.push(time) }
|
|
25
|
+
begin
|
|
26
|
+
adapter.send(method_name, *args)
|
|
27
|
+
implemented = true
|
|
28
|
+
rescue Nucleus::Errors::AdapterMissingImplementationError
|
|
29
|
+
implemented = false
|
|
30
|
+
rescue StandardError
|
|
31
|
+
implemented = true
|
|
32
|
+
end
|
|
33
|
+
adapter_results[method_name] = implemented
|
|
34
|
+
end
|
|
35
|
+
@vendor_results[vendor_name] = adapter_results
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
task markdown: :load do
|
|
40
|
+
# table header
|
|
41
|
+
puts "Method / Vendor|#{@vendor_results.keys.join('|')}"
|
|
42
|
+
|
|
43
|
+
# column styles
|
|
44
|
+
alignment = ':--'
|
|
45
|
+
@vendor_results.length.times { |_time| alignment << '|:-:' }
|
|
46
|
+
puts alignment
|
|
47
|
+
|
|
48
|
+
lines = []
|
|
49
|
+
@vendor_results.each do |_vendor, results|
|
|
50
|
+
results.each_with_index do |(method, supported), line|
|
|
51
|
+
lines[line] = "#{method}" unless lines[line]
|
|
52
|
+
lines[line] << "|#{supported ? '✓' : '✗'}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
lines.each do |line|
|
|
57
|
+
puts line
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
task :latex, [:save_to] => :load do |_t, args|
|
|
62
|
+
all_lines = []
|
|
63
|
+
all_lines << "\\begin{longtable}{|L{7cm}|#{'c|' * @vendor_results.length}}"
|
|
64
|
+
next_line = ' \\multicolumn{1}{l}{\\Large{\\textbf{Adapter compatibility}}}'
|
|
65
|
+
@vendor_results.keys.each do |vendor|
|
|
66
|
+
next_line += " & \\multicolumn{1}{l}{\\turn{60}{#{vendor}}}"
|
|
67
|
+
end
|
|
68
|
+
next_line += ' \\\\\\hline'
|
|
69
|
+
all_lines << next_line
|
|
70
|
+
all_lines << ' \\endhead'
|
|
71
|
+
all_lines << ' \\rowcolor{white}'
|
|
72
|
+
all_lines << ' \\caption{List of methods that are supported by Nucleus per vendor}'\
|
|
73
|
+
'\\label{table:evaluation_adapter_compatibility}%'
|
|
74
|
+
all_lines << ' \\endlastfoot'
|
|
75
|
+
|
|
76
|
+
lines = []
|
|
77
|
+
@vendor_results.each do |_vendor, results|
|
|
78
|
+
results.each_with_index do |(method, supported), line|
|
|
79
|
+
lines[line] = "#{method}" unless lines[line]
|
|
80
|
+
lines[line] << " & #{supported ? '\\ding{51}' : '\\cellcolor{failedtablebg}\\ding{55}'}"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# format and print all lines
|
|
85
|
+
lines.each_with_index do |line, index|
|
|
86
|
+
if index != lines.length - 1
|
|
87
|
+
all_lines << " #{line.gsub(/_/, '\_')} \\\\\\hline"
|
|
88
|
+
else
|
|
89
|
+
# special treatment for the last line
|
|
90
|
+
all_lines << " #{line.gsub(/_/, '\_')} \\\\\\hhline{|=|#{'=|' * @vendor_results.length}}"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# print general statistics
|
|
95
|
+
total_methods = @vendor_results.collect { |_v, tests| tests.length }.uniq.first
|
|
96
|
+
supported_count = @vendor_results.collect { |_v, tests| tests.find_all { |_m, s| s }.length }
|
|
97
|
+
all_lines << " Supported methods & #{supported_count.join(' & ')} \\\\\\hline"
|
|
98
|
+
to_print = supported_count.collect do |supported|
|
|
99
|
+
"#{format('%g', format('%.1f', (supported / total_methods.to_f * 100)))} \\%"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
all_lines << " Supported degree & #{to_print.join(' & ')} \\\\\\hline"
|
|
103
|
+
|
|
104
|
+
all_lines << '\\end{longtable}'
|
|
105
|
+
|
|
106
|
+
# print lines
|
|
107
|
+
all_lines.each { |line| puts line }
|
|
108
|
+
|
|
109
|
+
# and save to file if requested
|
|
110
|
+
File.open(args.save_to, 'w') { |file| file.write all_lines.join("\n") } if args.save_to
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
require 'rspec/core/rake_task'
|
|
2
|
+
require 'oj'
|
|
3
|
+
|
|
4
|
+
namespace :evaluation do
|
|
5
|
+
namespace :requests do
|
|
6
|
+
namespace :count do
|
|
7
|
+
desc 'Load the data that will be used in the request evaluation tasks'
|
|
8
|
+
task load: :environment do
|
|
9
|
+
# TODO: choose API version
|
|
10
|
+
api_version = 'v1'
|
|
11
|
+
|
|
12
|
+
adapter_dao = Nucleus::API::DB::AdapterDao.instance(api_version)
|
|
13
|
+
endpoint_dao = Nucleus::API::DB::EndpointDao.instance(api_version)
|
|
14
|
+
provider_dao = Nucleus::API::DB::ProviderDao.instance(api_version)
|
|
15
|
+
vendor_dao = Nucleus::API::DB::VendorDao.instance(api_version)
|
|
16
|
+
@vendor_results = {}
|
|
17
|
+
|
|
18
|
+
adapter_dao.all.each do |adapter_index_entry|
|
|
19
|
+
vendor_name = vendor_dao.get(provider_dao.get(endpoint_dao.get(adapter_index_entry.id).provider).vendor).name
|
|
20
|
+
# from camel to sneak case
|
|
21
|
+
adapter_file_name = vendor_name.gsub(/\s/, '_').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
|
22
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
|
|
23
|
+
next if @vendor_results.key?(vendor_name)
|
|
24
|
+
adaper_results = {}
|
|
25
|
+
|
|
26
|
+
method_recordings_dir = File.join('spec', 'adapter', 'recordings', api_version, adapter_file_name,
|
|
27
|
+
'vcr_cassettes', 'with_valid_credentials', 'is_compliant_and')
|
|
28
|
+
Find.find(method_recordings_dir) do |file|
|
|
29
|
+
next if File.directory?(file) || File.basename(file) == '.DS_Store'
|
|
30
|
+
test = Pathname.new(file).relative_path_from(Pathname.new(method_recordings_dir)).to_s
|
|
31
|
+
# Load contents with the serializer, oj
|
|
32
|
+
cassette = ::Oj.load(File.read(file))
|
|
33
|
+
adaper_results[test] = cassette['http_interactions'].length
|
|
34
|
+
end
|
|
35
|
+
@vendor_results[vendor_name] = adaper_results
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
@all_tests = @vendor_results.flat_map { |_name, tests| tests.keys }.uniq
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
task markdown: :load do
|
|
42
|
+
# table header
|
|
43
|
+
puts "Test / Vendor|#{@vendor_results.keys.join('|')}"
|
|
44
|
+
|
|
45
|
+
# column styles
|
|
46
|
+
alignment = ':--'
|
|
47
|
+
@vendor_results.length.times { |_time| alignment << '|:-:' }
|
|
48
|
+
puts alignment
|
|
49
|
+
|
|
50
|
+
lines = []
|
|
51
|
+
@all_tests.sort.each_with_index do |test_name, line|
|
|
52
|
+
@vendor_results.each do |_vendor, results|
|
|
53
|
+
lines[line] = "#{test_name}" unless lines[line]
|
|
54
|
+
lines[line] << "|#{results[test_name]}"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
lines.each do |line|
|
|
59
|
+
puts line
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# table header
|
|
63
|
+
puts '|' * @vendor_results.length
|
|
64
|
+
puts "Test / Vendor|#{@vendor_results.keys.join('|')}"
|
|
65
|
+
puts '|' * @vendor_results.length
|
|
66
|
+
puts "Tested methods|#{@vendor_results.collect { |_name, tests| tests.length }.join('|')}"
|
|
67
|
+
puts "Total vendor API requests|#{@vendor_results.collect do |_name, tests|
|
|
68
|
+
tests.map { |_key, value| value }.sum
|
|
69
|
+
end.join('|')}"
|
|
70
|
+
puts "Avg. vendor API requests per tested method|#{@vendor_results.collect do |_name, tests|
|
|
71
|
+
((tests.map { |_key, value| value }.sum) / tests.length.to_f).round(2)
|
|
72
|
+
end.join('|')}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
task :latex, [:save_to] => :load do |_t, args|
|
|
76
|
+
tests_with_wait = %w(app-actions/lifecycle/restart/succeeds
|
|
77
|
+
app-actions/lifecycle/start/succeeds_for_app_all_if_currently_stopped
|
|
78
|
+
app-actions/lifecycle/start/succeeds_for_app_min_if_currently_stopped
|
|
79
|
+
app-actions/lifecycle/stop/succeeds_for_app_all_if_currently_running
|
|
80
|
+
app-actions/lifecycle/stop/succeeds_for_app_min_if_currently_running
|
|
81
|
+
app-data/deploy/succeeds/and_app_with
|
|
82
|
+
app-data/rebuild/changes_the_release_version_property
|
|
83
|
+
app/web access/for_app_with_min_properties)
|
|
84
|
+
ignore_tests_with_wait = 0
|
|
85
|
+
ignore_req_with_wait = {}
|
|
86
|
+
@vendor_results.each { |vendor, _| ignore_req_with_wait[vendor] = 0 }
|
|
87
|
+
|
|
88
|
+
table = []
|
|
89
|
+
table << '\\scriptsize'
|
|
90
|
+
table << "\\begin{longtable}{|L{12cm}|#{'c|' * @vendor_results.length}}"
|
|
91
|
+
next_line = ' \\multicolumn{1}{l}{\\Large{\\textbf{recorded test cassette}}}'
|
|
92
|
+
@vendor_results.keys.each do |vendor|
|
|
93
|
+
next_line += " & \\multicolumn{1}{l}{\\turn{60}{#{vendor}}}"
|
|
94
|
+
end
|
|
95
|
+
next_line += ' \\\\\\hline'
|
|
96
|
+
table << next_line
|
|
97
|
+
table << ' \\endhead'
|
|
98
|
+
table << ' \\rowcolor{white}'
|
|
99
|
+
table << ' \\caption{Requests per method test case for all vendors}'\
|
|
100
|
+
'\\label{table:evaluation_request_count}%'
|
|
101
|
+
table << ' \\endlastfoot'
|
|
102
|
+
|
|
103
|
+
lines = []
|
|
104
|
+
@all_tests.sort.each_with_index do |t_name, line|
|
|
105
|
+
@vendor_results.each do |v, results|
|
|
106
|
+
unless lines[line]
|
|
107
|
+
lines[line] = "#{t_name}"
|
|
108
|
+
if tests_with_wait.any? { |name| t_name.start_with?(name) }
|
|
109
|
+
ignore_tests_with_wait += 1
|
|
110
|
+
lines[line] = "\\rowcolor{failedtablebg}#{lines[line]}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
ignore_req_with_wait[v] += results[t_name].to_i if tests_with_wait.any? { |name| t_name.start_with?(name) }
|
|
114
|
+
lines[line] << " & #{results[t_name]}"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# format and print all lines
|
|
119
|
+
lines.each_with_index do |line, index|
|
|
120
|
+
if index != lines.length - 1
|
|
121
|
+
table << " #{line.gsub(/_/, '\_')} \\\\\\hline"
|
|
122
|
+
else
|
|
123
|
+
# special treatment for the last line
|
|
124
|
+
table << " #{line.gsub(/_/, '\_')} \\\\\\hhline{|=|#{'=|' * @vendor_results.length}}"
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# print general statistics
|
|
129
|
+
table << " Tested methods & #{@vendor_results.collect { |_n, tests| tests.length }.join(' & ')} \\\\\\hline"
|
|
130
|
+
table << " Total vendor API requests & #{@vendor_results.collect do |_name, tests|
|
|
131
|
+
tests.map { |_key, value| value }.sum
|
|
132
|
+
end.join(' & ')} \\\\\\hline"
|
|
133
|
+
table << " Avg. vendor API requests per tested method & #{@vendor_results.collect do |_name, tests|
|
|
134
|
+
((tests.map { |_key, value| value }.sum) / tests.length.to_f).round(2)
|
|
135
|
+
end.join(' & ')} \\\\\\hhline{|=|#{'=|' * @vendor_results.length}}"
|
|
136
|
+
|
|
137
|
+
# sanitize stats, exclude methods with rspec wait repetitions
|
|
138
|
+
table << " Tested methods without repeated requests & #{@vendor_results.collect do |_n, tests|
|
|
139
|
+
tests.length - ignore_tests_with_wait
|
|
140
|
+
end.join(' & ')} \\\\\\hline"
|
|
141
|
+
|
|
142
|
+
table << " Total vendor API requests without repeated requests & #{@vendor_results.collect do |name, tests|
|
|
143
|
+
tests.map { |_key, value| value }.sum - ignore_req_with_wait[name]
|
|
144
|
+
end.join(' & ')} \\\\\\hline"
|
|
145
|
+
table << ' Avg. vendor API requests per tested method without repeated requests & '\
|
|
146
|
+
"#{@vendor_results.collect do |name, tests|
|
|
147
|
+
((tests.map { |_key, value| value }.sum - ignore_req_with_wait[name]) /
|
|
148
|
+
(tests.length - ignore_tests_with_wait).to_f).round(2)
|
|
149
|
+
end.join(' & ')} \\\\\\hline"
|
|
150
|
+
|
|
151
|
+
table << '\\end{longtable}'
|
|
152
|
+
table << '\\normalsize'
|
|
153
|
+
|
|
154
|
+
# print lines
|
|
155
|
+
table.each { |line| puts line }
|
|
156
|
+
|
|
157
|
+
# and save to file if requested
|
|
158
|
+
File.open(args.save_to, 'w') { |file| file.write table.join("\n") } if args.save_to
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|