vagrant-orchestrate 0.4.5 → 0.4.6
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 +4 -4
- data/.gitignore +0 -1
- data/Rakefile +13 -0
- data/Vagrantfile +30 -0
- data/acceptance/command/prompt_spec.rb +22 -0
- data/acceptance/command/push_spec.rb +78 -0
- data/acceptance/support-skeletons/basic/Vagrantfile +17 -0
- data/acceptance/support-skeletons/basic/dummy.box +0 -0
- data/acceptance/support-skeletons/prompt/Vagrantfile +16 -0
- data/acceptance/support-skeletons/prompt/dummy.box +0 -0
- data/lib/vagrant-orchestrate/action/setcredentials.rb +21 -40
- data/lib/vagrant-orchestrate/command/push.rb +21 -1
- data/lib/vagrant-orchestrate/plugin.rb +0 -4
- data/lib/vagrant-orchestrate/version.rb +1 -1
- data/spec/vagrant-orchestrate/command/init_spec.rb +0 -1
- data/vagrant-spec.config.rb +4 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d1d37bbcceb73c4aeea0523c3132be46e30a5dd
|
4
|
+
data.tar.gz: 8a2d5192f22543df2a99a31b72bd5fb95037d2e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d09668c2feeef5cafe7fff5885597105f7a1194c1b62ae0c07c0d7958b33abfd8ca201ddd0eee00af4b1713666a71cd88b987d06c6c51f385b0ee62253617ef
|
7
|
+
data.tar.gz: 04d66afcfcb9b2867de6b74b26d8d8b951343fcd16f8c1dc823288ef4d68e5055d8b360e3d15f92641660a188c8e5685967dd0ac94240f710574c3c2c2308d78
|
data/.gitignore
CHANGED
data/Rakefile
CHANGED
@@ -7,3 +7,16 @@ RSpec::Core::RakeTask.new(:spec)
|
|
7
7
|
|
8
8
|
task build: ["rubocop:auto_correct", :spec]
|
9
9
|
task default: :build
|
10
|
+
|
11
|
+
desc "Run acceptance tests with vagrant-spec"
|
12
|
+
task :acceptance do
|
13
|
+
puts "Brining up target servers"
|
14
|
+
# Spinning up local servers here, which the managed provider will connect to
|
15
|
+
# by IP. See the Vagrantfile in the root of the repo for more info.
|
16
|
+
system("vagrant up /local/ --no-provision")
|
17
|
+
# To ensure the ntp sync happens even if the servers are already up
|
18
|
+
system("vagrant provision /local/")
|
19
|
+
system("bundle exec vagrant-spec test --components=orchestrate/push orchestrate/prompt")
|
20
|
+
puts "Destroying target servers"
|
21
|
+
system("vagrant destroy -f /local/")
|
22
|
+
end
|
data/Vagrantfile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
managed_servers = %w( 192.168.10.80 192.168.10.81 192.168.10.82 192.168.10.83)
|
2
|
+
|
3
|
+
Vagrant.configure(2) do |config|
|
4
|
+
# These boxes are defined locally to enable acceptance testing. Spinning up
|
5
|
+
# real boxes in the vagrant-spec environment was expensive because it ignored
|
6
|
+
# the cache and didn't expose a facility to view the vagrant output as it ran.
|
7
|
+
# These machines get spun up in the rake task and then the vagrant-spec tests
|
8
|
+
# connect to them by IP address.
|
9
|
+
managed_servers.each_with_index do |ip, index|
|
10
|
+
config.vm.define "local-#{index + 1}" do |ubuntu|
|
11
|
+
# minimize clock skew, since we're using the `date` command to measure
|
12
|
+
# clock skew.
|
13
|
+
ubuntu.vm.provision :shell, inline: "ntpdate pool.ntp.org"
|
14
|
+
ubuntu.vm.box = "ubuntu/trusty64"
|
15
|
+
ubuntu.vm.network "private_network", ip: ip
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# These managed boxes connect to the local boxes defined above by ip address.
|
20
|
+
managed_servers.each_with_index do |server, index|
|
21
|
+
config.vm.define "managed-#{index + 1}" do |managed|
|
22
|
+
managed.vm.box = "managed-server-dummy"
|
23
|
+
managed.vm.box_url = "./dummy.box"
|
24
|
+
managed.ssh.password = "vagrant"
|
25
|
+
managed.vm.provider :managed do |provider|
|
26
|
+
provider.server = server
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "vagrant-spec"
|
2
|
+
|
3
|
+
describe "vagrant orchestrate prompt", component: "orchestrate/prompt" do
|
4
|
+
include_context "acceptance"
|
5
|
+
|
6
|
+
before do
|
7
|
+
environment.skeleton("prompt")
|
8
|
+
end
|
9
|
+
|
10
|
+
# Vagrant throws with the error message below if a prompt is encountered. We need
|
11
|
+
# to make sure that non-push commands don't prompt
|
12
|
+
# Vagrant is attempting to interface with the UI in a way that requires
|
13
|
+
# a TTY. Most actions in Vagrant that require a TTY have configuration
|
14
|
+
# switches to disable this requirement. Please do that or run Vagrant
|
15
|
+
# with TTY.
|
16
|
+
it "doesn't prompt with non-push commands" do
|
17
|
+
assert_execute("vagrant", "status")
|
18
|
+
end
|
19
|
+
|
20
|
+
# TODO: I wish there was a way to simulate prompting, but for now, that is left
|
21
|
+
# to the user as a manual exercise.
|
22
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "vagrant-spec"
|
2
|
+
|
3
|
+
describe "vagrant orchestrate push", component: "orchestrate/push" do
|
4
|
+
include_context "acceptance"
|
5
|
+
|
6
|
+
before do
|
7
|
+
environment.skeleton("basic")
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can push to a set of managed servers" do
|
11
|
+
assert_execute("vagrant", "orchestrate", "push")
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "strategies" do
|
15
|
+
it "can push in parallel" do
|
16
|
+
assert_execute("vagrant", "orchestrate", "push", "--strategy", "parallel")
|
17
|
+
|
18
|
+
machine_names = (1..4).collect { |i| "managed-#{i}" }
|
19
|
+
datetimes = get_sync_times(machine_names)
|
20
|
+
execute("vagrant", "destroy", "-f")
|
21
|
+
|
22
|
+
# Parallel provisioning should happen within a few seconds.
|
23
|
+
ensure_datetimes_within(datetimes, 5)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can push with carary strategy" do
|
27
|
+
assert_execute("vagrant", "orchestrate", "push", "--strategy", "canary", "-f")
|
28
|
+
canary = get_sync_times(["managed-1"]).first
|
29
|
+
the_rest = get_sync_times((2..4).collect { |i| "managed-#{i}" })
|
30
|
+
execute("vagrant", "destroy", "-f")
|
31
|
+
ensure_datetimes_within(the_rest, 5)
|
32
|
+
expect(diff_seconds(canary, the_rest.min)).to be >= 3
|
33
|
+
end
|
34
|
+
|
35
|
+
it "can push with half_half strategy" do
|
36
|
+
assert_execute("vagrant", "orchestrate", "push", "--strategy", "half_half", "-f")
|
37
|
+
first_half = get_sync_times(["managed-1", "managed-2"])
|
38
|
+
second_half = get_sync_times(["managed-3", "managed-4"])
|
39
|
+
execute("vagrant", "destroy", "-f")
|
40
|
+
ensure_datetimes_within(first_half, 5)
|
41
|
+
ensure_datetimes_within(second_half, 5)
|
42
|
+
expect(diff_seconds(first_half.max, second_half.min)).to be >= 3
|
43
|
+
end
|
44
|
+
|
45
|
+
it "can push with carary_half_half strategy" do
|
46
|
+
assert_execute("vagrant", "orchestrate", "push", "--strategy", "canary_half_half", "-f")
|
47
|
+
canary = get_sync_times(["managed-1"]).first
|
48
|
+
first_half = get_sync_times(["managed-2"])
|
49
|
+
second_half = get_sync_times(["managed-3", "managed-4"])
|
50
|
+
execute("vagrant", "destroy", "-f")
|
51
|
+
ensure_datetimes_within(first_half, 5)
|
52
|
+
expect(diff_seconds(canary, first_half.min)).to be > 3
|
53
|
+
expect(diff_seconds(first_half.max, second_half.min)).to be >= 3
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_sync_times(machines)
|
58
|
+
datetimes = []
|
59
|
+
machines.each do |machine|
|
60
|
+
execute("vagrant", "up", machine)
|
61
|
+
# This file is written by the shell provisioner in ../support-skeletons/basic/Vagrantfile
|
62
|
+
result = execute("vagrant", "ssh", "-c", "cat /tmp/sync_time", machine)
|
63
|
+
datetimes << DateTime.parse(result.stdout.chomp)
|
64
|
+
end
|
65
|
+
datetimes
|
66
|
+
end
|
67
|
+
|
68
|
+
# Ensure that the range (max - min) of the datetime objects passed in are within
|
69
|
+
# the given number of seconds.
|
70
|
+
def ensure_datetimes_within(datetimes, seconds)
|
71
|
+
expect(diff_seconds(datetimes.min, datetimes.max)).to be < seconds
|
72
|
+
end
|
73
|
+
|
74
|
+
# The difference between two datetimes in seconds
|
75
|
+
def diff_seconds(start, finish)
|
76
|
+
((finish - start) * 86_400).to_i
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
managed_servers = %w( 192.168.10.80 192.168.10.81 192.168.10.82 192.168.10.83)
|
2
|
+
|
3
|
+
Vagrant.configure(2) do |config|
|
4
|
+
config.ssh.password = "vagrant"
|
5
|
+
managed_servers.each_with_index do |server, index|
|
6
|
+
config.vm.define "managed-#{index + 1}" do |managed|
|
7
|
+
managed.vm.provision "shell", inline: "date > /tmp/sync_time; sleep 3"
|
8
|
+
managed.vm.box = "managed-server-dummy"
|
9
|
+
managed.vm.box_url = "./dummy.box"
|
10
|
+
# TODO: Why in the world do I need this? I thought it was the default!
|
11
|
+
managed.ssh.password = "vagrant"
|
12
|
+
managed.vm.provider :managed do |provider|
|
13
|
+
provider.server = server
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
Binary file
|
@@ -0,0 +1,16 @@
|
|
1
|
+
managed_servers = %w( 192.168.10.80 192.168.10.81 192.168.10.82 192.168.10.83 )
|
2
|
+
|
3
|
+
Vagrant.configure(2) do |config|
|
4
|
+
config.orchestrate.credentials.prompt = true
|
5
|
+
|
6
|
+
managed_servers.each_with_index do |server, index|
|
7
|
+
config.vm.define "managed-#{index + 1}" do |managed|
|
8
|
+
managed.vm.provision "shell", inline: "echo 'hello world'"
|
9
|
+
managed.vm.box = "managed-server-dummy"
|
10
|
+
managed.vm.box_url = "./dummy.box"
|
11
|
+
managed.vm.provider :managed do |provider|
|
12
|
+
provider.server = server
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
Binary file
|
@@ -2,84 +2,65 @@ module VagrantPlugins
|
|
2
2
|
module Orchestrate
|
3
3
|
module Action
|
4
4
|
class SetCredentials
|
5
|
-
def
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
|
-
# rubocop:disable Metrics/AbcSize
|
10
|
-
def call(env)
|
11
|
-
@machine = env[:machine]
|
12
|
-
|
13
|
-
if @machine.config.orchestrate.credentials
|
14
|
-
@ui = env[:ui]
|
15
|
-
config_creds = @machine.config.orchestrate.credentials
|
16
|
-
(username, password) = retrieve_creds(config_creds)
|
17
|
-
|
18
|
-
# Apply the credentials to the machine info, or back out if we were unable to procure them.
|
19
|
-
if username && password
|
20
|
-
apply_creds(username, password)
|
21
|
-
else
|
22
|
-
@ui.warn <<-WARNING
|
23
|
-
Vagrant-orchestrate could not gather credentials for machine #{@machine.name}. \
|
24
|
-
Continuing with default credentials."
|
25
|
-
WARNING
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
@app.call env
|
30
|
-
end
|
5
|
+
def retrieve_creds(config_creds, ui)
|
6
|
+
return unless config_creds
|
31
7
|
|
32
|
-
def retrieve_creds(config_creds)
|
33
8
|
# Use environment variable overrides, or else what was provided in the config file
|
34
9
|
config_creds.username = ENV["VAGRANT_ORCHESTRATE_USERNAME"] || config_creds.username
|
35
10
|
config_creds.password = ENV["VAGRANT_ORCHESTRATE_PASSWORD"] || config_creds.password
|
36
11
|
|
37
12
|
# Use credentials file to any username or password that is still undiscovered
|
38
|
-
check_creds_file(config_creds) unless config_creds.username && config_creds.password
|
13
|
+
check_creds_file(config_creds, ui) unless config_creds.username && config_creds.password
|
39
14
|
|
15
|
+
config_creds = maybe_prompt(config_creds)
|
16
|
+
|
17
|
+
[config_creds.username, config_creds.password]
|
18
|
+
end
|
19
|
+
|
20
|
+
def maybe_prompt(config_creds)
|
40
21
|
# Only prompt if allowed by config
|
41
22
|
if config_creds.prompt
|
42
|
-
config_creds.username ||= prompt_username
|
43
|
-
config_creds.password ||= prompt_password
|
23
|
+
config_creds.username ||= prompt_username(ui)
|
24
|
+
config_creds.password ||= prompt_password(ui)
|
44
25
|
end
|
45
|
-
|
46
|
-
[config_creds.username, config_creds.password]
|
26
|
+
config_creds
|
47
27
|
end
|
48
28
|
|
49
|
-
def apply_creds(username, password)
|
50
|
-
[
|
29
|
+
def apply_creds(machine, username, password)
|
30
|
+
[machine.config.winrm, machine.config.ssh].each do |config|
|
51
31
|
next unless config
|
52
32
|
config.username = username
|
53
33
|
config.password = password
|
54
34
|
end
|
55
35
|
end
|
56
36
|
|
57
|
-
def prompt_username
|
37
|
+
def prompt_username(ui)
|
58
38
|
default = ENV["USERNAME"]
|
59
39
|
default ||= ENV["USER"]
|
60
40
|
default = ENV["USERDOMAIN"] + "\\" + default if ENV["USERDOMAIN"]
|
61
|
-
username =
|
41
|
+
username = ui.ask("username? [#{default}] ")
|
62
42
|
username = default if username.empty?
|
63
43
|
username
|
64
44
|
end
|
65
45
|
|
66
|
-
def prompt_password
|
67
|
-
|
46
|
+
def prompt_password(ui)
|
47
|
+
ui.ask("password? ", echo: false)
|
68
48
|
end
|
69
49
|
|
70
|
-
def check_creds_file(config_creds)
|
50
|
+
def check_creds_file(config_creds, ui)
|
71
51
|
file_path = config_creds.file_path
|
72
52
|
return unless file_path
|
73
53
|
unless File.exist?(file_path)
|
74
54
|
@ui.info "Credential file not found at #{file_path}. Prompting user for credentials."
|
75
55
|
return
|
76
56
|
end
|
57
|
+
|
77
58
|
begin
|
78
59
|
creds_yaml = YAML.load(File.read(file_path))
|
79
60
|
config_creds.password ||= creds_yaml[:password] || creds_yaml["password"]
|
80
61
|
config_creds.username ||= creds_yaml[:username] || creds_yaml["username"]
|
81
62
|
rescue
|
82
|
-
|
63
|
+
ui.warn "Credentials file at #{file_path} was not valid YAML. Prompting user for credentials."
|
83
64
|
end
|
84
65
|
end
|
85
66
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "optparse"
|
2
2
|
require "vagrant"
|
3
|
+
require "vagrant-orchestrate/action/setcredentials"
|
3
4
|
|
4
5
|
# Borrowed from http://stackoverflow.com/questions/12374645/splitting-an-array-into-equal-parts-in-ruby
|
5
6
|
class Array
|
@@ -57,6 +58,8 @@ module VagrantPlugins
|
|
57
58
|
return 0
|
58
59
|
end
|
59
60
|
|
61
|
+
retrieve_creds(machines) if @env.vagrantfile.config.orchestrate.credentials
|
62
|
+
|
60
63
|
options[:parallel] = true
|
61
64
|
strategy = options[:strategy] || @env.vagrantfile.config.orchestrate.strategy
|
62
65
|
@env.ui.info("Pushing to managed servers using #{strategy} strategy.")
|
@@ -130,7 +133,7 @@ module VagrantPlugins
|
|
130
133
|
# rubocop:enable Metrics/AbcSize, MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
131
134
|
|
132
135
|
def prompt_for_continue
|
133
|
-
result = @env.ui.ask("Deployment paused for manual review. Would you like to continue? (y/n)")
|
136
|
+
result = @env.ui.ask("Deployment paused for manual review. Would you like to continue? (y/n) ")
|
134
137
|
if result.upcase != "Y"
|
135
138
|
@env.ui.info("Deployment push action cancelled by user")
|
136
139
|
return false
|
@@ -145,6 +148,23 @@ module VagrantPlugins
|
|
145
148
|
end
|
146
149
|
end
|
147
150
|
end
|
151
|
+
|
152
|
+
def retrieve_creds(machines)
|
153
|
+
creds = VagrantPlugins::Orchestrate::Action::SetCredentials.new
|
154
|
+
(username, password) = creds.retrieve_creds(@env.vagrantfile.config.orchestrate.credentials, @env.ui)
|
155
|
+
|
156
|
+
# Apply the credentials to the machine info, or back out if we were unable to procure them.
|
157
|
+
if username && password
|
158
|
+
machines.each do |machine|
|
159
|
+
creds.apply_creds(machine, username, password)
|
160
|
+
end
|
161
|
+
else
|
162
|
+
@env.ui.warn <<-WARNING
|
163
|
+
Vagrant-orchestrate could not gather credentials. \
|
164
|
+
Continuing with default credentials."
|
165
|
+
WARNING
|
166
|
+
end
|
167
|
+
end
|
148
168
|
end
|
149
169
|
end
|
150
170
|
end
|
@@ -34,10 +34,6 @@ module VagrantPlugins
|
|
34
34
|
Command::Root
|
35
35
|
end
|
36
36
|
|
37
|
-
action_hook(:orchestrate, Plugin::ALL_ACTIONS) do |hook|
|
38
|
-
hook.before Vagrant::Action::Builtin::ConfigValidate, Action::SetCredentials
|
39
|
-
end
|
40
|
-
|
41
37
|
action_hook(:orchestrate, :machine_action_up) do |hook|
|
42
38
|
hook.prepend Action::FilterManaged
|
43
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-orchestrate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Baldauf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -81,6 +81,13 @@ files:
|
|
81
81
|
- LICENSE
|
82
82
|
- README.md
|
83
83
|
- Rakefile
|
84
|
+
- Vagrantfile
|
85
|
+
- acceptance/command/prompt_spec.rb
|
86
|
+
- acceptance/command/push_spec.rb
|
87
|
+
- acceptance/support-skeletons/basic/Vagrantfile
|
88
|
+
- acceptance/support-skeletons/basic/dummy.box
|
89
|
+
- acceptance/support-skeletons/prompt/Vagrantfile
|
90
|
+
- acceptance/support-skeletons/prompt/dummy.box
|
84
91
|
- docs/strategy.md
|
85
92
|
- dummy.box
|
86
93
|
- lib/vagrant-orchestrate.rb
|
@@ -103,6 +110,7 @@ files:
|
|
103
110
|
- templates/vagrant/Vagrantfile.erb
|
104
111
|
- templates/vagrant/dummy.box
|
105
112
|
- vagrant-orchestrate.gemspec
|
113
|
+
- vagrant-spec.config.rb
|
106
114
|
homepage: https://github.com/Cimpress-MCP/vagrant-orchestrate
|
107
115
|
licenses:
|
108
116
|
- Apache 2.0
|