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.
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