Merge branch 'augeas' into 0.24.x

This commit is contained in:
James Turnbull 2008-10-29 15:46:16 +11:00
Родитель 56f3be66a4 751dc7b09f
Коммит a83b3ffb3f
3 изменённых файлов: 341 добавлений и 0 удалений

Просмотреть файл

@ -22,3 +22,6 @@ Puppet.features.add(:mongrel, :libs => %w{rubygems mongrel puppet/network/http_s
# We have lcs diff
Puppet.features.add :diff, :libs => %w{diff/lcs diff/lcs/hunk}
# We have augeas
Puppet.features.add(:augeas, :libs => ["augeas"])

Просмотреть файл

@ -0,0 +1,188 @@
#--
# Copyright (C) 2008 Red Hat Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Author: Bryan Kearney <bkearney@redhat.com>
require 'augeas' if Puppet.features.augeas?
Puppet::Type.type(:augeas).provide(:augeas) do
#class Puppet::Provider::Augeas < Puppet::Provider
include Puppet::Util
confine :true => Puppet.features.augeas?
has_features :parse_commands, :need_to_run?,:execute_changes
# Extracts an 2 dimensional array of commands which are in the
# form of command path value.
# The input can be
# - A string with one command
# - A string with many commands per line
# - An array of strings.
def parse_commands(data)
commands = Array.new()
if data.is_a?(String)
data.each_line do |line|
cmd_array = Array.new()
tokens = line.split(" ")
cmd = tokens.shift()
file = tokens.shift()
other = tokens.join(" ")
cmd_array << cmd if !cmd.nil?
cmd_array << file if !file.nil?
cmd_array << other if other != ""
commands << cmd_array
end
elsif data.is_a?(Array)
data.each do |datum|
commands.concat(parse_commands(datum))
end
end
return commands
end
def open_augeas
flags = 0
(flags = 1 << 2 ) if self.resource[:type_check] == :true
root = self.resource[:root]
load_path = self.resource[:load_path]
debug("Opening augeas with root #{root}, lens path #{load_path}, flags #{flags}")
Augeas.open(root, load_path,flags)
end
# Used by the need_to_run? method to process get filters. Returns
# true if there is a match, false if otherwise
# Assumes a syntax of get /files/path [COMPARATOR] value
def process_get(cmd_array)
return_value = false
#validate and tear apart the command
fail ("Invalid command: #{cmd_array.join(" ")}") if cmd_array.length < 4
cmd = cmd_array.shift()
path = cmd_array.shift()
comparator = cmd_array.shift()
arg = cmd_array.join(" ")
#check the value in augeas
aug = open_augeas()
result = aug.get(path) || ''
unless result.nil?
case comparator
when "!=":
return_value = true if !(result == arg)
when "=~":
regex = Regexp.new(arg)
loc = result=~ regex
return_value = true if ! loc.nil?
else
return_value = true if (result.send(comparator, arg))
end
end
return_value
end
# Used by the need_to_run? method to process match filters. Returns
# true if there is a match, false if otherwise
def process_match(cmd_array)
return_value = false
#validate and tear apart the command
fail("Invalid command: #{cmd_array.join(" ")}") if cmd_array.length < 4
cmd = cmd_array.shift()
path = cmd_array.shift()
verb = cmd_array.shift()
#Get the values from augeas
aug = open_augeas()
result = aug.match(path) || ''
# Now do the work
if (!result.nil?)
case verb
when "size":
fail("Invalid command: #{cmd_array.join(" ")}") if cmd_array.length != 2
comparator = cmd_array.shift()
arg = cmd_array.shift().to_i
return_value = true if (result.size.send(comparator, arg))
when "include":
arg = cmd_array.join(" ")
return_value = true if result.include?(arg)
when "==":
begin
arg = cmd_array.join(" ")
new_array = eval arg
return_value = true if result == new_array
rescue
fail("Invalid array in command: #{cmd_array.join(" ")}")
end
end
end
return_value
end
# Determines if augeas acutally needs to run.
def need_to_run?
return_value = true
filter = resource[:onlyif]
unless (filter == "")
cmd_array = filter.split
command = cmd_array[0];
cmd_array[1]= File.join(resource[:context], cmd_array[1])
begin
data = nil
case command
when "get" then return_value = process_get(cmd_array)
when "match" then return_value = process_match(cmd_array)
end
rescue Exception => e
fail("Error sending command '#{command}' with params #{cmd_array[1..-1].inspect}/#{e.message}")
end
end
return_value
end
# Actually execute the augeas changes.
def execute_changes
aug = open_augeas
commands = self.resource[:changes]
commands.each do |cmd_array|
fail("invalid command #{cmd_array.join[" "]}") if cmd_array.length < 2
command = cmd_array[0]
cmd_array.shift()
cmd_array[0]=File.join(resource[:context], cmd_array[0])
debug("sending command '#{command}' with params #{cmd_array.inspect}")
begin
case command
when "set": aug.set(cmd_array[0], cmd_array[1])
when "rm", "remove": aug.rm(cmd_array[0])
when "clear": aug.clear(cmd_array[0])
when "insert", "ins": aug.insert(cmd_array[0])
else fail("Command '#{command}' is not supported")
end
rescue Exception => e
fail("Error sending command '#{command}' with params #{cmd_array.inspect}/#{e.message}")
end
end
success = aug.save()
if (success != true)
fail("Save failed with return code #{success}")
end
return :executed
end
end

150
lib/puppet/type/augeas.rb Normal file
Просмотреть файл

@ -0,0 +1,150 @@
#--
# Copyright (C) 2008 Red Hat Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Publicretu
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Author: Bryan Kearney <bkearney@redhat.com>
Puppet::Type.newtype(:augeas) do
include Puppet::Util
feature :parse_commands, "Parse the command string"
feature :need_to_run?, "If the command should run"
feature :execute_changes, "Actually make the changes"
@doc = "Apply the changes (single or array of changes) to the filesystem
via the augeas tool.
Requires:
- augeas to be installed (http://www.augeas.net)
- ruby-augeas bindings
Sample usage with a string:
augeas{\"test1\" :
context => \"/files/etc/sysconfig/firstboot\",
changes => \"set RUN_FIRSTBOOT YES\"
onlyif => \"match other_value size > 0\"
}
Sample usage with an array and custom lenses:
augeas{\"jboss_conf\":
context => \"/files\",
changes => [
\"set /etc/jbossas/jbossas.conf/JBOSS_IP $ipaddress\",
\"set /etc/jbossas/jbossas.conf/JAVA_HOME /usr\"
],
load_path => \"$/usr/share/jbossas/lenses\",
}
"
newparam (:name) do
desc "The name of this task. Used for uniqueness"
isnamevar
end
newparam (:context) do
desc "Optional context path. This value is pre-pended to the paths of all changes"
defaultto ""
end
newparam (:onlyif) do
desc "Optional augeas command and comparisons to control the execution of this type.
Supported onlyif syntax:
get [AUGEAS_PATH] [COMPARATOR] [STRING]
match [MATCH_PATH] size [COMPARATOR] [INT]
match [MATCH_PATH] include [STRING]
match [MATCH_PATH] == [AN_ARRAY]
where
AUGEAS_PATH is a valid path scoped by the context
MATCH_PATH is a valid match synatx scoped by the context
COMPARATOR is in the set [> >= != == <= <]
STRING is a string
INT is a number
AN_ARRAY is in the form ['a string', 'another'] "
defaultto ""
end
newparam(:changes) do
desc "The changes which should be applied to the filesystem. This
can be either a string which contains a command or an array of commands.
Commands supported are:
set [PATH] [VALUE] Sets the value VALUE at loction PATH
rm [PATH] Removes the node at location PATH
remove [PATH] Synonym for rm
clear [PATH] Keeps the node at PATH, but removes the value.
ins [PATH] Inserts an empty node at PATH.
insert [PATH] Synonym for ins
If the parameter 'context' is set that that value is prepended to PATH"
munge do |value|
provider.parse_commands(value)
end
end
newparam(:root) do
desc "A file system path; all files loaded by Augeas are loaded underneath ROOT"
defaultto "/"
end
newparam(:load_path) do
desc "Optional colon separated list of directories; these directories are searched for schema definitions"
defaultto ""
end
newparam(:type_check) do
desc "Set to true if augeas should perform typechecking. Optional, defaults to false"
newvalues(:true, :false)
defaultto :false
end
# This is the acutal meat of the code. It forces
# augeas to be run and fails or not based on the augeas return
# code.
newproperty(:returns) do |property|
include Puppet::Util
desc "The expected return code from the augeas command. Should not be set"
defaultto 0
# Make output a bit prettier
def change_to_s(currentvalue, newvalue)
return "executed successfully"
end
# if the onlyif resource is provided, then the value is parsed.
# a return value of 0 will stop exection becuase it matches the
# default value.
def retrieve
if @resource.provider.need_to_run?()
:need_to_run
else
0
end
end
# Actually execute the command.
def sync
@resource.provider.execute_changes()
end
end
end