vagrant-orchestrate 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 85f4c2c23fc36ac0e8c472263b585d736444cde7
4
+ data.tar.gz: d85359d431acc54e007e5089e97b5391dc2af394
5
+ SHA512:
6
+ metadata.gz: 14e2b97efed9fd854b9abdb285869780a8e9145f07747105da88e902c73845e4b50d779c9e1059d70d8d59cd4b071181abe419a5ea55f95dd6e954a6a7f96208
7
+ data.tar.gz: bcfe1a59b4013c6905132bced3e6dc9f3617b5edb3594e268ea32ac81e34c846a3191a88ae14c7380cd14f0d2b122402da117bdf345f31035e400433a9dff51a
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+
16
+ /.vagrant/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,18 @@
1
+ AllCops:
2
+ Exclude:
3
+ - '*.gemspec'
4
+
5
+ Metrics/LineLength:
6
+ Max: 120
7
+
8
+ Style/Documentation:
9
+ Enabled: false
10
+
11
+ Metrics/MethodLength:
12
+ Max: 20
13
+
14
+ StringLiterals:
15
+ EnforcedStyle: double_quotes
16
+
17
+ Style/FileName:
18
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in vagrant-orchestrate.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem "vagrant", git: "https://github.com/mitchellh/vagrant.git"
8
+ gem "vagrant-spec", git: "https://github.com/mitchellh/vagrant-spec.git"
9
+ end
10
+
11
+ group :plugins do
12
+ gem "vagrant-orchestrate", path: "."
13
+ gem "vagrant-managed-servers"
14
+ end
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2014 Cimpress
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # Vagrant Orchestrate
2
+
3
+ This is a Vagrant 1.6+ plugin that allows orchestrated deployments
4
+ to existing servers on top of the excellent vagrant-managed-servers plugin.
5
+ It features a powerful templating `init` command and is designed from the
6
+ ground up to be cross-platform, with first class support for Windows,
7
+ Linux, and Mac.
8
+
9
+ ## Usage
10
+
11
+ Install using the standard Vagrant plugin installation method:
12
+
13
+ $ vagrant plugin install vagrant-orchestrate
14
+
15
+ ### Initialization
16
+ Initialize a Vagrantfile to orchestrate running a script on multiple managed servers
17
+
18
+ $ vagrant orchestrate init --shell
19
+
20
+ You'll need to edit your Vagrantfile and replace some of variables, such as ssh username and
21
+ password, and the path to the script to run. The first line of the file defines an array of
22
+ managed servers that the `push` command will operate on.
23
+
24
+ This works for Windows managed servers as well
25
+
26
+ $ vagrant orchestrate init --winrm [--winrm-username=USERNAME --winrm-password=PASSWORD]
27
+
28
+ For a full list of init options, run `vagrant orchestrate init --help`
29
+
30
+ ### Pushing changes
31
+ Go ahead and push changes to your managed servers.
32
+
33
+ $ vagrant orchestrate push
34
+
35
+ You can run vagrant with increased verbosity if you run into problems
36
+
37
+ $ vagrant orchestrate push --debug
38
+
39
+ ## Branching strategy
40
+
41
+ If you have several environments (e.g. dev, test, prod), it is recommended to create
42
+ a separate branch for each environment and put the appropriate servers into the
43
+ managed_servers array at the top of the Vagrantfile for each. To move a change
44
+ across branches, simply create a feature branch from your earliest branch and then
45
+ merge that feature into downstream environments to avoid conflicts.
46
+
47
+ ## Tips for Windows hosts
48
+
49
+ * Need rsync? Install [OpenSSH](http://www.mls-software.com/opensshd.html) and then run this [script]() to install rsync. Vagrant managed servers currently only works with cygwin based rsync implementations.
50
+
51
+ ## Contributing
52
+
53
+ 1. Fork it ( https://github.com/chrisbaldauf/vagrant-orchestrate/fork )
54
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
55
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
56
+ 4. Push to the branch (`git push origin my-new-feature`)
57
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require "rubocop/rake_task"
3
+
4
+ RuboCop::RakeTask.new
@@ -0,0 +1,145 @@
1
+ require "optparse"
2
+ require "vagrant"
3
+
4
+ # rubocop:disable Metrics/ClassLength
5
+ module VagrantPlugins
6
+ module Orchestrate
7
+ module Command
8
+ class Init < Vagrant.plugin("2", :command)
9
+ include Vagrant::Util
10
+
11
+ DEFAULT_SHELL_PATH = "{{YOUR_SCRIPT_PATH}}"
12
+ DEFAULT_SHELL_INLINE = "{{YOUR_SCRIPT_COMMAND}}"
13
+ DEFAULT_WINRM_USERNAME = "{{YOUR_WINRM_USERNAME}}"
14
+ DEFAULT_WINRM_PASSWORD = "{{YOUR_WINRM_PASSWORD}}"
15
+ DEFAULT_SSH_USERNAME = "{{YOUR_SSH_USERNAME}}"
16
+ DEFAULT_SSH_PASSWORD = "{{YOUR_SSH_PASSWORD}}"
17
+ DEFAULT_SSH_PRIVATE_KEY_PATH = "{{YOUR_SSH_PRIVATE_KEY_PATH}}"
18
+ DEFAULT_PLUGINS = ["vagrant-managed-servers"]
19
+
20
+ # rubocop:disable Metrics/AbcSize, MethodLength
21
+ def execute
22
+ options = {}
23
+
24
+ options[:provisioners] = []
25
+ options[:servers] = []
26
+ options[:plugins] = DEFAULT_PLUGINS
27
+
28
+ opts = OptionParser.new do |o|
29
+ o.banner = "Usage: vagrant orchestrate init [options]"
30
+ o.separator ""
31
+ o.separator "Options:"
32
+ o.separator ""
33
+
34
+ o.on("--provision-with x,y,z", Array, "Init only certain provisioners, by type.") do |list|
35
+ options[:provisioners] = list
36
+ end
37
+
38
+ o.on("--shell", "Shorthand for --provision-with shell") do
39
+ options[:provisioners] << "shell"
40
+ end
41
+
42
+ o.on("--shell-paths x,y,z", Array,
43
+ "Comma separated list of shell scripts to run on provision. Only with --shell") do |list|
44
+ options[:shell_paths] = list
45
+ end
46
+
47
+ o.on("--shell-inline command", String, "Inline script to run. Only with --shell") do |c|
48
+ options[:shell_inline] = c
49
+ end
50
+
51
+ o.on("--puppet", "Shorthand for --provisioner-with=puppet") do
52
+ options[:provisioners] << "puppet"
53
+ end
54
+
55
+ o.on("--ssh-username USERNAME", String, "The username for communicating over ssh") do |u|
56
+ options[:ssh_username] = u
57
+ end
58
+
59
+ o.on("--ssh-password PASSWORD", String, "The username for communicating over ssh") do |p|
60
+ options[:ssh_password] = p
61
+ end
62
+
63
+ o.on("--ssh-private-key-path PATH", String, "Paths to the private key for communinicating over ssh") do |k|
64
+ options[:ssh_private_key_path] = k
65
+ end
66
+
67
+ o.on("--winrm", "Use the winrm communicator") do
68
+ options[:communicator] = "winrm"
69
+ end
70
+
71
+ o.on("--winrm-username USERNAME", String, "The username for communicating with winrm") do |u|
72
+ options[:winrm_username] = u
73
+ end
74
+
75
+ o.on("--winrm-password PASSWORD", String, "The password for communicating with winrm") do |p|
76
+ options[:winrm_password] = p
77
+ end
78
+
79
+ o.on("--plugins x,y,z", Array, "A comma separated list of vagrant plugins to be installed") do |p|
80
+ options[:plugins] += p
81
+ end
82
+
83
+ o.on("--servers x,y,z", Array, "A comma separated list of servers hostnames or IPs to deploy to") do |list|
84
+ options[:servers] = list
85
+ end
86
+
87
+ o.on("-f", "--force", "Force overwriting of files") do
88
+ options[:force] = true
89
+ end
90
+ end
91
+
92
+ argv = parse_options(opts)
93
+ return unless argv
94
+
95
+ options[:shell_paths] ||= options[:shell_inline] ? [] : [DEFAULT_SHELL_PATH]
96
+ options[:shell_inline] ||= DEFAULT_SHELL_INLINE
97
+ options[:winrm_username] ||= DEFAULT_WINRM_USERNAME
98
+ options[:winrm_password] ||= DEFAULT_WINRM_PASSWORD
99
+ options[:communicator] ||= "ssh"
100
+ options[:ssh_username] ||= DEFAULT_SSH_USERNAME
101
+ options[:ssh_password] ||= DEFAULT_SSH_PASSWORD unless options[:ssh_private_key_path]
102
+ options[:ssh_private_key_path] ||= DEFAULT_SSH_PRIVATE_KEY_PATH
103
+
104
+ contents = TemplateRenderer.render(Orchestrate.source_root.join("templates/vagrant/Vagrantfile"),
105
+ provisioners: options[:provisioners],
106
+ shell_paths: options[:shell_paths],
107
+ shell_inline: options[:shell_inline],
108
+ communicator: options[:communicator],
109
+ winrm_username: options[:winrm_username],
110
+ winrm_password: options[:winrm_password],
111
+ ssh_username: options[:ssh_username],
112
+ ssh_password: options[:ssh_password],
113
+ ssh_private_key_path: options[:ssh_private_key_path],
114
+ servers: options[:servers],
115
+ plugins: options[:plugins]
116
+ )
117
+ write_vagrantfile(contents, options)
118
+
119
+ @env.ui.info(I18n.t("vagrant.commands.init.success"), prefix: false)
120
+
121
+ # Success, exit status 0
122
+ 0
123
+ end
124
+ # rubocop:enable Metrics/AbcSize, MethodLength
125
+
126
+ private
127
+
128
+ def write_vagrantfile(contents, options)
129
+ save_path = Pathname.new("Vagrantfile").expand_path(@env.cwd)
130
+ save_path.delete if save_path.exist? && options[:force]
131
+ fail Vagrant::Errors::VagrantfileExistsError if save_path.exist?
132
+
133
+ begin
134
+ save_path.open("w+") do |f|
135
+ f.write(contents)
136
+ end
137
+ rescue Errno::EACCES
138
+ raise Vagrant::Errors::VagrantfileWriteError
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ # rubocop:enable Metrics/ClassLength
@@ -0,0 +1,35 @@
1
+ require "optparse"
2
+ require "vagrant"
3
+
4
+ module VagrantPlugins
5
+ module Orchestrate
6
+ module Command
7
+ class Push < Vagrant.plugin("2", :command)
8
+ include Vagrant::Util
9
+
10
+ def execute
11
+ options = {}
12
+
13
+ opts = OptionParser.new do |o|
14
+ o.banner = "Usage: vagrant orchestrate push"
15
+ o.separator ""
16
+ end
17
+
18
+ # Parse the options
19
+ argv = parse_options(opts)
20
+
21
+ with_target_vms(argv, provider: :managed) do |machine|
22
+ unless machine.name.to_s.start_with? "managed-"
23
+ @logger.debug("Skipping machine #{machine.name}")
24
+ next
25
+ end
26
+
27
+ machine.action(:up, options)
28
+ machine.action(:provision, options)
29
+ machine.action(:destroy, options)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,74 @@
1
+ require "optparse"
2
+ require "vagrant"
3
+
4
+ module VagrantPlugins
5
+ module Orchestrate
6
+ module Command
7
+ class Root < Vagrant.plugin(2, :command)
8
+ def self.synopsis
9
+ 'Orchestrates provsioning of managed servers. Useful for deploying changes \
10
+ repeatedly across multiple managed environments'
11
+ end
12
+
13
+ def initialize(argv, env)
14
+ super
15
+
16
+ @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
17
+
18
+ @subcommands = Vagrant::Registry.new
19
+
20
+ @subcommands.register(:init) do
21
+ require_relative "init"
22
+ Init
23
+ end
24
+
25
+ @subcommands.register(:push) do
26
+ require_relative "push"
27
+ Push
28
+ end
29
+ end
30
+
31
+ def execute
32
+ if @main_args.include?("-h") || @main_args.include?("--help")
33
+ # Print the help for all the box commands.
34
+ return help
35
+ end
36
+
37
+ # If we reached this far then we must have a subcommand. If not,
38
+ # then we also just print the help and exit.
39
+ command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
40
+ return help if !command_class || !@sub_command
41
+ @logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
42
+
43
+ # Initialize and execute the command class
44
+ command_class.new(@sub_args, @env).execute
45
+ end
46
+
47
+ # Prints the help out for this command
48
+ # rubocop:disable Metrics/AbcSize
49
+ def help
50
+ opts = OptionParser.new do |o|
51
+ o.banner = "Usage: vagrant orchestrate <subcommand> [<args>]"
52
+ o.separator ""
53
+ o.separator "Available subcommands:"
54
+
55
+ # Add the available subcommands as separators in order to print them
56
+ # out as well.
57
+ keys = []
58
+ @subcommands.each { |key, _value| keys << key.to_s }
59
+
60
+ keys.sort.each do |key|
61
+ o.separator " #{key}"
62
+ end
63
+
64
+ o.separator ""
65
+ o.separator "For help on any individual subcommand run `vagrant orchestrate <subcommand> -h`"
66
+ end
67
+
68
+ @env.ui.info(opts.help, prefix: false)
69
+ end
70
+ # rubocop:enable Metrics/AbcSize
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,62 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant Orchestrate plugin must be run within Vagrant."
5
+ end
6
+
7
+ # This is a sanity check to make sure no one is attempting to install
8
+ # this into an early Vagrant version.
9
+ if Vagrant::VERSION < "1.6.0"
10
+ fail "The Vagrant Orchestrate plugin is only compatible with Vagrant 1.6+"
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module Orchestrate
15
+ class Plugin < Vagrant.plugin("2")
16
+ name "Orchestrate"
17
+ description <<-DESC
18
+ This plugin installs commands that make pushing changes to vagrant-managed-servers easy.
19
+ DESC
20
+
21
+ command(:orchestrate) do
22
+ require_relative "command/root"
23
+ Command::Root
24
+ end
25
+
26
+ # This initializes the internationalization strings.
27
+ def self.setup_i18n
28
+ I18n.load_path << File.expand_path("locales/en.yml", Orchestrate.source_root)
29
+ I18n.reload!
30
+ end
31
+
32
+ # This sets up our log level to be whatever VAGRANT_LOG is.
33
+ def self.setup_logging
34
+ require "log4r"
35
+
36
+ level = nil
37
+ begin
38
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
39
+ rescue NameError
40
+ # This means that the logging constant wasn't found,
41
+ # which is fine. We just keep `level` as `nil`. But
42
+ # we tell the user.
43
+ level = nil
44
+ end
45
+
46
+ # Some constants, such as "true" resolve to booleans, so the
47
+ # above error checking doesn't catch it. This will check to make
48
+ # sure that the log level is an integer, as Log4r requires.
49
+ level = nil unless level.is_a?(Integer)
50
+
51
+ # Set the logging level on all "vagrant" namespaced
52
+ # logs as long as we have a valid level.
53
+ if level
54
+ Log4r::Logger.new("vagrant_orchestrate").tap do |logger|
55
+ logger.outputters = Log4r::Outputter.stderr
56
+ logger.level = level
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module Orchestrate
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ require "vagrant-orchestrate/plugin"
2
+
3
+ module VagrantPlugins
4
+ module Orchestrate
5
+ # This returns the path to the source of this plugin.
6
+ #
7
+ # @return [Pathname]
8
+ def self.source_root
9
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
10
+ end
11
+ end
12
+ end
data/locales/en.yml ADDED
File without changes
@@ -0,0 +1,28 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = "random"
17
+ end
18
+
19
+ def capture_stdout(&_block)
20
+ original_stdout = $stdout
21
+ $stdout = fake = StringIO.new
22
+ begin
23
+ yield
24
+ ensure
25
+ $stdout = original_stdout
26
+ end
27
+ fake.string
28
+ end
@@ -0,0 +1,198 @@
1
+ require "vagrant-orchestrate/command/init"
2
+ require "vagrant-spec/unit"
3
+ require "pp"
4
+
5
+ describe VagrantPlugins::Orchestrate::Command::Init do
6
+ include_context "vagrant-unit"
7
+
8
+ let(:base_argv) { ["-f"] }
9
+ let(:argv) { [] }
10
+ let(:iso_env) do
11
+ env = isolated_environment
12
+ # We need to load an empty vagrantfile in order for things to be initialized
13
+ # properly
14
+ env.vagrantfile("")
15
+ env.create_vagrant_env ui_class: ui_class
16
+ end
17
+
18
+ let(:ui_class) { nil }
19
+
20
+ subject { described_class.new(base_argv + argv, iso_env) }
21
+
22
+ ["-h", "--help"].each do |arg|
23
+ describe "init help message #{arg}" do
24
+ let(:argv) { ["init", arg] }
25
+ let(:ui_class) { Vagrant::UI::Basic }
26
+ it "shows help" do
27
+ output = capture_stdout { subject.execute }
28
+ expect(output).to include("Usage: vagrant orchestrate init [options]")
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "no parameters" do
34
+ it "creates basic vagrantfile" do
35
+ subject.execute
36
+ expect(Dir.entries(iso_env.cwd)).to include("Vagrantfile")
37
+ end
38
+ end
39
+
40
+ context "shell provisioner" do
41
+ describe "basic operation" do
42
+ let(:argv) { ["--shell"] }
43
+ it "creates a vagrantfile with default shell path" do
44
+ subject.execute
45
+ expect(iso_env.vagrantfile.config.vm.provisioners.first.type).to eq(:shell)
46
+ expect(iso_env.vagrantfile.config.vm.provisioners.first.config.path).to eq(described_class::DEFAULT_SHELL_PATH)
47
+ end
48
+ end
49
+
50
+ describe "shell path" do
51
+ let(:argv) { ["--shell", "--shell-paths", "foo.sh"] }
52
+ it "creates a vagrantfile with custom shell path" do
53
+ subject.execute
54
+ expect(iso_env.vagrantfile.config.vm.provisioners.first.type).to eq(:shell)
55
+ expect(iso_env.vagrantfile.config.vm.provisioners.first.config.path).to eq("foo.sh")
56
+ end
57
+ end
58
+
59
+ describe "shell inline" do
60
+ let(:argv) { ["--shell", "--shell-inline", "echo Hello, World!"] }
61
+ it "is passed through" do
62
+ subject.execute
63
+ expect(iso_env.vagrantfile.config.vm.provisioners.first.config.inline).to eq("echo Hello, World!")
64
+ end
65
+ end
66
+
67
+ describe "multiple shell paths" do
68
+ let(:argv) { ["--shell", "--shell-paths", "foo.sh,bar.sh"] }
69
+ it "creates a vagrantfile with custom shell path" do
70
+ subject.execute
71
+ expect(iso_env.vagrantfile.config.vm.provisioners.first.type).to eq(:shell)
72
+ expect(iso_env.vagrantfile.config.vm.provisioners.first.config.path).to eq("foo.sh")
73
+ expect(iso_env.vagrantfile.config.vm.provisioners[1].config.path).to eq("bar.sh")
74
+ end
75
+ end
76
+ end
77
+
78
+ context "puppet provisioner" do
79
+ describe "basic operation" do
80
+ let(:argv) { ["--provision-with", "puppet"] }
81
+ it "creates a vagrantfile with a puppet provisioner" do
82
+ subject.execute
83
+ expect(iso_env.vagrantfile.config.vm.provisioners.first.type).to eq(:puppet)
84
+ end
85
+ end
86
+
87
+ describe "shorthand" do
88
+ let(:argv) { ["--puppet"] }
89
+ it "creates a vagrantfile with a puppet provisioner" do
90
+ subject.execute
91
+ expect(iso_env.vagrantfile.config.vm.provisioners.first.type).to eq(:puppet)
92
+ end
93
+ end
94
+ end
95
+
96
+ context "winrm" do
97
+ describe "basic" do
98
+ let(:argv) { ["--winrm"] }
99
+ it "creates a vagrantfile with the winrm communicator" do
100
+ subject.execute
101
+ expect(iso_env.vagrantfile.config.vm.communicator).to eq(:winrm)
102
+ expect(iso_env.vagrantfile.config.winrm.username).to eq(described_class::DEFAULT_WINRM_USERNAME)
103
+ expect(iso_env.vagrantfile.config.winrm.password).to eq(described_class::DEFAULT_WINRM_PASSWORD)
104
+ end
105
+ end
106
+
107
+ describe "username" do
108
+ let(:argv) { ["--winrm", "--winrm-username", "WINRM_USERNAME"] }
109
+ it "is parsed correctly" do
110
+ subject.execute
111
+ expect(iso_env.vagrantfile.config.winrm.username).to eq("WINRM_USERNAME")
112
+ end
113
+ end
114
+
115
+ describe "password" do
116
+ let(:argv) { ["--winrm", "--winrm-password", "WINRM_PASSWORD"] }
117
+ it "is parsed correctly" do
118
+ subject.execute
119
+ expect(iso_env.vagrantfile.config.winrm.password).to eq("WINRM_PASSWORD")
120
+ end
121
+ end
122
+ end
123
+
124
+ context "ssh" do
125
+ describe "default" do
126
+ it "has default username and password" do
127
+ subject.execute
128
+ expect(iso_env.vagrantfile.config.ssh.username).to eq(described_class::DEFAULT_SSH_USERNAME)
129
+ expect(iso_env.vagrantfile.config.ssh.password).to eq(described_class::DEFAULT_SSH_PASSWORD)
130
+ end
131
+ end
132
+
133
+ describe "username" do
134
+ let(:argv) { ["--ssh-username", "SSH_USERNAME"] }
135
+ it "is passed through" do
136
+ subject.execute
137
+ expect(iso_env.vagrantfile.config.ssh.username).to eq("SSH_USERNAME")
138
+ end
139
+ end
140
+
141
+ describe "password" do
142
+ let(:argv) { ["--ssh-password", "SSH_PASSWORD"] }
143
+ it "is passed through" do
144
+ subject.execute
145
+ expect(iso_env.vagrantfile.config.ssh.password).to eq("SSH_PASSWORD")
146
+ end
147
+ end
148
+
149
+ describe "private key path" do
150
+ let(:argv) { ["--ssh-private-key-path", "SSH_PRIVATE_KEY_PATH"] }
151
+ it "is passed through" do
152
+ subject.execute
153
+ expect(iso_env.vagrantfile.config.ssh.private_key_path.first).to eq("SSH_PRIVATE_KEY_PATH")
154
+ end
155
+ end
156
+ end
157
+
158
+ context "plugins" do
159
+ describe "default" do
160
+ it "has default plugins in vagrantfile" do
161
+ subject.execute
162
+ # Since the plugin stuff isn't part of the actual Vagrantfile spec, we'll
163
+ # just peek at the text of the file
164
+ vagrantfile = File.readlines(File.join(iso_env.cwd, "Vagrantfile")).join
165
+ expect(vagrantfile).to include("required_plugins = %w( #{described_class::DEFAULT_PLUGINS.join(' ')} )")
166
+ end
167
+ end
168
+
169
+ describe "specified plugins" do
170
+ let(:argv) { ["--plugins", "plugin1,plugin2"] }
171
+ it "are required" do
172
+ subject.execute
173
+ expected = "required_plugins = %w( #{described_class::DEFAULT_PLUGINS.join(' ')} plugin1 plugin2 )"
174
+ vagrantfile = File.readlines(File.join(iso_env.cwd, "Vagrantfile")).join
175
+ expect(vagrantfile).to include(expected)
176
+ end
177
+ end
178
+ end
179
+
180
+ context "servers" do
181
+ describe "default" do
182
+ it "has no servers in vagrantfile" do
183
+ subject.execute
184
+ vagrantfile = File.readlines(File.join(iso_env.cwd, "Vagrantfile")).join
185
+ expect(vagrantfile).to include("managed_servers = %w( )")
186
+ end
187
+ end
188
+
189
+ describe "specified servers" do
190
+ let(:argv) { ["--servers", "server1,server2"] }
191
+ it "are required" do
192
+ subject.execute
193
+ vagrantfile = File.readlines(File.join(iso_env.cwd, "Vagrantfile")).join
194
+ expect(vagrantfile).to include("managed_servers = %w( server1 server2 )")
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,27 @@
1
+ require "vagrant-orchestrate/command/root"
2
+ require "vagrant-orchestrate/command/init"
3
+ require "vagrant-spec/unit"
4
+
5
+ describe VagrantPlugins::Orchestrate::Command::Root do
6
+ include_context "vagrant-unit"
7
+
8
+ let(:argv) { [] }
9
+ let(:iso_env) do
10
+ env = isolated_environment
11
+ env.vagrantfile("")
12
+ env.create_vagrant_env ui_class: Vagrant::UI::Basic
13
+ end
14
+
15
+ subject { described_class.new(argv, iso_env) }
16
+
17
+ ["", "-h", "--help"].each do |arg|
18
+ describe "root help message #{arg}" do
19
+ let(:argv) { [arg] }
20
+ it "shows help" do
21
+ output = capture_stdout { subject.execute }
22
+ expect(output).to \
23
+ include("Usage: vagrant orchestrate <subcommand> [<args>]")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,45 @@
1
+ managed_servers = %w( <% servers.each do |s| -%><%= s %> <% end -%>)
2
+
3
+ <% if plugins.any? -%>
4
+ required_plugins = %w( <% plugins.each do |p| -%><%= p %> <% end -%>)
5
+ required_plugins.each do |plugin|
6
+ system "vagrant plugin install #{plugin}" unless Vagrant.has_plugin? plugin
7
+ end
8
+ <% end %>
9
+ Vagrant.configure("2") do |config|
10
+ <% if provisioners.include? "shell" -%>
11
+ <% shell_paths.each do |path| -%>
12
+ config.vm.provision "shell", path: "<%= path %>"
13
+ <% end -%>
14
+ <% if shell_inline -%>
15
+ config.vm.provision "shell", inline: "<%= shell_inline %>"
16
+ <% end -%>
17
+ <% end -%>
18
+ <% if provisioners.include? "puppet" -%>
19
+ config.vm.provision "puppet" do |puppet|
20
+ end
21
+ <% end -%>
22
+ <% if communicator == "ssh" -%>
23
+ config.ssh.username = "<%= ssh_username %>"
24
+ <% if ssh_password -%>
25
+ config.ssh.password = "<%= ssh_password %>"
26
+ <% end -%>
27
+ <% if !ssh_password -%>
28
+ config.ssh.private_key_path = "<%= ssh_private_key_path %>"
29
+ <% end -%>
30
+ <% end -%>
31
+ <% if communicator == "winrm" -%>
32
+ config.vm.communicator = "<%= communicator %>"
33
+ config.winrm.username = "<%= winrm_username %>"
34
+ config.winrm.password = "<%= winrm_password %>"
35
+ <% end -%>
36
+
37
+ managed_servers.each do |instance|
38
+ config.vm.define "managed-#{instance}" do |box|
39
+ box.vm.box = "tknerr/managed-server-dummy"
40
+ box.vm.provider :managed do |provider|
41
+ provider.server = instance
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vagrant-orchestrate/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'vagrant-orchestrate'
8
+ spec.version = VagrantPlugins::Orchestrate::VERSION
9
+ spec.authors = ['Christopher Baldauf']
10
+ spec.email = ['cbaldauf@cimpress.com']
11
+ spec.summary = 'Vagrant plugin to orchestrate the deployment of managed servers.'
12
+ spec.homepage = ''
13
+ spec.license = 'Apache 2.0'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_development_dependency 'bundler', '~> 1.6'
21
+ spec.add_development_dependency 'rake', '~> 10.0'
22
+ spec.add_development_dependency 'rspec'
23
+ # See Gemfile for additional development dependencies that were not available
24
+ # on rubygems (or another gem source), but needed to be downloaded from git.
25
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-orchestrate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Christopher Baldauf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - cbaldauf@cimpress.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - .rspec
64
+ - .rubocop.yml
65
+ - Gemfile
66
+ - LICENSE
67
+ - README.md
68
+ - Rakefile
69
+ - lib/vagrant-orchestrate.rb
70
+ - lib/vagrant-orchestrate/command/init.rb
71
+ - lib/vagrant-orchestrate/command/push.rb
72
+ - lib/vagrant-orchestrate/command/root.rb
73
+ - lib/vagrant-orchestrate/plugin.rb
74
+ - lib/vagrant-orchestrate/version.rb
75
+ - locales/en.yml
76
+ - spec/spec_helper.rb
77
+ - spec/vagrant-orchestrate/command/init_spec.rb
78
+ - spec/vagrant-orchestrate/command/root_spec.rb
79
+ - templates/vagrant/Vagrantfile.erb
80
+ - vagrant-orchestrate.gemspec
81
+ homepage: ''
82
+ licenses:
83
+ - Apache 2.0
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.0.14
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Vagrant plugin to orchestrate the deployment of managed servers.
105
+ test_files:
106
+ - spec/spec_helper.rb
107
+ - spec/vagrant-orchestrate/command/init_spec.rb
108
+ - spec/vagrant-orchestrate/command/root_spec.rb