vcloud-launcher 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +2 -0
- data/CHANGELOG.md +13 -0
- data/CONTRIBUTING.md +66 -0
- data/Gemfile +2 -2
- data/Rakefile +3 -9
- data/bin/vcloud-launch +1 -44
- data/lib/vcloud/launcher.rb +2 -0
- data/lib/vcloud/launcher/cli.rb +103 -0
- data/lib/vcloud/launcher/launch.rb +36 -1
- data/lib/vcloud/launcher/preamble.rb +60 -0
- data/lib/vcloud/launcher/version.rb +1 -1
- data/lib/vcloud/launcher/vm_orchestrator.rb +10 -5
- data/spec/integration/README.md +1 -1
- data/spec/integration/launcher/data/storage_profile.yaml.erb +0 -30
- data/spec/integration/launcher/{vcloud_launcher_spec.rb → launch_spec.rb} +42 -31
- data/spec/integration/launcher/storage_profile_integration_spec.rb +23 -35
- data/spec/spec_helper.rb +29 -0
- data/spec/vcloud/launcher/cli_spec.rb +214 -0
- data/spec/vcloud/launcher/launch_spec.rb +107 -1
- data/spec/vcloud/launcher/preamble_spec.rb +214 -0
- data/spec/vcloud/launcher/vapp_orchestrator_spec.rb +14 -14
- data/spec/vcloud/launcher/vm_orchestrator_spec.rb +109 -22
- data/vcloud-launcher.gemspec +8 -8
- metadata +40 -71
- data/features/step_definitions/vcloud-launch_steps.rb +0 -3
- data/features/support/env.rb +0 -16
- data/features/vcloud-launch.feature +0 -18
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## 0.2.0 (2014-07-14)
|
2
|
+
|
3
|
+
Features:
|
4
|
+
|
5
|
+
- `vcloud-configure-edge --version` now only returns the version string
|
6
|
+
and no usage information.
|
7
|
+
|
8
|
+
API changes:
|
9
|
+
|
10
|
+
- New `Vcloud::Launcher::Preamble` class for generating preambles, containing
|
11
|
+
logic moved from vCloud Core. Thanks to @bazbremner for this contribution.
|
12
|
+
- The minimum required Ruby version is now 1.9.3.
|
13
|
+
|
1
14
|
## 0.1.0 (2014-06-02)
|
2
15
|
|
3
16
|
Features:
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Contributing to vCloud Launcher
|
2
|
+
|
3
|
+
We really welcome contributions.
|
4
|
+
|
5
|
+
## A quick guide on how to contribute
|
6
|
+
|
7
|
+
1. Clone the repo:
|
8
|
+
|
9
|
+
git clone git@github.com:gds-operations/vcloud-launcher.git
|
10
|
+
|
11
|
+
2. Run `bundle` to get the required dependecies
|
12
|
+
|
13
|
+
3. Run the tests. Pull requests that add features must include unit tests,
|
14
|
+
so it is good to ensure you've got them passing to begin with.
|
15
|
+
|
16
|
+
bundle exec rake
|
17
|
+
|
18
|
+
If you have access to a live environment for testing, it would be great
|
19
|
+
if you could run the integration tests too - for more details on the
|
20
|
+
set-up for that, please see the [integration tests README]
|
21
|
+
(https://github.com/gds-operations/vcloud-launcher/blob/master/spec/integration/README.md)
|
22
|
+
|
23
|
+
4. Add your functionality or bug fix and a test for your change. Only refactoring and
|
24
|
+
documentation changes do not require tests. If the functionality is at all complicated
|
25
|
+
then it is likely that more than one test will be required. If you would like help
|
26
|
+
with writing tests please do ask us.
|
27
|
+
|
28
|
+
5. Make sure all the tests pass, including the integration tests if possible.
|
29
|
+
|
30
|
+
6. Update the [CHANGELOG](https://github.com/gds-operations/vcloud-launcher/blob/master/CHANGELOG.md)
|
31
|
+
with a short description of what the change is. This may be a feature, a bugfix, or an
|
32
|
+
API change. If your change is documenation or refactoring, you do not need to add a line
|
33
|
+
to the CHANGELOG.
|
34
|
+
|
35
|
+
7. Fork the repo, push to your fork, and submit a pull request.
|
36
|
+
|
37
|
+
## How soon will we respond?
|
38
|
+
|
39
|
+
We will comment on your pull request within two working days. However, we might not be able to review it immediately.
|
40
|
+
|
41
|
+
We may come back to you with comments and suggestions, and if we would like you to make changes, we will close the pull request as well as adding details of the changes we'd like you to make.
|
42
|
+
|
43
|
+
If you feel your pull request has been outstanding too long, please feel free to bump it by making a comment on it.
|
44
|
+
|
45
|
+
## Guidelines for making a pull request
|
46
|
+
|
47
|
+
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
|
48
|
+
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
|
49
|
+
interpreted as described in RFC 2119.
|
50
|
+
|
51
|
+
## In order for a pull request to be accepted, it MUST
|
52
|
+
|
53
|
+
- Include at least one test (unless it is documentation or refactoring). If you have any questions about how to write tests, please ask us, we will be happy to help
|
54
|
+
- Follow our [Git style guide](https://github.com/alphagov/styleguides/blob/master/git.md)
|
55
|
+
- Include a clear summary in the pull request comments as to what the change is and why
|
56
|
+
you are making it
|
57
|
+
- Be readable - we might ask you to change unclear variable names or obscure syntactic sugar
|
58
|
+
- Have [good commit messages](http://robots.thoughtbot.com/5-useful-tips-for-a-better-commit-message)
|
59
|
+
that explain the change being made in that commit. Don't be afraid to write a lot in the
|
60
|
+
detail.
|
61
|
+
|
62
|
+
## In order for a pull request to be accepted, it SHOULD
|
63
|
+
|
64
|
+
- Include a line in the CHANGELOG unless it is a refactoring or documentation change
|
65
|
+
- If it is code, follow our [Ruby style guide](https://github.com/alphagov/styleguides/blob/master/ruby.md)
|
66
|
+
- If it is documentation, follow the [GDS content style guide](https://www.gov.uk/design-principles/style-guide/style-points)
|
data/Gemfile
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
source '
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
if ENV['VCLOUD_CORE_DEV_MASTER']
|
6
|
-
gem 'vcloud-core', :git => 'git@github.com:
|
6
|
+
gem 'vcloud-core', :git => 'git@github.com:gds-operations/vcloud-core.git', :branch => 'master'
|
7
7
|
elsif ENV['VCLOUD_CORE_DEV_LOCAL']
|
8
8
|
gem 'vcloud-core', :path => '../vcloud-core'
|
9
9
|
end
|
data/Rakefile
CHANGED
@@ -1,23 +1,17 @@
|
|
1
|
-
require 'cucumber/rake/task'
|
2
1
|
require 'rspec/core/rake_task'
|
3
2
|
require 'gem_publisher'
|
4
3
|
|
5
|
-
task :default => [:rubocop, :spec
|
4
|
+
task :default => [:rubocop, :spec]
|
6
5
|
task :integration => ['integration:all']
|
7
6
|
|
8
7
|
RSpec::Core::RakeTask.new(:spec) do |task|
|
9
8
|
# Set a bogus Fog credential, otherwise it's possible for the unit
|
10
|
-
# tests to accidentially run (and succeed against!) an actual
|
9
|
+
# tests to accidentially run (and succeed against!) an actual
|
11
10
|
# environment, if Fog connection is not stubbed correctly.
|
12
11
|
ENV['FOG_CREDENTIAL'] = 'random_nonsense_owiejfoweijf'
|
13
12
|
task.pattern = FileList['spec/vcloud/**/*_spec.rb']
|
14
13
|
end
|
15
14
|
|
16
|
-
Cucumber::Rake::Task.new(:features) do |t|
|
17
|
-
t.cucumber_opts = "--format pretty --no-source"
|
18
|
-
t.fork = false
|
19
|
-
end
|
20
|
-
|
21
15
|
RSpec::Core::RakeTask.new('integration:quick') do |t|
|
22
16
|
t.rspec_opts = %w(--tag ~take_too_long)
|
23
17
|
t.pattern = FileList['spec/integration/**/*_spec.rb']
|
@@ -33,6 +27,6 @@ task :publish_gem do
|
|
33
27
|
end
|
34
28
|
|
35
29
|
require 'rubocop/rake_task'
|
36
|
-
|
30
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
37
31
|
task.options = ['--lint']
|
38
32
|
end
|
data/bin/vcloud-launch
CHANGED
@@ -1,48 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler/setup'
|
5
|
-
require 'optparse'
|
6
|
-
require 'methadone'
|
7
|
-
|
8
3
|
require 'vcloud/launcher'
|
9
4
|
|
10
|
-
|
11
|
-
include Methadone::Main
|
12
|
-
include Methadone::CLILogging
|
13
|
-
|
14
|
-
main do |org_config_file|
|
15
|
-
Vcloud::Launcher::Launch.new.run(org_config_file, options)
|
16
|
-
end
|
17
|
-
|
18
|
-
on("-x", "--dont-power-on", "Do not power on vApps (default is to power on)")
|
19
|
-
on("-c", "--continue-on-error", "Continue on error ( default is false) ")
|
20
|
-
on("-q", "--quiet", "Quiet output - only report errors")
|
21
|
-
on("-v", "--verbose", "Verbose output")
|
22
|
-
|
23
|
-
arg :org_config_file
|
24
|
-
|
25
|
-
examples_dir = File.absolute_path(
|
26
|
-
File.join(
|
27
|
-
File.dirname(__FILE__),
|
28
|
-
"..",
|
29
|
-
"examples",
|
30
|
-
File.basename(__FILE__),
|
31
|
-
))
|
32
|
-
|
33
|
-
description "
|
34
|
-
vcloud-launch takes a configuration describing a vCloud Org,
|
35
|
-
and tries to make it a reality.
|
36
|
-
|
37
|
-
See https://github.com/alphagov/vcloud-tools for more info
|
38
|
-
|
39
|
-
Example configuration files can be found in:
|
40
|
-
#{examples_dir}
|
41
|
-
"
|
42
|
-
|
43
|
-
version Vcloud::Launcher::VERSION
|
44
|
-
|
45
|
-
#use_log_level_option
|
46
|
-
|
47
|
-
go!
|
48
|
-
end
|
5
|
+
Vcloud::Launcher::Cli.new(ARGV).run
|
data/lib/vcloud/launcher.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
require 'vcloud/fog'
|
2
2
|
require 'vcloud/core'
|
3
3
|
|
4
|
+
require 'vcloud/launcher/cli'
|
4
5
|
require 'vcloud/launcher/schema/vm'
|
5
6
|
require 'vcloud/launcher/schema/vapp'
|
6
7
|
require 'vcloud/launcher/schema/launcher_vapps'
|
7
8
|
|
8
9
|
require 'vcloud/launcher/launch'
|
10
|
+
require 'vcloud/launcher/preamble'
|
9
11
|
require 'vcloud/launcher/vm_orchestrator'
|
10
12
|
require 'vcloud/launcher/vapp_orchestrator'
|
11
13
|
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Vcloud
|
4
|
+
module Launcher
|
5
|
+
class Cli
|
6
|
+
|
7
|
+
def initialize(argv_array)
|
8
|
+
@config_file = nil
|
9
|
+
@usage_text = nil
|
10
|
+
@options = {
|
11
|
+
"dont-power-on" => false,
|
12
|
+
"continue-on-error" => false,
|
13
|
+
"quiet" => false,
|
14
|
+
"verbose" => false,
|
15
|
+
}
|
16
|
+
|
17
|
+
parse(argv_array)
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
begin
|
22
|
+
Vcloud::Launcher::Launch.new.run(@config_file, @options)
|
23
|
+
rescue => error_msg
|
24
|
+
$stderr.puts(error_msg)
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def parse(args)
|
32
|
+
opt_parser = OptionParser.new do |opts|
|
33
|
+
examples_dir = File.absolute_path(
|
34
|
+
File.join(
|
35
|
+
File.dirname(__FILE__),
|
36
|
+
"..",
|
37
|
+
"..",
|
38
|
+
"..",
|
39
|
+
"examples",
|
40
|
+
File.basename($0),
|
41
|
+
))
|
42
|
+
|
43
|
+
opts.banner = <<-EOS
|
44
|
+
Usage: #{$0} [options] config_file
|
45
|
+
|
46
|
+
vcloud-launch takes a configuration describing a vCloud Org,
|
47
|
+
and tries to make it a reality.
|
48
|
+
|
49
|
+
See https://github.com/gds-operations/vcloud-tools for more info
|
50
|
+
|
51
|
+
Example configuration files can be found in:
|
52
|
+
#{examples_dir}
|
53
|
+
EOS
|
54
|
+
|
55
|
+
opts.separator ""
|
56
|
+
opts.separator "Options:"
|
57
|
+
|
58
|
+
opts.on("-x", "--dont-power-on", "Do not power on vApps (default is to power on)") do
|
59
|
+
@options["dont-power-on"] = true
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("-c", "--continue-on-error", "Continue on error (default is false)") do
|
63
|
+
@options["continue-on-error"] = true
|
64
|
+
end
|
65
|
+
|
66
|
+
opts.on("-q", "--quiet", "Quiet output - only report errors") do
|
67
|
+
@options["quiet"] = true
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.on("-v", "--verbose", "Verbose output") do
|
71
|
+
@options["verbose"] = true
|
72
|
+
end
|
73
|
+
|
74
|
+
opts.on("-h", "--help", "Print usage and exit") do
|
75
|
+
$stderr.puts opts
|
76
|
+
exit
|
77
|
+
end
|
78
|
+
|
79
|
+
opts.on("--version", "Display version and exit") do
|
80
|
+
puts Vcloud::Launcher::VERSION
|
81
|
+
exit
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
@usage_text = opt_parser.to_s
|
86
|
+
begin
|
87
|
+
opt_parser.parse!(args)
|
88
|
+
rescue OptionParser::InvalidOption => e
|
89
|
+
exit_error_usage(e)
|
90
|
+
end
|
91
|
+
|
92
|
+
exit_error_usage("must supply config_file") unless args.size == 1
|
93
|
+
@config_file = args.first
|
94
|
+
end
|
95
|
+
|
96
|
+
def exit_error_usage(error)
|
97
|
+
$stderr.puts "#{$0}: #{error}"
|
98
|
+
$stderr.puts @usage_text
|
99
|
+
exit 2
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -2,13 +2,21 @@ module Vcloud
|
|
2
2
|
module Launcher
|
3
3
|
class Launch
|
4
4
|
|
5
|
+
class MissingPreambleError < RuntimeError ; end
|
6
|
+
class MissingConfigurationError < RuntimeError ; end
|
7
|
+
|
8
|
+
attr_reader :config
|
9
|
+
|
5
10
|
def initialize
|
6
11
|
@config_loader = Vcloud::Core::ConfigLoader.new
|
7
12
|
end
|
8
13
|
|
9
14
|
def run(config_file = nil, cli_options = {})
|
10
15
|
set_logging_level(cli_options)
|
11
|
-
config = @config_loader.load_config(config_file, Vcloud::Launcher::Schema::LAUNCHER_VAPPS)
|
16
|
+
@config = @config_loader.load_config(config_file, Vcloud::Launcher::Schema::LAUNCHER_VAPPS)
|
17
|
+
|
18
|
+
validate_config
|
19
|
+
|
12
20
|
config[:vapps].each do |vapp_config|
|
13
21
|
Vcloud::Core.logger.info("Provisioning vApp #{vapp_config[:name]}.")
|
14
22
|
begin
|
@@ -34,6 +42,33 @@ module Vcloud
|
|
34
42
|
end
|
35
43
|
end
|
36
44
|
|
45
|
+
private
|
46
|
+
|
47
|
+
def validate_config
|
48
|
+
@config[:vapps].each do |vapp_config|
|
49
|
+
validate_vapp_config(vapp_config)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def validate_vapp_config(vapp_config)
|
54
|
+
bootstrap_config = vapp_config.fetch(:bootstrap, nil)
|
55
|
+
|
56
|
+
return unless bootstrap_config
|
57
|
+
|
58
|
+
if ! bootstrap_config[:script_path]
|
59
|
+
raise MissingConfigurationError, "Preamble script (script_path) not specified"
|
60
|
+
end
|
61
|
+
|
62
|
+
if bootstrap_config[:script_path] && ! File.exist?( bootstrap_config[:script_path])
|
63
|
+
raise MissingPreambleError, "Unable to find specified preamble script (#{bootstrap_config[:script_path]})"
|
64
|
+
end
|
65
|
+
|
66
|
+
template_vars = bootstrap_config.fetch(:vars, {})
|
67
|
+
|
68
|
+
if bootstrap_config[:script_path] && template_vars.empty?
|
69
|
+
Vcloud::Core.logger.info("Preamble file/template specified without variables to template.")
|
70
|
+
end
|
71
|
+
end
|
37
72
|
end
|
38
73
|
end
|
39
74
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Vcloud
|
2
|
+
module Launcher
|
3
|
+
class Preamble
|
4
|
+
class MissingConfigurationError < StandardError ; end
|
5
|
+
class MissingTemplateError < StandardError ; end
|
6
|
+
|
7
|
+
attr_reader :preamble_vars, :script_path
|
8
|
+
|
9
|
+
def initialize(vapp_name, vm_config)
|
10
|
+
@vapp_name = vapp_name
|
11
|
+
bootstrap_config = vm_config[:bootstrap]
|
12
|
+
|
13
|
+
raise MissingConfigurationError if bootstrap_config.nil?
|
14
|
+
|
15
|
+
@script_path = bootstrap_config.fetch(:script_path, nil)
|
16
|
+
raise MissingTemplateError unless @script_path
|
17
|
+
|
18
|
+
# Missing vars is acceptable - noop template.
|
19
|
+
@preamble_vars = bootstrap_config.fetch(:vars, {})
|
20
|
+
extra_disks = vm_config.fetch(:extra_disks, {})
|
21
|
+
|
22
|
+
@preamble_vars.merge!(extra_disks: extra_disks)
|
23
|
+
|
24
|
+
@script_post_processor = bootstrap_config.fetch(:script_post_processor, nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate
|
28
|
+
@script_post_processor ? post_process_erb_output : interpolated_preamble
|
29
|
+
end
|
30
|
+
|
31
|
+
def interpolated_preamble
|
32
|
+
@interpolated_preamble = interpolate_erb_file
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def interpolate_erb_file
|
38
|
+
erb_vars = OpenStruct.new({
|
39
|
+
vapp_name: @vapp_name,
|
40
|
+
vars: @preamble_vars,
|
41
|
+
})
|
42
|
+
binding_object = erb_vars.instance_eval { binding }
|
43
|
+
template_string = load_erb_file
|
44
|
+
|
45
|
+
ERB.new(template_string, nil, '>-').result(binding_object)
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_erb_file
|
49
|
+
File.read(File.expand_path(@script_path))
|
50
|
+
end
|
51
|
+
|
52
|
+
def post_process_erb_output
|
53
|
+
# Open3.capture2, as we just need to return STDOUT of the post_processor_script
|
54
|
+
Open3.capture2(
|
55
|
+
File.expand_path(@script_post_processor),
|
56
|
+
stdin_data: interpolated_preamble).first
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -17,13 +17,18 @@ module Vcloud
|
|
17
17
|
end
|
18
18
|
@vm.add_extra_disks(vm_config[:extra_disks])
|
19
19
|
@vm.update_metadata(vm_config[:metadata])
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
)
|
20
|
+
|
21
|
+
preamble = vm_config[:bootstrap] ? generate_preamble(vm_config) : ''
|
22
|
+
|
23
|
+
@vm.configure_guest_customization_section(preamble)
|
25
24
|
end
|
26
25
|
|
26
|
+
private
|
27
|
+
|
28
|
+
def generate_preamble(vm_config)
|
29
|
+
preamble = ::Vcloud::Launcher::Preamble.new(@vm.vapp_name, vm_config)
|
30
|
+
preamble.generate
|
31
|
+
end
|
27
32
|
end
|
28
33
|
end
|
29
34
|
end
|