vagrant-babushka 0.0.7 → 0.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0d8d6401a57d7fe37be1f75b453417e0bebfe344
4
- data.tar.gz: ba4180b390bdbcea4612f3c05bf378b23bb0af86
3
+ metadata.gz: 0c21e99dc53da017ce744dbf00984705e537fa75
4
+ data.tar.gz: 5aa688d0cc3af642b21eacebeb4c07f193b864bc
5
5
  SHA512:
6
- metadata.gz: 1d2a4980561b92ef73a65112896fd274e8523994620949eb9a04255eac5a54e97e105559ffee1b8bac1d45598d54a0b5b61e09ba750e9fd20d44759ae6ff7a55
7
- data.tar.gz: 80bada052a188da60332fc2e3e1711e229eb391d4328c10324117e8f802d37d50ee2808798c0be658886834810168ea9303ba90fc166579018b318a98f9492fc
6
+ metadata.gz: 4ec88c85577ce6a0907153e08a347cd4c4e4a958b7a70c20da4f69cf1cd8d0f709f19727ecba563b03dcc74776a49d42b33af873d0b0de7952ce345ac1e92e6c
7
+ data.tar.gz: cc858b966ce45dceb6b23d9d7b37e195f7d70054492a35dc2d4b9eda73af6ae47166c159dad423236a21b0102ffafef5b3e39be49c4cdd83dd47db526cfb9a48
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
+ .rspec
6
7
  Gemfile.lock
7
8
  InstalledFiles
8
9
  _yardoc
data/README.md CHANGED
@@ -10,6 +10,16 @@ Based on a [plugin concept][3] by @tcurdt.
10
10
  [3]: <https://github.com/tcurdt/vagrant-boxes/blob/master/plugins/babushka_provisioner.rb>
11
11
 
12
12
 
13
+ ## Requirements
14
+
15
+ * Vagrant 1.1+
16
+ * cURL on the virtual machine (will be installed if missing on Ubuntu)
17
+
18
+ Note: The latest version of this plugin has only been tested on Ubuntu
19
+ virtual machines. Please open a GitHub issue if it doesn't work for you
20
+ or your operating system.
21
+
22
+
13
23
  ## Installation
14
24
 
15
25
  ```bash
@@ -25,6 +35,9 @@ Add a Babushka provision block to your project's Vagrantfile:
25
35
  config.vm.provision :babushka do |babushka|
26
36
  # Set the Git branch of Babushka to install on the guest (defaults to master)
27
37
  babushka.bootstrap_branch = 'master'
38
+ # ...or set the URL of the bootstrap script directly
39
+ babushka.bootstrap_url = 'https://example.com/babushka-bootstrap'
40
+
28
41
 
29
42
  # Share a directory of local Babushka deps with the VM
30
43
  # This example shares the '.deps/' directory (relative to this
@@ -32,6 +45,7 @@ config.vm.provision :babushka do |babushka|
32
45
  # directory of the main SSH user on the guest)
33
46
  babushka.local_deps_path = '.deps'
34
47
 
48
+
35
49
  # Meet a local dep
36
50
  # Assuming a dep named 'htop' is defined in a file under './.deps'
37
51
  babushka.meet 'htop'
@@ -40,9 +54,9 @@ config.vm.provision :babushka do |babushka|
40
54
  # Assuming source 'tcurdt' has a dep named 'rbenv system'
41
55
  babushka.meet 'rbenv system', :source => 'tcurdt'
42
56
 
43
- # Also, you can set options for deps
57
+ # Also, you can set values for deps' parameters
44
58
  babushka.meet 'rbenv system', :params => {:key => "value"}
45
- # or for remote dep
59
+ # ...and for remote deps:
46
60
  babushka.meet 'rbenv system', :source => 'tcurdt', :params => {:key => "value"}
47
61
 
48
62
 
@@ -56,8 +70,34 @@ config.vm.provision :babushka do |babushka|
56
70
  # Assuming source 'tcurdt' has a dep named 'rbenv system'
57
71
  babushka.remote_dep 'tcurdt', 'rbenv system'
58
72
 
59
- # Also, you can set options for deps, using a hash as the third parameter
73
+ # Also, you can set values for deps' parameters, using a hash as the last parameter
60
74
  babushka.remote_dep 'tcurdt', 'rbenv system', :path => '/opt/rbenv'
75
+
76
+
77
+ # Set options for the Babushka run
78
+
79
+ # Enable/disable colorised (ANSI) output from Babushka
80
+ # The default value is inherited from Vagrant's current setting
81
+ babushka.color = true
82
+
83
+ # Enable Babushka's debug mode (defaults to false)
84
+ babushka.debug = true
85
+
86
+ # Only do a "dry run", don't meet any deps (defaults to false)
87
+ babushka.dry_run = true
88
+
89
+ # Show parameter values passed to deps (defaults to false)
90
+ babushka.show_args = true
91
+
92
+ # Enable silent mode, no output (defaults to false)
93
+ babushka.silent = true
94
+
95
+ # Enable/disable updating sources before running their deps (defaults to true)
96
+ babushka.update = false
97
+
98
+ # These options can be overridden on particular deps, for example:
99
+ babushka.meet 'rbenv system', :source => 'tcurdt', :update => false
100
+ babushka.meet 'htop', :color => false
61
101
  end
62
102
  ```
63
103
 
@@ -71,6 +111,12 @@ end
71
111
  5. Create new Pull Request
72
112
 
73
113
 
114
+ ## Testing
115
+
116
+ 1. `bundle install`
117
+ 2. `bundle exec rspec`
118
+
119
+
74
120
  ## Thanks
75
121
 
76
122
  [patcon](https://github.com/patcon)
@@ -2,15 +2,32 @@ module VagrantPlugins
2
2
  module Babushka
3
3
  # Main configuration object for Vagrant Babushka provisioner
4
4
  class Config < Vagrant.plugin("2", :config)
5
- attr_accessor :args, :deps, :local_deps_path, :bootstrap_branch
5
+ # Configuration keys that are used as Babushka command-line args
6
+ ARGUMENTS = [
7
+ :color,
8
+ :debug,
9
+ :dry_run,
10
+ :show_args,
11
+ :silent,
12
+ :update,
13
+ ]
14
+
15
+ attr_accessor :deps, :local_deps_path, :bootstrap_branch, :bootstrap_url
6
16
  attr_reader :messages
7
17
 
18
+ # Command-line argument options
19
+ attr_accessor *ARGUMENTS
20
+
8
21
  def initialize
9
22
  super
10
23
  @deps = []
11
24
  @local_deps_path = UNSET_VALUE
12
25
  @bootstrap_branch = UNSET_VALUE
26
+ @bootstrap_url = UNSET_VALUE
13
27
  @messages = []
28
+
29
+ # Reset all argument values to UNSET_VALUE
30
+ ARGUMENTS.each {|a| self.send "#{a}=".to_sym, UNSET_VALUE }
14
31
  end
15
32
 
16
33
  # This is called as a last-minute hook that allows the
@@ -21,6 +38,29 @@ module VagrantPlugins
21
38
  @deps = [] if @deps == UNSET_VALUE
22
39
  @local_deps_path = nil if @local_deps_path == UNSET_VALUE
23
40
  @bootstrap_branch = nil if @bootstrap_branch == UNSET_VALUE
41
+
42
+ # Setup bootstrap URL if not set
43
+ if @bootstrap_url == UNSET_VALUE
44
+ @bootstrap_url = "https://babushka.me/up"
45
+ @bootstrap_url += "/#{@bootstrap_branch}" if @bootstrap_branch
46
+ end
47
+
48
+ # Set defaults for command-line arguments
49
+ @color = nil if @color == UNSET_VALUE
50
+ @debug = false if @debug == UNSET_VALUE
51
+ @dry_run = false if @dry_run == UNSET_VALUE
52
+ @show_args = false if @show_args == UNSET_VALUE
53
+ @silent = false if @silent == UNSET_VALUE
54
+ @update = true if @update == UNSET_VALUE
55
+ end
56
+
57
+ # Retrieves a Hash of the command-line argument config values
58
+ #
59
+ # The returned Hash will have command-line argument names for
60
+ # keys, and the value for the argument as the corresponding
61
+ # value.
62
+ def arguments
63
+ ARGUMENTS.inject(Hash.new) {|hash, key| hash.merge({key => send(key)}) }
24
64
  end
25
65
 
26
66
  # Meets a local dep on the guest
@@ -52,13 +52,13 @@ module VagrantPlugins
52
52
  @options[:params] || Hash.new
53
53
  end
54
54
 
55
- # Creates a command string to use for this dep on the command line
55
+ # Retrieves the command-line arguments for the dep
56
56
  #
57
- # This will return a string which can be used as an argument to
58
- # "babushka meet" to meet this dep with its parameters.
59
- def command
60
- values = params.map {|k, v| "#{escape k}=#{escape v}" }
61
- [escape(id), values].flatten.join(" ")
57
+ # This returns a hash including all the Babushka command-line
58
+ # arguments (to override the global settings) when meeting this
59
+ # dep.
60
+ def arguments
61
+ @options.select {|key, value| Config::ARGUMENTS.include? key }
62
62
  end
63
63
 
64
64
  def ==(other)
@@ -71,12 +71,6 @@ module VagrantPlugins
71
71
  def state
72
72
  [@dep_name, @options[:params], @options[:source]]
73
73
  end
74
-
75
- private
76
- # Alias for Shellwords.escape
77
- def escape(string)
78
- Shellwords.escape(string.to_s)
79
- end
80
74
  end
81
75
  end
82
76
  end
@@ -2,7 +2,7 @@ module VagrantPlugins
2
2
  module Babushka
3
3
  class Plugin < Vagrant.plugin("2")
4
4
  name "Babushka"
5
- description <<-END
5
+ description <<-END.gsub(/ {6}|\n\Z/, "")
6
6
  Provides support for provisioning your virtual machines using
7
7
  Babushka.
8
8
  END
@@ -1,84 +1,248 @@
1
+ require 'forwardable'
2
+
1
3
  module VagrantPlugins
2
4
  module Babushka
3
5
  # The main implementation class for the Babushka provisioner
4
6
  class Provisioner < Vagrant.plugin("2", :provisioner)
5
7
 
6
- def initialize(machine, config)
7
- super
8
+ # Exception raised if cURL isn't on the VM and can't be installed
9
+ class CurlMissing < Vagrant::Errors::VagrantError
10
+ error_message <<-END.gsub(/ {8}|\n\Z/, "")
11
+ cURL couldn't be found on the VM, and this plugin doesn't
12
+ know how to install it on the guest OS.
13
+
14
+ Try installing it manually, or consider adding the
15
+ functionality to the plugin and opening a pull request.
16
+ END
8
17
  end
9
18
 
19
+ # Allow delegation of methods to an accessor
20
+ extend Forwardable
21
+
22
+ # Delegate some methods to @machine (to reduce boilerplate)
23
+ delegate [:communicate, :env, :name] => :@machine
24
+ delegate :ui => :env
25
+
26
+ attr_accessor :username, :group
27
+
28
+ # Called with the root configuration of the machine so the
29
+ # provisioner can add some configuration on top of the machine.
30
+ #
31
+ # During this step, and this step only, the provisioner should
32
+ # modify the root machine configuration to add any additional
33
+ # features it may need. Examples include sharing folders,
34
+ # networking, and so on. This step is guaranteed to be called
35
+ # before any of those steps are done so the provisioner may do
36
+ # that.
10
37
  def configure(root_config)
11
38
  @username = root_config.ssh.username || root_config.ssh.default.username
12
- @hostname = root_config.vm.hostname
13
- if @config.local_deps_path
14
- local_path = @config.local_deps_path
15
- remote_path = "/home/#{@username}/babushka-deps"
16
- opts = {id: 'babushka_deps', nfs: false}
17
- root_config.vm.synced_folder local_path, remote_path, opts
18
- end
39
+ share_local_deps(root_config) if config.local_deps_path
19
40
  end
20
41
 
21
42
  # This is the method called when the actual provisioning should
22
43
  # be done. The communicator is guaranteed to be ready at this
23
44
  # point, and any shared folders or networds are already set up.
24
45
  def provision
25
- render_messages!
26
- bootstrap_babushka! unless @machine.communicate.test('babushka --version')
27
- @config.deps.map do |dep|
28
- run_remote "babushka --update --defaults --color #{dep.command}"
46
+ detect_ssh_group
47
+ render_messages
48
+ prepare
49
+ do_babushka_run
50
+ end
51
+
52
+ # Shares local deps with the virtual machine
53
+ def share_local_deps(root_config)
54
+ local_path = config.local_deps_path
55
+ remote_path = "~#{escape username}/babushka-deps"
56
+ opts = {:id => 'babushka_deps', :nfs => false}
57
+ root_config.vm.synced_folder local_path, remote_path, opts
58
+ end
59
+
60
+ # Determines and saves the name of the SSH user's primary group
61
+ def detect_ssh_group
62
+ @group = ""
63
+
64
+ # Save stdout into @group
65
+ communicate.execute("id -gn #{escape username}") do |type, data|
66
+ @group += data if type == :stdout
29
67
  end
68
+
69
+ # Remove trailing newline from command output
70
+ @group.gsub! /\n\Z/, ""
30
71
  end
31
72
 
32
- private
33
73
  # Renders the messages to the log output
34
74
  #
35
75
  # The config object maintains a list of "messages" to be shown
36
76
  # when provisioning occurs, since there's no way to show messages
37
77
  # at the time of configuration actually occurring. This displays
38
78
  # the messages that were saved.
39
- def render_messages!
40
- @config.messages.each do |(level, info, caller)|
79
+ def render_messages
80
+ config.messages.each do |(level, info, caller)|
41
81
  info = "vagrant-babushka: #{info}"
42
82
  info += "\nIn #{caller.first}" unless caller.nil?
43
- @machine.env.ui.send level.to_sym, info.to_s, :scope => @machine.name
83
+ ui.send level.to_sym, info.to_s, :scope => name
44
84
  end
45
85
  end
46
86
 
47
- # Installs Babushka on the guest using the bootstrap script
48
- def bootstrap_babushka!
49
- require 'net/http'
50
- @machine.env.ui.info("Installing babushka on #{@hostname}.")
51
- local_tmpfile = remote_tmpfile = "/tmp/babushka_me_up"
52
- File.open(local_tmpfile, 'w') {|f| f.write `curl #{babushka_uri}` }
53
- @machine.communicate.upload(local_tmpfile, remote_tmpfile)
54
- run_remote "#{proxy_env} sh #{remote_tmpfile}"
87
+ # Performs preparation necessary before Babushka can be invoked
88
+ #
89
+ # Installs Babushka if it's not available. If Babushka needs to
90
+ # be installed, cURL will be installed first so that Babushka
91
+ # can be downloaded over HTTPS (as wget may not support HTTPS).
92
+ def prepare
93
+ unless in_path? "babushka"
94
+ # Install cURL first to ensure we can download over HTTPS
95
+ install_curl! unless in_path? "curl"
96
+ create_destination!
97
+ install_babushka!
98
+ ui.info "\n\n\n"
99
+ end
55
100
  end
56
101
 
57
- # Extracts the HTTPS proxy from the host environment variables
58
- def proxy_env
59
- vars = ''
60
- vars_from_env = ENV.select { |k, _| /https_proxy/i.match(k) }
61
- vars = vars_from_env.to_a.map{ |pair| pair.join('=') }.join(' ') unless vars_from_env.empty?
62
- vars
102
+ # Invokes Babushka on the virtual machine to meet requested deps
103
+ #
104
+ # Since Babushka can only meet one dep at a time, if multiple
105
+ # deps are in the meet list (the user has requested multiple
106
+ # deps to be run) then we have to have multiple invokations,
107
+ # once for each dep.
108
+ def do_babushka_run
109
+ if config.deps.empty?
110
+ ui.warn <<-END.gsub(/ {12}|\n\Z/, ""), :scope => name
111
+ Didn't find any Babushka deps to be met on the VM.
112
+ Add some to your Vagrantfile: babushka.meet 'my dep'
113
+ END
114
+ else
115
+ ui.info "Provisioning VM using Babushka...", :scope => name
116
+ config.deps.each do |dep|
117
+ ui.info "Meeting Babushka dep '#{dep.id}'", :scope => name
118
+ ui.info "Executing '#{command_for(dep).strip}'...", :scope => name
119
+ communicate.execute command_for(dep), &log_stdout
120
+ end
121
+ end
63
122
  end
64
123
 
65
- # Retrieves the URL to use to bootstrap Babushka on the guest
66
- def babushka_uri
67
- uri = 'https://babushka.me/up'
68
- uri = "#{uri}/#{@config.bootstrap_branch}" unless @config.bootstrap_branch.nil?
69
- uri
70
- end
124
+ private
125
+ # Determines if the virtual machine has a command in its $PATH
126
+ #
127
+ # command: The name of the command to look for
128
+ def in_path?(command)
129
+ communicate.test("which #{escape command}").tap do |result|
130
+ if result
131
+ ui.info "'#{command}' found on guest", :scope => name
132
+ end
133
+ end
134
+ end
71
135
 
72
- # Executes a command on the guest and handles logging the output
73
- #
74
- # * command: The command to execute (as a string)
75
- def run_remote(command)
76
- @machine.communicate.sudo(command) do |type, data|
77
- color = type == :stdout ? :green : :red
78
- @machine.env.ui.info(data.chomp, :color => color, :prefix => false)
136
+ # Installs cURL on the virtual machine
137
+ def install_curl!
138
+ raise CurlMissing.new unless in_path? "apt-get"
139
+ ui.info "Installing cURL package on VM...", :scope => name
140
+ communicate.sudo "apt-get --quiet --assume-yes install curl"
141
+ end
142
+
143
+ # Creates the Babushka installation directory on the VM
144
+ #
145
+ # This will create the directory (as root), then set up the
146
+ # permissions on it to belong to the SSH user's primary group,
147
+ # and give the group read and write privileges. The permissions
148
+ # are also adjusted on /usr/local/bin, so Babushka can symlink
149
+ # itself into the PATH.
150
+ def create_destination!
151
+ ui.info "Creating Babushka directory...", :scope => name
152
+ communicate.sudo [
153
+ # Create directory, and parent directories if also missing
154
+ "mkdir -p /usr/local/babushka",
155
+
156
+ # Change Babushka directory's group to user's primary group
157
+ "chgrp #{escape group} /usr/local/babushka /usr/local/bin",
158
+
159
+ # Add read/write privileges where Babushka needs them
160
+ "chmod g+rw /usr/local/babushka /usr/local/bin",
161
+ ].join(" && ")
79
162
  end
80
- end
81
163
 
164
+ # Installs Babushka on the virtual machine
165
+ def install_babushka!
166
+ ui.info <<-END.gsub(/ {12}|\n\Z/, ""), :scope => name
167
+ Installing Babushka via bootstrap script at \
168
+ #{config.bootstrap_url}...
169
+ END
170
+
171
+ unless config.bootstrap_url =~ %r[^https://]
172
+ ui.warn "WARNING: Using non-SSL source", :scope => name
173
+ end
174
+
175
+ # Log stdout straight to Vagrant's output
176
+ communicate.execute install_babushka_command, &log_stdout
177
+ end
178
+
179
+ # The command used to install Babushka on the virtual machine
180
+ def install_babushka_command
181
+ %Q[#{vars} sh -c "`#{vars} curl #{escape config.bootstrap_url}`"]
182
+ end
183
+
184
+ # Retrieves the environment variables to use for VM commands
185
+ #
186
+ # Extracts the HTTPS proxy from the host environment variables
187
+ #
188
+ # Returns a string that can be used as a prefix to a command in
189
+ # order to assign the variables for that command.
190
+ def vars
191
+ proxy_env = ENV.select {|k, _| /https_proxy/i.match(k) }
192
+ proxy_env.map{|k, v| "#{escape k}=#{escape v}" }.join(" ")
193
+ end
194
+
195
+ # A block that logs stdout, when passed to a communicator
196
+ #
197
+ # type: The stream where the output in data came from, one of
198
+ # :stdout or :stderr
199
+ # data: The echoed data as a string
200
+ def log_stdout
201
+ lambda do |type, data|
202
+ ui.info data, :new_line => false if type == :stdout
203
+ end
204
+ end
205
+
206
+ # Creates a command string to use for a dep on the command line
207
+ #
208
+ # This will return a string which can be used as a command to
209
+ # run Babushka to meet a particular dep.
210
+ #
211
+ # * dep: The Dep to generate the command string for
212
+ def command_for(dep)
213
+ [
214
+ vars, "babushka", "meet",
215
+ args_for(dep), # Babushka command-line arguments
216
+ escape(dep.id), # Identifier for the dep to be met
217
+ dep.params.map {|k, v| "#{escape k}=#{escape v}" },
218
+ ].flatten.join(" ")
219
+ end
220
+
221
+ # Generates the Babushka command-line arguments for a dep
222
+ #
223
+ # Given a dep, this method merges the configuration options for
224
+ # the specific dep with the configuration of the provisioner as
225
+ # "defaults" if values aren't set on the dep itself.
226
+ #
227
+ # * dep: The Dep to generate the command string for
228
+ def args_for(dep)
229
+ result = config.arguments.merge(dep.arguments)
230
+ result[:color] = ui.is_a? Vagrant::UI::Colored if result[:color].nil?
231
+ [
232
+ '--defaults', # Must use defaults -- stdin not connected
233
+ result[:color] ? '--color' : '--no-color',
234
+ result[:debug] ? '--debug' : nil,
235
+ result[:dry_run] ? '--dry-run' : nil,
236
+ result[:show_args] ? '--show-args' : nil,
237
+ result[:silent] ? '--silent' : nil,
238
+ result[:update] ? '--update' : nil,
239
+ ].compact.join(" ") # Remove nil values and concatenate
240
+ end
241
+
242
+ # Alias for Shellwords.escape
243
+ def escape(string)
244
+ Shellwords.escape(string.to_s)
245
+ end
82
246
  end
83
247
  end
84
248
  end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Babushka
3
- VERSION = "0.0.7"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -3,28 +3,63 @@ require "spec_helper"
3
3
  describe VagrantPlugins::Babushka::Config do
4
4
  let(:unset_value) { described_class::UNSET_VALUE }
5
5
  let(:config) { described_class.new }
6
+ subject { config }
6
7
 
7
8
  context "with default configuration" do
8
- before { subject.finalize! }
9
+ before { config.finalize! }
9
10
  its(:deps) { should eq [] }
10
11
  its(:local_deps_path) { should be_nil }
11
12
  its(:bootstrap_branch) { should be_nil }
12
13
  end
13
14
 
14
15
  describe "#local_deps_path" do
15
- before { subject.local_deps_path = '.deps' }
16
+ before { config.local_deps_path = '.deps'; config.finalize! }
16
17
  its(:local_deps_path) { should eq '.deps' }
17
18
  end
18
19
 
19
20
  describe "#bootstrap_branch" do
20
- before { subject.bootstrap_branch = 'new' }
21
+ before { config.bootstrap_branch = 'new'; config.finalize! }
21
22
  its(:bootstrap_branch) { should eq 'new' }
23
+ its(:bootstrap_url) { should eq 'https://babushka.me/up/new' }
24
+ end
25
+
26
+ describe "#bootstrap_url" do
27
+ before do
28
+ config.bootstrap_url = 'https://example.com/foo'
29
+ config.finalize!
30
+ end
31
+
32
+ its(:bootstrap_url) { should eq 'https://example.com/foo' }
33
+ end
34
+
35
+ describe "#arguments" do
36
+ before do
37
+ config.color = false
38
+ config.debug = true
39
+ config.dry_run = true
40
+ config.bootstrap_url = double "bootstrap_url"
41
+ config.finalize!
42
+ end
43
+
44
+ subject { config.arguments }
45
+
46
+ specify "set values should override defaults" do
47
+ expect(subject).to eq({
48
+ :color => false,
49
+ :debug => true,
50
+ :dry_run => true,
51
+ :show_args => false,
52
+ :silent => false,
53
+ :update => true,
54
+ })
55
+ end
22
56
  end
23
57
 
24
58
  describe "#local_dep" do
25
59
  before do
26
- subject.local_dep 'foobar', :baz => :qux
27
- subject.local_dep 'testme', :one => :two
60
+ config.local_dep 'foobar', :baz => :qux
61
+ config.local_dep 'testme', :one => :two
62
+ config.finalize!
28
63
  end
29
64
 
30
65
  it "should store the deps correctly" do
@@ -37,8 +72,9 @@ describe VagrantPlugins::Babushka::Config do
37
72
 
38
73
  describe "#remote_dep" do
39
74
  before do
40
- subject.remote_dep 'user1', 'foobar', :baz => :qux
41
- subject.remote_dep 'user2', 'testme', :one => :two
75
+ config.remote_dep 'user1', 'foobar', :baz => :qux
76
+ config.remote_dep 'user2', 'testme', :one => :two
77
+ config.finalize!
42
78
  end
43
79
 
44
80
  it "should store the deps correctly" do
@@ -51,8 +87,9 @@ describe VagrantPlugins::Babushka::Config do
51
87
 
52
88
  describe "#meet" do
53
89
  before {
54
- subject.meet 'test1', :source => 'user1', :params => {:abc => :def}
55
- subject.meet 'test2', :source => 'user2', :params => {:ghi => :jkl}
90
+ config.meet 'test1', :source => 'user1', :params => {:abc => :def}
91
+ config.meet 'test2', :source => 'user2', :params => {:ghi => :jkl}
92
+ config.finalize!
56
93
  }
57
94
 
58
95
  it "should store the deps correctly" do
@@ -21,11 +21,6 @@ describe VagrantPlugins::Babushka::Dep do
21
21
  it { should be_nil }
22
22
  end
23
23
 
24
- describe "#command" do
25
- subject { dep.command }
26
- it { should eq "the\\ dep" }
27
- end
28
-
29
24
  context "with source" do
30
25
  let(:options) { {:source => source} }
31
26
  let(:source) { double "source", :to_s => "the source" }
@@ -39,11 +34,6 @@ describe VagrantPlugins::Babushka::Dep do
39
34
  subject { dep.source }
40
35
  it { should eq source.to_s }
41
36
  end
42
-
43
- describe "#command" do
44
- subject { dep.command }
45
- it { should eq "the\\ source:the\\ dep" }
46
- end
47
37
  end
48
38
 
49
39
  context "with params" do
@@ -52,22 +42,18 @@ describe VagrantPlugins::Babushka::Dep do
52
42
 
53
43
  describe "#params" do
54
44
  subject { dep.params }
55
- end
56
-
57
- describe "#command" do
58
- subject { dep.command }
59
- it { should eq "the\\ dep foo=bar baz=qux" }
45
+ it { should be params }
60
46
  end
61
47
  end
62
48
 
63
- context "with source and params" do
64
- let(:options) { {:params => params, :source => source} }
65
- let(:params) { {:foo => :bar, :baz => :qux} }
66
- let(:source) { double "source", :to_s => "the source" }
49
+ context "with arguments" do
50
+ let(:options) { {:color => color, :source => source} }
51
+ let(:color) { double "color" }
52
+ let(:source) { double "source" }
67
53
 
68
- describe "#command" do
69
- subject { dep.command }
70
- it { should eq "the\\ source:the\\ dep foo=bar baz=qux" }
54
+ describe "#arguments" do
55
+ subject { dep.arguments }
56
+ it { should eq({:color => color}) }
71
57
  end
72
58
  end
73
59
  end
@@ -0,0 +1,122 @@
1
+ require "spec_helper"
2
+
3
+ describe VagrantPlugins::Babushka::Provisioner do
4
+ let(:config) { double "config" }
5
+ let(:machine) { double "machine", :name => "the name", :communicate => communicate, :env => env }
6
+ let(:communicate) { double "communicate" }
7
+ let(:env) { double "env", :ui => ui }
8
+ let(:ui) { double "ui" }
9
+ let(:provisioner) { described_class.new machine, config }
10
+ subject { provisioner }
11
+
12
+ describe "#share_local_deps" do
13
+ let(:root_config) { double "root config", :vm => vm }
14
+ let(:config) { double "config", :local_deps_path => local_deps_path }
15
+ let(:local_deps_path) { double "local deps path", :to_s => "the local deps" }
16
+ let(:vm) { double "root config.vm" }
17
+
18
+ it "should configure the directory to be shared" do
19
+ expect(config).to receive(:local_deps_path).and_return(local_deps_path)
20
+ expect(vm).to receive(:synced_folder).with(local_deps_path, "~the\\ user/babushka-deps", {:id => 'babushka_deps', :nfs => false})
21
+ provisioner.username = double "username", :to_s => "the user"
22
+ provisioner.share_local_deps root_config
23
+ subject
24
+ end
25
+ end
26
+
27
+ describe "#detect_ssh_group" do
28
+ let(:username) { double "username", :to_s => 'the user' }
29
+
30
+ before do
31
+ provisioner.username = username
32
+ expect(communicate).to receive(:execute).with("id -gn the\\ user").and_yield(:stdout, "test\n")
33
+ subject.detect_ssh_group
34
+ end
35
+
36
+ its(:group) { should eq "test" }
37
+ end
38
+
39
+ describe "#render_messages" do
40
+ let(:config) { double "config", :messages => messages }
41
+ let(:messages) do
42
+ [
43
+ [:warn, "foo bar baz"],
44
+ [:info, "one two three", ['file x line y']],
45
+ ]
46
+ end
47
+
48
+ it "should output the mesages" do
49
+ expect(ui).to receive(:send).with(:warn, "vagrant-babushka: foo bar baz", :scope => "the name")
50
+ expect(ui).to receive(:send).with(:info, "vagrant-babushka: one two three\nIn file x line y", :scope => "the name")
51
+ subject.render_messages
52
+ end
53
+ end
54
+
55
+ describe "#prepare" do
56
+ context "with Babushka not yet installed" do
57
+ it "should install cURL and Babushka" do
58
+ expect(provisioner).to receive(:in_path?).with("babushka").and_return(false)
59
+ expect(provisioner).to receive(:in_path?).with("curl").and_return(false)
60
+ expect(provisioner).to receive(:install_curl!)
61
+ expect(provisioner).to receive(:create_destination!)
62
+ expect(provisioner).to receive(:install_babushka!)
63
+ expect(ui).to receive(:info).with("\n\n\n")
64
+ subject.prepare
65
+ end
66
+
67
+ context "with cURL already installed" do
68
+ it "should install Babushka" do
69
+ expect(provisioner).to receive(:in_path?).with("babushka").and_return(false)
70
+ expect(provisioner).to receive(:in_path?).with("curl").and_return(true)
71
+ expect(provisioner).to_not receive(:install_curl!)
72
+ expect(provisioner).to receive(:create_destination!)
73
+ expect(provisioner).to receive(:install_babushka!)
74
+ expect(ui).to receive(:info).with("\n\n\n")
75
+ subject.prepare
76
+ end
77
+ end
78
+ end
79
+
80
+ context "with Babushka already installed" do
81
+ it "should not do anything" do
82
+ expect(provisioner).to receive(:in_path?).with("babushka").and_return(true)
83
+ expect(provisioner).to_not receive(:install_babushka!)
84
+ subject.prepare
85
+ end
86
+ end
87
+ end
88
+
89
+ describe "#do_babushka_run" do
90
+ let(:deps) { Array.new }
91
+ let(:config) { double "config", :deps => deps }
92
+
93
+ context "with no deps specified" do
94
+ it "should log a warning" do
95
+ expect(ui).to receive(:warn).with(<<-END.gsub(/ {10}|\n\Z/, ""), :scope => "the name")
96
+ Didn't find any Babushka deps to be met on the VM.
97
+ Add some to your Vagrantfile: babushka.meet 'my dep'
98
+ END
99
+ subject.do_babushka_run
100
+ end
101
+ end
102
+
103
+ context "with deps specified" do
104
+ let(:deps) { [dep1, dep2] }
105
+ let(:dep1) { double "dep 1", :id => "the dep 1" }
106
+ let(:dep2) { double "dep 2", :id => "the dep 2" }
107
+
108
+ it "should meet the deps" do
109
+ expect(ui).to receive(:info).with("Provisioning VM using Babushka...", :scope => "the name")
110
+ expect(ui).to receive(:info).with("Meeting Babushka dep 'the dep 1'", :scope => "the name")
111
+ expect(ui).to receive(:info).with("Executing 'foo'...", :scope => "the name")
112
+ expect(ui).to receive(:info).with("Meeting Babushka dep 'the dep 2'", :scope => "the name")
113
+ expect(ui).to receive(:info).with("Executing 'bar'...", :scope => "the name")
114
+ expect(provisioner).to receive(:command_for).with(dep1).twice().and_return("foo")
115
+ expect(communicate).to receive(:execute).with("foo")
116
+ expect(provisioner).to receive(:command_for).with(dep2).twice().and_return("bar")
117
+ expect(communicate).to receive(:execute).with("bar")
118
+ subject.do_babushka_run
119
+ end
120
+ end
121
+ end
122
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-babushka
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Valgis
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-10 00:00:00.000000000 Z
12
+ date: 2013-11-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -90,6 +90,7 @@ files:
90
90
  - spec/spec_helper.rb
91
91
  - spec/unit/vagrant-babushka/config_spec.rb
92
92
  - spec/unit/vagrant-babushka/dep_spec.rb
93
+ - spec/unit/vagrant-babushka/provisioner_spec.rb
93
94
  - vagrant-babushka.gemspec
94
95
  homepage: https://github.com/vvalgis/vagrant-babushka
95
96
  licenses:
@@ -119,3 +120,4 @@ test_files:
119
120
  - spec/spec_helper.rb
120
121
  - spec/unit/vagrant-babushka/config_spec.rb
121
122
  - spec/unit/vagrant-babushka/dep_spec.rb
123
+ - spec/unit/vagrant-babushka/provisioner_spec.rb