vagrant-orchestrate 0.0.1

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 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