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