Merge branch '0.24.x'
Conflicts: lib/puppet/util/settings.rb spec/integration/defaults.rb spec/unit/node/catalog.rb spec/unit/type/interface.rb spec/unit/type/ssh_authorized_key.rb
This commit is contained in:
Коммит
b0febd263c
|
@ -8,6 +8,14 @@
|
|||
set file paths to 'false' to disable the CRL.
|
||||
|
||||
0.24.?
|
||||
Fixed #1232 - the rundir no longer specifies a user/group,
|
||||
and there are now client- and server-specific yaml directories.
|
||||
|
||||
Fixed 1240 - puppet will function more like puppetd if graphing
|
||||
or reporting are enabled.
|
||||
|
||||
Fixed #1231 - Exceptions during initialization should now be clearer.
|
||||
|
||||
Fixed #1006 - puppetrun --class works again. I added the class
|
||||
membership testing to the Ldap node terminus, and added tests,
|
||||
so it shouldn't break again.
|
||||
|
|
|
@ -163,8 +163,9 @@ end
|
|||
# Now parse the config
|
||||
Puppet.parse_config
|
||||
|
||||
Puppet.genconfig
|
||||
Puppet.genmanifest
|
||||
if Puppet.settings.print_configs?
|
||||
exit(Puppet.settings.print_configs ? 0 : 1)
|
||||
end
|
||||
|
||||
begin
|
||||
if options[:local] or options[:bucket]
|
||||
|
|
|
@ -212,6 +212,8 @@ begin
|
|||
# Translate it to a RAL catalog
|
||||
catalog = catalog.to_ral
|
||||
|
||||
catalog.host_config = true if Puppet[:graph] or Puppet[:report]
|
||||
|
||||
catalog.finalize
|
||||
|
||||
# And apply it
|
||||
|
|
|
@ -138,8 +138,9 @@ server = nil
|
|||
end
|
||||
end
|
||||
|
||||
Puppet.genconfig
|
||||
Puppet.genmanifest
|
||||
if Puppet.settings.print_configs?
|
||||
exit(Puppet.settings.print_configs ? 0 : 1)
|
||||
end
|
||||
|
||||
unless ARGV.length > 0
|
||||
$stderr.puts "You must pass a script to parse"
|
||||
|
|
|
@ -63,8 +63,6 @@ module Puppet
|
|||
:rundir => {
|
||||
:default => rundir,
|
||||
:mode => 01777,
|
||||
:owner => "$user",
|
||||
:group => "$group",
|
||||
:desc => "Where Puppet PID files are kept."
|
||||
},
|
||||
:genconfig => [false,
|
||||
|
@ -382,7 +380,9 @@ module Puppet
|
|||
# To make sure this directory is created before we try to use it on the server, we need
|
||||
# it to be in the server section (#1138).
|
||||
:yamldir => {:default => "$vardir/yaml", :owner => "$user", :group => "$user", :mode => "750",
|
||||
:desc => "The directory in which YAML data is stored, usually in a subdirectory."}
|
||||
:desc => "The directory in which YAML data is stored, usually in a subdirectory."},
|
||||
:clientyamldir => {:default => "$vardir/client_yaml", :mode => "750",
|
||||
:desc => "The directory in which client-side YAML data is stored."}
|
||||
)
|
||||
|
||||
self.setdefaults(:puppetd,
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
require 'puppet'
|
||||
require 'puppet/util/methodhelper'
|
||||
require 'puppet/util/errors'
|
||||
|
||||
module Puppet
|
||||
# events are transient packets of information; they result in one or more (or none)
|
||||
# subscriptions getting triggered, and then they get cleared
|
||||
# eventually, these will be passed on to some central event system
|
||||
class Event
|
||||
include Puppet
|
||||
include Puppet::Util::MethodHelper
|
||||
include Puppet::Util::Errors
|
||||
|
||||
attr_accessor :event, :source, :transaction
|
||||
|
||||
@@events = []
|
||||
|
||||
def initialize(args)
|
||||
set_options symbolize_options(args)
|
||||
requiredopts(:event, :source)
|
||||
end
|
||||
|
||||
def to_s
|
||||
@source.to_s + " -> " + self.event.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -14,7 +14,7 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
|
|||
end
|
||||
|
||||
# Separate this out so it's relatively atomic. It's tempting to call
|
||||
# process() instead of entry2hash() here, but it ends up being
|
||||
# process() instead of name2hash() here, but it ends up being
|
||||
# difficult to test because all exceptions get caught by ldapsearch.
|
||||
# LAK:NOTE Unfortunately, the ldap support is too stupid to throw anything
|
||||
# but LDAP::ResultError, even on bad connections, so we are rough handed
|
||||
|
@ -35,21 +35,14 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap
|
|||
|
||||
node = nil
|
||||
names.each do |name|
|
||||
break if node = process(name)
|
||||
end
|
||||
return nil unless node
|
||||
next unless info = name2hash(name)
|
||||
|
||||
node.name = request.key
|
||||
break if node = info2node(request.key, info)
|
||||
end
|
||||
|
||||
return node
|
||||
end
|
||||
|
||||
def process(name)
|
||||
return nil unless info = name2hash(name)
|
||||
|
||||
info2node(name, info)
|
||||
end
|
||||
|
||||
# Find more than one node. LAK:NOTE This is a bit of a clumsy API, because the 'search'
|
||||
# method currently *requires* a key. It seems appropriate in some cases but not others,
|
||||
# and I don't really know how to get rid of it as a requirement but allow it when desired.
|
||||
|
|
|
@ -36,7 +36,8 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
|
|||
|
||||
# Return the path to a given node's file.
|
||||
def path(name)
|
||||
File.join(Puppet[:yamldir], self.class.indirection_name.to_s, name.to_s + ".yaml")
|
||||
base = (Puppet[:name] == "puppetmasterd") ? Puppet[:yamldir] : Puppet[:clientyamldir]
|
||||
File.join(base, self.class.indirection_name.to_s, name.to_s + ".yaml")
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -139,7 +139,7 @@ class Puppet::Type
|
|||
end
|
||||
|
||||
if ensureparam and ! ensureparam.insync?(currentvalues[ensureparam])
|
||||
changes << Puppet::PropertyChange.new(ensureparam, currentvalues[ensureparam])
|
||||
changes << Puppet::Transaction::Change.new(ensureparam, currentvalues[ensureparam])
|
||||
# Else, if the 'ensure' property is correctly absent, then do
|
||||
# nothing
|
||||
elsif ensureparam and currentvalues[ensureparam] == :absent
|
||||
|
@ -149,7 +149,7 @@ class Puppet::Type
|
|||
currentvalues[property] ||= :absent
|
||||
! property.insync?(currentvalues[property])
|
||||
}.collect { |property|
|
||||
Puppet::PropertyChange.new(property, currentvalues[property])
|
||||
Puppet::Transaction::Change.new(property, currentvalues[property])
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -75,6 +75,8 @@ class Puppet::Node
|
|||
def fact_merge
|
||||
if facts = Puppet::Node::Facts.find(name)
|
||||
merge(facts.values)
|
||||
else
|
||||
Puppet.warning "Could not find facts for %s; you probably have a discrepancy between the node and fact names" % name
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ class Puppet::Node::Catalog < Puppet::PGraph
|
|||
# isn't sufficient.
|
||||
return if newref == resource.ref
|
||||
if existing = @resource_table[newref]
|
||||
return if existing == resource
|
||||
raise(ArgumentError, "Cannot alias %s to %s; resource %s already exists" % [resource.ref, name, newref])
|
||||
end
|
||||
@resource_table[newref] = resource
|
||||
|
|
|
@ -58,7 +58,7 @@ class Puppet::PGraph < Puppet::SimpleGraph
|
|||
# to, which is the same thing as saying all edges directly below
|
||||
# This vertex in the graph.
|
||||
adjacent(source, :direction => :out, :type => :edges).find_all do |edge|
|
||||
edge.match?(event.event)
|
||||
edge.match?(event.name)
|
||||
end
|
||||
end.compact.flatten
|
||||
end
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# blocks for actually doing work on the system.
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/propertychange'
|
||||
require 'puppet/parameter'
|
||||
|
||||
module Puppet
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
# the class responsible for actually doing any work
|
||||
|
||||
# enables no-op and logging/rollback
|
||||
|
||||
module Puppet
|
||||
# Handle all of the work around performing an actual change,
|
||||
# including calling 'sync' on the properties and producing events.
|
||||
class PropertyChange
|
||||
attr_accessor :is, :should, :type, :path, :property, :transaction, :changed, :proxy
|
||||
|
||||
# The log file generated when this object was changed.
|
||||
attr_reader :report
|
||||
|
||||
# Switch the goals of the property, thus running the change in reverse.
|
||||
def backward
|
||||
@property.should = @is
|
||||
@is = @property.retrieve
|
||||
|
||||
unless defined? @transaction
|
||||
raise Puppet::Error,
|
||||
"PropertyChange '%s' tried to be executed outside of transaction" %
|
||||
self
|
||||
end
|
||||
unless @property.insync?(@is)
|
||||
@property.info "Backing %s" % self
|
||||
return self.go
|
||||
else
|
||||
@property.debug "rollback is already in sync: %s vs. %s" %
|
||||
[@is, @property.should.inspect]
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def changed?
|
||||
self.changed
|
||||
end
|
||||
|
||||
# Create our event object.
|
||||
def event(name)
|
||||
# default to a simple event type
|
||||
unless name.is_a?(Symbol)
|
||||
@property.warning("Property '%s' returned invalid event '%s'; resetting to default" %
|
||||
[@property.class, name])
|
||||
|
||||
event = @property.resource.class.name.id2name + "_changed"
|
||||
end
|
||||
|
||||
Puppet::Event.new(
|
||||
:event => name,
|
||||
:transaction => @transaction,
|
||||
:source => self.source
|
||||
)
|
||||
end
|
||||
|
||||
def initialize(property, currentvalue)
|
||||
unless property.is_a?(Puppet::Property)
|
||||
raise Puppet::DevError, "Got a %s instead of a property" %
|
||||
property.class
|
||||
end
|
||||
@property = property
|
||||
@path = [property.path,"change"].flatten
|
||||
@is = currentvalue
|
||||
|
||||
@should = property.should
|
||||
|
||||
@changed = false
|
||||
end
|
||||
|
||||
# Perform the actual change. This method can go either forward or
|
||||
# backward, and produces an event.
|
||||
def go
|
||||
if skip?
|
||||
if self.noop
|
||||
return [event(:noop)]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
# The transaction catches any exceptions here.
|
||||
events = @property.sync
|
||||
if events.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
if events.is_a?(Array)
|
||||
if events.empty?
|
||||
return nil
|
||||
end
|
||||
else
|
||||
events = [events]
|
||||
end
|
||||
|
||||
return events.collect { |name|
|
||||
@report = @property.log(@property.change_to_s(@is, @should))
|
||||
event(name)
|
||||
}
|
||||
end
|
||||
|
||||
def forward
|
||||
#@property.debug "moving change forward"
|
||||
|
||||
unless defined? @transaction
|
||||
raise Puppet::Error,
|
||||
"PropertyChange '%s' tried to be executed outside of transaction" %
|
||||
self
|
||||
end
|
||||
|
||||
return self.go
|
||||
end
|
||||
|
||||
def noop
|
||||
return @property.noop
|
||||
end
|
||||
|
||||
def skip?
|
||||
if @property.insync?(@is)
|
||||
@property.info "Already in sync"
|
||||
return true
|
||||
end
|
||||
|
||||
if @property.noop
|
||||
@property.log "is %s, should be %s (noop)" %
|
||||
[property.is_to_s(@is), property.should_to_s(@should)]
|
||||
#@property.debug "%s is noop" % @property
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def source
|
||||
self.proxy || @property.resource
|
||||
end
|
||||
|
||||
def to_s
|
||||
return "change %s.%s(%s)" %
|
||||
[@transaction.object_id, self.object_id, @property.change_to_s(@is, @should)]
|
||||
#return "change %s.%s" % [@transaction.object_id, self.object_id]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,250 +0,0 @@
|
|||
require 'puppet/provider/parsedfile'
|
||||
require 'erb'
|
||||
|
||||
Puppet::Type.type(:interface).provide(:redhat) do
|
||||
desc "Manage network interfaces on Red Hat operating systems. This provider
|
||||
parses and generates configuration files in ``/etc/sysconfig/network-scripts``."
|
||||
|
||||
INTERFACE_DIR = "/etc/sysconfig/network-scripts"
|
||||
confine :exists => INTERFACE_DIR
|
||||
defaultfor :operatingsystem => [:fedora, :centos, :redhat]
|
||||
|
||||
# Create the setter/gettor methods to match the model.
|
||||
mk_resource_methods
|
||||
|
||||
@templates = {}
|
||||
|
||||
# Register a template.
|
||||
def self.register_template(name, string)
|
||||
@templates[name] = ERB.new(string)
|
||||
end
|
||||
|
||||
# Retrieve a template by name.
|
||||
def self.template(name)
|
||||
@templates[name]
|
||||
end
|
||||
|
||||
register_template :alias, <<-ALIAS
|
||||
DEVICE=<%= self.device %>
|
||||
ONBOOT=<%= self.on_boot %>
|
||||
BOOTPROTO=none
|
||||
IPADDR=<%= self.name %>
|
||||
NETMASK=<%= self.netmask %>
|
||||
BROADCAST=
|
||||
ALIAS
|
||||
|
||||
|
||||
register_template :normal, <<-LOOPBACKDUMMY
|
||||
DEVICE=<%= self.device %>
|
||||
ONBOOT=<%= self.on_boot %>
|
||||
BOOTPROTO=static
|
||||
IPADDR=<%= self.name %>
|
||||
NETMASK=<%= self.netmask %>
|
||||
BROADCAST=
|
||||
LOOPBACKDUMMY
|
||||
|
||||
# maximum number of dummy interfaces
|
||||
@max_dummies = 10
|
||||
|
||||
# maximum number of aliases per interface
|
||||
@max_aliases_per_iface = 10
|
||||
|
||||
@@dummies = []
|
||||
@@aliases = Hash.new { |hash, key| hash[key] = [] }
|
||||
|
||||
# calculate which dummy interfaces are currently already in
|
||||
# use prior to needing to call self.next_dummy later on.
|
||||
def self.instances
|
||||
# parse all of the config files at once
|
||||
Dir.glob("%s/ifcfg-*" % INTERFACE_DIR).collect do |file|
|
||||
record = parse(file)
|
||||
|
||||
# store the existing dummy interfaces
|
||||
@@dummies << record[:ifnum] if (record[:interface_type] == :dummy and ! @@dummies.include?(record[:ifnum]))
|
||||
|
||||
@@aliases[record[:interface]] << record[:ifnum] if record[:interface_type] == :alias
|
||||
|
||||
new(record)
|
||||
end
|
||||
end
|
||||
|
||||
# return the next avaliable dummy interface number, in the case where
|
||||
# ifnum is not manually specified
|
||||
def self.next_dummy
|
||||
@max_dummies.times do |i|
|
||||
unless @@dummies.include?(i.to_s)
|
||||
@@dummies << i.to_s
|
||||
return i.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# return the next available alias on a given interface, in the case
|
||||
# where ifnum if not manually specified
|
||||
def self.next_alias(interface)
|
||||
@max_aliases_per_iface.times do |i|
|
||||
unless @@aliases[interface].include?(i.to_s)
|
||||
@@aliases[interface] << i.to_s
|
||||
return i.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# base the ifnum, for dummy / loopback interface in linux
|
||||
# on the last octect of the IP address
|
||||
|
||||
# Parse the existing file.
|
||||
def self.parse(file)
|
||||
instance = new()
|
||||
return instance unless FileTest.exist?(file)
|
||||
|
||||
File.readlines(file).each do |line|
|
||||
if line =~ /^(\w+)=(.+)$/
|
||||
instance.send($1.downcase + "=", $2)
|
||||
end
|
||||
end
|
||||
|
||||
return instance
|
||||
end
|
||||
|
||||
# Prefetch our interface list, yo.
|
||||
def self.prefetch(resources)
|
||||
instances.each do |prov|
|
||||
if resource = resources[prov.name]
|
||||
resource.provider = prov
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
self.class.resource_type.validproperties.each do |property|
|
||||
if value = @resource.should(property)
|
||||
@property_hash[property] = value
|
||||
end
|
||||
end
|
||||
@property_hash[:name] = @resource.name
|
||||
|
||||
return (@resource.class.name.to_s + "_created").intern
|
||||
end
|
||||
|
||||
def destroy
|
||||
File.unlink(file_path)
|
||||
end
|
||||
|
||||
def exists?
|
||||
FileTest.exist?(file_path)
|
||||
end
|
||||
|
||||
# generate the content for the interface file, so this is dependent
|
||||
# on whether we are adding an alias to a real interface, or a loopback
|
||||
# address (also dummy) on linux. For linux it's quite involved, and we
|
||||
# will use an ERB template
|
||||
def generate
|
||||
itype = self.interface_type == :alias ? :alias : :normal
|
||||
self.class.template(itype).result(binding)
|
||||
end
|
||||
|
||||
# Where should the file be written out?
|
||||
# This defaults to INTERFACE_DIR/ifcfg-<namevar>, but can have a
|
||||
# more symbolic name by setting interface_desc in the type.
|
||||
def file_path
|
||||
if resource and val = resource[:interface_desc]
|
||||
desc = val
|
||||
else
|
||||
desc = self.name
|
||||
end
|
||||
|
||||
self.fail("Could not get name for interface") unless desc
|
||||
|
||||
if self.interface_type == :alias
|
||||
return File.join(INTERFACE_DIR, "ifcfg-" + self.interface + ":" + desc)
|
||||
else
|
||||
return File.join(INTERFACE_DIR, "ifcfg-" + desc)
|
||||
end
|
||||
end
|
||||
|
||||
# Use the device value to figure out all kinds of nifty things.
|
||||
def device=(value)
|
||||
case value
|
||||
when /:/:
|
||||
@property_hash[:interface], @property_hash[:ifnum] = value.split(":")
|
||||
@property_hash[:interface_type] = :alias
|
||||
when /^dummy/:
|
||||
@property_hash[:interface_type] = :loopback
|
||||
@property_hash[:interface] = "dummy"
|
||||
|
||||
# take the number of the dummy interface, as this is used
|
||||
# when working out whether to call next_dummy when dynamically
|
||||
# creating these
|
||||
@property_hash[:ifnum] = value.sub("dummy",'')
|
||||
|
||||
@@dummies << @property_hash[:ifnum].to_s unless @@dummies.include?(@property_hash[:ifnum].to_s)
|
||||
else
|
||||
@property_hash[:interface_type] = :normal
|
||||
@property_hash[:interface] = value
|
||||
end
|
||||
end
|
||||
|
||||
# create the device name, so this based on the IP, and interface + type
|
||||
def device
|
||||
case @resource.should(:interface_type)
|
||||
when :loopback
|
||||
@property_hash[:ifnum] ||= self.class.next_dummy
|
||||
return "dummy" + @property_hash[:ifnum]
|
||||
when :alias
|
||||
@property_hash[:ifnum] ||= self.class.next_alias(@resource[:interface])
|
||||
return @resource[:interface] + ":" + @property_hash[:ifnum]
|
||||
end
|
||||
end
|
||||
|
||||
# Set the name to our ip address.
|
||||
def ipaddr=(value)
|
||||
@property_hash[:name] = value
|
||||
end
|
||||
|
||||
# whether the device is to be brought up on boot or not. converts
|
||||
# the true / false of the type, into yes / no values respectively
|
||||
# writing out the ifcfg-* files
|
||||
def on_boot
|
||||
case @property_hash[:onboot].to_s
|
||||
when "true"
|
||||
return "yes"
|
||||
when "false"
|
||||
return "no"
|
||||
else
|
||||
return "neither"
|
||||
end
|
||||
end
|
||||
|
||||
# Mark whether the interface should be started on boot.
|
||||
def on_boot=(value)
|
||||
# translate whether we come up on boot to true/false
|
||||
case value.downcase
|
||||
when "yes":
|
||||
@property_hash[:onboot] = :true
|
||||
else
|
||||
@property_hash[:onboot] = :false
|
||||
end
|
||||
end
|
||||
|
||||
# Write the new file out.
|
||||
def flush
|
||||
# Don't flush to disk if we're removing the config.
|
||||
return if self.ensure == :absent
|
||||
|
||||
@property_hash.each do |name, val|
|
||||
if val == :absent
|
||||
raise ArgumentError, "Propety %s must be provided" % val
|
||||
end
|
||||
end
|
||||
|
||||
File.open(file_path, "w") do |f|
|
||||
f.puts generate()
|
||||
end
|
||||
end
|
||||
|
||||
def prefetch
|
||||
@property_hash = self.class.parse(file_path)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
require 'puppet/provider/parsedfile'
|
||||
require 'erb'
|
||||
|
||||
Puppet::Type.type(:interface).provide(:sunos) do
|
||||
confine :kernel => "SunOS"
|
||||
|
||||
# Add accessor/getter methods for each property/parameter; these methods
|
||||
# modify @property_hash.
|
||||
mk_resource_methods
|
||||
|
||||
# Get a list of interface instances.
|
||||
def self.instances
|
||||
Dir.glob("/etc/hostname.*").collect do |file|
|
||||
device = File.basename(file).split(".").pop
|
||||
|
||||
instance = new(:interface => device)
|
||||
instance.parse
|
||||
instance
|
||||
end
|
||||
end
|
||||
|
||||
def self.match(hash)
|
||||
# see if we can match the has against an existing object
|
||||
if model.find { |obj| obj.value(:name) == hash[:name] }
|
||||
return obj
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Prefetch our interface list, yo.
|
||||
def self.prefetch(resources)
|
||||
instances.each do |prov|
|
||||
if resource = resources[prov.name]
|
||||
resource.provider = prov
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(*args)
|
||||
@property_hash = {}
|
||||
super
|
||||
end
|
||||
|
||||
def create
|
||||
self.class.resource_type.validproperties.each do |property|
|
||||
if value = resource.should(property)
|
||||
@property_hash[property] = value
|
||||
end
|
||||
end
|
||||
@property_hash[:name] = resource.name
|
||||
|
||||
return (@resource.class.name.to_s + "_created").intern
|
||||
end
|
||||
|
||||
def destroy
|
||||
File.unlink(file_path)
|
||||
@property_hash[:ensure] = :absent
|
||||
end
|
||||
|
||||
def exists?
|
||||
FileTest.exist?(file_path)
|
||||
end
|
||||
|
||||
# Where should the file be written out? Can be overridden by setting
|
||||
# :target in the model.
|
||||
def file_path
|
||||
self.fail("Could not determine interface") unless interface = @property_hash[:interface] || (resource and resource[:interface])
|
||||
return File.join("/etc", "hostname." + interface)
|
||||
end
|
||||
|
||||
def flush
|
||||
return if self.ensure == :absent
|
||||
File.open(file_path, "w") { |f| f.print generate() + "\n" }
|
||||
end
|
||||
|
||||
# Turn our record into a line.
|
||||
def generate
|
||||
ret = []
|
||||
if self.interface_type == :alias
|
||||
ret << "addif"
|
||||
end
|
||||
ret << self.name
|
||||
|
||||
if self.ifopts != :absent
|
||||
if @property_hash[:ifopts].is_a?(Array)
|
||||
ret << @property_hash[:ifopts].join(" ")
|
||||
else
|
||||
ret << @property_hash[:ifopts]
|
||||
end
|
||||
end
|
||||
|
||||
if self.onboot and ! [:absent, :false].include?(self.onboot)
|
||||
ret << "up"
|
||||
end
|
||||
|
||||
return ret.join(" ")
|
||||
end
|
||||
|
||||
# Parse our interface file.
|
||||
def parse
|
||||
(@property_hash = {:ensure => :absent} and return) unless FileTest.exist?(file_path)
|
||||
|
||||
values = File.read(file_path).chomp.split(/\s+/)
|
||||
|
||||
@property_hash[:ensure] = :present
|
||||
#@property_hash = {:ensure => :present}
|
||||
|
||||
# Are we the primary interface?
|
||||
if values[0] == "addif"
|
||||
@property_hash[:interface_type] = :alias
|
||||
values.shift
|
||||
else
|
||||
@property_hash[:interface_type] = :normal
|
||||
end
|
||||
|
||||
# Should the interface be up by default?
|
||||
if values[-1] == "up"
|
||||
@property_hash[:onboot] = :true
|
||||
values.pop
|
||||
else
|
||||
@property_hash[:onboot] = :false
|
||||
end
|
||||
|
||||
# Set the interface name.
|
||||
@property_hash[:name] = values.shift
|
||||
|
||||
# Handle any interface options
|
||||
unless values.empty?
|
||||
@property_hash[:ifopts] = values.join(" ")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -29,21 +29,5 @@ Puppet::Type.type(:ssh_authorized_key).provide(:parsed,
|
|||
record[:options] = record[:options].join(',')
|
||||
end
|
||||
}
|
||||
|
||||
def prefetch
|
||||
if not @resource.should(:target)
|
||||
#
|
||||
# Set default target when user is given
|
||||
if val = @resource.should(:user)
|
||||
target = File.expand_path("~%s/.ssh/authorized_keys" % val)
|
||||
Puppet::debug("Setting target to %s" % target)
|
||||
@resource[:target] = target
|
||||
else
|
||||
raise Puppet::Error, "Missing attribute 'user' or 'target'"
|
||||
end
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
# and performs them
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/propertychange'
|
||||
|
||||
module Puppet
|
||||
class Transaction
|
||||
require 'puppet/transaction/change'
|
||||
require 'puppet/transaction/event'
|
||||
|
||||
attr_accessor :component, :catalog, :ignoreschedules
|
||||
attr_accessor :sorted_resources, :configurator
|
||||
|
||||
|
@ -96,7 +98,7 @@ class Transaction
|
|||
# Create an edge with this resource as both the source and
|
||||
# target. The triggering method treats these specially for
|
||||
# logging.
|
||||
events = resourceevents.collect { |e| e.event }
|
||||
events = resourceevents.collect { |e| e.name }
|
||||
set_trigger(Puppet::Relationship.new(resource, resource, :callback => :refresh, :event => events))
|
||||
end
|
||||
end
|
||||
|
@ -109,7 +111,6 @@ class Transaction
|
|||
changes.collect { |change|
|
||||
@changes << change
|
||||
@count += 1
|
||||
change.transaction = self
|
||||
events = nil
|
||||
begin
|
||||
# use an array, so that changes can return more than one
|
||||
|
@ -278,7 +279,7 @@ class Transaction
|
|||
# of course, bad.
|
||||
edge = orig_edge.class.new(orig_edge.source, orig_edge.target)
|
||||
label = orig_edge.label.dup
|
||||
label[:event] = events.collect { |e| e.event }
|
||||
label[:event] = events.collect { |e| e.name }
|
||||
edge.label = label
|
||||
set_trigger(edge)
|
||||
end
|
||||
|
@ -680,11 +681,7 @@ class Transaction
|
|||
[callback, subs.length]
|
||||
|
||||
# And then add an event for it.
|
||||
return [Puppet::Event.new(
|
||||
:event => :noop,
|
||||
:transaction => self,
|
||||
:source => resource
|
||||
)]
|
||||
return [Puppet::Transaction::Event.new(:noop, resource)]
|
||||
end
|
||||
|
||||
if subs.length == 1 and subs[0].source == resource
|
||||
|
@ -712,11 +709,7 @@ class Transaction
|
|||
end
|
||||
|
||||
# And then add an event for it.
|
||||
trigged << Puppet::Event.new(
|
||||
:event => :triggered,
|
||||
:transaction => self,
|
||||
:source => resource
|
||||
)
|
||||
trigged << Puppet::Transaction::Event.new(:triggered, resource)
|
||||
|
||||
triggered(resource, callback)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
require 'puppet/transaction'
|
||||
require 'puppet/transaction/event'
|
||||
|
||||
# Handle all of the work around performing an actual change,
|
||||
# including calling 'sync' on the properties and producing events.
|
||||
class Puppet::Transaction::Change
|
||||
attr_accessor :is, :should, :path, :property, :changed, :proxy
|
||||
|
||||
# Switch the goals of the property, thus running the change in reverse.
|
||||
def backward
|
||||
@is, @should = @should, @is
|
||||
@property.should = @should
|
||||
|
||||
@property.info "Reversing %s" % self
|
||||
return self.go
|
||||
end
|
||||
|
||||
def changed?
|
||||
self.changed
|
||||
end
|
||||
|
||||
# Create our event object.
|
||||
def event(name)
|
||||
# default to a simple event type
|
||||
unless name.is_a?(Symbol)
|
||||
@property.warning("Property '%s' returned invalid event '%s'; resetting to default" %
|
||||
[@property.class, name])
|
||||
|
||||
name = @property.event(should)
|
||||
end
|
||||
|
||||
Puppet::Transaction::Event.new(name, self.resource)
|
||||
end
|
||||
|
||||
def initialize(property, currentvalue)
|
||||
@property = property
|
||||
@path = [property.path,"change"].flatten
|
||||
@is = currentvalue
|
||||
|
||||
@should = property.should
|
||||
|
||||
@changed = false
|
||||
end
|
||||
|
||||
# Perform the actual change. This method can go either forward or
|
||||
# backward, and produces an event.
|
||||
def go
|
||||
if self.noop?
|
||||
@property.log "is %s, should be %s (noop)" % [property.is_to_s(@is), property.should_to_s(@should)]
|
||||
return [event(:noop)]
|
||||
end
|
||||
|
||||
# The transaction catches any exceptions here.
|
||||
events = @property.sync
|
||||
if events.nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
if events.is_a?(Array)
|
||||
if events.empty?
|
||||
return nil
|
||||
end
|
||||
else
|
||||
events = [events]
|
||||
end
|
||||
|
||||
return events.collect { |name|
|
||||
@report = @property.log(@property.change_to_s(@is, @should))
|
||||
event(name)
|
||||
}
|
||||
end
|
||||
|
||||
def forward
|
||||
return self.go
|
||||
end
|
||||
|
||||
# Is our property noop? This is used for generating special events.
|
||||
def noop?
|
||||
return @property.noop
|
||||
end
|
||||
|
||||
# The resource that generated this change. This is used for handling events,
|
||||
# and the proxy resource is used for generated resources, since we can't
|
||||
# send an event to a resource we don't have a direct relationship. If we
|
||||
# have a proxy resource, then the events will be considered to be from
|
||||
# that resource, rather than us, so the graph resolution will still work.
|
||||
def resource
|
||||
self.proxy || @property.resource
|
||||
end
|
||||
|
||||
def to_s
|
||||
return "change %s" % @property.change_to_s(@is, @should)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
require 'puppet'
|
||||
require 'puppet/util/methodhelper'
|
||||
require 'puppet/util/errors'
|
||||
|
||||
# events are transient packets of information; they result in one or more (or none)
|
||||
# subscriptions getting triggered, and then they get cleared
|
||||
# eventually, these will be passed on to some central event system
|
||||
class Puppet::Transaction::Event
|
||||
include Puppet::Util::MethodHelper
|
||||
include Puppet::Util::Errors
|
||||
|
||||
attr_reader :name, :source
|
||||
|
||||
def initialize(name, source)
|
||||
@name, @source = name, source
|
||||
end
|
||||
|
||||
def to_s
|
||||
source.to_s + " -> " + name.to_s
|
||||
end
|
||||
end
|
|
@ -1,6 +1,5 @@
|
|||
require 'puppet'
|
||||
require 'puppet/util/log'
|
||||
require 'puppet/event'
|
||||
require 'puppet/util/metric'
|
||||
require 'puppet/property'
|
||||
require 'puppet/parameter'
|
||||
|
@ -415,7 +414,6 @@ class Type
|
|||
end # Puppet::Type
|
||||
end
|
||||
|
||||
require 'puppet/propertychange'
|
||||
require 'puppet/provider'
|
||||
|
||||
# Always load these types.
|
||||
|
|
|
@ -138,11 +138,6 @@ module Puppet
|
|||
# We have to treat :present specially, because it works with any
|
||||
# type of file.
|
||||
def insync?(currentvalue)
|
||||
if property = @resource.property(:source) and ! property.described?
|
||||
warning "No specified sources exist"
|
||||
return true
|
||||
end
|
||||
|
||||
if self.should == :present
|
||||
if currentvalue.nil? or currentvalue == :absent
|
||||
return false
|
||||
|
|
|
@ -135,18 +135,8 @@ module Puppet
|
|||
return args
|
||||
end
|
||||
|
||||
# Have we successfully described the remote source?
|
||||
def described?
|
||||
! @stats.nil? and ! @stats[:type].nil? #and @is != :notdescribed
|
||||
end
|
||||
|
||||
# Use the info we get from describe() to check if we're in sync.
|
||||
def insync?(currentvalue)
|
||||
unless described?
|
||||
warning "No specified sources exist"
|
||||
return true
|
||||
end
|
||||
|
||||
if currentvalue == :nocopy
|
||||
return true
|
||||
end
|
||||
|
@ -180,7 +170,11 @@ module Puppet
|
|||
def pinparams
|
||||
[:mode, :type, :owner, :group]
|
||||
end
|
||||
|
||||
|
||||
def found?
|
||||
! (@stats.nil? or @stats[:type].nil?)
|
||||
end
|
||||
|
||||
# This basically calls describe() on our file, and then sets all
|
||||
# of the local states appropriately. If the remote file is a normal
|
||||
# file then we set it to copy; if it's a directory, then we just mark
|
||||
|
@ -202,8 +196,8 @@ module Puppet
|
|||
}
|
||||
end
|
||||
|
||||
if @stats.nil? or @stats[:type].nil?
|
||||
return nil # :notdescribed
|
||||
if !found?
|
||||
raise Puppet::Error, "No specified source was found from" + @should.inject("") { |s, source| s + " #{source},"}.gsub(/,$/,"")
|
||||
end
|
||||
|
||||
case @stats[:type]
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
Puppet::Type.newtype(:interface) do
|
||||
require 'erb'
|
||||
|
||||
@doc = "Create configuration for IP address aliases and loopback addresses."
|
||||
|
||||
newparam(:name, :namevar => true) do
|
||||
desc "The ipaddress to add to alias or loopback/dummy interface"
|
||||
end
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:interface) do
|
||||
desc "The interface the IP should be added to"
|
||||
end
|
||||
|
||||
newproperty(:interface_type) do
|
||||
desc "The interface type, loopback (also dummy) or alias"
|
||||
|
||||
newvalue(:loopback)
|
||||
newvalue(:alias)
|
||||
newvalue(:normal)
|
||||
|
||||
# Make dummy and loopback equivalent
|
||||
aliasvalue(:dummy, :loopback)
|
||||
|
||||
defaultto :normal
|
||||
end
|
||||
|
||||
newparam(:interface_desc) do
|
||||
desc "On Linux, the description / symbolic name you wish to refer to the
|
||||
interface by. When absent, Redhat Linux defaults to uses the namevar
|
||||
which will be either the IP address, or hostname."
|
||||
end
|
||||
|
||||
newproperty(:onboot) do
|
||||
desc "Whether the interface should be configured to come up on boot"
|
||||
newvalue(:true)
|
||||
newvalue(:false)
|
||||
end
|
||||
|
||||
newproperty(:ifnum) do
|
||||
desc "If not automatically configuring the dummy interface or
|
||||
and alias. This is use to force a given number to be used"
|
||||
end
|
||||
|
||||
newproperty(:netmask) do
|
||||
desc "The netmask for the interface."
|
||||
end
|
||||
|
||||
newproperty(:ifopts) do
|
||||
desc "Interface options."
|
||||
end
|
||||
|
||||
newparam(:target) do
|
||||
include Puppet::Util::Warnings
|
||||
desc "The path to the file this resource creates."
|
||||
|
||||
munge { |value| warnonce "Interface targets are deprecated and no longer have any function" }
|
||||
end
|
||||
end
|
|
@ -5,14 +5,14 @@ module Puppet
|
|||
ensurable
|
||||
|
||||
newparam(:name) do
|
||||
desc "The ssh key comment."
|
||||
desc "The SSH key comment."
|
||||
|
||||
isnamevar
|
||||
end
|
||||
|
||||
newproperty(:type) do
|
||||
desc "The encryption type used. Probably ssh-dss or ssh-rsa for
|
||||
ssh version 2. Not used for ssh version 1."
|
||||
desc "The encryption type used. Usually ssh-dss or ssh-rsa for
|
||||
SSH version 2. Not used for SSH version 1."
|
||||
|
||||
newvalue("ssh-dss")
|
||||
newvalue("ssh-rsa")
|
||||
|
@ -26,19 +26,55 @@ module Puppet
|
|||
end
|
||||
|
||||
newproperty(:user) do
|
||||
desc "The user account in which the ssh key should be installed."
|
||||
desc "The user account in which the SSH key should be installed."
|
||||
|
||||
def value=(value)
|
||||
@resource[:target] = File.expand_path("~%s/.ssh/authorized_keys" % value)
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:target) do
|
||||
desc "The file in which to store the ssh key."
|
||||
desc "The file in which to store the SSH key."
|
||||
end
|
||||
|
||||
newproperty(:options, :array_matching => :all) do
|
||||
desc "Key options, see sshd(8) for possible values. Multiple values
|
||||
should be specified as an array."
|
||||
desc "Key options, see sshd(8) for possible values. Multiple values
|
||||
should be specified as an array."
|
||||
|
||||
defaultto do :absent end
|
||||
end
|
||||
|
||||
def generate
|
||||
atype = Puppet::Type.type(:file)
|
||||
target = self.should(:target)
|
||||
dir = File.dirname(target)
|
||||
user = should(:user) ? should(:user) : "root"
|
||||
|
||||
rels = []
|
||||
|
||||
unless catalog.resource(:file, dir)
|
||||
rels << atype.create(:name => dir, :ensure => :directory, :mode => 0700, :owner => user)
|
||||
end
|
||||
|
||||
unless catalog.resource(:file, target)
|
||||
rels << atype.create(:name => target, :ensure => :present, :mode => 0600, :owner => user)
|
||||
end
|
||||
|
||||
rels
|
||||
end
|
||||
|
||||
autorequire(:user) do
|
||||
if should(:user)
|
||||
should(:user)
|
||||
end
|
||||
end
|
||||
|
||||
validate do
|
||||
unless should(:target)
|
||||
raise Puppet::Error, "Attribute 'user' or 'target' is mandatory"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# Description of yum repositories
|
||||
|
||||
require 'puppet/propertychange'
|
||||
require 'puppet/util/inifile'
|
||||
|
||||
module Puppet
|
||||
|
|
|
@ -63,7 +63,6 @@ class Puppet::Util::Ldap::Connection
|
|||
@connection.set_option(LDAP::LDAP_OPT_REFERRALS, LDAP::LDAP_OPT_ON)
|
||||
@connection.simple_bind(user, password)
|
||||
rescue => detail
|
||||
puts detail.class
|
||||
raise Puppet::Error, "Could not connect to LDAP: %s" % detail
|
||||
end
|
||||
end
|
||||
|
|
|
@ -644,13 +644,10 @@ Generated on #{Time.now}.
|
|||
begin
|
||||
catalog.host_config = false
|
||||
catalog.apply do |transaction|
|
||||
if failures = transaction.any_failed?
|
||||
# LAK:NOTE We should do something like this for some cases,
|
||||
# since it can otherwise be hard to know what failed.
|
||||
#transaction.report.logs.find_all { |log| log.level == :err }.each do |log|
|
||||
# puts log.message
|
||||
#end
|
||||
raise "Could not configure myself; got %s failure(s)" % failures
|
||||
if transaction.any_failed?
|
||||
report = transaction.report
|
||||
failures = report.logs.find_all { |log| log.level == :err }
|
||||
raise "Got %s failure(s) while initializing: %s" % [failures.length, failures.collect { |l| l.to_s }.join("; ")]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,4 +27,24 @@ describe "Puppet defaults" do
|
|||
Puppet.settings[:cacrl] = 'false'
|
||||
end
|
||||
end
|
||||
|
||||
it "should have a clientyamldir setting" do
|
||||
Puppet.settings[:clientyamldir].should_not be_nil
|
||||
end
|
||||
|
||||
it "should have different values for the yamldir and clientyamldir" do
|
||||
Puppet.settings[:yamldir].should_not == Puppet.settings[:clientyamldir]
|
||||
end
|
||||
|
||||
# See #1232
|
||||
it "should not specify a user or group for the clientyamldir" do
|
||||
Puppet.settings.element(:clientyamldir).owner.should be_nil
|
||||
Puppet.settings.element(:clientyamldir).group.should be_nil
|
||||
end
|
||||
|
||||
# See #1232
|
||||
it "should not specify a user or group for the rundir" do
|
||||
Puppet.settings.element(:rundir).owner.should be_nil
|
||||
Puppet.settings.element(:rundir).group.should be_nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -136,6 +136,14 @@ describe Puppet::Node::Ldap do
|
|||
@searcher.stubs(:name2hash).returns @result
|
||||
end
|
||||
|
||||
it "should create the node with the correct name, even if it was found by a different name" do
|
||||
@searcher.expects(:name2hash).with("mynode.domain.com").returns nil
|
||||
@searcher.expects(:name2hash).with("mynode").returns @result
|
||||
|
||||
Puppet::Node.expects(:new).with("mynode.domain.com").returns @node
|
||||
@searcher.find(@request)
|
||||
end
|
||||
|
||||
it "should add any classes from ldap" do
|
||||
@result[:classes] = %w[a b c d]
|
||||
@node.expects(:classes=).with(%w{a b c d})
|
||||
|
@ -161,6 +169,19 @@ describe Puppet::Node::Ldap do
|
|||
@searcher.find(@request)
|
||||
end
|
||||
|
||||
it "should merge the node's facts after the parameters from ldap are assigned" do
|
||||
# Make sure we've got data to start with, so the parameters are actually set.
|
||||
@result[:parameters] = {}
|
||||
@result[:parameters]["one"] = "yay"
|
||||
|
||||
# A hackish way to enforce order.
|
||||
set = false
|
||||
@node.expects(:parameters=).with { |*args| set = true }
|
||||
@node.expects(:fact_merge).with { |*args| raise "Facts were merged before parameters were set" unless set; true }
|
||||
|
||||
@searcher.find(@request)
|
||||
end
|
||||
|
||||
describe "and a parent node is specified" do
|
||||
before do
|
||||
@entry = {:classes => [], :parameters => {}}
|
||||
|
@ -304,13 +325,22 @@ describe Puppet::Node::Ldap do
|
|||
@searcher.search @request
|
||||
end
|
||||
|
||||
it "should return a node for each processed entry" do
|
||||
@searcher.expects(:ldapsearch).yields("one")
|
||||
@searcher.expects(:entry2hash).with("one").returns(:name => "foo")
|
||||
it "should return a node for each processed entry with the name from the entry" do
|
||||
@searcher.expects(:ldapsearch).yields("whatever")
|
||||
@searcher.expects(:entry2hash).with("whatever").returns(:name => "foo")
|
||||
result = @searcher.search(@request)
|
||||
result[0].should be_instance_of(Puppet::Node)
|
||||
result[0].name.should == "foo"
|
||||
end
|
||||
|
||||
it "should merge each node's facts" do
|
||||
node = mock 'node'
|
||||
Puppet::Node.expects(:new).with("foo").returns node
|
||||
node.expects(:fact_merge)
|
||||
@searcher.stubs(:ldapsearch).yields("one")
|
||||
@searcher.stubs(:entry2hash).with("one").returns(:name => "foo")
|
||||
@searcher.search(@request)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -20,12 +20,25 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do
|
|||
@subject.name = :me
|
||||
|
||||
@dir = "/what/ever"
|
||||
Puppet.settings.stubs(:value).with(:yamldir).returns(@dir)
|
||||
Puppet.settings.stubs(:value).returns("fakesettingdata")
|
||||
Puppet.settings.stubs(:value).with(:clientyamldir).returns(@dir)
|
||||
|
||||
@request = stub 'request', :key => :me, :instance => @subject
|
||||
end
|
||||
|
||||
describe Puppet::Indirector::Yaml, " when choosing file location" do
|
||||
it "should use the yamldir if the process name is 'puppetmasterd'" do
|
||||
Puppet.settings.expects(:value).with(:name).returns "puppetmasterd"
|
||||
Puppet.settings.expects(:value).with(:yamldir).returns "/main/yaml/dir"
|
||||
@store.path(:me).should =~ %r{^/main/yaml/dir}
|
||||
end
|
||||
|
||||
it "should use the client yamldir if the process name is not 'puppetmasterd'" do
|
||||
Puppet.settings.expects(:value).with(:name).returns "cient"
|
||||
Puppet.settings.expects(:value).with(:clientyamldir).returns "/client/yaml/dir"
|
||||
@store.path(:me).should =~ %r{^/client/yaml/dir}
|
||||
end
|
||||
|
||||
it "should store all files in a single file root set in the Puppet defaults" do
|
||||
@store.path(:me).should =~ %r{^#{@dir}}
|
||||
end
|
||||
|
|
|
@ -492,7 +492,12 @@ describe Puppet::Node::Catalog, " when functioning as a resource container" do
|
|||
@catalog.resource("me", "other").should equal(@one)
|
||||
end
|
||||
|
||||
it "should fail to add an alias if the aliased name already exists as a resource" do
|
||||
it "should ignore conflicting aliases that point to the aliased resource" do
|
||||
@catalog.alias(@one, "other")
|
||||
lambda { @catalog.alias(@one, "other") }.should_not raise_error
|
||||
end
|
||||
|
||||
it "should fail to add an alias if the aliased name already exists" do
|
||||
@catalog.add_resource @one
|
||||
proc { @catalog.alias @two, "one" }.should raise_error(ArgumentError)
|
||||
end
|
||||
|
|
|
@ -47,8 +47,8 @@ end
|
|||
describe Puppet::PGraph, " when matching edges" do
|
||||
before do
|
||||
@graph = Puppet::PGraph.new
|
||||
@event = Puppet::Event.new(:source => "a", :event => :yay)
|
||||
@none = Puppet::Event.new(:source => "a", :event => :NONE)
|
||||
@event = Puppet::Transaction::Event.new(:yay, "a")
|
||||
@none = Puppet::Transaction::Event.new(:NONE, "a")
|
||||
|
||||
@edges = {}
|
||||
@edges["a/b"] = Puppet::Relationship.new("a", "b", {:event => :yay, :callback => :refresh})
|
||||
|
|
|
@ -1,268 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# Created by Luke Kanies on 2007-11-20.
|
||||
# Copyright (c) 2006. All rights reserved.
|
||||
|
||||
require File.dirname(__FILE__) + '/../../../spec_helper'
|
||||
|
||||
provider_class = Puppet::Type.type(:interface).provider(:redhat)
|
||||
|
||||
describe provider_class do
|
||||
it "should not be functional on systems without a network-scripts directory" do
|
||||
FileTest.expects(:exist?).with("/etc/sysconfig/network-scripts").returns(false)
|
||||
provider_class.should_not be_suitable
|
||||
end
|
||||
|
||||
it "should be functional on systems with a network-scripts directory" do
|
||||
FileTest.expects(:exist?).with("/etc/sysconfig/network-scripts").returns(true)
|
||||
provider_class.should be_suitable
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when determining the file path" do
|
||||
it "should always contain '/etc/sysconfig/network-scripts/ifcfg-'" do
|
||||
provider = provider_class.new(:name => "192.168.0.1")
|
||||
provider.file_path.should =~ %r{^/etc/sysconfig/network-scripts/ifcfg-}
|
||||
end
|
||||
|
||||
it "should include the interface name and the description when the interface is an alias" do
|
||||
provider = provider_class.new(:name => "192.168.0.1", :interface => "eth0")
|
||||
provider.interface_type = :alias
|
||||
resource = stub 'resource'
|
||||
resource.stubs(:[]).with(:interface_desc).returns("blah")
|
||||
provider.resource = resource
|
||||
provider.file_path.should == "/etc/sysconfig/network-scripts/ifcfg-eth0:blah"
|
||||
end
|
||||
|
||||
it "should just include the description when the interface is not an alias" do
|
||||
provider = provider_class.new(:name => "192.168.0.1")
|
||||
provider.interface_type = :normal
|
||||
resource = stub 'resource'
|
||||
resource.stubs(:[]).with(:interface_desc).returns("eth0")
|
||||
provider.resource = resource
|
||||
provider.file_path.should == "/etc/sysconfig/network-scripts/ifcfg-eth0"
|
||||
end
|
||||
|
||||
it "should use the interface description if one is available" do
|
||||
provider = provider_class.new(:name => "192.168.0.1")
|
||||
provider.interface_type = :normal
|
||||
resource = stub 'resource'
|
||||
resource.stubs(:[]).with(:interface_desc).returns("eth0")
|
||||
provider.resource = resource
|
||||
provider.file_path.should == "/etc/sysconfig/network-scripts/ifcfg-eth0"
|
||||
end
|
||||
|
||||
it "should use the name if no interface description is available" do
|
||||
provider = provider_class.new(:name => "192.168.0.1")
|
||||
provider.interface_type = :normal
|
||||
provider.file_path.should == "/etc/sysconfig/network-scripts/ifcfg-192.168.0.1"
|
||||
end
|
||||
|
||||
it "should fail if no name or interface description can be found" do
|
||||
provider = provider_class.new()
|
||||
proc { provider.file_path }.should raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when returning instances" do
|
||||
it "should consider each file in the network-scripts directory an interface instance" do
|
||||
Dir.expects(:glob).with("/etc/sysconfig/network-scripts/ifcfg-*").returns(%w{one two})
|
||||
one = {:name => "one"}
|
||||
two = {:name => "two"}
|
||||
Puppet::Type::Interface::ProviderRedhat.expects(:parse).with("one").returns(one)
|
||||
Puppet::Type::Interface::ProviderRedhat.expects(:parse).with("two").returns(two)
|
||||
Puppet::Type::Interface::ProviderRedhat.expects(:new).with(one).returns(:one)
|
||||
Puppet::Type::Interface::ProviderRedhat.expects(:new).with(two).returns(:two)
|
||||
Puppet::Type::Interface::ProviderRedhat.instances.should == [:one, :two]
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when parsing" do
|
||||
it "should return an unmodified provider if the file does not exist" do
|
||||
FileTest.expects(:exist?).with("/my/file").returns(false)
|
||||
provider = mock 'provider'
|
||||
Puppet::Type::Interface::ProviderRedhat.expects(:new).returns(provider)
|
||||
Puppet::Type::Interface::ProviderRedhat.parse("/my/file").should equal(provider)
|
||||
end
|
||||
|
||||
it "should set each attribute in the file on the provider" do
|
||||
FileTest.expects(:exist?).with("/my/file").returns(true)
|
||||
File.expects(:readlines).with("/my/file").returns(%w{one=two three=four})
|
||||
provider = mock 'provider'
|
||||
Puppet::Type::Interface::ProviderRedhat.expects(:new).returns(provider)
|
||||
provider.expects(:one=).with('two')
|
||||
provider.expects(:three=).with('four')
|
||||
Puppet::Type::Interface::ProviderRedhat.parse("/my/file").should equal(provider)
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when setting the device to a value containing ':'" do
|
||||
before do
|
||||
@provider = Puppet::Type::Interface::ProviderRedhat.new
|
||||
@provider.device = "one:two"
|
||||
end
|
||||
it "should set the interface type to :alias" do
|
||||
@provider.interface_type.should == :alias
|
||||
end
|
||||
it "should set the interface to the string to the left of the ':'" do
|
||||
@provider.interface.should == "one"
|
||||
end
|
||||
it "should set the ifnum to the string to the right of the ':'" do
|
||||
@provider.ifnum.should == "two"
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when setting the device to a value starting with 'dummy-'" do
|
||||
before do
|
||||
@provider = Puppet::Type::Interface::ProviderRedhat.new
|
||||
@provider.device = "dummy5"
|
||||
end
|
||||
it "should set the interface type to :loopback" do
|
||||
@provider.interface_type.should == :loopback
|
||||
end
|
||||
it "should set the interface to 'dummy'" do
|
||||
@provider.interface.should == "dummy"
|
||||
end
|
||||
it "should set the ifnum to remainder of value after removing 'dummy'" do
|
||||
@provider.ifnum.should == "5"
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when setting the device to a value containing neither 'dummy-' nor ':'" do
|
||||
before do
|
||||
@provider = Puppet::Type::Interface::ProviderRedhat.new
|
||||
@provider.device = "whatever"
|
||||
end
|
||||
it "should set the interface type to :normal" do
|
||||
@provider.interface_type.should == :normal
|
||||
end
|
||||
it "should set the interface to the device value" do
|
||||
@provider.interface.should == "whatever"
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when setting the on_boot value" do
|
||||
before do
|
||||
@provider = Puppet::Type::Interface::ProviderRedhat.new
|
||||
end
|
||||
it "should set it to :true if the value is 'yes'" do
|
||||
@provider.on_boot = "yes"
|
||||
@provider.onboot.should == :true
|
||||
end
|
||||
it "should set it to :false if the value is not 'yes'" do
|
||||
@provider.on_boot = "no"
|
||||
@provider.onboot.should == :false
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when setting the ipaddr value" do
|
||||
before do
|
||||
@provider = Puppet::Type::Interface::ProviderRedhat.new
|
||||
end
|
||||
|
||||
it "should set the name to the provided value" do
|
||||
@provider.ipaddr = "yay"
|
||||
@provider.name.should == "yay"
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when generating" do
|
||||
before do
|
||||
@provider = Puppet::Type::Interface::ProviderRedhat.new
|
||||
@provider.interface_type = :alias
|
||||
@provider.stubs(:device).returns("mydevice")
|
||||
@provider.stubs(:on_boot).returns("myboot")
|
||||
@provider.stubs(:name).returns("myname")
|
||||
@provider.stubs(:netmask).returns("mynetmask")
|
||||
@provider.interface_type = :alias
|
||||
|
||||
@text = @provider.generate
|
||||
end
|
||||
|
||||
it "should set the bootproto to none if the interface is an alias" do
|
||||
@text.should =~ /^BOOTPROTO=none$/
|
||||
end
|
||||
|
||||
it "should set the bootproto to static if the interface is a loopback" do
|
||||
@provider.interface_type = :loopback
|
||||
@text = @provider.generate
|
||||
@text.should =~ /^BOOTPROTO=static$/
|
||||
end
|
||||
|
||||
it "should set the broadcast address to nothing" do
|
||||
@text.should =~ /^BROADCAST=$/
|
||||
end
|
||||
|
||||
it "should set the netmask to mynetmask" do
|
||||
@text.should =~ /^NETMASK=mynetmask$/
|
||||
end
|
||||
|
||||
it "should set the device to the provider's device" do
|
||||
@text.should =~ /^DEVICE=mydevice$/
|
||||
end
|
||||
|
||||
it "should set the onboot to the provider's on_boot value" do
|
||||
@text.should =~ /^ONBOOT=myboot$/
|
||||
end
|
||||
|
||||
it "should set the ipaddr to the provider's name" do
|
||||
@text.should =~ /^IPADDR=myname$/
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when creating and destroying" do
|
||||
before do
|
||||
@provider = provider_class.new(:interface => "eth0", :name => "testing")
|
||||
@path = "/etc/sysconfig/network-scripts/ifcfg-testing"
|
||||
end
|
||||
|
||||
it "should consider the interface present if the file exists" do
|
||||
FileTest.expects(:exist?).with(@path).returns(true)
|
||||
@provider.should be_exists
|
||||
end
|
||||
|
||||
it "should consider the interface absent if the file does not exist" do
|
||||
FileTest.expects(:exist?).with(@path).returns(false)
|
||||
@provider.should_not be_exists
|
||||
end
|
||||
|
||||
it "should remove the file if the interface is being destroyed" do
|
||||
File.expects(:unlink).with(@path)
|
||||
@provider.destroy
|
||||
end
|
||||
|
||||
it "should mark :ensure as :absent if the interface is destroyed" do
|
||||
File.stubs(:unlink)
|
||||
@provider.destroy
|
||||
@provider.ensure.should == :absent
|
||||
end
|
||||
|
||||
it "should mark :ensure as :present if the interface is being created" do
|
||||
resource = stub 'resource', :name => 'testing'
|
||||
resource.stubs(:should).with { |name| name == :ensure }.returns(:present)
|
||||
resource.stubs(:should).with { |name| name != :ensure }.returns(nil)
|
||||
@provider.resource = resource
|
||||
@provider.create
|
||||
@provider.ensure.should == :present
|
||||
end
|
||||
|
||||
it "should write the generated text to disk when the interface is flushed" do
|
||||
fh = mock("filehandle")
|
||||
File.expects(:open).yields(fh)
|
||||
fh.expects(:puts).with("generated")
|
||||
resource = stub 'resource', :name => 'testing'
|
||||
resource.stubs(:[]).with(:interface_desc).returns(nil)
|
||||
resource.stubs(:should).with { |name| name == :ensure }.returns(:present)
|
||||
resource.stubs(:should).with { |name| name != :ensure }.returns(nil)
|
||||
@provider.resource = resource
|
||||
@provider.create
|
||||
|
||||
@provider.stubs(:generate).returns("generated")
|
||||
@provider.flush
|
||||
end
|
||||
|
||||
it "should not write the generated text to disk when the interface is flushed if :ensure == :absent" do
|
||||
@provider.ensure = :absent
|
||||
@provider.flush
|
||||
end
|
||||
end
|
|
@ -1,239 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# Created by Luke Kanies on 2007-11-25.
|
||||
# Copyright (c) 2006. All rights reserved.
|
||||
|
||||
require File.dirname(__FILE__) + '/../../../spec_helper'
|
||||
|
||||
require 'puppet/provider/interface/sunos'
|
||||
|
||||
|
||||
provider_class = Puppet::Type.type(:interface).provider(:sunos)
|
||||
|
||||
describe provider_class do
|
||||
it "should not be functional on non-SunOS kernels" do
|
||||
Facter.expects(:value).with(:kernel).returns("Linux")
|
||||
provider_class.should_not be_suitable
|
||||
end
|
||||
|
||||
it "should be functional on SunOS kernels" do
|
||||
Facter.expects(:value).with(:kernel).returns("SunOS")
|
||||
provider_class.should be_suitable
|
||||
end
|
||||
|
||||
it "should pick its file path by combining '/etc/hostname.' with the interface if one is set" do
|
||||
provider = provider_class.new(:record_type => :sunos, :interface_type => :normal, :name => "testing", :interface => 'eth0')
|
||||
provider.file_path.should == "/etc/hostname.eth0"
|
||||
end
|
||||
|
||||
it "should pick its file path by combining '/etc/hostname.' with the resource's interface if one is not set in the provider" do
|
||||
provider = provider_class.new(:record_type => :sunos, :interface_type => :normal, :name => "testing")
|
||||
resource = mock 'resource'
|
||||
resource.stubs(:[]).with(:interface).returns("eth0")
|
||||
provider.resource = resource
|
||||
provider.file_path.should == "/etc/hostname.eth0"
|
||||
end
|
||||
|
||||
it "should fail when picking its file path if there is no resource nor an interface set in the provider" do
|
||||
provider = provider_class.new(:record_type => :sunos, :interface_type => :normal, :name => "testing")
|
||||
proc { provider.file_path }.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when listing interfaces" do
|
||||
it "should return an instance for every file matching /etc/hostname.*, created with the interface name set from the file" do
|
||||
Dir.expects(:glob).with("/etc/hostname.*").returns(%w{/etc/hostname.one /etc/hostname.two})
|
||||
one_instance = stub 'one_instance', :parse => nil
|
||||
two_instance = stub 'two_instance', :parse => nil
|
||||
provider_class.expects(:new).with(:interface => "one").returns(one_instance)
|
||||
provider_class.expects(:new).with(:interface => "two").returns(two_instance)
|
||||
|
||||
provider_class.instances.should == [one_instance, two_instance]
|
||||
end
|
||||
|
||||
it "should call parse on each instance being returned" do
|
||||
Dir.expects(:glob).with("/etc/hostname.*").returns(%w{/etc/hostname.one})
|
||||
one_instance = mock 'one_instance'
|
||||
provider_class.expects(:new).with(:interface => "one").returns(one_instance)
|
||||
|
||||
one_instance.expects(:parse)
|
||||
|
||||
provider_class.instances
|
||||
end
|
||||
|
||||
it "should assign matching providers to any prefetched instances" do
|
||||
Dir.expects(:glob).with("/etc/hostname.*").returns(%w{one two})
|
||||
one_instance = stub 'one_instance', :name => "one", :parse => nil
|
||||
two_instance = stub 'two_instance', :name => "two", :parse => nil
|
||||
provider_class.expects(:new).with(:interface => "one").returns(one_instance)
|
||||
provider_class.expects(:new).with(:interface => "two").returns(two_instance)
|
||||
|
||||
resources = {"one" => mock("one"), "three" => mock('three')}
|
||||
resources["one"].expects(:provider=).with(one_instance)
|
||||
|
||||
provider_class.prefetch(resources)
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when creating and destroying" do
|
||||
before do
|
||||
@provider = provider_class.new(:interface => "eth0", :name => "testing")
|
||||
end
|
||||
|
||||
it "should consider the interface present if the file exists" do
|
||||
FileTest.expects(:exist?).with("/etc/hostname.eth0").returns(true)
|
||||
@provider.should be_exists
|
||||
end
|
||||
|
||||
it "should consider the interface absent if the file does not exist" do
|
||||
FileTest.expects(:exist?).with("/etc/hostname.eth0").returns(false)
|
||||
@provider.should_not be_exists
|
||||
end
|
||||
|
||||
it "should remove the file if the interface is being destroyed" do
|
||||
File.expects(:unlink).with("/etc/hostname.eth0")
|
||||
@provider.destroy
|
||||
end
|
||||
|
||||
it "should mark :ensure as :absent if the interface is destroyed" do
|
||||
File.stubs(:unlink)
|
||||
@provider.destroy
|
||||
@provider.ensure.should == :absent
|
||||
end
|
||||
|
||||
it "should mark :ensure as :present if the interface is being created" do
|
||||
resource = stub 'resource', :name => 'testing'
|
||||
resource.stubs(:should).with { |name| name == :ensure }.returns(:present)
|
||||
resource.stubs(:should).with { |name| name != :ensure }.returns(nil)
|
||||
@provider.resource = resource
|
||||
@provider.create
|
||||
@provider.ensure.should == :present
|
||||
end
|
||||
|
||||
it "should write the generated text to disk when the interface is flushed" do
|
||||
fh = mock("filehandle")
|
||||
File.expects(:open).yields(fh)
|
||||
fh.expects(:print).with("testing\n")
|
||||
resource = stub 'resource', :name => 'testing'
|
||||
resource.stubs(:should).with { |name| name == :ensure }.returns(:present)
|
||||
resource.stubs(:should).with { |name| name != :ensure }.returns(nil)
|
||||
@provider.resource = resource
|
||||
@provider.create
|
||||
@provider.flush
|
||||
end
|
||||
|
||||
it "should not write the generated text to disk when the interface is flushed if :ensure == :absent" do
|
||||
@provider.ensure = :absent
|
||||
@provider.flush
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when parsing a non-existant file" do
|
||||
it "should mark the interface as absent" do
|
||||
@provider = provider_class.new(:interface => "eth0", :name => "testing")
|
||||
FileTest.expects(:exist?).with("/etc/hostname.eth0").returns(false)
|
||||
@provider.parse
|
||||
@provider.ensure.should == :absent
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when parsing an existing file" do
|
||||
before do
|
||||
@provider = provider_class.new(:interface => "eth0", :name => "testing")
|
||||
FileTest.stubs(:exist?).with("/etc/hostname.eth0").returns(true)
|
||||
end
|
||||
|
||||
def set_text(text)
|
||||
File.stubs(:read).with("/etc/hostname.eth0").returns(text)
|
||||
end
|
||||
|
||||
it "should retain the interface name" do
|
||||
set_text "testing"
|
||||
@provider.parse
|
||||
@provider.ensure.should == :present
|
||||
@provider.interface.should == "eth0"
|
||||
end
|
||||
|
||||
it "should mark the interface as present" do
|
||||
set_text "testing"
|
||||
@provider.parse
|
||||
@provider.ensure.should == :present
|
||||
end
|
||||
|
||||
it "should mark the interface as an alias if the first word is 'addif'" do
|
||||
set_text "addif testing"
|
||||
@provider.parse
|
||||
@provider.interface_type.should == :alias
|
||||
end
|
||||
|
||||
it "should not mark the interface as normal if the first word is not 'addif'" do
|
||||
set_text "testing"
|
||||
@provider.parse
|
||||
@provider.interface_type.should == :normal
|
||||
end
|
||||
|
||||
it "should start the interface on boot of the last word is 'up'" do
|
||||
set_text "testing up"
|
||||
@provider.parse
|
||||
@provider.onboot.should == :true
|
||||
end
|
||||
|
||||
it "should not start the interface on boot of the last word is not 'up'" do
|
||||
set_text "testing"
|
||||
@provider.parse
|
||||
@provider.onboot.should == :false
|
||||
end
|
||||
|
||||
it "should set the interface to the first non-behavioural word" do
|
||||
set_text "addif testing up"
|
||||
@provider.parse
|
||||
@provider.name.should == "testing"
|
||||
end
|
||||
|
||||
it "should consider any remaining terms to be interface options" do
|
||||
set_text "addif testing -O up"
|
||||
@provider.parse
|
||||
@provider.ifopts.should == "-O"
|
||||
end
|
||||
end
|
||||
|
||||
describe provider_class, " when generating" do
|
||||
before do
|
||||
@provider = provider_class.new(:interface => "eth0", :name => "testing")
|
||||
end
|
||||
|
||||
it "should prefix the text with 'addif' if the interface is an alias" do
|
||||
@provider.interface_type = :alias
|
||||
@provider.generate.should == "addif testing"
|
||||
end
|
||||
|
||||
it "should not prefix the text with 'addif' if the interface is not an alias" do
|
||||
@provider.generate.should == "testing"
|
||||
end
|
||||
|
||||
it "should put the ifopts after the name if they are present" do
|
||||
@provider.ifopts = "-O"
|
||||
@provider.generate.should == "testing -O"
|
||||
end
|
||||
|
||||
it "should mark the interface up if onboot is enabled" do
|
||||
@provider.onboot = :true
|
||||
@provider.generate.should == "testing up"
|
||||
end
|
||||
|
||||
it "should use the resource name if no provider name is present" do
|
||||
provider = provider_class.new(:interface => "eth0")
|
||||
resource = stub 'resource', :name => "rtest"
|
||||
provider.resource = resource
|
||||
provider.generate.should == "rtest"
|
||||
end
|
||||
|
||||
it "should use the provider name if present" do
|
||||
@provider.generate.should == "testing"
|
||||
end
|
||||
|
||||
it "should fail if neither a resource nor the provider name is present" do
|
||||
provider = provider_class.new(:interface => "eth0")
|
||||
proc { provider.generate }.should raise_error
|
||||
end
|
||||
end
|
|
@ -0,0 +1,182 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../../spec_helper'
|
||||
|
||||
require 'puppet/transaction/change'
|
||||
|
||||
describe Puppet::Transaction::Change do
|
||||
Change = Puppet::Transaction::Change
|
||||
|
||||
describe "when initializing" do
|
||||
before do
|
||||
@property = stub 'property', :path => "/property/path", :should => "shouldval"
|
||||
end
|
||||
|
||||
it "should require the property and current value" do
|
||||
lambda { Change.new() }.should raise_error
|
||||
end
|
||||
|
||||
it "should set its property to the provided property" do
|
||||
Change.new(@property, "value").property.should == :property
|
||||
end
|
||||
|
||||
it "should set its 'is' value to the provided value" do
|
||||
Change.new(@property, "value").is.should == "value"
|
||||
end
|
||||
|
||||
it "should retrieve the 'should' value from the property" do
|
||||
# Yay rspec :)
|
||||
Change.new(@property, "value").should.should == @property.should
|
||||
end
|
||||
|
||||
it "should set its path to the path of the property plus 'change'" do
|
||||
Change.new(@property, "value").path.should == [@property.path, "change"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "when an instance" do
|
||||
before do
|
||||
@property = stub 'property', :path => "/property/path", :should => "shouldval"
|
||||
@change = Change.new(@property, "value")
|
||||
end
|
||||
|
||||
it "should be noop if the property is noop" do
|
||||
@property.expects(:noop).returns true
|
||||
@change.noop?.should be_true
|
||||
end
|
||||
|
||||
it "should set its resource to the proxy if it has one" do
|
||||
@change.proxy = :myresource
|
||||
@change.resource.should == :myresource
|
||||
end
|
||||
|
||||
it "should set its resource to the property's resource if no proxy is set" do
|
||||
@property.expects(:resource).returns :myresource
|
||||
@change.resource.should == :myresource
|
||||
end
|
||||
|
||||
it "should have a method for marking that it's been execution" do
|
||||
@change.changed = true
|
||||
@change.changed?.should be_true
|
||||
end
|
||||
|
||||
describe "and creating an event" do
|
||||
before do
|
||||
@property.stubs(:resource).returns "myresource"
|
||||
end
|
||||
|
||||
it "should produce a warning if the event name is not a symbol" do
|
||||
@property.expects(:warning)
|
||||
@property.stubs(:event).returns :myevent
|
||||
@change.event("a string")
|
||||
end
|
||||
|
||||
it "should use the property to generate the event name if the provided name is not a symbol" do
|
||||
@property.stubs(:warning)
|
||||
@property.expects(:event).with(@change.should).returns :myevent
|
||||
|
||||
Puppet::Transaction::Event.expects(:new).with { |name, source| name == :myevent }
|
||||
|
||||
@change.event("a string")
|
||||
end
|
||||
end
|
||||
|
||||
describe "and executing" do
|
||||
describe "in noop mode" do
|
||||
before { @change.stubs(:noop?).returns true }
|
||||
|
||||
it "should log that it is in noop" do
|
||||
@property.expects(:is_to_s)
|
||||
@property.expects(:should_to_s)
|
||||
@property.expects(:log)
|
||||
|
||||
@change.stubs :event
|
||||
@change.forward
|
||||
end
|
||||
|
||||
it "should produce a :noop event and return" do
|
||||
@property.stub_everything
|
||||
|
||||
@change.expects(:event).with(:noop).returns :noop_event
|
||||
|
||||
@change.forward.should == [:noop_event]
|
||||
end
|
||||
end
|
||||
|
||||
describe "without noop" do
|
||||
before do
|
||||
@change.stubs(:noop?).returns false
|
||||
@property.stub_everything
|
||||
@property.stubs(:resource).returns "myresource"
|
||||
end
|
||||
|
||||
it "should sync the property" do
|
||||
@property.expects(:sync)
|
||||
|
||||
@change.forward
|
||||
end
|
||||
|
||||
it "should return nil if syncing the property returns nil" do
|
||||
@property.stubs(:sync).returns nil
|
||||
|
||||
@change.forward.should be_nil
|
||||
end
|
||||
|
||||
it "should return nil if syncing the property returns an empty array" do
|
||||
@property.stubs(:sync).returns []
|
||||
|
||||
@change.forward.should be_nil
|
||||
end
|
||||
|
||||
it "should log the change" do
|
||||
@property.expects(:sync).returns [:one]
|
||||
|
||||
@property.expects(:log)
|
||||
@property.expects(:change_to_s)
|
||||
|
||||
@change.forward
|
||||
end
|
||||
|
||||
it "should return an array of events" do
|
||||
@property.expects(:sync).returns [:one, :two]
|
||||
|
||||
@change.expects(:event).with(:one).returns :uno
|
||||
@change.expects(:event).with(:two).returns :dos
|
||||
|
||||
@change.forward.should == [:uno, :dos]
|
||||
end
|
||||
end
|
||||
|
||||
describe "backward" do
|
||||
before do
|
||||
@property = stub 'property'
|
||||
@property.stub_everything
|
||||
@property.stubs(:should).returns "shouldval"
|
||||
@change = Change.new(@property, "value")
|
||||
@change.stubs :go
|
||||
end
|
||||
|
||||
it "should swap the 'is' and 'should' values" do
|
||||
@change.backward
|
||||
@change.is.should == "shouldval"
|
||||
@change.should.should == "value"
|
||||
end
|
||||
|
||||
it "should set the 'should' value on the property to the previous 'is' value" do
|
||||
@property.expects(:should=).with "value"
|
||||
@change.backward
|
||||
end
|
||||
|
||||
it "should log that it's reversing the change" do
|
||||
@property.expects(:info)
|
||||
@change.backward
|
||||
end
|
||||
|
||||
it "should execute" do
|
||||
@change.expects(:go)
|
||||
@change.backward
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../../spec_helper'
|
||||
|
||||
require 'puppet/transaction/event'
|
||||
|
||||
describe Puppet::Transaction::Event do
|
||||
Event = Puppet::Transaction::Event
|
||||
|
||||
it "should require a name and a source" do
|
||||
lambda { Event.new }.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "should have a name getter" do
|
||||
Event.new(:foo, "bar").name.should == :foo
|
||||
end
|
||||
|
||||
it "should have a source accessor" do
|
||||
Event.new(:foo, "bar").source.should == "bar"
|
||||
end
|
||||
|
||||
it "should be able to produce a string containing the event name and the source" do
|
||||
Event.new(:event, :source).to_s.should == "source -> event"
|
||||
end
|
||||
end
|
|
@ -31,6 +31,18 @@ describe Puppet::Type.type(:file) do
|
|||
end
|
||||
end
|
||||
|
||||
describe "when specifying a source" do
|
||||
before do
|
||||
@file[:source] = "/bar"
|
||||
end
|
||||
|
||||
it "should raise if source doesn't exist" do
|
||||
@file.property(:source).expects(:found?).returns(false)
|
||||
lambda { @file.retrieve }.should raise_error(Puppet::Error)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "when retrieving remote files" do
|
||||
before do
|
||||
@filesource = Puppet::Type::File::FileSource.new
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require File.dirname(__FILE__) + '/../../spec_helper'
|
||||
|
||||
interface = Puppet::Type.type(:interface)
|
||||
|
||||
describe interface do
|
||||
before do
|
||||
@class = Puppet::Type.type(:interface)
|
||||
|
||||
@provider_class = stub 'provider_class', :name => "fake", :suitable? => true, :supports_parameter? => true
|
||||
@class.stubs(:defaultprovider).returns(@provider_class)
|
||||
@class.stubs(:provider).returns(@provider_class)
|
||||
|
||||
@provider = stub 'provider', :class => @provider_class, :file_path => "/tmp/whatever", :clear => nil
|
||||
@provider_class.stubs(:new).returns(@provider)
|
||||
end
|
||||
|
||||
it "should have a name parameter" do
|
||||
@class.attrtype(:name).should == :param
|
||||
end
|
||||
|
||||
it "should have :name be its namevar" do
|
||||
@class.namevar.should == :name
|
||||
end
|
||||
|
||||
it "should have a :provider parameter" do
|
||||
@class.attrtype(:provider).should == :param
|
||||
end
|
||||
|
||||
it "should have an ensure property" do
|
||||
@class.attrtype(:ensure).should == :property
|
||||
end
|
||||
|
||||
it "should support :present as a value for :ensure" do
|
||||
proc { @class.create(:name => "whev", :ensure => :present) }.should_not raise_error
|
||||
end
|
||||
|
||||
it "should support :absent as a value for :ensure" do
|
||||
proc { @class.create(:name => "whev", :ensure => :absent) }.should_not raise_error
|
||||
end
|
||||
|
||||
it "should have an interface_type property" do
|
||||
@class.attrtype(:interface_type).should == :property
|
||||
end
|
||||
it "should support :loopback as an interface_type value" do
|
||||
proc { @class.create(:name => "whev", :interface_type => :loopback) }.should_not raise_error
|
||||
end
|
||||
it "should support :alias as an interface_type value" do
|
||||
proc { @class.create(:name => "whev", :interface_type => :alias) }.should_not raise_error
|
||||
end
|
||||
it "should support :normal as an interface_type value" do
|
||||
proc { @class.create(:name => "whev", :interface_type => :normal) }.should_not raise_error
|
||||
end
|
||||
it "should alias :dummy to the :loopback interface_type value" do
|
||||
int = @class.create(:name => "whev", :interface_type => :dummy)
|
||||
int.should(:interface_type).should == :loopback
|
||||
end
|
||||
|
||||
it "should not support values other than :loopback, :alias, :normal, and :dummy in the interface_type" do
|
||||
proc { @class.create(:name => "whev", :interface_type => :something) }.should raise_error(Puppet::Error)
|
||||
end
|
||||
|
||||
it "should have an interface_desc parameter" do
|
||||
@class.attrtype(:interface_desc).should == :param
|
||||
end
|
||||
|
||||
it "should have an onboot property" do
|
||||
@class.attrtype(:onboot).should == :property
|
||||
end
|
||||
it "should support :true as an onboot value" do
|
||||
proc { @class.create(:name => "whev", :onboot => :true) }.should_not raise_error
|
||||
end
|
||||
it "should support :false as an onboot value" do
|
||||
proc { @class.create(:name => "whev", :onboot => :false) }.should_not raise_error
|
||||
end
|
||||
|
||||
it "should have an ifnum property" do
|
||||
@class.attrtype(:ifnum).should == :property
|
||||
end
|
||||
|
||||
it "should have a netmask property" do
|
||||
@class.attrtype(:netmask).should == :property
|
||||
end
|
||||
|
||||
it "should have an ifopts property" do
|
||||
@class.attrtype(:ifopts).should == :property
|
||||
end
|
||||
|
||||
it "should have a target parameter" do
|
||||
@class.attrtype(:target).should == :param
|
||||
end
|
||||
end
|
|
@ -14,6 +14,7 @@ describe ssh_authorized_key do
|
|||
|
||||
@provider = stub 'provider', :class => @provider_class, :file_path => "/tmp/whatever", :clear => nil
|
||||
@provider_class.stubs(:new).returns(@provider)
|
||||
@catalog = Puppet::Node::Catalog.new
|
||||
end
|
||||
|
||||
it "should have a name parameter" do
|
||||
|
@ -33,27 +34,27 @@ describe ssh_authorized_key do
|
|||
end
|
||||
|
||||
it "should support :present as a value for :ensure" do
|
||||
proc { @class.create(:name => "whev", :ensure => :present) }.should_not raise_error
|
||||
proc { @class.create(:name => "whev", :ensure => :present, :user => "nobody") }.should_not raise_error
|
||||
end
|
||||
|
||||
it "should support :absent as a value for :ensure" do
|
||||
proc { @class.create(:name => "whev", :ensure => :absent) }.should_not raise_error
|
||||
proc { @class.create(:name => "whev", :ensure => :absent, :user => "nobody") }.should_not raise_error
|
||||
end
|
||||
|
||||
it "should have an type property" do
|
||||
@class.attrtype(:type).should == :property
|
||||
end
|
||||
it "should support ssh-dss as an type value" do
|
||||
proc { @class.create(:name => "whev", :type => "ssh-dss") }.should_not raise_error
|
||||
proc { @class.create(:name => "whev", :type => "ssh-dss", :user => "nobody") }.should_not raise_error
|
||||
end
|
||||
it "should support ssh-rsa as an type value" do
|
||||
proc { @class.create(:name => "whev", :type => "ssh-rsa") }.should_not raise_error
|
||||
proc { @class.create(:name => "whev", :type => "ssh-rsa", :user => "nobody") }.should_not raise_error
|
||||
end
|
||||
it "should support :dsa as an type value" do
|
||||
proc { @class.create(:name => "whev", :type => :dsa) }.should_not raise_error
|
||||
proc { @class.create(:name => "whev", :type => :dsa, :user => "nobody") }.should_not raise_error
|
||||
end
|
||||
it "should support :rsa as an type value" do
|
||||
proc { @class.create(:name => "whev", :type => :rsa) }.should_not raise_error
|
||||
proc { @class.create(:name => "whev", :type => :rsa, :user => "nobody") }.should_not raise_error
|
||||
end
|
||||
|
||||
it "should not support values other than ssh-dss, ssh-rsa, dsa, rsa in the ssh_authorized_key_type" do
|
||||
|
@ -75,4 +76,55 @@ describe ssh_authorized_key do
|
|||
it "should have a target property" do
|
||||
@class.attrtype(:target).should == :property
|
||||
end
|
||||
|
||||
it "should autorequire parent directories when user is given" do
|
||||
@catalog.add_resource @class.create(
|
||||
:name => "Test",
|
||||
:key => "AAA",
|
||||
:type => "ssh-rsa",
|
||||
:ensure => :present,
|
||||
:user => "root")
|
||||
@catalog.apply
|
||||
|
||||
target = File.expand_path("~root/.ssh")
|
||||
@catalog.resource(:file, target).should be_an_instance_of(Puppet::Type.type(:file))
|
||||
end
|
||||
|
||||
it "should set target when user is given" do
|
||||
@catalog.add_resource @class.create(
|
||||
:name => "Test",
|
||||
:key => "AAA",
|
||||
:type => "ssh-rsa",
|
||||
:ensure => :present,
|
||||
:user => "root")
|
||||
@catalog.apply
|
||||
|
||||
target = File.expand_path("~root/.ssh/authorized_keys")
|
||||
@catalog.resource(:file, target).should be_an_instance_of(Puppet::Type.type(:file))
|
||||
end
|
||||
|
||||
|
||||
it "should autorequire parent directories when target is given" do
|
||||
target = "/tmp/home/foo/bar/.ssh/authorized_keys"
|
||||
|
||||
@catalog.add_resource @class.create(
|
||||
:name => "Test",
|
||||
:key => "AAA",
|
||||
:type => "ssh-rsa",
|
||||
:ensure => :present,
|
||||
:target => target)
|
||||
@catalog.apply
|
||||
|
||||
@catalog.resource(:file, target).should be_an_instance_of(Puppet::Type.type(:file))
|
||||
end
|
||||
|
||||
it "should raise an error when neither user nor target is given" do
|
||||
proc do
|
||||
@class.create(
|
||||
:name => "Test",
|
||||
:key => "AAA",
|
||||
:type => "ssh-rsa",
|
||||
:ensure => :present)
|
||||
end.should raise_error(Puppet::Error)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -668,11 +668,17 @@ describe Puppet::Util::Settings do
|
|||
@settings.reuse
|
||||
end
|
||||
|
||||
it "should fail if any resources fail" do
|
||||
it "should fail with an appropriate message if any resources fail" do
|
||||
stub_transaction
|
||||
@trans.expects(:any_failed?).returns(true)
|
||||
report = mock 'report'
|
||||
@trans.expects(:report).returns report
|
||||
|
||||
proc { @settings.use(:whatever) }.should raise_error(RuntimeError)
|
||||
log = mock 'log', :to_s => "My failure", :level => :err
|
||||
report.expects(:logs).returns [log]
|
||||
|
||||
@settings.expects(:raise).with { |msg| msg.include?("My failure") }
|
||||
@settings.use(:whatever)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ module PuppetTest::Support::Utils
|
|||
newevents = nil
|
||||
assert_nothing_raised("Transaction %s %s failed" % [type, msg]) {
|
||||
newevents = trans.send(method).reject { |e| e.nil? }.collect { |e|
|
||||
e.event
|
||||
e.name
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# Created by Luke A. Kanies on 2006-12-21.
|
||||
# Copyright (c) 2006. All rights reserved.
|
||||
|
||||
require File.dirname(__FILE__) + '/../lib/puppettest'
|
||||
|
||||
require 'puppettest'
|
||||
|
||||
class TestPropertyChange < Test::Unit::TestCase
|
||||
include PuppetTest
|
||||
class FakeProperty < Puppet::Property
|
||||
attr_accessor :is, :should, :resource
|
||||
attr_reader :noop
|
||||
def change_to_s(currentvalue, newvalue)
|
||||
"fake change"
|
||||
end
|
||||
def insync?(is)
|
||||
is == @should
|
||||
end
|
||||
def log(msg)
|
||||
Puppet::Util::Log.create(
|
||||
:level => :info,
|
||||
:source => self,
|
||||
:message => msg
|
||||
)
|
||||
end
|
||||
def noop
|
||||
if defined? @noop
|
||||
@noop
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
def path
|
||||
"fakechange"
|
||||
end
|
||||
def should_to_s(newvalue)
|
||||
newvalue.to_s
|
||||
end
|
||||
def sync
|
||||
if insync?(@is)
|
||||
return nil
|
||||
else
|
||||
@is = @should
|
||||
return :fake_change
|
||||
end
|
||||
end
|
||||
def to_s
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
def mkchange
|
||||
property = FakeProperty.new :resource => "fakeparent"
|
||||
property.is = :start
|
||||
property.should = :finish
|
||||
property.resource = :parent
|
||||
change = nil
|
||||
assert_nothing_raised do
|
||||
change = Puppet::PropertyChange.new(property, :start)
|
||||
end
|
||||
change.transaction = :trans
|
||||
|
||||
assert_equal(:start, change.is, "@is did not get copied")
|
||||
assert_equal(:finish, change.should, "@should did not get copied")
|
||||
assert_equal(%w{fakechange change}, change.path, "path did not get set correctly")
|
||||
|
||||
assert(! change.changed?, "change defaulted to already changed")
|
||||
|
||||
return change
|
||||
end
|
||||
|
||||
def test_go
|
||||
change = mkchange
|
||||
|
||||
coll = logcollector()
|
||||
|
||||
events = nil
|
||||
# First make sure we get an immediate return
|
||||
assert_nothing_raised do
|
||||
events = change.go
|
||||
end
|
||||
assert_instance_of(Array, events, "events were not returned in an array")
|
||||
assert_instance_of(Puppet::Event, events[0], "event array did not contain events")
|
||||
|
||||
event = events.shift
|
||||
{:event => :fake_change, :transaction => :trans, :source => :parent}.each do |method, val|
|
||||
assert_equal(val, event.send(method), "Event did not set %s correctly" % method)
|
||||
end
|
||||
|
||||
# Disabled, because it fails when running the whole suite at once.
|
||||
#assert(coll.detect { |l| l.message == "fake change" }, "Did not log change")
|
||||
assert_equal(change.property.is, change.property.should, "did not call sync method")
|
||||
|
||||
# Now make sure that proxy sources can be set.
|
||||
assert_nothing_raised do
|
||||
change.proxy = :other
|
||||
end
|
||||
# Reset, so we change again
|
||||
change.property.is = :start
|
||||
change.is = :start
|
||||
assert_nothing_raised do
|
||||
events = change.go
|
||||
end
|
||||
|
||||
assert_instance_of(Array, events, "events were not returned in an array")
|
||||
assert_instance_of(Puppet::Event, events[0], "event array did not contain events")
|
||||
|
||||
event = events.shift
|
||||
{:event => :fake_change, :transaction => :trans, :source => :other}.each do |method, val|
|
||||
assert_equal(val, event.send(method), "Event did not set %s correctly" % method)
|
||||
end
|
||||
|
||||
#assert(coll.detect { |l| l.message == "fake change" }, "Did not log change")
|
||||
assert_equal(change.property.is, change.property.should, "did not call sync method")
|
||||
end
|
||||
|
||||
# Related to #542. Make sure changes in noop mode produce the :noop event.
|
||||
def test_noop_event
|
||||
change = mkchange
|
||||
|
||||
assert(! change.skip?, "Change is already being skipped")
|
||||
|
||||
Puppet[:noop] = true
|
||||
|
||||
change.property.noop = true
|
||||
assert(change.noop, "did not set noop")
|
||||
assert(change.skip?, "setting noop did not mark change for skipping")
|
||||
|
||||
event = nil
|
||||
assert_nothing_raised("Could not generate noop event") do
|
||||
event = change.forward
|
||||
end
|
||||
|
||||
assert_equal(1, event.length, "got wrong number of events")
|
||||
assert_equal(:noop, event[0].event, "did not generate noop mode when in noop")
|
||||
end
|
||||
end
|
||||
|
|
@ -792,7 +792,7 @@ class TestTransactions < Test::Unit::TestCase
|
|||
def test_proxy_resources
|
||||
type = mkreducer do
|
||||
def evaluate
|
||||
return Puppet::PropertyChange.new(Fakeprop.new(
|
||||
return Puppet::Transaction::Change.new(Fakeprop.new(
|
||||
:path => :path, :is => :is, :should => :should, :name => self.name, :resource => "a parent"), :is)
|
||||
end
|
||||
end
|
||||
|
@ -811,7 +811,7 @@ class TestTransactions < Test::Unit::TestCase
|
|||
assert(changes.length > 0, "did not get any changes")
|
||||
|
||||
changes.each do |change|
|
||||
assert_equal(resource, change.source, "change did not get proxy set correctly")
|
||||
assert_equal(resource, change.resource, "change did not get proxy set correctly")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -901,10 +901,9 @@ class TestTransactions < Test::Unit::TestCase
|
|||
assert(result, "c did not trigger anything")
|
||||
assert_instance_of(Array, result)
|
||||
event = result.shift
|
||||
assert_instance_of(Puppet::Event, event)
|
||||
assert_equal(:triggered, event.event, "event was not set correctly")
|
||||
assert_instance_of(Puppet::Transaction::Event, event)
|
||||
assert_equal(:triggered, event.name, "event was not set correctly")
|
||||
assert_equal(c, event.source, "source was not set correctly")
|
||||
assert_equal(trans, event.transaction, "transaction was not set correctly")
|
||||
|
||||
assert(trans.triggered?(c, :refresh),
|
||||
"Transaction did not store the trigger")
|
||||
|
@ -991,7 +990,7 @@ class TestTransactions < Test::Unit::TestCase
|
|||
newparam(:name) {}
|
||||
newproperty(:testing) do
|
||||
def sync
|
||||
self.is = self.should
|
||||
# noop
|
||||
:ran_testing
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
require File.dirname(__FILE__) + '/../../lib/puppettest'
|
||||
|
||||
require 'puppettest'
|
||||
require 'puppet/type/sshkey'
|
||||
require 'facter'
|
||||
|
||||
class TestSSHKey < Test::Unit::TestCase
|
||||
|
|
Загрузка…
Ссылка в новой задаче