caterer 0.5.0 → 0.6.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/lib/caterer/action/config/validate/image.rb +8 -5
- data/lib/caterer/action/config/validate/provisioner.rb +14 -11
- data/lib/caterer/action/provisioner/base.rb +10 -4
- data/lib/caterer/action/provisioner/bootstrap.rb +1 -1
- data/lib/caterer/action/provisioner/cleanup.rb +1 -1
- data/lib/caterer/action/provisioner/install.rb +1 -1
- data/lib/caterer/action/provisioner/prepare.rb +1 -1
- data/lib/caterer/action/provisioner/provision.rb +1 -1
- data/lib/caterer/action/provisioner/validate/bootstrapped.rb +1 -1
- data/lib/caterer/action/provisioner/validate/engine.rb +24 -0
- data/lib/caterer/action/provisioner/validate.rb +1 -0
- data/lib/caterer/actions.rb +1 -0
- data/lib/caterer/command/base.rb +5 -1
- data/lib/caterer/config/base.rb +2 -0
- data/lib/caterer/config/image.rb +3 -3
- data/lib/caterer/provisioner/base.rb +9 -12
- data/lib/caterer/provisioner/chef_solo.rb +126 -84
- data/lib/caterer/provisioners.rb +1 -0
- data/lib/caterer/server.rb +53 -36
- data/lib/caterer/version.rb +1 -1
- data/lib/caterer.rb +6 -1
- data/lib/templates/provisioner/chef_solo/solo.erb +4 -4
- metadata +4 -4
- data/lib/caterer/config/provision/chef_solo.rb +0 -74
- data/lib/caterer/config/provision.rb +0 -7
@@ -5,12 +5,15 @@ module Caterer
|
|
5
5
|
class Image < Base
|
6
6
|
|
7
7
|
def call(env)
|
8
|
-
# check to ensure the image exists
|
9
|
-
image = env[:config].images[env[:image]]
|
10
8
|
|
11
|
-
if
|
12
|
-
|
13
|
-
|
9
|
+
if env[:image]
|
10
|
+
# check to ensure the image exists
|
11
|
+
image = env[:config].images[env[:image]]
|
12
|
+
|
13
|
+
if not image
|
14
|
+
env[:ui].error "image ':#{env[:image]}' is not defined"
|
15
|
+
return
|
16
|
+
end
|
14
17
|
end
|
15
18
|
|
16
19
|
@app.call(env)
|
@@ -5,19 +5,22 @@ module Caterer
|
|
5
5
|
class Provisioner < Base
|
6
6
|
|
7
7
|
def call(env)
|
8
|
-
provisioner = env[:config].images[env[:image]].provisioner
|
9
8
|
|
10
|
-
if
|
11
|
-
env[:
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
errors.each do |key, val|
|
17
|
-
env[:ui].error "image :#{env[:image]} provisioner error -> #{key} #{val}"
|
9
|
+
if env[:image]
|
10
|
+
provisioner = env[:config].images[env[:image]].provisioner
|
11
|
+
|
12
|
+
if not provisioner
|
13
|
+
env[:ui].error "provisioner for image ':#{env[:image]}' is not defined"
|
14
|
+
return
|
18
15
|
end
|
19
|
-
|
20
|
-
|
16
|
+
|
17
|
+
if errors = provisioner.errors
|
18
|
+
errors.each do |key, val|
|
19
|
+
env[:ui].error "image :#{env[:image]} provisioner error -> #{key} #{val}"
|
20
|
+
end
|
21
|
+
return
|
22
|
+
end
|
23
|
+
end
|
21
24
|
|
22
25
|
@app.call(env)
|
23
26
|
end
|
@@ -1,13 +1,19 @@
|
|
1
|
-
require 'active_support/inflector'
|
2
|
-
|
3
1
|
module Caterer
|
4
2
|
module Action
|
5
3
|
module Provisioner
|
6
4
|
class Base < Action::Base
|
7
5
|
|
8
6
|
def provisioner(env)
|
9
|
-
|
10
|
-
|
7
|
+
|
8
|
+
if image = env[:image]
|
9
|
+
env[:config].images[image].provisioner
|
10
|
+
else
|
11
|
+
Caterer.provisioners.get(env[:engine] || default_engine).new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_engine
|
16
|
+
Caterer.config.default_provisioner
|
11
17
|
end
|
12
18
|
|
13
19
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Caterer
|
2
|
+
module Action
|
3
|
+
module Provisioner
|
4
|
+
module Validate
|
5
|
+
class Engine < Base
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
|
9
|
+
if env[:engine]
|
10
|
+
if not Caterer.provisioners.get(env[:engine])
|
11
|
+
env[:ui].error "Unsupported provision engine #{env[:engine]}"
|
12
|
+
return
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
@app.call(env)
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/caterer/actions.rb
CHANGED
@@ -3,6 +3,7 @@ Caterer.actions.register(:validate) do
|
|
3
3
|
Vli::Action::Builder.new do
|
4
4
|
use Caterer::Action::Config::Validate::Image
|
5
5
|
use Caterer::Action::Config::Validate::Provisioner
|
6
|
+
use Caterer::Action::Provisioner::Validate::Engine
|
6
7
|
use Caterer::Action::Server::Validate::SSH
|
7
8
|
use Caterer::Action::Server::Validate::Unlocked
|
8
9
|
end
|
data/lib/caterer/command/base.rb
CHANGED
@@ -60,7 +60,7 @@ module Caterer
|
|
60
60
|
argv.first.split(",").each do |host|
|
61
61
|
|
62
62
|
if group = @env.config.groups[host.to_sym]
|
63
|
-
group.members.each do |member|
|
63
|
+
group.members.each do |key, member|
|
64
64
|
servers << init_server(group, member, options)
|
65
65
|
end
|
66
66
|
else
|
@@ -99,6 +99,10 @@ module Caterer
|
|
99
99
|
opts[:images] = image_list(options) || member.images || group.images
|
100
100
|
opts[:key] = options[:key] || member.key || group.key
|
101
101
|
|
102
|
+
if engine = options[:engine]
|
103
|
+
opts[:engine] = engine.to_sym
|
104
|
+
end
|
105
|
+
|
102
106
|
opts[:data] = begin
|
103
107
|
data = nil
|
104
108
|
if json = options[:data]
|
data/lib/caterer/config/base.rb
CHANGED
data/lib/caterer/config/image.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/inflector'
|
2
|
-
|
3
1
|
module Caterer
|
4
2
|
module Config
|
5
3
|
class Image
|
@@ -11,7 +9,9 @@ module Caterer
|
|
11
9
|
end
|
12
10
|
|
13
11
|
def provision(type)
|
14
|
-
|
12
|
+
provisioner_klass = Caterer.provisioners.get(type)
|
13
|
+
raise ":#{type} is not a valida provisioner" if not provisioner_klass
|
14
|
+
@provisioner = provisioner_klass.new
|
15
15
|
yield @provisioner if block_given?
|
16
16
|
end
|
17
17
|
|
@@ -2,19 +2,16 @@ module Caterer
|
|
2
2
|
module Provisioner
|
3
3
|
class Base
|
4
4
|
|
5
|
-
|
5
|
+
# config dsl
|
6
|
+
def errors; end
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
def
|
13
|
-
def
|
14
|
-
def cleanup; end
|
15
|
-
def install; end
|
16
|
-
def prepare; end
|
17
|
-
def provision; end
|
8
|
+
# provision dsl
|
9
|
+
def bootstrap(server); end
|
10
|
+
def bootstrapped?(server); true; end
|
11
|
+
def cleanup(server); end
|
12
|
+
def install(server); end
|
13
|
+
def prepare(server); end
|
14
|
+
def provision(server); end
|
18
15
|
|
19
16
|
end
|
20
17
|
end
|
@@ -8,7 +8,76 @@ module Caterer
|
|
8
8
|
module Provisioner
|
9
9
|
class ChefSolo < Base
|
10
10
|
|
11
|
-
|
11
|
+
attr_reader :run_list
|
12
|
+
attr_accessor :json, :cookbooks_path, :roles_path
|
13
|
+
attr_accessor :data_bags_path, :bootstrap_scripts
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@run_list = []
|
17
|
+
@json = {}
|
18
|
+
@cookbooks_path = ['cookbooks']
|
19
|
+
@roles_path = ['roles']
|
20
|
+
@data_bags_path = ['data_bags']
|
21
|
+
@bootstrap_scripts = []
|
22
|
+
end
|
23
|
+
|
24
|
+
# config DSL
|
25
|
+
|
26
|
+
def add_recipe(recipe)
|
27
|
+
@run_list << "recipe[#{recipe}]"
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_role(role)
|
31
|
+
@run_list << "role[#{role}]"
|
32
|
+
end
|
33
|
+
|
34
|
+
# I don't like this at all, but it seems to make the best Caterfile workflow
|
35
|
+
def add_image(image)
|
36
|
+
image = Caterer.config.images[image]
|
37
|
+
raise "Unknown image :#{image}" if not image
|
38
|
+
|
39
|
+
provisioner = image.provisioner
|
40
|
+
raise "No provisioner for :#{image}" if not provisioner
|
41
|
+
|
42
|
+
if not provisioner.class == self.class
|
43
|
+
raise "add_image incompatibility: #{provisioner.class} != #{self.class}"
|
44
|
+
end
|
45
|
+
|
46
|
+
@run_list += provisioner.run_list
|
47
|
+
@bootstrap_scripts += provisioner.bootstrap_scripts
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_bootstrap(script)
|
51
|
+
@bootstrap_scripts << script
|
52
|
+
end
|
53
|
+
|
54
|
+
def errors
|
55
|
+
errors = {}
|
56
|
+
|
57
|
+
if not @run_list.length > 0
|
58
|
+
errors[:run_list] = "is empty"
|
59
|
+
end
|
60
|
+
|
61
|
+
if not @cookbooks_path.is_a? Array
|
62
|
+
errors[:cookbooks_path] = "must be an array"
|
63
|
+
end
|
64
|
+
|
65
|
+
if not @roles_path.is_a? Array
|
66
|
+
errors[:roles_path] = "must be an array"
|
67
|
+
end
|
68
|
+
|
69
|
+
if not @data_bags_path.is_a? Array
|
70
|
+
errors[:data_bags_path] = "must be an array"
|
71
|
+
end
|
72
|
+
|
73
|
+
if errors.length > 0
|
74
|
+
errors
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# provision engine
|
79
|
+
|
80
|
+
def bootstrap(server)
|
12
81
|
|
13
82
|
# validate
|
14
83
|
with_bootstrap_scripts do |script, count|
|
@@ -24,10 +93,10 @@ module Caterer
|
|
24
93
|
with_bootstrap_scripts do |script, count|
|
25
94
|
|
26
95
|
server.ui.info "Uploading #{script}..."
|
27
|
-
server.ssh.upload script, "#{
|
96
|
+
server.ssh.upload script, "#{target_bootstrap_path}-#{count}"
|
28
97
|
|
29
|
-
server.ssh.sudo "chown #{server.username} #{
|
30
|
-
server.ssh.sudo "chmod +x #{
|
98
|
+
server.ssh.sudo "chown #{server.username} #{target_bootstrap_path}-#{count}", :stream => true
|
99
|
+
server.ssh.sudo "chmod +x #{target_bootstrap_path}-#{count}", :stream => true
|
31
100
|
|
32
101
|
end
|
33
102
|
|
@@ -35,189 +104,162 @@ module Caterer
|
|
35
104
|
with_bootstrap_scripts do |script, count|
|
36
105
|
|
37
106
|
server.ui.info "Running #{script}..."
|
38
|
-
server.ssh.sudo "#{
|
107
|
+
server.ssh.sudo "#{target_bootstrap_path}-#{count}", :stream => true
|
39
108
|
|
40
109
|
end
|
41
110
|
|
42
111
|
end
|
43
112
|
|
44
|
-
def bootstrapped?
|
113
|
+
def bootstrapped?(server)
|
45
114
|
res = server.ssh.sudo "command -v chef-solo &>/dev/null"
|
46
115
|
res == 0 ? true : false
|
47
116
|
end
|
48
117
|
|
49
|
-
def prepare
|
118
|
+
def prepare(server)
|
50
119
|
# create base dir
|
51
|
-
server.ssh.sudo "mkdir -p #{
|
52
|
-
server.ssh.sudo "chown -R #{server.username} #{
|
120
|
+
server.ssh.sudo "mkdir -p #{target_base_path}", :stream => true
|
121
|
+
server.ssh.sudo "chown -R #{server.username} #{target_base_path}", :stream => true
|
53
122
|
end
|
54
123
|
|
55
|
-
def install
|
124
|
+
def install(server)
|
56
125
|
server.ui.info "Preparing installation..."
|
57
126
|
|
58
127
|
# upload
|
59
|
-
server.ssh.upload install_script, "#{
|
128
|
+
server.ssh.upload install_script, "#{target_install_path}"
|
60
129
|
|
61
130
|
# set permissions
|
62
|
-
server.ssh.sudo "chown #{server.username} #{
|
63
|
-
server.ssh.sudo "chmod +x #{
|
131
|
+
server.ssh.sudo "chown #{server.username} #{target_install_path}", :stream => true
|
132
|
+
server.ssh.sudo "chmod +x #{target_install_path}", :stream => true
|
64
133
|
|
65
134
|
# run
|
66
135
|
server.ui.info "Installing chef-solo..."
|
67
|
-
server.ssh.sudo "#{
|
136
|
+
server.ssh.sudo "#{target_install_path}", :stream => true
|
68
137
|
end
|
69
138
|
|
70
|
-
def provision
|
139
|
+
def provision(server)
|
71
140
|
|
72
141
|
# create cookbooks directory
|
73
|
-
server.ssh.sudo "mkdir -p #{
|
74
|
-
server.ssh.sudo "chown -R #{server.username} #{
|
142
|
+
server.ssh.sudo "mkdir -p #{target_cookbooks_path}", :stream => true
|
143
|
+
server.ssh.sudo "chown -R #{server.username} #{target_cookbooks_path}", :stream => true
|
75
144
|
|
76
145
|
# sync cookbooks
|
77
146
|
server.ui.info "Syncing cookbooks..."
|
78
|
-
|
79
|
-
upload_directory path, "#{
|
147
|
+
cookbooks_path.each do |path|
|
148
|
+
server.upload_directory path, "#{target_cookbooks_path}/#{Digest::MD5.hexdigest(path)}"
|
80
149
|
end
|
81
150
|
|
82
151
|
# create roles directory
|
83
|
-
server.ssh.sudo "mkdir -p #{
|
84
|
-
server.ssh.sudo "chown -R #{server.username} #{
|
152
|
+
server.ssh.sudo "mkdir -p #{target_roles_path}", :stream => true
|
153
|
+
server.ssh.sudo "chown -R #{server.username} #{target_roles_path}", :stream => true
|
85
154
|
|
86
155
|
# sync roles
|
87
156
|
server.ui.info "Syncing roles..."
|
88
|
-
|
89
|
-
upload_directory path,
|
157
|
+
roles_path.each do |path|
|
158
|
+
server.upload_directory path, target_roles_path
|
90
159
|
end
|
91
160
|
|
92
161
|
# create data_bags directory
|
93
|
-
server.ssh.sudo "mkdir -p #{
|
94
|
-
server.ssh.sudo "chown -R #{server.username} #{
|
162
|
+
server.ssh.sudo "mkdir -p #{target_data_bags_path}", :stream => true
|
163
|
+
server.ssh.sudo "chown -R #{server.username} #{target_data_bags_path}", :stream => true
|
95
164
|
|
96
165
|
# sync databags
|
97
166
|
server.ui.info "Syncing data bags..."
|
98
|
-
|
99
|
-
upload_directory path,
|
167
|
+
data_bags_path.each do |path|
|
168
|
+
server.upload_directory path, target_data_bags_path
|
100
169
|
end
|
101
170
|
|
102
171
|
# create solo.rb
|
103
172
|
server.ui.info "Generating solo.rb..."
|
104
|
-
server.ssh.upload(StringIO.new(solo_content),
|
173
|
+
server.ssh.upload(StringIO.new(solo_content(server)), target_solo_path)
|
105
174
|
|
106
175
|
# create json
|
107
176
|
server.ui.info "Generating json config..."
|
108
|
-
server.ssh.upload(StringIO.new(json_config),
|
177
|
+
server.ssh.upload(StringIO.new(json_config(config_data.merge(server.data))), target_json_config_path)
|
109
178
|
|
110
179
|
# set permissions on everything
|
111
|
-
server.ssh.sudo "chown -R #{server.username} #{
|
180
|
+
server.ssh.sudo "chown -R #{server.username} #{target_base_path}", :stream => true
|
112
181
|
|
113
182
|
# run
|
114
183
|
server.ui.info "Running chef-solo..."
|
115
184
|
server.ssh.sudo command_string, :stream => true
|
116
185
|
end
|
117
186
|
|
118
|
-
def cleanup
|
187
|
+
def cleanup(server)
|
119
188
|
server.ui.info "Cleaning up..."
|
120
189
|
|
121
190
|
# installer
|
122
|
-
server.ssh.sudo "rm -f #{
|
191
|
+
server.ssh.sudo "rm -f #{target_install_path}", :stream => true
|
123
192
|
|
124
193
|
# bootstrap scripts
|
125
|
-
server.ssh.sudo "rm -f #{
|
194
|
+
server.ssh.sudo "rm -f #{target_bootstrap_path}*", :stream => true
|
126
195
|
|
127
196
|
# solo.rb
|
128
|
-
server.ssh.sudo "rm -f #{
|
197
|
+
server.ssh.sudo "rm -f #{target_solo_path}", :stream => true
|
129
198
|
|
130
199
|
# json
|
131
|
-
server.ssh.sudo "rm -f #{
|
200
|
+
server.ssh.sudo "rm -f #{target_json_config_path}", :stream => true
|
132
201
|
|
133
202
|
# for now, leave cookbooks, roles, and data bags for faster provisioning
|
134
203
|
end
|
135
204
|
|
136
205
|
protected
|
137
206
|
|
138
|
-
def upload_directory(from, to)
|
139
|
-
if File.exists? from
|
140
|
-
if @server.can_rsync?
|
141
|
-
from += "/" if not from.match /\/$/
|
142
|
-
res = @server.rsync.sync(from, to)
|
143
|
-
server.ui.error "rsync was unsuccessful" if res != 0
|
144
|
-
else
|
145
|
-
server.ui.warn "Rsync unavailable, falling back to scp (slower)..."
|
146
|
-
unique = Digest::MD5.hexdigest(from)
|
147
|
-
server.ssh.sudo "rm -rf #{to}/*", :stream => true
|
148
|
-
server.ssh.sudo "mkdir -p #{to}/#{unique}", :stream => true
|
149
|
-
server.ssh.sudo "chown -R #{server.username} #{to}/#{unique}", :stream => true
|
150
|
-
server.ssh.upload from, "#{to}/#{unique}"
|
151
|
-
server.ssh.sudo "mv #{to}/#{unique}/**/* #{to}/", :stream => true
|
152
|
-
server.ssh.sudo "rm -rf #{to}/#{unique}", :stream => true
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
207
|
def with_bootstrap_scripts
|
158
|
-
|
208
|
+
bootstrap_scripts.each_with_index do |script, index|
|
159
209
|
yield script, index if block_given?
|
160
210
|
end
|
161
211
|
end
|
162
212
|
|
163
|
-
def
|
164
|
-
config.bootstrap_scripts
|
165
|
-
end
|
166
|
-
|
167
|
-
def base_path
|
213
|
+
def target_base_path
|
168
214
|
"/tmp/cater-chef-solo"
|
169
215
|
end
|
170
216
|
|
171
|
-
def
|
172
|
-
"#{
|
173
|
-
end
|
174
|
-
|
175
|
-
def bootstrap_path
|
176
|
-
"#{base_path}/bootstrap"
|
217
|
+
def target_install_path
|
218
|
+
"#{target_base_path}/install"
|
177
219
|
end
|
178
220
|
|
179
|
-
def
|
180
|
-
"#{
|
221
|
+
def target_bootstrap_path
|
222
|
+
"#{target_base_path}/bootstrap"
|
181
223
|
end
|
182
224
|
|
183
|
-
def
|
184
|
-
"#{
|
225
|
+
def target_cookbooks_path
|
226
|
+
"#{target_base_path}/cookbooks"
|
185
227
|
end
|
186
228
|
|
187
|
-
def
|
188
|
-
"#{
|
229
|
+
def target_roles_path
|
230
|
+
"#{target_base_path}/roles"
|
189
231
|
end
|
190
232
|
|
191
|
-
def
|
192
|
-
"#{
|
233
|
+
def target_data_bags_path
|
234
|
+
"#{target_base_path}/data_bags"
|
193
235
|
end
|
194
236
|
|
195
|
-
def
|
196
|
-
"#{
|
237
|
+
def target_solo_path
|
238
|
+
"#{target_base_path}/solo.rb"
|
197
239
|
end
|
198
240
|
|
199
|
-
def
|
200
|
-
config.
|
241
|
+
def target_json_config_path
|
242
|
+
"#{target_base_path}/config.json"
|
201
243
|
end
|
202
244
|
|
203
245
|
def install_script
|
204
246
|
File.expand_path("../../../templates/provisioner/chef_solo/bootstrap.sh", __FILE__)
|
205
247
|
end
|
206
248
|
|
207
|
-
def solo_content
|
208
|
-
Tilt.new(File.expand_path('../../../templates/provisioner/chef_solo/solo.erb', __FILE__)).render(self)
|
249
|
+
def solo_content(server)
|
250
|
+
Tilt.new(File.expand_path('../../../templates/provisioner/chef_solo/solo.erb', __FILE__)).render(self, {:server => server})
|
209
251
|
end
|
210
252
|
|
211
|
-
def json_config
|
212
|
-
MultiJson.dump(
|
253
|
+
def json_config(data)
|
254
|
+
MultiJson.dump(data)
|
213
255
|
end
|
214
256
|
|
215
257
|
def config_data
|
216
|
-
{:run_list =>
|
258
|
+
{:run_list => run_list}.merge(json)
|
217
259
|
end
|
218
260
|
|
219
261
|
def command_string
|
220
|
-
"chef-solo -c #{
|
262
|
+
"chef-solo -c #{target_solo_path} -j #{target_json_config_path}"
|
221
263
|
end
|
222
264
|
|
223
265
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Caterer.provisioners.register(:chef_solo) { Caterer::Provisioner::ChefSolo }
|
data/lib/caterer/server.rb
CHANGED
@@ -15,6 +15,7 @@ module Caterer
|
|
15
15
|
@key = opts[:key]
|
16
16
|
@images = opts[:images] || []
|
17
17
|
@data = opts[:data] || {}
|
18
|
+
@engine = opts[:engine]
|
18
19
|
|
19
20
|
@logger = Log4r::Logger.new("caterer::server")
|
20
21
|
|
@@ -22,22 +23,38 @@ module Caterer
|
|
22
23
|
end
|
23
24
|
|
24
25
|
def bootstrap(opts={})
|
25
|
-
if @images.length
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
if @images.length > 0
|
27
|
+
@images.each do |i|
|
28
|
+
ui.info "*** Bootstrapping image: #{i} ***"
|
29
|
+
run_action(:bootstrap, opts.merge({:image => i}))
|
30
|
+
end
|
31
|
+
else
|
32
|
+
ui.info "*** Bootstrapping ***"
|
33
|
+
run_action(:bootstrap, opts.merge({:engine => @engine}))
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
34
37
|
def provision(opts={})
|
35
|
-
if @images.length
|
36
|
-
|
38
|
+
if @images.length > 0
|
39
|
+
@images.each do |i|
|
40
|
+
ui.info "*** Provisioning image: #{i} ***"
|
41
|
+
run_action(:provision, opts.merge({:image => i}))
|
42
|
+
end
|
43
|
+
else
|
44
|
+
ui.info "*** Provisioning ***"
|
45
|
+
run_action(:provision, opts.merge({:engine => @engine}))
|
37
46
|
end
|
38
|
-
|
39
|
-
|
40
|
-
|
47
|
+
end
|
48
|
+
|
49
|
+
def up(opts={})
|
50
|
+
if @images.length > 0
|
51
|
+
@images.each do |i|
|
52
|
+
ui.info "*** Up'ing image: #{i} ***"
|
53
|
+
run_action(:up, opts.merge({:image => i}))
|
54
|
+
end
|
55
|
+
else
|
56
|
+
ui.info "*** Up'ing ***"
|
57
|
+
run_action(:up, opts.merge({:engine => @engine}))
|
41
58
|
end
|
42
59
|
end
|
43
60
|
|
@@ -45,34 +62,14 @@ module Caterer
|
|
45
62
|
run_action(:reboot, opts)
|
46
63
|
end
|
47
64
|
|
48
|
-
def up(opts={})
|
49
|
-
if @images.length == 0
|
50
|
-
ui.error "image list is empty, nothing to do"
|
51
|
-
end
|
52
|
-
@images.each do |i|
|
53
|
-
ui.info "*** Up'ing image: #{i} ***"
|
54
|
-
run_action(:up, opts.merge({:image => i}))
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
65
|
def lock(opts={})
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
@images.each do |i|
|
63
|
-
ui.info "*** Locking image: #{i} ***"
|
64
|
-
run_action(:lock, opts.merge({:image => i}))
|
65
|
-
end
|
66
|
+
ui.info "*** Locking ***"
|
67
|
+
run_action(:lock, opts)
|
66
68
|
end
|
67
69
|
|
68
70
|
def unlock(opts={})
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
@images.each do |i|
|
73
|
-
ui.info "*** Unlocking image: #{i} ***"
|
74
|
-
run_action(:unlock, opts.merge({:image => i}))
|
75
|
-
end
|
71
|
+
ui.info "*** Unlocking ***"
|
72
|
+
run_action(:unlock, opts)
|
76
73
|
end
|
77
74
|
|
78
75
|
def reboot!
|
@@ -112,7 +109,7 @@ module Caterer
|
|
112
109
|
opts[:paranoid] = false
|
113
110
|
opts[:port] = port
|
114
111
|
opts[:password] = password if password
|
115
|
-
opts[:keys] = [
|
112
|
+
opts[:keys] = [].tap {|keys| keys << @key if @key }
|
116
113
|
end
|
117
114
|
end
|
118
115
|
|
@@ -160,6 +157,26 @@ module Caterer
|
|
160
157
|
env.action_runner.run(name, options)
|
161
158
|
end
|
162
159
|
|
160
|
+
def upload_directory(from, to)
|
161
|
+
if File.exists? from
|
162
|
+
if can_rsync?
|
163
|
+
from += "/" if not from.match /\/$/
|
164
|
+
res = rsync.sync(from, to)
|
165
|
+
ui.error "rsync was unsuccessful" if res != 0
|
166
|
+
else
|
167
|
+
# yuck. Heaven help the poor soul who hath not rsync...
|
168
|
+
ui.warn "Rsync unavailable, falling back to scp (slower)..."
|
169
|
+
unique = Digest::MD5.hexdigest(from)
|
170
|
+
ssh.sudo "rm -rf #{to}/*", :stream => true
|
171
|
+
ssh.sudo "mkdir -p #{to}/#{unique}", :stream => true
|
172
|
+
ssh.sudo "chown -R #{username} #{to}/#{unique}", :stream => true
|
173
|
+
ssh.upload from, "#{to}/#{unique}"
|
174
|
+
ssh.sudo "mv #{to}/#{unique}/**/* #{to}/", :stream => true
|
175
|
+
ssh.sudo "rm -rf #{to}/#{unique}", :stream => true
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
163
180
|
protected
|
164
181
|
|
165
182
|
def lock_path
|
data/lib/caterer/version.rb
CHANGED
data/lib/caterer.rb
CHANGED
@@ -23,6 +23,10 @@ module Caterer
|
|
23
23
|
@commands ||= Vli::Registry.new
|
24
24
|
end
|
25
25
|
|
26
|
+
def provisioners
|
27
|
+
@provisioners ||= Vli::Registry.new
|
28
|
+
end
|
29
|
+
|
26
30
|
def config
|
27
31
|
@config ||= Config::Base.new
|
28
32
|
end
|
@@ -34,4 +38,5 @@ module Caterer
|
|
34
38
|
end
|
35
39
|
|
36
40
|
require 'caterer/commands'
|
37
|
-
require 'caterer/actions'
|
41
|
+
require 'caterer/actions'
|
42
|
+
require 'caterer/provisioners'
|
@@ -1,5 +1,5 @@
|
|
1
|
-
file_cache_path "<%=
|
1
|
+
file_cache_path "<%= target_base_path %>"
|
2
2
|
node_name "<%= server.host %>"
|
3
|
-
cookbook_path <%=
|
4
|
-
data_bag_path "<%=
|
5
|
-
role_path "<%=
|
3
|
+
cookbook_path <%= cookbooks_path.map { |path| "#{target_cookbooks_path}/#{Digest::MD5.hexdigest(path)}" }.inspect %>
|
4
|
+
data_bag_path "<%= target_data_bags_path %>"
|
5
|
+
role_path "<%= target_roles_path %>"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: caterer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: log4r
|
@@ -195,6 +195,7 @@ files:
|
|
195
195
|
- lib/caterer/action/provisioner/provision.rb
|
196
196
|
- lib/caterer/action/provisioner/validate.rb
|
197
197
|
- lib/caterer/action/provisioner/validate/bootstrapped.rb
|
198
|
+
- lib/caterer/action/provisioner/validate/engine.rb
|
198
199
|
- lib/caterer/action/server.rb
|
199
200
|
- lib/caterer/action/server/lock.rb
|
200
201
|
- lib/caterer/action/server/reboot.rb
|
@@ -222,13 +223,12 @@ files:
|
|
222
223
|
- lib/caterer/config/group.rb
|
223
224
|
- lib/caterer/config/image.rb
|
224
225
|
- lib/caterer/config/member.rb
|
225
|
-
- lib/caterer/config/provision.rb
|
226
|
-
- lib/caterer/config/provision/chef_solo.rb
|
227
226
|
- lib/caterer/environment.rb
|
228
227
|
- lib/caterer/logger.rb
|
229
228
|
- lib/caterer/provisioner.rb
|
230
229
|
- lib/caterer/provisioner/base.rb
|
231
230
|
- lib/caterer/provisioner/chef_solo.rb
|
231
|
+
- lib/caterer/provisioners.rb
|
232
232
|
- lib/caterer/server.rb
|
233
233
|
- lib/caterer/util.rb
|
234
234
|
- lib/caterer/util/ansi_escape_code_remover.rb
|
@@ -1,74 +0,0 @@
|
|
1
|
-
module Caterer
|
2
|
-
module Config
|
3
|
-
module Provision
|
4
|
-
|
5
|
-
class ChefSolo
|
6
|
-
|
7
|
-
attr_reader :name, :run_list
|
8
|
-
attr_accessor :json, :cookbooks_path, :roles_path, :data_bags_path, :bootstrap_scripts
|
9
|
-
|
10
|
-
def initialize(name)
|
11
|
-
@name = name
|
12
|
-
@run_list = []
|
13
|
-
@json = {}
|
14
|
-
@cookbooks_path = ['cookbooks']
|
15
|
-
@roles_path = ['roles']
|
16
|
-
@data_bags_path = ['data_bags']
|
17
|
-
@bootstrap_scripts = []
|
18
|
-
end
|
19
|
-
|
20
|
-
def add_recipe(recipe)
|
21
|
-
@run_list << "recipe[#{recipe}]"
|
22
|
-
end
|
23
|
-
|
24
|
-
def add_role(role)
|
25
|
-
@run_list << "role[#{role}]"
|
26
|
-
end
|
27
|
-
|
28
|
-
def add_image(image)
|
29
|
-
image = Caterer.config.images[image]
|
30
|
-
raise "Unknown image :#{image}" if not image
|
31
|
-
|
32
|
-
provisioner = image.provisioner
|
33
|
-
raise "No provisioner for :#{image}" if not provisioner
|
34
|
-
|
35
|
-
if not provisioner.name == :chef_solo
|
36
|
-
raise "Incompatible provisioner. Must be :#{provisioner.name}"
|
37
|
-
end
|
38
|
-
|
39
|
-
@run_list += provisioner.run_list
|
40
|
-
@bootstrap_scripts += provisioner.bootstrap_scripts
|
41
|
-
end
|
42
|
-
|
43
|
-
def add_bootstrap(script)
|
44
|
-
@bootstrap_scripts << script
|
45
|
-
end
|
46
|
-
|
47
|
-
def errors
|
48
|
-
errors = {}
|
49
|
-
|
50
|
-
if not @run_list.length > 0
|
51
|
-
errors[:run_list] = "is empty"
|
52
|
-
end
|
53
|
-
|
54
|
-
if not @cookbooks_path.is_a? Array
|
55
|
-
errors[:cookbooks_path] = "must be an array"
|
56
|
-
end
|
57
|
-
|
58
|
-
if not @roles_path.is_a? Array
|
59
|
-
errors[:roles_path] = "must be an array"
|
60
|
-
end
|
61
|
-
|
62
|
-
if not @data_bags_path.is_a? Array
|
63
|
-
errors[:data_bags_path] = "must be an array"
|
64
|
-
end
|
65
|
-
|
66
|
-
if errors.length > 0
|
67
|
-
errors
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|