Skip to content

Commit

Permalink
Merge pull request #5 from EncoreTechnologies/feature/unit-testing
Browse files Browse the repository at this point in the history
Added lots of unit testing for ipa_kinit
  • Loading branch information
nmaludy authored Jan 14, 2021
2 parents 03b615a + 616859e commit 0b8b2cb
Show file tree
Hide file tree
Showing 9 changed files with 339 additions and 14 deletions.
3 changes: 2 additions & 1 deletion .sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ Gemfile:
- gem: 'yaml-lint'
version: '>= 0.0.10'
spec/spec_helper.rb:
mock_with: ':mocha'
# rspec mock is preferred, mocha was old (according to puppetlabs_spec_helper/CHANGELOG.md)
mock_with: ':rspec'
strict_level: ':warning'
spec_overrides:
# print out really long exception messages (this prevents them from being truncated)
Expand Down
10 changes: 3 additions & 7 deletions lib/facter/ipa_login_defs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,16 @@
confine { File.exist?('/etc/login.defs') }

setcode do
regex_login_defs = Regexp.new(%r{^\s*([A-Z_0-9]+)\s+(\d+)(\s*#.*)?$})
regex_login_defs = Regexp.new(%r{^\s*([A-Z_0-9]+)\s+(.+)(\s*#.*)?$})
lines_array = File.readlines('/etc/login.defs')
login_defs = {}
lines_array.each do |line|
match = line.match(regex_login_defs)
next unless match
param = match.captures[0]
value = match.captures[1]
begin
# try casting to an int, if it fails, no big deal
value = value.to_i
rescue TypeError
nil # empty statement to suppress rubocop
end
# if the string only contains numbers, cast it to a number
value = value.to_i if value =~ %r{^\d+$}
login_defs[param] = value
end
login_defs
Expand Down
4 changes: 3 additions & 1 deletion lib/puppet/provider/ipa_kinit/default.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'ipa'))

Puppet::Type.type(:ipa_kinit).provide(:default, parent: Puppet::Provider::Ipa) do
defaultfor kernel: 'Linux'

commands kinit: 'kinit'
commands klist: 'klist'
commands kdestroy: 'kdestroy'
Expand Down Expand Up @@ -59,7 +61,7 @@ def read_instance
break
end
rescue Puppet::ExecutionFailure => e
Puppet.debug("lklist returned an error: #{e}")
Puppet.debug("klist returned an error: #{e}")
end
instance = { ensure: :absent, name: resource[:name] } if instance.nil?
Puppet.debug("klist instance = #{instance}")
Expand Down
2 changes: 1 addition & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

RSpec.configure do |c|
c.mock_with :mocha
c.mock_with :rspec
end

require 'puppetlabs_spec_helper/module_spec_helper'
Expand Down
9 changes: 5 additions & 4 deletions spec/spec_helper_local.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
def mock_firewalld
before(:each) do
# mock out exec resource for firewalld::reload
output = mock
output.stubs(:exitstatus).returns(0)
Puppet::Util::Execution.stubs(:execute).returns(output)
output = double
allow(output).to receive(:exitstatus).and_return(0)

allow_any_instance_of(Puppet::Util::Execution).to receive(:execute).and_return(output) # rubocop:disable RSpec/AnyInstance

# mock out firewalld so we don't get prompts
Puppet::Provider::Firewalld.any_instance.stubs(:running).returns(:true) # rubocop:disable RSpec/AnyInstance
allow_any_instance_of(Puppet::Provider::Firewalld).to receive(:running).and_return(:true) # rubocop:disable RSpec/AnyInstance
end
end
55 changes: 55 additions & 0 deletions spec/unit/facter/ipa_login_defs_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
require 'spec_helper'
require 'facter'
require 'facter/ipa_login_defs'

describe 'ipa_login_defs', type: :fact do
subject(:fact) { Facter.fact(subject) }

let(:mock_etc_login_defs) do
str = <<-EOS
#
# Please note that the parameters in this configuration file control the
# behavior of the tools from the shadow-utils component. None of these
# tools uses the PAM mechanism, and the utilities that use PAM (such as the
# passwd command) should therefore be configured elsewhere. Refer to
# /etc/pam.d/system-auth for more information.
#
MAIL_DIR /var/spool/mail
#
# Min/max values for automatic uid selection in useradd
#
UID_MIN 1000
UID_MAX 60000
#
# Min/max values for automatic gid selection in groupadd
#
GID_MIN 1000
GID_MAX 60000
# Use SHA512 to encrypt password.
ENCRYPT_METHOD SHA512
EOS
str.lines
end

before :each do
Facter.clear
end

it 'returns a value' do
# mock the File.readlines and give it some fake output of our file
expect(File).to receive(:readlines).with('/etc/login.defs').and_return(mock_etc_login_defs)
expected_fact = {
'MAIL_DIR' => '/var/spool/mail',
'UID_MIN' => 1_000,
'UID_MAX' => 60_000,
'GID_MIN' => 1_000,
'GID_MAX' => 60_000,
'ENCRYPT_METHOD' => 'SHA512',
}
expect(Facter.fact(:ipa_login_defs).value).to eq(expected_fact)
end
end
162 changes: 162 additions & 0 deletions spec/unit/puppet/provider/ipa_kinit/default_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
require 'spec_helper'

describe Puppet::Type.type(:ipa_kinit).provider(:default) do
let(:name) { 'admin' }
let(:properties) do
{
# this provider: is necessary, otherwise this provider isn't chosen
provider: described_class.name,
name: name,
ensure: :present,
password: 'AdminPassword123',
}
end
let(:resource) { Puppet::Type.type(:ipa_kinit).new(properties) }
let(:provider) { resource.provider }

describe '#read_instance' do
it 'return a resource when name matches' do
klist_return = <<-EOS
Principal name Cache name
-------------- ----------
[email protected] KCM:0
EOS
prov = resource.provider
expect(prov).to receive(:klist).with('-l').and_return(klist_return)
expect(prov.read_instance).to eq(ensure: :present,
name: name,
principal_name: '[email protected]')
end

it 'return {ensure: absent} instance when no names match' do
klist_return = <<-EOS
Principal name Cache name
-------------- ----------
[email protected] KCM:0
EOS
expect(provider).to receive(:klist).with('-l').and_return(klist_return)
expect(provider.read_instance).to eq(ensure: :absent, name: name)
end

it 'return good instance when realm isnt passed in, as long as user matches' do
klist_return = <<-EOS
Principal name Cache name
-------------- ----------
[email protected] KCM:0
EOS
expect(provider).to receive(:klist).with('-l').and_return(klist_return)
expect(provider.read_instance).to eq(ensure: :present,
name: name,
principal_name: '[email protected]')
end

it 'return {ensure: absent} instance when klist fails' do
expect(provider).to receive(:klist).with('-l').and_raise(Puppet::ExecutionFailure.new('x'))
expect(provider.read_instance).to eq(ensure: :absent, name: name)
end

context 'with realm set' do
let(:properties) do
{
# this provider: is necessary, otherwise this provider isn't chosen
provider: described_class.name,
name: name,
realm: 'EXPECTED.DOMAIN.TLD',
}
end

it 'return a resource when name and realm matches' do
klist_return = <<-EOS
Principal name Cache name
-------------- ----------
[email protected] KCM:0
EOS
expect(provider).to receive(:klist).with('-l').and_return(klist_return)
expect(provider.read_instance).to eq(ensure: :present,
name: name,
principal_name: '[email protected]',
realm: 'EXPECTED.DOMAIN.TLD')
end

it 'return a {ensure: absent} instance when name matches but realm doesnt match' do
klist_return = <<-EOS
Principal name Cache name
-------------- ----------
[email protected] KCM:0
EOS
expect(provider).to receive(:klist).with('-l').and_return(klist_return)
expect(provider.read_instance).to eq(ensure: :absent, name: name)
end
end
end

describe '#flush_instance' do
context 'when destroying' do
let(:properties) do
{
# this provider: is necessary, otherwise this provider isn't chosen
provider: described_class.name,
name: name,
ensure: :absent,
}
end

let(:provider) do
prov = resource.provider
props = { principal_name: '[email protected]' }
prov.instance_variable_set(:@cached_instance, properties.merge(props))
prov
end

it 'run kdestroy with the principal name' do
expect(provider).to receive(:kdestroy).with(['-p', '[email protected]'])
provider.flush_instance
end
end

context 'when creating' do
it 'run kinit with username and password' do
command_str = 'echo $KINIT_PASSWORD | /bin/kinit admin'
expect(provider).to receive(:command).with(:kinit).and_return('/bin/kinit')
expect(Puppet::Util::Execution).to receive(:execute).with(
command_str,
override_locale: false,
failonfail: true,
combine: true,
custom_environment: {
'KINIT_PASSWORD' => 'AdminPassword123',
},
)
provider.flush_instance
end

context 'with realm' do
let(:properties) do
{
# this provider: is necessary, otherwise this provider isn't chosen
provider: described_class.name,
name: name,
ensure: :present,
password: 'AdminPassword123',
realm: 'EXPECTED.DOMAIN.TLD',
}
end

it 'run kinit with username@realm specified' do
command_str = 'echo $KINIT_PASSWORD | /bin/kinit [email protected]'
expect(provider).to receive(:command).with(:kinit).and_return('/bin/kinit')
expect(Puppet::Util::Execution).to receive(:execute).with(
command_str,
override_locale: false,
failonfail: true,
combine: true,
custom_environment: {
'KINIT_PASSWORD' => 'AdminPassword123',
},
)
provider.flush_instance
end
end
end
end
end
19 changes: 19 additions & 0 deletions spec/unit/puppet/provider/ipa_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# require 'spec_helper'

# describe Puppet::Type.type("provider").provider("ipa") do
# let (:provider) { subject }
# let(:properties) do
# {}
# end
# let(:resource) { subject.new(properties) }

# it 'should return an array of instances' do
# expect(subject.instances).to be_instance_of(Array)
# end

# describe 'getter property methods' do
# end

# describe 'setter property methods' do
# end
# end
Loading

0 comments on commit 0b8b2cb

Please sign in to comment.