nucleus 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitattributes +1 -0
- data/.gitignore +19 -0
- data/.rspec +3 -0
- data/.rubocop.yml +44 -0
- data/.travis.yml +21 -0
- data/CHANGELOG.md +19 -0
- data/CONTRIBUTING.md +13 -0
- data/Gemfile +16 -0
- data/Guardfile +22 -0
- data/LICENSE +21 -0
- data/README.md +675 -0
- data/Rakefile +137 -0
- data/bin/nucleus +91 -0
- data/bin/nucleus.bat +1 -0
- data/config.ru +18 -0
- data/config/adapters/cloud_control.yml +32 -0
- data/config/adapters/cloud_foundry_v2.yml +61 -0
- data/config/adapters/heroku.yml +13 -0
- data/config/adapters/openshift_v2.yml +20 -0
- data/config/nucleus_config.rb +47 -0
- data/lib/nucleus.rb +13 -0
- data/lib/nucleus/adapter_resolver.rb +115 -0
- data/lib/nucleus/adapters/base_adapter.rb +109 -0
- data/lib/nucleus/adapters/buildpack_translator.rb +79 -0
- data/lib/nucleus/adapters/v1/cloud_control/application.rb +108 -0
- data/lib/nucleus/adapters/v1/cloud_control/authentication.rb +27 -0
- data/lib/nucleus/adapters/v1/cloud_control/buildpacks.rb +23 -0
- data/lib/nucleus/adapters/v1/cloud_control/cloud_control.rb +153 -0
- data/lib/nucleus/adapters/v1/cloud_control/data.rb +76 -0
- data/lib/nucleus/adapters/v1/cloud_control/domains.rb +68 -0
- data/lib/nucleus/adapters/v1/cloud_control/lifecycle.rb +27 -0
- data/lib/nucleus/adapters/v1/cloud_control/log_poller.rb +71 -0
- data/lib/nucleus/adapters/v1/cloud_control/logs.rb +103 -0
- data/lib/nucleus/adapters/v1/cloud_control/regions.rb +32 -0
- data/lib/nucleus/adapters/v1/cloud_control/scaling.rb +17 -0
- data/lib/nucleus/adapters/v1/cloud_control/semantic_errors.rb +31 -0
- data/lib/nucleus/adapters/v1/cloud_control/services.rb +162 -0
- data/lib/nucleus/adapters/v1/cloud_control/token.rb +17 -0
- data/lib/nucleus/adapters/v1/cloud_control/vars.rb +88 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/app_states.rb +28 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/application.rb +111 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/authentication.rb +17 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/buildpacks.rb +23 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/cloud_foundry_v2.rb +141 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/data.rb +97 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/domains.rb +149 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/lifecycle.rb +41 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/logs.rb +303 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/regions.rb +33 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/scaling.rb +15 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/semantic_errors.rb +27 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/services.rb +286 -0
- data/lib/nucleus/adapters/v1/cloud_foundry_v2/vars.rb +80 -0
- data/lib/nucleus/adapters/v1/heroku/app_states.rb +57 -0
- data/lib/nucleus/adapters/v1/heroku/application.rb +93 -0
- data/lib/nucleus/adapters/v1/heroku/authentication.rb +27 -0
- data/lib/nucleus/adapters/v1/heroku/buildpacks.rb +27 -0
- data/lib/nucleus/adapters/v1/heroku/data.rb +78 -0
- data/lib/nucleus/adapters/v1/heroku/domains.rb +43 -0
- data/lib/nucleus/adapters/v1/heroku/heroku.rb +146 -0
- data/lib/nucleus/adapters/v1/heroku/lifecycle.rb +51 -0
- data/lib/nucleus/adapters/v1/heroku/logs.rb +108 -0
- data/lib/nucleus/adapters/v1/heroku/regions.rb +42 -0
- data/lib/nucleus/adapters/v1/heroku/scaling.rb +28 -0
- data/lib/nucleus/adapters/v1/heroku/semantic_errors.rb +23 -0
- data/lib/nucleus/adapters/v1/heroku/services.rb +168 -0
- data/lib/nucleus/adapters/v1/heroku/vars.rb +65 -0
- data/lib/nucleus/adapters/v1/openshift_v2/app_states.rb +68 -0
- data/lib/nucleus/adapters/v1/openshift_v2/application.rb +108 -0
- data/lib/nucleus/adapters/v1/openshift_v2/authentication.rb +21 -0
- data/lib/nucleus/adapters/v1/openshift_v2/data.rb +96 -0
- data/lib/nucleus/adapters/v1/openshift_v2/domains.rb +37 -0
- data/lib/nucleus/adapters/v1/openshift_v2/lifecycle.rb +60 -0
- data/lib/nucleus/adapters/v1/openshift_v2/logs.rb +106 -0
- data/lib/nucleus/adapters/v1/openshift_v2/openshift_v2.rb +125 -0
- data/lib/nucleus/adapters/v1/openshift_v2/regions.rb +58 -0
- data/lib/nucleus/adapters/v1/openshift_v2/scaling.rb +39 -0
- data/lib/nucleus/adapters/v1/openshift_v2/semantic_errors.rb +40 -0
- data/lib/nucleus/adapters/v1/openshift_v2/services.rb +173 -0
- data/lib/nucleus/adapters/v1/openshift_v2/vars.rb +49 -0
- data/lib/nucleus/adapters/v1/stub_adapter.rb +464 -0
- data/lib/nucleus/core/adapter_authentication_inductor.rb +62 -0
- data/lib/nucleus/core/adapter_extensions/auth/auth_client.rb +44 -0
- data/lib/nucleus/core/adapter_extensions/auth/authentication_retry_wrapper.rb +79 -0
- data/lib/nucleus/core/adapter_extensions/auth/expiring_token_auth_client.rb +53 -0
- data/lib/nucleus/core/adapter_extensions/auth/http_basic_auth_client.rb +37 -0
- data/lib/nucleus/core/adapter_extensions/auth/o_auth2_auth_client.rb +95 -0
- data/lib/nucleus/core/adapter_extensions/auth/token_auth_client.rb +36 -0
- data/lib/nucleus/core/adapter_extensions/http_client.rb +177 -0
- data/lib/nucleus/core/adapter_extensions/http_tail_client.rb +26 -0
- data/lib/nucleus/core/adapter_extensions/tail_stopper.rb +25 -0
- data/lib/nucleus/core/common/errors/ambiguous_adapter_error.rb +7 -0
- data/lib/nucleus/core/common/errors/file_existence_error.rb +7 -0
- data/lib/nucleus/core/common/errors/startup_error.rb +12 -0
- data/lib/nucleus/core/common/exit_codes.rb +25 -0
- data/lib/nucleus/core/common/files/application_repo_sanitizer.rb +52 -0
- data/lib/nucleus/core/common/files/archive_extractor.rb +112 -0
- data/lib/nucleus/core/common/files/archiver.rb +91 -0
- data/lib/nucleus/core/common/link_generator.rb +46 -0
- data/lib/nucleus/core/common/logging/logging.rb +52 -0
- data/lib/nucleus/core/common/logging/multi_logger.rb +59 -0
- data/lib/nucleus/core/common/logging/request_log_formatter.rb +48 -0
- data/lib/nucleus/core/common/ssh_handler.rb +108 -0
- data/lib/nucleus/core/common/stream_callback.rb +27 -0
- data/lib/nucleus/core/common/thread_config_accessor.rb +85 -0
- data/lib/nucleus/core/common/url_converter.rb +28 -0
- data/lib/nucleus/core/enums/application_states.rb +26 -0
- data/lib/nucleus/core/enums/logfile_types.rb +28 -0
- data/lib/nucleus/core/error_messages.rb +127 -0
- data/lib/nucleus/core/errors/adapter_error.rb +13 -0
- data/lib/nucleus/core/errors/adapter_missing_implementation_error.rb +12 -0
- data/lib/nucleus/core/errors/adapter_request_error.rb +10 -0
- data/lib/nucleus/core/errors/adapter_resource_not_found_error.rb +10 -0
- data/lib/nucleus/core/errors/endpoint_authentication_error.rb +10 -0
- data/lib/nucleus/core/errors/platform_specific_semantic_error.rb +12 -0
- data/lib/nucleus/core/errors/platform_timeout_error.rb +10 -0
- data/lib/nucleus/core/errors/platform_unavailable_error.rb +10 -0
- data/lib/nucleus/core/errors/semantic_adapter_request_error.rb +19 -0
- data/lib/nucleus/core/errors/unknown_adapter_call_error.rb +10 -0
- data/lib/nucleus/core/file_handling/archive_converter.rb +29 -0
- data/lib/nucleus/core/file_handling/file_manager.rb +64 -0
- data/lib/nucleus/core/file_handling/git_deployer.rb +133 -0
- data/lib/nucleus/core/file_handling/git_repo_analyzer.rb +23 -0
- data/lib/nucleus/core/import/adapter_configuration.rb +53 -0
- data/lib/nucleus/core/import/vendor_parser.rb +28 -0
- data/lib/nucleus/core/import/version_detector.rb +18 -0
- data/lib/nucleus/core/models/abstract_model.rb +29 -0
- data/lib/nucleus/core/models/endpoint.rb +30 -0
- data/lib/nucleus/core/models/provider.rb +26 -0
- data/lib/nucleus/core/models/vendor.rb +22 -0
- data/lib/nucleus/ext/kernel.rb +5 -0
- data/lib/nucleus/ext/regexp.rb +49 -0
- data/lib/nucleus/os.rb +15 -0
- data/lib/nucleus/root_dir.rb +13 -0
- data/lib/nucleus/scripts/finalize.rb +8 -0
- data/lib/nucleus/scripts/initialize.rb +9 -0
- data/lib/nucleus/scripts/initialize_config_defaults.rb +26 -0
- data/lib/nucleus/scripts/load.rb +17 -0
- data/lib/nucleus/scripts/load_dependencies.rb +43 -0
- data/lib/nucleus/scripts/setup_config.rb +28 -0
- data/lib/nucleus/scripts/shutdown.rb +11 -0
- data/lib/nucleus/version.rb +3 -0
- data/nucleus.gemspec +88 -0
- data/public/robots.txt +2 -0
- data/public/swagger-ui/css/reset.css +125 -0
- data/public/swagger-ui/css/screen.css +1224 -0
- data/public/swagger-ui/images/apple-touch-icon-114x114.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-120x120.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-144x144.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-152x152.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-57x57.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-60x60.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-72x72.png +0 -0
- data/public/swagger-ui/images/apple-touch-icon-76x76.png +0 -0
- data/public/swagger-ui/images/explorer_icons.png +0 -0
- data/public/swagger-ui/images/favicon-128.png +0 -0
- data/public/swagger-ui/images/favicon-16x16.png +0 -0
- data/public/swagger-ui/images/favicon-196x196.png +0 -0
- data/public/swagger-ui/images/favicon-32x32.png +0 -0
- data/public/swagger-ui/images/favicon-96x96.png +0 -0
- data/public/swagger-ui/images/favicon.ico +0 -0
- data/public/swagger-ui/images/logo_small.png +0 -0
- data/public/swagger-ui/images/mstile-144x144.png +0 -0
- data/public/swagger-ui/images/mstile-150x150.png +0 -0
- data/public/swagger-ui/images/mstile-310x150.png +0 -0
- data/public/swagger-ui/images/mstile-310x310.png +0 -0
- data/public/swagger-ui/images/mstile-70x70.png +0 -0
- data/public/swagger-ui/images/pet_store_api.png +0 -0
- data/public/swagger-ui/images/throbber.gif +0 -0
- data/public/swagger-ui/images/wordnik_api.png +0 -0
- data/public/swagger-ui/index.html +107 -0
- data/public/swagger-ui/lib/backbone-min.js +38 -0
- data/public/swagger-ui/lib/handlebars-1.0.0.js +2278 -0
- data/public/swagger-ui/lib/highlight.7.3.pack.js +1 -0
- data/public/swagger-ui/lib/jquery-1.8.0.min.js +2 -0
- data/public/swagger-ui/lib/jquery.ba-bbq.min.js +18 -0
- data/public/swagger-ui/lib/jquery.slideto.min.js +1 -0
- data/public/swagger-ui/lib/jquery.wiggle.min.js +8 -0
- data/public/swagger-ui/lib/shred.bundle.js +2765 -0
- data/public/swagger-ui/lib/shred/content.js +193 -0
- data/public/swagger-ui/lib/swagger-oauth.js +211 -0
- data/public/swagger-ui/lib/swagger.js +1653 -0
- data/public/swagger-ui/lib/underscore-min.js +32 -0
- data/public/swagger-ui/o2c.html +15 -0
- data/public/swagger-ui/redirect.html +14 -0
- data/public/swagger-ui/swagger-ui.js +2324 -0
- data/public/swagger-ui/swagger-ui.min.js +1 -0
- data/schemas/api.adapter.schema.yml +31 -0
- data/schemas/api.requirements.schema.yml +17 -0
- data/spec/factories/models.rb +61 -0
- data/spec/integration/api/auth_spec.rb +58 -0
- data/spec/integration/api/endpoints_spec.rb +167 -0
- data/spec/integration/api/errors_spec.rb +47 -0
- data/spec/integration/api/providers_spec.rb +157 -0
- data/spec/integration/api/swagger_schema_spec.rb +64 -0
- data/spec/integration/api/vendors_spec.rb +45 -0
- data/spec/integration/integration_spec_helper.rb +27 -0
- data/spec/integration/test_data_generator.rb +55 -0
- data/spec/nucleus_git_key.pem +51 -0
- data/spec/spec_helper.rb +98 -0
- data/spec/support/shared_example_request_types.rb +99 -0
- data/spec/test_suites.rake +31 -0
- data/spec/unit/adapters/archive_converter_spec.rb +25 -0
- data/spec/unit/adapters/file_manager_spec.rb +93 -0
- data/spec/unit/adapters/git_deployer_spec.rb +262 -0
- data/spec/unit/adapters/v1/stub_spec.rb +14 -0
- data/spec/unit/common/helpers/auth_helper_spec.rb +73 -0
- data/spec/unit/common/oauth2_auth_client_spec.rb +108 -0
- data/spec/unit/common/regexp_spec.rb +33 -0
- data/spec/unit/common/request_log_formatter_spec.rb +108 -0
- data/spec/unit/common/thread_config_accessor_spec.rb +97 -0
- data/spec/unit/models/endpoint_spec.rb +83 -0
- data/spec/unit/models/provider_spec.rb +102 -0
- data/spec/unit/models/vendor_spec.rb +100 -0
- data/spec/unit/schemas/adapter_schema_spec.rb +16 -0
- data/spec/unit/schemas/adapter_validation_spec.rb +56 -0
- data/spec/unit/schemas/requirements_schema_spec.rb +16 -0
- data/spec/unit/unit_spec_helper.rb +11 -0
- data/tasks/compatibility.rake +113 -0
- data/tasks/evaluation.rake +162 -0
- data/wiki/adapter_tests.md +99 -0
- data/wiki/implement_new_adapter.md +155 -0
- metadata +836 -0
data/Rakefile
ADDED
|
@@ -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
|
data/bin/nucleus
ADDED
|
@@ -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!
|
data/bin/nucleus.bat
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@ruby -C%~dp0.. "%~dp0nucleus" %*
|
data/config.ru
ADDED
|
@@ -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,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 (!)'
|
data/lib/nucleus.rb
ADDED
|
@@ -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
|