vagrant-cookbook-fetcher 0.0.10 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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'