nucleus 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (224) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +44 -0
  6. data/.travis.yml +21 -0
  7. data/CHANGELOG.md +19 -0
  8. data/CONTRIBUTING.md +13 -0
  9. data/Gemfile +16 -0
  10. data/Guardfile +22 -0
  11. data/LICENSE +21 -0
  12. data/README.md +675 -0
  13. data/Rakefile +137 -0
  14. data/bin/nucleus +91 -0
  15. data/bin/nucleus.bat +1 -0
  16. data/config.ru +18 -0
  17. data/config/adapters/cloud_control.yml +32 -0
  18. data/config/adapters/cloud_foundry_v2.yml +61 -0
  19. data/config/adapters/heroku.yml +13 -0
  20. data/config/adapters/openshift_v2.yml +20 -0
  21. data/config/nucleus_config.rb +47 -0
  22. data/lib/nucleus.rb +13 -0
  23. data/lib/nucleus/adapter_resolver.rb +115 -0
  24. data/lib/nucleus/adapters/base_adapter.rb +109 -0
  25. data/lib/nucleus/adapters/buildpack_translator.rb +79 -0
  26. data/lib/nucleus/adapters/v1/cloud_control/application.rb +108 -0
  27. data/lib/nucleus/adapters/v1/cloud_control/authentication.rb +27 -0
  28. data/lib/nucleus/adapters/v1/cloud_control/buildpacks.rb +23 -0
  29. data/lib/nucleus/adapters/v1/cloud_control/cloud_control.rb +153 -0
  30. data/lib/nucleus/adapters/v1/cloud_control/data.rb +76 -0
  31. data/lib/nucleus/adapters/v1/cloud_control/domains.rb +68 -0
  32. data/lib/nucleus/adapters/v1/cloud_control/lifecycle.rb +27 -0
  33. data/lib/nucleus/adapters/v1/cloud_control/log_poller.rb +71 -0
  34. data/lib/nucleus/adapters/v1/cloud_control/logs.rb +103 -0
  35. data/lib/nucleus/adapters/v1/cloud_control/regions.rb +32 -0
  36. data/lib/nucleus/adapters/v1/cloud_control/scaling.rb +17 -0
  37. data/lib/nucleus/adapters/v1/cloud_control/semantic_errors.rb +31 -0
  38. data/lib/nucleus/adapters/v1/cloud_control/services.rb +162 -0
  39. data/lib/nucleus/adapters/v1/cloud_control/token.rb +17 -0
  40. data/lib/nucleus/adapters/v1/cloud_control/vars.rb +88 -0
  41. data/lib/nucleus/adapters/v1/cloud_foundry_v2/app_states.rb +28 -0
  42. data/lib/nucleus/adapters/v1/cloud_foundry_v2/application.rb +111 -0
  43. data/lib/nucleus/adapters/v1/cloud_foundry_v2/authentication.rb +17 -0
  44. data/lib/nucleus/adapters/v1/cloud_foundry_v2/buildpacks.rb +23 -0
  45. data/lib/nucleus/adapters/v1/cloud_foundry_v2/cloud_foundry_v2.rb +141 -0
  46. data/lib/nucleus/adapters/v1/cloud_foundry_v2/data.rb +97 -0
  47. data/lib/nucleus/adapters/v1/cloud_foundry_v2/domains.rb +149 -0
  48. data/lib/nucleus/adapters/v1/cloud_foundry_v2/lifecycle.rb +41 -0
  49. data/lib/nucleus/adapters/v1/cloud_foundry_v2/logs.rb +303 -0
  50. data/lib/nucleus/adapters/v1/cloud_foundry_v2/regions.rb +33 -0
  51. data/lib/nucleus/adapters/v1/cloud_foundry_v2/scaling.rb +15 -0
  52. data/lib/nucleus/adapters/v1/cloud_foundry_v2/semantic_errors.rb +27 -0
  53. data/lib/nucleus/adapters/v1/cloud_foundry_v2/services.rb +286 -0
  54. data/lib/nucleus/adapters/v1/cloud_foundry_v2/vars.rb +80 -0
  55. data/lib/nucleus/adapters/v1/heroku/app_states.rb +57 -0
  56. data/lib/nucleus/adapters/v1/heroku/application.rb +93 -0
  57. data/lib/nucleus/adapters/v1/heroku/authentication.rb +27 -0
  58. data/lib/nucleus/adapters/v1/heroku/buildpacks.rb +27 -0
  59. data/lib/nucleus/adapters/v1/heroku/data.rb +78 -0
  60. data/lib/nucleus/adapters/v1/heroku/domains.rb +43 -0
  61. data/lib/nucleus/adapters/v1/heroku/heroku.rb +146 -0
  62. data/lib/nucleus/adapters/v1/heroku/lifecycle.rb +51 -0
  63. data/lib/nucleus/adapters/v1/heroku/logs.rb +108 -0
  64. data/lib/nucleus/adapters/v1/heroku/regions.rb +42 -0
  65. data/lib/nucleus/adapters/v1/heroku/scaling.rb +28 -0
  66. data/lib/nucleus/adapters/v1/heroku/semantic_errors.rb +23 -0
  67. data/lib/nucleus/adapters/v1/heroku/services.rb +168 -0
  68. data/lib/nucleus/adapters/v1/heroku/vars.rb +65 -0
  69. data/lib/nucleus/adapters/v1/openshift_v2/app_states.rb +68 -0
  70. data/lib/nucleus/adapters/v1/openshift_v2/application.rb +108 -0
  71. data/lib/nucleus/adapters/v1/openshift_v2/authentication.rb +21 -0
  72. data/lib/nucleus/adapters/v1/openshift_v2/data.rb +96 -0
  73. data/lib/nucleus/adapters/v1/openshift_v2/domains.rb +37 -0
  74. data/lib/nucleus/adapters/v1/openshift_v2/lifecycle.rb +60 -0
  75. data/lib/nucleus/adapters/v1/openshift_v2/logs.rb +106 -0
  76. data/lib/nucleus/adapters/v1/openshift_v2/openshift_v2.rb +125 -0
  77. data/lib/nucleus/adapters/v1/openshift_v2/regions.rb +58 -0
  78. data/lib/nucleus/adapters/v1/openshift_v2/scaling.rb +39 -0
  79. data/lib/nucleus/adapters/v1/openshift_v2/semantic_errors.rb +40 -0
  80. data/lib/nucleus/adapters/v1/openshift_v2/services.rb +173 -0
  81. data/lib/nucleus/adapters/v1/openshift_v2/vars.rb +49 -0
  82. data/lib/nucleus/adapters/v1/stub_adapter.rb +464 -0
  83. data/lib/nucleus/core/adapter_authentication_inductor.rb +62 -0
  84. data/lib/nucleus/core/adapter_extensions/auth/auth_client.rb +44 -0
  85. data/lib/nucleus/core/adapter_extensions/auth/authentication_retry_wrapper.rb +79 -0
  86. data/lib/nucleus/core/adapter_extensions/auth/expiring_token_auth_client.rb +53 -0
  87. data/lib/nucleus/core/adapter_extensions/auth/http_basic_auth_client.rb +37 -0
  88. data/lib/nucleus/core/adapter_extensions/auth/o_auth2_auth_client.rb +95 -0
  89. data/lib/nucleus/core/adapter_extensions/auth/token_auth_client.rb +36 -0
  90. data/lib/nucleus/core/adapter_extensions/http_client.rb +177 -0
  91. data/lib/nucleus/core/adapter_extensions/http_tail_client.rb +26 -0
  92. data/lib/nucleus/core/adapter_extensions/tail_stopper.rb +25 -0
  93. data/lib/nucleus/core/common/errors/ambiguous_adapter_error.rb +7 -0
  94. data/lib/nucleus/core/common/errors/file_existence_error.rb +7 -0
  95. data/lib/nucleus/core/common/errors/startup_error.rb +12 -0
  96. data/lib/nucleus/core/common/exit_codes.rb +25 -0
  97. data/lib/nucleus/core/common/files/application_repo_sanitizer.rb +52 -0
  98. data/lib/nucleus/core/common/files/archive_extractor.rb +112 -0
  99. data/lib/nucleus/core/common/files/archiver.rb +91 -0
  100. data/lib/nucleus/core/common/link_generator.rb +46 -0
  101. data/lib/nucleus/core/common/logging/logging.rb +52 -0
  102. data/lib/nucleus/core/common/logging/multi_logger.rb +59 -0
  103. data/lib/nucleus/core/common/logging/request_log_formatter.rb +48 -0
  104. data/lib/nucleus/core/common/ssh_handler.rb +108 -0
  105. data/lib/nucleus/core/common/stream_callback.rb +27 -0
  106. data/lib/nucleus/core/common/thread_config_accessor.rb +85 -0
  107. data/lib/nucleus/core/common/url_converter.rb +28 -0
  108. data/lib/nucleus/core/enums/application_states.rb +26 -0
  109. data/lib/nucleus/core/enums/logfile_types.rb +28 -0
  110. data/lib/nucleus/core/error_messages.rb +127 -0
  111. data/lib/nucleus/core/errors/adapter_error.rb +13 -0
  112. data/lib/nucleus/core/errors/adapter_missing_implementation_error.rb +12 -0
  113. data/lib/nucleus/core/errors/adapter_request_error.rb +10 -0
  114. data/lib/nucleus/core/errors/adapter_resource_not_found_error.rb +10 -0
  115. data/lib/nucleus/core/errors/endpoint_authentication_error.rb +10 -0
  116. data/lib/nucleus/core/errors/platform_specific_semantic_error.rb +12 -0
  117. data/lib/nucleus/core/errors/platform_timeout_error.rb +10 -0
  118. data/lib/nucleus/core/errors/platform_unavailable_error.rb +10 -0
  119. data/lib/nucleus/core/errors/semantic_adapter_request_error.rb +19 -0
  120. data/lib/nucleus/core/errors/unknown_adapter_call_error.rb +10 -0
  121. data/lib/nucleus/core/file_handling/archive_converter.rb +29 -0
  122. data/lib/nucleus/core/file_handling/file_manager.rb +64 -0
  123. data/lib/nucleus/core/file_handling/git_deployer.rb +133 -0
  124. data/lib/nucleus/core/file_handling/git_repo_analyzer.rb +23 -0
  125. data/lib/nucleus/core/import/adapter_configuration.rb +53 -0
  126. data/lib/nucleus/core/import/vendor_parser.rb +28 -0
  127. data/lib/nucleus/core/import/version_detector.rb +18 -0
  128. data/lib/nucleus/core/models/abstract_model.rb +29 -0
  129. data/lib/nucleus/core/models/endpoint.rb +30 -0
  130. data/lib/nucleus/core/models/provider.rb +26 -0
  131. data/lib/nucleus/core/models/vendor.rb +22 -0
  132. data/lib/nucleus/ext/kernel.rb +5 -0
  133. data/lib/nucleus/ext/regexp.rb +49 -0
  134. data/lib/nucleus/os.rb +15 -0
  135. data/lib/nucleus/root_dir.rb +13 -0
  136. data/lib/nucleus/scripts/finalize.rb +8 -0
  137. data/lib/nucleus/scripts/initialize.rb +9 -0
  138. data/lib/nucleus/scripts/initialize_config_defaults.rb +26 -0
  139. data/lib/nucleus/scripts/load.rb +17 -0
  140. data/lib/nucleus/scripts/load_dependencies.rb +43 -0
  141. data/lib/nucleus/scripts/setup_config.rb +28 -0
  142. data/lib/nucleus/scripts/shutdown.rb +11 -0
  143. data/lib/nucleus/version.rb +3 -0
  144. data/nucleus.gemspec +88 -0
  145. data/public/robots.txt +2 -0
  146. data/public/swagger-ui/css/reset.css +125 -0
  147. data/public/swagger-ui/css/screen.css +1224 -0
  148. data/public/swagger-ui/images/apple-touch-icon-114x114.png +0 -0
  149. data/public/swagger-ui/images/apple-touch-icon-120x120.png +0 -0
  150. data/public/swagger-ui/images/apple-touch-icon-144x144.png +0 -0
  151. data/public/swagger-ui/images/apple-touch-icon-152x152.png +0 -0
  152. data/public/swagger-ui/images/apple-touch-icon-57x57.png +0 -0
  153. data/public/swagger-ui/images/apple-touch-icon-60x60.png +0 -0
  154. data/public/swagger-ui/images/apple-touch-icon-72x72.png +0 -0
  155. data/public/swagger-ui/images/apple-touch-icon-76x76.png +0 -0
  156. data/public/swagger-ui/images/explorer_icons.png +0 -0
  157. data/public/swagger-ui/images/favicon-128.png +0 -0
  158. data/public/swagger-ui/images/favicon-16x16.png +0 -0
  159. data/public/swagger-ui/images/favicon-196x196.png +0 -0
  160. data/public/swagger-ui/images/favicon-32x32.png +0 -0
  161. data/public/swagger-ui/images/favicon-96x96.png +0 -0
  162. data/public/swagger-ui/images/favicon.ico +0 -0
  163. data/public/swagger-ui/images/logo_small.png +0 -0
  164. data/public/swagger-ui/images/mstile-144x144.png +0 -0
  165. data/public/swagger-ui/images/mstile-150x150.png +0 -0
  166. data/public/swagger-ui/images/mstile-310x150.png +0 -0
  167. data/public/swagger-ui/images/mstile-310x310.png +0 -0
  168. data/public/swagger-ui/images/mstile-70x70.png +0 -0
  169. data/public/swagger-ui/images/pet_store_api.png +0 -0
  170. data/public/swagger-ui/images/throbber.gif +0 -0
  171. data/public/swagger-ui/images/wordnik_api.png +0 -0
  172. data/public/swagger-ui/index.html +107 -0
  173. data/public/swagger-ui/lib/backbone-min.js +38 -0
  174. data/public/swagger-ui/lib/handlebars-1.0.0.js +2278 -0
  175. data/public/swagger-ui/lib/highlight.7.3.pack.js +1 -0
  176. data/public/swagger-ui/lib/jquery-1.8.0.min.js +2 -0
  177. data/public/swagger-ui/lib/jquery.ba-bbq.min.js +18 -0
  178. data/public/swagger-ui/lib/jquery.slideto.min.js +1 -0
  179. data/public/swagger-ui/lib/jquery.wiggle.min.js +8 -0
  180. data/public/swagger-ui/lib/shred.bundle.js +2765 -0
  181. data/public/swagger-ui/lib/shred/content.js +193 -0
  182. data/public/swagger-ui/lib/swagger-oauth.js +211 -0
  183. data/public/swagger-ui/lib/swagger.js +1653 -0
  184. data/public/swagger-ui/lib/underscore-min.js +32 -0
  185. data/public/swagger-ui/o2c.html +15 -0
  186. data/public/swagger-ui/redirect.html +14 -0
  187. data/public/swagger-ui/swagger-ui.js +2324 -0
  188. data/public/swagger-ui/swagger-ui.min.js +1 -0
  189. data/schemas/api.adapter.schema.yml +31 -0
  190. data/schemas/api.requirements.schema.yml +17 -0
  191. data/spec/factories/models.rb +61 -0
  192. data/spec/integration/api/auth_spec.rb +58 -0
  193. data/spec/integration/api/endpoints_spec.rb +167 -0
  194. data/spec/integration/api/errors_spec.rb +47 -0
  195. data/spec/integration/api/providers_spec.rb +157 -0
  196. data/spec/integration/api/swagger_schema_spec.rb +64 -0
  197. data/spec/integration/api/vendors_spec.rb +45 -0
  198. data/spec/integration/integration_spec_helper.rb +27 -0
  199. data/spec/integration/test_data_generator.rb +55 -0
  200. data/spec/nucleus_git_key.pem +51 -0
  201. data/spec/spec_helper.rb +98 -0
  202. data/spec/support/shared_example_request_types.rb +99 -0
  203. data/spec/test_suites.rake +31 -0
  204. data/spec/unit/adapters/archive_converter_spec.rb +25 -0
  205. data/spec/unit/adapters/file_manager_spec.rb +93 -0
  206. data/spec/unit/adapters/git_deployer_spec.rb +262 -0
  207. data/spec/unit/adapters/v1/stub_spec.rb +14 -0
  208. data/spec/unit/common/helpers/auth_helper_spec.rb +73 -0
  209. data/spec/unit/common/oauth2_auth_client_spec.rb +108 -0
  210. data/spec/unit/common/regexp_spec.rb +33 -0
  211. data/spec/unit/common/request_log_formatter_spec.rb +108 -0
  212. data/spec/unit/common/thread_config_accessor_spec.rb +97 -0
  213. data/spec/unit/models/endpoint_spec.rb +83 -0
  214. data/spec/unit/models/provider_spec.rb +102 -0
  215. data/spec/unit/models/vendor_spec.rb +100 -0
  216. data/spec/unit/schemas/adapter_schema_spec.rb +16 -0
  217. data/spec/unit/schemas/adapter_validation_spec.rb +56 -0
  218. data/spec/unit/schemas/requirements_schema_spec.rb +16 -0
  219. data/spec/unit/unit_spec_helper.rb +11 -0
  220. data/tasks/compatibility.rake +113 -0
  221. data/tasks/evaluation.rake +162 -0
  222. data/wiki/adapter_tests.md +99 -0
  223. data/wiki/implement_new_adapter.md +155 -0
  224. 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,11 @@
1
+ require 'spec/spec_helper'
2
+ require 'memfs'
3
+
4
+ # define test suite for coverage report
5
+ SimpleCov.command_name 'spec:suite:unit'
6
+
7
+ RSpec.configure do |c|
8
+ c.around(:each, memfs: true) do |example|
9
+ MemFs.activate { example.run }
10
+ end
11
+ 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 ? '&#10003;' : '&#10007;'}"
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