puppet 7.0.0 → 7.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CODEOWNERS +2 -16
- data/Gemfile +2 -3
- data/Gemfile.lock +13 -9
- data/ext/project_data.yaml +1 -0
- data/lib/puppet/application_support.rb +7 -0
- data/lib/puppet/defaults.rb +1 -27
- data/lib/puppet/environments.rb +38 -54
- data/lib/puppet/face/node/clean.rb +8 -0
- data/lib/puppet/ffi/posix.rb +10 -0
- data/lib/puppet/ffi/posix/constants.rb +14 -0
- data/lib/puppet/ffi/posix/functions.rb +24 -0
- data/lib/puppet/parser/templatewrapper.rb +1 -1
- data/lib/puppet/provider/user/aix.rb +2 -2
- data/lib/puppet/type/user.rb +1 -1
- data/lib/puppet/util/posix.rb +53 -4
- data/lib/puppet/version.rb +1 -1
- data/man/man5/puppet.conf.5 +2 -2
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/fixtures/unit/provider/user/aix/aix_passwd_file.out +4 -0
- data/spec/unit/application_spec.rb +34 -0
- data/spec/unit/defaults_spec.rb +1 -56
- data/spec/unit/environments_spec.rb +96 -19
- data/spec/unit/face/node_spec.rb +14 -2
- data/spec/unit/parser/templatewrapper_spec.rb +4 -3
- data/spec/unit/provider/user/aix_spec.rb +5 -0
- data/spec/unit/provider/user/pw_spec.rb +2 -0
- data/spec/unit/provider/user/useradd_spec.rb +1 -0
- data/spec/unit/util/posix_spec.rb +357 -15
- data/spec/unit/util/storage_spec.rb +3 -1
- metadata +19 -2
@@ -629,19 +629,6 @@ config_version=$vardir/random/scripts
|
|
629
629
|
context "expiration policies" do
|
630
630
|
let(:service) { ReplayExpirationService.new }
|
631
631
|
|
632
|
-
# The environment named `:an_environment` will already be loaded when the
|
633
|
-
# block is yielded to
|
634
|
-
def with_environment_loaded(service, &block)
|
635
|
-
loader_from(:filesystem => [directory_tree], :directory => directory_tree.children.first) do |loader|
|
636
|
-
using_expiration_service(service) do
|
637
|
-
cached = Puppet::Environments::Cached.new(loader)
|
638
|
-
cached.get!(:an_environment)
|
639
|
-
|
640
|
-
yield cached if block_given?
|
641
|
-
end
|
642
|
-
end
|
643
|
-
end
|
644
|
-
|
645
632
|
it "notifies when the environment is first created" do
|
646
633
|
with_environment_loaded(service)
|
647
634
|
|
@@ -662,10 +649,7 @@ config_version=$vardir/random/scripts
|
|
662
649
|
it "evicts an expired environment" do
|
663
650
|
service = ReplayExpirationService.new
|
664
651
|
|
665
|
-
|
666
|
-
# no entries are expired. But if `Time.now < @next_expiration` and there is
|
667
|
-
# an expired entry, then the `service#expired?` method is called twice.
|
668
|
-
expect(service).to receive(:expired?).twice.and_return(true)
|
652
|
+
expect(service).to receive(:expired?).and_return(true)
|
669
653
|
|
670
654
|
with_environment_loaded(service) do |cached|
|
671
655
|
cached.get!(:an_environment)
|
@@ -706,8 +690,7 @@ config_version=$vardir/random/scripts
|
|
706
690
|
it "evicts a recently touched environment" do
|
707
691
|
Puppet[:environment_timeout] = 60
|
708
692
|
|
709
|
-
|
710
|
-
expect(service).to receive(:expired?).twice.and_return(true)
|
693
|
+
expect(service).to receive(:expired?).and_return(true)
|
711
694
|
|
712
695
|
with_environment_loaded(service) do |cached|
|
713
696
|
# even though the environment was recently touched, it's been expired
|
@@ -726,6 +709,87 @@ config_version=$vardir/random/scripts
|
|
726
709
|
with_global_module_path([])
|
727
710
|
end
|
728
711
|
end
|
712
|
+
|
713
|
+
context '#clear' do
|
714
|
+
let(:service) { ReplayExpirationService.new }
|
715
|
+
|
716
|
+
it "evicts an environment" do
|
717
|
+
with_environment_loaded(service) do |cached|
|
718
|
+
cached.clear(:an_environment)
|
719
|
+
end
|
720
|
+
|
721
|
+
expect(service.evicted_envs).to eq([:an_environment])
|
722
|
+
end
|
723
|
+
end
|
724
|
+
|
725
|
+
context '#clear_all' do
|
726
|
+
let(:service) { ReplayExpirationService.new }
|
727
|
+
|
728
|
+
it 'evicts all environments' do
|
729
|
+
with_environment_loaded(service) do |cached|
|
730
|
+
cached.get(:an_environment)
|
731
|
+
cached.get(:another_environment)
|
732
|
+
cached.clear_all
|
733
|
+
|
734
|
+
expect(service.evicted_envs).to match([:an_environment, :another_environment])
|
735
|
+
end
|
736
|
+
end
|
737
|
+
|
738
|
+
it 'clears cached environment settings' do
|
739
|
+
base_dir = File.expand_path("envdir")
|
740
|
+
original_envdir = FS::MemoryFile.a_directory(base_dir, [
|
741
|
+
FS::MemoryFile.a_directory("env3", [
|
742
|
+
FS::MemoryFile.a_regular_file_containing("environment.conf", <<-EOF)
|
743
|
+
manifest=/manifest_orig
|
744
|
+
modulepath=/modules_orig
|
745
|
+
environment_timeout=60
|
746
|
+
EOF
|
747
|
+
]),
|
748
|
+
])
|
749
|
+
|
750
|
+
FS.overlay(original_envdir) do
|
751
|
+
dir_loader = Puppet::Environments::Directories.new(original_envdir, [])
|
752
|
+
loader = Puppet::Environments::Cached.new(dir_loader)
|
753
|
+
Puppet.override(:environments => loader) do
|
754
|
+
original_env = loader.get("env3") # force the environment.conf to be read
|
755
|
+
|
756
|
+
changed_envdir = FS::MemoryFile.a_directory(base_dir, [
|
757
|
+
FS::MemoryFile.a_directory("env3", [
|
758
|
+
FS::MemoryFile.a_regular_file_containing("environment.conf", <<-EOF)
|
759
|
+
manifest=/manifest_changed
|
760
|
+
modulepath=/modules_changed
|
761
|
+
environment_timeout=60
|
762
|
+
EOF
|
763
|
+
]),
|
764
|
+
])
|
765
|
+
|
766
|
+
#Clear all cached environments
|
767
|
+
loader.clear_all
|
768
|
+
|
769
|
+
FS.overlay(changed_envdir) do
|
770
|
+
changed_env = loader.get("env3")
|
771
|
+
|
772
|
+
expect(original_env).to environment(:env3).
|
773
|
+
with_manifest(File.expand_path("/manifest_orig")).
|
774
|
+
with_full_modulepath([File.expand_path("/modules_orig")])
|
775
|
+
|
776
|
+
expect(changed_env).to environment(:env3).
|
777
|
+
with_manifest(File.expand_path("/manifest_changed")).
|
778
|
+
with_full_modulepath([File.expand_path("/modules_changed")])
|
779
|
+
end
|
780
|
+
end
|
781
|
+
end
|
782
|
+
end
|
783
|
+
|
784
|
+
it 'deletes environment text domains' do
|
785
|
+
with_environment_loaded(service) do |cached|
|
786
|
+
cached.get(:an_environment)
|
787
|
+
cached.clear_all
|
788
|
+
|
789
|
+
expect(FastGettext.text_domain).to eq(Puppet::GettextConfig::DEFAULT_TEXT_DOMAIN)
|
790
|
+
end
|
791
|
+
end
|
792
|
+
end
|
729
793
|
end
|
730
794
|
|
731
795
|
RSpec::Matchers.define :environment do |name|
|
@@ -820,6 +884,19 @@ config_version=$vardir/random/scripts
|
|
820
884
|
end
|
821
885
|
end
|
822
886
|
|
887
|
+
# The environment named `:an_environment` will already be loaded when the
|
888
|
+
# block is yielded to
|
889
|
+
def with_environment_loaded(service, &block)
|
890
|
+
loader_from(:filesystem => [directory_tree], :directory => directory_tree.children.first) do |loader|
|
891
|
+
using_expiration_service(service) do
|
892
|
+
cached = Puppet::Environments::Cached.new(loader)
|
893
|
+
cached.get!(:an_environment)
|
894
|
+
|
895
|
+
yield cached if block_given?
|
896
|
+
end
|
897
|
+
end
|
898
|
+
end
|
899
|
+
|
823
900
|
class ReplayExpirationService < Puppet::Environments::Cached::DefaultCacheExpirationService
|
824
901
|
attr_reader :created_envs, :evicted_envs
|
825
902
|
|
data/spec/unit/face/node_spec.rb
CHANGED
@@ -89,8 +89,20 @@ describe Puppet::Face[:node, '0.0.1'] do
|
|
89
89
|
|
90
90
|
describe "when cleaning certificate", :if => Puppet.features.puppetserver_ca? do
|
91
91
|
it "should call the CA CLI gem's clean action" do
|
92
|
-
expect_any_instance_of(Puppetserver::Ca::Action::Clean).
|
93
|
-
|
92
|
+
expect_any_instance_of(Puppetserver::Ca::Action::Clean).
|
93
|
+
to receive(:clean_certs).
|
94
|
+
with(['hostname'], anything).
|
95
|
+
and_return(:success)
|
96
|
+
|
97
|
+
if Puppet[:cadir].start_with?(Puppet[:ssldir])
|
98
|
+
expect_any_instance_of(LoggerIO).
|
99
|
+
to receive(:warn).
|
100
|
+
with(/cadir is currently configured to be inside/)
|
101
|
+
end
|
102
|
+
|
103
|
+
expect(Puppet).not_to receive(:warning)
|
104
|
+
result = subject.clean_cert('hostname')
|
105
|
+
expect(result).to eq(0)
|
94
106
|
end
|
95
107
|
|
96
108
|
it "should not call the CA CLI gem's clean action if the gem is missing" do
|
@@ -57,9 +57,10 @@ describe Puppet::Parser::TemplateWrapper do
|
|
57
57
|
expect(tw.all_tags).to eq(["tag1","tag2"])
|
58
58
|
end
|
59
59
|
|
60
|
-
it "
|
61
|
-
expect
|
62
|
-
|
60
|
+
it "raises not implemented error" do
|
61
|
+
expect {
|
62
|
+
tw.tags
|
63
|
+
}.to raise_error(NotImplementedError, /Call 'all_tags' instead/)
|
63
64
|
end
|
64
65
|
|
65
66
|
it "raises error on access to removed in-scope variables via method calls" do
|
@@ -143,6 +143,11 @@ describe 'Puppet::Type::User::Provider::Aix' do
|
|
143
143
|
it "returns the user's password" do
|
144
144
|
expect(call_parse_password).to eql('some_password')
|
145
145
|
end
|
146
|
+
|
147
|
+
it "returns the user's password with tabs" do
|
148
|
+
resource[:name] = 'tab_password_user'
|
149
|
+
expect(call_parse_password).to eql('some_password')
|
150
|
+
end
|
146
151
|
end
|
147
152
|
|
148
153
|
# TODO: If we move from using Mocha to rspec's mocks,
|
@@ -53,12 +53,14 @@ describe Puppet::Type.type(:user).provider(:pw) do
|
|
53
53
|
|
54
54
|
it "should use -G with the correct argument when the groups property is set" do
|
55
55
|
resource[:groups] = "group1"
|
56
|
+
allow(Puppet::Util::POSIX).to receive(:groups_of).with('testuser').and_return([])
|
56
57
|
expect(provider).to receive(:execute).with(include("-G").and(include("group1")), kind_of(Hash))
|
57
58
|
provider.create
|
58
59
|
end
|
59
60
|
|
60
61
|
it "should use -G with all the given groups when the groups property is set to an array" do
|
61
62
|
resource[:groups] = ["group1", "group2"]
|
63
|
+
allow(Puppet::Util::POSIX).to receive(:groups_of).with('testuser').and_return([])
|
62
64
|
expect(provider).to receive(:execute).with(include("-G").and(include("group1,group2")), kind_of(Hash))
|
63
65
|
provider.create
|
64
66
|
end
|
@@ -4,6 +4,7 @@ RSpec::Matchers.define_negated_matcher :excluding, :include
|
|
4
4
|
|
5
5
|
describe Puppet::Type.type(:user).provider(:useradd) do
|
6
6
|
before :each do
|
7
|
+
allow(Puppet::Util::POSIX).to receive(:groups_of).and_return([])
|
7
8
|
allow(described_class).to receive(:command).with(:password).and_return('/usr/bin/chage')
|
8
9
|
allow(described_class).to receive(:command).with(:localpassword).and_return('/usr/sbin/lchage')
|
9
10
|
allow(described_class).to receive(:command).with(:add).and_return('/usr/sbin/useradd')
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
require 'puppet/ffi/posix'
|
3
4
|
require 'puppet/util/posix'
|
4
5
|
|
5
6
|
class PosixTest
|
@@ -11,35 +12,338 @@ describe Puppet::Util::POSIX do
|
|
11
12
|
@posix = PosixTest.new
|
12
13
|
end
|
13
14
|
|
14
|
-
describe '.groups_of' do
|
15
|
+
describe '.groups_of' do
|
16
|
+
let(:mock_user_data) { double(user, :gid => 1000) }
|
17
|
+
|
18
|
+
let(:ngroups_ptr) { double('FFI::MemoryPointer', :address => 0x0001, :size => 4) }
|
19
|
+
let(:groups_ptr) { double('FFI::MemoryPointer', :address => 0x0002, :size => Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS) }
|
20
|
+
|
15
21
|
let(:mock_groups) do
|
16
22
|
[
|
17
|
-
['
|
18
|
-
['
|
19
|
-
['group1', ['user1', 'user2']],
|
20
|
-
['
|
21
|
-
['
|
22
|
-
|
23
|
+
['root', ['root'], 0],
|
24
|
+
['nomembers', [], 5 ],
|
25
|
+
['group1', ['user1', 'user2'], 1001],
|
26
|
+
['group2', ['user2'], 2002],
|
27
|
+
['group1', ['user1', 'user2'], 1001],
|
28
|
+
['group3', ['user1'], 3003],
|
29
|
+
['group4', ['user2'], 4004],
|
30
|
+
['user1', [], 1111],
|
31
|
+
['user2', [], 2222]
|
32
|
+
].map do |(name, members, gid)|
|
23
33
|
group_struct = double("Group #{name}")
|
24
34
|
allow(group_struct).to receive(:name).and_return(name)
|
25
35
|
allow(group_struct).to receive(:mem).and_return(members)
|
36
|
+
allow(group_struct).to receive(:gid).and_return(gid)
|
26
37
|
|
27
38
|
group_struct
|
28
39
|
end
|
29
40
|
end
|
30
41
|
|
42
|
+
def prepare_user_and_groups_env(user, groups)
|
43
|
+
groups_gids = []
|
44
|
+
groups_and_user = []
|
45
|
+
groups_and_user.replace(groups)
|
46
|
+
groups_and_user.push(user)
|
47
|
+
|
48
|
+
groups_and_user.each do |group|
|
49
|
+
mock_group = mock_groups.find { |m| m.name == group }
|
50
|
+
groups_gids.push(mock_group.gid)
|
51
|
+
|
52
|
+
allow(Puppet::Etc).to receive(:getgrgid).with(mock_group.gid).and_return(mock_group)
|
53
|
+
end
|
54
|
+
|
55
|
+
if groups_and_user.size > Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS
|
56
|
+
allow(ngroups_ptr).to receive(:read_int).and_return(Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS, groups_and_user.size)
|
57
|
+
else
|
58
|
+
allow(ngroups_ptr).to receive(:read_int).and_return(groups_and_user.size)
|
59
|
+
end
|
60
|
+
|
61
|
+
allow(groups_ptr).to receive(:get_array_of_uint).with(0, groups_and_user.size).and_return(groups_gids)
|
62
|
+
allow(Puppet::Etc).to receive(:getpwnam).with(user).and_return(mock_user_data)
|
63
|
+
end
|
64
|
+
|
31
65
|
before(:each) do
|
32
|
-
|
33
|
-
|
34
|
-
|
66
|
+
allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist).and_return(true)
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'when it uses FFI function getgrouplist' do
|
70
|
+
before(:each) do
|
71
|
+
allow(FFI::MemoryPointer).to receive(:new).with(:int).and_yield(ngroups_ptr)
|
72
|
+
allow(FFI::MemoryPointer).to receive(:new).with(:uint, Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS).and_yield(groups_ptr)
|
73
|
+
allow(ngroups_ptr).to receive(:write_int).with(Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS).and_return(ngroups_ptr)
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'when there are groups' do
|
77
|
+
context 'for user1' do
|
78
|
+
let(:user) { 'user1' }
|
79
|
+
let(:expected_groups) { ['group1', 'group3'] }
|
80
|
+
|
81
|
+
before(:each) do
|
82
|
+
prepare_user_and_groups_env(user, expected_groups)
|
83
|
+
allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should return the groups for given user" do
|
87
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should not print any debug message about falling back to Puppet::Etc.group' do
|
91
|
+
expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
|
92
|
+
Puppet::Util::POSIX.groups_of(user)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'for user2' do
|
97
|
+
let(:user) { 'user2' }
|
98
|
+
let(:expected_groups) { ['group1', 'group2', 'group4'] }
|
99
|
+
|
100
|
+
before(:each) do
|
101
|
+
prepare_user_and_groups_env(user, expected_groups)
|
102
|
+
allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should return the groups for given user" do
|
106
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should not print any debug message about falling back to Puppet::Etc.group' do
|
110
|
+
expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
|
111
|
+
Puppet::Util::POSIX.groups_of(user)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'when there are no groups' do
|
117
|
+
let(:user) { 'nomembers' }
|
118
|
+
let(:expected_groups) { [] }
|
119
|
+
|
120
|
+
before(:each) do
|
121
|
+
prepare_user_and_groups_env(user, expected_groups)
|
122
|
+
allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should return no groups for given user" do
|
126
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should not print any debug message about falling back to Puppet::Etc.group' do
|
130
|
+
expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
|
131
|
+
Puppet::Util::POSIX.groups_of(user)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe 'when primary group explicitly contains user' do
|
136
|
+
let(:user) { 'root' }
|
137
|
+
let(:expected_groups) { ['root'] }
|
138
|
+
|
139
|
+
before(:each) do
|
140
|
+
prepare_user_and_groups_env(user, expected_groups)
|
141
|
+
allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should return the groups, including primary group, for given user" do
|
145
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should not print any debug message about falling back to Puppet::Etc.group' do
|
149
|
+
expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
|
150
|
+
Puppet::Util::POSIX.groups_of(user)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe 'when primary group does not explicitly contain user' do
|
155
|
+
let(:user) { 'user1' }
|
156
|
+
let(:expected_groups) { ['group1', 'group3'] }
|
157
|
+
|
158
|
+
before(:each) do
|
159
|
+
prepare_user_and_groups_env(user, expected_groups)
|
160
|
+
allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should not return primary group for given user" do
|
164
|
+
expect(Puppet::Util::POSIX.groups_of(user)).not_to include(user)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should not print any debug message about falling back to Puppet::Etc.group' do
|
168
|
+
expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
|
169
|
+
Puppet::Util::POSIX.groups_of(user)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'number of groups' do
|
174
|
+
before(:each) do
|
175
|
+
stub_const("Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS", 2)
|
176
|
+
prepare_user_and_groups_env(user, expected_groups)
|
177
|
+
|
178
|
+
allow(FFI::MemoryPointer).to receive(:new).with(:uint, Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS).and_yield(groups_ptr)
|
179
|
+
allow(ngroups_ptr).to receive(:write_int).with(Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS).and_return(ngroups_ptr)
|
180
|
+
end
|
181
|
+
|
182
|
+
describe 'when there are less than maximum expected number of groups' do
|
183
|
+
let(:user) { 'root' }
|
184
|
+
let(:expected_groups) { ['root'] }
|
185
|
+
|
186
|
+
before(:each) do
|
187
|
+
allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(1)
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should return the groups for given user, after one 'getgrouplist' call" do
|
191
|
+
expect(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).once
|
192
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'should not print any debug message about falling back to Puppet::Etc.group' do
|
196
|
+
expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
|
197
|
+
Puppet::Util::POSIX.groups_of(user)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe 'when there are more than maximum expected number of groups' do
|
202
|
+
let(:user) { 'user1' }
|
203
|
+
let(:expected_groups) { ['group1', 'group3'] }
|
204
|
+
|
205
|
+
before(:each) do
|
206
|
+
allow(FFI::MemoryPointer).to receive(:new).with(:uint, Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS * 2).and_yield(groups_ptr)
|
207
|
+
allow(ngroups_ptr).to receive(:write_int).with(Puppet::FFI::POSIX::Constants::MAXIMUM_NUMBER_OF_GROUPS * 2).and_return(ngroups_ptr)
|
208
|
+
|
209
|
+
allow(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).and_return(-1, 1)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should return the groups for given user, after two 'getgrouplist' calls" do
|
213
|
+
expect(Puppet::FFI::POSIX::Functions).to receive(:getgrouplist).twice
|
214
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should not print any debug message about falling back to Puppet::Etc.group' do
|
218
|
+
expect(Puppet).not_to receive(:debug).with(/Falling back to Puppet::Etc.group:/)
|
219
|
+
Puppet::Util::POSIX.groups_of(user)
|
220
|
+
end
|
221
|
+
end
|
35
222
|
end
|
36
|
-
allow(Puppet::Etc).to etc_stub
|
37
223
|
end
|
38
224
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
225
|
+
describe 'when it falls back to Puppet::Etc.group method' do
|
226
|
+
before(:each) do
|
227
|
+
etc_stub = receive(:group)
|
228
|
+
mock_groups.each do |mock_group|
|
229
|
+
etc_stub = etc_stub.and_yield(mock_group)
|
230
|
+
end
|
231
|
+
allow(Puppet::Etc).to etc_stub
|
232
|
+
|
233
|
+
allow(Puppet::Etc).to receive(:getpwnam).with(user).and_raise(ArgumentError, "can't find user for #{user}")
|
234
|
+
allow(Puppet).to receive(:debug)
|
235
|
+
|
236
|
+
expect(Puppet::FFI::POSIX::Functions).not_to receive(:getgrouplist)
|
237
|
+
end
|
238
|
+
|
239
|
+
describe 'when there are groups' do
|
240
|
+
context 'for user1' do
|
241
|
+
let(:user) { 'user1' }
|
242
|
+
let(:expected_groups) { ['group1', 'group3'] }
|
243
|
+
|
244
|
+
it "should return the groups for given user" do
|
245
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'logs a debug message' do
|
249
|
+
expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: can't find user for #{user}")
|
250
|
+
Puppet::Util::POSIX.groups_of(user)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
context 'for user2' do
|
255
|
+
let(:user) { 'user2' }
|
256
|
+
let(:expected_groups) { ['group1', 'group2', 'group4'] }
|
257
|
+
|
258
|
+
it "should return the groups for given user" do
|
259
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'logs a debug message' do
|
263
|
+
expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: can't find user for #{user}")
|
264
|
+
Puppet::Util::POSIX.groups_of(user)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
describe 'when there are no groups' do
|
270
|
+
let(:user) { 'nomembers' }
|
271
|
+
let(:expected_groups) { [] }
|
272
|
+
|
273
|
+
it "should return no groups for given user" do
|
274
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'logs a debug message' do
|
278
|
+
expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: can't find user for #{user}")
|
279
|
+
Puppet::Util::POSIX.groups_of(user)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe 'when primary group explicitly contains user' do
|
284
|
+
let(:user) { 'root' }
|
285
|
+
let(:expected_groups) { ['root'] }
|
286
|
+
|
287
|
+
it "should return the groups, including primary group, for given user" do
|
288
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'logs a debug message' do
|
292
|
+
expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: can't find user for #{user}")
|
293
|
+
Puppet::Util::POSIX.groups_of(user)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
describe 'when primary group does not explicitly contain user' do
|
298
|
+
let(:user) { 'user1' }
|
299
|
+
let(:expected_groups) { ['group1', 'group3'] }
|
300
|
+
|
301
|
+
it "should not return primary group for given user" do
|
302
|
+
expect(Puppet::Util::POSIX.groups_of(user)).not_to include(user)
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'logs a debug message' do
|
306
|
+
expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: can't find user for #{user}")
|
307
|
+
Puppet::Util::POSIX.groups_of(user)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe "when the 'getgrouplist' method is not available" do
|
312
|
+
let(:user) { 'user1' }
|
313
|
+
let(:expected_groups) { ['group1', 'group3'] }
|
314
|
+
|
315
|
+
before(:each) do
|
316
|
+
allow(Puppet::FFI::POSIX::Functions).to receive(:respond_to?).with(:getgrouplist).and_return(false)
|
317
|
+
end
|
318
|
+
|
319
|
+
it "should return the groups" do
|
320
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'logs a debug message' do
|
324
|
+
expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: The 'getgrouplist' method is not available")
|
325
|
+
Puppet::Util::POSIX.groups_of(user)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
|
330
|
+
describe "when ffi is not available on the machine" do
|
331
|
+
let(:user) { 'user1' }
|
332
|
+
let(:expected_groups) { ['group1', 'group3'] }
|
333
|
+
|
334
|
+
before(:each) do
|
335
|
+
allow(Puppet::Util::POSIX).to receive(:require).with('puppet/ffi/posix').and_raise(LoadError, 'cannot load such file -- ffi')
|
336
|
+
end
|
337
|
+
|
338
|
+
it "should return the groups" do
|
339
|
+
expect(Puppet::Util::POSIX.groups_of(user)).to eql(expected_groups)
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'logs a debug message' do
|
343
|
+
expect(Puppet).to receive(:debug).with("Falling back to Puppet::Etc.group: cannot load such file -- ffi")
|
344
|
+
Puppet::Util::POSIX.groups_of(user)
|
345
|
+
end
|
346
|
+
end
|
43
347
|
end
|
44
348
|
end
|
45
349
|
|
@@ -189,6 +493,25 @@ describe Puppet::Util::POSIX do
|
|
189
493
|
expect(@posix.gid("asdf")).to eq(100)
|
190
494
|
end
|
191
495
|
|
496
|
+
it "returns the id without full groups query if multiple groups have the same id" do
|
497
|
+
expect(@posix).to receive(:get_posix_field).with(:group, :gid, "asdf").and_return(100)
|
498
|
+
expect(@posix).to receive(:get_posix_field).with(:group, :name, 100).and_return("boo")
|
499
|
+
expect(@posix).to receive(:get_posix_field).with(:group, :gid, "boo").and_return(100)
|
500
|
+
|
501
|
+
expect(@posix).not_to receive(:search_posix_field)
|
502
|
+
expect(@posix.gid("asdf")).to eq(100)
|
503
|
+
end
|
504
|
+
|
505
|
+
it "returns the id with full groups query if name is nil" do
|
506
|
+
expect(@posix).to receive(:get_posix_field).with(:group, :gid, "asdf").and_return(100)
|
507
|
+
expect(@posix).to receive(:get_posix_field).with(:group, :name, 100).and_return(nil)
|
508
|
+
expect(@posix).not_to receive(:get_posix_field).with(:group, :gid, nil)
|
509
|
+
|
510
|
+
|
511
|
+
expect(@posix).to receive(:search_posix_field).with(:group, :gid, "asdf").and_return(100)
|
512
|
+
expect(@posix.gid("asdf")).to eq(100)
|
513
|
+
end
|
514
|
+
|
192
515
|
it "should use :search_posix_field if the discovered name does not match the passed-in name" do
|
193
516
|
expect(@posix).to receive(:get_posix_field).with(:group, :gid, "asdf").and_return(100)
|
194
517
|
expect(@posix).to receive(:get_posix_field).with(:group, :name, 100).and_return("boo")
|
@@ -265,6 +588,25 @@ describe Puppet::Util::POSIX do
|
|
265
588
|
expect(@posix.uid("asdf")).to eq(100)
|
266
589
|
end
|
267
590
|
|
591
|
+
it "returns the id without full users query if multiple users have the same id" do
|
592
|
+
expect(@posix).to receive(:get_posix_field).with(:passwd, :uid, "asdf").and_return(100)
|
593
|
+
expect(@posix).to receive(:get_posix_field).with(:passwd, :name, 100).and_return("boo")
|
594
|
+
expect(@posix).to receive(:get_posix_field).with(:passwd, :uid, "boo").and_return(100)
|
595
|
+
|
596
|
+
expect(@posix).not_to receive(:search_posix_field)
|
597
|
+
expect(@posix.uid("asdf")).to eq(100)
|
598
|
+
end
|
599
|
+
|
600
|
+
it "returns the id with full users query if name is nil" do
|
601
|
+
expect(@posix).to receive(:get_posix_field).with(:passwd, :uid, "asdf").and_return(100)
|
602
|
+
expect(@posix).to receive(:get_posix_field).with(:passwd, :name, 100).and_return(nil)
|
603
|
+
expect(@posix).not_to receive(:get_posix_field).with(:passwd, :uid, nil)
|
604
|
+
|
605
|
+
|
606
|
+
expect(@posix).to receive(:search_posix_field).with(:passwd, :uid, "asdf").and_return(100)
|
607
|
+
expect(@posix.uid("asdf")).to eq(100)
|
608
|
+
end
|
609
|
+
|
268
610
|
it "should use :search_posix_field if the discovered name does not match the passed-in name" do
|
269
611
|
expect(@posix).to receive(:get_posix_field).with(:passwd, :uid, "asdf").and_return(100)
|
270
612
|
expect(@posix).to receive(:get_posix_field).with(:passwd, :name, 100).and_return("boo")
|