Module: CfYAML

Defined in:
lib/libcfruby/cfyaml.rb

Overview

A set of methods for loading and automatically executing highly-compressed cfrubyscript in yaml form

Defined Under Namespace

Classes: CfYamlError, StructureError

Class Method Summary collapse

Class Method Details

.configure_file(structure) ⇒ Object

takes a structure loaded from yaml (a Hash or Array of Hash’s) and executes it as a series of cfrubyscript commands. Each Hash must contain a filename key which dictates the file (or files) to be worked on. The following keys are then executed in order. any subkey that takes options may define them in an option hash, and then redefine the main variables in a subkey using the same name as in: set:

options:
  whitespace: true
set: ['variable', 'value' ]

Options will cascade to the next item in the sequence.

mkdir

If filename does not exist, create it as a directory

touch

If filename does not exist, create it as an empty file

template

If filename is singular and doesn’t exist, this file will be copied into its’ place

user

Executes a chown command with this user and group (or currently running group if group is not given)

group

Executes a chmod command with this group and user (or currently running user if user is not given)

mode

Executes a chmod with this mode

comment

Comments the line or lines given

uncomment

Uncomments the line or lines given

set

Executes set passing name, value pairs as given

replace

Executes the replace command passing regex, str pairs as given

must_not_contain

Executes file_must_not_contain

must_contain

Executes file_must_contain



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/libcfruby/cfyaml.rb', line 238

def CfYAML.configure_file(structure)
	changemade = false
	
	# If it is an Array iterate.  If a String, parse as yaml.  If IO, read and parse
	if(structure.kind_of?(Array))
		structure.each() { |s|
			configure_file(s)
		}
		return()
	end

	filename = structure['filename']
	
	options = parse_options(structure['options'])

	if(structure.has_key?('template'))
		if(Dir.glob(filename).length == 0)
			Cfruby::FileOps.copy(structure['template'], filename)
		end
	end

	if(structure.has_key?('mkdir'))
		if(Dir.glob(filename).length == 0)
			if(Cfruby::FileOps.mkdir(filename, :makeparent => true))
				changemade = true
			end
		end
	elsif(structure.has_key?('touch'))
		if(Dir.glob(filename).length == 0)
			if(Cfruby::FileOps.touch(filename))
				changemade = true
			end
		end
	end
	
	if(structure.has_key?('user') or structure.has_key?('group'))
		if(structure.has_key?('user'))
			user = structure['user']
		else
			user = Process.euid()
		end
		if(structure.has_key?('group'))
			group = structure['group']
		else
			group = Process.gid()
		end
		if(Cfruby::FileOps.chown(filename, user, group, options))
			changemade = true
		end
	end
	
	if(structure.has_key?('mode'))
		if(Cfruby::FileOps.chmod(filename, structure['mode'], options))
			changemade = true
		end
	end
	
	if(structure.has_key?('comment'))
		lines = Array.new()
		if(structure['comment'].kind_of?(Hash))
			options = parse_options(structure['comment']['options'])
			lines = structure['comment']['comment']
		else
			lines = structure['comment']
		end
		if(Cfruby::FileEdit.comment(filename, lines, options))
			changemade = true
		end
	end

	if(structure.has_key?('uncomment'))
		lines = Array.new()
		if(structure['comment'].kind_of?(Hash))
			options = parse_options(structure['uncomment']['options'])
			lines = structure['uncomment']['uncomment']
		else
			lines = structure['uncomment']
		end
		if(Cfruby::FileEdit.uncomment(filename, lines, options))
			changemade = true
		end
	end

	if(structure.has_key?('set'))
		variables = Array.new()
		if(structure['set'].kind_of?(Hash))
			options = parse_options(structure['set']['options'])
			variables = structure['set']['set']
		else
			variables = structure['set']
		end
		variables.each() { |s|
			if(Cfruby::FileEdit.set(filename, s[0], s[1], options))
				changemade = true
			end
		}
	end
	
	if(structure.has_key?('replace'))
		replacements = nil
		if(structure['replace'].kind_of?(Hash))
			options = parse_options(structure['replace']['options'])
			replacements = structure['replace']['replace']
		else
			replacements = structure['replace']
		end
		replacements.each() { |r|
			if(Cfruby::FileEdit.replace(filename, r[0], r[1], options))
				changemade = true
			end
		}
	end

	if(structure.has_key?('must_not_contain'))
		lines = nil
		if(structure['must_not_contain'].kind_of?(Hash))
			options = parse_options(structure['must_not_contain']['options'])
			lines = structure['must_not_contain']['must_not_contain']
		else
			lines = structure['must_not_contain']
		end
		if(Cfruby::FileEdit.file_must_not_contain(filename, lines, options))
			changemade = true
		end
	end

	if(structure.has_key?('must_contain'))
		lines = nil
		if(structure['must_contain'].kind_of?(Hash))
			options = parse_options(structure['must_contain']['options'])
			lines = structure['must_contain']['must_contain']
		else
			lines = structure['must_contain']
		end
		if(Cfruby::FileEdit.file_must_contain(filename, lines, options))
			changemade = true
		end
	end
	
	return(changemade)
end

.delete(hash) ⇒ Object

Deletes the file or Array of files in hash. May take an optional options: key that may contain any option suitable for passing to FileOps.delete



160
161
162
163
# File 'lib/libcfruby/cfyaml.rb', line 160

def CfYAML.delete(hash)
	options = parse_options(structure['options'])
	return(Cfruby::FileOps.delete(hash['delete'], options))
end

.disable(hash) ⇒ Object

Disables the file or Array of files in hash. May take an optional options: key that may contain any option suitable for passing to FileOps.disable



168
169
170
171
# File 'lib/libcfruby/cfyaml.rb', line 168

def CfYAML.disable(hash)
	options = parse_options(structure['options'])
	return(Cfruby::FileOps.disable(hash['disable'], options))
end

.evaluate(hash) ⇒ Object

Evaluates the code or Array of code in hash



147
148
149
150
151
152
153
154
155
# File 'lib/libcfruby/cfyaml.rb', line 147

def CfYAML.evaluate(hash)
	commands = hash['eval']
	if(!commands.kind_of?(Array))
		commands = Array.[](commands)
	end
	commands.each() { |command|
		eval(command)
	}
end

.execute(hash) ⇒ Object

Executes the command or Array of commands in hash

user

Run the command(s) as user

useshell

Run the commands in the default shell (not compatible with user)

arguments

If useshell is given, then the arguments should be given as an Array in arguments



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/libcfruby/cfyaml.rb', line 178

def CfYAML.execute(hash)
	commands = hash['execute']
	if(!commands.kind_of?(Array))
		commands = Array.[](commands)
	end
	user = hash['user']
	commands.each() { |command|
		if(hash['useshell'])
		  arguments = hash['arguments'] | Array.new()
			Cfruby::Exec.shellexec(command, arguments)
		else
			Cfruby::Exec.exec(command, user)
		end
	}
end

.install_packages(hash) ⇒ Object

Installs the package or Array of packages in hash



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/libcfruby/cfyaml.rb', line 196

def CfYAML.install_packages(hash)
	changemade = false
	
	os = Cfruby::OS::OSFactory.new.get_os()
	pkg_manager = os.get_package_manager()
	packages = hash['install']
	if(!packages.kind_of?(Array))
		packages = Array.[](packages)
	end
	packages.each() { |package|
		if(pkg_manager.install(package))
			changemade = true
		end
	}
	
	return(changemade)
end

.load(filename, changed = false) ⇒ Object

Executes a YAML file by loading it and processing each array entry in it in turn recursively, depth first. changed is only used internally.



50
51
52
53
54
55
56
57
58
59
# File 'lib/libcfruby/cfyaml.rb', line 50

def CfYAML.load(filename, changed=false)
	fp = filename
	if(!filename.kind_of?(IO))
		fp = File.open(filename, File::RDONLY)
	end
	
	cfyamlcode = YAML.load(fp)

	return(process(cfyamlcode, changed))
end

.process(object, changed = false) ⇒ Object

Executes an object loaded from a YAML file. changed is only used internally. Returns true if a known change was made. Specifically, it does the following (in order):

1. Check for a +condition+ key.  If it exists, eval it as a ruby statement and stop processing if the
   result of the eval() is false or nil.
2. Check for a +change_made+ key (which must be set to true or false).  This value is checked against
  whether or not a change was actually made by the *immediately previous* section.  If they do not match, then
  this section will stop processing.
3. The section is searched for a primary key, which will then determine how the rest of the section is
  processed.  These are:
   * load
   * actions
   * eval
   * filename
   * install
   * delete
   * disable
   * execute


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/libcfruby/cfyaml.rb', line 79

def CfYAML.process(object, changed=false)
	if(object.kind_of?(Hash))
		begin
			# first check for condition
			if(object.has_key?('conditions'))
				conditions = object['conditions']
				if(!conditions.kind_of?(Array))
					conditions = Array.[](conditions)
				end
		
				conditions.each() { |c|
					if(!eval(c.to_s))
						return(false)
					end
				}
			end
			
			if(object.has_key?('change_made'))
				if(object['change_made'] != changed)
					return(false)
				end
			end

			# load has to be handled here because it should not change
			# the changed flag on its own.
			if(object.has_key?('load'))
				if(object['load'].kind_of?(Array))
					object['load'].each() { |s|
						changed = load(s, changed)
					}
				else
					changed = load(object['load'], changed)
				end
			end

			changed = false
	
			if(object.has_key?('actions'))
				changed = process(object['actions'], changed)
			elsif(object.has_key?('eval'))
				evaluate(object)
			elsif(object.has_key?('filename'))
				changed = configure_file(object)
			elsif(object.has_key?('install'))
				changed = install_packages(object)
			elsif(object.has_key?('delete'))
				changed = delete(object)
			elsif(object.has_key?('disable'))
				changed = disable(object)
			elsif(object.has_key?('execute'))
				execute(object)
			else
				raise(CfYamlError, "Unable to find primary key (actions, eval, filename, install, or execute)")
			end
		rescue
			raise(CfYamlError, "Error processing section:\n #{object.to_yaml}\n\n#{$!.to_s}\n\n")
		end
	elsif(object.kind_of?(Array))
		object.each() { |o|
			changed = process(o, changed)
		}
	end
	
	return(changed)
end