vagrant-cookbook-fetcher 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,29 @@
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.
@@ -0,0 +1,62 @@
1
+ vagrant-cookbook-fetcher
2
+ ========================
3
+
4
+ A Vagrant plugin to automatically fetch cookbooks, roles, and such whenever you run vagrant provision, up or start.
5
+
6
+ ## Behavior
7
+
8
+ Once you set a URL that provides a list of checkouts, this plugin will create two directory trees:
9
+
10
+ my-vagrant-project
11
+ |...Vagrantfile
12
+ |...checkouts
13
+ | |...checkout-foo
14
+ | |...checkout-bar
15
+ |...combined
16
+ |...roles
17
+ |...nodes
18
+ |...data_bags
19
+
20
+ The plugin will loop through the list of checkouts, perform a clone/checkout or pull/update to make sure the checkout exists in the 'checkouts' directory.
21
+
22
+ Next, the plugin creates the 'combined' directory. Each checkout that has a roles directory gets its roles symlinked to; likewise for data bags and nodes. This feature allows you to have roles defined in multiple checkouts, and used from your local project. In the event of name collisions, the later checkout wins. The links are specially constructed to be valid from within the VM, so long as the v-root remains mounted at /vagrant .
23
+
24
+ Finally, the plugin configures chef-solo, setting the cookbook path (to an ordered array of the checkouts's cookbooks directories), the roles path (to the combined path), and the databags path (to the combined path).
25
+
26
+ ## Checkout List Format
27
+
28
+ git,src@src.omniti.com:~internal/chef/common,omniti-internal-common,multi-repo,chef.key
29
+ git,git@trac-il.omniti.net:myproject/support/chef,myproject-chef,master,AGENT
30
+ git,https://github.com/opscode-cookbooks/php.git,opscode-php/cookbooks/php,master,NONE
31
+
32
+ The fields are: VCS,repo address, directory name, branch, credentials
33
+ * VCS may be either 'git' or 'svn' (TODO).
34
+ * repo address is the identifier of the repository from which to obtain the checkout.
35
+ * directory name is the path under <vagrant-root>/checkouts to clone/checkout into. It may contain slashes.
36
+ * branch is the name of the git branch. Leave blank for svn (use repo address for svn branching)
37
+ * (this feature is TODO) credentials is the method to authenticate to the repo server. NONE means use no authentication. AGENT means to rely on a running ssh-agent to provide credentials. All other values are taken to specify the location of a SSH private key, relative to <vagrant-root>, that should be used with a GIT_SSH wrapper.
38
+
39
+ ## Configuration
40
+
41
+ ### config.auto_checkout.url
42
+
43
+ Default: none.
44
+
45
+ URL that replies with a CSV file containing the list of checkouts.
46
+
47
+ If absent, no fetch occurs.
48
+
49
+ ### config.auto_checkout.disable
50
+
51
+ Default: false
52
+
53
+ If true, no checkout will be be run. This can be useful if you're provisioning frequently and making local changes to your recipes.
54
+
55
+ Even if the fetch is disabled, this plugin will still try to tell chef-solo about your cookbook, role, and data_bag paths, unless you override them.
56
+
57
+ ## TODO
58
+
59
+ * Add svn support
60
+ * Actually respect the credentials column
61
+ * Make checkout list format less awful, add headers
62
+ * support chef, not just chef-solo
@@ -0,0 +1,205 @@
1
+
2
+ # http://vagrantup.com/v1/docs/extending/configuration.html
3
+ class CookbookFetcherConfig < Vagrant::Config::Base
4
+ attr_accessor :url
5
+ attr_accessor :disable
6
+ end
7
+ Vagrant.config_keys.register(:cookbook_fetcher) { CookbookFetcherConfig }
8
+
9
+
10
+ # This is a Vagrant middleware plugin
11
+ # http://vagrantup.com/v1/docs/extending/middleware.html
12
+
13
+ class CookbookFetcher
14
+ def initialize(app, env)
15
+ @app = app
16
+ end
17
+
18
+ def call(env)
19
+
20
+ if !env[:global_config].cookbook_fetcher.disable then
21
+ if !env[:global_config].cookbook_fetcher.url.nil? then
22
+ fetch_checkouts env
23
+ else
24
+ env[:ui].warn "No URL set for auto-checkout, skipping"
25
+ end
26
+ else
27
+ env[:ui].info "Auto-checkout disabled, skipping"
28
+ end
29
+
30
+ # Continue daisy chain
31
+ @app.call(env)
32
+ end
33
+
34
+
35
+ def fetch_checkouts (env)
36
+ url = env[:global_config].cookbook_fetcher.url
37
+ env[:ui].info "Fetching checkout list from #{url}"
38
+
39
+ checkouts = fetch_checkout_list url
40
+ perform_checkouts checkouts
41
+ update_links checkouts
42
+ end
43
+
44
+ def fetch_checkout_list (url)
45
+ require 'open-uri'
46
+
47
+ checkouts = { :by_dir => {}, :cookbook_list => [] }
48
+
49
+ open(url, {:ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE }) do |resp|
50
+ resp.each do |line|
51
+ line.chomp!
52
+ if !line.empty? then
53
+ pieces = line.split(/,/)
54
+ branch = pieces[3]
55
+ dir = pieces[2]
56
+
57
+ # Build info hash
58
+ checkouts[:by_dir][dir] = {
59
+ :vcs => pieces[0],
60
+ :repo => pieces[1],
61
+ :dir => dir,
62
+ :branch => pieces[3],
63
+ :creds => pieces[4],
64
+ }
65
+
66
+ # Build cookbook list. Use first part of directory, and append cookbooks
67
+ checkouts[:cookbook_list].push 'checkouts/' + (dir.split('/'))[0] + '/cookbooks'
68
+
69
+ # Write cookbook order to a file, in case we are later disabled
70
+ File.open('.cookbook-order', 'w') do |f|
71
+ f.print(checkouts[:cookbook_list].join("\n"))
72
+ end
73
+
74
+ end
75
+ end
76
+ end
77
+
78
+ return checkouts
79
+
80
+ end
81
+
82
+ def perform_checkouts (checkouts)
83
+
84
+ if !Dir.exists?("checkouts") then Dir.mkdir("checkouts") end
85
+
86
+ Dir.chdir("checkouts") do
87
+ checkouts[:by_dir].each do |dir, info|
88
+ puts "Updating checkout '#{dir}'"
89
+ if info[:vcs] == 'git' then
90
+
91
+ if Dir.exists?(info[:dir]) then
92
+ # pull
93
+ Dir.chdir(info[:dir]) do
94
+ # TODO ignores git creds
95
+ cmd = "git checkout #{info[:branch]}"
96
+ unless system cmd then raise "Could not '#{cmd}'" end
97
+ cmd = "git pull"
98
+ unless system cmd then raise "Could not '#{cmd}'" end
99
+ end
100
+ else
101
+ # clone
102
+ cmd = "git clone -b #{info[:branch]} #{info[:repo]} #{info[:dir]}"
103
+ unless system cmd then raise "Could not '#{cmd}'" end
104
+ end
105
+ else
106
+ raise "Unsupported VCS '#{info[:vcs]}' in checkout list for entry '#{dir}'"
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ def update_links (checkouts)
113
+ things_to_link = ["roles", "nodes", "handlers", "data_bags"]
114
+ puts "Updating links to #{things_to_link.join(', ')}"
115
+
116
+ if !Dir.exists?("combined") then Dir.mkdir("combined") end
117
+ Dir.chdir("combined") do
118
+
119
+ # Create/clear the subdirs
120
+ things_to_link.each do |thing|
121
+ if !Dir.exists?(thing) then Dir.mkdir(thing) end
122
+ Dir.foreach(thing) do |file|
123
+ if FileTest.symlink?(file) then File.delete(file) end
124
+ end
125
+ end
126
+ end
127
+
128
+ # Being careful to go in cookbook order, symlink the files
129
+ checkouts[:cookbook_list].each do |cookbook_dir|
130
+ checkout_dir = (cookbook_dir.split('/'))[1]
131
+ things_to_link.each do |thing|
132
+ co_thing_dir = "checkouts/#{checkout_dir}/#{thing}"
133
+ combined_dir = "combined/#{thing}"
134
+ if Dir.exists?(co_thing_dir) then
135
+ Dir.entries(co_thing_dir).grep(/\.(rb|json)$/).each do |file|
136
+ # Under vagrant, we see this directory as /vagrant/checkouts/foo/role/bar.rb
137
+ # Use -f so later checkouts can override earlier ones
138
+ cmd = "ln -sf /vagrant/#{co_thing_dir}/#{file} combined/#{thing}/#{file}"
139
+ unless system cmd then raise "Could not '#{cmd}'" end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+
147
+ end
148
+
149
+ Vagrant.actions[:provision].insert(Vagrant::Action::General::Validate, CookbookFetcher)
150
+ # Note that :up includes :start ( see https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/action/builtin.rb )
151
+ Vagrant.actions[:start].insert(Vagrant::Action::General::Validate, CookbookFetcher)
152
+
153
+
154
+ # Injects auto-checkout-derived chef-solo config
155
+ class CookbookFetcherConfigureChef
156
+ def initialize(app, env)
157
+ @app = app
158
+ end
159
+
160
+ def call(env)
161
+ # Do this even if fetch is disabled
162
+
163
+ require 'pp'
164
+ # there has got to be a better way
165
+ provisioners_list = env[:vm].config.to_hash["keys"][:vm].provisioners
166
+
167
+ chef_solo = provisioners_list.find { |p| p.shortcut === :chef_solo }
168
+ if !chef_solo.nil? then
169
+ solo_cfg = chef_solo.config
170
+
171
+ if solo_cfg.roles_path.nil? then
172
+ solo_cfg.roles_path = "combined/roles"
173
+ else
174
+ env[:ui].warn "Auto-checkout is keeping your custom chef-solo role path"
175
+ end
176
+
177
+ if solo_cfg.data_bags_path.nil? then
178
+ solo_cfg.data_bags_path = "combined/data_bags"
179
+ else
180
+ env[:ui].warn "Auto-checkout is keeping your custom chef-solo data_bags path"
181
+ end
182
+
183
+ # Cookbooks has a default
184
+ if solo_cfg.cookbooks_path === ["cookbooks", [:vm, "cookbooks"]] then
185
+ # Read from filesystem
186
+ if !File.exists?(".cookbook-order") then
187
+ env[:ui].error "Auto-checkout could not a .cookbook-order file. You need to run provision with autocheckout enabled at least once (or else specify your own cookbook path)"
188
+ end
189
+
190
+ cbs = []
191
+ IO.readlines(".cookbook-order").each { |line| cbs.push line.chomp }
192
+ solo_cfg.cookbooks_path = cbs
193
+ else
194
+ env[:ui].warn "Auto-checkout is keeping your custom chef-solo cookbook path"
195
+ end
196
+
197
+ end
198
+
199
+ # Continue daisy chain
200
+ @app.call(env)
201
+ end
202
+ end
203
+
204
+ Vagrant.actions[:provision].insert(Vagrant::Action::VM::Provision, CookbookFetcherConfigureChef)
205
+ Vagrant.actions[:start].insert(Vagrant::Action::VM::Provision, CookbookFetcherConfigureChef)
@@ -0,0 +1 @@
1
+ require 'vagrant_cookbook_fetcher'
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-cookbook-fetcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Clinton Wolfe
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-09 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Whenever you run start, up, or provision, this plugin will dynamically
15
+ fetch a list of checkouts from a URL; checkout each one; then create a combined
16
+ roles directory, with symlinks.
17
+ email: clinton@NOSPAM.omniti.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - LICENSE
23
+ - README.md
24
+ - lib/vagrant_init.rb
25
+ - lib/vagrant_cookbook_fetcher.rb
26
+ homepage: https://github.com/clintoncwolfe/vagrant-cookbook-fetcher
27
+ licenses: []
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 1.8.11
47
+ signing_key:
48
+ specification_version: 3
49
+ summary: Fetch your Chef cookbooks whenever you provision
50
+ test_files: []