vagrant-cookbook-fetcher 0.0.10 → 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.
data/README.md CHANGED
@@ -3,6 +3,12 @@ vagrant-cookbook-fetcher
3
3
 
4
4
  A Vagrant plugin to automatically fetch cookbooks, roles, and such whenever you run vagrant provision, up or start.
5
5
 
6
+ ## Compatibility
7
+
8
+ For vagrant 1.0.x, use vagrant-cookbook-fetcher 0.0.x .
9
+ For vagrant 1.1.x, use vagrant-cookbook-fetcher 0.1.x . It may or may not work.
10
+ For vagrant 1.2.x, use vagrant-cookbook-fetcher 0.1.x .
11
+
6
12
  ## Behavior
7
13
 
8
14
  Once you set a URL in your Vagrantfile that provides a list of checkouts, this plugin will create two directory trees (checkouts and combined):
@@ -0,0 +1,28 @@
1
+ require "vagrant/action/builder"
2
+
3
+ module VagrantPlugins
4
+ module CookbookFetcher
5
+ module Action
6
+ include Vagrant::Action::Builtin
7
+
8
+ autoload :DetectCheckoutDisabled, File.expand_path("../action/detect_checkout_disabled", __FILE__)
9
+ autoload :FetchCookbooks, File.expand_path("../action/fetch_cookbooks", __FILE__)
10
+ autoload :UpdateLinks, File.expand_path("../action/update_links", __FILE__)
11
+ autoload :ConfigureChef, File.expand_path("../action/configure_chef", __FILE__)
12
+
13
+ def self.run_checkout
14
+ @run_checkout ||= ::Vagrant::Action::Builder.new.tap do |b|
15
+ b.use ConfigValidate
16
+ b.use Call, DetectCheckoutDisabled do |env1, b2|
17
+ if env1[:checkout_disabled]
18
+ b2.use FetchCookbooks
19
+ b2.use UpdateLinks
20
+ end
21
+ end
22
+ b.use ConfigureChef
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "guts"
2
+
3
+ module VagrantPlugins
4
+ module CookbookFetcher
5
+ class FetchCookbooksAction
6
+
7
+ def initialize(app, env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+
13
+ vcf_config = env[:machine].config.cookbook_fetcher
14
+ unless vcf_config.disable then
15
+ CookbookFetcher.perform_fetch(\
16
+ :url => env[:machine].config.cookbook_fetcher.url,
17
+ :logger => env[:ui],
18
+ :path => env[:root_path]
19
+ )
20
+ else
21
+ env[:ui].info "Cookbook fetching disabled, skipping"
22
+ end
23
+
24
+ # Continue daisy chain
25
+ @app.call(env)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ module VagrantPlugins
2
+ module CookbookFetcher
3
+ class SetChefPathsAction
4
+
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ # there has got to be a better way
11
+ provisioners_list = env[:machine].config.vm.provisioners
12
+ chef_solo = provisioners_list.find { |p| p.name === :chef_solo }
13
+
14
+ if chef_solo then
15
+ solo_cfg = chef_solo.config
16
+
17
+ Dir.chdir(env[:root_path]) do
18
+ # In Vagrant 1.2.x+, these are all arrays
19
+ solo_cfg.roles_path.push [:host, "combined/roles"]
20
+ solo_cfg.data_bags_path.push [:host, "combined/data_bags"]
21
+
22
+ # The first time we fetch cookbooks, we store the cookbook order in a file.
23
+ unless File.exists?(".cookbook-order") then
24
+ env[:ui].error "Cookbook Fetcher checkout could find not a .cookbook-order file. You need to run provision with checkout enabled at least once (or else disable cookbook fetcher)."
25
+ return
26
+ end
27
+
28
+ # For cookbook path, Vagrant defaults to this:
29
+ # [[:host, "cookbooks"], [:vm, "cookbooks"]]
30
+ # But we're overriding that.
31
+ solo_cfg.cookbooks_path = []
32
+
33
+ # Read from filesystem
34
+ IO.readlines(".cookbook-order").each do |line|
35
+ solo_cfg.cookbooks_path.push [ :host, line.chomp ]
36
+ end
37
+
38
+ end
39
+ end
40
+
41
+ # Continue daisy chain
42
+ @app.call(env)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'guts'
2
+ module VagrantPlugins
3
+ module CookbookFetcher
4
+ class CheckoutCommand < Vagrant.plugin("2", "command")
5
+ def execute
6
+ CookbookFetcher.perform_fetch(
7
+ :url => @env.config_global.cookbook_fetcher.url,
8
+ :logger => @env.ui,
9
+ :path => @env.root_path
10
+ )
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ module VagrantPlugins
2
+ module CookbookFetcher
3
+ class Config < Vagrant.plugin("2", :config)
4
+ attr_accessor :url
5
+ attr_accessor :disable
6
+
7
+ def initialize
8
+ super
9
+ @url = UNSET_VALUE
10
+ @disable = UNSET_VALUE
11
+ end
12
+
13
+ def finalize!
14
+ @disable = false if @disable == UNSET_VALUE
15
+ end
16
+
17
+ def validate(machine)
18
+ errors = []
19
+ unless @disable then
20
+ if @url == UNSET_VALUE
21
+ errors << "vagrant-cookbook-fetcher plugin requires a config parameter, 'url', which is missing."
22
+ end
23
+ end
24
+
25
+ { 'Cookbook Fetcher' => errors }
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,248 @@
1
+ module VagrantPlugins
2
+ module CookbookFetcher
3
+
4
+ # Utility method - reads the config, fetches the checkout list,
5
+ # does the checkout, and does the crosslinks. Expects cwd to be the root_path.
6
+ def perform_fetch (args = {})
7
+ url = args[:url]
8
+ logger = args[:logger]
9
+ path = args[:path]
10
+
11
+ unless url then
12
+ logger.warn "No cookbook_fetcher URL specified - skipping checkouts"
13
+ return
14
+ end
15
+
16
+ Dir.chdir(path) do
17
+ checkouts = CookbookFetcher.fetch_checkout_list(url,logger)
18
+ CookbookFetcher.perform_checkouts(checkouts,logger)
19
+ CookbookFetcher.update_links(checkouts,logger)
20
+ end
21
+ end
22
+ module_function :perform_fetch
23
+
24
+
25
+ private
26
+
27
+ # Utility method, fetches checkout list, parses it,
28
+ # and writes cookbook order to a file in the current working directory.
29
+ def fetch_checkout_list (url, logger)
30
+ require 'open-uri'
31
+
32
+ checkouts = { :by_dir => {}, :cookbook_list => [] }
33
+
34
+ logger.info "Fetching checkout list from #{url}"
35
+
36
+ # This is idiotic, but open-uri's open() fails on URLs like 'file:///...'
37
+ # It does fine on absolute paths, though.
38
+ url.gsub!(/^file:\/\//, '')
39
+
40
+ open(url, {:ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE }) do |resp|
41
+ resp.each do |line|
42
+ line.chomp!
43
+ if !line.empty? then
44
+ pieces = line.split(/,/)
45
+ branch = pieces[3]
46
+ dir = pieces[2]
47
+
48
+ # Build info hash
49
+ checkouts[:by_dir][dir] = {
50
+ :vcs => pieces[0],
51
+ :repo => pieces[1],
52
+ :dir => dir,
53
+ :branch => pieces[3],
54
+ :creds => pieces[4],
55
+ }
56
+
57
+ # Build cookbook list. Use first part of directory, and append cookbooks
58
+ checkouts[:cookbook_list].push 'checkouts/' + (dir.split('/'))[0] + '/cookbooks'
59
+
60
+ # Write cookbook order to a file, in case we are later disabled
61
+ File.open('.cookbook-order', 'w') do |f|
62
+ f.print(checkouts[:cookbook_list].join("\n"))
63
+ end
64
+ end
65
+ end
66
+ end
67
+ return checkouts
68
+ end
69
+ module_function :fetch_checkout_list
70
+
71
+ def safe_run (cmd, logger, ignore_regex = nil)
72
+ if logger.respond_to?(:debug)
73
+ logger.debug("Running #{cmd}")
74
+ end
75
+ output = `#{cmd} 2>&1`
76
+ unless $?.success? then
77
+ pwd = Dir.pwd
78
+ logger.error("Got exit code #{$?.exitstatus} while running '#{cmd}' in '#{pwd}'")
79
+ logger.error("Output: #{output}")
80
+ exit $?.exitstatus
81
+ end
82
+ if (ignore_regex)
83
+ output.gsub!(ignore_regex, '')
84
+ end
85
+ output.chomp!
86
+ unless output.empty?
87
+ puts output
88
+ end
89
+ end
90
+ module_function :safe_run
91
+
92
+ # Utility method. Based on a parsed checkout list,
93
+ # performs each of the checkouts, creating the checkouts/ directory in
94
+ # the current directory.
95
+
96
+ def perform_checkouts (checkouts,logger)
97
+
98
+ if !Dir.exists?("checkouts") then Dir.mkdir("checkouts") end
99
+
100
+ Dir.chdir("checkouts") do
101
+ checkouts[:by_dir].each do |dir, info|
102
+ logger.info "Updating checkout '#{dir}'"
103
+
104
+ if info[:vcs] == 'git' then
105
+ if Dir.exists?(info[:dir]) then
106
+ # pull
107
+ Dir.chdir(info[:dir]) do
108
+ # TODO ignores git creds
109
+ cmd = "git remote set-url origin #{info[:repo]}"
110
+ safe_run(cmd, logger)
111
+ cmd = "git fetch origin"
112
+ safe_run(cmd, logger)
113
+
114
+ local_branch = `git rev-parse --verify --symbolic-full-name #{info[:branch]} 2> /dev/null`.rstrip
115
+ # no local branch
116
+ if ! $?.success? then
117
+ cmd = "git rev-parse --verify -q --symbolic-full-name origin/#{info[:branch]}"
118
+ unless system cmd then raise "Could not find branch or commit #{info[:branch]}" end
119
+ cmd = "git checkout -b #{info[:branch]} origin/#{info[:branch]}"
120
+ safe_run(cmd, logger)
121
+
122
+ elsif local_branch.empty? then
123
+ # no branch
124
+ cmd = "git checkout #{info[:branch]}"
125
+ safe_run(cmd, logger)
126
+ else
127
+ # local branch already exists
128
+ cmd = "git checkout #{info[:branch]}"
129
+ safe_run(cmd, logger, /Already on '.+'/)
130
+ cmd = "git merge origin/#{info[:branch]}"
131
+ safe_run(cmd, logger, /Already up-to-date\./)
132
+ end
133
+ end
134
+ else
135
+ # clone
136
+ # can't use --branch because it won't work with commit ids
137
+ cmd = "git clone --no-checkout #{info[:repo]} #{info[:dir]}"
138
+ safe_run(cmd, logger)
139
+ Dir.chdir(info[:dir]) do
140
+ cmd = "git rev-parse --verify -q origin/#{info[:branch]}"
141
+ # branch
142
+ if system cmd then
143
+ current_branch=`git symbolic-ref HEAD 2> /dev/null`.rstrip
144
+ if $?.success? && current_branch == "refs/heads/#{info[:branch]}" then
145
+ cmd = "git checkout #{info[:branch]}"
146
+ safe_run(cmd, logger)
147
+ else
148
+ cmd = "git checkout -B #{info[:branch]} origin/#{info[:branch]}"
149
+ safe_run(cmd, logger)
150
+ end
151
+ #commit
152
+ else
153
+ cmd = "git checkout #{info[:branch]}"
154
+ safe_run(cmd, logger)
155
+ end
156
+ end
157
+ end
158
+ else
159
+ raise "Unsupported VCS '#{info[:vcs]}' in checkout list for entry '#{dir}'"
160
+ end
161
+ end
162
+ end
163
+ end
164
+ module_function :perform_checkouts
165
+
166
+ # Utility method - given a parsed checkout list, and assuming the checkout have
167
+ # already been performed, creates the combined/ directory in the current directory,
168
+ # and symlinks in the roles, nodes, etc.
169
+ def update_links (checkouts,logger)
170
+ things_to_link = {
171
+ "roles" => {:vagrant_pov_link => true, :target_dir => "roles", :step_in => false },
172
+ "nodes" => {:vagrant_pov_link => true, :target_dir => "nodes", :step_in => false },
173
+ "handlers" => {:vagrant_pov_link => true, :target_dir => "handlers", :step_in => false },
174
+ "data_bags" => {:vagrant_pov_link => true, :target_dir => "data_bags", :step_in => true },
175
+ "spec_ext" => {:vagrant_pov_link => false, :target_dir => "spec", :step_in => false },
176
+ "spec_int" => {:vagrant_pov_link => true, :target_dir => "spec", :step_in => false },
177
+ }
178
+ logger.info "Updating links to #{things_to_link.keys.sort.join(', ')}"
179
+
180
+ if !Dir.exists?("combined") then Dir.mkdir("combined") end
181
+ Dir.chdir("combined") do
182
+
183
+ # Create/clear the subdirs
184
+ things_to_link.keys.each do |thing|
185
+ if !Dir.exists?(thing) then Dir.mkdir(thing) end
186
+ if (things_to_link[thing][:step_in]) then
187
+ Dir.foreach(thing) do |top_dir|
188
+ Dir.foreach(thing + '/' + top_dir) do |file|
189
+ if FileTest.symlink?(file) then File.delete(file) end
190
+ end
191
+ end
192
+ else
193
+ Dir.foreach(thing) do |file|
194
+ if FileTest.symlink?(file) then File.delete(file) end
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ # Being careful to go in cookbook order, symlink the files
201
+ checkouts[:cookbook_list].each do |cookbook_dir|
202
+ checkout_dir = (cookbook_dir.split('/'))[1]
203
+ things_to_link.each do |thing, opts|
204
+ checkout_thing_dir = "checkouts/#{checkout_dir}/#{opts[:target_dir]}"
205
+ combined_dir = "combined/#{thing}"
206
+ if Dir.exists?(checkout_thing_dir) then
207
+ if opts[:step_in] then
208
+ Dir.foreach(checkout_thing_dir) do |checkout_top_dir|
209
+ next unless File.directory?(checkout_thing_dir + '/' + checkout_top_dir)
210
+ next if checkout_top_dir.start_with?('.')
211
+ combined_top_dir = combined_dir + '/' + checkout_top_dir
212
+ if !Dir.exists?(combined_top_dir) then Dir.mkdir(combined_top_dir) end
213
+ Dir.entries(checkout_thing_dir + '/' + checkout_top_dir).grep(/\.(rb|json)$/).each do |file|
214
+ if opts[:vagrant_pov_link] then
215
+ # Under vagrant, we see this directory as /vagrant/checkouts/<checkout>/data_bags/<dbag>/<dbag_entry.json>
216
+ # Use -f so later checkouts can override earlier ones
217
+ cmd = "ln -sf /vagrant/#{checkout_thing_dir + '/' + checkout_top_dir}/#{file} combined/#{thing}/#{checkout_top_dir}/#{file}"
218
+ unless system cmd then raise "Could not '#{cmd}'" end
219
+ else
220
+ # Link as visible to the host machine
221
+ # Use -f so later checkouts can override earlier ones
222
+ cmd = "ln -sf ../../#{checkout_thing_dir + '/' + checkout_top_dir}/#{file} combined/#{thing}/#{checkout_top_dir}/#{file}"
223
+ unless system cmd then raise "Could not '#{cmd}'" end
224
+ end
225
+ end
226
+ end
227
+ else
228
+ Dir.entries(checkout_thing_dir).grep(/\.(rb|json)$/).each do |file|
229
+ if opts[:vagrant_pov_link] then
230
+ # Under vagrant, we see this directory as /vagrant/checkouts/foo/role/bar.rb
231
+ # Use -f so later checkouts can override earlier ones
232
+ cmd = "ln -sf /vagrant/#{checkout_thing_dir}/#{file} combined/#{thing}/#{file}"
233
+ unless system cmd then raise "Could not '#{cmd}'" end
234
+ else
235
+ # Link as visible to the host machine
236
+ # Use -f so later checkouts can override earlier ones
237
+ cmd = "ln -sf ../../#{checkout_thing_dir}/#{file} combined/#{thing}/#{file}"
238
+ unless system cmd then raise "Could not '#{cmd}'" end
239
+ end
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end
246
+ module_function :update_links
247
+ end
248
+ end
@@ -0,0 +1,37 @@
1
+ module VagrantPlugins
2
+ module CookbookFetcher
3
+ class Plugin < Vagrant.plugin("2")
4
+ name "Cookbook Fetcher"
5
+
6
+ config "cookbook_fetcher" do
7
+ require_relative "config"
8
+ Config
9
+ end
10
+
11
+ # We want to act on 'up' and 'provision'
12
+ [
13
+ :machine_action_up,
14
+ :machine_action_provision
15
+ ].each do |chain|
16
+
17
+ # This hook performs the actual fetch
18
+ action_hook(:cookbook_fetcher_do_fetch, chain) do |hook|
19
+ require_relative "action_fetch_cookbooks"
20
+ hook.before(Vagrant::Action::Builtin::Provision, VagrantPlugins::CookbookFetcher::FetchCookbooksAction)
21
+ end
22
+
23
+ # This hook configures chef-solo to use a special set of paths
24
+ action_hook(:cookbook_fetcher_set_chef_paths, chain) do |hook|
25
+ require_relative "action_set_chef_paths"
26
+ hook.before(Vagrant::Action::Builtin::Provision, VagrantPlugins::CookbookFetcher::SetChefPathsAction)
27
+ end
28
+ end
29
+
30
+ command "checkout" do
31
+ require_relative "command"
32
+ CheckoutCommand
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ module VagrantPlugins
2
+ module CookbookFetcher
3
+ NAME = "vagrant-cookbook-fetcher"
4
+ VERSION = "0.1.0"
5
+ AUTHOR = "Clinton Wolfe"
6
+ AUTHOR_EMAIL = "clintoncwolfe [at] gmail [dot] com"
7
+ SUMMARY = "Fetch your Chef cookbooks whenever you provision"
8
+ DESCRIPTION = "Whenever you run start, up, or provision, this plugin will dynamically fetch a list of checkouts from a URL; checkout each one; then create a combined roles directory, with symlinks."
9
+ URL = "http://github.com/clintoncwolfe/vagrant-cookbook-fetcher"
10
+ end
11
+ end
12
+
13
+ # Some older Vagrantfiles looked for this symbol to detect VCF.
14
+ module CookbookFetcher
15
+ end
@@ -0,0 +1,12 @@
1
+
2
+ require "vagrant-cookbook-fetcher/version"
3
+ require "vagrant-cookbook-fetcher/plugin"
4
+
5
+ module VagrantPlugins
6
+ module CookbookFetcher
7
+
8
+ # Defaults for config
9
+ # TODO
10
+
11
+ end
12
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-cookbook-fetcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,38 +9,25 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-17 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: vagrant
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - <=
20
- - !ruby/object:Gem::Version
21
- version: 1.0.7
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - <=
28
- - !ruby/object:Gem::Version
29
- version: 1.0.7
30
- description: Whenever you run start, up, or provision, this plugin will dynamically
31
- fetch a list of checkouts from a URL; checkout each one; then create a combined
32
- roles directory, with symlinks.
33
- email: clinton@NOSPAM.omniti.com
12
+ date: 2013-07-02 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Fetch your Chef cookbooks whenever you provision
15
+ email: clintoncwolfe [at] gmail [dot] com
34
16
  executables: []
35
17
  extensions: []
36
18
  extra_rdoc_files: []
37
19
  files:
38
- - ChangeLog
39
- - LICENSE
40
20
  - README.md
41
- - lib/vagrant_init.rb
42
- - lib/vagrant_cookbook_fetcher.rb
43
- homepage: https://github.com/clintoncwolfe/vagrant-cookbook-fetcher
21
+ - lib/vagrant-cookbook-fetcher/guts.rb
22
+ - lib/vagrant-cookbook-fetcher/command.rb
23
+ - lib/vagrant-cookbook-fetcher/action.rb
24
+ - lib/vagrant-cookbook-fetcher/action_fetch_cookbooks.rb
25
+ - lib/vagrant-cookbook-fetcher/config.rb
26
+ - lib/vagrant-cookbook-fetcher/plugin.rb
27
+ - lib/vagrant-cookbook-fetcher/version.rb
28
+ - lib/vagrant-cookbook-fetcher/action_set_chef_paths.rb
29
+ - lib/vagrant-cookbook-fetcher.rb
30
+ homepage: http://github.com/clintoncwolfe/vagrant-cookbook-fetcher
44
31
  licenses: []
45
32
  post_install_message:
46
33
  rdoc_options: []
@@ -59,9 +46,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
46
  - !ruby/object:Gem::Version
60
47
  version: '0'
61
48
  requirements: []
62
- rubyforge_project:
49
+ rubyforge_project: vagrant-cookbook-fetcher
63
50
  rubygems_version: 1.8.24
64
51
  signing_key:
65
52
  specification_version: 3
66
- summary: Fetch your Chef cookbooks whenever you provision
53
+ summary: Whenever you run start, up, or provision, this plugin will dynamically fetch
54
+ a list of checkouts from a URL; checkout each one; then create a combined roles
55
+ directory, with symlinks.
67
56
  test_files: []
data/ChangeLog DELETED
@@ -1,29 +0,0 @@
1
- 2013-04-17 0.0.10 Clinton Wolfe <clintoncwolfe at gmail dot com>
2
- * Update README to include command integration, fix formatting
3
-
4
- 2013-04-09 0.0.9 Clinton Wolfe <clintoncwolfe at gmail dot com>
5
- * Rewrite combined/ linker to be more flexible
6
- * Create two spec directories in combined/ - one symlinked from the perspective of
7
- the VM host, and one from the perspective of the VM guest
8
-
9
- 2013-04-08 0.0.8 Clinton Wolfe <clintoncwolfe at gmail dot com>
10
- * Correct rspec directory name specs => spec
11
- * Update changelog with changes for 0.0.7
12
-
13
- 2013-04-07 0.0.7 Clinton Wolfe <clintoncwolfe at gmail dot com>
14
- * Ensure that checkout always occurs relative to Vagrant project root,
15
- not current working directory
16
- * Link 'specs' directories for rspec testing
17
- * Add hook to run as command (vagrant checkout)
18
- * Constrain to be vagrant 1.0.x plugin
19
-
20
- 2012-09-25 0.0.6 Clinton Wolfe <clintoncwolfe at gmail dot com>
21
-
22
- * Add changelog
23
-
24
- * Fix broken initial checkout bug introduced in 0.0.5 (Graham Knop)
25
-
26
- 2012-09-21 0.0.5 Clinton Wolfe <clintoncwolfe at gmail dot com>
27
-
28
- * Add ability to specify a commit, not just a branch, in checkout lists (Graham Knop)
29
- * Make databag combined symlinks properly descend one directory down (Clinton Wolfe)
data/LICENSE DELETED
@@ -1,29 +0,0 @@
1
- Copyright (c) 2012, OmniTI Computer Consulting, Inc.
2
- All rights reserved.
3
-
4
- Redistribution and use in source and binary forms, with or without
5
- modification, are permitted provided that the following conditions are
6
- met:
7
-
8
- * Redistributions of source code must retain the above copyright
9
- notice, this list of conditions and the following disclaimer.
10
- * Redistributions in binary form must reproduce the above
11
- copyright notice, this list of conditions and the following
12
- disclaimer in the documentation and/or other materials provided
13
- with the distribution.
14
- * Neither the name OmniTI Computer Consulting, Inc. nor the names
15
- of its contributors may be used to endorse or promote products
16
- derived from this software without specific prior written
17
- permission.
18
-
19
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -1,315 +0,0 @@
1
- module CookbookFetcher
2
-
3
- # http://vagrantup.com/v1/docs/extending/configuration.html
4
- class Config < Vagrant::Config::Base
5
- attr_accessor :url
6
- attr_accessor :disable
7
- end
8
- Vagrant.config_keys.register(:cookbook_fetcher) { CookbookFetcher::Config }
9
-
10
- # Utility method - reads the config, fetches the checkout list,
11
- # does the checkout, and does the crosslinks. Expects cwd to be the root_path.
12
- def perform_fetch (global_config, logger)
13
-
14
- unless global_config.cookbook_fetcher then
15
- logger.warn "No config.cookbook_fetcher section found in Vagrantfile - skipping checkouts"
16
- return
17
- end
18
-
19
- url = global_config.cookbook_fetcher.url
20
- unless url then
21
- logger.warn "No config.cookbook_fetcher.url value found in Vagrantfile - skipping checkouts"
22
- return
23
- end
24
-
25
- checkouts = CookbookFetcher.fetch_checkout_list(url,logger)
26
- CookbookFetcher.perform_checkouts(checkouts,logger)
27
- CookbookFetcher.update_links(checkouts,logger)
28
- end
29
- module_function :perform_fetch
30
-
31
- # Utility method, fetches checkout list, parses it,
32
- # and writes cookbook order to a file in the current working directory.
33
- def fetch_checkout_list (url, logger)
34
- require 'open-uri'
35
-
36
- checkouts = { :by_dir => {}, :cookbook_list => [] }
37
-
38
- logger.info "Fetching checkout list from #{url}"
39
- open(url, {:ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE }) do |resp|
40
- resp.each do |line|
41
- line.chomp!
42
- if !line.empty? then
43
- pieces = line.split(/,/)
44
- branch = pieces[3]
45
- dir = pieces[2]
46
-
47
- # Build info hash
48
- checkouts[:by_dir][dir] = {
49
- :vcs => pieces[0],
50
- :repo => pieces[1],
51
- :dir => dir,
52
- :branch => pieces[3],
53
- :creds => pieces[4],
54
- }
55
-
56
- # Build cookbook list. Use first part of directory, and append cookbooks
57
- checkouts[:cookbook_list].push 'checkouts/' + (dir.split('/'))[0] + '/cookbooks'
58
-
59
- # Write cookbook order to a file, in case we are later disabled
60
- File.open('.cookbook-order', 'w') do |f|
61
- f.print(checkouts[:cookbook_list].join("\n"))
62
- end
63
- end
64
- end
65
- end
66
- return checkouts
67
- end
68
- module_function :fetch_checkout_list
69
-
70
- # Utility method. Based on a parsed checkout list,
71
- # performs each of the checkouts, creating the checkouts/ directory in
72
- # the current directory.
73
- def perform_checkouts (checkouts,logger)
74
-
75
- if !Dir.exists?("checkouts") then Dir.mkdir("checkouts") end
76
-
77
- Dir.chdir("checkouts") do
78
- checkouts[:by_dir].each do |dir, info|
79
- logger.info "Updating checkout '#{dir}'"
80
- if info[:vcs] == 'git' then
81
-
82
- if Dir.exists?(info[:dir]) then
83
- # pull
84
- Dir.chdir(info[:dir]) do
85
- # TODO ignores git creds
86
- cmd = "git remote set-url origin #{info[:repo]}"
87
- unless system cmd then raise "Could not '#{cmd}'" end
88
- cmd = "git fetch origin"
89
- unless system cmd then raise "Could not '#{cmd}'" end
90
- local_branch = `git rev-parse --verify --symbolic-full-name #{info[:branch]} 2> /dev/null`.rstrip
91
- # no local branch
92
- if ! $?.success? then
93
- cmd = "git rev-parse --verify -q --symbolic-full-name origin/#{info[:branch]}"
94
- unless system cmd then raise "Could not find branch or commit #{info[:branch]}" end
95
- cmd = "git checkout -b #{info[:branch]} origin/#{info[:branch]}"
96
- unless system cmd then raise "Could not '#{cmd}'" end
97
- # no branch
98
- elsif local_branch.empty? then
99
- cmd = "git checkout #{info[:branch]}"
100
- unless system cmd then raise "Could not '#{cmd}'" end
101
- # local branch already exists
102
- else
103
- cmd = "git checkout #{info[:branch]}"
104
- unless system cmd then raise "Could not '#{cmd}'" end
105
- cmd = "git merge origin/#{info[:branch]}"
106
- unless system cmd then raise "Could not '#{cmd}'" end
107
- end
108
- end
109
- else
110
- # clone
111
- # can't use --branch because it won't work with commit ids
112
- cmd = "git clone --no-checkout #{info[:repo]} #{info[:dir]}"
113
- unless system cmd then raise "Could not '#{cmd}'" end
114
- Dir.chdir(info[:dir]) do
115
- cmd = "git rev-parse --verify -q origin/#{info[:branch]}"
116
- # branch
117
- if system cmd then
118
- current_branch=`git symbolic-ref HEAD 2> /dev/null`.rstrip
119
- if $?.success? && current_branch == "refs/heads/#{info[:branch]}" then
120
- cmd = "git checkout #{info[:branch]}"
121
- unless system cmd then raise "Could not '#{cmd}'" end
122
- else
123
- cmd = "git checkout -B #{info[:branch]} origin/#{info[:branch]}"
124
- unless system cmd then raise "Could not '#{cmd}'" end
125
- end
126
- #commit
127
- else
128
- cmd = "git checkout #{info[:branch]}"
129
- unless system cmd then raise "Could not '#{cmd}'" end
130
- end
131
- end
132
- end
133
- else
134
- raise "Unsupported VCS '#{info[:vcs]}' in checkout list for entry '#{dir}'"
135
- end
136
- end
137
- end
138
- end
139
- module_function :perform_checkouts
140
-
141
- # Utility method - given a parsed checkout list, and assuming the checkout have
142
- # already been performed, creates the combined/ directory in the current directory,
143
- # and symlinks in the roles, nodes, etc.
144
- def update_links (checkouts,logger)
145
- things_to_link = {
146
- "roles" => {:vagrant_pov_link => true, :target_dir => "roles", :step_in => false },
147
- "nodes" => {:vagrant_pov_link => true, :target_dir => "nodes", :step_in => false },
148
- "handlers" => {:vagrant_pov_link => true, :target_dir => "handlers", :step_in => false },
149
- "data_bags" => {:vagrant_pov_link => true, :target_dir => "data_bags", :step_in => true },
150
- "spec_ext" => {:vagrant_pov_link => false, :target_dir => "spec", :step_in => false },
151
- "spec_int" => {:vagrant_pov_link => true, :target_dir => "spec", :step_in => false },
152
- }
153
- logger.info "Updating links to #{things_to_link.keys.sort.join(', ')}"
154
-
155
- if !Dir.exists?("combined") then Dir.mkdir("combined") end
156
- Dir.chdir("combined") do
157
-
158
- # Create/clear the subdirs
159
- things_to_link.keys.each do |thing|
160
- if !Dir.exists?(thing) then Dir.mkdir(thing) end
161
- if (things_to_link[thing][:step_in]) then
162
- Dir.foreach(thing) do |top_dir|
163
- Dir.foreach(thing + '/' + top_dir) do |file|
164
- if FileTest.symlink?(file) then File.delete(file) end
165
- end
166
- end
167
- else
168
- Dir.foreach(thing) do |file|
169
- if FileTest.symlink?(file) then File.delete(file) end
170
- end
171
- end
172
- end
173
- end
174
-
175
- # Being careful to go in cookbook order, symlink the files
176
- checkouts[:cookbook_list].each do |cookbook_dir|
177
- checkout_dir = (cookbook_dir.split('/'))[1]
178
- things_to_link.each do |thing, opts|
179
- checkout_thing_dir = "checkouts/#{checkout_dir}/#{opts[:target_dir]}"
180
- combined_dir = "combined/#{thing}"
181
- if Dir.exists?(checkout_thing_dir) then
182
- if opts[:step_in] then
183
- Dir.foreach(checkout_thing_dir) do |checkout_top_dir|
184
- next unless File.directory?(checkout_thing_dir + '/' + checkout_top_dir)
185
- next if checkout_top_dir.start_with?('.')
186
- combined_top_dir = combined_dir + '/' + checkout_top_dir
187
- if !Dir.exists?(combined_top_dir) then Dir.mkdir(combined_top_dir) end
188
- Dir.entries(checkout_thing_dir + '/' + checkout_top_dir).grep(/\.(rb|json)$/).each do |file|
189
- if opts[:vagrant_pov_link] then
190
- # Under vagrant, we see this directory as /vagrant/checkouts/<checkout>/data_bags/<dbag>/<dbag_entry.json>
191
- # Use -f so later checkouts can override earlier ones
192
- cmd = "ln -sf /vagrant/#{checkout_thing_dir + '/' + checkout_top_dir}/#{file} combined/#{thing}/#{checkout_top_dir}/#{file}"
193
- unless system cmd then raise "Could not '#{cmd}'" end
194
- else
195
- # Link as visible to the host machine
196
- # Use -f so later checkouts can override earlier ones
197
- cmd = "ln -sf ../../#{checkout_thing_dir + '/' + checkout_top_dir}/#{file} combined/#{thing}/#{checkout_top_dir}/#{file}"
198
- unless system cmd then raise "Could not '#{cmd}'" end
199
- end
200
- end
201
- end
202
- else
203
- Dir.entries(checkout_thing_dir).grep(/\.(rb|json)$/).each do |file|
204
- if opts[:vagrant_pov_link] then
205
- # Under vagrant, we see this directory as /vagrant/checkouts/foo/role/bar.rb
206
- # Use -f so later checkouts can override earlier ones
207
- cmd = "ln -sf /vagrant/#{checkout_thing_dir}/#{file} combined/#{thing}/#{file}"
208
- unless system cmd then raise "Could not '#{cmd}'" end
209
- else
210
- # Link as visible to the host machine
211
- # Use -f so later checkouts can override earlier ones
212
- cmd = "ln -sf ../../#{checkout_thing_dir}/#{file} combined/#{thing}/#{file}"
213
- unless system cmd then raise "Could not '#{cmd}'" end
214
- end
215
- end
216
- end
217
- end
218
- end
219
- end
220
- end
221
- module_function :update_links
222
-
223
- # This is a Vagrant middleware plugin, which implements fetching the cookbooks
224
- # http://vagrantup.com/v1/docs/extending/middleware.html
225
- class FetchHook
226
- def initialize(app, env)
227
- @app = app
228
- end
229
-
230
- def call(env)
231
- if !env[:global_config].cookbook_fetcher.disable then
232
- Dir.chdir(env[:root_path]) do
233
- CookbookFetcher.perform_fetch(env[:global_config], env[:ui])
234
- end
235
- else
236
- env[:ui].info "Auto-checkout disabled, skipping"
237
- end
238
-
239
- # Continue daisy chain
240
- @app.call(env)
241
- end
242
- end
243
-
244
- # Install fetcher hook
245
- Vagrant.actions[:provision].insert(Vagrant::Action::General::Validate, CookbookFetcher::FetchHook)
246
- # Note that :up includes :start ( see https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/action/builtin.rb )
247
- Vagrant.actions[:start].insert(Vagrant::Action::General::Validate, CookbookFetcher::FetchHook)
248
-
249
-
250
- # Middleware to tweak chef config
251
- # Injects auto-checkout-derived chef-solo config
252
- class ConfigureChef
253
- def initialize(app, env)
254
- @app = app
255
- end
256
-
257
- def call(env)
258
- # Do this even if fetch is disabled
259
-
260
- # there has got to be a better way
261
- provisioners_list = env[:vm].config.to_hash["keys"][:vm].provisioners
262
-
263
- chef_solo = provisioners_list.find { |p| p.shortcut === :chef_solo }
264
- if !chef_solo.nil? then
265
- solo_cfg = chef_solo.config
266
-
267
- # TODO - need cwd block
268
- Dir.chdir(env[:root_path]) do
269
- if solo_cfg.roles_path.nil? then
270
- solo_cfg.roles_path = "combined/roles"
271
- else
272
- env[:ui].warn "Auto-checkout is keeping your custom chef-solo role path"
273
- end
274
-
275
- if solo_cfg.data_bags_path.nil? then
276
- solo_cfg.data_bags_path = "combined/data_bags"
277
- else
278
- env[:ui].warn "Auto-checkout is keeping your custom chef-solo data_bags path"
279
- end
280
-
281
- # Cookbooks has a default
282
- if solo_cfg.cookbooks_path === ["cookbooks", [:vm, "cookbooks"]] then
283
- # Read from filesystem
284
- if !File.exists?(".cookbook-order") then
285
- env[:ui].error "Auto-checkout could find not a .cookbook-order file. You need to run provision with autocheckout enabled at least once (or else specify your own cookbook path)"
286
- end
287
-
288
- cbs = []
289
- IO.readlines(".cookbook-order").each { |line| cbs.push line.chomp }
290
- solo_cfg.cookbooks_path = cbs
291
- else
292
- env[:ui].warn "Auto-checkout is keeping your custom chef-solo cookbook path"
293
- end
294
- end
295
- end
296
-
297
- # Continue daisy chain
298
- @app.call(env)
299
- end
300
- end
301
-
302
- Vagrant.actions[:provision].insert(Vagrant::Action::VM::Provision, CookbookFetcher::ConfigureChef)
303
- Vagrant.actions[:start].insert(Vagrant::Action::VM::Provision, CookbookFetcher::ConfigureChef)
304
-
305
- class CheckoutCommand < Vagrant::Command::Base
306
- def execute
307
- Dir.chdir(@env.root_path) do
308
- CookbookFetcher.perform_fetch(@env.config.global, @env.ui)
309
- end
310
- end
311
- end
312
- Vagrant.commands.register(:checkout) { CookbookFetcher::CheckoutCommand }
313
-
314
-
315
- end
data/lib/vagrant_init.rb DELETED
@@ -1 +0,0 @@
1
- require 'vagrant_cookbook_fetcher'