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,137 @@
1
+ import 'tasks/compatibility.rake'
2
+ import 'tasks/evaluation.rake'
3
+ import 'spec/test_suites.rake'
4
+
5
+ require 'rake'
6
+ require 'rubygems'
7
+ require 'bundler'
8
+ require 'bundler/gem_tasks'
9
+ require 'rspec/core/rake_task'
10
+ require 'rainbow/ext/string' unless String.respond_to?(:color)
11
+ require 'rubocop/rake_task'
12
+
13
+ RuboCop::RakeTask.new
14
+
15
+ # first check code style, then execute the tests
16
+ task default: [:rubocop, :spec]
17
+
18
+ # map spec task to all test suites
19
+ task :spec do
20
+ # first, run all tests
21
+ Rake::Task['spec:suite:all'].invoke
22
+ # if on the CI system, push coverage report to codeclimate
23
+ if ENV['CODECLIMATE_REPO_TOKEN']
24
+ require 'simplecov'
25
+ require 'codeclimate-test-reporter'
26
+ CodeClimate::TestReporter::Formatter.new.format(SimpleCov.result)
27
+ end
28
+ end
29
+
30
+ task :doc_toc do
31
+ File.open('README.md', 'r') do |f|
32
+ f.each_line do |line|
33
+ forbidden_words = ['Table of contents', 'define', 'pragma']
34
+ next if !line.start_with?('#') || forbidden_words.any? { |w| line =~ /#{w}/ }
35
+
36
+ title = line.delete('#').strip
37
+ href = title.tr(' ', '-').downcase
38
+ puts ' ' * (line.count('#') - 1) + "* [#{title}](\##{href})"
39
+ end
40
+ end
41
+ end
42
+
43
+ desc 'Record all adapter tests'
44
+ task :record do
45
+ # http://www.relishapp.com/vcr/vcr/v/2-9-3/docs/record-modes
46
+ ENV['VCR_RECORD_MODE'] = 'once'
47
+ # recording only valid for adapter tests
48
+ Rake::Task['spec:suite:adapters'].invoke
49
+ end
50
+
51
+ namespace :record do
52
+ FileList['spec/adapter/v1/**'].each do |file|
53
+ next unless File.directory?(file)
54
+ adapter = File.basename(file)
55
+
56
+ desc "Record #{adapter} adapter tests"
57
+ RSpec::Core::RakeTask.new(adapter) do |t|
58
+ # new_episodes
59
+ ENV['VCR_RECORD_MODE'] = 'once'
60
+ t.pattern = "spec/adapter/v1/#{adapter}/*_spec.rb"
61
+ t.verbose = true
62
+ end
63
+ end
64
+ end
65
+
66
+ task :environment do
67
+ ENV['RACK_ENV'] ||= 'development'
68
+ require 'configatron'
69
+ require 'nucleus/scripts/setup_config'
70
+ nucleus_config.logging.level = Logger::Severity::ERROR
71
+ require 'nucleus_api/scripts/load_api'
72
+ require 'nucleus_api/scripts/initialize_api'
73
+ end
74
+
75
+ task routes: :environment do
76
+ Nucleus::API::RootAPI.routes.each do |route|
77
+ next if route.nil? || route.route_method.nil?
78
+ method = route.route_method.ljust(10)
79
+ path = route.route_path
80
+ version = route.instance_variable_get(:@options)[:version]
81
+ path = path.gsub(/:version/, version) unless version.nil?
82
+ puts " #{method} #{path} - [#{version}]"
83
+ end
84
+ end
85
+
86
+ task schema_v1: :environment do
87
+ require 'json'
88
+ response = Nucleus::API::RootAPI.call(
89
+ 'REQUEST_METHOD' => 'GET',
90
+ 'PATH_INFO' => '/schema',
91
+ 'rack.input' => StringIO.new)[2].body[0]
92
+ json = JSON.parse(response)
93
+ puts JSON.pretty_generate(json)
94
+ end
95
+
96
+ begin
97
+ require 'yard'
98
+ DOC_FILES = %w(lib/**/*.rb)
99
+
100
+ YARD::Rake::YardocTask.new(:doc) do |t|
101
+ t.files = DOC_FILES
102
+ end
103
+
104
+ namespace :doc do
105
+ YARD::Rake::YardocTask.new(:pages) do |t|
106
+ t.files = DOC_FILES
107
+ t.options = ['-o', '../nucleus.doc/docs', '--title', "Nucleus #{Nucleus::VERSION} Documentation"]
108
+ end
109
+
110
+ desc 'Check out gh-pages.'
111
+ task :checkout do
112
+ dir = File.join(__dir__, '..', 'nucleus.doc')
113
+ unless Dir.exist?(dir)
114
+ Dir.mkdir(dir)
115
+ Dir.chdir(dir) do
116
+ system('git init')
117
+ system('git remote add origin git@github.com:stefan-kolb/nucleus.git')
118
+ system('git pull')
119
+ system('git checkout gh-pages')
120
+ end
121
+ end
122
+ end
123
+
124
+ desc 'Generate and publish YARD docs to GitHub pages.'
125
+ task publish: %w(doc:pages:checkout doc:pages) do
126
+ Dir.chdir(File.join(__dir__, '..', 'nucleus.doc')) do
127
+ system('git checkout gh-pages')
128
+ system('git add .')
129
+ system('git add -u')
130
+ system("git commit -m 'Generating docs for version #{Nucleus::VERSION}.'")
131
+ system('git push origin gh-pages')
132
+ end
133
+ end
134
+ end
135
+ rescue LoadError
136
+ puts 'You need to install YARD.'
137
+ end
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # set the process name on ps, does not work on OS X due to system limitations
4
+ $0 = 'Nucleus'
5
+ Process.setproctitle('Nucleus') if Process.respond_to?(:setproctitle)
6
+
7
+ root_dir = File.join(__dir__, '..')
8
+
9
+ require 'optparse'
10
+ require 'yaml'
11
+ require 'thin'
12
+
13
+ NUCLEUS_CONFIG_LOCATION = File.join(root_dir, 'config', 'nucleus_config.rb')
14
+
15
+ options = { env: 'development', logdir: File.join(root_dir, 'log'), config: File.expand_path(NUCLEUS_CONFIG_LOCATION) }
16
+ optparse = OptionParser.new do |opts|
17
+ opts.banner = <<BANNER
18
+ Usage:
19
+ nucleus [options]
20
+
21
+ Options:
22
+ BANNER
23
+ opts.on('-r', '--hostname HOSTNAME', 'Bind to HOST address (default: localhost)') { |host| ENV['NUCLEUS_API_HOST'] = host }
24
+ opts.on('-p', '--port PORT', 'Use PORT (default: 9292)') { |port| ENV['NUCLEUS_API_PORT'] = port }
25
+ opts.on('-e', '--env ENV', 'Environment (default: "development")') { |env| options[:env] = env }
26
+ opts.on('-t', '--timeout TIMEOUT', 'Timeout for single request (default: 30)') { |timeout| ENV['NUCLEUS_API_TIMEOUT'] = timeout }
27
+ opts.on('-h', '--help', '') { options[:help] = true }
28
+ opts.separator <<EOS
29
+
30
+ Daemon options:
31
+ EOS
32
+ opts.on('-d', '--daemon', 'Run the server as daemon in the background (default: false)') { options[:daemon] = true }
33
+ opts.on('-u', '--user USER', 'User to run daemon as. Use with -d (default: "nobody")') { |user| options[:user] = user }
34
+ opts.on('-g', '--group GROUP', 'Group to run daemon as. Use with -d (default: "nobody")') { |group| options[:group] = group }
35
+ opts.on('-b', '--pid PID', 'File to store PID (default: tmp/pids/thin.pid)') { |pid| options[:pid] = pid }
36
+ opts.on('-l', '--logdir LOGDIR', "Directory for log files if run as daemon, defaults to #{options[:logdir]}") { |opt| options[:logdir] = opt }
37
+ opts.separator <<EOS
38
+
39
+ SSL options:
40
+ EOS
41
+ opts.on('-s', '--ssl', 'Enable SSL (default: false, use with: ssl-key and ssl-cert)') { options[:ssl] = true }
42
+ opts.on('-k', '--ssl-key KEY', 'SSL key file to use (use with: ssl and ssl-cert)') { |key| options[:ssl_key] = key }
43
+ opts.on('-c', '--ssl-cert CERT', 'SSL certificate file to use (use with: ssl and ssl-key)') { |cert| options[:ssl_cert] = cert }
44
+ end
45
+
46
+ optparse.parse!
47
+
48
+ if options[:help]
49
+ puts optparse
50
+ exit(0)
51
+ end
52
+
53
+ if options[:env] == 'production' && ( !options.key?(:ssl) || options[:ssl] == false)
54
+ puts 'You need to use HTTPS when running a production server. Please specify the SSL key and certificate.'
55
+ exit(201)
56
+ end
57
+
58
+ if options[:ssl]
59
+ unless options[:ssl_key]
60
+ puts "You need to set SSL key using '-k /path/to/keyfile.key'"
61
+ exit(101)
62
+ end
63
+ unless options[:ssl_cert]
64
+ puts "You need to set SSL certificate using '-c /path/to/certificate.crt'"
65
+ exit(102)
66
+ end
67
+ end
68
+
69
+ ENV['NUCLEUS_API_HOST'] = 'localhost' unless ENV['NUCLEUS_API_HOST']
70
+ ENV['NUCLEUS_API_PORT'] = '9292' unless ENV['NUCLEUS_API_PORT']
71
+
72
+ argv_opts = ARGV.clone
73
+ argv_opts << ['start'] unless Thin::Runner.commands.include?(options[0])
74
+ argv_opts << ['--address', ENV['NUCLEUS_API_HOST'] ]
75
+ argv_opts << ['--port', ENV['NUCLEUS_API_PORT'] ]
76
+ argv_opts << ['--rackup', File.join(root_dir, 'config.ru') ]
77
+ argv_opts << ['-e', options[:env] ]
78
+ argv_opts << ['--timeout', ENV['NUCLEUS_API_TIMEOUT'] || '60']
79
+ argv_opts << ['--ssl', '--ssl-key-file', options[:ssl_key], '--ssl-cert-file', options[:ssl_cert]] if options[:ssl]
80
+
81
+ if options[:daemon]
82
+ options[:env] = 'production'
83
+ argv_opts << [ '--daemonize', '--user', options[:user] || 'nobody', '--tag', 'Nucleus on Thin']
84
+ argv_opts << [ '--pid', options[:pid]] if options[:pid]
85
+ argv_opts << [ '--group', options[:group] || 'nobody' ]
86
+ argv_opts << [ '--log', File.join(options[:logdir], 'nucleus_daemon.log')] unless ENV['NUCLEUS_API_LOG']
87
+ end
88
+ argv_opts.flatten!
89
+
90
+ thin = Thin::Runner.new(argv_opts)
91
+ thin.run!
@@ -0,0 +1 @@
1
+ @ruby -C%~dp0.. "%~dp0nucleus" %*
@@ -0,0 +1,18 @@
1
+ #########################
2
+ ### Setup Application ###
3
+ #########################
4
+ require 'bundler/setup'
5
+
6
+ # Load configuration
7
+ require 'nucleus/scripts/setup_config'
8
+ # Load application
9
+ require 'nucleus_api/scripts/load_api'
10
+ # Initialize the application
11
+ require 'nucleus_api/scripts/initialize_api'
12
+
13
+ # Initialize the Rack environment
14
+ # GO TO THIS FILE TO INCLUDE MIDDLEWARE (!)
15
+ require 'nucleus_api/scripts/rack_application'
16
+
17
+ # finally start the application
18
+ run Nucleus::API::Rack.app
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: "cloudControl"
3
+ id: "cloudcontrol"
4
+ providers:
5
+ -
6
+ name: "cloudControl"
7
+ id: "cloudcontrol"
8
+ endpoints:
9
+ -
10
+ name: "cloudControl"
11
+ id: "cloudcontrol"
12
+ url: "api.cloudcontrol.com"
13
+ -
14
+ name: "dotCloud"
15
+ id: "dotcloud"
16
+ url: "api.dotcloudapp.com"
17
+ -
18
+ name: "exoscale Apps"
19
+ id: "exoscale"
20
+ endpoints:
21
+ -
22
+ name: "exoscale Apps"
23
+ id: "exoscale"
24
+ url: "api.app.exo.io"
25
+ -
26
+ name: "Cloud&Heat App Elevator"
27
+ id: "cloudandheat"
28
+ endpoints:
29
+ -
30
+ name: "Cloud&Heat App Elevator"
31
+ id: "cloudandheat"
32
+ url: "api.cnh-apps.com"
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: "Cloud Foundry v2"
3
+ id: "cloud_foundry_v2"
4
+ providers:
5
+ -
6
+ name: "bosh"
7
+ id: "cf-bosh"
8
+ endpoints:
9
+ -
10
+ name: "bosh local"
11
+ id: "cf-bosh-local"
12
+ url: "api.10.244.0.34.xip.io"
13
+ app_domain: "10.244.0.34.xip.io"
14
+ # trust endpoint, no ssl certificate verification
15
+ trust: true
16
+ -
17
+ name: "Pivotal"
18
+ id: "pivotal"
19
+ endpoints:
20
+ -
21
+ name: "Pivotal Web Services"
22
+ id: "pivotal"
23
+ url: "api.run.pivotal.io"
24
+ app_domain: "cfapps.io"
25
+ -
26
+ name: "IBM Bluemix"
27
+ id: "bluemix"
28
+ endpoints:
29
+ -
30
+ name: "Europe - Great Britain"
31
+ id: "bluemix-eu-gb"
32
+ url: "api.eu-gb.bluemix.net"
33
+ app_domain: "eu-gb.mybluemix.net"
34
+ -
35
+ name: "United States - South"
36
+ id: "bluemix-us-south"
37
+ url: "api.ng.bluemix.net"
38
+ app_domain: "ng.mybluemix.net"
39
+ -
40
+ name: "Anynines"
41
+ id: "anynines"
42
+ endpoints:
43
+ -
44
+ name: "Anynines"
45
+ id: "anynines"
46
+ url: "api.de.a9s.eu"
47
+ app_domain: "a9s.eu"
48
+ -
49
+ name: "AppFog"
50
+ id: "appfog"
51
+ endpoints:
52
+ -
53
+ name: "US East"
54
+ id: "appfog-us-east"
55
+ url: "api.useast.appfog.ctl.io"
56
+ app_domain: "useast.appfog.ctl.io"
57
+ -
58
+ name: "US West"
59
+ id: "appfog-us-west"
60
+ url: "api.uswest.appfog.ctl.io"
61
+ app_domain: "uswest.appfog.ctl.io"
@@ -0,0 +1,13 @@
1
+ ---
2
+ name: "Heroku"
3
+ id: "heroku"
4
+ providers:
5
+ -
6
+ name: "Heroku"
7
+ id: "heroku"
8
+ endpoints:
9
+ -
10
+ name: "Heroku"
11
+ id: "heroku"
12
+ url: "api.heroku.com"
13
+ app_domain: "herokuapp.com"
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: "Openshift v2"
3
+ id: "openshift_v2"
4
+ providers:
5
+ -
6
+ name: "Openshift Online"
7
+ id: "openshift-online"
8
+ endpoints:
9
+ -
10
+ name: "Openshift Online"
11
+ id: "openshift-online"
12
+ url: "openshift.redhat.com/broker/rest"
13
+ -
14
+ name: "Getup Cloud"
15
+ id: "getup"
16
+ endpoints:
17
+ -
18
+ name: "Getup Cloud"
19
+ id: "getup"
20
+ url: "broker.getupcloud.com/broker/rest"
@@ -0,0 +1,47 @@
1
+ # [optional] The available levels are: FATAL, ERROR, WARN, INFO, DEBUG
2
+ # Defaults to: Logger::Severity::WARN
3
+ # nucleus_config.logging.level = Logger::Severity::WARN
4
+
5
+ # [optional] Logging directory
6
+ # Defaults to: File.expand_path(File.join(File.dirname(__FILE__), '..', 'log'))
7
+ # nucleus_config.logging.path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'log'))
8
+
9
+ # [optional] Database backend to use. Choose one of: [:Daybreak, :LMDB]
10
+ # Defaults to: :Daybreak on Unix, :LMDB on windows systems.
11
+ # nucleus_config.db.backend = :Daybreak
12
+
13
+ # [optional] Options to start the backend.
14
+ # See http://www.rubydoc.info/gems/moneta/Moneta/Adapters for valid options on the chosen adapter.
15
+ # Defaults to: {}
16
+ # nucleus_config.db.backend_options = {}
17
+
18
+ # [optional] Please specify the DB directory if you plan to use a file storage.
19
+ # Defaults to: a temporary directory.
20
+ # nucleus_config.db.path = '/Users/cmr/Documents/workspace-rubymine/nucleus/store/'
21
+
22
+ # [optional] If true, the DB will be deleted when the server is being closed.
23
+ # Defaults to: true
24
+ # nucleus_config.db.delete_on_shutdown = false
25
+
26
+ # [optional, requires 'nucleus_config.db.path'] If true, the DB will be initialized with default values,
27
+ # which may partially override previously persisted entities.
28
+ # False keeps the changes that were applied during runtime.
29
+ # Defaults to: false
30
+ # nucleus_config.db.override = false
31
+
32
+ # [optional] Specify the location of a private key (ssh-rsa, OpenSSH) that shall be used for Git actions.
33
+ # E.g. /home/myusername/.ssh/id_rsa
34
+ # If set to false, Nucleus will use its own private key (config/nucleus_git_key.pem) to authenticate all Git actions.
35
+ # Defaults to: nil
36
+ # nucleus_config.ssh.custom_key = nil
37
+
38
+ # [optional] Specify the public API description
39
+ # nucleus_config.api.title = 'Nucleus - Platform as a Service abstraction layer API'
40
+ # nucleus_config.api.description = 'Nucleus allows to manage multiple PaaS providers with just one API to be used'
41
+ # nucleus_config.api.contact = 'stefan.kolb@uni-bamberg.de'
42
+ # # The name of the license.
43
+ # nucleus_config.api.license = 'TBD'
44
+ # # The URL of the license.
45
+ # nucleus_config.api.license_url = ''
46
+ # # The URL of the API terms and conditions.
47
+ # nucleus_config.api.terms_of_service_url = 'API still under development, no guarantees (!)'
@@ -0,0 +1,13 @@
1
+ require 'nucleus/version'
2
+
3
+ # _Nucleus_ is a RESTful abstraction layer to achieve unified deployment and management functions
4
+ # of Platform-as-a-Service (PaaS) providers.<br>
5
+ module Nucleus
6
+ # Load the default configuration
7
+ require 'nucleus/scripts/setup_config'
8
+ # Load the actual application and its dependencies
9
+ require 'nucleus/scripts/load'
10
+
11
+ # now require the parts that are only relevant when using Nucleus as gem
12
+ require 'nucleus/adapter_resolver'
13
+ end
@@ -0,0 +1,115 @@
1
+ module Nucleus
2
+ # The {AdapterResolver} can be used within Ruby applications to retrieve a Nucleus adapter.
3
+ # Returned adapters are patched so that each call enforces authentication and retries a call when a token was expired.
4
+ class AdapterResolver
5
+ include Nucleus::UrlConverter
6
+
7
+ def initialize(requested_version)
8
+ fail 'No such version supported' unless Nucleus::VersionDetector.api_versions.include?(requested_version)
9
+ @api_version = requested_version
10
+ end
11
+
12
+ # Get a list of all adapters that are currently supported.
13
+ # @return [Hash<String, Hash<String, Nucleus::Adapters::BaseAdapter>>] currently supported adapters
14
+ def adapters
15
+ setup
16
+ @adapters
17
+ end
18
+
19
+ # Load the adapter to interact with the platform of the vendor that is offered at the endpoint_url.
20
+ # @param [String] vendor The vendor / adapter name that shall be used to communicate with the endpoint.
21
+ # Must be supported, otherwise a +StandardError+ will be thrown.
22
+ # @param [String] username The username that shall be used for authentication
23
+ # @param [String] password The password that shall be used for authentication
24
+ # @param [Hash<Symbol,?>] options Further options to apply when creating the adapter instance.
25
+ # If available, the default configuration of the vendor configuration is applied as default.
26
+ # @option options [String] :app_domain The domain where applications of the platform will be made available at.
27
+ # This option must be set for custom deployments of platforms like Cloud Foundry or Openshift.
28
+ # For IBM Bluemix this value would be: +eu-gb.mybluemix.net+ or +ng.mybluemix.net+, depending on the endpoint.
29
+ # @option options [String] :check_ssl Set to false if SSL certificates shall not be verified (trust self-signed)
30
+ # @option options [String] :api_url URL of the endpoint's API that shall be used.
31
+ # Must be specified if there are multiple endpoints available and will be forced to https://
32
+ # @raise [StandardError] if the vendor is unknown / not supported or no unique API endpoint could be identified
33
+ # @return [Nucleus::Adapters::BaseAdapter] loaded adapter implementation
34
+ def load(vendor, username, password, options = {})
35
+ setup
36
+ fail StandardError, "Could not find adapter for vendor '#{vendor}'" unless @adapters.key?(vendor)
37
+
38
+ # load the endpoint's HTTPS enabled API URL
39
+ endpoint_url = load_endpoint(vendor, options)
40
+
41
+ # load default configuration if available
42
+ if @configurations[vendor].key?(endpoint_url)
43
+ default_configuration = @configurations[vendor][endpoint_url]
44
+ options = default_configuration.merge(options)
45
+ end
46
+
47
+ check_ssl = options.key?(:check_ssl) ? options[:check_ssl] : true
48
+ adapter = @adapters[vendor].new(endpoint_url, options[:app_domain], check_ssl)
49
+
50
+ fake_env = { 'HTTP_AUTHORIZATION' => 'Basic ' + ["#{username}:#{password}"].pack('m*').gsub(/\n/, '') }
51
+ # patch the adapter so that calls are wrapped and expect valid authentication
52
+ AdapterAuthenticationInductor.patch(adapter, fake_env)
53
+
54
+ cache_key = adapter.cache_key(username, password)
55
+ # no auth object available, perform authentication first
56
+ auth_object = adapter.auth_client
57
+ # throws an error if the authentication failed
58
+ auth_object.authenticate(username, password)
59
+ # cache the auth object so it does not have to be retrieved per request
60
+ adapter.cache(cache_key, auth_object)
61
+
62
+ # return patched and initially authenticated adapter
63
+ adapter
64
+ end
65
+
66
+ private
67
+
68
+ def load_endpoint(vendor, options)
69
+ if options.key?(:api_url)
70
+ # use chosen url endpoint
71
+ endpoint_url = options[:api_url]
72
+ elsif @configurations[vendor].length == 1
73
+ # use default endpoint
74
+ endpoint_url = @configurations[vendor].keys.first
75
+ else
76
+ fail StandardError, "Could not identify an API endpoint for the vendor '#{vendor}'. "\
77
+ "Please specify the API URL to use with the ':api_url' option."
78
+ end
79
+
80
+ # make sure url uses https
81
+ secure_url(endpoint_url)
82
+ end
83
+
84
+ def setup
85
+ # perform the setup only once
86
+ return if @adapters
87
+
88
+ # Initialize the application (import adapters, load DAOs, ...)
89
+ require 'nucleus/scripts/initialize'
90
+ # load the configuration values
91
+ require 'nucleus/scripts/initialize_config_defaults'
92
+ # Once invoked the configuration is locked
93
+ require 'nucleus/scripts/finalize'
94
+
95
+ @adapters = {}
96
+ @configurations = {}
97
+ Nucleus::Adapters.configuration_files.each do |adapter_config|
98
+ vendor = Nucleus::VendorParser.parse(adapter_config)
99
+ next unless vendor
100
+ adapter_clazz = Nucleus::Adapters.adapter_clazz(adapter_config, @api_version)
101
+ next unless adapter_clazz
102
+ @adapters[vendor.id] = adapter_clazz
103
+ @configurations[vendor.id] = {}
104
+
105
+ # now load the default configurations for this vendor
106
+ vendor.providers.each do |provider|
107
+ provider.endpoints.each do |endpoint|
108
+ @configurations[vendor.id][secure_url(endpoint.url)] = { check_ssl: !endpoint.trust,
109
+ app_domain: endpoint.app_domain }
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end