summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG108
-rwxr-xr-xinstall.rb45
-rw-r--r--lib/puppet.rb2
-rw-r--r--lib/puppet/configurer/downloader.rb1
-rw-r--r--lib/puppet/configurer/plugin_handler.rb9
-rw-r--r--lib/puppet/indirector/facts/inventory_active_record.rb97
-rw-r--r--lib/puppet/module.rb2
-rw-r--r--lib/puppet/network/rest_authconfig.rb2
-rw-r--r--lib/puppet/parser/ast/collection.rb9
-rwxr-xr-xlib/puppet/provider/mount/parsed.rb6
-rwxr-xr-xlib/puppet/provider/parsedfile.rb4
-rw-r--r--lib/puppet/provider/user/useradd.rb7
-rw-r--r--lib/puppet/rails/database/004_add_inventory_service_tables.rb36
-rw-r--r--lib/puppet/rails/database/schema.rb17
-rw-r--r--lib/puppet/rails/inventory_fact.rb5
-rw-r--r--lib/puppet/rails/inventory_node.rb25
-rw-r--r--lib/puppet/reports/store.rb5
-rw-r--r--lib/puppet/resource.rb39
-rw-r--r--lib/puppet/type.rb10
-rw-r--r--lib/puppet/type/computer.rb6
-rwxr-xr-xlib/puppet/type/exec.rb4
-rw-r--r--lib/puppet/type/file.rb4
-rw-r--r--lib/puppet/type/macauthorization.rb5
-rw-r--r--lib/puppet/type/mcx.rb5
-rwxr-xr-xlib/puppet/type/mount.rb5
-rw-r--r--lib/puppet/type/package.rb6
-rw-r--r--lib/puppet/type/selmodule.rb4
-rw-r--r--lib/puppet/type/ssh_authorized_key.rb6
-rwxr-xr-xlib/puppet/type/user.rb15
-rwxr-xr-xlib/puppet/type/zfs.rb4
-rw-r--r--lib/puppet/type/zone.rb4
-rw-r--r--lib/puppet/util.rb5
-rw-r--r--lib/puppet/util/execution.rb9
-rw-r--r--lib/puppet/util/execution_stub.rb26
-rw-r--r--lib/puppet/util/settings.rb2
-rw-r--r--spec/integration/provider/mount_spec.rb151
-rw-r--r--spec/spec_helper.rb1
-rwxr-xr-xspec/unit/configurer/downloader_spec.rb32
-rw-r--r--spec/unit/indirector/facts/inventory_active_record_spec.rb164
-rwxr-xr-xspec/unit/module_spec.rb4
-rw-r--r--spec/unit/network/handler/fileserver_spec.rb2
-rwxr-xr-xspec/unit/parser/ast/collection_spec.rb28
-rwxr-xr-xspec/unit/parser/parser_spec.rb2
-rwxr-xr-xspec/unit/provider/ssh_authorized_key/parsed_spec.rb1
-rw-r--r--spec/unit/provider/user/user_role_add_spec.rb1
-rwxr-xr-xspec/unit/provider/user/useradd_spec.rb46
-rw-r--r--spec/unit/reports/store_spec.rb2
-rwxr-xr-xspec/unit/resource_spec.rb22
-rwxr-xr-xspec/unit/type/mount_spec.rb96
-rwxr-xr-xspec/unit/type/user_spec.rb4
-rwxr-xr-xspec/unit/type_spec.rb13
-rw-r--r--spec/unit/util/execution_spec.rb49
-rw-r--r--spec/unit/util/execution_stub_spec.rb35
-rwxr-xr-xspec/unit/util/settings_spec.rb13
54 files changed, 1033 insertions, 172 deletions
diff --git a/CHANGELOG b/CHANGELOG
index c08d7e72f..2885596e3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,111 @@
-2.6.6rc1
+2.6.7rc1
========
+852fb97 (#5073) Download plugins even if you're filtering on tags
+4f34dbf Fix #5610: Prevent unnecessary RAL lookups
+9781032 Revert "Merge branch 'ticket/2.6.x/5605' of git://github.com/stschulte/puppet into 2.6.next"
+25926d1 (#6723) Fix withenv environment restoration bug
+093f162 (#6689) Remove extraneous include of Puppet::Util in InventoryActiveRecord
+4c19299 Remove extra trailing whitespace from lib/puppet/resource.rb
+ff9e242 (#5428) More fully "stub" Puppet::Resource::Reference for use with storedconfigs
+0262633 (#6707) Fix typo in rest_authconfig.rb
+8858e40 (#6689) Make inventory_active_record terminus search quickly
+285c4cc (#5392) Give a better error when realizing a non-existant resource
+cd5deda (#2645) Adding a less-stubby test to verify the "system" attribute's behavior
+531e258 maint: Remove serialization of InventoryFact values
+3489412 maint: Rename InventoryHost to InventoryNode
+4bd5493 Fixed #2645 - Added support for creating system users
+a3f2357 maint: Remove spec run noise
+7764412 maint:Refactor of mount provider integration tests
+880d0c6 (#6338) Support searching on metadata in InventoryActiveRecord terminus
+f836366 (#6338) Implement search for InventoryActiveRecord facts terminus
+8ce30c8 (#6338) Add an InventoryActiveRecord terminus for Facts
+1ef83cb Added integration tests for the mount provider
+64440e5 (#6513) Propagate the environment when doing variable lookup in settings
+92dffb2 (#6513) Adjust P::U::Settings test name to reflect what it tests
+5ef1031 (#6632) Adding a new mount no longer causes error with umount
+bd5517d Adjust Darwin mount provider tests to pass on Linux
+9d2fceb Maint: Begin adding integration tests for the mount provider
+23d1c03 Maint: Added the ability to replace the behavior of Puppet::Util.execute with an arbitrary code block for ease in spec testing.
+455a891 (#5794) create reports directory when creating host specific directory
+1b1e803 (5724) Prep for deprecation of DESTDIR
+f4a0af1 Refactoring duplicate code and logic in prep for DESTDIR deprecation.
+7a00d6b (#6606) Inline docs: Document all autorequire relationships
+e3aec14 (#5148) Fix failing spec due to timezone
+8bd80a9 (#5148) Add support for PSON to facts
+c3baa28 (#6338) Remove inventory indirection, and move to facts indirection
+6c53eb3 (#6445) Fix inline docs: puppet agent does not accept --mkusers
+4e29f43 (#6541) maint: whitespace cleanup on the file integration spec
+b907ba3 (#6541) Fix content with checksum truncation bug
+422399b (#5466) Write specs for output of puppet resource
+8cc390c (#5466) Monkey patch Symbol so that you can sort them
+24eacb7 (#5466) Fixed puppet resource bug with trailing ,
+743e039 (#4922) Don't truncate remotely-sourced files on 404
+bb69011 (#6338) Remove unused version control tags
+e2a5085 Maint: Align tabs in a code block in the Augeas type.
+65a5496 (#6509) Inline docs: Fix erroneous code block in directoryservice provider for computer type
+ea9f1f0 Maint: Rewrite comments about symlinks to reflect best practice.
+94f8ead (#6509) Inline docs: Fix broken lists in Launchd provider.
+c80a77d (#6509) Inline docs: Fix broken code blocks in zpool type
+27863c3 (#6509) Inline docs: Fix code blocks in service type.
+f4034f7 (#6509) Inline docs: fix broken code blocks in schedule.rb.
+6f6c4b5 (#6509) Inline docs: Fix broken code block in file type (content attribute)
+a949a83 Revert "(#6309) Ensure the correct device is mounted when managing mounts"
+23a510a (#4914) Improved stubbing in mount/parsed_spec tests.
+ac2262d (#3999) Allow disabling of default SELinux context detection for files
+23eb77d (#6322) --noop should not suppress error codes
+439115e (#6499) Make puppet respond identically to -h and --help
+23b7119 Maint: Add an assertion mechanism to Puppet
+e3dfe41 (#6418) Recursive files shouldn't be audited
+0e9858f (#6407) Fix spec test hang with Mocha >= 0.9.11 in zlib testing
+309b932 (#5552) Display help when no subcommand is given.
+de6a205 (#5552) Clean up subcommand handling inside puppet cert.
+bb31c3d (#6376) Add test case for facts find request
+2ecf913 Revert "(#5935) Allow functions to accept negated values"
+c57c508 (#4914) Improved parsed_spec for mount
+ec33a09 (#4914) Remove mount specs
+e854205 Remove pending tests from parsed mount provider
+6cb365a (#6309) Ensure the correct device is mounted when managing mounts
+d1f1858 (#6376) Add support and testing for _search GET requests
+3b41d44 Clean up whitespace, and commented out code in parsed mount provider
+a7cebf8 (#6337) Fix Ruby warning on 1.8.6 about "future compatibility"
+8a48560 (#5150) Make fact REST terminus configurable to connect to inventory service
+e6870f6 (#5166) Inventory service is now searchable by timestamp.
+2d2f9ab Maint: backport timestamp accessor for facts from 2.7 branch
+fa0ed63 Refactored Puppet::Node::Inventory::Yaml tests in preparation for adding freshness check
+67f24e4 Refactor Puppet::Node::Inventory::Yaml in preparation for adding freshness
+23fc4db (#5132) Provide a query REST interface for inventory
+e3c59df (#5935) Allow functions to accept negated values
+7cb884e (#6346) Move the trap calls onto Signal so they're easier to stub
+b5bae9f (#6331) Remove final special :trac: link from the file content property
+4d25d90 (#6331) Inline documentation: Fix rotted links pointing at the Trac wiki
+b25d9e4 maint: make rspec exit with status 1 when there are failures
+5c26f68 (#5516) Rebuild parser.rb after merge.
+e512e3e (#5977) fix spec test failure when new applications are introduced.
+b5b5923 misc: ast_context has two arguments, not one.
+414e3a5 Fix #5516 - Hashes can't be used in selectors
+c373b62 Fix #6269 - Hashes only work with two levels of access
+9090507 Fix #6267 - puppetdoc embedded links to puppet entities are not hyperlinked
+b4a171e Fix #5720 - puppetdoc misses some class comments
+cfa0c32 Fix #6281 - Make sure puppetdoc analyzes all files
+48bc7d0 Fix #6280 - puppetdoc crashing on string interpolation
+0b7faa6 (#6270) Fix formatting in split function's doc string
+637e139 (#6270) Fix formatting in regsubst function's doc string
+e9ee621 (6130) Change header level on metaparameter reference
+d6e4ffe (#4914) Specs for mounted? match new behaviour
+f534470 (#4914) Add specs for modified mount provider
+b753038 (#4914) Add specs for modified mount type
+9f40608 (#4914) Update property blocks
+fd111f2 (#4914) Query property_hash for mountstate
+2884660 (#4914) Prefetch mountstate
+ade951a (#4914) Join lines for better readability
+8b98526 (#5662) Fixed tests that didnt stub key_attributes
+02b3111 (#5605) Prefetch doesnt work with composite keys
+2a0c970 (#5662) Parsedfile doesnt work with mult keyattr
+35dd070 (#5661) Creating types dont work with >1 namevar
+
+2.6.6
+=====
+d24e32a Update CHANGELOG and version for 2.6.6rc1
7c2a980 (#6541) Fix content with checksum truncation bug
63e911f (#6418) Recursive files shouldn't be audited
diff --git a/install.rb b/install.rb
index 72acb24f5..6854363ca 100755
--- a/install.rb
+++ b/install.rb
@@ -275,34 +275,29 @@ def prepare_installation
mandir = Config::CONFIG['mandir']
end
- # To be deprecated once people move over to using --destdir option
- if (destdir = ENV['DESTDIR'])
- configdir = "#{destdir}#{configdir}"
- bindir = "#{destdir}#{bindir}"
- sbindir = "#{destdir}#{sbindir}"
- mandir = "#{destdir}#{mandir}"
- sitelibdir = "#{destdir}#{sitelibdir}"
-
- FileUtils.makedirs(configdir) if InstallOptions.configs
- FileUtils.makedirs(bindir)
- FileUtils.makedirs(sbindir)
- FileUtils.makedirs(mandir)
- FileUtils.makedirs(sitelibdir)
# This is the new way forward
- elsif (destdir = InstallOptions.destdir)
- configdir = "#{destdir}#{configdir}"
- bindir = "#{destdir}#{bindir}"
- sbindir = "#{destdir}#{sbindir}"
- mandir = "#{destdir}#{mandir}"
- sitelibdir = "#{destdir}#{sitelibdir}"
-
- FileUtils.makedirs(configdir) if InstallOptions.configs
- FileUtils.makedirs(bindir)
- FileUtils.makedirs(sbindir)
- FileUtils.makedirs(mandir)
- FileUtils.makedirs(sitelibdir)
+ if not InstallOptions.destdir.nil?
+ destdir = InstallOptions.destdir
+ # To be deprecated once people move over to using --destdir option
+ elsif ENV['DESTDIR'] != nil?
+ destdir = ENV['DESTDIR']
+ warn "DESTDIR is deprecated. Use --destdir instead."
+ else
+ destdir = ''
end
+ configdir = "#{destdir}#{configdir}"
+ bindir = "#{destdir}#{bindir}"
+ sbindir = "#{destdir}#{sbindir}"
+ mandir = "#{destdir}#{mandir}"
+ sitelibdir = "#{destdir}#{sitelibdir}"
+
+ FileUtils.makedirs(configdir) if InstallOptions.configs
+ FileUtils.makedirs(bindir)
+ FileUtils.makedirs(sbindir)
+ FileUtils.makedirs(mandir)
+ FileUtils.makedirs(sitelibdir)
+
tmpdirs << bindir
InstallOptions.tmp_dirs = tmpdirs.compact
diff --git a/lib/puppet.rb b/lib/puppet.rb
index b13e06b9d..ef5fb7f06 100644
--- a/lib/puppet.rb
+++ b/lib/puppet.rb
@@ -24,7 +24,7 @@ require 'puppet/util/run_mode'
# it's also a place to find top-level commands like 'debug'
module Puppet
- PUPPETVERSION = '2.6.6'
+ PUPPETVERSION = '2.6.7'
def Puppet.version
PUPPETVERSION
diff --git a/lib/puppet/configurer/downloader.rb b/lib/puppet/configurer/downloader.rb
index 1b587ed4b..b3696201a 100644
--- a/lib/puppet/configurer/downloader.rb
+++ b/lib/puppet/configurer/downloader.rb
@@ -50,6 +50,7 @@ class Puppet::Configurer::Downloader
def catalog
catalog = Puppet::Resource::Catalog.new
+ catalog.host_config = false
catalog.add_resource(file)
catalog
end
diff --git a/lib/puppet/configurer/plugin_handler.rb b/lib/puppet/configurer/plugin_handler.rb
index cfc6b5a0b..ae088f26f 100644
--- a/lib/puppet/configurer/plugin_handler.rb
+++ b/lib/puppet/configurer/plugin_handler.rb
@@ -9,7 +9,14 @@ module Puppet::Configurer::PluginHandler
# Retrieve facts from the central server.
def download_plugins
return nil unless download_plugins?
- Puppet::Configurer::Downloader.new("plugin", Puppet[:plugindest], Puppet[:pluginsource], Puppet[:pluginsignore]).evaluate.each { |file| load_plugin(file) }
+ plugin_downloader = Puppet::Configurer::Downloader.new(
+ "plugin",
+ Puppet[:plugindest],
+ Puppet[:pluginsource],
+ Puppet[:pluginsignore]
+ )
+
+ plugin_downloader.evaluate.each { |file| load_plugin(file) }
end
def load_plugin(file)
diff --git a/lib/puppet/indirector/facts/inventory_active_record.rb b/lib/puppet/indirector/facts/inventory_active_record.rb
new file mode 100644
index 000000000..db4c63f00
--- /dev/null
+++ b/lib/puppet/indirector/facts/inventory_active_record.rb
@@ -0,0 +1,97 @@
+require 'puppet/rails'
+require 'puppet/rails/inventory_node'
+require 'puppet/rails/inventory_fact'
+require 'puppet/indirector/active_record'
+
+class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRecord
+ def find(request)
+ node = Puppet::Rails::InventoryNode.find_by_name(request.key)
+ return nil unless node
+ facts = Puppet::Node::Facts.new(node.name, node.facts_to_hash)
+ facts.timestamp = node.timestamp
+ facts
+ end
+
+ def save(request)
+ facts = request.instance
+ node = Puppet::Rails::InventoryNode.find_by_name(request.key) || Puppet::Rails::InventoryNode.create(:name => request.key, :timestamp => facts.timestamp)
+ node.timestamp = facts.timestamp
+
+ ActiveRecord::Base.transaction do
+ Puppet::Rails::InventoryFact.delete_all(:node_id => node.id)
+ # We don't want to save internal values as facts, because those are
+ # metadata that belong on the node
+ facts.values.each do |name,value|
+ next if name.to_s =~ /^_/
+ node.facts.build(:name => name, :value => value)
+ end
+ node.save
+ end
+ end
+
+ def search(request)
+ return [] unless request.options
+ matching_nodes = []
+ fact_names = []
+ fact_filters = Hash.new {|h,k| h[k] = []}
+ meta_filters = Hash.new {|h,k| h[k] = []}
+ request.options.each do |key,value|
+ type, name, operator = key.to_s.split(".")
+ operator ||= "eq"
+ if type == "facts"
+ fact_filters[operator] << [name,value]
+ elsif type == "meta" and name == "timestamp"
+ meta_filters[operator] << [name,value]
+ end
+ end
+
+ matching_nodes = nodes_matching_fact_filters(fact_filters) + nodes_matching_meta_filters(meta_filters)
+
+ # to_a because [].inject == nil
+ matching_nodes.inject {|nodes,this_set| nodes & this_set}.to_a.sort
+ end
+
+ private
+
+ def nodes_matching_fact_filters(fact_filters)
+ node_sets = []
+ fact_filters['eq'].each do |name,value|
+ node_sets << Puppet::Rails::InventoryNode.has_fact_with_value(name,value).map {|node| node.name}
+ end
+ fact_filters['ne'].each do |name,value|
+ node_sets << Puppet::Rails::InventoryNode.has_fact_without_value(name,value).map {|node| node.name}
+ end
+ {
+ 'gt' => '>',
+ 'lt' => '<',
+ 'ge' => '>=',
+ 'le' => '<='
+ }.each do |operator_name,operator|
+ fact_filters[operator_name].each do |name,value|
+ facts = Puppet::Rails::InventoryFact.find_by_sql(["SELECT inventory_facts.value, inventory_nodes.name AS node_name
+ FROM inventory_facts INNER JOIN inventory_nodes
+ ON inventory_facts.node_id = inventory_nodes.id
+ WHERE inventory_facts.name = ?", name])
+ node_sets << facts.select {|fact| fact.value.to_f.send(operator, value.to_f)}.map {|fact| fact.node_name}
+ end
+ end
+ node_sets
+ end
+
+ def nodes_matching_meta_filters(meta_filters)
+ node_sets = []
+ {
+ 'eq' => '=',
+ 'ne' => '!=',
+ 'gt' => '>',
+ 'lt' => '<',
+ 'ge' => '>=',
+ 'le' => '<='
+ }.each do |operator_name,operator|
+ meta_filters[operator_name].each do |name,value|
+ node_sets << Puppet::Rails::InventoryNode.find(:all, :select => "name", :conditions => ["timestamp #{operator} ?", value]).map {|node| node.name}
+ end
+ end
+ node_sets
+ end
+end
diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb
index 8da19c2ce..43266b2b5 100644
--- a/lib/puppet/module.rb
+++ b/lib/puppet/module.rb
@@ -191,7 +191,7 @@ class Puppet::Module
def backward_compatible_plugins_dir
if dir = File.join(path, "plugins") and FileTest.exist?(dir)
- warning "using the deprecated 'plugins' directory for ruby extensions; please move to 'lib'"
+ Puppet.warning "using the deprecated 'plugins' directory for ruby extensions; please move to 'lib'"
return dir
else
return File.join(path, "lib")
diff --git a/lib/puppet/network/rest_authconfig.rb b/lib/puppet/network/rest_authconfig.rb
index 9e3632499..cf76978fe 100644
--- a/lib/puppet/network/rest_authconfig.rb
+++ b/lib/puppet/network/rest_authconfig.rb
@@ -61,7 +61,7 @@ module Puppet
def insert_default_acl
DEFAULT_ACL.each do |acl|
unless rights[acl[:acl]]
- Puppet.info "Inserting default '#{acl[:acl]}'(#{acl[:authenticated] ? "auth" : "non-auth"}) acl because #{( !exists? ? "#{Puppet[:rest_authconfig]} doesn't exist" : "none where found in '#{@file}'")}"
+ Puppet.info "Inserting default '#{acl[:acl]}'(#{acl[:authenticated] ? "auth" : "non-auth"}) ACL because #{( !exists? ? "#{Puppet[:rest_authconfig]} doesn't exist" : "none were found in '#{@file}'")}"
mk_acl(acl)
end
end
diff --git a/lib/puppet/parser/ast/collection.rb b/lib/puppet/parser/ast/collection.rb
index ef36b7143..565b83195 100644
--- a/lib/puppet/parser/ast/collection.rb
+++ b/lib/puppet/parser/ast/collection.rb
@@ -16,6 +16,7 @@ class Puppet::Parser::AST
str, code = query && query.safeevaluate(scope)
resource_type = scope.find_resource_type(@type)
+ fail "Resource type #{@type} doesn't exist" unless resource_type
newcoll = Puppet::Parser::Collector.new(scope, resource_type.name, str, code, self.form)
scope.compiler.add_collection(newcoll)
@@ -26,10 +27,10 @@ class Puppet::Parser::AST
params = @override.collect { |param| param.safeevaluate(scope) }
newcoll.add_override(
:parameters => params,
- :file => @file,
- :line => @line,
- :source => scope.source,
- :scope => scope
+ :file => @file,
+ :line => @line,
+ :source => scope.source,
+ :scope => scope
)
end
diff --git a/lib/puppet/provider/mount/parsed.rb b/lib/puppet/provider/mount/parsed.rb
index 42e543c15..11c5e21a9 100755
--- a/lib/puppet/provider/mount/parsed.rb
+++ b/lib/puppet/provider/mount/parsed.rb
@@ -97,4 +97,10 @@ Puppet::Type.type(:mount).provide(
end
instances
end
+
+ def flush
+ needs_mount = @property_hash.delete(:needs_mount)
+ super
+ mount if needs_mount
+ end
end
diff --git a/lib/puppet/provider/parsedfile.rb b/lib/puppet/provider/parsedfile.rb
index ffd36e59f..75a215f4b 100755
--- a/lib/puppet/provider/parsedfile.rb
+++ b/lib/puppet/provider/parsedfile.rb
@@ -334,7 +334,9 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
@property_hash[:target] = @resource.should(:target) || self.class.default_target
self.class.modified(@property_hash[:target])
end
- @property_hash[:name] ||= @resource.name
+ @resource.class.key_attributes.each do |attr|
+ @property_hash[attr] ||= @resource[attr]
+ end
self.class.flush(@property_hash)
diff --git a/lib/puppet/provider/user/useradd.rb b/lib/puppet/provider/user/useradd.rb
index ba406cc63..b87971738 100644
--- a/lib/puppet/provider/user/useradd.rb
+++ b/lib/puppet/provider/user/useradd.rb
@@ -19,7 +19,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
value !~ /\s/
end
- has_features :manages_homedir, :allows_duplicates, :manages_expiry
+ has_features :manages_homedir, :allows_duplicates, :manages_expiry, :system_users
has_features :manages_passwords, :manages_password_age if Puppet.features.libshadow?
@@ -46,6 +46,10 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
cmd
end
+ def check_system_users
+ @resource.system? ? ["-r"] : []
+ end
+
def add_properties
cmd = []
Puppet::Type.type(:user).validproperties.each do |property|
@@ -66,6 +70,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
cmd += check_allow_dup
cmd += check_manage_home
cmd += check_manage_expiry
+ cmd += check_system_users
cmd << @resource[:name]
end
diff --git a/lib/puppet/rails/database/004_add_inventory_service_tables.rb b/lib/puppet/rails/database/004_add_inventory_service_tables.rb
new file mode 100644
index 000000000..6e6b28c0c
--- /dev/null
+++ b/lib/puppet/rails/database/004_add_inventory_service_tables.rb
@@ -0,0 +1,36 @@
+class AddInventoryServiceTables < ActiveRecord::Migration
+ def self.up
+ unless ActiveRecord::Base.connection.tables.include?("inventory_nodes")
+ create_table :inventory_nodes do |t|
+ t.column :name, :string, :null => false
+ t.column :timestamp, :datetime, :null => false
+ t.column :updated_at, :datetime
+ t.column :created_at, :datetime
+ end
+
+ add_index :inventory_nodes, :name, :unique => true
+ end
+
+ unless ActiveRecord::Base.connection.tables.include?("inventory_facts")
+ create_table :inventory_facts, :id => false do |t|
+ t.column :node_id, :integer, :null => false
+ t.column :name, :string, :null => false
+ t.column :value, :text, :null => false
+ end
+
+ add_index :inventory_facts, [:node_id, :name], :unique => true
+ end
+ end
+
+ def self.down
+ unless ActiveRecord::Base.connection.tables.include?("inventory_nodes")
+ remove_index :inventory_nodes, :name
+ drop_table :inventory_nodes
+ end
+
+ if ActiveRecord::Base.connection.tables.include?("inventory_facts")
+ remove_index :inventory_facts, [:node_id, :name]
+ drop_table :inventory_facts
+ end
+ end
+end
diff --git a/lib/puppet/rails/database/schema.rb b/lib/puppet/rails/database/schema.rb
index 8b389d773..7b75f4216 100644
--- a/lib/puppet/rails/database/schema.rb
+++ b/lib/puppet/rails/database/schema.rb
@@ -103,6 +103,23 @@ class Puppet::Rails::Schema
t.column :created_at, :datetime
end
add_index :param_names, :name
+
+ create_table :inventory_nodes do |t|
+ t.column :name, :string, :null => false
+ t.column :timestamp, :datetime, :null => false
+ t.column :updated_at, :datetime
+ t.column :created_at, :datetime
+ end
+
+ add_index :inventory_nodes, :name, :unique => true
+
+ create_table :inventory_facts, :id => false do |t|
+ t.column :node_id, :integer, :null => false
+ t.column :name, :string, :null => false
+ t.column :value, :text, :null => false
+ end
+
+ add_index :inventory_facts, [:node_id, :name], :unique => true
end
end
ensure
diff --git a/lib/puppet/rails/inventory_fact.rb b/lib/puppet/rails/inventory_fact.rb
new file mode 100644
index 000000000..aa6334eef
--- /dev/null
+++ b/lib/puppet/rails/inventory_fact.rb
@@ -0,0 +1,5 @@
+require 'puppet/rails/inventory_node'
+
+class Puppet::Rails::InventoryFact < ::ActiveRecord::Base
+ belongs_to :node, :class_name => "Puppet::Rails::InventoryNode"
+end
diff --git a/lib/puppet/rails/inventory_node.rb b/lib/puppet/rails/inventory_node.rb
new file mode 100644
index 000000000..52f8621a4
--- /dev/null
+++ b/lib/puppet/rails/inventory_node.rb
@@ -0,0 +1,25 @@
+require 'puppet/rails/inventory_fact'
+
+class Puppet::Rails::InventoryNode < ::ActiveRecord::Base
+ has_many :facts, :class_name => "Puppet::Rails::InventoryFact", :foreign_key => :node_id, :dependent => :delete_all
+
+ named_scope :has_fact_with_value, lambda { |name,value|
+ {
+ :conditions => ["inventory_facts.name = ? AND inventory_facts.value = ?", name, value],
+ :joins => :facts
+ }
+ }
+
+ named_scope :has_fact_without_value, lambda { |name,value|
+ {
+ :conditions => ["inventory_facts.name = ? AND inventory_facts.value != ?", name, value],
+ :joins => :facts
+ }
+ }
+
+ def facts_to_hash
+ facts.inject({}) do |fact_hash,fact|
+ fact_hash.merge(fact.name => fact.value)
+ end
+ end
+end
diff --git a/lib/puppet/reports/store.rb b/lib/puppet/reports/store.rb
index 99a9fc177..625a263b3 100644
--- a/lib/puppet/reports/store.rb
+++ b/lib/puppet/reports/store.rb
@@ -15,7 +15,10 @@ Puppet::Reports.register_report(:store) do
dir = File.join(Puppet[:reportdir], client)
- Dir.mkdir(dir, 0750) unless FileTest.exists?(dir)
+ if ! FileTest.exists?(dir)
+ FileUtils.mkdir_p(dir)
+ FileUtils.chmod_R(0750, dir)
+ end
# Now store the report.
now = Time.now.gmtime
diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb
index a71675e11..214516908 100644
--- a/lib/puppet/resource.rb
+++ b/lib/puppet/resource.rb
@@ -5,6 +5,11 @@ require 'puppet/util/pson'
# The simplest resource class. Eventually it will function as the
# base class for all resource-like behaviour.
class Puppet::Resource
+ # This stub class is only needed for serialization compatibility with 0.25.x.
+ # Specifically, it exists to provide a compatibility API when using YAML
+ # serialized objects loaded from StoreConfigs.
+ Reference = Puppet::Resource
+
include Puppet::Util::Tagging
require 'puppet/resource/type_collection_helper'
@@ -87,7 +92,7 @@ class Puppet::Resource
def yaml_property_munge(x)
case x
when Hash
- x.inject({}) { |h,kv|
+ x.inject({}) { |h,kv|
k,v = kv
h[k] = self.class.value_to_pson_data(v)
h
@@ -104,7 +109,7 @@ class Puppet::Resource
# be overridden at some point, but this works for now.
%w{has_key? keys length delete empty? <<}.each do |method|
define_method(method) do |*args|
- @parameters.send(method, *args)
+ parameters.send(method, *args)
end
end
@@ -112,13 +117,13 @@ class Puppet::Resource
# to lower-case symbols.
def []=(param, value)
validate_parameter(param) if validate_parameters
- @parameters[parameter_name(param)] = value
+ parameters[parameter_name(param)] = value
end
# Return a given parameter's value. Converts all passed names
# to lower-case symbols.
def [](param)
- @parameters[parameter_name(param)]
+ parameters[parameter_name(param)]
end
def ==(other)
@@ -140,11 +145,11 @@ class Puppet::Resource
# Iterate over each param/value pair, as required for Enumerable.
def each
- @parameters.each { |p,v| yield p, v }
+ parameters.each { |p,v| yield p, v }
end
def include?(parameter)
- super || @parameters.keys.include?( parameter_name(parameter) )
+ super || parameters.keys.include?( parameter_name(parameter) )
end
# These two methods are extracted into a Helper
@@ -170,14 +175,6 @@ class Puppet::Resource
end
end
- # This stub class is only needed for serialization compatibility with 0.25.x
- class Reference
- attr_accessor :type,:title
- def initialize(type,title)
- @type,@title = type,title
- end
- end
-
# Create our resource.
def initialize(type, title = nil, attributes = {})
@parameters = {}
@@ -204,7 +201,7 @@ class Puppet::Resource
tag(self.type)
tag(self.title) if valid_tag?(self.title)
- @reference = Reference.new(@type,@title) # for serialization compatibility with 0.25.x
+ @reference = self # for serialization compatibility with 0.25.x
if strict? and ! resource_type
if @type == 'Class'
raise ArgumentError, "Could not find declared class #{title}"
@@ -234,7 +231,7 @@ class Puppet::Resource
# Produce a simple hash of our parameters.
def to_hash
- parse_title.merge @parameters
+ parse_title.merge parameters
end
def to_s
@@ -256,7 +253,7 @@ class Puppet::Resource
# Convert our resource to Puppet code.
def to_manifest
# Collect list of attributes to align => and move ensure first
- attr = @parameters.keys
+ attr = parameters.keys
attr_max = attr.inject(0) { |max,k| k.to_s.length > max ? k.to_s.length : max }
attr.sort!
@@ -266,7 +263,7 @@ class Puppet::Resource
end
attributes = attr.collect { |k|
- v = @parameters[k]
+ v = parameters[k]
if v.is_a? Array
" %-#{attr_max}s => %s,\n" % [ k, "[\'#{v.join("', '")}\']" ]
else
@@ -433,4 +430,10 @@ class Puppet::Resource
return { :name => title.to_s }
end
end
+
+ def parameters
+ # @parameters could have been loaded from YAML, causing it to be nil (by
+ # bypassing initialize).
+ @parameters ||= {}
+ end
end
diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb
index f70a3ec0b..d24cc8554 100644
--- a/lib/puppet/type.rb
+++ b/lib/puppet/type.rb
@@ -200,7 +200,7 @@ class Type
end
def uniqueness_key
- to_resource.uniqueness_key
+ self.class.key_attributes.sort_by { |attribute_name| attribute_name.to_s }.map{ |attribute_name| self[attribute_name] }
end
# Create a new parameter. Requires a block and a name, stores it in the
@@ -382,8 +382,8 @@ class Type
fail("Invalid parameter #{name}(#{name.inspect})") unless self.class.validattr?(name)
- if name == :name
- name = name_var
+ if name == :name && nv = name_var
+ name = nv
end
if obj = @parameters[name]
@@ -403,8 +403,8 @@ class Type
fail("Invalid parameter #{name}") unless self.class.validattr?(name)
- if name == :name
- name = name_var
+ if name == :name && nv = name_var
+ name = nv
end
raise Puppet::Error.new("Got nil value for #{name}") if value.nil?
diff --git a/lib/puppet/type/computer.rb b/lib/puppet/type/computer.rb
index 89a0692bf..7a2c52d53 100644
--- a/lib/puppet/type/computer.rb
+++ b/lib/puppet/type/computer.rb
@@ -14,7 +14,11 @@ Puppet::Type.newtype(:computer) do
type as per other platforms.
This type primarily exists to create localhost Computer objects that MCX
- policy can then be attached to."
+ policy can then be attached to.
+
+ **Autorequires:** If Puppet is managing the plist file representing a
+ Computer object (located at `/var/db/dslocal/nodes/Default/computers/{name}.plist`),
+ the Computer resource will autorequire it."
# ensurable
diff --git a/lib/puppet/type/exec.rb b/lib/puppet/type/exec.rb
index 033183ae7..ae579502a 100755
--- a/lib/puppet/type/exec.rb
+++ b/lib/puppet/type/exec.rb
@@ -22,7 +22,9 @@ module Puppet
to native Puppet types as quickly as possible. If you find that
you are doing a lot of work with `exec`, please at least notify
us at Puppet Labs what you are doing, and hopefully we can work with
- you to get a native resource type for the work you are doing."
+ you to get a native resource type for the work you are doing.
+
+ **Autorequires:** If Puppet is managing an exec's cwd or the executable file used in an exec's command, the exec resource will autorequire those files. If Puppet is managing the user that an exec should run as, the exec resource will autorequire that user."
require 'open3'
diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
index 963b9e5dd..16b1f962d 100644
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@ -22,7 +22,9 @@ Puppet::Type.newtype(:file) do
If you find that you are often copying files in from a central
location, rather than using native resources, please contact
Puppet Labs and we can hopefully work with you to develop a
- native resource to support what you are doing."
+ native resource to support what you are doing.
+
+ **Autorequires:** If Puppet is managing the user or group that owns a file, the file resource will autorequire them. If Puppet is managing any parent directories of a file, the file resource will autorequire them."
def self.title_patterns
[ [ /^(.*?)\/*\Z/m, [ [ :path, lambda{|x| x} ] ] ] ]
diff --git a/lib/puppet/type/macauthorization.rb b/lib/puppet/type/macauthorization.rb
index ef6fbb6c1..e89aa7c89 100644
--- a/lib/puppet/type/macauthorization.rb
+++ b/lib/puppet/type/macauthorization.rb
@@ -1,7 +1,10 @@
Puppet::Type.newtype(:macauthorization) do
@doc = "Manage the Mac OS X authorization database.
- See the [Apple developer site](http://developer.apple.com/documentation/Security/Conceptual/Security_Overview/Security_Services/chapter_4_section_5.html) for more information."
+ See the [Apple developer site](http://developer.apple.com/documentation/Security/Conceptual/Security_Overview/Security_Services/chapter_4_section_5.html) for more information.
+
+ **Autorequires:** If Puppet is managing the `/etc/authorization` file, each
+ macauthorization resource will autorequire it."
ensurable
diff --git a/lib/puppet/type/mcx.rb b/lib/puppet/type/mcx.rb
index 4f0a6c3c5..07c9348dd 100644
--- a/lib/puppet/type/mcx.rb
+++ b/lib/puppet/type/mcx.rb
@@ -27,8 +27,11 @@ content property of the file type in Puppet.
The recommended method of using this type is to use Work Group Manager
to manage users and groups on the local computer, record the resulting
-puppet manifest using the command 'ralsh mcx' then deploying this
+puppet manifest using the command `puppet resource mcx`, then deploy it
to other machines.
+
+**Autorequires:** If Puppet is managing the user, group, or computer that these
+MCX settings refer to, the MCX resource will autorequire that user, group, or computer.
"
feature :manages_content, \
"The provider can manage MCXSettings as a string.",
diff --git a/lib/puppet/type/mount.rb b/lib/puppet/type/mount.rb
index f0d5bcac4..5b8c5ca58 100755
--- a/lib/puppet/type/mount.rb
+++ b/lib/puppet/type/mount.rb
@@ -74,12 +74,13 @@ module Puppet
newvalue(:mounted, :event => :mount_mounted) do
# Create the mount point if it does not already exist.
current_value = self.retrieve
+ currently_mounted = provider.mounted?
provider.create if [nil, :absent, :ghost].include?(current_value)
syncothers
# The fs can be already mounted if it was absent but mounted
- provider.mount unless provider.mounted?
+ provider.property_hash[:needs_mount] = true unless currently_mounted
end
# insync: mounted -> present
@@ -225,7 +226,7 @@ module Puppet
def refresh
# Only remount if we're supposed to be mounted.
- provider.remount if self.should(:fstype) != "swap" and self.should(:ensure) == :mounted
+ provider.remount if self.should(:fstype) != "swap" and provider.mounted?
end
def value(name)
diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb
index d73d90dff..1222a5319 100644
--- a/lib/puppet/type/package.rb
+++ b/lib/puppet/type/package.rb
@@ -15,7 +15,11 @@ module Puppet
using based on the platform you are on, but you can override it
using the `provider` parameter; each provider defines what it
requires in order to function, and you must meet those requirements
- to use a given provider."
+ to use a given provider.
+
+ **Autorequires:** If Puppet is managing the files specified as a package's
+ `adminfile`, `responsefile`, or `source`, the package resource will autorequire
+ those files."
feature :installable, "The provider can install packages.",
:methods => [:install]
diff --git a/lib/puppet/type/selmodule.rb b/lib/puppet/type/selmodule.rb
index 60be8a855..e76c18cc0 100644
--- a/lib/puppet/type/selmodule.rb
+++ b/lib/puppet/type/selmodule.rb
@@ -5,7 +5,9 @@
Puppet::Type.newtype(:selmodule) do
@doc = "Manages loading and unloading of SELinux policy modules
on the system. Requires SELinux support. See man semodule(8)
- for more information on SELinux policy modules."
+ for more information on SELinux policy modules.
+
+ **Autorequires:** If Puppet is managing the file containing this SELinux policy module (which is either explicitly specified in the `selmodulepath` attribute or will be found at {`selmoduledir`}/{`name`}.pp), the selmodule resource will autorequire that file."
ensurable
diff --git a/lib/puppet/type/ssh_authorized_key.rb b/lib/puppet/type/ssh_authorized_key.rb
index e3320140e..8338e2d64 100644
--- a/lib/puppet/type/ssh_authorized_key.rb
+++ b/lib/puppet/type/ssh_authorized_key.rb
@@ -1,7 +1,11 @@
module Puppet
newtype(:ssh_authorized_key) do
@doc = "Manages SSH authorized keys. Currently only type 2 keys are
- supported."
+ supported.
+
+ **Autorequires:** If Puppet is managing the user account in which this
+ SSH key should be installed, the `ssh_authorized_key` resource will autorequire
+ that user."
ensurable
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index e7389a0d1..f74e4266f 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -12,7 +12,9 @@ module Puppet
This resource type uses the prescribed native tools for creating
groups and generally uses POSIX APIs for retrieving information
- about them. It does not directly modify `/etc/passwd` or anything."
+ about them. It does not directly modify `/etc/passwd` or anything.
+
+ **Autorequires:** If Puppet is managing the user's primary group (as provided in the `gid` attribute), the user resource will autorequire that group. If Puppet is managing any role accounts corresponding to the user's roles, the user resource will autorequire those role accounts."
feature :allows_duplicates,
"The provider supports duplicate users with the same UID."
@@ -34,6 +36,9 @@ module Puppet
feature :manages_expiry,
"The provider can manage the expiry date for a user."
+ feature :system_users,
+ "The provider allows you to create system users with lower UIDs."
+
newproperty(:ensure, :parent => Puppet::Property::Ensure) do
newvalue(:present, :event => :user_created) do
provider.create
@@ -230,6 +235,14 @@ module Puppet
defaultto :minimum
end
+ newparam(:system, :boolean => true) do
+ desc "Whether the user is a system user with lower UID."
+
+ newvalues(:true, :false)
+
+ defaultto false
+ end
+
newparam(:allowdupe, :boolean => true) do
desc "Whether to allow duplicate UIDs."
diff --git a/lib/puppet/type/zfs.rb b/lib/puppet/type/zfs.rb
index be18ab5aa..7123f8ac9 100755
--- a/lib/puppet/type/zfs.rb
+++ b/lib/puppet/type/zfs.rb
@@ -1,6 +1,8 @@
module Puppet
newtype(:zfs) do
- @doc = "Manage zfs. Create destroy and set properties on zfs instances."
+ @doc = "Manage zfs. Create destroy and set properties on zfs instances.
+
+**Autorequires:** If Puppet is managing the zpool at the root of this zfs instance, the zfs resource will autorequire it. If Puppet is managing any parent zfs instances, the zfs resource will autorequire them."
ensurable
diff --git a/lib/puppet/type/zone.rb b/lib/puppet/type/zone.rb
index c7c2aa143..1bae93120 100644
--- a/lib/puppet/type/zone.rb
+++ b/lib/puppet/type/zone.rb
@@ -1,5 +1,7 @@
Puppet::Type.newtype(:zone) do
- @doc = "Solaris zones."
+ @doc = "Solaris zones.
+
+**Autorequires:** If Puppet is managing the directory specified as the root of the zone's filesystem (with the `path` attribute), the zone resource will autorequire that directory."
# These properties modify the zone configuration, and they need to provide
# the text separately from syncing it, so all config statements can be rolled
diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index 850d147e2..d06f44808 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -4,6 +4,7 @@ require 'puppet/util/monkey_patches'
require 'sync'
require 'puppet/external/lock'
require 'monitor'
+require 'puppet/util/execution_stub'
module Puppet
# A command failed to execute.
@@ -264,6 +265,10 @@ module Util
arguments[:uid] = Puppet::Util::SUIDManager.convert_xid(:uid, arguments[:uid]) if arguments[:uid]
arguments[:gid] = Puppet::Util::SUIDManager.convert_xid(:gid, arguments[:gid]) if arguments[:gid]
+ if execution_stub = Puppet::Util::ExecutionStub.current_value
+ return execution_stub.call(command, arguments)
+ end
+
@@os ||= Facter.value(:operatingsystem)
output = nil
child_pid, child_status = nil
diff --git a/lib/puppet/util/execution.rb b/lib/puppet/util/execution.rb
index dd820f856..69f4f2c15 100644
--- a/lib/puppet/util/execution.rb
+++ b/lib/puppet/util/execution.rb
@@ -4,16 +4,15 @@ module Puppet::Util::Execution
# Run some code with a specific environment. Resets the environment back to
# what it was at the end of the code.
def withenv(hash)
- oldvals = {}
+ saved = ENV.to_hash
hash.each do |name, val|
- name = name.to_s
- oldvals[name] = ENV[name]
- ENV[name] = val
+ ENV[name.to_s] = val
end
yield
ensure
- oldvals.each do |name, val|
+ ENV.clear
+ saved.each do |name, val|
ENV[name] = val
end
end
diff --git a/lib/puppet/util/execution_stub.rb b/lib/puppet/util/execution_stub.rb
new file mode 100644
index 000000000..af74e0f72
--- /dev/null
+++ b/lib/puppet/util/execution_stub.rb
@@ -0,0 +1,26 @@
+module Puppet::Util
+ class ExecutionStub
+ class << self
+ # Set a stub block that Puppet::Util.execute() should invoke instead
+ # of actually executing commands on the target machine. Intended
+ # for spec testing.
+ #
+ # The arguments passed to the block are |command, options|, where
+ # command is an array of strings and options is an options hash.
+ def set(&block)
+ @value = block
+ end
+
+ # Uninstall any execution stub, so that calls to
+ # Puppet::Util.execute() behave normally again.
+ def reset
+ @value = nil
+ end
+
+ # Retrieve the current execution stub, or nil if there is no stub.
+ def current_value
+ @value
+ end
+ end
+ end
+end
diff --git a/lib/puppet/util/settings.rb b/lib/puppet/util/settings.rb
index 626ed20eb..f243b8691 100644
--- a/lib/puppet/util/settings.rb
+++ b/lib/puppet/util/settings.rb
@@ -91,7 +91,7 @@ class Puppet::Util::Settings
varname = $2 || $1
if varname == "environment" and environment
environment
- elsif pval = self.value(varname)
+ elsif pval = self.value(varname, environment)
pval
else
raise Puppet::DevError, "Could not find value for #{value}"
diff --git a/spec/integration/provider/mount_spec.rb b/spec/integration/provider/mount_spec.rb
new file mode 100644
index 000000000..d6f25fe1d
--- /dev/null
+++ b/spec/integration/provider/mount_spec.rb
@@ -0,0 +1,151 @@
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/file_bucket/dipper'
+
+describe "mount provider (integration)" do
+ include PuppetSpec::Files
+
+ def create_fake_fstab(initially_contains_entry)
+ File.open(@fake_fstab, 'w') do |f|
+ if initially_contains_entry
+ f.puts("/dev/disk1s1\t/Volumes/foo_disk\tmsdos\tlocal\t0\t0")
+ end
+ end
+ end
+
+ before :each do
+ @fake_fstab = tmpfile('fstab')
+ @current_options = "local"
+ @current_device = "/dev/disk1s1"
+ Puppet::Type.type(:mount).defaultprovider.stubs(:default_target).returns(@fake_fstab)
+ Facter.stubs(:value).with(:operatingsystem).returns('Darwin')
+ Puppet::Util::ExecutionStub.set do |command, options|
+ case command[0]
+ when %r{/s?bin/mount}
+ if command.length == 1
+ if @mounted
+ "#{@current_device} on /Volumes/foo_disk (msdos, #{@current_options})\n"
+ else
+ ''
+ end
+ else
+ command.length.should == 4
+ command[1].should == '-o'
+ command[3].should == '/Volumes/foo_disk'
+ @mounted.should == false # verify that we don't try to call "mount" redundantly
+ @current_options = command[2]
+ @current_device = check_fstab(true)
+ @mounted = true
+ ''
+ end
+ when %r{/s?bin/umount}
+ command.length.should == 2
+ command[1].should == '/Volumes/foo_disk'
+ @mounted.should == true # "umount" doesn't work when device not mounted (see #6632)
+ @mounted = false
+ ''
+ else
+ fail "Unexpected command #{command.inspect} executed"
+ end
+ end
+ end
+
+ after :each do
+ Puppet::Type::Mount::ProviderParsed.clear # Work around bug #6628
+ end
+
+ def check_fstab(expected_to_be_present)
+ # Verify that the fake fstab has the expected data in it
+ fstab_contents = File.read(@fake_fstab).lines.map(&:chomp).reject { |x| x =~ /^#|^$/ }
+ if expected_to_be_present
+ fstab_contents.length().should == 1
+ device, rest_of_line = fstab_contents[0].split(/\t/,2)
+ rest_of_line.should == "/Volumes/foo_disk\tmsdos\t#{@desired_options}\t0\t0"
+ device
+ else
+ fstab_contents.length().should == 0
+ nil
+ end
+ end
+
+ def run_in_catalog(settings)
+ resource = Puppet::Type.type(:mount).new(settings.merge(:name => "/Volumes/foo_disk",
+ :device => "/dev/disk1s1", :fstype => "msdos"))
+ Puppet::FileBucket::Dipper.any_instance.stubs(:backup) # Don't backup to the filebucket
+ resource.expects(:err).never
+ catalog = Puppet::Resource::Catalog.new
+ catalog.host_config = false # Stop Puppet from doing a bunch of magic
+ catalog.add_resource resource
+ catalog.apply
+ end
+
+ [false, true].each do |initial_state|
+ describe "When initially #{initial_state ? 'mounted' : 'unmounted'}" do
+ before :each do
+ @mounted = initial_state
+ end
+
+ [false, true].each do |initial_fstab_entry|
+ describe "When there is #{initial_fstab_entry ? 'an' : 'no'} initial fstab entry" do
+ before :each do
+ create_fake_fstab(initial_fstab_entry)
+ end
+
+ [:defined, :present, :mounted, :unmounted, :absent].each do |ensure_setting|
+ expected_final_state = case ensure_setting
+ when :mounted
+ true
+ when :unmounted, :absent
+ false
+ when :defined, :present
+ initial_state
+ else
+ fail "Unknown ensure_setting #{ensure_setting}"
+ end
+ expected_fstab_data = (ensure_setting != :absent)
+ describe "When setting ensure => #{ensure_setting}" do
+ ["local", "journaled"].each do |options_setting|
+ describe "When setting options => #{options_setting}" do
+ it "should leave the system in the #{expected_final_state ? 'mounted' : 'unmounted'} state, #{expected_fstab_data ? 'with' : 'without'} data in /etc/fstab" do
+ @desired_options = options_setting
+ run_in_catalog(:ensure=>ensure_setting, :options => options_setting)
+ @mounted.should == expected_final_state
+ if expected_fstab_data
+ check_fstab(expected_fstab_data).should == "/dev/disk1s1"
+ else
+ check_fstab(expected_fstab_data).should == nil
+ end
+ if @mounted
+ if ![:defined, :present].include?(ensure_setting)
+ @current_options.should == @desired_options
+ elsif initial_fstab_entry
+ @current_options.should == @desired_options
+ else
+ @current_options.should == 'local' #Workaround for #6645
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ describe "When the wrong device is mounted" do
+ it "should remount the correct device" do
+ pending "Due to bug 6309"
+ @mounted = true
+ @current_device = "/dev/disk2s2"
+ create_fake_fstab(true)
+ @desired_options = "local"
+ run_in_catalog(:ensure=>:mounted, :options=>'local')
+ @current_device.should=="/dev/disk1s1"
+ @mounted.should==true
+ @current_options.should=='local'
+ check_fstab(true).should == "/dev/disk1s1"
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index b23b3d97a..d7f546b0b 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -51,6 +51,7 @@ RSpec.configure do |config|
Puppet.settings.clear
Puppet::Node::Environment.clear
Puppet::Util::Storage.clear
+ Puppet::Util::ExecutionStub.reset
PuppetSpec::Files.cleanup
diff --git a/spec/unit/configurer/downloader_spec.rb b/spec/unit/configurer/downloader_spec.rb
index b2485ccc8..266a96b03 100755
--- a/spec/unit/configurer/downloader_spec.rb
+++ b/spec/unit/configurer/downloader_spec.rb
@@ -5,6 +5,8 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
require 'puppet/configurer/downloader'
describe Puppet::Configurer::Downloader do
+ require 'puppet_spec/files'
+ include PuppetSpec::Files
it "should require a name" do
lambda { Puppet::Configurer::Downloader.new }.should raise_error(ArgumentError)
end
@@ -96,25 +98,35 @@ describe Puppet::Configurer::Downloader do
describe "when creating the catalog to do the downloading" do
before do
- @dler = Puppet::Configurer::Downloader.new("foo", "path", "source")
+ @dler = Puppet::Configurer::Downloader.new("foo", "/download/path", "source")
end
it "should create a catalog and add the file to it" do
- file = mock 'file'
- catalog = mock 'catalog'
-
- @dler.expects(:file).returns file
-
- Puppet::Resource::Catalog.expects(:new).returns catalog
- catalog.expects(:add_resource).with(file)
+ catalog = @dler.catalog
+ catalog.resources.size.should == 1
+ catalog.resources.first.class.should == Puppet::Type::File
+ catalog.resources.first.name.should == "/download/path"
+ end
- @dler.catalog.should equal(catalog)
+ it "should specify that it is not managing a host catalog" do
+ @dler.catalog.host_config.should == false
end
+
end
describe "when downloading" do
before do
- @dler = Puppet::Configurer::Downloader.new("foo", "path", "source")
+ @dl_name = tmpfile("downloadpath")
+ source_name = tmpfile("source")
+ File.open(source_name, 'w') {|f| f.write('hola mundo') }
+ @dler = Puppet::Configurer::Downloader.new("foo", @dl_name, source_name)
+ end
+
+ it "should not skip downloaded resources when filtering on tags" do
+ Puppet[:tags] = 'maytag'
+ @dler.evaluate
+
+ File.exists?(@dl_name).should be_true
end
it "should log that it is downloading" do
diff --git a/spec/unit/indirector/facts/inventory_active_record_spec.rb b/spec/unit/indirector/facts/inventory_active_record_spec.rb
new file mode 100644
index 000000000..43b9fa397
--- /dev/null
+++ b/spec/unit/indirector/facts/inventory_active_record_spec.rb
@@ -0,0 +1,164 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'sqlite3' rescue nil
+require 'tempfile'
+require 'puppet/rails'
+
+describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.rails? and defined? SQLite3) do
+ let(:terminus) { Puppet::Node::Facts::InventoryActiveRecord.new }
+
+ before :all do
+ require 'puppet/indirector/facts/inventory_active_record'
+ @dbfile = Tempfile.new("testdb")
+ @dbfile.close
+ end
+
+ after :all do
+ Puppet::Node::Facts.indirection.reset_terminus_class
+ @dbfile.unlink
+ end
+
+ before :each do
+ Puppet::Node::Facts.indirection.terminus_class = :inventory_active_record
+ Puppet[:dbadapter] = 'sqlite3'
+ Puppet[:dblocation] = @dbfile.path
+ Puppet[:railslog] = "/dev/null"
+ Puppet::Rails.init
+ end
+
+ after :each do
+ Puppet::Rails.teardown
+ end
+
+ describe "#save" do
+ it "should use an existing node if possible" do
+ node = Puppet::Rails::InventoryNode.new(:name => "foo", :timestamp => Time.now)
+ node.save
+ facts = Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin")
+ Puppet::Node::Facts.indirection.save(facts)
+
+ Puppet::Rails::InventoryNode.count.should == 1
+ Puppet::Rails::InventoryNode.first.should == node
+ end
+
+ it "should create a new node if one can't be found" do
+ # This test isn't valid if there are nodes to begin with
+ Puppet::Rails::InventoryNode.count.should == 0
+
+ facts = Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin")
+ Puppet::Node::Facts.indirection.save(facts)
+
+ Puppet::Rails::InventoryNode.count.should == 1
+ Puppet::Rails::InventoryNode.first.name.should == "foo"
+ end
+
+ it "should save the facts" do
+ facts = Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin")
+ Puppet::Node::Facts.indirection.save(facts)
+
+ Puppet::Rails::InventoryFact.all.map{|f| [f.name,f.value]}.should =~ [["uptime_days","60"],["kernel","Darwin"]]
+ end
+
+ it "should remove the previous facts for an existing node" do
+ facts = Puppet::Node::Facts.new("foo", "uptime_days" => "30", "kernel" => "Darwin")
+ Puppet::Node::Facts.indirection.save(facts)
+ bar_facts = Puppet::Node::Facts.new("bar", "uptime_days" => "35", "kernel" => "Linux")
+ foo_facts = Puppet::Node::Facts.new("foo", "uptime_days" => "60", "is_virtual" => "false")
+ Puppet::Node::Facts.indirection.save(bar_facts)
+ Puppet::Node::Facts.indirection.save(foo_facts)
+
+ Puppet::Node::Facts.indirection.find("bar").should == bar_facts
+ Puppet::Node::Facts.indirection.find("foo").should == foo_facts
+ Puppet::Rails::InventoryFact.all.map{|f| [f.name,f.value]}.should_not include(["uptime_days", "30"], ["kernel", "Darwin"])
+ end
+ end
+
+ describe "#find" do
+ before do
+ @foo_facts = Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin")
+ @bar_facts = Puppet::Node::Facts.new("bar", "uptime_days" => "30", "kernel" => "Linux")
+ Puppet::Node::Facts.indirection.save(@foo_facts)
+ Puppet::Node::Facts.indirection.save(@bar_facts)
+ end
+
+ it "should identify facts by node name" do
+ Puppet::Node::Facts.indirection.find("foo").should == @foo_facts
+ end
+
+ it "should return nil if no node instance can be found" do
+ Puppet::Node::Facts.indirection.find("non-existent node").should == nil
+ end
+ end
+
+ describe "#search" do
+ def search_request(conditions)
+ Puppet::Indirector::Request.new(:facts, :search, nil, conditions)
+ end
+
+ before :each do
+ @now = Time.now
+ @foo = Puppet::Node::Facts.new("foo", "fact1" => "value1", "fact2" => "value2", "uptime_days" => "30")
+ @bar = Puppet::Node::Facts.new("bar", "fact1" => "value1", "uptime_days" => "60")
+ @baz = Puppet::Node::Facts.new("baz", "fact1" => "value2", "fact2" => "value1", "uptime_days" => "90")
+ @bat = Puppet::Node::Facts.new("bat")
+ @foo.timestamp = @now - 3600*1
+ @bar.timestamp = @now - 3600*3
+ @baz.timestamp = @now - 3600*5
+ @bat.timestamp = @now - 3600*7
+ [@foo, @bar, @baz, @bat].each {|facts| Puppet::Node::Facts.indirection.save(facts)}
+ end
+
+ it "should return node names that match 'equal' constraints" do
+ request = search_request('facts.fact1.eq' => 'value1',
+ 'facts.fact2.eq' => 'value2')
+ terminus.search(request).should == ["foo"]
+ end
+
+ it "should return node names that match 'not equal' constraints" do
+ request = search_request('facts.fact1.ne' => 'value2')
+ terminus.search(request).should == ["bar","foo"]
+ end
+
+ it "should return node names that match strict inequality constraints" do
+ request = search_request('facts.uptime_days.gt' => '20',
+ 'facts.uptime_days.lt' => '70')
+ terminus.search(request).should == ["bar","foo"]
+ end
+
+ it "should return node names that match non-strict inequality constraints" do
+ request = search_request('facts.uptime_days.ge' => '30',
+ 'facts.uptime_days.le' => '60')
+ terminus.search(request).should == ["bar","foo"]
+ end
+
+ it "should return node names whose facts are within a given timeframe" do
+ request = search_request('meta.timestamp.ge' => @now - 3600*5,
+ 'meta.timestamp.le' => @now - 3600*1)
+ terminus.search(request).should == ["bar","baz","foo"]
+ end
+
+ it "should return node names whose facts are from a specific time" do
+ request = search_request('meta.timestamp.eq' => @now - 3600*3)
+ terminus.search(request).should == ["bar"]
+ end
+
+ it "should return node names whose facts are not from a specific time" do
+ request = search_request('meta.timestamp.ne' => @now - 3600*1)
+ terminus.search(request).should == ["bar","bat","baz"]
+ end
+
+ it "should perform strict searches on nodes by timestamp" do
+ request = search_request('meta.timestamp.gt' => @now - 3600*5,
+ 'meta.timestamp.lt' => @now - 3600*1)
+ terminus.search(request).should == ["bar"]
+ end
+
+ it "should search nodes based on both facts and timestamp values" do
+ request = search_request('facts.uptime_days.gt' => '45',
+ 'meta.timestamp.lt' => @now - 3600*4)
+ terminus.search(request).should == ["baz"]
+ end
+ end
+end
+
diff --git a/spec/unit/module_spec.rb b/spec/unit/module_spec.rb
index 8f1c794b2..54f5444ee 100755
--- a/spec/unit/module_spec.rb
+++ b/spec/unit/module_spec.rb
@@ -367,9 +367,9 @@ describe Puppet::Module do
mod.stubs(:path).returns "/a/foo"
FileTest.expects(:exist?).with("/a/foo/plugins").returns true
- mod.expects(:warning)
-
mod.plugin_directory.should == "/a/foo/plugins"
+ @logs.first.message.should == "using the deprecated 'plugins' directory for ruby extensions; please move to 'lib'"
+ @logs.first.level.should == :warning
end
it "should default to 'lib' for the plugins directory" do
diff --git a/spec/unit/network/handler/fileserver_spec.rb b/spec/unit/network/handler/fileserver_spec.rb
index b1306c69e..014b82e69 100644
--- a/spec/unit/network/handler/fileserver_spec.rb
+++ b/spec/unit/network/handler/fileserver_spec.rb
@@ -158,7 +158,7 @@ describe Puppet::Network::Handler::FileServer do
end
it "should not fail for inexistant plugins type" do
- lambda { @mount.list("puppet/parser",true,false) }.should_not raise_error
+ @mount.list("puppet/parser",true,false)
end
end
diff --git a/spec/unit/parser/ast/collection_spec.rb b/spec/unit/parser/ast/collection_spec.rb
index a495bca15..99abc998d 100755
--- a/spec/unit/parser/ast/collection_spec.rb
+++ b/spec/unit/parser/ast/collection_spec.rb
@@ -4,20 +4,21 @@ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
describe Puppet::Parser::AST::Collection do
before :each do
- @scope = stub_everything 'scope'
- @mytype = stub_everything('mytype')
- @scope.stubs(:find_resource_type).returns @mytype
- @compiler = stub_everything 'compile'
- @scope.stubs(:compiler).returns(@compiler)
+ @mytype = Puppet::Resource::Type.new(:definition, "mytype")
+ @environment = Puppet::Node::Environment.new
+ @environment.known_resource_types.add @mytype
+
+ @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foonode", :environment => @environment))
+ @scope = Puppet::Parser::Scope.new(:compiler => @compiler)
@overrides = stub_everything 'overrides'
@overrides.stubs(:is_a?).with(Puppet::Parser::AST).returns(true)
-
end
it "should evaluate its query" do
query = mock 'query'
collection = Puppet::Parser::AST::Collection.new :query => query, :form => :virtual
+ collection.type = 'mytype'
query.expects(:safeevaluate).with(@scope)
@@ -26,8 +27,8 @@ describe Puppet::Parser::AST::Collection do
it "should instantiate a Collector for this type" do
collection = Puppet::Parser::AST::Collection.new :form => :virtual, :type => "test"
- @test_type = stub 'type', :name => 'test'
- @scope.expects(:find_resource_type).with('test').returns @test_type
+ @test_type = Puppet::Resource::Type.new(:definition, "test")
+ @environment.known_resource_types.add @test_type
Puppet::Parser::Collector.expects(:new).with(@scope, "test", nil, nil, :virtual)
@@ -35,7 +36,7 @@ describe Puppet::Parser::AST::Collection do
end
it "should tell the compiler about this collector" do
- collection = Puppet::Parser::AST::Collection.new :form => :virtual, :type => "test"
+ collection = Puppet::Parser::AST::Collection.new :form => :virtual, :type => "mytype"
Puppet::Parser::Collector.stubs(:new).returns("whatever")
@compiler.expects(:add_collection).with("whatever")
@@ -45,7 +46,7 @@ describe Puppet::Parser::AST::Collection do
it "should evaluate overriden paramaters" do
collector = stub_everything 'collector'
- collection = Puppet::Parser::AST::Collection.new :form => :virtual, :type => "test", :override => @overrides
+ collection = Puppet::Parser::AST::Collection.new :form => :virtual, :type => "mytype", :override => @overrides
Puppet::Parser::Collector.stubs(:new).returns(collector)
@overrides.expects(:safeevaluate).with(@scope)
@@ -55,7 +56,7 @@ describe Puppet::Parser::AST::Collection do
it "should tell the collector about overrides" do
collector = mock 'collector'
- collection = Puppet::Parser::AST::Collection.new :form => :virtual, :type => "test", :override => @overrides
+ collection = Puppet::Parser::AST::Collection.new :form => :virtual, :type => "mytype", :override => @overrides
Puppet::Parser::Collector.stubs(:new).returns(collector)
collector.expects(:add_override)
@@ -63,5 +64,8 @@ describe Puppet::Parser::AST::Collection do
collection.evaluate(@scope)
end
-
+ it "should fail when evaluating undefined resource types" do
+ collection = Puppet::Parser::AST::Collection.new :form => :virtual, :type => "bogus"
+ lambda { collection.evaluate(@scope) }.should raise_error "Resource type bogus doesn't exist"
+ end
end
diff --git a/spec/unit/parser/parser_spec.rb b/spec/unit/parser/parser_spec.rb
index 233de23c0..01cdcb976 100755
--- a/spec/unit/parser/parser_spec.rb
+++ b/spec/unit/parser/parser_spec.rb
@@ -264,7 +264,7 @@ describe Puppet::Parser do
before do
@lexer = stub 'lexer', :line => 50, :file => "/foo/bar", :getcomment => "whev"
@parser.stubs(:lexer).returns @lexer
- @class = stub 'class', :use_docs => false
+ @class = Puppet::Resource::Type.new(:hostclass, "myclass", :use_docs => false)
end
it "should return a new instance of the provided class created with the provided options" do
diff --git a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
index 7a1bd77f4..3ac57facc 100755
--- a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
+++ b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
@@ -86,6 +86,7 @@ describe provider_class do
before :each do
@resource = stub("resource", :name => "foo")
@resource.stubs(:[]).returns "foo"
+ @resource.class.stubs(:key_attributes).returns( [:name] )
@provider = provider_class.new(@resource)
provider_class.stubs(:filetype).returns(Puppet::Util::FileType::FileTypeRam)
diff --git a/spec/unit/provider/user/user_role_add_spec.rb b/spec/unit/provider/user/user_role_add_spec.rb
index 9cd0feb12..12a71d25a 100644
--- a/spec/unit/provider/user/user_role_add_spec.rb
+++ b/spec/unit/provider/user/user_role_add_spec.rb
@@ -115,6 +115,7 @@ describe provider_class do
describe "when allow duplicate is enabled" do
before do
@resource.expects(:allowdupe?).returns true
+ @resource.stubs(:system?)
@provider.stubs(:is_role?).returns(false)
@provider.stubs(:execute)
@provider.expects(:execute).with { |args| args.include?("-o") }
diff --git a/spec/unit/provider/user/useradd_spec.rb b/spec/unit/provider/user/useradd_spec.rb
index f9babe6aa..b1719eeaf 100755
--- a/spec/unit/provider/user/useradd_spec.rb
+++ b/spec/unit/provider/user/useradd_spec.rb
@@ -15,6 +15,7 @@ describe provider_class do
# #1360
it "should add -o when allowdupe is enabled and the user is being created" do
@resource.expects(:allowdupe?).returns true
+ @resource.expects(:system?).returns true
@provider.stubs(:execute)
@provider.expects(:execute).with { |args| args.include?("-o") }
@provider.create
@@ -27,6 +28,14 @@ describe provider_class do
@provider.uid = 150
end
+ it "should add -r when system is enabled" do
+ @resource.expects(:allowdupe?).returns true
+ @resource.expects(:system?).returns true
+ @provider.stubs(:execute)
+ @provider.expects(:execute).with { |args| args.include?("-r") }
+ @provider.create
+ end
+
it "should set password age rules" do
provider_class.has_feature :manages_password_age
@resource = Puppet::Type.type(:user).new :name => "myuser", :password_min_age => 5, :password_max_age => 10, :provider => :useradd
@@ -53,6 +62,23 @@ describe provider_class do
end
end
+ describe "when checking to add system users" do
+ it "should check system users" do
+ @resource.expects(:system?)
+ @provider.check_system_users
+ end
+
+ it "should return an array with a flag if it's a system user" do
+ @resource.stubs(:system?).returns true
+ @provider.check_system_users.must == ["-r"]
+ end
+
+ it "should return an empty array if it's not a system user" do
+ @resource.stubs(:system?).returns false
+ @provider.check_system_users.must == []
+ end
+ end
+
describe "when checking manage home" do
it "should check manage home" do
@resource.expects(:managehome?)
@@ -88,6 +114,7 @@ describe provider_class do
before do
@resource.stubs(:allowdupe?).returns true
@resource.stubs(:managehome?).returns true
+ @resource.stubs(:system?).returns true
end
it "should call command with :add" do
@@ -115,20 +142,32 @@ describe provider_class do
@provider.addcmd
end
+ it "should return an array with -r if system? is true" do
+ resource = Puppet::Type.type(:user).new( :name => "bob", :system => true)
+
+ provider_class.new( resource ).addcmd.should include("-r")
+ end
+
+ it "should return an array without -r if system? is false" do
+ resource = Puppet::Type.type(:user).new( :name => "bob", :system => false)
+
+ provider_class.new( resource ).addcmd.should_not include("-r")
+ end
+
it "should return an array with full command" do
@provider.stubs(:command).with(:add).returns("useradd")
@provider.stubs(:add_properties).returns(["-G", "somegroup"])
@resource.stubs(:[]).with(:name).returns("someuser")
@resource.stubs(:[]).with(:expiry).returns("somedate")
- @provider.addcmd.must == ["useradd", "-G", "somegroup", "-o", "-m", '-e somedate', "someuser"]
+ @provider.addcmd.must == ["useradd", "-G", "somegroup", "-o", "-m", '-e somedate', "-r", "someuser"]
end
- it "should return an array without -e if expery is undefined full command" do
+ it "should return an array without -e if expiry is undefined full command" do
@provider.stubs(:command).with(:add).returns("useradd")
@provider.stubs(:add_properties).returns(["-G", "somegroup"])
@resource.stubs(:[]).with(:name).returns("someuser")
@resource.stubs(:[]).with(:expiry).returns nil
- @provider.addcmd.must == ["useradd", "-G", "somegroup", "-o", "-m", "someuser"]
+ @provider.addcmd.must == ["useradd", "-G", "somegroup", "-o", "-m", "-r", "someuser"]
end
end
@@ -136,6 +175,7 @@ describe provider_class do
before do
@resource.stubs(:allowdupe?).returns true
@resource.stubs(:managehome?).returns true
+ @resource.stubs(:system?).returns true
end
it "should call command with :pass" do
diff --git a/spec/unit/reports/store_spec.rb b/spec/unit/reports/store_spec.rb
index 1acb5badd..9d9042386 100644
--- a/spec/unit/reports/store_spec.rb
+++ b/spec/unit/reports/store_spec.rb
@@ -11,7 +11,7 @@ describe processor do
describe "#process" do
include PuppetSpec::Files
before :each do
- Puppet[:reportdir] = tmpdir('reports')
+ Puppet[:reportdir] = tmpdir('reports') << '/reports'
@report = YAML.load_file(File.join(PuppetSpec::FIXTURE_DIR, 'yaml/report2.6.x.yaml')).extend processor
end
diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb
index e5146f332..916741d1a 100755
--- a/spec/unit/resource_spec.rb
+++ b/spec/unit/resource_spec.rb
@@ -463,6 +463,28 @@ describe Puppet::Resource do
end
end
+ describe "when loading 0.25.x storedconfigs YAML" do
+ before :each do
+ @old_storedconfig_yaml = %q{--- !ruby/object:Puppet::Resource::Reference
+builtin_type:
+title: /tmp/bar
+type: File
+}
+ end
+
+ it "should deserialize a Puppet::Resource::Reference without exceptions" do
+ lambda { YAML.load(@old_storedconfig_yaml) }.should_not raise_error
+ end
+
+ it "should deserialize as a Puppet::Resource::Reference as a Puppet::Resource" do
+ YAML.load(@old_storedconfig_yaml).class.should == Puppet::Resource
+ end
+
+ it "should to_hash properly" do
+ YAML.load(@old_storedconfig_yaml).to_hash.should == { :path => "/tmp/bar" }
+ end
+ end
+
describe "when converting to a RAL resource" do
it "should use the resource type's :new method to create the resource if the resource is of a builtin type" do
resource = Puppet::Resource.new("file", @basepath+"/my/file")
diff --git a/spec/unit/type/mount_spec.rb b/spec/unit/type/mount_spec.rb
index 333876cca..4638e9a2e 100755
--- a/spec/unit/type/mount_spec.rb
+++ b/spec/unit/type/mount_spec.rb
@@ -65,7 +65,8 @@ end
describe Puppet::Type.type(:mount)::Ensure do
before :each do
- @provider = stub 'provider', :class => Puppet::Type.type(:mount).defaultprovider, :clear => nil, :satisfies? => true, :name => :mock
+ provider_properties = {}
+ @provider = stub 'provider', :class => Puppet::Type.type(:mount).defaultprovider, :clear => nil, :satisfies? => true, :name => :mock, :property_hash => provider_properties
Puppet::Type.type(:mount).defaultprovider.stubs(:new).returns(@provider)
@mount = Puppet::Type.type(:mount).new(:name => "yay", :check => :ensure)
@@ -93,11 +94,12 @@ describe Puppet::Type.type(:mount)::Ensure do
@provider.stubs(:mounted?).returns([:mounted,:ghost].include? options[:from])
@provider.expects(:create).times(options[:create] || 0)
@provider.expects(:destroy).times(options[:destroy] || 0)
- @provider.expects(:mount).times(options[:mount] || 0)
+ @provider.expects(:mount).never
@provider.expects(:unmount).times(options[:unmount] || 0)
@ensure.stubs(:syncothers)
@ensure.should = options[:to]
@ensure.sync
+ (!!@provider.property_hash[:needs_mount]).should == (!!options[:mount])
end
it "should create itself when changing from :ghost to :present" do
@@ -230,48 +232,50 @@ describe Puppet::Type.type(:mount)::Ensure do
end
describe Puppet::Type.type(:mount), "when responding to refresh" do
+ pending "2.6.x specifies slightly different behavior and the desired behavior needs to be clarified and revisited. See ticket #4904" do
- it "should remount if it is supposed to be mounted" do
- @mount[:ensure] = "mounted"
- @provider.expects(:remount)
+ it "should remount if it is supposed to be mounted" do
+ @mount[:ensure] = "mounted"
+ @provider.expects(:remount)
- @mount.refresh
- end
+ @mount.refresh
+ end
- it "should not remount if it is supposed to be present" do
- @mount[:ensure] = "present"
- @provider.expects(:remount).never
+ it "should not remount if it is supposed to be present" do
+ @mount[:ensure] = "present"
+ @provider.expects(:remount).never
- @mount.refresh
- end
+ @mount.refresh
+ end
- it "should not remount if it is supposed to be absent" do
- @mount[:ensure] = "absent"
- @provider.expects(:remount).never
+ it "should not remount if it is supposed to be absent" do
+ @mount[:ensure] = "absent"
+ @provider.expects(:remount).never
- @mount.refresh
- end
+ @mount.refresh
+ end
- it "should not remount if it is supposed to be defined" do
- @mount[:ensure] = "defined"
- @provider.expects(:remount).never
+ it "should not remount if it is supposed to be defined" do
+ @mount[:ensure] = "defined"
+ @provider.expects(:remount).never
- @mount.refresh
- end
+ @mount.refresh
+ end
- it "should not remount if it is supposed to be unmounted" do
- @mount[:ensure] = "unmounted"
- @provider.expects(:remount).never
+ it "should not remount if it is supposed to be unmounted" do
+ @mount[:ensure] = "unmounted"
+ @provider.expects(:remount).never
- @mount.refresh
- end
+ @mount.refresh
+ end
- it "should not remount swap filesystems" do
- @mount[:ensure] = "mounted"
- @mount[:fstype] = "swap"
- @provider.expects(:remount).never
+ it "should not remount swap filesystems" do
+ @mount[:ensure] = "mounted"
+ @mount[:fstype] = "swap"
+ @provider.expects(:remount).never
- @mount.refresh
+ @mount.refresh
+ end
end
end
end
@@ -307,34 +311,6 @@ describe Puppet::Type.type(:mount), "when modifying an existing mount entry" do
@catalog.apply
end
- it "should flush changes before mounting" do
- syncorder = sequence('syncorder')
- @mount.provider.expects(:options).returns 'soft'
- @mount.provider.expects(:ensure).returns :unmounted
- @mount.provider.expects(:mounted?).returns false
-
- @mount.provider.expects(:options=).in_sequence(syncorder).with 'hard'
- @mount.expects(:flush).in_sequence(syncorder) # Have to write with no options
- @mount.provider.expects(:mount).in_sequence(syncorder)
- @mount.expects(:flush).in_sequence(syncorder) # Call flush again cause we changed everything
-
- @mount[:ensure] = :mounted
- @mount[:options] = 'hard'
-
- @catalog.apply
- end
-
- it "should not flush before mounting if there are no other changes" do
- syncorder = sequence('syncorder')
- @mount.provider.expects(:ensure).returns :unmounted
- @mount.provider.expects(:mounted?).returns false
- @mount.provider.expects(:mount).in_sequence(syncorder)
- @mount.expects(:flush).in_sequence(syncorder) # Call flush cause we changed everything
-
- @mount[:ensure] = :mounted
- @catalog.apply
- end
-
it "should umount before flushing changes to disk" do
syncorder = sequence('syncorder')
@mount.provider.expects(:options).returns 'soft'
diff --git a/spec/unit/type/user_spec.rb b/spec/unit/type/user_spec.rb
index 117c90f1c..6421e6049 100755
--- a/spec/unit/type/user_spec.rb
+++ b/spec/unit/type/user_spec.rb
@@ -43,6 +43,10 @@ describe user do
user.provider_feature(:manages_password_age).should_not be_nil
end
+ it "should have a system_users feature" do
+ user.provider_feature(:system_users).should_not be_nil
+ end
+
describe "instances" do
it "should have a valid provider" do
user.new(:name => "foo").provider.class.ancestors.should be_include(Puppet::Provider)
diff --git a/spec/unit/type_spec.rb b/spec/unit/type_spec.rb
index d1143d92e..f9372fced 100755
--- a/spec/unit/type_spec.rb
+++ b/spec/unit/type_spec.rb
@@ -434,7 +434,7 @@ describe Puppet::Type do
patterns.length.should == 1
patterns[0].length.should == 2
end
-
+
it "should have a regexp that captures the entire string" do
patterns = @type_class.title_patterns
string = "abc\n\tdef"
@@ -570,4 +570,15 @@ describe Puppet::Type.metaparamclass(:audit) do
@resource[:audit] = :noop
@resource.parameter(:noop).should be_nil
end
+
+ describe "when generating the uniqueness key" do
+ it "should include all of the key_attributes in alphabetical order by attribute name" do
+ Puppet::Type.type(:file).stubs(:key_attributes).returns [:path, :mode, :owner]
+ Puppet::Type.type(:file).stubs(:title_patterns).returns(
+ [ [ /(.*)/, [ [:path, lambda{|x| x} ] ] ] ]
+ )
+ res = Puppet::Type.type(:file).new( :title => '/my/file', :path => '/my/file', :owner => 'root', :content => 'hello' )
+ res.uniqueness_key.should == [ nil, 'root', '/my/file']
+ end
+ end
end
diff --git a/spec/unit/util/execution_spec.rb b/spec/unit/util/execution_spec.rb
new file mode 100644
index 000000000..312dd3b8e
--- /dev/null
+++ b/spec/unit/util/execution_spec.rb
@@ -0,0 +1,49 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Util::Execution do
+ include Puppet::Util::Execution
+ describe "#withenv" do
+ before :each do
+ @original_path = ENV["PATH"]
+ @new_env = {:PATH => "/some/bogus/path"}
+ end
+
+ it "should change environment variables within the block then reset environment variables to their original values" do
+ withenv @new_env do
+ ENV["PATH"].should == "/some/bogus/path"
+ end
+ ENV["PATH"].should == @original_path
+ end
+
+ it "should reset environment variables to their original values even if the block fails" do
+ begin
+ withenv @new_env do
+ ENV["PATH"].should == "/some/bogus/path"
+ raise "This is a failure"
+ end
+ rescue
+ end
+ ENV["PATH"].should == @original_path
+ end
+
+ it "should reset environment variables even when they are set twice" do
+ # Setting Path & Environment parameters in Exec type can cause weirdness
+ @new_env["PATH"] = "/someother/bogus/path"
+ withenv @new_env do
+ # When assigning duplicate keys, can't guarantee order of evaluation
+ ENV["PATH"].should =~ /\/some.*\/bogus\/path/
+ end
+ ENV["PATH"].should == @original_path
+ end
+
+ it "should remove any new environment variables after the block ends" do
+ @new_env[:FOO] = "bar"
+ withenv @new_env do
+ ENV["FOO"].should == "bar"
+ end
+ ENV["FOO"].should == nil
+ end
+ end
+end
diff --git a/spec/unit/util/execution_stub_spec.rb b/spec/unit/util/execution_stub_spec.rb
new file mode 100644
index 000000000..14cf9c67a
--- /dev/null
+++ b/spec/unit/util/execution_stub_spec.rb
@@ -0,0 +1,35 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Util::ExecutionStub do
+ it "should use the provided stub code when 'set' is called" do
+ Puppet::Util::ExecutionStub.set do |command, options|
+ command.should == ['/bin/foo', 'bar']
+ "stub output"
+ end
+ Puppet::Util::ExecutionStub.current_value.should_not == nil
+ Puppet::Util.execute(['/bin/foo', 'bar']).should == "stub output"
+ end
+
+ it "should automatically restore normal execution at the conclusion of each spec test" do
+ # Note: this test relies on the previous test creating a stub.
+ Puppet::Util::ExecutionStub.current_value.should == nil
+ end
+
+ it "should restore normal execution after 'reset' is called" do
+ true_command = Puppet::Util.which('true') # Note: "true" exists at different paths in different OSes
+ stub_call_count = 0
+ Puppet::Util::ExecutionStub.set do |command, options|
+ command.should == [true_command]
+ stub_call_count += 1
+ 'stub called'
+ end
+ Puppet::Util.execute([true_command]).should == 'stub called'
+ stub_call_count.should == 1
+ Puppet::Util::ExecutionStub.reset
+ Puppet::Util::ExecutionStub.current_value.should == nil
+ Puppet::Util.execute([true_command]).should == ''
+ stub_call_count.should == 1
+ end
+end
diff --git a/spec/unit/util/settings_spec.rb b/spec/unit/util/settings_spec.rb
index 732be6a08..2ab31c294 100755
--- a/spec/unit/util/settings_spec.rb
+++ b/spec/unit/util/settings_spec.rb
@@ -284,7 +284,8 @@ describe Puppet::Util::Settings do
@settings = Puppet::Util::Settings.new
@settings.setdefaults :section,
:config => ["/my/file", "a"],
- :one => ["ONE", "a"]
+ :one => ["ONE", "a"],
+ :two => ["TWO", "b"]
FileTest.stubs(:exist?).returns true
Puppet.stubs(:run_mode).returns stub('run_mode', :name => :mymode)
end
@@ -331,12 +332,20 @@ describe Puppet::Util::Settings do
@settings.value(:one, "env").should == "envval"
end
- it "should interpolate found values using the current environment" do
+ it 'should use the current environment for $environment' do
@settings.setdefaults :main, :myval => ["$environment/foo", "mydocs"]
@settings.value(:myval, "myenv").should == "myenv/foo"
end
+ it "should interpolate found values using the current environment" do
+ text = "[main]\none = mainval\n[myname]\none = nameval\ntwo = $one/two\n"
+ @settings.stubs(:read_file).returns(text)
+ @settings.parse
+
+ @settings.value(:two, "myname").should == "nameval/two"
+ end
+
it "should return values in a specified environment before values in the main or name sections" do
text = "[env]\none = envval\n[main]\none = mainval\n[myname]\none = nameval\n"
@settings.stubs(:read_file).returns(text)