Giter Club home page Giter Club logo

rspec-puppet-facts's People

Contributors

alexjfisher avatar bastelfreak avatar baurmatt avatar bodgit avatar davids avatar dependabot-preview[bot] avatar dependabot[bot] avatar edgej avatar ekohl avatar ghoneycutt avatar halfninja avatar jordanbreen28 avatar kenyon avatar logicminds avatar mcanevet avatar mmoll avatar raphink avatar rodjek avatar russellshackleford avatar seanmil avatar smortex avatar stbenjam avatar threepistons avatar tjm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rspec-puppet-facts's Issues

Support the facts/trusted hashes

There is no normalization within rspec-puppet between legacy and the equivalent structured facts hash. e.g. $operatingsystemmajrelease and $facts['os']['release']['major'], thought they contain the same value. Are there any plans to provide those facts in rspec-puppet-facts?

/cc @rodjek

rspec-puppet-facts hangs searching for facter version

Whilst trying to downgrade the facter version, rspec-puppet-facts will hang if it can't find a suitable version.

An example from puppet-ipset module.

with

RSpec.configure do |c|
  c.default_facter_version = '3.9'
end

and metadata.json

operatingsystem_support: [  
    {
      operatingsystem: Debian,    
      operatingsystemrelease: [  
        9,  
        8,  
        10  
      ]
    },
    {
      operatingsystem: Ubuntu,    
      operatingsystemrelease: [  
        16.04,  
        18.04  
      ]
    },
    {
      operatingsystem: RedHat,    
      operatingsystemrelease: [  
        7,  
        8  
      ]
    },
    {
      operatingsystem: CentOS,    
      operatingsystemrelease: [  
        7,  
        8  
      ]
    },
    {
      operatingsystem: OracleLinux,    
      operatingsystemrelease: [  
        7,  
        8  
      ]
    },
    {
      operatingsystem: Scientific,    
      operatingsystemrelease: [  
        7,  
        8  
      ]
    },
    {
      operatingsystem: Archlinux    
    }
  ],

Adding debug to https://github.com/mcanevet/rspec-puppet-facts/blob/4e07ec47787632ac3e3f8a8330ec074cc4b8905f/lib/rspec-puppet-facts.rb#L113 to print out version...

"3.9"
"3.8."
"3.7."
"3.6."
"3.5."
"3.4."
"3.3."
"3.2."
"3.1."
"3.0."
"3.-1."
"3.-2."
"3.-3."
"3.-4."
"3.-5."
"3.-6."
^C

The down_facter_version function is very simplistic. It only checks the minor version and doesn't check that it isn't already 0.

Remove Ruby 1.8.7/1.9.3 support

If you look at the latest builds, ruby 1.8.7 tests are in the allowed_failures group already and now 1.9.3 tests are failing (see #43). You could probably fix this for 1.9.3, somehow, but it's only a stop-gap solution as more and more gems start giving up 1.9 support. I would recommend removing both version entirely, as they provide no benefit due to failing during gem downloads, and only result in slower test completion.

The required_ruby_version should be set in the gemspec at this time as well.

Symbolized facts causes hiera to "ignore bad definition" in hierarchy

Summary

When I try to perform a hiera.lookup request in a spec, the hierarchy doesn't find the kernel fact. Because of that, Hiera shows this message:

Ignoring bad definition in :hierarchy: 'kernel/'

And as a result, the data I need is not found.

spec/spec_helper.rb

require "puppetlabs_spec_helper/module_spec_helper"
require "rspec-puppet-facts"
include RspecPuppetFacts

# needed to perform lookups inside specs
require "hiera"

RSpec.configure do |c|
  c.default_facts = {
    "hostname"      => `hostname -f`.strip,
    "ipaddress"     => `hostname -i`.strip,
    "puppetversion" => "4.6.1",
  }

  c.fail_fast = true if ENV['FAIL_FAST'] == "true"

  # needed to evaluate hiera lookups in the puppet code
  c.hiera_config = "spec/fixtures/hiera/hiera.yaml"

  if ENV['COVERAGE'] == "true"
    c.after(:suite) do
      RSpec::Puppet::Coverage.report!
    end
  end
end

# Default to "no" as our specs fail on default facts (i.e. "$::networking")
ENV['STRICT_VARIABLES'] = "no" unless ENV['STRICT_VARIABLES']

spec/fixtures/hiera/hiera.yaml

:backends:
  - yaml
:yaml:
  :datadir: spec/fixtures/hiera
:hierarchy:
  - "fqdn/%{fqdn}"
  - "environment/%{environment}"
  - "hostgroup/%{hostgroup}"
  - "os/%{operatingsystem}/%{operatingsystemrelease}"
  - "os/%{operatingsystem}"
  - "kernel/%{kernel}"
  - "common"

spec/fixtures/hiera/os/Ubuntu.yaml

cron_service: 'cron'

spec/fixtures/hiera/kernel/Linux.yaml

cron_service: 'crond'

manifests/linux.pp

class ta_base::linux() {
  $cron_service = hiera('cron_service')

  service { $cron_service:
    enable     => true,
    ensure     => true,
    hasrestart => true,
    hasstatus  => true,
  }
}

spec/classes/linux_spec.rb

require "spec_helper"

hiera = Hiera.new(:config => "spec/fixtures/hiera/hiera.yaml")

describe "ta_base::linux" do
  on_supported_os.each do |os, facts|
    context "on #{os}" do
      let(:facts) { facts }

      cron_service = hiera.lookup("cron_service", nil, facts)

      it { is_expected.to compile.with_all_deps }

      it { is_expected.to contain_service(cron_service)
        .with(
          "enable"  => true,
          "ensure"  => true
        )
      }
    end
  end
end

Example run

$ SPEC=spec/classes/linux_spec.rb FAIL_FAST=true rake spec_standalone
/home/dunk/.rvm/rubies/ruby-2.3.1/bin/ruby -I/home/dunk/.rvm/gems/ruby-2.3.1@puppet-testing/gems/rspec-core-3.6.0/lib:/home/dunk/.rvm/gems/ruby-2.3.1@puppet-testing/gems/rspec-support-3.6.0/lib/home/dunk/.rvm/gems/ruby-2.3.1@puppet-testing/gems/rspec-core-3.6.0/exe/rspec spec/classes/linux_spec.rb --color
DEBUG: 2017-08-23 17:38:05 -0600: Hiera YAML backend starting
DEBUG: 2017-08-23 17:38:05 -0600: Looking up cron_service in YAML backend
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'fqdn/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'environment/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'hostgroup/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'os//'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'os/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'kernel/'
DEBUG: 2017-08-23 17:38:05 -0600: Looking for data source common
DEBUG: 2017-08-23 17:38:05 -0600: Looking up cron_service in YAML backend
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'fqdn/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'environment/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'hostgroup/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'os//'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'os/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'kernel/'
DEBUG: 2017-08-23 17:38:05 -0600: Looking for data source common
DEBUG: 2017-08-23 17:38:05 -0600: Looking up cron_service in YAML backend
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'fqdn/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'environment/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'hostgroup/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'os//'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'os/'
DEBUG: 2017-08-23 17:38:05 -0600: Ignoring bad definition in :hierarchy: 'kernel/'
DEBUG: 2017-08-23 17:38:05 -0600: Looking for data source common

ta_base::linux
  on centos-6-x86_64
    should compile into a catalogue without dependency cycles
    should contain Service[] with enable => true and ensure => true (FAILED - 1)

Failures:

  1) ta_base::linux on centos-6-x86_64 should contain Service[] with enable => true and ensure => true
     Failure/Error:
       it { is_expected.to contain_service(cron_service)
         .with(
           "enable"  => true,
           "ensure"  => true
         )
       }

     ArgumentError:
       No title provided and "Service" is not a valid resource reference
     # /home/dunk/.rvm/gems/ruby-2.3.1@puppet-testing/gems/puppet-4.7.0/lib/puppet/resource.rb:572:in `extract_type_and_title'
     # /home/dunk/.rvm/gems/ruby-2.3.1@puppet-testing/gems/puppet-4.7.0/lib/puppet/resource.rb:557:in `type_and_title'
     # /home/dunk/.rvm/gems/ruby-2.3.1@puppet-testing/gems/puppet-4.7.0/lib/puppet/resource/catalog.rb:355:in `resource'
     # /home/dunk/.rvm/gems/ruby-2.3.1@puppet-testing/gems/rspec-puppet-2.6.8/lib/rspec-puppet/matchers/create_generic.rb:85:in `matches?'
     # ./spec/classes/linux_spec.rb:17:in `block (4 levels) in <top (required)>'

Finished in 3.93 seconds (files took 4.26 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/classes/linux_spec.rb[1:1:2] # ta_base::linux on centos-6-x86_64 should contain Service[] with enable => true and ensure => true

/home/dunk/.rvm/rubies/ruby-2.3.1/bin/ruby -I/home/dunk/.rvm/gems/ruby-2.3.1@puppet-testing/gems/rspec-core-3.6.0/lib:/home/dunk/.rvm/gems/ruby-2.3.1@puppet-testing/gems/rspec-support-3.6.0/lib/home/dunk/.rvm/gems/ruby-2.3.1@puppet-testing/gems/rspec-core-3.6.0/exe/rspec spec/classes/linux_spec.rb --color failed

From what I can see, this comes down to the facts hash having kernel as a Symbol instead of a String, because it properly loads spec/fixtures/hiera/kernel/Linux.yaml when I do this:

# manifest
facts['kernel'] = "Linux"
cron_service = hiera.lookup("cron_service", nil, facts)

# log output from running test
DEBUG: 2017-08-23 17:39:14 -0600: Looking up cron_service in YAML backend
DEBUG: 2017-08-23 17:39:14 -0600: Ignoring bad definition in :hierarchy: 'fqdn/'
DEBUG: 2017-08-23 17:39:14 -0600: Ignoring bad definition in :hierarchy: 'environment/'
DEBUG: 2017-08-23 17:39:14 -0600: Ignoring bad definition in :hierarchy: 'hostgroup/'
DEBUG: 2017-08-23 17:39:14 -0600: Ignoring bad definition in :hierarchy: 'os//'
DEBUG: 2017-08-23 17:39:14 -0600: Ignoring bad definition in :hierarchy: 'os/'
DEBUG: 2017-08-23 17:39:14 -0600: Looking for data source kernel/Linux
DEBUG: 2017-08-23 17:39:14 -0600: Found cron_service in kernel/Linux
  • The last 2 lines being the key difference:

    Looking for data source kernel/Linux
    Found cron_service in kernel/Linux
    

So....

  • Am I configuring something incorrectly?
  • Should I post an issue to https://tickets.puppetlabs.com/ for Hiera?
  • Should I just eat dinner?
    • Yes. Yes I should.

Support for RedHat family minor releases when reading metadata.json

Metadata.json supports minor OS releases of RedHat
https://docs.puppetlabs.com/puppet/latest/reference/modules_publishing.html#operating-system-compatibility-in-metadatajson

It'd be nice if rspec-puppet-facts could too. :)

If I try to use

 "operatingsystem_support": [
  {
    "operatingsystem": "RedHat",
    "operatingsystemrelease":[ "6.5", "6.6", "7.1" ]
  }
]

I get

Can't find facts for 'redhat-6.5-x86_64' for facter 2.4, skipping...
Can't find facts for 'redhat-6.6-x86_64' for facter 2.4, skipping...
Can't find facts for 'redhat-7.1-x86_64' for facter 2.4, skipping...

I guess the only fact that would vary between minor releases is "operatingsystemrelease" and "os"
(which is currently set to 6.5 for redhat 6 facts).

facts > 2.5 not working as expected

In doing some testing if you lookup %{::memory.system.total_bytes} it returns null and I believe that is because puppet requires facter and the latest version if 2.5.1 and in that facts set there is no fact for that even though for example 4.10.1 ships with 3.6.4 and it is available in facterdb under 3.6 folder.

I think there either needs to be a facter gem published to support later than 2.5 or some way for rspec-puppet-facts to use the 3.x facts from facterdb

PR #72 breaks Puppet 6

The change done in #72 breaks our CI using Puppet 6:

An error occurred while loading ./spec/classes/vhosts_spec.rb.
Failure/Error:
  on_supported_os.each do |os, os_facts|
    context "on #{os}" do
      let(:facts) { os_facts }
      let :pre_condition do
        <<-EOF
        # Fake assert_private function from stdlib to not fail within this test
        function assert_private () { }
        include apache
        EOF
      end

LoadError:
  cannot load such file -- augeas
# /usr/local/bundle/gems/rspec-puppet-2.7.1/lib/rspec-puppet/monkey_patches.rb:350:in `require'
# /usr/local/bundle/gems/rspec-puppet-2.7.1/lib/rspec-puppet/monkey_patches.rb:350:in `require'
# /usr/local/bundle/gems/rspec-puppet-facts-1.9.1/lib/rspec-puppet-facts.rb:220:in `common_facts'
# /usr/local/bundle/gems/rspec-puppet-facts-1.9.1/lib/rspec-puppet-facts.rb:134:in `block in on_supported_os'
# /usr/local/bundle/gems/rspec-puppet-facts-1.9.1/lib/rspec-puppet-facts.rb:117:in `map'
# /usr/local/bundle/gems/rspec-puppet-facts-1.9.1/lib/rspec-puppet-facts.rb:117:in `on_supported_os'
# ./spec/classes/vhosts_spec.rb:4:in `block in <top (required)>'
# ./spec/classes/vhosts_spec.rb:3:in `<top (required)>'

That's probably because the rescue doesn't rescue a LoadError. I will submit a PR for this.

Inconsistent FQDNs in facts

It would be useful if the facts had consistent, known hostnames and domains. This would make it easier to construct tests for manifests using these facts, without having to override/merge these.

Exclude based on osfamily rather than rewriting the supported os hash

I'm trying to apply the following conditional rather than having to rewrite the supported block:
but for some reason this doesn't seem to be working as Ubuntu is still trying to run, I'm sure I'm doing something wrong:

metadata.json

  "operatingsystem_support": [
    {
      "operatingsystem": "CentOS",
      "operatingsystemrelease": [
        "5",
        "6",
        "7"
      ]
    },
    {
      "operatingsystem": "Ubuntu",
      "operatingsystemrelease": [
        "12.04",
        "14.04",
        "16.04"
      ]
    }
  ],
require 'spec_helper'
describe 'profile_base::el' do
  context 'supported operating systems' do
    on_supported_os.each do |os, facts|
      context "on #{os}" do
        let(:facts) do
          facts.merge({
            puppetversion: Puppet.version,
            sudoversion: '1.7.10p9'
          })
        end
        if (:osfamily != "Debian") then
          context "profile_base::el class without any parameters" do
            %w(profile_base::el profile_base::linux
               profile_base::nix).each do |puppet_class|
              it { should contain_class(puppet_class) }
              it { should compile.with_all_deps }
            end
          end
        end
      end
    end
  end
end

rspec-puppet does not run tests on all supported OSes defined in a module

I am using rspec-puppet and it appears that not all supported operating systems are being tested. For example, here is the metadata for one of the modules I am currently testing.

"name": "mdct-dhcpd",
"version": "0.1.0",
"author": "Michael Watters",
"summary": "Installs and configures dhcpd",
"license": "Apache-2.0",
"source": "",
"project_page": null,
"issues_url": null,
"dependencies": [
{"name":"puppetlabs/firewall", "version_requirement": ">= 0.0.4 <= 1.8.1" }
],
"operatingsystem_support": [
{ "operatingsystem":"CentOS", "operatingsystemrelease":[ "7" ] },
{ "operatingsystem":"Fedora", "operatingsystemrelease":[ "20", "21", "22", "23", "24", "25", "26" ] }
],
"data_provider": null
}`

When rake spec is run only Fedora 23-26 are tested.

usr/bin/ruby -I/home/00/d861703/.gem/ruby/gems/rspec-support-3.6.0/lib:/usr/local/share/gems/gems/rspec-core-3.6.0/lib /usr/local/share/gems/gems/rspec-core-3.6.0/exe/rspec --pattern spec/{aliases,classes,defines,unit,functions,hosts,integration,type_aliases,types}/**/*_spec.rb --color

dhcpd
on fedora-23-x86_64
should contain Firewall[105 dhcpd] with dport => "68", proto => "udp" and action => "accept"
should contain Package[dhcp] that comes before File[/etc/dhcp/dhcpd.conf]
should contain File[/etc/dhcp/dhcpd.conf] that requires Package[dhcp]
should contain Service[dhcpd] with ensure => "running" and enable => true
on fedora-22-x86_64
should contain Firewall[105 dhcpd] with dport => "68", proto => "udp" and action => "accept"
should contain Package[dhcp] that comes before File[/etc/dhcp/dhcpd.conf]
should contain File[/etc/dhcp/dhcpd.conf] that requires Package[dhcp]
should contain Service[dhcpd] with ensure => "running" and enable => true
on fedora-25-x86_64
should contain Firewall[105 dhcpd] with dport => "68", proto => "udp" and action => "accept"
should contain Package[dhcp] that comes before File[/etc/dhcp/dhcpd.conf]
should contain File[/etc/dhcp/dhcpd.conf] that requires Package[dhcp]
should contain Service[dhcpd] with ensure => "running" and enable => true
on fedora-24-x86_64
should contain Firewall[105 dhcpd] with dport => "68", proto => "udp" and action => "accept"
should contain Package[dhcp] that comes before File[/etc/dhcp/dhcpd.conf]
should contain File[/etc/dhcp/dhcpd.conf] that requires Package[dhcp]
should contain Service[dhcpd] with ensure => "running" and enable => true
on centos-7-x86_64
should contain Firewall[105 dhcpd] with dport => "68", proto => "udp" and action => "accept"
should contain Package[dhcp] that comes before File[/etc/dhcp/dhcpd.conf]
should contain File[/etc/dhcp/dhcpd.conf] that requires Package[dhcp]
should contain Service[dhcpd] with ensure => "running" and enable => true

Finished in 1.43 seconds (files took 2.37 seconds to load)
20 examples, 0 failures

Is there a way to make tests run on all defined operating systems?

Missing the 'puppetversion' fact

I'm not sure if this is intended or not, but this gem seems to be missing the puppetversion fact, which has been around since at least Facter 1.6.

I'm currently using the following workaround:

let(:facts) do
  facts.merge!({ :puppetversion => ENV['PUPPET_VERSION'] || '3.7.0' })
end

Testing functions with Puppet 4

I have the following rspec tests for my functions based on the example in the README:

require 'spec_helper'

describe 'my_function' do

  let(:scope) { PuppetlabsSpec::PuppetInternals.scope }

  on_supported_os.each do |os, facts|
    context "on #{os}" do
      before :each do
        facts.each do |k, v|
          scope.stubs(:lookupvar).with("::#{k}").returns(v)
          scope.stubs(:lookupvar).with(k.to_s).returns(v)
        end
      end
      it { should run.with_params(...).and_return(...) }
      ...
    end
  end
end

This all works fine on Puppet ~> 3.0 but as soon as I try with ~> 4.0 I get errors like this:

  x) my_function on centos-6-x86_64 
      Failure/Error: it { should run.with_params(...).and_return(...) }

      NameError:
        undefined method `function_my_function' for class `Puppet::Parser::Scope'

If I remove the let(:scope) ... and associated bits then it works again but obviously lacks the per-OS facts, etc. Is there some additional setup needed for Puppet 4?

structured facts example

Is it possible to set structured facts in the test spec? For example if one needs AWS ec2 metadata as a fact in an rspec test how do you do that? This doesn't seem to work.

        let(:facts) do
          facts.merge({
            :ec2_tag_name => 'vmName-dev-01',
            :ec2_tag_env => 'dev',
            :ec2_tag_company => 'flux',
            :ec2_metadata['public-ipv4'] => '54.1.2.3',
          })
        end

Allow modules to export custom fact values

I'm using the service_provider fact from the stdlib module in my own modules. Because this fact won't be in facterdb I have to provide values for it. Now, I can do this using add_custom_fact :service_provider, ->(os, facts) { ... } however at least for this fact, the logic can be quite cumbersome. I also have to duplicate this logic across every module that uses this same fact.

It would be handy if (somehow) a module that provides a custom fact also exports some example values for use in tests split by OS which could then be picked up by rspec-puppet-facts. I'm not sure how it would work, but given every module dependency is available under spec/fixtures/modules/* during a test run some well-defined location in each module could be used. So stdlib would have example values that on for example, RHEL6, service_provider is init, on RHEL7 its systemd, plus all of the other OS values, etc.

I found voxpupuli/facterdb#49 which is about the package_provider fact, but it's the same problem.

"add_custom_fact" creates String-Facts instead of Symbol-Facts

Hello,
I am using rspec-puppet-facts 2.0.5 and facterdb 1.19.0 on ruby 2.7.6 and Puppet 7.19.0.

When I try to add or override a Fact in my spec_helper.rb like so…:

add_custom_fact :blubb, 'blobb'

… then it appears in the Facts-Hash as String "blubb" => "blobb" instead of as a Symbol :blubb => "blobb".

This leads to the Problem, that I cannot override Facts from Facter-DB, because f.e. add_custom_fact :ipaddress => '1.2.3.4' happens to create the String-Fact "ipaddress" => '1.2.3.4' besides the previously existing :ipaddress => '10.0.2.15' instead of overriding it. The same goes for the nested Hash :network versus "network".

Actually it seems to be even worse:

My Rspec-Test throws…:

expected that the catalogue would contain Service_monitoring::Monitor::Host[foo.example.com] 
with address set to "10.0.2.15" but it is set to "1.2.3.4"

… because the Rspec-Test picks up the Symbol-Fact…

        it 'should export itself as monitoring::host' do
          expect(exported_resources).to contain_service_monitoring__monitor__host(node)
            .with_address(facts[:networking]['ip'])
        end

… and the Puppet-Code picks up the String-Fact:

  $agent_ip_address                     = $::facts['networking']['ip']

I tried to find the Source of this Misbehaviour (IMHO), but even in rspec-puppet-facts.rb the Symbols stay untouched:

  def add_custom_fact(name, value, options = {})
    options[:confine] = [options[:confine]] if options[:confine].is_a?(String)
    options[:exclude] = [options[:exclude]] if options[:exclude].is_a?(String)
    RspecPuppetFacts.register_custom_fact(name, value, options)
  end

  def self.register_custom_fact(name, value, options)
    @custom_facts ||= {}
    @custom_facts[name] = {:options => options, :value => value}
  end

So I guess either I need some Help about what I am doing wrong, or I spotted kind of a Bug.

operatingsystemrelease filter should work with string instead of array

If I want to create a test block using on_supported_os with only one os release, I still have to make the filter an array instead of a single string which I would expect to work, as other filters like operatingsystem work with a string.

Example that doesn't work:

on_supported_os({
  :supported_os => [ {
    'operatingsystem' => 'RedHat',
    'operatingsystemrelease' => '5',
  } ]
}).each do ...

Example that actually works:

on_supported_os({
  :supported_os => [ {
    'operatingsystem' => 'RedHat',
    'operatingsystemrelease' => ['5'],
  } ]
}).each do ...

Cut a new release

#103 greatly improves performance. It would be great if this could make it into a release.

facterversion filter fails with windows and facter version 3.x

The hardwaremodule fact changed between facter versions 2.x and 3.x. This is causing a failure to lookup windows systems in FacterDB when the facterversion is set to the 3.x version.

Facterversion 3.x (hardwaremodel => 'x86_64')
https://github.com/camptocamp/facterdb/blob/master/facts/3.5/windows-2012%20r2-x86_64.facts#L21

Facterversion 2.x (hardwaremodel => '64')
https://github.com/camptocamp/facterdb/blob/master/facts/2.5/windows-2012%20r2-x86_64.facts#L7

https://github.com/mcanevet/rspec-puppet-facts/blob/master/lib/rspec-puppet-facts.rb#L64

Because we hardcode x64 regardless of facter versions failures to lookup will fail.

Additionally

hardwaremodel = version =~ /^[12]\./ ? 'x64' : 'x86_64' is not tied to a windows release and should be bound to the facterversion instead of the windows version. This causes another issue where windows 2012 systems with facterversion of 3.x would never be found either.

Strict fact retrieval

Supported OS entries in metadata.json which don't match any facts are simply silently not tested. This could happen when the user has a typo in the OS name or in any of the OS release names, or if FacterDB has not yet been populated with facts for the given OS name and release.

For example, given a semantically correct support matrix like so:

"operatingsystem_support": [
   {
        "operatingsystem": "CentOS",
        "operatingsystemrelease": ["6", "7"]
    }
]

on_supported_os could have 0, 1 or 2 entries depending on Facter version and FacterDB parity. Thus with the recommended use pattern for on_supported_os, it's possible that no testing occurs at all, or less testing is happening than intended, with at most a warning message in the test result output.

With typos in the support matrix, this problem could happen even with a fully populated FacterDB.

I think rspec-puppet-facts should throw an error if facts for a given OS name and release are not found. I'm guessing this precludes the use of FacterDB.get_facts, the API of which seems to be the root cause of this issue (or maybe validating its return value is an acceptable solution).

facts cannot be cased as described

When trying to use a case facts[:osfamily] like described, I'm getting the following error trying to do a validation:

An error occurred while loading ./spec/classes/libvirt_spec.rb.
Failure/Error: case facts[:osfamily]
  `facts` is not available on an example group (e.g. a `describe` or `context` block). It is only available from within individual examples (e.g. `it` blocks) or from constructs that run in the scope of an example (e.g. `before`, `let`, etc).
# ./spec/classes/libvirt_spec.rb:11:in `block (3 levels) in <top (required)>'
# ./spec/classes/libvirt_spec.rb:7:in `block (2 levels) in <top (required)>'
# ./spec/classes/libvirt_spec.rb:6:in `each'
# ./spec/classes/libvirt_spec.rb:6:in `block in <top (required)>'
# ./spec/classes/libvirt_spec.rb:5:in `<top (required)>'
Run options: exclude {:bolt=>true}

Where I'm literally just proceeding as exampled:

describe 'libvirt', type: :class do
  on_supported_os.each do |os, os_facts|
    context "on #{os}" do
      let(:facts) do
        os_facts
      end
      case facts[:osfamily]
      when 'Debian'
        let :params do
          {
            package_libvirtd: 'libvirtd',
            package_libvirt_devel: 'libvirt-dev'
          }
        end
        it {
          is_expected.to contain_package('libvirtd').with(
            'ensure' => 'present',
          )
        }
        it {
          is_expected.to contain_package('libvirt-dev').with(
            'ensure' => 'present',
          )
        }
        it {
          is_expected.to contain_package('ruby-libvirt').with(
            'ensure' => 'present',
            'provider' => 'puppet_gem',
          )
        }
      end
      it { is_expected.to compile }
    end
  end
end

So the documentation would clearly need some form of update as to how to do a OS-specific distinction here.

Windows Server support in metadata.json

It appears that the proper way to support Windows variants in metadata.json, looking at a few puppetlabs examples, is with a string Server <version>[ <release>], e.g. Server 2012 R2. However, this does not result in the OS being added to the on_supported_os hash. Instead, the string 2012 R2 needs to be used.

Which is correct, and is there a way to normalize that so either string would pick up the windows-2012-r2 collections in facterdb?

Caching

It would be great if it was possible to cache the result of on_supported_os, so it runs only once. It is slows a lot of tests and this could greatly improve a lot of rspec tests speed.

Overriding structured facts

#37 covered how to set custom structured facts but this doesn't seem to work when I want to override an existing nested structured fact.

For example, I want to force $facts['os']['selinux']['enabled'] to be true regardless but it's always false because that's what is now set in the shipped facts, (fairly sure it used to be true or unset in previous facterdb releases so it was working by chance).

      let(:facts) do
        facts.merge({
          os: {
            selinux: {
              enabled: true,
            },
          },
        })
      end

I found there is a deep_merge gem pulled in via Puppet so I tried instead:

      let(:facts) do
        DeepMerge.deep_merge!(facts, {
          os: {
            selinux: {
              enabled: true,
            },
          },
        })
      end

But this gem seems to have odd merge behaviour and won't overwrite existing values.

What's the easiest way to do this?

File resource is trying to load Windows provider on a non-Windows computer

With v1.9.0 having better Windows support, it has exposed a possible issue with loading providers.

In the puppet_agent module, running https://github.com/puppetlabs/puppetlabs-puppet_agent/blob/master/spec/classes/puppet_agent_spec.rb with v 1.8.0 of rspec-puppet-facts gem, they pass correctly.

When I run with v1.9.0 I get errrors such as;

  8) puppet_agent supported operating systems on ubuntu-16.04-x86_64 puppet_agent class without any parameters should compile into a catalogue without dependency cycles
     Failure/Error: it { is_expected.to compile.with_all_deps }

     NoMethodError:
       undefined method `supports_acl?' for File[sources.list](provider=windows):Puppet::Type::File::ProviderWindows
     # /usr/local/bundle/gems/puppet-5.4.0/lib/puppet/provider/file/windows.rb:84:in `validate'
     # /usr/local/bundle/gems/puppet-5.4.0/lib/puppet/type/file.rb:394:in `block (2 levels) in <top (required)>'
     # /usr/local/bundle/gems/puppet-5.4.0/lib/puppet/type.rb:2402:in `initialize'
     # /usr/local/bundle/gems/puppet-5.4.0/lib/puppet/type/file.rb:491:in `initialize'
     # /usr/local/bundle/gems/puppet-5.4.0/lib/puppet/resource.rb:461:in `new'
     # /usr/local/bundle/gems/puppet-5.4.0/lib/puppet/resource.rb:461:in `to_ral'
     # /usr/local/bundle/gems/puppet-5.4.0/lib/puppet/resource/catalog.rb:640:in `block in to_catalog'
     # /usr/local/bundle/gems/puppet-5.4.0/lib/puppet/resource/catalog.rb:632:in `each'
     # /usr/local/bundle/gems/puppet-5.4.0/lib/puppet/resource/catalog.rb:632:in `to_catalog'
     # /usr/local/bundle/gems/puppet-5.4.0/lib/puppet/resource/catalog.rb:513:in `to_ral'
     # /usr/local/bundle/gems/rspec-puppet-2.6.9/lib/rspec-puppet/matchers/compile.rb:142:in `cycles_found?'
     # /usr/local/bundle/gems/rspec-puppet-2.6.9/lib/rspec-puppet/matchers/compile.rb:25:in `matches?'
     # ./spec/classes/puppet_agent_spec.rb:154:in `block (7 levels) in <top (required)>'

Note that it's trying to load the Windows File resource provider.

So what I did was run ONLY ubuntu-16.04-x86_64 tests and they pass. If the Windows tests run prior they fail with error above.

It appears that the first invocation is determining the default provider.

To test this I changed:
https://github.com/puppetlabs/puppetlabs-puppet_agent/blob/master/spec/classes/puppet_agent_spec.rb#L75

to (ubuntu only)

context "on #{os}", :if => (os == 'ubuntu-16.04-x86_64') do

to (windows -> windows -> ubuntu)

context "on #{os}", :if => (os == 'windows-2008 R2-x64' || os == 'windows-2012-x64' || os == 'ubuntu-16.04-x86_64') do

Environment:
Docker on Windows
Linux bdf55e700bbe 4.9.60-linuxkit-aufs #1 SMP Mon Nov 6 16:00:12 UTC 2017 x86_64 GNU/Linux

Puppet facts

root@bdf55e700bbe:/project# bundle exec puppet facts
{
  "name": "bdf55e700bbe.gallifrey.local",
  "values": {
    "puppetversion": "5.4.0",
    "kernel": "Linux",
    "kernelrelease": "4.9.60-linuxkit-aufs",
    "facterversion": "2.5.1",
    "partitions": {
      "sda1": {
        "size": "125827072",
        "mount": "/etc/resolv.conf"
      }
    },
    "operatingsystem": "Debian",
    "domain": "gallifrey.local",
    "operatingsystemmajrelease": "8",
    "timezone": "UTC",
    "selinux": false,
    "uptime_days": 0,
    "physicalprocessorcount": 1,
    "os": {
      "name": "Debian",
      "family": "Debian",
      "release": {
        "major": "8",
        "minor": "8",
        "full": "8.8"
      }
    },
    "rubyplatform": "x86_64-linux",
    "virtual": "docker",
    "is_virtual": true,
    "architecture": "amd64",
    "hardwaremodel": "x86_64",
    "uptime_hours": 3,
    "processors": {
      "models": [
        "Intel(R) Core(TM) i7-7560U CPU @ 2.40GHz",
        "Intel(R) Core(TM) i7-7560U CPU @ 2.40GHz"
      ],
      "count": 2,
      "physicalcount": 1
    },
    "processor0": "Intel(R) Core(TM) i7-7560U CPU @ 2.40GHz",
    "processor1": "Intel(R) Core(TM) i7-7560U CPU @ 2.40GHz",
    "processorcount": 2,
    "interfaces": "",
    "ipaddress": "172.17.0.2",
    "osfamily": "Debian",
    "operatingsystemrelease": "8.8",
    "kernelmajversion": "4.9",
    "rubysitedir": "/usr/local/lib/ruby/site_ruby/2.1.0",
    "uptime_seconds": 11444,
    "fqdn": "bdf55e700bbe.gallifrey.local",
    "filesystems": "ext2,ext3,ext4,iso9660,msdos,squashfs,udf,vfat,xfs",
    "uniqueid": "11ac0200",
    "path": "/usr/local/bundle/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "blockdevice_sr0_size": 443424768,
    "blockdevice_sr0_vendor": "Msft",
    "blockdevice_sr0_model": "Virtual DVD-ROM",
    "blockdevice_sda_size": 64424509440,
    "blockdevice_sda_vendor": "Msft",
    "blockdevice_sda_model": "Virtual Disk",
    "blockdevice_sr1_size": 174080,
    "blockdevice_sr1_vendor": "Msft",
    "blockdevice_sr1_model": "Virtual DVD-ROM",
    "blockdevices": "sda,sr0,sr1",
    "gid": "root",
    "system_uptime": {
      "seconds": 11444,
      "hours": 3,
      "days": 0,
      "uptime": "3:10 hours"
    },
    "hostname": "bdf55e700bbe",
    "rubyversion": "2.1.10",
    "kernelversion": "4.9.60",
    "ps": "ps -ef",
    "memorysize": "1.93 GB",
    "memoryfree": "1.53 GB",
    "swapsize": "1024.00 MB",
    "swapfree": "1023.83 MB",
    "swapsize_mb": "1024.00",
    "swapfree_mb": "1023.83",
    "memorysize_mb": "1980.77",
    "memoryfree_mb": "1565.25",
    "hardwareisa": "unknown",
    "id": "root",
    "uptime": "3:10 hours",
    "clientcert": "bdf55e700bbe.gallifrey.local",
    "clientversion": "5.4.0",
    "clientnoop": false
  },
  "timestamp": "2018-02-26T06:52:36.884490600+00:00",
  "expiration": "2018-02-26T07:22:36.884672700+00:00"
}

Not all specified Ubuntu operatingsystemrelease captured

I've run into unexpected behavior with respect to Ubuntu operatingsystemreleases. Specifically, rspec-puppet-facts doesn't appear to process all specified minor releases.

Here's the relevant section of metadata.json:

      "operatingsystem_support": [
    {
      "operatingsystem": "Ubuntu",
      "operatingsystemrelease": [
        "12.04",
        "14.04",
        "14.10",
        "15.04",
        "15.10"
      ]
    }
  ]

I would expect rspec-puppet-facts to iterate through each operatingsystemrelease allowing me to test for run tests for 12.04, 14.04, 14.10, 15.04, 15.10. It's not. Instead I get iterations only on 12.04, 14.10, 15.10. No opportunity to test 14.04 or 15.04 is provided.

It kinda acts like rspec-puppet-facts is doing some kind of filtering on major version (12, 14, 15) such that only one minor version (the largest) is kept. Is this expected behavior?

release notes for 3.0.0

symbolized facts deprecation

With the release of rspec-puppet-facts 4.0.0 we will remove support for symbolized facts. At the moment people typically use this in their unit files:

case facts[:os]['name']
when 'Archlinux'
  context 'on Archlinux' do
    it { is_expected.to contain_package('borg') }
  end
when 'Ubuntu'

For history reasons the first level of facts were symbols. You will have to update it to strings with the 4.0.0 release:

case facts['os']['name']
when 'Archlinux'
  context 'on Archlinux' do
    it { is_expected.to contain_package('borg') }
  end
when 'Ubuntu'

Memoizing facts

Currently on_supported_os collects facts on every invocation. Typically it's called in every file with the same arguments (none). These calls can be slow and the result will be the same anyway. In voxpupuli/voxpupuli-test@5fb4475 I implemented memoization for voxpupuli-test.

Would this be a welcome addition to rspec-puppet-facts itself or should we keep it in voxpupuli-test?

How to include lsbdistcodename?

Is lsbdistcodename supported already and I just don't know how to access it?

If lsbdistcodename isn't already supported, is there a way to do some kind of selector in facts.merge like below for RHEL?

        let(:facts) do
          facts.merge(
            case $::operatingsystemmajrelease {
              when '6'
                :lsbdistcodename => 'Santiago'
              when '7'
                :lsbdistcodename => 'Maipo'
            end
        end

Modern Facts not populated

In the parlance of Facter 3.6 docs and as far as I can see, this gem only populates legacy facts, but not modern facts.

Are you planing to add support for modern facts? PR welcome?

Can't distinguish between "2012" and "2012 R2"

With either "2012" or "2012 R2" as operatingsystemrelease in metadata.json, unit tests are always run for both entries:

david@davids:~/tmp/testmod$ grep -A3 windows metadata.json 
      "operatingsystem": "windows",
      "operatingsystemrelease": [
        "2012 R2"
      ]
david@davids:~/tmp/testmod$ bundle exec rspec -fd spec/classes/foo_spec.rb 

testmod::foo
  on debian-8-x86_64
    should compile into a catalogue without dependency cycles (FAILED - 1)
  on windows-2012-x64
    should compile into a catalogue without dependency cycles (FAILED - 2)
  on windows-2012 R2-x64
    should compile into a catalogue without dependency cycles (FAILED - 3)
  on ubuntu-16.04-x86_64
    should compile into a catalogue without dependency cycles (FAILED - 4)

Custom facts from function are not symbolised

I'm attempting to use the add_custom_fact functionality to add a 'systemd' fact for testing a module that uses 'camptocamp-systemd'.

It would appear that the fact is not being symbolised correctly when testing in rspec.

I've added the following to spec_helper.rb:

add_custom_fact :systemd, ->(os,facts) {
  case facts[:osfamily]
  when 'RedHat'
    case facts[:operatingsystemmajrelease]
    when '5','6'
      false
    when '7'
      true
    end
  when 'Debian'
    case facts[:lsbdistcodename]
    when 'jessie'
      true
    else
      false
    end
  else 
    false
  end
}

But when dumping the 'facts' value from within a rspec test, I get:

{:sshfp_ecdsa=>"SSHFP 3 1 5ac9d8a3d8d21350da19cd71d21b1cb4ddcd32e1\nSSHFP 3 2 31425eee47ed3ae3e968f6bc48ab5a645f899744848d81d768b2ad38b43c289b", :lsbdistrelease=>"12.04", :uptime=>"0:03 hours", :is_virtual=>true, :ipaddress=>"10.0.2.15", :serialnumber=>"0", :manufacturer=>"innotek GmbH", :rubyplatform=>"x86_64-linux", :boardmanufacturer=>"Oracle Corporation", :macaddress_eth0=>"08:00:27:0f:67:ea", :network_eth0=>"10.0.2.0", :blockdevice_sda_vendor=>"ATA", :timezone=>"UTC", :processorcount=>1, :sshfp_rsa=>"SSHFP 1 1 ff2e5147dbd06309221334e95182a2578376b99c\nSSHFP 1 2 a4fa733c8b80d653e1f7bde1a62aa32e7d3b011681ee59bfd014642d8900f744", :domain=>"example.com", :memoryfree_mb=>"432.00", :swapsize_mb=>"512.00", :bios_vendor=>"innotek GmbH", :sshdsakey=>"AAAAB3NzaC1kc3MAAACBAM7xkV/4Q+vcuK0a6af7qVEoc6eSM6GbvFuzoTBV5op14wl0ajkxUlrOdXG0gQDsA+2j+5TyyKkdhD2Wdkkji1cagA1mUJFDcVSVeXipFibBtd7wmGNdbEbCjByL8ZM71AS3y6JywygpoX3k9l+qhuJdc01wwNRV937Md1+zmNF/AAAAFQCPEqcFfYRS0J9qxTkotkDb0ObF8wAAAIEAjteqq8MGXAejpufCbR5BF7992wo/naz6WOi1e5hcE53rQ/3GEBQhN7qEu+79wA1jZs2433xOoK9aA76pXIZs682pf022wDIN/RRa/8pjoH603asbY30NookmyD7CdRKGu1NJW2XgEYHHvypa3d2TEf1/B/zZCEG0Sf0x+MTFwuMAAACBAI3VHzREuRjdt+Pjv2UrXVtbuQYlAuXTzL5k3LPoCJX6bZWxB8ZkBH5TUVY0dm8+Z5jT8uyfOlez8rx6dSb5yCU/xtCYv6od9qvn1bRQGqwME9uRSKUuobu8lDD0sAaeHEhBskPbYQTiFImG51uW5K9uutTR7+sqs1TqWB/czPsw", :bios_release_date=>"12/01/2006", :filesystems=>"ext2,ext3,ext4,vfat", :blockdevice_sr1_vendor=>"VBOX", :memoryfree=>"432.00 MB", :hardwareisa=>"x86_64", :blockdevice_sda_size=>10632560640, :blockdevice_sda_model=>"VBOX HARDDISK", :processor0=>"Intel(R) Core(TM)2 Quad CPU    Q6700  @ 2.66GHz", :kernelmajversion=>"3.5", :partitions=>{"sda1"=>{"uuid"=>"0387e66f-2dec-40a0-ac75-d36281af965c", "filesystem"=>"ext2", "mount"=>"/boot", "size"=>"497664"}, "sda2"=>{"size"=>"2"}, "sda5"=>{"filesystem"=>"LVM2_member", "size"=>"20262912"}}, :path=>"/home/vagrant/vendor/bundler/ruby/1.8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/var/lib/gems/1.8/bin/:/root/.gem/ruby/2.1.0/bin:/usr/lib64/ruby/gems/1.9.1/gems/bundler-1.7.12/bin:/usr/lib64/ruby/gems/2.0.0/gems/bundler-1.7.12/bin", :blockdevice_sr1_size=>1073741312, :productname=>"VirtualBox", :netmask=>"255.255.255.0", :hardwaremodel=>"x86_64", :uptime_days=>0, :virtual=>"virtualbox", :boardserialnumber=>"0", :rubysitedir=>"/Users/gavinw/.rvm/rubies/ruby-1.9.3-p551/lib/ruby/site_ruby/1.9.1", :system_uptime=>{"days"=>0, "seconds"=>197, "hours"=>0, "uptime"=>"0:03 hours"}, :selinux=>false, :sshecdsakey=>"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLBtSpI6A01NXAodidU0F2aFYsKsZS/w3TQC79BSBiIX7jkr61Sk5U9ui98DJ75yI1cu40m0U1UYyx6ic8YrmCw=", :memorysize=>"491.21 MB", :operatingsystem=>"Ubuntu", :lsbdistid=>"Ubuntu", :gem_version=>"~> 2.4.0", :mtu_lo=>16436, :operatingsystemmajrelease=>"12.04", :os=>{"lsb"=>{"distcodename"=>"precise", "distdescription"=>"Ubuntu 12.04.2 LTS", "distrelease"=>"12.04", "majdistrelease"=>"12.04", "distid"=>"Ubuntu"}, "release"=>{"major"=>"12.04", "full"=>"12.04"}, "name"=>"Ubuntu", "family"=>"Debian"}, :bios_version=>"VirtualBox", :architecture=>"amd64", :lsbdistcodename=>"precise", :blockdevices=>"sda,sr0,sr1", :id=>"root", :kernelrelease=>"3.5.0-23-generic", :ps=>"ps -ef", :lsbmajdistrelease=>"12.04", :ipaddress_lo=>"127.0.0.1", :lsbdistdescription=>"Ubuntu 12.04.2 LTS", :macaddress=>"08:00:27:0f:67:ea", :osfamily=>"Debian", :processors=>{"models"=>["Intel(R) Core(TM)2 Quad CPU    Q6700  @ 2.66GHz"], "physicalcount"=>1, "count"=>1}, :netmask_eth0=>"255.255.255.0", :netmask_lo=>"255.0.0.0", :blockdevice_sr0_model=>"CD-ROM", :uptime_hours=>0, :mtu_eth0=>1500, :physicalprocessorcount=>1, :sshfp_dsa=>"SSHFP 2 1 50660f826759a12fe1a9a798418936739b1e41cf\nSSHFP 2 2 d88a5eee3ca9e8c68f668ad7fd21f5feb8b324bd2efaa35b78fcdcf415496279", :facterversion=>"2.4.0", :sshrsakey=>"AAAAB3NzaC1yc2EAAAADAQABAAABAQCXu5RlDOqQ9yghl+U0dkglhOQD6maadTZ34t8KlEwjFnhOx1jpbKVRG2vIJCDusHcIxYPS+uN4owEFbz7l9MtEwCMkzf9fg1imlzRnItAkFtcDZx/jV/PDWcESnTXhc2DRW51IM3pzyHoYThj/cQF4rRDlif1S0H6uj9soJRQi/ftoB62Zkme4j6/GMhY6iJzH3KifTAd3gxaRdp/28/Ym+Q1YZNXAq/BpnNSTEhg9kyHX6M9aTOfZ1K4jqtQaJSiJxZvVZMcWP2lbwIy3NR2uX6D27LK0vd57XOj49R6RjhAnFEKq1Hxa1qOdQrYEeGLuFqMEVwVT6NNuRgFIpyyx", :uuid=>"3C88DC2E-F7DA-4254-9BA4-2E7B341FD7D9", :blockdevice_sr0_vendor=>"VBOX", :type=>"Other", :gid=>"root", :swapfree_mb=>"512.00", :uptime_seconds=>197, :blockdevice_sr0_size=>1073741312, :swapfree=>"512.00 MB", :hostname=>"foo", :kernel=>"Linux", :fqdn=>"foo.example.com", :interfaces=>"eth0,lo", :ipaddress_eth0=>"10.0.2.15", :boardproductname=>"VirtualBox", :memorysize_mb=>"491.21", :swapsize=>"512.00 MB", :uniqueid=>"007f0101", :operatingsystemrelease=>"12.04", :blockdevice_sr1_model=>"CD-ROM", :rubyversion=>"1.9.3", :kernelversion=>"3.5.0", :network_lo=>"127.0.0.0", :mco_version=>"2.9.0", :puppetversion=>"4.7.0", "systemd"=>false}

Note "systemd"=>false at the end.

More docs changes needed

If I follow the directions at https://github.com/mcanevet/rspec-puppet-facts#specifying-the-supported-operating-systems about specifying a hash to on_supported_os and use the documented hash format, Rubocop complains about using an obsolete hash format.

require 'spec_helper'

describe 'profiles::packagemanager' do
  test_on = {
    :supported_os => [
      {
        'operatingsystem'        => 'Ubuntu',
        'operatingsystemrelease' => ['18.04', '16.04'],
      },
    ],
  }
  on_supported_os(test_on).each do |os, os_facts|
    let(:facts) do
      os_facts
    end

    context "on #{os} with local=true" do
      let :params do
        {
          'local'  => 'true',
          'mirror' => 'ftpmirror.ncl.ac.uk',
        }
      end

      # case os_facts[:operatingsystem]
      # when 'Ubuntu'
      it { is_expected.to compile }
      it {
        is_expected.to contain_class('apt').with(
          'purge'  => { 'sources.list' => 'true' },
          'update' => { 'frequency' => 'always', 'loglevel' => 'debug' },
        )
      }
      it { is_expected.to contain_exec('apt--f-install') }
      it { is_expected.to contain_apt__source('puppetlabs') }
      it { is_expected.to contain_apt__source('ubuntu') }
      it { is_expected.to contain_apt__source('ubuntu-updates') }
      it { is_expected.to contain_apt__source('ubuntu-partner') }
      it { is_expected.to contain_apt__source('ubuntu-security') }
      it { is_expected.to contain_apt__source('telred') }
      it { is_expected.to contain_apt__key('puppetlabs') }
      it { is_expected.to contain_apt__key('ubuntu-archive') }
      it { is_expected.to contain_apt__key('ubuntu-cdimage') }
      it { is_expected.to contain_apt__key('TEL.RED Release Signing Key') }
      # end
    end
  end
end

gives

~/git/PUPPET/puppet5/site/profiles(50-rolesprofiles*) » pdk validate
pdk (INFO): Running all available validators...
pdk (INFO): Using Ruby 2.5.7
pdk (INFO): Using Puppet 6.10.1
[✔] Checking metadata syntax (metadata.json tasks/*.json).
[✔] Checking module metadata style (metadata.json).
[✔] Checking YAML syntax (["**/*.yaml", "*.yaml", "**/*.yml", "*.yml"]).
[✔] Checking Puppet manifest syntax (**/*.pp).
[✔] Checking Puppet manifest style (**/*.pp).
[✖] Checking Ruby code style (**/**.rb).
[✔] Checking task names (tasks/**/*).
info: puppet-epp: ./: Target does not contain any files to validate (**/*.epp).
convention: rubocop: spec/classes/packagemanager_spec.rb:5:5: Style/HashSyntax: Use the new Ruby 1.9 hash syntax.
info: task-metadata-lint: ./: Target does not contain any files to validate (tasks/*.json).

If I update to the newer hash style

  test_on = {
    supported_os: [
      {
        'operatingsystem'        => 'Ubuntu',
        'operatingsystemrelease' => ['18.04', '16.04'],
      },
    ],
  }

Then the validator is happy.

Not being particularly fluent in Ruby, I tried to misstate the newer hash style as follows:

  test_on = {
    supported_os: [
      {
        operatingsystem: 'Ubuntu',
        operatingsystemrelease: ['18.04', '16.04'],
      },
    ],
  }

This gave NoMethodError: undefined method `downcase' for nil:NilClass. Only when I was typing up an issue about the NoMethodError did I stumble upon the correct hash syntax.

I'll make another merge/pull request later when I'm not in the middle of trying to make my profiles actually work.

Unable to change default fact for certain tests

Hi, I need to mock the ipaddress and macaddress fact for two tests, here is my a part of my spec file:

require 'spec_helper'

describe 'profiles::base', type: :class do
  on_supported_os.each do |os, facts|
    context "on #{os} " do
      let :facts do
        # mocked_facts(facts)
        facts
      end 

      context 'the default base profile on all systems' do
        it { should compile.with_all_deps }
        describe 'we create awesome facts' do
          let :facts do
            super().merge(
              ipaddress: '10.16.254.253',
              macaddress: 'AA:BB:CC:DD:EE:FF'
            )
          end
          it do
            should contain_file_line('set-ip').with(
              path: '/etc/facter/facts.d/sach.txt',
              line: 'primary_ip=10.16.254.253'
          )
          end
          it do
            should contain_file_line('set-mac').with(
              path: '/etc/facter/facts.d/sach.txt',
              line: 'primary_mac=AA:BB:CC:DD:EE:FF'
          )
          end
        end
      end
    end
  end
end

This results in:

  1) profiles::base on debian-6-x86_64  the default base profile on all systems we create awesome facts should contain File_line[set-ip] with path => "/etc/facter/facts.d/sach.txt" and line => "primary_ip=10.16.254.253"
     Failure/Error:
         should contain_file_line('set-ip').with(
           path: '/etc/facter/facts.d/sach.txt',
           line: 'primary_ip=10.16.254.253'
       )

       expected that the catalogue would contain File_line[set-ip] with line set to "primary_ip=10.16.254.253" but it is set to "primary_ip=10.0.2.15"
     # ./spec/classes/base_spec.rb:100:in `block (6 levels) in <top (required)>'

  2) profiles::base on debian-6-x86_64  the default base profile on all systems we create awesome facts should contain File_line[set-mac] with path => "/etc/facter/facts.d/sach.txt" and line => "primary_mac=AA:BB:CC:DD:EE:FF"
     Failure/Error:
         should contain_file_line('set-mac').with(
           path: '/etc/facter/facts.d/sach.txt',
           line: 'primary_mac=AA:BB:CC:DD:EE:FF'
       )

       expected that the catalogue would contain File_line[set-mac] with line set to "primary_mac=AA:BB:CC:DD:EE:FF" but it is set to "primary_mac=08:00:27:d9:42:67"
     # ./spec/classes/base_spec.rb:106:in `block (6 levels) in <top (required)>'

Instead of super().merge() I also tried facts.merge(), which resulted in the same error.

Reduce calls to FacterDB

While #122 greatly reduces the expensive calls to on_supported_os, there are still a lot of calls to FacterDB. Some hot code is here:

https://github.com/mcanevet/rspec-puppet-facts/blob/c2987a1b6cd7a9ab104aed8aa7ff61e28ce29cce/lib/rspec-puppet-facts.rb#L115-L141

Effectively for every filter (which is a tuple of OS and release) it does a call to FacterDB to get facts. If there is not an exact match for the requested Facter version it does another. Then once is has collected all this information, it does one last call to FacterDB to get all the data. Note that this last call is effectively redundant because for every iteration the facts for that filter were already retrieved.

This gives us a worst case complexity of 2n+1 where n is the number of supported OS releases.

The most obvious workaround is to record new facts for every facter release. This would reduce it down to n+1 complexity. However, that means the FacterDB itself will grow which may result in other scaling problems.

Perhaps FacterDB could expose a richer API to allow more effective queries. For example, a lambda to filter a fact. This is not supported by jgrep, but something to think about.

Another consideration is to just query without a facterversion filter and then filter out any unwanted results. Then concat those results.

AIX hardware model should not be x86_64

I have been chatting on Puppet Community slack, asking about why my AIX tests aren't working (aren't running for AIX), and someone pointed me to https://github.com/mcanevet/rspec-puppet-facts/blob/010538181409b159c93e265a4648dd966ae77dfb/lib/rspec-puppet-facts.rb#L58-L66

This should have a case for AIX, but I am not sure what hardwaremodel needs to be set to. I was thinking powerpc (uname -p) or isa fact based on what the other operating systems are using. However the "hardwaremodel" fact comes out as something like IBM,8284-22A which is pretty non-useful. It makes me think that either the hardwaremodel is hopelessly generic on other platforms or its incorrectly populated for AIX. Maybe we could just set the hardware model filter to something like /^IBM/ ?

I figured I would start here with a discussion before trying to throw code at it, cause I am soo green when it comes to rspec testing that I am not really sure how to even test this code. :)

NOTE: I recently submitted some facts for reference.

~tommy

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.