Skip to content

Fix user provider specs - #604

Open
jcharaoui wants to merge 2 commits into
OpenVoxProject:mainfrom
jcharaoui:fix_useradd_specs
Open

Fix user provider specs#604
jcharaoui wants to merge 2 commits into
OpenVoxProject:mainfrom
jcharaoui:fix_useradd_specs

Conversation

@jcharaoui

Copy link
Copy Markdown
Contributor

This fixes multiple user provider specs failing with:

NameError:
uninitialized constant Etc::PasswdEntry

which suggests these specs weren't getting much exercise, probably because the CI environment is lacking the ruby-shadow library which in turn disables the Puppet feature transparently.

It also updates a couple assertions that were also outdated.

@jcharaoui

Copy link
Copy Markdown
Contributor Author
Logs of the failing RSpec tests
Failures:

  1) Puppet::Type::User::ProviderOpenbsd#addcmd should return an array with the full command and expiry as MM/DD/YY
     Failure/Error: expect(provider.addcmd).to eq(['/usr/sbin/useradd', '-e', 'June 01 1997', 'myuser'])
       expected: ["/usr/sbin/useradd", "-e", "June 01 1997", "myuser"]
            got: ["/usr/sbin/useradd", "-e", "June 01 1997", "-L", "staff", "myuser"]
       (compared using ==)
     # ./spec/unit/provider/user/openbsd_spec.rb:50:in `block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  2) Puppet::Type::User::ProviderOpenbsd#loginclass should return the loginclass if set
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/openbsd_spec.rb:25:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/openbsd_spec.rb:60:in `block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  3) Puppet::Type::User::ProviderOpenbsd#loginclass should return the empty string when loginclass isn't set
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/openbsd_spec.rb:25:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/openbsd_spec.rb:65:in `block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  4) Puppet::Type::User::ProviderOpenbsd#loginclass should return nil when loginclass isn't available
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/openbsd_spec.rb:25:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/openbsd_spec.rb:71:in `block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
Finished in 10.74 seconds (files took 2.05 seconds to load)

  1) Puppet::Type::User::ProviderUseradd#password_min_age should return the correct value if libshadow is present
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/useradd_spec.rb:32:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/useradd_spec.rb:698:in `block (4 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  2) Puppet::Type::User::ProviderUseradd#password_min_age should query using the canonical_name attribute of the user
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/useradd_spec.rb:32:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/useradd_spec.rb:711:in `block (4 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  3) Puppet::Type::User::ProviderUseradd#password_max_age should return the correct value if libshadow is present
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/useradd_spec.rb:32:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/useradd_spec.rb:698:in `block (4 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  4) Puppet::Type::User::ProviderUseradd#password_max_age should query using the canonical_name attribute of the user
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/useradd_spec.rb:32:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/useradd_spec.rb:711:in `block (4 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  5) Puppet::Type::User::ProviderUseradd#password_warn_days should return the correct value if libshadow is present
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/useradd_spec.rb:32:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/useradd_spec.rb:698:in `block (4 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  6) Puppet::Type::User::ProviderUseradd#password_warn_days should query using the canonical_name attribute of the user
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/useradd_spec.rb:32:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/useradd_spec.rb:711:in `block (4 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  7) Puppet::Type::User::ProviderUseradd#password should return the correct value if libshadow is present
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/useradd_spec.rb:32:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/useradd_spec.rb:698:in `block (4 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  8) Puppet::Type::User::ProviderUseradd#password should query using the canonical_name attribute of the user
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/useradd_spec.rb:32:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/useradd_spec.rb:711:in `block (4 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  9) Puppet::Type::User::ProviderUseradd#expiry should return absent if expiry is -1
     Failure/Error: entry = Etc::PasswdEntry.new
     NameError:
       uninitialized constant Etc::PasswdEntry
     # ./spec/unit/provider/user/useradd_spec.rb:32:in `block (2 levels) in <top (required)>'
     # ./spec/unit/provider/user/useradd_spec.rb:733:in `block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
     # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
     # util/rspec_runner:47:in `run'
     # util/rspec_runner:61:in `<main>'
  10) Puppet::Type::User::ProviderUseradd#expiry should convert to YYYY-MM-DD
      Failure/Error: entry = Etc::PasswdEntry.new
      NameError:
        uninitialized constant Etc::PasswdEntry
      # ./spec/unit/provider/user/useradd_spec.rb:32:in `block (2 levels) in <top (required)>'
      # ./spec/unit/provider/user/useradd_spec.rb:739:in `block (3 levels) in <top (required)>'
      # ./spec/spec_helper.rb:171:in `block (2 levels) in <top (required)>'
      # /usr/share/rubygems-integration/all/gems/webmock-3.26.2/lib/webmock/rspec.rb:39:in `block (2 levels) in <top (required)>'
      # util/rspec_runner:47:in `run'
      # util/rspec_runner:61:in `<main>'
Finished in 5.05 seconds (files took 1.19 seconds to load)

Finished in 1 minute 8.62 seconds
25180 examples, 14 failures, 22 pending

Failed examples:
rspec ./spec/unit/provider/user/openbsd_spec.rb:46 # Puppet::Type::User::ProviderOpenbsd#addcmd should return an array with the full command and expiry as MM/DD/YY
rspec ./spec/unit/provider/user/openbsd_spec.rb:59 # Puppet::Type::User::ProviderOpenbsd#loginclass should return the loginclass if set
rspec ./spec/unit/provider/user/openbsd_spec.rb:64 # Puppet::Type::User::ProviderOpenbsd#loginclass should return the empty string when loginclass isn't set
rspec ./spec/unit/provider/user/openbsd_spec.rb:70 # Puppet::Type::User::ProviderOpenbsd#loginclass should return nil when loginclass isn't available
rspec ./spec/unit/provider/user/useradd_spec.rb[1:16:3] # Puppet::Type::User::ProviderUseradd#password_min_age should return the correct value if libshadow is present
rspec ./spec/unit/provider/user/useradd_spec.rb[1:16:4] # Puppet::Type::User::ProviderUseradd#password_min_age should query using the canonical_name attribute of the user
rspec ./spec/unit/provider/user/useradd_spec.rb[1:17:3] # Puppet::Type::User::ProviderUseradd#password_max_age should return the correct value if libshadow is present
rspec ./spec/unit/provider/user/useradd_spec.rb[1:17:4] # Puppet::Type::User::ProviderUseradd#password_max_age should query using the canonical_name attribute of the user
rspec ./spec/unit/provider/user/useradd_spec.rb[1:18:3] # Puppet::Type::User::ProviderUseradd#password_warn_days should return the correct value if libshadow is present
rspec ./spec/unit/provider/user/useradd_spec.rb[1:18:4] # Puppet::Type::User::ProviderUseradd#password_warn_days should query using the canonical_name attribute of the user
rspec ./spec/unit/provider/user/useradd_spec.rb[1:19:3] # Puppet::Type::User::ProviderUseradd#password should return the correct value if libshadow is present
rspec ./spec/unit/provider/user/useradd_spec.rb[1:19:4] # Puppet::Type::User::ProviderUseradd#password should query using the canonical_name attribute of the user
rspec ./spec/unit/provider/user/useradd_spec.rb:732 # Puppet::Type::User::ProviderUseradd#expiry should return absent if expiry is -1
rspec ./spec/unit/provider/user/useradd_spec.rb:738 # Puppet::Type::User::ProviderUseradd#expiry should convert to YYYY-MM-DD

@jcharaoui

jcharaoui commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

I believe the failing testcase is due to a mismatch of ruby-shadow lib versions.

In Debian we use 2.5.1, which should be the latest release.

I couldn't tell which version is used in the CI environment.

Comment thread spec/unit/provider/user/openbsd_spec.rb Outdated
This fixes multiple user provider specs failing with:

  NameError:
    uninitialized constant Etc::PasswdEntry

which suggests these specs weren't getting much exercise, probably
because the CI environment is lacking the ruby-shadow library which in
turn disables the Puppet feature transparently.

It also updates a couple assertions that were also outdated.

Signed-off-by: Jérôme Charaoui <jerome@riseup.net>
Signed-off-by: Jérôme Charaoui <jerome@riseup.net>
@@ -22,7 +22,7 @@

let(:shadow_entry) {
return unless Puppet.features.libshadow?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we never executed that test in CI because the ruby-shadow gem is missing and then the return hits?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(we need to get the gem into our CI)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think that's correct. Installing the gem in CI would be well-advised, IMHO.

let(:shadow_entry) {
return unless Puppet.features.libshadow?
entry = Etc::PasswdEntry.new
entry = Shadow::Passwd::Entry.new

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this requried? did the API for the ruby-shadow gem change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I mentioned in the OP, Etc::PasswdEntry doesn't exist, so the test crashes right there, but only when ruby-shadow is available in the environment, which is why it wasn't caught earlier.

If you look at dd3df54 it sounds like the intention was to change it to Etc::Passwd not Etc::PasswdEntry (which doesn't seem to have existed, ever) but that doesn't work either, and it was never caught because again, the spec never actually ran in CI...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants