vagrant-orchestrate 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4760cd6a2cdc63739d752fe2341dd49e2e174676
4
- data.tar.gz: c244aaadc7615858ae95ee9315ae6d306cdad82e
3
+ metadata.gz: 2d1d37bbcceb73c4aeea0523c3132be46e30a5dd
4
+ data.tar.gz: 8a2d5192f22543df2a99a31b72bd5fb95037d2e4
5
5
  SHA512:
6
- metadata.gz: bbabd2ed817ea80ce81706464852f569b59e5e5bae90b25979765380772af47857c94f61e212dcd4776eed92cfe820e44811e92e63c9ba705bc89eaf6d12cb07
7
- data.tar.gz: a7f8b8f32cc8d86ba46267ab946a1bdc730e0a309fcdac9288c2bde3978d2477fbf7a57c3aec28f0922f36dea73697678b1a46076276b885ccb6f054e14c2993
6
+ metadata.gz: 4d09668c2feeef5cafe7fff5885597105f7a1194c1b62ae0c07c0d7958b33abfd8ca201ddd0eee00af4b1713666a71cd88b987d06c6c51f385b0ee62253617ef
7
+ data.tar.gz: 04d66afcfcb9b2867de6b74b26d8d8b951343fcd16f8c1dc823288ef4d68e5055d8b360e3d15f92641660a188c8e5685967dd0ac94240f710574c3c2c2308d78
data/.gitignore CHANGED
@@ -14,6 +14,5 @@
14
14
  mkmf.log
15
15
 
16
16
  /.vagrant/
17
- Vagrantfile
18
17
  .DS_Store
19
18
  servers.json
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
@@ -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
@@ -2,84 +2,65 @@ module VagrantPlugins
2
2
  module Orchestrate
3
3
  module Action
4
4
  class SetCredentials
5
- def initialize(app, _env)
6
- @app = app
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
- [@machine.config.winrm, @machine.config.ssh].each do |config|
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 = @ui.ask("username? [#{default}] ")
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
- @ui.ask("password? ", echo: false)
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
- @ui.warn "Credentials file at #{file_path} was not valid YAML. Prompting user for credentials."
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
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Orchestrate
3
- VERSION = "0.4.5"
3
+ VERSION = "0.4.6"
4
4
  end
5
5
  end
@@ -1,6 +1,5 @@
1
1
  require "vagrant-orchestrate/command/init"
2
2
  require "vagrant-spec/unit"
3
- require "pp"
4
3
 
5
4
  describe VagrantPlugins::Orchestrate::Command::Init do
6
5
  include_context "vagrant-unit"
@@ -0,0 +1,4 @@
1
+ Vagrant::Spec::Acceptance.configure do |c|
2
+ c.component_paths << File.join("acceptance")
3
+ c.skeleton_paths << File.join("acceptance", "support-skeletons")
4
+ 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.5
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-02 00:00:00.000000000 Z
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