From 35dd0702e9619706b6365a98da2826a612a4047a Mon Sep 17 00:00:00 2001 From: Stefan Schulte Date: Sun, 5 Dec 2010 11:30:42 +0100 Subject: (#5661) Creating types dont work with >1 namevar The methods [] and []= of type.rb are handling :name in a special way. When someone wants to access resource[:name] puppet tries to replace :name with the name_var. If the type has more than one key_attribute name_var is always returning false so we'll get the error Resource type does not support parameter false This patch doesnt try to substitute :name if we dont have a single namevar, aka. we have more than one key_attribute --- lib/puppet/type.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 1b6e7dcd7..cb1022ddf 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -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? -- cgit From 2a0c970b8f91c9687d3f2a1dea5adac44b5f96fb Mon Sep 17 00:00:00 2001 From: Stefan Schulte Date: Sun, 5 Dec 2010 16:25:06 +0100 Subject: (#5662) Parsedfile doesnt work with mult keyattr When one wants to use the parsedfile provider for a type with more than one key_attribute (e.g. a type for entries in /etc/services with name and protocol as key_attributes) the provider will not store all key_attributes in property_hash and not all keyattributes will be visible in the to_line function. The create method of parsedfile will only put validproperties into the propertyhash. As result :name and all the other key_attributes will not be set. In the flush method however the :name parameter is put in the property_hash but the method does not handle other keyattributes. This patch modifies flush to put all key_attributes into the property hash (Note: @resource.name is basically just an alias for @resource[:name]) --- lib/puppet/provider/parsedfile.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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) -- cgit From 02b311113df84646406737ccfad961c5b6df4ae8 Mon Sep 17 00:00:00 2001 From: Stefan Schulte Date: Thu, 23 Dec 2010 18:08:37 +0100 Subject: (#5605) Prefetch doesnt work with composite keys The uniqueness_key method of a type or resource object should return a key that can be used to identify this resource. In fact puppet seldomly uses this method and instead uses resource[:name] as an identifier. While this is totally fine for resourcetypes with a single key_attribute (and resource[:name] returning the namevar), it breaks things as soon as one creates a type with a composite key (prefetching for example is broken). To ease the process of replacing calls to resource[:name] to resource.uniqueness_key, the method uniqueness_key now just returns name_var if there is only one key_attribute (immitating self[:name]) and only returns an array of all the values of all the key_attributes if we have more than one key_attribute. The resourcehash which is passed to providers in their prefetch method is now build with uniqueness_key as the hashkey. Because of the new behaviour of uniqueness_key we hopefully wont break existing providers while allowing new providers for types with composite keys to implement correct prefetch methods. --- lib/puppet/resource.rb | 9 +++++++-- lib/puppet/transaction.rb | 2 +- lib/puppet/type.rb | 8 +++++++- spec/unit/resource_spec.rb | 11 +++++++++-- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb index 4f0d50750..a52796800 100644 --- a/lib/puppet/resource.rb +++ b/lib/puppet/resource.rb @@ -237,11 +237,16 @@ class Puppet::Resource h = self.to_hash h[namevar] ||= h[:name] h[:name] ||= h[namevar] - h.values_at(*key_attributes.sort_by { |k| k.to_s }) + # Simulate the same behaviour like Type#uniqueness_key + if key_attributes.size == 1 + h[namevar] + else + h.values_at(*key_attributes) + end end def key_attributes - return(resource_type.respond_to? :key_attributes) ? resource_type.key_attributes : [:name] + resource_type.respond_to?(:key_attributes) ? resource_type.key_attributes : [:name] end # Convert our resource to Puppet code. diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index dcd9aad0a..0bb98f827 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -252,7 +252,7 @@ class Puppet::Transaction @catalog.vertices.each do |resource| if provider = resource.provider and provider.class.respond_to?(:prefetch) prefetchers[provider.class] ||= {} - prefetchers[provider.class][resource.name] = resource + prefetchers[provider.class][resource.uniqueness_key] = resource end end diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 1b6e7dcd7..c50f8de50 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -200,7 +200,13 @@ class Type end def uniqueness_key - to_resource.uniqueness_key + # If we have only one namevar use that one (res.uniqueness_key behaves + # like res[:name] in that case). Otherwise use an array of all keyattributes + if name_var + self[:name] + else + @parameters.values_at(*self.class.key_attributes).collect {|p| p.value } + end end # Create a new parameter. Requires a block and a name, stores it in the diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index e65e8a13a..092ae8ce0 100755 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -268,7 +268,7 @@ describe Puppet::Resource do describe "when referring to a resource with name canonicalization" do it "should canonicalize its own name" do res = Puppet::Resource.new("file", "/path/") - res.uniqueness_key.should == ["/path"] + res.uniqueness_key.should == "/path" res.ref.should == "File[/path/]" end end @@ -770,7 +770,14 @@ describe Puppet::Resource do end describe "when generating the uniqueness key" do - it "should include all of the key_attributes in alphabetical order by attribute name" do + + it "should use namevar if there is only one key_attribute" do + Puppet::Type.type(:file).stubs(:key_attributes).returns [:path] + res = Puppet::Resource.new("file", "/my/file", :parameters => {:owner => 'root', :content => 'hello'}) + res.uniqueness_key.should == '/my/file' + end + + it "should include all of the key_attributes" do Puppet::Type.type(:file).stubs(:key_attributes).returns [:myvar, :owner, :path] Puppet::Type.type(:file).stubs(:title_patterns).returns( [ [ /(.*)/, [ [:path, lambda{|x| x} ] ] ] ] -- cgit From 8b98526b0f81d559fdf85fc8aaf370f75baa5919 Mon Sep 17 00:00:00 2001 From: Stefan Schulte Date: Thu, 23 Dec 2010 22:11:49 +0100 Subject: (#5662) Fixed tests that didnt stub key_attributes The parsedfile provider calls the method key_attributes of the resource class to decide what resourceparameters must be put in the property_hash. Tests that uses fake resources and only stub resource[:name] must also stub resource.class.key_attributes --- spec/unit/provider/mount/parsed_spec.rb | 1 + spec/unit/provider/ssh_authorized_key/parsed_spec.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/spec/unit/provider/mount/parsed_spec.rb b/spec/unit/provider/mount/parsed_spec.rb index 7d2e8a84c..3d37fc72e 100755 --- a/spec/unit/provider/mount/parsed_spec.rb +++ b/spec/unit/provider/mount/parsed_spec.rb @@ -51,6 +51,7 @@ module ParsedMountTesting #hash[:provider] = @provider_class.name fakeresource = stub :type => :mount, :name => hash[:name] + fakeresource.class.stubs(:key_attributes).returns([:name]) fakeresource.stubs(:[]).with(:name).returns(hash[:name]) fakeresource.stubs(:should).with(:target).returns(nil) diff --git a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb index 11e9233e0..2e5be165a 100755 --- a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +++ b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb @@ -104,6 +104,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) -- cgit From 7a00d6b4b7428145ab774f76c7433bda07c81f99 Mon Sep 17 00:00:00 2001 From: nfagerlund Date: Fri, 4 Mar 2011 17:46:25 -0800 Subject: (#6606) Inline docs: Document all autorequire relationships This patch appends **Autorequires:** notes to the @doc string of every type whose instances can autorequire other resources. This will put autorequire info right on the types reference where it can do the most good. --- lib/puppet/type/computer.rb | 6 +++++- lib/puppet/type/exec.rb | 4 +++- lib/puppet/type/file.rb | 4 +++- lib/puppet/type/macauthorization.rb | 5 ++++- lib/puppet/type/mcx.rb | 5 ++++- lib/puppet/type/package.rb | 6 +++++- lib/puppet/type/selmodule.rb | 4 +++- lib/puppet/type/ssh_authorized_key.rb | 6 +++++- lib/puppet/type/user.rb | 4 +++- lib/puppet/type/zfs.rb | 4 +++- lib/puppet/type/zone.rb | 4 +++- 11 files changed, 41 insertions(+), 11 deletions(-) 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 daa49e223..5ed2b104c 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 cbb51bbed..e1a4ecbb9 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/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..584d3adfc 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." diff --git a/lib/puppet/type/zfs.rb b/lib/puppet/type/zfs.rb index 1757931f8..6f04bddd8 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 408d6f5dd..471619c98 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 -- cgit From f4a0af16eaa30571662017cab7e106a96b99988d Mon Sep 17 00:00:00 2001 From: Elias Lutfallah Date: Sat, 5 Mar 2011 15:07:39 -0600 Subject: Refactoring duplicate code and logic in prep for DESTDIR deprecation. DESTDIR is slated to be deprecated. The block of code that checks for DESTDIR contained duplicate code as the block that checks for --destdir. The dupe code has been moved out of the destdir checks. I have also flipped the order of checking. Previously, if the DESTDIR env was set it would be used regardless of whether or not the --destdir flag was set. No env, no flag: ./install.rb destdir = nil Env only: DESTDIR="foo" ./install.rb destdir = foo Flag only: ./install.rb --destdir="bar" destdir = bar Both (uses flag): DESTDIR="foo" ./install.rb --destdir="bar" destdir = bar --- install.rb | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/install.rb b/install.rb index 7627a8d11..d20b7cda7 100755 --- a/install.rb +++ b/install.rb @@ -300,34 +300,28 @@ 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'] + 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 -- cgit From 1b1e803b4d2bf1e87b8796556439e3c0bada57ea Mon Sep 17 00:00:00 2001 From: Elias Lutfallah Date: Sat, 5 Mar 2011 15:23:06 -0600 Subject: (5724) Prep for deprecation of DESTDIR In preparation of deprecating the DESTDIR env variable, I've added a warning when the DESTDIR variable is being used. --- install.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/install.rb b/install.rb index d20b7cda7..e8755e07a 100755 --- a/install.rb +++ b/install.rb @@ -306,6 +306,7 @@ def prepare_installation # 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 -- cgit From 455a89129a6860215d8e79972f720eaa7564e625 Mon Sep 17 00:00:00 2001 From: Valdis Victor Vitayaudom Date: Sat, 5 Mar 2011 13:36:02 -0800 Subject: (#5794) create reports directory when creating host specific directory --- lib/puppet/reports/store.rb | 5 ++++- spec/unit/reports/store_spec.rb | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) 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/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 -- cgit From 23d1c0346a609369b457da876714c6671fcf3d44 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Thu, 24 Feb 2011 12:43:45 -0800 Subject: Maint: Added the ability to replace the behavior of Puppet::Util.execute with an arbitrary code block for ease in spec testing. Reviewed-by: Max Martin --- lib/puppet/util.rb | 5 +++++ lib/puppet/util/execution_stub.rb | 26 ++++++++++++++++++++++++++ spec/spec_helper.rb | 1 + spec/unit/util/execution_stub_spec.rb | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 lib/puppet/util/execution_stub.rb create mode 100644 spec/unit/util/execution_stub_spec.rb 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_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/spec/spec_helper.rb b/spec/spec_helper.rb index a374fb008..ae4edb2d9 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -34,6 +34,7 @@ RSpec.configure do |config| Puppet.settings.clear Puppet::Node::Environment.clear Puppet::Util::Storage.clear + Puppet::Util::ExecutionStub.reset if defined?($tmpfiles) $tmpfiles.each do |file| 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 -- cgit From 9d2fceb7141e4cc7a6215aa2529239eb2eb6c8fd Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Tue, 1 Mar 2011 14:06:42 -0800 Subject: Maint: Begin adding integration tests for the mount provider These tests form a starting point for integration testing the mount provider, using the new Puppet::Util::ExecutionStub mechanism to simulate the state of the machine in response to the execution of "mount" and "umount" commands. The tests currently work around some known bugs (6628, 6632, and 6633). Reviewed-by: Max Martin --- spec/integration/provider/mount_spec.rb | 93 +++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 spec/integration/provider/mount_spec.rb diff --git a/spec/integration/provider/mount_spec.rb b/spec/integration/provider/mount_spec.rb new file mode 100644 index 000000000..69a9eeb56 --- /dev/null +++ b/spec/integration/provider/mount_spec.rb @@ -0,0 +1,93 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/file_bucket/dipper' + +describe "mount provider (integration)" do + include PuppetSpec::Files + + before :each do + @fake_fstab = tmpfile('fstab') + File.open(@fake_fstab, 'w') do |f| + # leave file empty + end + 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 '/sbin/mount' + if command.length == 1 + if @mounted + "/dev/disk1s1 on /Volumes/foo_disk (msdos, local)\n" + else + '' + end + else + command.length.should == 4 + command[1].should == '-o' + command[2].should == 'local' + command[3].should == '/Volumes/foo_disk' + @mounted.should == false # verify that we don't try to call "mount" redundantly + check_fstab + @mounted = true + '' + end + when '/sbin/umount' + fail "unexpected umount" unless @umount_permitted + command.length.should == 2 + command[1].should == '/Volumes/foo_disk' + @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 + # Verify that the fake fstab has the expected data in it + File.read(@fake_fstab).lines.reject { |x| x =~ /^#/ }.should == ["/dev/disk1s1\t/Volumes/foo_disk\tmsdos\tlocal\t0\t0\n"] + end + + def run_in_catalog(ensure_setting) + resource = Puppet::Type.type(:mount).new(:name => "/Volumes/foo_disk", :ensure => ensure_setting, + :device => "/dev/disk1s1", :options => "local", :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 + + [:defined, :present].each do |ensure_setting| + describe "When setting ensure => #{ensure_setting}" do + it "should create an fstab entry if none exists" do + @mounted = false + @umount_permitted = false + run_in_catalog(ensure_setting) + @mounted.should == false + check_fstab + end + end + end + + it "should be able to create and mount a brand new mount point" do + @mounted = false + @umount_permitted = true # Work around bug #6632 + run_in_catalog(:mounted) + @mounted.should == true + check_fstab + end + + it "should be able to create an fstab entry for an already-mounted device" do + @mounted = true + @umount_permitted = true # Work around bug #6633 + run_in_catalog(:mounted) + @mounted.should == true + check_fstab + end +end -- cgit From bd5517dd9cd8e10f488713d9654957746e687378 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Mon, 7 Mar 2011 17:56:41 -0800 Subject: Adjust Darwin mount provider tests to pass on Linux mount, and umount are located under /bin, instead of /sbin on Linux, so we adjust the ExecutionStub to accept either location. Paired-with: Jacob Helwig --- spec/integration/provider/mount_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/integration/provider/mount_spec.rb b/spec/integration/provider/mount_spec.rb index 69a9eeb56..c28707dd9 100644 --- a/spec/integration/provider/mount_spec.rb +++ b/spec/integration/provider/mount_spec.rb @@ -14,7 +14,7 @@ describe "mount provider (integration)" do Facter.stubs(:value).with(:operatingsystem).returns('Darwin') Puppet::Util::ExecutionStub.set do |command, options| case command[0] - when '/sbin/mount' + when %r{/s?bin/mount} if command.length == 1 if @mounted "/dev/disk1s1 on /Volumes/foo_disk (msdos, local)\n" @@ -31,7 +31,7 @@ describe "mount provider (integration)" do @mounted = true '' end - when '/sbin/umount' + when %r{/s?bin/umount} fail "unexpected umount" unless @umount_permitted command.length.should == 2 command[1].should == '/Volumes/foo_disk' -- cgit From 5ef10315705b8e4d69d13b8df86b9585f2bcc29a Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Tue, 8 Mar 2011 11:35:58 -0800 Subject: (#6632) Adding a new mount no longer causes error with umount There were two problems: * In lib/puppet/type/mount.rb, we were calling provider.mounted? to determine whether we needed to execute "mount" after updating the in-memory fstab record. This wasn't working properly because provider.mounted? makes its decision based on the data stored in the in-memory fstab record. Since the fstab record had just been updated, provider.mounted? was incorrectly returning true even though the device wasn't actually mounted. Fixed this by checking provider.mounted? before updating the in-memory fstab record. * Calling mount from this point in lib/puppet/type/mount.rb is actually too early, because even though the in-memory fstab record has been created, its contents have not been written to `/etc/fstab` yet. Fixed this by storing a :needs_mount entry in the property_hash and checking it at the end of the flush() method. Reviewed-by: Jacob Helwig --- lib/puppet/provider/mount/parsed.rb | 6 ++++++ lib/puppet/type/mount.rb | 3 ++- spec/integration/provider/mount_spec.rb | 3 ++- spec/unit/type/mount_spec.rb | 34 ++++----------------------------- 4 files changed, 14 insertions(+), 32 deletions(-) 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/type/mount.rb b/lib/puppet/type/mount.rb index 98a1f2509..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 diff --git a/spec/integration/provider/mount_spec.rb b/spec/integration/provider/mount_spec.rb index c28707dd9..518b2956f 100644 --- a/spec/integration/provider/mount_spec.rb +++ b/spec/integration/provider/mount_spec.rb @@ -35,6 +35,7 @@ describe "mount provider (integration)" do fail "unexpected umount" unless @umount_permitted 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 @@ -77,7 +78,7 @@ describe "mount provider (integration)" do it "should be able to create and mount a brand new mount point" do @mounted = false - @umount_permitted = true # Work around bug #6632 + @umount_permitted = true # Work around bug #6633 run_in_catalog(:mounted) @mounted.should == true check_fstab diff --git a/spec/unit/type/mount_spec.rb b/spec/unit/type/mount_spec.rb index 7f9a0eba6..fdb67f7d5 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 @@ -285,34 +287,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' -- cgit From 92dffb29b50160e429b93f941054e5b74df8c598 Mon Sep 17 00:00:00 2001 From: Jacob Helwig Date: Sat, 5 Mar 2011 12:35:25 -0600 Subject: (#6513) Adjust P::U::Settings test name to reflect what it tests The 'should interpolate found values using the current environment' wasn't actually testing what it was describing, since the environment variable is special cased. Reviewed-by: Jesse Wolfe --- spec/unit/util/settings_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/unit/util/settings_spec.rb b/spec/unit/util/settings_spec.rb index 7bca44b76..3ed843b0b 100755 --- a/spec/unit/util/settings_spec.rb +++ b/spec/unit/util/settings_spec.rb @@ -331,7 +331,7 @@ 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" -- cgit From 64440e58967667426e7294ed38ad16e19812d8c4 Mon Sep 17 00:00:00 2001 From: Jacob Helwig Date: Sat, 5 Mar 2011 12:39:14 -0600 Subject: (#6513) Propagate the environment when doing variable lookup in settings For example with the following: test.conf: [master] rrddir = /var/lib/puppet/rrd templatedir = /var/lib/puppet/templates [env_a] templatedir = $rrddir/templates rrddir = /tmp/env_a/ The command: RUBYLIB=lib bin/puppet master --config ./test.conf --environment env_a --configprint templatedir originally produced '/var/lib/puppet/rrd/templates' instead of the expected '/tmp/env_a/templates' Reviewed-by: Jesse Wolfe --- lib/puppet/util/settings.rb | 2 +- spec/unit/util/settings_spec.rb | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) 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/unit/util/settings_spec.rb b/spec/unit/util/settings_spec.rb index 3ed843b0b..07b712c08 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 @@ -337,6 +338,14 @@ describe Puppet::Util::Settings do @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) -- cgit From 1ef83cb750896f997a347a144e20aa6c96daf171 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Tue, 8 Mar 2011 13:26:43 -0800 Subject: Added integration tests for the mount provider Paired-with: Max Martin --- spec/integration/provider/mount_spec.rb | 99 +++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 35 deletions(-) diff --git a/spec/integration/provider/mount_spec.rb b/spec/integration/provider/mount_spec.rb index 518b2956f..a62505d6d 100644 --- a/spec/integration/provider/mount_spec.rb +++ b/spec/integration/provider/mount_spec.rb @@ -5,11 +5,17 @@ require 'puppet/file_bucket/dipper' describe "mount provider (integration)" do include PuppetSpec::Files - before :each do - @fake_fstab = tmpfile('fstab') + def create_fake_fstab(initially_contains_entry) File.open(@fake_fstab, 'w') do |f| - # leave file empty + 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" 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| @@ -17,22 +23,21 @@ describe "mount provider (integration)" do when %r{/s?bin/mount} if command.length == 1 if @mounted - "/dev/disk1s1 on /Volumes/foo_disk (msdos, local)\n" + "/dev/disk1s1 on /Volumes/foo_disk (msdos, #{@current_options})\n" else '' end else command.length.should == 4 command[1].should == '-o' - command[2].should == 'local' command[3].should == '/Volumes/foo_disk' @mounted.should == false # verify that we don't try to call "mount" redundantly - check_fstab + @current_options = command[2] + check_fstab(true) @mounted = true '' end when %r{/s?bin/umount} - fail "unexpected umount" unless @umount_permitted command.length.should == 2 command[1].should == '/Volumes/foo_disk' @mounted.should == true # "umount" doesn't work when device not mounted (see #6632) @@ -48,14 +53,15 @@ describe "mount provider (integration)" do Puppet::Type::Mount::ProviderParsed.clear # Work around bug #6628 end - def check_fstab + def check_fstab(expected_to_be_present) # Verify that the fake fstab has the expected data in it - File.read(@fake_fstab).lines.reject { |x| x =~ /^#/ }.should == ["/dev/disk1s1\t/Volumes/foo_disk\tmsdos\tlocal\t0\t0\n"] + expected_data = expected_to_be_present ? ["/dev/disk1s1\t/Volumes/foo_disk\tmsdos\t#{@desired_options}\t0\t0"] : [] + File.read(@fake_fstab).lines.map(&:chomp).reject { |x| x =~ /^#|^$/ }.should == expected_data end - def run_in_catalog(ensure_setting) - resource = Puppet::Type.type(:mount).new(:name => "/Volumes/foo_disk", :ensure => ensure_setting, - :device => "/dev/disk1s1", :options => "local", :fstype => "msdos") + 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 @@ -64,31 +70,54 @@ describe "mount provider (integration)" do catalog.apply end - [:defined, :present].each do |ensure_setting| - describe "When setting ensure => #{ensure_setting}" do - it "should create an fstab entry if none exists" do - @mounted = false - @umount_permitted = false - run_in_catalog(ensure_setting) - @mounted.should == false - check_fstab + [false, true].each do |initial_state| + describe "When initially #{initial_state ? 'mounted' : 'unmounted'}" do + before :each do + @mounted = initial_state end - end - end - it "should be able to create and mount a brand new mount point" do - @mounted = false - @umount_permitted = true # Work around bug #6633 - run_in_catalog(:mounted) - @mounted.should == true - check_fstab - 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 - it "should be able to create an fstab entry for an already-mounted device" do - @mounted = true - @umount_permitted = true # Work around bug #6633 - run_in_catalog(:mounted) - @mounted.should == true - check_fstab + [: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 + check_fstab(expected_fstab_data) + 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 end -- cgit From 8ce30c83ddba87ba7e2622a46f27143159132789 Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Mon, 7 Mar 2011 15:19:20 -0800 Subject: (#6338) Add an InventoryActiveRecord terminus for Facts So far this terminus only supports find and save. Search is forthcoming. It uses two new tables (inventory_host and inventory_facts) so that it won't interact with storedconfigs. Paired-With: Jacob Helwig --- .../indirector/facts/inventory_active_record.rb | 33 ++++++++ .../database/004_add_inventory_service_tables.rb | 36 ++++++++ lib/puppet/rails/database/schema.rb | 17 ++++ lib/puppet/rails/inventory_fact.rb | 6 ++ lib/puppet/rails/inventory_host.rb | 11 +++ .../facts/inventory_active_record_spec.rb | 99 ++++++++++++++++++++++ 6 files changed, 202 insertions(+) create mode 100644 lib/puppet/indirector/facts/inventory_active_record.rb create mode 100644 lib/puppet/rails/database/004_add_inventory_service_tables.rb create mode 100644 lib/puppet/rails/inventory_fact.rb create mode 100644 lib/puppet/rails/inventory_host.rb create mode 100644 spec/unit/indirector/facts/inventory_active_record_spec.rb 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..6cd63ab1a --- /dev/null +++ b/lib/puppet/indirector/facts/inventory_active_record.rb @@ -0,0 +1,33 @@ +require 'puppet/rails/inventory_host' +require 'puppet/rails/inventory_fact' +require 'puppet/indirector/active_record' + +class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRecord + def find(request) + host = Puppet::Rails::InventoryHost.find_by_name(request.key) + return nil unless host + facts = Puppet::Node::Facts.new(host.name, host.facts_to_hash) + facts.timestamp = host.timestamp + facts.values.each do |key,value| + facts.values[key] = value.first if value.is_a?(Array) && value.length == 1 + end + facts + end + + def save(request) + facts = request.instance + host = Puppet::Rails::InventoryHost.find_by_name(request.key) || Puppet::Rails::InventoryHost.create(:name => request.key, :timestamp => facts.timestamp) + host.timestamp = facts.timestamp + + ActiveRecord::Base.transaction do + Puppet::Rails::InventoryFact.delete_all(:inventory_host_id => host.id) + # We don't want to save internal values as facts, because those are + # metadata that belong on the host + facts.values.each do |name,value| + next if name.to_s =~ /^_/ + host.facts.build(:name => name, :value => value) + end + host.save + end + end +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..22298437a --- /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_hosts") + create_table :inventory_hosts 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_hosts, :name, :unique => true + end + + unless ActiveRecord::Base.connection.tables.include?("inventory_facts") + create_table :inventory_facts, :id => false do |t| + t.column :inventory_host_id, :integer, :null => false + t.column :name, :string, :null => false + t.column :value, :text, :null => false + end + + add_index :inventory_facts, [:inventory_host_id, :name], :unique => true + end + end + + def self.down + unless ActiveRecord::Base.connection.tables.include?("inventory_hosts") + remove_index :inventory_hosts, :name + drop_table :inventory_hosts + end + + if ActiveRecord::Base.connection.tables.include?("inventory_facts") + remove_index :inventory_facts, [:inventory_host_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..5e455d6c0 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_hosts 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_hosts, :name, :unique => true + + create_table :inventory_facts, :id => false do |t| + t.column :inventory_host_id, :integer, :null => false + t.column :name, :string, :null => false + t.column :value, :text, :null => false + end + + add_index :inventory_facts, [:inventory_host_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..ecb6e41ee --- /dev/null +++ b/lib/puppet/rails/inventory_fact.rb @@ -0,0 +1,6 @@ +require 'puppet/rails/inventory_host' + +class Puppet::Rails::InventoryFact < ::ActiveRecord::Base + belongs_to :host, :class_name => "Puppet::Rails::InventoryHost" + serialize :value +end diff --git a/lib/puppet/rails/inventory_host.rb b/lib/puppet/rails/inventory_host.rb new file mode 100644 index 000000000..433e54389 --- /dev/null +++ b/lib/puppet/rails/inventory_host.rb @@ -0,0 +1,11 @@ +require 'puppet/rails/inventory_fact' + +class Puppet::Rails::InventoryHost < ::ActiveRecord::Base + has_many :facts, :class_name => "Puppet::Rails::InventoryFact", :dependent => :delete_all + + def facts_to_hash + facts.inject({}) do |fact_hash,fact| + fact_hash.merge(fact.name => fact.value) + end + end +end 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..b97bada19 --- /dev/null +++ b/spec/unit/indirector/facts/inventory_active_record_spec.rb @@ -0,0 +1,99 @@ +#!/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.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 host if possible" do + host = Puppet::Rails::InventoryHost.new(:name => "foo", :timestamp => Time.now) + host.save + Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin").save + + Puppet::Rails::InventoryHost.count.should == 1 + Puppet::Rails::InventoryHost.first.should == host + end + + it "should create a new host if one can't be found" do + # This test isn't valid if there are hosts to begin with + Puppet::Rails::InventoryHost.count.should == 0 + + Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin").save + + Puppet::Rails::InventoryHost.count.should == 1 + Puppet::Rails::InventoryHost.first.name.should == "foo" + end + + it "should save the facts" do + Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin").save + + 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 host" do + Puppet::Node::Facts.new("foo", "uptime_days" => "30", "kernel" => "Darwin").save + 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") + bar_facts.save + foo_facts.save + + Puppet::Node::Facts.find("bar").should == bar_facts + Puppet::Node::Facts.find("foo").should == foo_facts + Puppet::Rails::InventoryFact.all.map{|f| [f.name,f.value]}.should_not include(["uptime_days", "30"], ["kernel", "Darwin"]) + end + + it "should not replace the node's facts if something goes wrong" do + 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") + @foo_facts.save + @bar_facts.save + end + + it "should identify facts by host name" do + Puppet::Node::Facts.find("foo").should == @foo_facts + end + + it "should return nil if no host instance can be found" do + Puppet::Node::Facts.find("non-existent host").should == nil + end + + it "should convert all single-member arrays into non-arrays" do + Puppet::Node::Facts.new("array", "fact1" => ["value1"]).save + + Puppet::Node::Facts.find("array").values["fact1"].should == "value1" + end + end +end + -- cgit From f83636698229241b2ab35849437f3e515f6ac5c1 Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Mon, 7 Mar 2011 16:42:53 -0800 Subject: (#6338) Implement search for InventoryActiveRecord facts terminus Paired-With: Max Martin Reviewed-By: Jacob Helwig --- .../indirector/facts/inventory_active_record.rb | 34 ++++++++++++++ lib/puppet/rails/inventory_host.rb | 26 +++++++++++ .../facts/inventory_active_record_spec.rb | 52 ++++++++++++++++++++++ 3 files changed, 112 insertions(+) diff --git a/lib/puppet/indirector/facts/inventory_active_record.rb b/lib/puppet/indirector/facts/inventory_active_record.rb index 6cd63ab1a..30cb88ea0 100644 --- a/lib/puppet/indirector/facts/inventory_active_record.rb +++ b/lib/puppet/indirector/facts/inventory_active_record.rb @@ -30,4 +30,38 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec host.save end end + + def search(request) + return [] unless request.options + fact_names = [] + filters = Hash.new {|h,k| h[k] = []} + request.options.each do |key,value| + type, name, operator = key.to_s.split(".") + operator ||= "eq" + filters[operator] << [name,value] + end + + + host_sets = [] + filters['eq'].each do |name,value| + host_sets << Puppet::Rails::InventoryHost.has_fact_with_value(name,value).map {|host| host.name} + end + filters['ne'].each do |name,value| + host_sets << Puppet::Rails::InventoryHost.has_fact_without_value(name,value).map {|host| host.name} + end + { + 'gt' => '>', + 'lt' => '<', + 'ge' => '>=', + 'le' => '<=' + }.each do |operator_name,operator| + filters[operator_name].each do |name,value| + hosts_with_fact = Puppet::Rails::InventoryHost.has_fact(name) + host_sets << hosts_with_fact.select {|h| h.value_for(name).to_f.send(operator, value.to_f)}.map {|host| host.name} + end + end + + # to_a because [].inject == nil + host_sets.inject {|hosts,this_set| hosts & this_set}.to_a + end end diff --git a/lib/puppet/rails/inventory_host.rb b/lib/puppet/rails/inventory_host.rb index 433e54389..10dd62083 100644 --- a/lib/puppet/rails/inventory_host.rb +++ b/lib/puppet/rails/inventory_host.rb @@ -3,6 +3,32 @@ require 'puppet/rails/inventory_fact' class Puppet::Rails::InventoryHost < ::ActiveRecord::Base has_many :facts, :class_name => "Puppet::Rails::InventoryFact", :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 + } + } + + named_scope :has_fact, lambda { |name| + { + :conditions => ["inventory_facts.name = ?", name], + :joins => :facts + } + } + + def value_for(fact_name) + fact = facts.find_by_name(fact_name) + fact ? fact.value : nil + end + def facts_to_hash facts.inject({}) do |fact_hash,fact| fact_hash.merge(fact.name => fact.value) diff --git a/spec/unit/indirector/facts/inventory_active_record_spec.rb b/spec/unit/indirector/facts/inventory_active_record_spec.rb index b97bada19..7fb55561d 100644 --- a/spec/unit/indirector/facts/inventory_active_record_spec.rb +++ b/spec/unit/indirector/facts/inventory_active_record_spec.rb @@ -95,5 +95,57 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.r Puppet::Node::Facts.find("array").values["fact1"].should == "value1" end end + + describe "#search" do + + it "should return node names that match 'equal' constraints" do + Puppet::Node::Facts.new("foo", "fact1" => "value1", "fact2" => "value2", "fact3" => "value3").save + Puppet::Node::Facts.new("bar", "fact1" => "value2").save + Puppet::Node::Facts.new("baz", "fact1" => "value1", "fact2" => "value1", "fact3" => "value1").save + + request = Puppet::Indirector::Request.new(:facts, :search, nil, + {'facts.fact1.eq' => 'value1', + 'facts.fact2.eq' => 'value2', + 'facts.fact3.eq' => 'value3'}) + terminus.search(request).should =~ ["foo"] + end + + it "should return node names that match 'not equal' constraints" do + Puppet::Node::Facts.new("foo", "fact1" => "value1", "fact2" => "value2", "fact3" => "value3").save + Puppet::Node::Facts.new("bar", "fact1" => "value2").save + Puppet::Node::Facts.new("baz", "fact1" => "value1", "fact2" => "value1", "fact3" => "value1").save + Puppet::Node::Facts.new("bang", "fact1" => "value1", "fact2" => "value2", "fact3" => "value1").save + + request = Puppet::Indirector::Request.new(:facts, :search, nil, + {'facts.fact1.ne' => 'value3', + 'facts.fact2.ne' => 'value1', + 'facts.fact3.ne' => 'value2'}) + terminus.search(request).should =~ ["foo","bang"] + end + + it "should return node names that match strict inequality constraints" do + Puppet::Node::Facts.new("foo", "uptime_days" => "30").save + Puppet::Node::Facts.new("bar", "uptime_days" => "60").save + Puppet::Node::Facts.new("baz", "uptime_days" => "90").save + + request = Puppet::Indirector::Request.new(:facts, :search, nil, + {'facts.uptime_days.gt' => '20', + 'facts.uptime_days.lt' => '70'}) + + terminus.search(request).should =~ ["foo","bar"] + end + + it "should return node names that match non-strict inequality constraints" do + Puppet::Node::Facts.new("foo", "uptime_days" => "30").save + Puppet::Node::Facts.new("bar", "uptime_days" => "60").save + Puppet::Node::Facts.new("baz", "uptime_days" => "90").save + + request = Puppet::Indirector::Request.new(:facts, :search, nil, + {'facts.uptime_days.ge' => '30', + 'facts.uptime_days.le' => '60'}) + + terminus.search(request).should =~ ["foo","bar"] + end + end end -- cgit From 880d0c6cbd20758e02848d1fa61966402dc44dc0 Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Mon, 7 Mar 2011 17:28:43 -0800 Subject: (#6338) Support searching on metadata in InventoryActiveRecord terminus Timestamps are currently the only supported metadata for searching. Paired-With: Max Martin Reviewed-By: Jacob Helwig --- .../indirector/facts/inventory_active_record.rb | 42 ++++++++-- .../facts/inventory_active_record_spec.rb | 89 +++++++++++++--------- 2 files changed, 90 insertions(+), 41 deletions(-) diff --git a/lib/puppet/indirector/facts/inventory_active_record.rb b/lib/puppet/indirector/facts/inventory_active_record.rb index 30cb88ea0..5b8606839 100644 --- a/lib/puppet/indirector/facts/inventory_active_record.rb +++ b/lib/puppet/indirector/facts/inventory_active_record.rb @@ -34,19 +34,32 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec def search(request) return [] unless request.options fact_names = [] - filters = Hash.new {|h,k| h[k] = []} + 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" - filters[operator] << [name,value] + if type == "facts" + fact_filters[operator] << [name,value] + elsif type == "meta" and name == "timestamp" + meta_filters[operator] << [name,value] + end end + matching_hosts = hosts_matching_fact_filters(fact_filters) + hosts_matching_meta_filters(meta_filters) + + # to_a because [].inject == nil + matching_hosts.inject {|hosts,this_set| hosts & this_set}.to_a.sort + end + + private + def hosts_matching_fact_filters(fact_filters) host_sets = [] - filters['eq'].each do |name,value| + fact_filters['eq'].each do |name,value| host_sets << Puppet::Rails::InventoryHost.has_fact_with_value(name,value).map {|host| host.name} end - filters['ne'].each do |name,value| + fact_filters['ne'].each do |name,value| host_sets << Puppet::Rails::InventoryHost.has_fact_without_value(name,value).map {|host| host.name} end { @@ -55,13 +68,28 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec 'ge' => '>=', 'le' => '<=' }.each do |operator_name,operator| - filters[operator_name].each do |name,value| + fact_filters[operator_name].each do |name,value| hosts_with_fact = Puppet::Rails::InventoryHost.has_fact(name) host_sets << hosts_with_fact.select {|h| h.value_for(name).to_f.send(operator, value.to_f)}.map {|host| host.name} end end + host_sets + end - # to_a because [].inject == nil - host_sets.inject {|hosts,this_set| hosts & this_set}.to_a + def hosts_matching_meta_filters(meta_filters) + host_sets = [] + { + 'eq' => '=', + 'ne' => '!=', + 'gt' => '>', + 'lt' => '<', + 'ge' => '>=', + 'le' => '<=' + }.each do |operator_name,operator| + meta_filters[operator_name].each do |name,value| + host_sets << Puppet::Rails::InventoryHost.find(:all, :conditions => ["timestamp #{operator} ?", value]).map {|host| host.name} + end + end + host_sets end end diff --git a/spec/unit/indirector/facts/inventory_active_record_spec.rb b/spec/unit/indirector/facts/inventory_active_record_spec.rb index 7fb55561d..69d614023 100644 --- a/spec/unit/indirector/facts/inventory_active_record_spec.rb +++ b/spec/unit/indirector/facts/inventory_active_record_spec.rb @@ -97,54 +97,75 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.r end describe "#search" do + def search_request(conditions) + Puppet::Indirector::Request.new(:facts, :search, nil, conditions) + end - it "should return node names that match 'equal' constraints" do - Puppet::Node::Facts.new("foo", "fact1" => "value1", "fact2" => "value2", "fact3" => "value3").save - Puppet::Node::Facts.new("bar", "fact1" => "value2").save - Puppet::Node::Facts.new("baz", "fact1" => "value1", "fact2" => "value1", "fact3" => "value1").save + 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.save + @bar.save + @baz.save + @bat.save + end - request = Puppet::Indirector::Request.new(:facts, :search, nil, - {'facts.fact1.eq' => 'value1', - 'facts.fact2.eq' => 'value2', - 'facts.fact3.eq' => 'value3'}) - terminus.search(request).should =~ ["foo"] + 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 - Puppet::Node::Facts.new("foo", "fact1" => "value1", "fact2" => "value2", "fact3" => "value3").save - Puppet::Node::Facts.new("bar", "fact1" => "value2").save - Puppet::Node::Facts.new("baz", "fact1" => "value1", "fact2" => "value1", "fact3" => "value1").save - Puppet::Node::Facts.new("bang", "fact1" => "value1", "fact2" => "value2", "fact3" => "value1").save - - request = Puppet::Indirector::Request.new(:facts, :search, nil, - {'facts.fact1.ne' => 'value3', - 'facts.fact2.ne' => 'value1', - 'facts.fact3.ne' => 'value2'}) - terminus.search(request).should =~ ["foo","bang"] + 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 - Puppet::Node::Facts.new("foo", "uptime_days" => "30").save - Puppet::Node::Facts.new("bar", "uptime_days" => "60").save - Puppet::Node::Facts.new("baz", "uptime_days" => "90").save + request = search_request('facts.uptime_days.gt' => '20', + 'facts.uptime_days.lt' => '70') + terminus.search(request).should == ["bar","foo"] + end - request = Puppet::Indirector::Request.new(:facts, :search, nil, - {'facts.uptime_days.gt' => '20', - 'facts.uptime_days.lt' => '70'}) + 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 - terminus.search(request).should =~ ["foo","bar"] + 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 that match non-strict inequality constraints" do - Puppet::Node::Facts.new("foo", "uptime_days" => "30").save - Puppet::Node::Facts.new("bar", "uptime_days" => "60").save - Puppet::Node::Facts.new("baz", "uptime_days" => "90").save + 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 - request = Puppet::Indirector::Request.new(:facts, :search, nil, - {'facts.uptime_days.ge' => '30', - 'facts.uptime_days.le' => '60'}) + 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 - terminus.search(request).should =~ ["foo","bar"] + 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 -- cgit From 7764412aacb4132d40561e2ba47d52f5e333c16e Mon Sep 17 00:00:00 2001 From: Max Martin Date: Tue, 8 Mar 2011 16:20:53 -0800 Subject: maint:Refactor of mount provider integration tests When adding a test for #6309, decided to refactor mount provider integration tests by adding return value to check_fstab method. Paired-with:Paul Berry --- spec/integration/provider/mount_spec.rb | 38 ++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/spec/integration/provider/mount_spec.rb b/spec/integration/provider/mount_spec.rb index a62505d6d..d6f25fe1d 100644 --- a/spec/integration/provider/mount_spec.rb +++ b/spec/integration/provider/mount_spec.rb @@ -16,6 +16,7 @@ describe "mount provider (integration)" do 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| @@ -23,7 +24,7 @@ describe "mount provider (integration)" do when %r{/s?bin/mount} if command.length == 1 if @mounted - "/dev/disk1s1 on /Volumes/foo_disk (msdos, #{@current_options})\n" + "#{@current_device} on /Volumes/foo_disk (msdos, #{@current_options})\n" else '' end @@ -33,7 +34,7 @@ describe "mount provider (integration)" do command[3].should == '/Volumes/foo_disk' @mounted.should == false # verify that we don't try to call "mount" redundantly @current_options = command[2] - check_fstab(true) + @current_device = check_fstab(true) @mounted = true '' end @@ -55,8 +56,16 @@ describe "mount provider (integration)" do def check_fstab(expected_to_be_present) # Verify that the fake fstab has the expected data in it - expected_data = expected_to_be_present ? ["/dev/disk1s1\t/Volumes/foo_disk\tmsdos\t#{@desired_options}\t0\t0"] : [] - File.read(@fake_fstab).lines.map(&:chomp).reject { |x| x =~ /^#|^$/ }.should == expected_data + 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) @@ -101,7 +110,11 @@ describe "mount provider (integration)" do @desired_options = options_setting run_in_catalog(:ensure=>ensure_setting, :options => options_setting) @mounted.should == expected_final_state - check_fstab(expected_fstab_data) + 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 @@ -120,4 +133,19 @@ describe "mount provider (integration)" do 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 -- cgit From a3f2357215b15f318500d6637f393dad0d4a4181 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Tue, 8 Mar 2011 16:59:12 -0800 Subject: maint: Remove spec run noise There were some warnings and stack traces in the spec output that aren't necessary. The only interesting fix is of the message: lib/puppet/module.rb:79 warning: multiple values for a block parameter (0 for 1) from lib/puppet/util/logging.rb:30 If you call any form of logging on a module you end calling the file method on the module just because logging always checks for that method and calls it if it's defined, but in this case it's not defined in the way that logging expected so passes the wrong paramters. The easy solution is just to call logging on Puppet, which makes sense in this case anyway, and I don't think it's worth a separate ticket to deal with that logging warning. Reviewed-by: Nick Lewis --- lib/puppet/module.rb | 2 +- spec/unit/indirector/queue_spec.rb | 3 +++ spec/unit/module_spec.rb | 4 ++-- spec/unit/network/handler/fileserver_spec.rb | 2 +- spec/unit/parser/parser_spec.rb | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) 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/spec/unit/indirector/queue_spec.rb b/spec/unit/indirector/queue_spec.rb index 00463ee0f..bbe00c75f 100755 --- a/spec/unit/indirector/queue_spec.rb +++ b/spec/unit/indirector/queue_spec.rb @@ -114,6 +114,9 @@ describe Puppet::Indirector::Queue, :if => Puppet.features.pson? do @store_class.client.expects(:subscribe).yields("foo") @store_class.expects(:intern).raises ArgumentError Puppet.expects(:err) + + @store_class.expects(:puts) + @store_class.subscribe {|o| o } end end diff --git a/spec/unit/module_spec.rb b/spec/unit/module_spec.rb index 37dad7e25..0b4873f5f 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 b37d4f551..9d34e9cdd 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/parser_spec.rb b/spec/unit/parser/parser_spec.rb index 6cc393d91..2ed279fd9 100755 --- a/spec/unit/parser/parser_spec.rb +++ b/spec/unit/parser/parser_spec.rb @@ -259,7 +259,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 -- cgit From 4bd54939ceb4c588b1633117d88472fe48e9dfdf Mon Sep 17 00:00:00 2001 From: James Turnbull Date: Wed, 9 Mar 2011 17:56:37 +1100 Subject: Fixed #2645 - Added support for creating system users On Red Hat, Ubuntu, Debian and deriatives the -r flag allows creation of "system" users with a UID below that defined in /etc/login.defs. This commit adds support for a system parameter and a system_users feature which can be used like so: user { "foo": system => true, ensure => present, } This will create a user with a lower UID. The system parameter defaults to false. --- lib/puppet/provider/user/useradd.rb | 7 +++++- lib/puppet/type/user.rb | 11 ++++++++++ spec/unit/provider/user/useradd_spec.rb | 39 ++++++++++++++++++++++++++++++--- spec/unit/type/user_spec.rb | 4 ++++ 4 files changed, 57 insertions(+), 4 deletions(-) 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/type/user.rb b/lib/puppet/type/user.rb index e7389a0d1..dcba181fe 100755 --- a/lib/puppet/type/user.rb +++ b/lib/puppet/type/user.rb @@ -34,6 +34,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 +233,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/spec/unit/provider/user/useradd_spec.rb b/spec/unit/provider/user/useradd_spec.rb index 9ebba596c..81ad7d400 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 @@ -105,6 +132,11 @@ describe provider_class do @provider.addcmd end + it "should check and add if it's a system user" do + @provider.expects(:check_system_users).returns([]) + @provider.addcmd + end + it "should check and add if home is managed" do @provider.expects(:check_manage_home).returns([]) @provider.addcmd @@ -120,15 +152,15 @@ describe provider_class do @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 +168,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/type/user_spec.rb b/spec/unit/type/user_spec.rb index 297134446..5a84af443 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) -- cgit From 3489412a03fec009bc42222f449077e6f14998a4 Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Wed, 9 Mar 2011 12:55:03 -0800 Subject: maint: Rename InventoryHost to InventoryNode This had been conflating hosts and nodes, when nodes is the most accurate. --- .../indirector/facts/inventory_active_record.rb | 48 +++++++++++----------- .../database/004_add_inventory_service_tables.rb | 18 ++++---- lib/puppet/rails/database/schema.rb | 8 ++-- lib/puppet/rails/inventory_fact.rb | 4 +- lib/puppet/rails/inventory_host.rb | 37 ----------------- lib/puppet/rails/inventory_node.rb | 37 +++++++++++++++++ .../facts/inventory_active_record_spec.rb | 28 ++++++------- 7 files changed, 90 insertions(+), 90 deletions(-) delete mode 100644 lib/puppet/rails/inventory_host.rb create mode 100644 lib/puppet/rails/inventory_node.rb diff --git a/lib/puppet/indirector/facts/inventory_active_record.rb b/lib/puppet/indirector/facts/inventory_active_record.rb index 5b8606839..2c2597f81 100644 --- a/lib/puppet/indirector/facts/inventory_active_record.rb +++ b/lib/puppet/indirector/facts/inventory_active_record.rb @@ -1,13 +1,13 @@ -require 'puppet/rails/inventory_host' +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) - host = Puppet::Rails::InventoryHost.find_by_name(request.key) - return nil unless host - facts = Puppet::Node::Facts.new(host.name, host.facts_to_hash) - facts.timestamp = host.timestamp + 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.values.each do |key,value| facts.values[key] = value.first if value.is_a?(Array) && value.length == 1 end @@ -16,18 +16,18 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec def save(request) facts = request.instance - host = Puppet::Rails::InventoryHost.find_by_name(request.key) || Puppet::Rails::InventoryHost.create(:name => request.key, :timestamp => facts.timestamp) - host.timestamp = facts.timestamp + 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(:inventory_host_id => host.id) + Puppet::Rails::InventoryFact.delete_all(:inventory_node_id => node.id) # We don't want to save internal values as facts, because those are - # metadata that belong on the host + # metadata that belong on the node facts.values.each do |name,value| next if name.to_s =~ /^_/ - host.facts.build(:name => name, :value => value) + node.facts.build(:name => name, :value => value) end - host.save + node.save end end @@ -46,21 +46,21 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec end end - matching_hosts = hosts_matching_fact_filters(fact_filters) + hosts_matching_meta_filters(meta_filters) + matching_nodes = nodes_matching_fact_filters(fact_filters) + nodes_matching_meta_filters(meta_filters) # to_a because [].inject == nil - matching_hosts.inject {|hosts,this_set| hosts & this_set}.to_a.sort + matching_nodes.inject {|nodes,this_set| nodes & this_set}.to_a.sort end private - def hosts_matching_fact_filters(fact_filters) - host_sets = [] + def nodes_matching_fact_filters(fact_filters) + node_sets = [] fact_filters['eq'].each do |name,value| - host_sets << Puppet::Rails::InventoryHost.has_fact_with_value(name,value).map {|host| host.name} + node_sets << Puppet::Rails::InventoryNode.has_fact_with_value(name,value).map {|node| node.name} end fact_filters['ne'].each do |name,value| - host_sets << Puppet::Rails::InventoryHost.has_fact_without_value(name,value).map {|host| host.name} + node_sets << Puppet::Rails::InventoryNode.has_fact_without_value(name,value).map {|node| node.name} end { 'gt' => '>', @@ -69,15 +69,15 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec 'le' => '<=' }.each do |operator_name,operator| fact_filters[operator_name].each do |name,value| - hosts_with_fact = Puppet::Rails::InventoryHost.has_fact(name) - host_sets << hosts_with_fact.select {|h| h.value_for(name).to_f.send(operator, value.to_f)}.map {|host| host.name} + nodes_with_fact = Puppet::Rails::InventoryNode.has_fact(name) + node_sets << nodes_with_fact.select {|h| h.value_for(name).to_f.send(operator, value.to_f)}.map {|node| node.name} end end - host_sets + node_sets end - def hosts_matching_meta_filters(meta_filters) - host_sets = [] + def nodes_matching_meta_filters(meta_filters) + node_sets = [] { 'eq' => '=', 'ne' => '!=', @@ -87,9 +87,9 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec 'le' => '<=' }.each do |operator_name,operator| meta_filters[operator_name].each do |name,value| - host_sets << Puppet::Rails::InventoryHost.find(:all, :conditions => ["timestamp #{operator} ?", value]).map {|host| host.name} + node_sets << Puppet::Rails::InventoryNode.find(:all, :conditions => ["timestamp #{operator} ?", value]).map {|node| node.name} end end - host_sets + node_sets end 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 index 22298437a..a819cac1a 100644 --- a/lib/puppet/rails/database/004_add_inventory_service_tables.rb +++ b/lib/puppet/rails/database/004_add_inventory_service_tables.rb @@ -1,35 +1,35 @@ class AddInventoryServiceTables < ActiveRecord::Migration def self.up - unless ActiveRecord::Base.connection.tables.include?("inventory_hosts") - create_table :inventory_hosts do |t| + 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_hosts, :name, :unique => true + 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 :inventory_host_id, :integer, :null => false + t.column :inventory_node_id, :integer, :null => false t.column :name, :string, :null => false t.column :value, :text, :null => false end - add_index :inventory_facts, [:inventory_host_id, :name], :unique => true + add_index :inventory_facts, [:inventory_node_id, :name], :unique => true end end def self.down - unless ActiveRecord::Base.connection.tables.include?("inventory_hosts") - remove_index :inventory_hosts, :name - drop_table :inventory_hosts + 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, [:inventory_host_id, :name] + remove_index :inventory_facts, [:inventory_node_id, :name] drop_table :inventory_facts end end diff --git a/lib/puppet/rails/database/schema.rb b/lib/puppet/rails/database/schema.rb index 5e455d6c0..9fd640fe4 100644 --- a/lib/puppet/rails/database/schema.rb +++ b/lib/puppet/rails/database/schema.rb @@ -104,22 +104,22 @@ class Puppet::Rails::Schema end add_index :param_names, :name - create_table :inventory_hosts do |t| + 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_hosts, :name, :unique => true + add_index :inventory_nodes, :name, :unique => true create_table :inventory_facts, :id => false do |t| - t.column :inventory_host_id, :integer, :null => false + t.column :inventory_node_id, :integer, :null => false t.column :name, :string, :null => false t.column :value, :text, :null => false end - add_index :inventory_facts, [:inventory_host_id, :name], :unique => true + add_index :inventory_facts, [:inventory_node_id, :name], :unique => true end end ensure diff --git a/lib/puppet/rails/inventory_fact.rb b/lib/puppet/rails/inventory_fact.rb index ecb6e41ee..033943358 100644 --- a/lib/puppet/rails/inventory_fact.rb +++ b/lib/puppet/rails/inventory_fact.rb @@ -1,6 +1,6 @@ -require 'puppet/rails/inventory_host' +require 'puppet/rails/inventory_node' class Puppet::Rails::InventoryFact < ::ActiveRecord::Base - belongs_to :host, :class_name => "Puppet::Rails::InventoryHost" + belongs_to :node, :class_name => "Puppet::Rails::InventoryNode" serialize :value end diff --git a/lib/puppet/rails/inventory_host.rb b/lib/puppet/rails/inventory_host.rb deleted file mode 100644 index 10dd62083..000000000 --- a/lib/puppet/rails/inventory_host.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'puppet/rails/inventory_fact' - -class Puppet::Rails::InventoryHost < ::ActiveRecord::Base - has_many :facts, :class_name => "Puppet::Rails::InventoryFact", :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 - } - } - - named_scope :has_fact, lambda { |name| - { - :conditions => ["inventory_facts.name = ?", name], - :joins => :facts - } - } - - def value_for(fact_name) - fact = facts.find_by_name(fact_name) - fact ? fact.value : nil - end - - 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/rails/inventory_node.rb b/lib/puppet/rails/inventory_node.rb new file mode 100644 index 000000000..b3e321f94 --- /dev/null +++ b/lib/puppet/rails/inventory_node.rb @@ -0,0 +1,37 @@ +require 'puppet/rails/inventory_fact' + +class Puppet::Rails::InventoryNode < ::ActiveRecord::Base + has_many :facts, :class_name => "Puppet::Rails::InventoryFact", :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 + } + } + + named_scope :has_fact, lambda { |name| + { + :conditions => ["inventory_facts.name = ?", name], + :joins => :facts + } + } + + def value_for(fact_name) + fact = facts.find_by_name(fact_name) + fact ? fact.value : nil + end + + def facts_to_hash + facts.inject({}) do |fact_hash,fact| + fact_hash.merge(fact.name => fact.value) + end + end +end diff --git a/spec/unit/indirector/facts/inventory_active_record_spec.rb b/spec/unit/indirector/facts/inventory_active_record_spec.rb index 69d614023..ca16606b2 100644 --- a/spec/unit/indirector/facts/inventory_active_record_spec.rb +++ b/spec/unit/indirector/facts/inventory_active_record_spec.rb @@ -32,23 +32,23 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.r end describe "#save" do - it "should use an existing host if possible" do - host = Puppet::Rails::InventoryHost.new(:name => "foo", :timestamp => Time.now) - host.save + it "should use an existing node if possible" do + node = Puppet::Rails::InventoryNode.new(:name => "foo", :timestamp => Time.now) + node.save Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin").save - Puppet::Rails::InventoryHost.count.should == 1 - Puppet::Rails::InventoryHost.first.should == host + Puppet::Rails::InventoryNode.count.should == 1 + Puppet::Rails::InventoryNode.first.should == node end - it "should create a new host if one can't be found" do - # This test isn't valid if there are hosts to begin with - Puppet::Rails::InventoryHost.count.should == 0 + 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 Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin").save - Puppet::Rails::InventoryHost.count.should == 1 - Puppet::Rails::InventoryHost.first.name.should == "foo" + Puppet::Rails::InventoryNode.count.should == 1 + Puppet::Rails::InventoryNode.first.name.should == "foo" end it "should save the facts" do @@ -57,7 +57,7 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.r 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 host" do + it "should remove the previous facts for an existing node" do Puppet::Node::Facts.new("foo", "uptime_days" => "30", "kernel" => "Darwin").save 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") @@ -81,12 +81,12 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.r @bar_facts.save end - it "should identify facts by host name" do + it "should identify facts by node name" do Puppet::Node::Facts.find("foo").should == @foo_facts end - it "should return nil if no host instance can be found" do - Puppet::Node::Facts.find("non-existent host").should == nil + it "should return nil if no node instance can be found" do + Puppet::Node::Facts.find("non-existent node").should == nil end it "should convert all single-member arrays into non-arrays" do -- cgit From 531e25836e1313cd508ab8394e16cf438a62ac7b Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Wed, 9 Mar 2011 12:55:52 -0800 Subject: maint: Remove serialization of InventoryFact values This is not necessary because fact values are always strings, and it wasn't doing the unnecessary job it was expected to do anyway. --- lib/puppet/indirector/facts/inventory_active_record.rb | 3 --- lib/puppet/rails/inventory_fact.rb | 1 - spec/unit/indirector/facts/inventory_active_record_spec.rb | 6 ------ 3 files changed, 10 deletions(-) diff --git a/lib/puppet/indirector/facts/inventory_active_record.rb b/lib/puppet/indirector/facts/inventory_active_record.rb index 2c2597f81..89edaf332 100644 --- a/lib/puppet/indirector/facts/inventory_active_record.rb +++ b/lib/puppet/indirector/facts/inventory_active_record.rb @@ -8,9 +8,6 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec return nil unless node facts = Puppet::Node::Facts.new(node.name, node.facts_to_hash) facts.timestamp = node.timestamp - facts.values.each do |key,value| - facts.values[key] = value.first if value.is_a?(Array) && value.length == 1 - end facts end diff --git a/lib/puppet/rails/inventory_fact.rb b/lib/puppet/rails/inventory_fact.rb index 033943358..aa6334eef 100644 --- a/lib/puppet/rails/inventory_fact.rb +++ b/lib/puppet/rails/inventory_fact.rb @@ -2,5 +2,4 @@ require 'puppet/rails/inventory_node' class Puppet::Rails::InventoryFact < ::ActiveRecord::Base belongs_to :node, :class_name => "Puppet::Rails::InventoryNode" - serialize :value end diff --git a/spec/unit/indirector/facts/inventory_active_record_spec.rb b/spec/unit/indirector/facts/inventory_active_record_spec.rb index ca16606b2..c29e58400 100644 --- a/spec/unit/indirector/facts/inventory_active_record_spec.rb +++ b/spec/unit/indirector/facts/inventory_active_record_spec.rb @@ -88,12 +88,6 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.r it "should return nil if no node instance can be found" do Puppet::Node::Facts.find("non-existent node").should == nil end - - it "should convert all single-member arrays into non-arrays" do - Puppet::Node::Facts.new("array", "fact1" => ["value1"]).save - - Puppet::Node::Facts.find("array").values["fact1"].should == "value1" - end end describe "#search" do -- cgit From 86c60354da1d5a2a54baf6dbd92677a12701423d Mon Sep 17 00:00:00 2001 From: Jacob Helwig Date: Wed, 9 Mar 2011 14:35:19 -0800 Subject: Update CHANGELOG for 2.6.6 --- CHANGELOG | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index c08d7e72f..7f5ff355f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ -2.6.6rc1 +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 -- cgit From cd5deda8f9eefbe55c63c97c81293d01ca05c110 Mon Sep 17 00:00:00 2001 From: Jesse Wolfe Date: Wed, 9 Mar 2011 16:00:17 -0800 Subject: (#2645) Adding a less-stubby test to verify the "system" attribute's behavior Paired-with: Jacob Helwig --- spec/unit/provider/user/user_role_add_spec.rb | 1 + spec/unit/provider/user/useradd_spec.rb | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/spec/unit/provider/user/user_role_add_spec.rb b/spec/unit/provider/user/user_role_add_spec.rb index 9cf649267..f73942389 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 81ad7d400..fd75c43f3 100755 --- a/spec/unit/provider/user/useradd_spec.rb +++ b/spec/unit/provider/user/useradd_spec.rb @@ -132,11 +132,6 @@ describe provider_class do @provider.addcmd end - it "should check and add if it's a system user" do - @provider.expects(:check_system_users).returns([]) - @provider.addcmd - end - it "should check and add if home is managed" do @provider.expects(:check_manage_home).returns([]) @provider.addcmd @@ -147,6 +142,18 @@ 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"]) -- cgit From 285c4cc4b056b9c4990738c3d479d1a8993cf959 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Wed, 9 Mar 2011 16:17:17 -0800 Subject: (#5392) Give a better error when realizing a non-existant resource You can reproduce the error with a simple manifest Bogus_type <| title == 'foo' |> We used to fail because find_resource_type returned nil and we never checked if it was nil before calling methods on it. Reviewed-by: Max Martin --- lib/puppet/parser/ast/collection.rb | 9 +++++---- spec/unit/parser/ast/collection_spec.rb | 28 ++++++++++++++++------------ 2 files changed, 21 insertions(+), 16 deletions(-) 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/spec/unit/parser/ast/collection_spec.rb b/spec/unit/parser/ast/collection_spec.rb index 392a2c0f0..cc33075b7 100755 --- a/spec/unit/parser/ast/collection_spec.rb +++ b/spec/unit/parser/ast/collection_spec.rb @@ -4,20 +4,21 @@ require 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 -- cgit From 8858e40839bd693420ddc791df6b51de79356d2a Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Fri, 11 Mar 2011 15:22:23 -0800 Subject: (#6689) Make inventory_active_record terminus search quickly This terminus behaves the same on all supported DB platforms, by performing a limited portion of its query in SQL, and the rest of the comparison in Ruby. Its results are consistent with the YAML terminus. Paired-With: Jesse Wolfe --- lib/puppet/indirector/facts/inventory_active_record.rb | 14 ++++++++++---- .../rails/database/004_add_inventory_service_tables.rb | 6 +++--- lib/puppet/rails/database/schema.rb | 4 ++-- lib/puppet/rails/inventory_node.rb | 14 +------------- spec/unit/indirector/facts/inventory_active_record_spec.rb | 3 --- 5 files changed, 16 insertions(+), 25 deletions(-) diff --git a/lib/puppet/indirector/facts/inventory_active_record.rb b/lib/puppet/indirector/facts/inventory_active_record.rb index 89edaf332..5d130eae2 100644 --- a/lib/puppet/indirector/facts/inventory_active_record.rb +++ b/lib/puppet/indirector/facts/inventory_active_record.rb @@ -1,8 +1,10 @@ +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 + include Puppet::Util def find(request) node = Puppet::Rails::InventoryNode.find_by_name(request.key) return nil unless node @@ -17,7 +19,7 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec node.timestamp = facts.timestamp ActiveRecord::Base.transaction do - Puppet::Rails::InventoryFact.delete_all(:inventory_node_id => node.id) + 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| @@ -30,6 +32,7 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec 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] = []} @@ -66,8 +69,11 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec 'le' => '<=' }.each do |operator_name,operator| fact_filters[operator_name].each do |name,value| - nodes_with_fact = Puppet::Rails::InventoryNode.has_fact(name) - node_sets << nodes_with_fact.select {|h| h.value_for(name).to_f.send(operator, value.to_f)}.map {|node| node.name} + 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 @@ -84,7 +90,7 @@ class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRec 'le' => '<=' }.each do |operator_name,operator| meta_filters[operator_name].each do |name,value| - node_sets << Puppet::Rails::InventoryNode.find(:all, :conditions => ["timestamp #{operator} ?", value]).map {|node| node.name} + node_sets << Puppet::Rails::InventoryNode.find(:all, :select => "name", :conditions => ["timestamp #{operator} ?", value]).map {|node| node.name} end end node_sets diff --git a/lib/puppet/rails/database/004_add_inventory_service_tables.rb b/lib/puppet/rails/database/004_add_inventory_service_tables.rb index a819cac1a..6e6b28c0c 100644 --- a/lib/puppet/rails/database/004_add_inventory_service_tables.rb +++ b/lib/puppet/rails/database/004_add_inventory_service_tables.rb @@ -13,12 +13,12 @@ class AddInventoryServiceTables < ActiveRecord::Migration unless ActiveRecord::Base.connection.tables.include?("inventory_facts") create_table :inventory_facts, :id => false do |t| - t.column :inventory_node_id, :integer, :null => false + t.column :node_id, :integer, :null => false t.column :name, :string, :null => false t.column :value, :text, :null => false end - add_index :inventory_facts, [:inventory_node_id, :name], :unique => true + add_index :inventory_facts, [:node_id, :name], :unique => true end end @@ -29,7 +29,7 @@ class AddInventoryServiceTables < ActiveRecord::Migration end if ActiveRecord::Base.connection.tables.include?("inventory_facts") - remove_index :inventory_facts, [:inventory_node_id, :name] + remove_index :inventory_facts, [:node_id, :name] drop_table :inventory_facts end end diff --git a/lib/puppet/rails/database/schema.rb b/lib/puppet/rails/database/schema.rb index 9fd640fe4..7b75f4216 100644 --- a/lib/puppet/rails/database/schema.rb +++ b/lib/puppet/rails/database/schema.rb @@ -114,12 +114,12 @@ class Puppet::Rails::Schema add_index :inventory_nodes, :name, :unique => true create_table :inventory_facts, :id => false do |t| - t.column :inventory_node_id, :integer, :null => false + t.column :node_id, :integer, :null => false t.column :name, :string, :null => false t.column :value, :text, :null => false end - add_index :inventory_facts, [:inventory_node_id, :name], :unique => true + add_index :inventory_facts, [:node_id, :name], :unique => true end end ensure diff --git a/lib/puppet/rails/inventory_node.rb b/lib/puppet/rails/inventory_node.rb index b3e321f94..52f8621a4 100644 --- a/lib/puppet/rails/inventory_node.rb +++ b/lib/puppet/rails/inventory_node.rb @@ -1,7 +1,7 @@ require 'puppet/rails/inventory_fact' class Puppet::Rails::InventoryNode < ::ActiveRecord::Base - has_many :facts, :class_name => "Puppet::Rails::InventoryFact", :dependent => :delete_all + has_many :facts, :class_name => "Puppet::Rails::InventoryFact", :foreign_key => :node_id, :dependent => :delete_all named_scope :has_fact_with_value, lambda { |name,value| { @@ -17,18 +17,6 @@ class Puppet::Rails::InventoryNode < ::ActiveRecord::Base } } - named_scope :has_fact, lambda { |name| - { - :conditions => ["inventory_facts.name = ?", name], - :joins => :facts - } - } - - def value_for(fact_name) - fact = facts.find_by_name(fact_name) - fact ? fact.value : nil - end - def facts_to_hash facts.inject({}) do |fact_hash,fact| fact_hash.merge(fact.name => fact.value) diff --git a/spec/unit/indirector/facts/inventory_active_record_spec.rb b/spec/unit/indirector/facts/inventory_active_record_spec.rb index c29e58400..9558abde2 100644 --- a/spec/unit/indirector/facts/inventory_active_record_spec.rb +++ b/spec/unit/indirector/facts/inventory_active_record_spec.rb @@ -68,9 +68,6 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.r Puppet::Node::Facts.find("foo").should == foo_facts Puppet::Rails::InventoryFact.all.map{|f| [f.name,f.value]}.should_not include(["uptime_days", "30"], ["kernel", "Darwin"]) end - - it "should not replace the node's facts if something goes wrong" do - end end describe "#find" do -- cgit From 02626335b5e7fdbecf46639e4a4efe8e18ead982 Mon Sep 17 00:00:00 2001 From: nfagerlund Date: Mon, 14 Mar 2011 13:19:17 -0700 Subject: (#6707) Fix typo in rest_authconfig.rb "Where" -> "were." Capitalize "ACL." --- lib/puppet/network/rest_authconfig.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/puppet/network/rest_authconfig.rb b/lib/puppet/network/rest_authconfig.rb index 7a6147a82..e6067612a 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 -- cgit From ff9e2425a58bb2b1ab836e440c3344b4012623c5 Mon Sep 17 00:00:00 2001 From: Jacob Helwig Date: Fri, 25 Feb 2011 17:03:56 -0800 Subject: (#5428) More fully "stub" Puppet::Resource::Reference for use with storedconfigs The Puppet::Resource::Reference class wasn't stubbing enough of the 0.25.x behavior to satisfy the needs of storedconfigs. Since P::R::Reference, and Puppet::Resource were merged as part of 2.6.x, we can pretend that P::Resource is P::R::Reference for the purposes of loading data from storedconfigs. This should still satisfy the over-the-wire serialization needs of 0.25.x. This also changes internal references to @parameters in Puppet::Resource(::Reference) to go through a parameters method. This allows us to "initialize" this instance variable lazily, since loading via YAML bypasses the normal initialize method. Paired-with: Daniel Pittman Reviewed-by: Markus Roberts --- lib/puppet/resource.rb | 35 +++++++++++++++++++---------------- spec/unit/resource_spec.rb | 26 ++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb index e832804f5..e47fc7ecc 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' @@ -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 "%s { '%s':\n%s\n}" % [self.type.to_s.downcase, self.title, - @parameters.collect { |p, v| + parameters.collect { |p, v| if v.is_a? Array " #{p} => [\'#{v.join("','")}\']" else @@ -422,4 +419,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/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index ff31b2492..4c1dc4952 100755 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -99,11 +99,11 @@ describe Puppet::Resource do end it 'should fail if strict is set and type does not exist' do - lambda { Puppet::Resource.new('foo', 'title', {:strict=>true}) }.should raise_error(ArgumentError, 'Invalid resource type foo') + lambda { Puppet::Resource.new('foo', 'title', {:strict=>true}) }.should raise_error(ArgumentError, 'Invalid resource type foo') end it 'should fail if strict is set and class does not exist' do - lambda { Puppet::Resource.new('Class', 'foo', {:strict=>true}) }.should raise_error(ArgumentError, 'Could not find declared class foo') + lambda { Puppet::Resource.new('Class', 'foo', {:strict=>true}) }.should raise_error(ArgumentError, 'Could not find declared class foo') end it "should fail if the title is a hash and the type is not a valid resource reference string" do @@ -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") -- cgit From 4c1929952e7239f14aa1ab6a317d445a05d770c3 Mon Sep 17 00:00:00 2001 From: Jacob Helwig Date: Fri, 25 Feb 2011 18:11:47 -0800 Subject: Remove extra trailing whitespace from lib/puppet/resource.rb Paired-with: Daniel Pittman --- lib/puppet/resource.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb index e47fc7ecc..45ee2e990 100644 --- a/lib/puppet/resource.rb +++ b/lib/puppet/resource.rb @@ -92,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 -- cgit From 093f1627025a69f1c0a1b570139147e6fc843d2c Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Fri, 11 Mar 2011 16:36:07 -0800 Subject: (#6689) Remove extraneous include of Puppet::Util in InventoryActiveRecord This was added while developing in order to benchmark, but wasn't removed before committing. Reviewed-By: Jacob Helwig --- lib/puppet/indirector/facts/inventory_active_record.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/puppet/indirector/facts/inventory_active_record.rb b/lib/puppet/indirector/facts/inventory_active_record.rb index 5d130eae2..db4c63f00 100644 --- a/lib/puppet/indirector/facts/inventory_active_record.rb +++ b/lib/puppet/indirector/facts/inventory_active_record.rb @@ -4,7 +4,6 @@ require 'puppet/rails/inventory_fact' require 'puppet/indirector/active_record' class Puppet::Node::Facts::InventoryActiveRecord < Puppet::Indirector::ActiveRecord - include Puppet::Util def find(request) node = Puppet::Rails::InventoryNode.find_by_name(request.key) return nil unless node -- cgit From 25926d1922a9b75bc87ed7feed30693a69cdea9a Mon Sep 17 00:00:00 2001 From: Max Martin Date: Tue, 15 Mar 2011 15:52:37 -0700 Subject: (#6723) Fix withenv environment restoration bug Ensured that withenv properly restores the environment after it runs a block and added testing for the method. Reviewed-by: Matt Robinson and Daniel Pittman --- lib/puppet/util/execution.rb | 9 ++++---- spec/unit/util/execution_spec.rb | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 spec/unit/util/execution_spec.rb 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/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 -- cgit From 9781032736a34f577241828bcf812a648b4f42e9 Mon Sep 17 00:00:00 2001 From: Jesse Wolfe Date: Tue, 15 Mar 2011 17:28:52 -0700 Subject: Revert "Merge branch 'ticket/2.6.x/5605' of git://github.com/stschulte/puppet into 2.6.next" This reverts commit 658bdb72bee3ad664627a71793213e6540afd5cb, reversing changes made to 4c9bd43bc2f5fde9d86196e8689dced929d39aad. See comment at http://projects.puppetlabs.com/issues/5605#note-9 --- lib/puppet/resource.rb | 9 ++------- lib/puppet/transaction.rb | 2 +- lib/puppet/type.rb | 8 +------- spec/unit/resource_spec.rb | 11 ++--------- 4 files changed, 6 insertions(+), 24 deletions(-) diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb index 0f4e24cc4..214516908 100644 --- a/lib/puppet/resource.rb +++ b/lib/puppet/resource.rb @@ -243,16 +243,11 @@ class Puppet::Resource h = self.to_hash h[namevar] ||= h[:name] h[:name] ||= h[namevar] - # Simulate the same behaviour like Type#uniqueness_key - if key_attributes.size == 1 - h[namevar] - else - h.values_at(*key_attributes) - end + h.values_at(*key_attributes.sort_by { |k| k.to_s }) end def key_attributes - resource_type.respond_to?(:key_attributes) ? resource_type.key_attributes : [:name] + return(resource_type.respond_to? :key_attributes) ? resource_type.key_attributes : [:name] end # Convert our resource to Puppet code. diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index 6c816f130..aa650eea1 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -245,7 +245,7 @@ class Puppet::Transaction @catalog.vertices.each do |resource| if provider = resource.provider and provider.class.respond_to?(:prefetch) prefetchers[provider.class] ||= {} - prefetchers[provider.class][resource.uniqueness_key] = resource + prefetchers[provider.class][resource.name] = resource end end diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index c8d8688b0..205d809c1 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -200,13 +200,7 @@ class Type end def uniqueness_key - # If we have only one namevar use that one (res.uniqueness_key behaves - # like res[:name] in that case). Otherwise use an array of all keyattributes - if name_var - self[:name] - else - @parameters.values_at(*self.class.key_attributes).collect {|p| p.value } - end + to_resource.uniqueness_key end # Create a new parameter. Requires a block and a name, stores it in the diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index 6f94409ab..345ccd06e 100755 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -276,7 +276,7 @@ describe Puppet::Resource do describe "when referring to a resource with name canonicalization" do it "should canonicalize its own name" do res = Puppet::Resource.new("file", "/path/") - res.uniqueness_key.should == "/path" + res.uniqueness_key.should == ["/path"] res.ref.should == "File[/path/]" end end @@ -800,14 +800,7 @@ type: File end describe "when generating the uniqueness key" do - - it "should use namevar if there is only one key_attribute" do - Puppet::Type.type(:file).stubs(:key_attributes).returns [:path] - res = Puppet::Resource.new("file", "/my/file", :parameters => {:owner => 'root', :content => 'hello'}) - res.uniqueness_key.should == '/my/file' - end - - it "should include all of the key_attributes" do + it "should include all of the key_attributes in alphabetical order by attribute name" do Puppet::Type.type(:file).stubs(:key_attributes).returns [:myvar, :owner, :path] Puppet::Type.type(:file).stubs(:title_patterns).returns( [ [ /(.*)/, [ [:path, lambda{|x| x} ] ] ] ] -- cgit From 4f34dbf206e591614c2fc06ce9bed1628ee85715 Mon Sep 17 00:00:00 2001 From: Jesse Wolfe Date: Tue, 15 Mar 2011 15:29:01 -0700 Subject: Fix #5610: Prevent unnecessary RAL lookups Reviewed-By: Paul Berry --- lib/puppet/type.rb | 2 +- spec/unit/type_spec.rb | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 205d809c1..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 diff --git a/spec/unit/type_spec.rb b/spec/unit/type_spec.rb index b7a08977e..6d9d0b234 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 -- cgit From 852fb9744320c253772c85e52b262b0290fb7dd4 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Tue, 15 Mar 2011 16:13:15 -0700 Subject: (#5073) Download plugins even if you're filtering on tags When we eval a resource in transaction.rb it was being skipped when filtering on tags and downloading the plugins. There's a lot of complicated conditions for whether to skip a resource, but this is a condensed version of the path that was causing plugins not to be downloaded. skip? missing_tags? !ignore_tags? !host_config The Puppet::Configurer::Downloader creates separate catalogs and applies them to get custom facts and plugins, so should be setting host_config to false. Puppet::Util::Settings also sets host_config to false when you call use on settings, while normal catalog application defaults to true. Thanks to Stefan Schulte for suggesting the implementation fix. --- lib/puppet/configurer/downloader.rb | 1 + lib/puppet/configurer/plugin_handler.rb | 9 ++++++++- spec/unit/configurer/downloader_spec.rb | 32 ++++++++++++++++++++++---------- 3 files changed, 31 insertions(+), 11 deletions(-) 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/spec/unit/configurer/downloader_spec.rb b/spec/unit/configurer/downloader_spec.rb index c57f39fb5..4080263e7 100755 --- a/spec/unit/configurer/downloader_spec.rb +++ b/spec/unit/configurer/downloader_spec.rb @@ -5,6 +5,8 @@ require 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 -- cgit From 17f673dd6fee08309970f8ff721855cf1644b45f Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Wed, 16 Mar 2011 11:38:36 -0700 Subject: Updated CHANGELOG for 2.6.7rc1 --- CHANGELOG | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- lib/puppet.rb | 2 +- 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7f5ff355f..2885596e3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,110 @@ -2.6.6 +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/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 -- cgit