promotion 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --title "Promotion" -m rdoc --main README lib/**/*.rb - README
data/CHANGELOG ADDED
File without changes
data/README ADDED
@@ -0,0 +1,256 @@
1
+ = Promotion
2
+ Promotion makes it possible to repeatedly deploy an application in a fast and
3
+ reliable way.
4
+
5
+ == Staging
6
+ A key concept is the *staging* area. It is a folder (+/var/staging+ by default)
7
+ where the files for each application are loaded into a named sub-folder (eg. +/var/staging/myapp+).
8
+ For example, a staging area may look like this:
9
+
10
+ /var
11
+ |__ staging
12
+ |__ webapp1 -- a web application
13
+ |__ monitor -- sysadmin tool to monitor availability
14
+ |__ analytics -- analytics app for admins
15
+ |__ snort -- a custom config for snort
16
+
17
+ In this example, note that we also have an area for an installed application like snort.
18
+ Although the binaries are installed through normal package installation,
19
+ you may have a lot of time and work invested in the
20
+ configuration. These files can of course be backed up and restored manually, but the purpose of
21
+ Promotion is to make deployment fast and reliable. One way to achieve that is to store your
22
+ valuable configuration files in source control, so you can reliably checkout the latest version
23
+ for deployment each and every time. So the +snort+ staging area need only hold a few configuration
24
+ files.
25
+
26
+ Aside: why not just use version control?::
27
+ The important files are spread all over the file system, so the only way to restore them all
28
+ in a single command is to make the root directory a subversion working folder, add selected
29
+ files to version control and then have <code>.svn</code> folders spread all over the place.
30
+ Moreover, you'd need to run svn as root.
31
+
32
+ == Deployment Descriptor
33
+ Each application has an XML <b>deployment descriptor</b> (eg. +/var/staging/myapp/deploy.xml+)
34
+ that describes the conditions necessary for the successful operation of the application.
35
+
36
+ The deployment descriptor describes how to move the files from staging to their correct
37
+ locations in the file system. This simple requirement unrolls into a chain of others:
38
+ - we need the folder to be there to put the file in
39
+ - the permissions need to be correct on the file and folder
40
+ - the ownerships must be set
41
+ - that means we need the necessary user accounts created
42
+ - which means we first need the right groups set up.
43
+
44
+ In addition to installing the application's files, there are system-wide configuration
45
+ files that need to be adjusted to enable an application to startup or run properly:
46
+ - /etc/profile
47
+ - /etc/rc.conf.local
48
+ - /etc/sudoers
49
+ - /var/cron/tabs/*
50
+
51
+ Promotion generates these files based on the set of all of the deployment descriptors it finds
52
+ in the staging area.
53
+
54
+ An important aspect is that a deployment is *idempotent* - you can do it as many
55
+ times as you like and the result will be the same. This means its safe to make a
56
+ small change to an application and re-deploy it in a few seconds, ready for testing.
57
+
58
+ Promotion is useful in a testing environment when changes and redeployments are frequent,
59
+ but it shines in a production environment by reducing maintenance downtime and risk.
60
+
61
+ Promotion was originally designed for use on an OpenBSD system, but is configurable enough to work
62
+ on any *nix system. Just modify the <code>promotion/config.rb</code> configuration file
63
+ to suit your system's paths.
64
+
65
+ == Installation
66
+ *WARNING*::
67
+ Promotion will makes changes to your operating system, including important system-wide files.
68
+
69
+ DO NOT USE ON A PRODUCTION SYSTEM without rigorous testing in a virtual machine first.
70
+
71
+ Create the staging area (and set permissions appropriately):
72
+
73
+ $ sudo mkdir /var/staging
74
+
75
+ Check out the promotion app into staging, and bootstrap promotion
76
+ $ sudo wget http://rubyforge.org/frs/download.php/76463/promotion-x.y.z.zip
77
+ $ sudo unzip promotion-x.y.z.zip -d promotion # creates the promotion sub-directory
78
+ $ cd promotion
79
+ $ sudo ruby bin/bootstrap
80
+ Promoting promotion...OK.
81
+ $ cd /var/staging
82
+ Now you are ready to use Promotion to deploy other applications.
83
+
84
+ == Usage
85
+ For each application you want to deploy, create its staging folder:
86
+ $ cd /var/staging
87
+ $ sudo svn checkout https://hosted/path/to/project/dist myapp
88
+ The project (or perhaps a +dist+ folder designed for deployment) is checked out into
89
+ a folder with the given name.
90
+
91
+ Now you can promote the application:
92
+ $ sudo promote myapp
93
+ Promoting myapp...OK.
94
+
95
+ If a database is involved, you can also migrate the database schema:
96
+ $ sudo evolve myapp
97
+ Evolving the database to version 1023
98
+ which will execute any new schema migration scripts. If you execute it again,
99
+ you will see:
100
+ $ sudo evolve myapp
101
+ Already at version 1023.
102
+
103
+ If you want to revert to an earlier version of the database schema:
104
+ $ sudo devolve myapp 1017
105
+ Devolving the database to version 1017
106
+ which will execute the schema migration scripts in the +devolve+ folder,
107
+ in reverse order from 1023 down to 1017.
108
+
109
+ == Deployment descriptor syntax
110
+ The deployment descriptor is typically named <code>deploy.xml</code> and placed at the top
111
+ of the application's staging folder (eg. <code>/var/staging/myapp</code>).
112
+
113
+ It's structure is described by the XML schema which can be found at
114
+ at +/var/staging/promotion/promotion.xsd+ or at
115
+ http://finalstep.com.au/schema/promotion.v100.xsd
116
+
117
+ === +Specification+
118
+ The top level element is a Specification
119
+ <?xml version="1.0" encoding="UTF-8" ?>
120
+ <Specification Name="myapp" Title="My Test App"
121
+ xmlns="http://finalstep.com.au/promotion/v100"
122
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
123
+ xsi:schemaLocation="http://finalstep.com.au/schema/promotion.v100.xsd ../promotion/promotion.xsd">
124
+ which has a +Name+ matching the staging folder it resides in (+myapp+), and a fuller +Title+.
125
+
126
+ === +Description+
127
+ A description element is the first child:
128
+ <Description>
129
+ The promotion manager ensures that the environment for an application
130
+ is set up correctly, including folder and file permissions and ownership,
131
+ startup scripts, sudoers privileges and environment variables.
132
+ </Description>
133
+
134
+ === +Groups+
135
+ The sequence is then driven by dependencies: you cannot set ownerships until you have
136
+ users, and you cannot create a user without a group, so Groups come first. Each of these
137
+ elements is optional however.
138
+ <Groups>
139
+ <Group Gid="502" Name="_mysql" />
140
+ </Groups>
141
+ This creates a group with group ID <code>502</code> and the name <code>_mysql</code>.
142
+
143
+ === +Users+
144
+ We can also create an admin and a user to run the MySQL daemon:
145
+ <Users>
146
+ <User Name="richard" Class="staff" Gecos="Richard Kernahan" Uid="1002" Gid="1002"
147
+ Home="/home/richard" Shell="/bin/ksh" Groups="wheel webadmin"/>
148
+ <User Name="_mysql" Class="daemon" Gecos="MySQL Account" Uid="502"Gid="502"
149
+ Home="/nonexistent" Shell="/sbin/nologin" />
150
+ </Users>
151
+
152
+ - +Name+, +Uid+, and +Gid+ are mandatory
153
+ - +Gecos+ defaults to the Name
154
+ - +Home+ for +richard+ defaults to +/home/richard+
155
+ - +Shell+ defaults to +/sbin/nologin+
156
+ - +Groups+ is an optional space-separated list of groups the user should be added to
157
+
158
+ === +Folders+
159
+ Before we can move files into place, we need the Folders set up:
160
+ <Folders Mode="0750" Owner="root" Group="wheel">
161
+ <Folder Owner="_mysql" Group="_mysql">/var/mysql</Folder>
162
+ <Folder>/home/myapp</Folder>
163
+ <Folder>/var/myapp</Folder>
164
+ </Folders>
165
+ You can have several +Folders+ elements, if desired. The defaults for all +Folder+
166
+ child elements may be set as attributes of the parent +Folders+ element. In this example,
167
+ all the folders will have permissions <code>rwxr-x---</code>, and ownership of <code>root:wheel</code>.
168
+ Note that the folder <code>/var/mysql</code> has a different owner and group. Any Folder can
169
+ override the default Mode, Owner, and Group.
170
+
171
+ === +Files+
172
+ Finally we can specify how to move the files into place:
173
+ <Files Owner="root" Group="wheel" Mode="0644" Source="conf">
174
+ <File>/etc/my.cnf</File>
175
+ <File>/etc/myapp.conf</File>
176
+ </Files>
177
+ <Files Owner="root" Group="wheel" Mode="0750" Source="sbin">
178
+ <File>/usr/local/sbin/up!</File>
179
+ <File>/usr/local/sbin/down!</File>
180
+ <File>/usr/local/sbin/push!</File>
181
+ </Files>
182
+
183
+ In this example, we have two sets of files. The first set is expected to be found under the +conf+
184
+ folder. Looking at the first file, we see the destination path +/etc/my.cnf+.
185
+ The source file should have the same filename +my.cnf+ and be located in the +conf+ folder.
186
+ This results in Promotion executing a command such as:
187
+
188
+ cp -f /var/staging/myapp/conf/my.cnf /etc/my.cnf
189
+
190
+ This allows a flatter, more convenient project folder structure, since the deployment descriptor maps
191
+ the files into their proper operating system locations.
192
+
193
+ As for Folders, the Files element can define the default Owner, Group and Mode for all File children.
194
+
195
+ === +Allfiles+
196
+ A convenient shorthand for copying all the files in a folder to another folder is the
197
+ +Allfiles+ element. In this example, we will copy everything from the conf folder to
198
+ the destination folder specified.
199
+ <Allfiles Group="bin" Mode="0644" Owner="root" Source="conf">/var/axonsec/conf</Allfiles>
200
+
201
+ === +Daemon+
202
+ To enable an application to startup automatically, a +Daemon+ element is needed. The name of the
203
+ startup script is expected to be <code>/etc/rc.d/myapp</code>.
204
+ <Daemon Flags="" Priority="10" User="" />
205
+
206
+ The +Flags+ attribute contains the command line options provided to the executable by
207
+ <code>/etc/rc.conf.local</code>.
208
+
209
+ The lower the +Priority+ value, the earlier that script is run (high values start later).
210
+
211
+ The +User+ is the user running the process, typically an unprivileged user named <code>_myapp</code>.
212
+ Leave blank to run the startup script as root (eg. as when dropping privileges).
213
+
214
+ === +Crontab+
215
+ Cron jobs are often needed for an application to run smoothly. Instead of creating them by hand,
216
+ you can specify each job as part of the deployment descriptor and let promotion set up the crontab
217
+ automatically.
218
+ <Crontab>
219
+ <Schedule User="root" Hour="2" Minute="7"
220
+ Comment="Backup the entire database at 2:07am each morning">
221
+ <Command><![CDATA[/usr/local/sbin/myappbak]]></Command>
222
+ </Schedule>
223
+ </Crontab>
224
+ In this example, we specify a job to be added to root's crontab, to backup the database
225
+ at 2:07am each morning. The time specification is as defined in <code>crontab(5)</code>:
226
+ - Minute
227
+ - Hour
228
+ - DayOfMonth
229
+ - Month
230
+ - DayOfWeek
231
+ The +Command+ is best wrapped safely in a CDATA section in case of XML-unsafe characters
232
+ like $.
233
+
234
+ The +Comment+ will be inserted into the final crontab file just before the job specification.
235
+
236
+ === +Database+
237
+ If the application has a database, we need to specify the path to the DBMS client command
238
+ line tool.
239
+ <Database>/usr/local/bin/mysql</Database>
240
+
241
+ If using SQLite3, a +Database+ attribute is also needed to specify the file to operate on:
242
+ <Database database="/var/myapp/data/orders.db">/usr/bin/sqlite3</Database>
243
+
244
+ == Database schema migration
245
+ Four components are required to automate database schema migration:
246
+ 1. Database migration scripts, stored in the +evolve+ and +devolve+ sub-folders
247
+ of the application's staging folder. These are normal migration scripts you might apply
248
+ manually.
249
+ 2. A <code><Database></code> element in the deployment descriptor, containing the path to
250
+ the database client command line tool. In the case of SQLite3, it also needs a <code>database</code>
251
+ attribute containing the path of the database file to operate on.
252
+ 3. Privileges to allow the user to apply the migration scripts to the database, or else
253
+ it will of course fail.
254
+ 4. Credentials for the user stored privately in <code>~/.my.cnf</code> or <code>~/.pgpass</code>
255
+ (unless using SQLite3). This allows the scripts to be executed in batch mode, without
256
+ prompting for a password.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.7
data/bin/devolve ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/local/bin/ruby -I/usr/local/
2
+ # This script devolves the database
3
+
4
+ require 'getoptlong'
5
+ #______________________
6
+ # Set usage
7
+ #
8
+ usage=<<-EOT
9
+ devolve - devolve the database schema using migration scripts
10
+ usage: sudo /usr/local/bin/devolve [--config configFilepath] appname target
11
+ where appname is the name of a folder in /var/staging containing a file deploy.xml
12
+ target integer version to devolve to
13
+ EOT
14
+ #______________________
15
+ # parse options
16
+ #
17
+ opts = GetoptLong.new(
18
+ [ "--config", "-c", GetoptLong::REQUIRED_ARGUMENT ],
19
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ]
20
+ )
21
+ config = nil
22
+ configFilename = nil
23
+ opts.each do |opt, arg|
24
+ case opt
25
+ when "--config"
26
+ configFilename = arg
27
+ when "--help"
28
+ puts usage
29
+ exit 1
30
+ end
31
+ end
32
+ #______________________
33
+ # check arguments
34
+ #
35
+ if ARGV.length != 2
36
+ puts(usage)
37
+ exit 1
38
+ end
39
+ appname = ARGV[0]
40
+ targetVersion = ARGV[1].to_i()
41
+ unless targetVersion >= 1000
42
+ puts("target version must be 1000 or greater")
43
+ puts(usage)
44
+ exit 1
45
+ end
46
+ configFilename ||= "promotion/config.rb"
47
+ require(configFilename)
48
+ unless File.directory?(File.expand_path(appname, Folders::Staging))
49
+ puts("The application #{appname} was not found in the staging area #{Folders::Staging}")
50
+ puts("Aborting")
51
+ exit 1
52
+ end
53
+ #______________________
54
+ # start application
55
+ #
56
+ $stdout.flush()
57
+ require 'promotion/application'
58
+ app = Promotion::Application.new(appname)
59
+ app.devolve(targetVersion)
data/bin/evolve ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/local/bin/ruby -I/usr/local/
2
+ # This script evolves the database
3
+
4
+ require 'getoptlong'
5
+ #______________________
6
+ # Set usage
7
+ #
8
+ usage=<<-EOT
9
+ evolve - evolve the database schema using migration scripts
10
+ usage: sudo /usr/local/bin/evolve [--config configFilepath] appname [target]
11
+ where appname is the name of a folder in /var/staging containing a file deploy.xml
12
+ target is an integer version to evolve to (default is to evolve as far as possible)
13
+ EOT
14
+ #______________________
15
+ # parse options
16
+ #
17
+ opts = GetoptLong.new(
18
+ [ "--config", "-c", GetoptLong::REQUIRED_ARGUMENT ],
19
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ]
20
+ )
21
+ config = nil
22
+ configFilename = nil
23
+ opts.each do |opt, arg|
24
+ case opt
25
+ when "--config"
26
+ configFilename = arg
27
+ when "--help"
28
+ puts usage
29
+ exit 1
30
+ end
31
+ end
32
+ #______________________
33
+ # check arguments
34
+ #
35
+ if ARGV.length < 1
36
+ puts(usage)
37
+ exit 1
38
+ end
39
+ appname = ARGV[0]
40
+ if ARGV.length > 1
41
+ targetVersion = ARGV[1].to_i()
42
+ unless targetVersion > 1000
43
+ puts(usage)
44
+ exit 1
45
+ end
46
+ end
47
+ configFilename ||= "promotion/config.rb"
48
+ require(configFilename)
49
+ unless File.directory?(File.expand_path(appname, Folders::Staging))
50
+ puts("The application #{appname} was not found in the staging area #{Folders::Staging}")
51
+ puts("Aborting")
52
+ exit 1
53
+ end
54
+ #______________________
55
+ # start application
56
+ #
57
+ $stdout.flush()
58
+ require 'promotion/application'
59
+ app = Promotion::Application.new(appname)
60
+ app.evolve(targetVersion)
data/bin/promote ADDED
@@ -0,0 +1,67 @@
1
+ #!/usr/local/bin/ruby -I/usr/local/
2
+ # This script starts the promotion application
3
+
4
+ #______________________
5
+ if Process.euid != 0
6
+ puts("This script must be run as root")
7
+ exit 1
8
+ end
9
+
10
+ require 'getoptlong'
11
+ #______________________
12
+ # Set usage
13
+ #
14
+ usage=<<-EOT
15
+ promotion - installer and configuration manager
16
+ usage: sudo /usr/local/bin/promotion [--config configFilepath] appname
17
+ where appname is the name of a folder under /var/staging
18
+ EOT
19
+ #______________________
20
+ # parse options
21
+ #
22
+ opts = GetoptLong.new(
23
+ [ "--config", "-c", GetoptLong::REQUIRED_ARGUMENT ],
24
+ [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
25
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ]
26
+ )
27
+ config = nil
28
+ configFilename = nil
29
+ opts.each do |opt, arg|
30
+ case opt
31
+ when "--config"
32
+ configFilename = arg
33
+ when "--help"
34
+ puts usage
35
+ exit 1
36
+ end
37
+ end
38
+ #______________________
39
+ # check arguments
40
+ #
41
+ if ARGV.length() == 0
42
+ puts("No application to install. We will just regenerate the environment files.")
43
+ elsif ARGV.length() > 1
44
+ puts("Please specify just one application at a time.")
45
+ puts(usage)
46
+ exit 1
47
+ end
48
+ appname = ARGV[0]
49
+ unless File.directory?(File.expand_path(appname, "/var/staging"))
50
+ puts("The application #{appname} was not found in the staging area /var/staging")
51
+ puts("Aborting")
52
+ exit 1
53
+ end
54
+ #______________________
55
+ # Configure
56
+ #
57
+ configFilename ||= "promotion/config.rb"
58
+ require(configFilename)
59
+ #______________________
60
+ # start application
61
+ #
62
+ print("Promoting #{appname}...")
63
+ $stdout.flush()
64
+ require 'promotion/application'
65
+ app = Promotion::Application.new(appname)
66
+ app.promote()
67
+ puts("OK.")
data/deploy.xml ADDED
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <Specification Name="promotion" Title="Promotion Manager"
3
+ xmlns="http://finalstep.com.au/promotion/v100"
4
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5
+ xsi:schemaLocation="http://finalstep.com.au/schema/promotion.v100.xsd ../promotion/promotion.xsd">
6
+ <Description>
7
+ The promotion manager ensures that the environment for an application
8
+ is set up correctly, including folder and file permissions and ownership,
9
+ startup scripts, sudoers privileges and environment variables.
10
+ </Description>
11
+ <Folders>
12
+ <Folder Mode="0770">/var/staging</Folder>
13
+ <Folder Mode="0770">/var/staging/promotion</Folder>
14
+ <Folder Clear="true">/usr/local/promotion</Folder>
15
+ <Folder>/usr/local/promotion/erb</Folder>
16
+ </Folders>
17
+ <Files Source="bin" Mode="0755">
18
+ <File>/usr/local/sbin/promote</File>
19
+ <File>/usr/local/sbin/evolve</File>
20
+ <File>/usr/local/sbin/devolve</File>
21
+ </Files>
22
+ <Files Source="lib/promotion">
23
+ <File>/usr/local/promotion/application.rb</File>
24
+ <File>/usr/local/promotion/config.rb</File>
25
+ <File>/usr/local/promotion/enforcer.rb</File>
26
+ <File>/usr/local/promotion/generator.rb</File>
27
+ <File>/usr/local/promotion/evolver.rb</File>
28
+ </Files>
29
+ <Files Source="lib/promotion/erb">
30
+ <File>/usr/local/promotion/erb/profile.erb</File>
31
+ <File>/usr/local/promotion/erb/rc.conf.local.erb</File>
32
+ <File>/usr/local/promotion/erb/sudoers.erb</File>
33
+ <File>/usr/local/promotion/erb/crontab.erb</File>
34
+ </Files>
35
+ </Specification>
@@ -0,0 +1,19 @@
1
+ #!/usr/local/bin/ruby
2
+ # Working directory is the ext/promotion/ folder
3
+
4
+ # generate Makefile to install binaries
5
+ source = "../../bin"
6
+ target = "/usr/local"
7
+ makeContents=<<-EOT
8
+ # Makefile for Promotion
9
+ .PHONY : all
10
+ all :
11
+ .PHONY : install
12
+ install :
13
+ install -m 0750 -o root -g wheel #{source}/promote #{target}/sbin
14
+ install -m 0750 -o root -g wheel #{source}/evolve #{target}/sbin
15
+ install -m 0750 -o root -g wheel #{source}/devolve #{target}/sbin
16
+ EOT
17
+ makefile = File.new("Makefile", "w")
18
+ makefile.puts(makeContents)
19
+ makefile.close()
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'promotion/enforcer'
3
+ require 'promotion/generator'
4
+ require 'promotion/evolver'
5
+ require 'log4r'
6
+ include Log4r
7
+
8
+ module Promotion # :nodoc:
9
+
10
+ # The Promotion::Application coordinates the activity of the components:
11
+ # - Enforcer
12
+ # - Generator
13
+ # - Evolver
14
+ class Application
15
+
16
+ # Creates a new Promotion::Application instance for a specific app to be promoted.
17
+ # A global +$log+ logger is also created.
18
+ def initialize(appname)
19
+ @appname = appname
20
+ $log = Logger.new(@appname)
21
+ FileOutputter[@appname] = FileOutputter.new(@appname, :filename => Files::Log)
22
+ FileOutputter[@appname].formatter = PatternFormatter.new(:pattern => "%d %m")
23
+ $log.outputters = FileOutputter[@appname]
24
+ end
25
+
26
+ # Promotes an application into production.
27
+ def promote()
28
+ enforcer = Promotion::Enforcer.new(@appname)
29
+ generator = Promotion::Generator.new()
30
+ enforcer.start()
31
+ generator.start()
32
+ $log.info("Application #{@appname} successfully promoted.")
33
+ end
34
+
35
+ # Evolves the database to a target version, or as far as possible, by
36
+ # executing database migration scripts in the +evolve+ folder
37
+ def evolve(target=nil)
38
+ evolver = Promotion::Evolver.new(@appname, true, target)
39
+ evolver.start()
40
+ end
41
+
42
+ # Devolve a database back to an earlier version
43
+ def devolve(target=nil)
44
+ evolver = Promotion::Evolver.new(@appname, false, target)
45
+ evolver.start()
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,55 @@
1
+ # application configuration for promotion
2
+ # PRODUCTION
3
+
4
+ # A section of the configuration file that contains folder paths
5
+ module Folders
6
+ # The folder where applications are staged (eg. from Subversion)
7
+ # ready for deployment
8
+ Staging = "/var/staging"
9
+ # The folder containing the ERB templates
10
+ Templates = "/usr/local/promotion/erb"
11
+ # The system crontab folder
12
+ Crontabs = "/var/cron/tabs"
13
+ end
14
+
15
+ # A section of the configuration file that contains file paths
16
+ module Files
17
+ # The standard name of the deployment descriptor for all apps
18
+ Spec = "deploy.xml"
19
+ # The log file for promotion
20
+ Log = "/var/staging/Promotion.log"
21
+ # system path to the shared profile
22
+ Profile = "/etc/profile"
23
+ # system path to the sudoers file
24
+ Sudoers = "/etc/sudoers"
25
+ # system path to rc.conf.local
26
+ Rc_conf = "/etc/rc.conf.local"
27
+ # path to useradd executable
28
+ Useradd = "/usr/sbin/useradd"
29
+ # path to groupadd executable
30
+ Groupadd = "/usr/sbin/groupadd"
31
+ # path to visudo executable
32
+ Visudo = "/usr/sbin/visudo"
33
+ # path to crontab executable
34
+ Crontab = "/usr/bin/crontab"
35
+ # path to zip executable
36
+ Zip = "/usr/local/bin/zip -q "
37
+ end
38
+
39
+ # A section of the configuration file that contains ERB template filenames
40
+ module Templates
41
+ # filename for Profile template
42
+ Profile = "profile.erb"
43
+ # filename for Rc_conf template
44
+ Rc_conf = "rc.conf.local.erb"
45
+ # filename for Sudoers template
46
+ Sudoers = "sudoers.erb"
47
+ # filename for Crontab template
48
+ Crontab = "crontab.erb"
49
+ end
50
+
51
+ raise "staging area not found" unless File.directory?(Folders::Staging)
52
+ raise "template folder not found" unless File.directory?(Folders::Templates)
53
+ Templates.constants { |template|
54
+ raise "template #{template} not found" unless File.exist?(File.expand_path(Templates.const_get(template), Folders::Templates))
55
+ }