caterer 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Berksfile +3 -0
- data/Berksfile.lock +0 -0
- data/README.md +138 -2
- data/Vagrantfile +22 -0
- data/bin/cater +9 -0
- data/caterer.gemspec +5 -0
- data/cookbooks/users/recipes/default.rb +18 -0
- data/example/Caterfile +28 -10
- data/example/bootstrap.sh +3 -0
- data/knife.rb +1 -0
- data/lib/caterer/action/base.rb +10 -0
- data/lib/caterer/action/config/validate/image.rb +23 -0
- data/lib/caterer/action/config/validate/provisioner.rb +29 -0
- data/lib/caterer/action/config/validate.rb +10 -0
- data/lib/caterer/action/config.rb +7 -0
- data/lib/caterer/action/provisioner/base.rb +16 -0
- data/lib/caterer/action/provisioner/bootstrap.rb +14 -0
- data/lib/caterer/action/provisioner/cleanup.rb +14 -0
- data/lib/caterer/action/provisioner/prepare.rb +14 -0
- data/lib/caterer/action/provisioner/provision.rb +14 -0
- data/lib/caterer/action/provisioner.rb +11 -0
- data/lib/caterer/action/server/validate/ssh.rb +22 -0
- data/lib/caterer/action/server/validate.rb +9 -0
- data/lib/caterer/action/server.rb +7 -0
- data/lib/caterer/action.rb +9 -0
- data/lib/caterer/actions.rb +48 -0
- data/lib/caterer/command/base.rb +100 -0
- data/lib/caterer/command/bootstrap.rb +28 -0
- data/lib/caterer/command/provision.rb +24 -0
- data/lib/caterer/command/reboot.rb +22 -0
- data/lib/caterer/command/test.rb +9 -2
- data/lib/caterer/command/up.rb +28 -0
- data/lib/caterer/command.rb +6 -1
- data/lib/caterer/commands.rb +6 -1
- data/lib/caterer/communication/rsync.rb +14 -0
- data/lib/caterer/communication/ssh.rb +185 -0
- data/lib/caterer/communication.rb +6 -0
- data/lib/caterer/config/base.rb +24 -11
- data/lib/caterer/config/group.rb +24 -0
- data/lib/caterer/config/image.rb +20 -0
- data/lib/caterer/config/member.rb +14 -0
- data/lib/caterer/config/provision/chef_solo.rb +36 -12
- data/lib/caterer/config/provision.rb +5 -3
- data/lib/caterer/config.rb +5 -1
- data/lib/caterer/environment.rb +38 -12
- data/lib/caterer/provisioner/base.rb +19 -0
- data/lib/caterer/provisioner/chef_solo.rb +150 -0
- data/lib/caterer/provisioner.rb +6 -0
- data/lib/caterer/server.rb +102 -0
- data/lib/caterer/util/ansi_escape_code_remover.rb +34 -0
- data/lib/caterer/util/retryable.rb +25 -0
- data/lib/caterer/util.rb +6 -0
- data/lib/caterer/version.rb +1 -1
- data/lib/caterer.rb +15 -5
- data/lib/templates/provisioner/chef_solo/bootstrap.sh +87 -0
- data/lib/templates/provisioner/chef_solo/solo.erb +3 -0
- metadata +124 -3
- data/lib/caterer/config/role.rb +0 -21
@@ -0,0 +1,28 @@
|
|
1
|
+
module Caterer
|
2
|
+
module Command
|
3
|
+
class Bootstrap < Base
|
4
|
+
|
5
|
+
def execute
|
6
|
+
options = {}
|
7
|
+
opts = OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: cater bootstrap HOST [options]"
|
9
|
+
opts.separator ""
|
10
|
+
opts.on("-s SCRIPT", "--script SCRIPT", 'optional bootstrap script') do |s|
|
11
|
+
options[:script] = s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Parse the options
|
16
|
+
argv = parse_options(opts, options, true)
|
17
|
+
return if not argv
|
18
|
+
|
19
|
+
with_target_servers(argv, options) do |server|
|
20
|
+
server.bootstrap({:script => options[:script]})
|
21
|
+
end
|
22
|
+
|
23
|
+
0
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Caterer
|
2
|
+
module Command
|
3
|
+
class Provision < Base
|
4
|
+
|
5
|
+
def execute
|
6
|
+
options = {}
|
7
|
+
opts = OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: cater provision HOST [options]"
|
9
|
+
end
|
10
|
+
|
11
|
+
# Parse the options
|
12
|
+
argv = parse_options(opts, options, true)
|
13
|
+
return if not argv
|
14
|
+
|
15
|
+
with_target_servers(argv, options) do |server|
|
16
|
+
server.provision
|
17
|
+
end
|
18
|
+
|
19
|
+
0
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Caterer
|
2
|
+
module Command
|
3
|
+
class Reboot < Base
|
4
|
+
|
5
|
+
def execute
|
6
|
+
options = {}
|
7
|
+
opts = OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: cater provision HOST [options]"
|
9
|
+
end
|
10
|
+
|
11
|
+
# Parse the options
|
12
|
+
argv = parse_options(opts, options, true)
|
13
|
+
return if not argv
|
14
|
+
|
15
|
+
@env.ui.info options
|
16
|
+
@env.ui.info argv
|
17
|
+
0
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/caterer/command/test.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
module Caterer
|
2
2
|
module Command
|
3
|
-
class Test <
|
3
|
+
class Test < Base
|
4
4
|
|
5
5
|
def execute
|
6
|
-
|
6
|
+
options = {}
|
7
|
+
opts = OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: cater test"
|
9
|
+
end
|
10
|
+
|
11
|
+
# Parse the options
|
12
|
+
argv = parse_options(opts, options, false)
|
13
|
+
|
7
14
|
0
|
8
15
|
end
|
9
16
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Caterer
|
2
|
+
module Command
|
3
|
+
class Up < Base
|
4
|
+
|
5
|
+
def execute
|
6
|
+
options = {}
|
7
|
+
opts = OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: cater provision HOST [options]"
|
9
|
+
opts.separator ""
|
10
|
+
opts.on("-s SCRIPT", "--script SCRIPT", 'optional bootstrap script') do |s|
|
11
|
+
options[:script] = s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Parse the options
|
16
|
+
argv = parse_options(opts, options, true)
|
17
|
+
return if not argv
|
18
|
+
|
19
|
+
with_target_servers(argv, options) do |server|
|
20
|
+
server.up({:script => options[:script]})
|
21
|
+
end
|
22
|
+
|
23
|
+
0
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/caterer/command.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
module Caterer
|
2
2
|
module Command
|
3
|
-
autoload :
|
3
|
+
autoload :Base, 'caterer/command/base'
|
4
|
+
autoload :Bootstrap, 'caterer/command/bootstrap'
|
5
|
+
autoload :Provision, 'caterer/command/provision'
|
6
|
+
autoload :Reboot, 'caterer/command/reboot'
|
7
|
+
autoload :Test, 'caterer/command/test'
|
8
|
+
autoload :Up, 'caterer/command/up'
|
4
9
|
end
|
5
10
|
end
|
data/lib/caterer/commands.rb
CHANGED
@@ -1 +1,6 @@
|
|
1
|
-
|
1
|
+
# commands
|
2
|
+
Caterer.commands.register(:test) { Caterer::Command::Test }
|
3
|
+
Caterer.commands.register(:bootstrap) { Caterer::Command::Bootstrap }
|
4
|
+
Caterer.commands.register(:provision) { Caterer::Command::Provision }
|
5
|
+
Caterer.commands.register(:up) { Caterer::Command::Up }
|
6
|
+
Caterer.commands.register(:reboot) { Caterer::Command::Reboot }
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'net/ssh'
|
3
|
+
require 'net/scp'
|
4
|
+
require 'log4r'
|
5
|
+
|
6
|
+
module Caterer
|
7
|
+
module Communication
|
8
|
+
class SSH
|
9
|
+
include Util::ANSIEscapeCodeRemover
|
10
|
+
include Util::Retryable
|
11
|
+
|
12
|
+
def initialize(server)
|
13
|
+
@server = server
|
14
|
+
@connection = nil
|
15
|
+
@logger = Log4r::Logger.new("caterer::communication::ssh")
|
16
|
+
end
|
17
|
+
|
18
|
+
def ready?
|
19
|
+
@logger.debug("Checking whether SSH is ready...")
|
20
|
+
|
21
|
+
Timeout.timeout(30) do
|
22
|
+
connect
|
23
|
+
end
|
24
|
+
|
25
|
+
# If we reached this point then we successfully connected
|
26
|
+
@logger.info("SSH is ready!")
|
27
|
+
true
|
28
|
+
rescue => e
|
29
|
+
# The above errors represent various reasons that SSH may not be
|
30
|
+
# ready yet. Return false.
|
31
|
+
@logger.info("SSH not up: #{e.inspect}")
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
|
35
|
+
def execute(command, opts={}, &block)
|
36
|
+
connect do |connection|
|
37
|
+
shell_execute(connection, command, opts, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def sudo(command, opts={}, &block)
|
42
|
+
sudo = (@server.username == 'root') ? false : true
|
43
|
+
execute(command, opts.merge({:sudo => sudo}), &block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def upload(from, to)
|
47
|
+
@logger.debug("Uploading: #{from} to #{to}")
|
48
|
+
|
49
|
+
# Do an SCP-based upload...
|
50
|
+
connect do |connection|
|
51
|
+
opts = {}
|
52
|
+
opts[:recursive] = true if from.is_a?(String) and File.directory?(from)
|
53
|
+
scp = Net::SCP.new(connection)
|
54
|
+
scp.upload!(from, to, opts)
|
55
|
+
end
|
56
|
+
rescue Net::SCP::Error => e
|
57
|
+
# If we get the exit code of 127, then this means SCP is unavailable.
|
58
|
+
raise "scp unavailable" if e.message =~ /\(127\)/
|
59
|
+
|
60
|
+
# Otherwise, just raise the error up
|
61
|
+
raise
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
# Opens an SSH connection and yields it to a block.
|
67
|
+
def connect
|
68
|
+
if @connection && !@connection.closed?
|
69
|
+
# There is a chance that the socket is closed despite us checking
|
70
|
+
# 'closed?' above. To test this we need to send data through the
|
71
|
+
# socket.
|
72
|
+
begin
|
73
|
+
@connection.exec!("")
|
74
|
+
rescue IOError
|
75
|
+
@logger.info("Connection has been closed. Not re-using.")
|
76
|
+
@connection = nil
|
77
|
+
end
|
78
|
+
|
79
|
+
# If the @connection is still around, then it is valid,
|
80
|
+
# and we use it.
|
81
|
+
if @connection
|
82
|
+
@logger.debug("Re-using SSH connection.")
|
83
|
+
return yield @connection if block_given?
|
84
|
+
return
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Connect to SSH, giving it a few tries
|
89
|
+
connection = nil
|
90
|
+
# These are the exceptions that we retry because they represent
|
91
|
+
# errors that are generally fixed from a retry and don't
|
92
|
+
# necessarily represent immediate failure cases.
|
93
|
+
exceptions = [
|
94
|
+
Errno::ECONNREFUSED,
|
95
|
+
Errno::EHOSTUNREACH,
|
96
|
+
Net::SSH::Disconnect,
|
97
|
+
Timeout::Error
|
98
|
+
]
|
99
|
+
|
100
|
+
@logger.info("Connecting to SSH: (#{@server.host}:#{@server.port}")
|
101
|
+
@server.ui.info "Connecting..."
|
102
|
+
connection = retryable(:tries => 10, :on => exceptions) do
|
103
|
+
Net::SSH.start(@server.host, @server.username, @server.ssh_opts)
|
104
|
+
end
|
105
|
+
|
106
|
+
@connection = connection
|
107
|
+
|
108
|
+
# This is hacky but actually helps with some issues where
|
109
|
+
# Net::SSH is simply not robust enough to handle... see
|
110
|
+
# issue #391, #455, etc.
|
111
|
+
# sleep 4
|
112
|
+
|
113
|
+
# Yield the connection that is ready to be used and
|
114
|
+
# return the value of the block
|
115
|
+
return yield connection if block_given?
|
116
|
+
end
|
117
|
+
|
118
|
+
# Executes the command on an SSH connection within a login shell.
|
119
|
+
def shell_execute(connection, command, opts={})
|
120
|
+
|
121
|
+
opts[:sudo] ||= false
|
122
|
+
opts[:stream] ||= false
|
123
|
+
|
124
|
+
@logger.info("Execute: #{command} (opts=#{opts.inspect})")
|
125
|
+
exit_status = nil
|
126
|
+
|
127
|
+
# Determine the shell to execute. If we are using `sudo` then we
|
128
|
+
# need to wrap the shell in a `sudo` call.
|
129
|
+
shell = "bash -l"
|
130
|
+
shell = "sudo -H #{shell}" if opts[:sudo]
|
131
|
+
|
132
|
+
# Open the channel so we can execute or command
|
133
|
+
channel = connection.open_channel do |ch|
|
134
|
+
ch.exec(shell) do |ch2, _|
|
135
|
+
# Setup the channel callbacks so we can get data and exit status
|
136
|
+
ch2.on_data do |ch3, data|
|
137
|
+
@logger.debug("stdout: #{data}")
|
138
|
+
if block_given?
|
139
|
+
# Filter out the clear screen command
|
140
|
+
data = remove_ansi_escape_codes(data)
|
141
|
+
yield :stdout, data
|
142
|
+
end
|
143
|
+
if opts[:stream]
|
144
|
+
@server.ui.info data, {:prefix => false, :new_line => false}
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
ch2.on_extended_data do |ch3, type, data|
|
149
|
+
@logger.debug("stderr: #{data}")
|
150
|
+
if block_given?
|
151
|
+
# Filter out the clear screen command
|
152
|
+
data = remove_ansi_escape_codes(data)
|
153
|
+
yield :stderr, data
|
154
|
+
end
|
155
|
+
if opts[:stream]
|
156
|
+
@server.ui.info data, {:prefix => false, :new_line => false}
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
ch2.on_request("exit-status") do |ch3, data|
|
161
|
+
exit_status = data.read_long
|
162
|
+
@logger.debug("Exit status: #{exit_status}")
|
163
|
+
end
|
164
|
+
|
165
|
+
# Set the terminal
|
166
|
+
ch2.send_data "export TERM=vt100\n"
|
167
|
+
|
168
|
+
# Output the command
|
169
|
+
ch2.send_data "#{command}\n"
|
170
|
+
|
171
|
+
# Remember to exit or this channel will hang open
|
172
|
+
ch2.send_data "exit\n"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Wait for the channel to complete
|
177
|
+
channel.wait
|
178
|
+
|
179
|
+
# Return the final exit status
|
180
|
+
return exit_status
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
data/lib/caterer/config/base.rb
CHANGED
@@ -1,17 +1,30 @@
|
|
1
|
-
module Caterer
|
1
|
+
module Caterer
|
2
|
+
module Config
|
3
|
+
class Base
|
2
4
|
|
3
|
-
|
4
|
-
attr_accessor :roles
|
5
|
+
attr_reader :images, :groups
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def initialize
|
8
|
+
@images = {}
|
9
|
+
@groups = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def image(name)
|
13
|
+
@images[name] ||= Image.new(name)
|
14
|
+
yield @images[name] if block_given?
|
15
|
+
end
|
16
|
+
|
17
|
+
def group(name)
|
18
|
+
@groups[name] ||= Group.new(name)
|
19
|
+
yield @groups[name] if block_given?
|
20
|
+
end
|
21
|
+
|
22
|
+
def member(name, &block)
|
23
|
+
group(:default) do |d|
|
24
|
+
d.member(name, &block)
|
25
|
+
end
|
26
|
+
end
|
9
27
|
|
10
|
-
def role(name)
|
11
|
-
role = Caterer::Config::Role.new(name)
|
12
|
-
yield role if block_given?
|
13
|
-
@roles << role
|
14
28
|
end
|
15
29
|
end
|
16
|
-
|
17
30
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Caterer
|
2
|
+
module Config
|
3
|
+
class Group
|
4
|
+
|
5
|
+
attr_reader :name
|
6
|
+
attr_accessor :images, :members, :user, :password
|
7
|
+
|
8
|
+
def initialize(name=nil)
|
9
|
+
@name = name
|
10
|
+
@images = []
|
11
|
+
@members = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_image(image)
|
15
|
+
@images << image
|
16
|
+
end
|
17
|
+
|
18
|
+
def member(name)
|
19
|
+
@members[name] ||= Member.new(name)
|
20
|
+
yield @members[name] if block_given?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module Caterer
|
4
|
+
module Config
|
5
|
+
class Image
|
6
|
+
|
7
|
+
attr_reader :name, :provisioner
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name
|
11
|
+
end
|
12
|
+
|
13
|
+
def provision(type)
|
14
|
+
@provisioner = "Caterer::Config::Provision::#{type.to_s.classify}".constantize.new(type)
|
15
|
+
yield @provisioner if block_given?
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,18 +1,42 @@
|
|
1
|
-
module Caterer
|
1
|
+
module Caterer
|
2
|
+
module Config
|
3
|
+
module Provision
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
class ChefSolo
|
6
|
+
|
7
|
+
attr_reader :name, :run_list
|
8
|
+
attr_accessor :json, :cookbooks_path, :roles_path, :data_bags_path, :bootstrap_script
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
+
end
|
11
18
|
|
12
|
-
|
13
|
-
|
14
|
-
|
19
|
+
def add_recipe(recipe)
|
20
|
+
@run_list << "recipe[#{recipe}]"
|
21
|
+
end
|
15
22
|
|
16
|
-
|
23
|
+
def add_role(role)
|
24
|
+
@run_list << "role[#{role}]"
|
25
|
+
end
|
26
|
+
|
27
|
+
def errors
|
28
|
+
errors = {}
|
17
29
|
|
30
|
+
if not @run_list.length > 0
|
31
|
+
errors[:run_list] = "is empty"
|
32
|
+
end
|
33
|
+
|
34
|
+
if errors.length > 0
|
35
|
+
errors
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
18
42
|
end
|
data/lib/caterer/config.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
module Caterer
|
2
2
|
module Config
|
3
3
|
autoload :Base, 'caterer/config/base'
|
4
|
-
autoload :
|
4
|
+
autoload :Cluster, 'caterer/config/cluster'
|
5
|
+
autoload :Group, 'caterer/config/group'
|
6
|
+
autoload :Member, 'caterer/config/member'
|
7
|
+
autoload :Node, 'caterer/config/node'
|
8
|
+
autoload :Image, 'caterer/config/image'
|
5
9
|
autoload :Provision, 'caterer/config/provision'
|
6
10
|
end
|
7
11
|
end
|
data/lib/caterer/environment.rb
CHANGED
@@ -9,42 +9,68 @@ module Caterer
|
|
9
9
|
opts = {
|
10
10
|
:cwd => nil,
|
11
11
|
:caterfile_name => nil,
|
12
|
-
:ui_class => nil
|
12
|
+
:ui_class => nil,
|
13
|
+
:custom_config => nil
|
13
14
|
}.merge(opts)
|
14
15
|
|
15
16
|
opts[:cwd] ||= ENV["CATERER_CWD"] if ENV.has_key?("CATERER_CWD")
|
16
17
|
opts[:cwd] ||= Dir.pwd
|
17
|
-
opts[:cwd] = Pathname.new(opts[:cwd])
|
18
18
|
|
19
19
|
opts[:caterfile_name] ||= []
|
20
|
-
opts[:caterfile_name] = [opts[:caterfile_name]] if !opts[:
|
20
|
+
opts[:caterfile_name] = [opts[:caterfile_name]] if !opts[:caterfile_name].is_a?(Array)
|
21
21
|
opts[:caterfile_name] += ["Caterfile"]
|
22
22
|
|
23
|
-
@cwd = opts[:cwd]
|
23
|
+
@cwd = Pathname.new(opts[:cwd])
|
24
24
|
@caterfile_name = opts[:caterfile_name]
|
25
|
+
@custom_config = opts[:custom_config]
|
25
26
|
|
26
27
|
ui_class = opts[:ui_class] || Vli::UI::Silent
|
27
28
|
@ui = ui_class.new("cater")
|
28
29
|
|
29
30
|
end
|
30
31
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
32
|
+
def action_runner
|
33
|
+
@action_runner ||= Vli::Action::Runner.new(action_registry) do
|
34
|
+
{
|
35
|
+
:action_runner => action_runner,
|
36
|
+
:ui => @ui
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def action_registry
|
42
|
+
Caterer.actions
|
43
|
+
end
|
44
|
+
|
45
|
+
def config
|
46
|
+
@config ||= begin
|
47
|
+
load_default_config
|
48
|
+
load_custom_config
|
49
|
+
Caterer.config
|
50
|
+
end
|
34
51
|
end
|
52
|
+
alias :load! :config
|
35
53
|
|
36
54
|
def load_default_config
|
37
|
-
|
38
|
-
# require 'config/default'
|
55
|
+
require_relative '../../config/default'
|
39
56
|
end
|
40
57
|
|
41
58
|
def load_custom_config
|
42
|
-
@
|
43
|
-
|
44
|
-
|
59
|
+
if @custom_config
|
60
|
+
# if it's been explicitly defined, load it
|
61
|
+
load_config_file @custom_config
|
62
|
+
else
|
63
|
+
# lets try a few variations
|
64
|
+
@caterfile_name.each do |config_file|
|
65
|
+
load_config_file "#{@cwd}/#{config_file}"
|
66
|
+
end
|
45
67
|
end
|
46
68
|
end
|
47
69
|
|
70
|
+
def load_config_file(file)
|
71
|
+
load file if File.exists? file
|
72
|
+
end
|
73
|
+
|
48
74
|
def cli(*args)
|
49
75
|
Cli.new(args.flatten, self).execute
|
50
76
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Caterer
|
2
|
+
module Provisioner
|
3
|
+
class Base
|
4
|
+
|
5
|
+
attr_reader :server
|
6
|
+
|
7
|
+
def initialize(server, config=nil)
|
8
|
+
@server = server
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
def bootstrap(script=nil); end
|
13
|
+
def prepare; end
|
14
|
+
def provision; end
|
15
|
+
def cleanup; end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|