$ whoami

Ben RobertsI currently work as a systems administrator for GSA Capital, managing Unix, Linux and Windows systems and providing IT support. I rely heavily on automation and open source technologies in my daily activities.

I previously worked as a Network Projects engineer for Atos in the Major Projects division. My role included design and implementation of LAN and WAN systems in Data Centre environments. My last project involved working on a major internal infrastructure overhaul spanning five sites for which I produced all the physical layer design and implementation.

Before then, I worked for Netcraft in Bath, while taking a year out from my degree studies. My roles included developing and running the SSL Server Survey, reviewing Automated Vulnerability Scan results, and performing occasional penetration tests against web applications for financial institutions.

I am a former graudate of ECS (University of Southampton), earning a First in Computer Science with Distributed Systems and Networks to the Masters level.

In my spare time, I am a member of the Sabayon Linux developers group, where I help maintain the Sabayon Community Repositories, help look after the project infrastructure, maintain the puppet-sabayon module, and dabble with package maintenance.

You can contact me via me@benroberts.net.

Recent Posts

Puppet custom type validation woes

Since I’ve just lost a full day to troubleshooting this issue, I’m documenting it in case it hits anyone else. In at least puppet versions 4.7.0 and earlier, global type validation cannot be used to ensure the presence of paramters without breaking puppet resource.

Simplified example type:

Puppet::Type.newtype(:entropy_mask) do
  @desc = "Mask packages in Entropy"

  ensurable

  newparam(:name) do
    desc "Unique name for this mask"
  end

  newproperty(:package) do
    desc "Name of the package being masked"
  end

  validate do
    # This will break for `puppet resource`
    raise(ArgumentError, "Package is required") if self[:package].nil?
  end
end

This works fine to validate that in a puppet manifest the `package` parameter is provided, but not when puppet resource interrogates the state of the existing system due to the way the object is constructed.

Puppet calls the `provider.instances` to obtain a list of the resources on the system managed by that provider. In the example above, the provider was a child of ParsedFile and took care of parsing the contents of /etc/entropy/packages/package.mask, splitting the lines into the various properties including package

Puppet then tries to create an instance of the Type/resource for each object retrieved by the provider. It does so by instantiating an instance of the type, but passing in the namevar and provider only. It then attempts to iterate through all the provider properties and set them on the resource one by one. The problem is that validation happens on the call to new() and so the required properties have not yet been set.

Here’s the code from lib/puppet/type.rb from puppet 4.7.0, with irrelevant bits stripped out and comments added by me:

def self.instances
  # Iterate through all providers for this type
  providers_by_source.collect do |provider|
    # Iterate through all instances managed by this provider
    provider.instances.collect do |instance|
      # Instantiate the resource using just the namevar and provider
      result = new(:name => instance.name, :provider => instance)
      # Oops, type.validate() got called here, but not all properties
      # have been set yet</code>

      # Now iterate through all properties on the provider and set
      # them on the resource
      properties.each { |name| result.newattr(name) }

      # And add this to the list of resources to return
      result
    end
  end.flatten.compact
end

Of course, once the problem is understood, finding out that someone else already discovered this 2 years ago becomes much easier. Here’s the upstream bug report: https://tickets.puppetlabs.com/browse/PUP-3732

  1. puppet-sabayon Leave a reply
  2. Going Paperless Leave a reply
  3. Removing stale facts from PuppetDB 3 Replies
  4. Setting up hiera-eyaml-gpg 1 Reply
  5. ZFS on Sabayon Leave a reply
  6. Using puppet on Sabayon Linux Leave a reply
  7. Puppetenvsh Mcollective Agent 2 Replies