vagrant-babushka 0.0.7 → 0.1.0

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