nucleus 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|