facter 1.5 → 1.5.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of facter might be problematic. Click here for more details.
- data/CHANGELOG +51 -1
- data/Rakefile +10 -1
- data/conf/osx/PackageInfo.plist +36 -0
- data/conf/osx/createpackage.sh +167 -0
- data/conf/osx/preflight +11 -0
- data/conf/redhat/facter.spec +120 -0
- data/conf/solaris/pkginfo +7 -0
- data/documentation/custom.page +22 -0
- data/documentation/index.page +19 -0
- data/install.rb +227 -92
- data/lib/facter.rb +1 -1
- data/lib/facter/domain.rb +14 -0
- data/lib/facter/hardwaremodel.rb +8 -0
- data/lib/facter/ipaddress.rb +21 -2
- data/lib/facter/ipmess.rb +8 -37
- data/lib/facter/kernel.rb +7 -1
- data/lib/facter/kernelrelease.rb +16 -1
- data/lib/facter/kernelversion.rb +5 -0
- data/lib/facter/lsb.rb +1 -0
- data/lib/facter/macaddress.rb +15 -1
- data/lib/facter/operatingsystem.rb +6 -1
- data/lib/facter/operatingsystemrelease.rb +34 -7
- data/lib/facter/puppetversion.rb +1 -1
- data/lib/facter/util/ip.rb +37 -47
- data/lib/facter/util/manufacturer.rb +2 -2
- data/lib/facter/util/resolution.rb +13 -3
- data/lib/facter/virtual.rb +62 -0
- data/spec/Rakefile +18 -0
- data/spec/integration/facter.rb +27 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/unit/data/linux_ifconfig_all_with_single_interface +18 -0
- data/spec/unit/data/solaris_ifconfig_single_interface +3 -0
- data/spec/unit/facter.rb +134 -0
- data/spec/unit/util/collection.rb +255 -0
- data/spec/unit/util/confine.rb +75 -0
- data/spec/unit/util/fact.rb +129 -0
- data/spec/unit/util/ip.rb +40 -0
- data/spec/unit/util/loader.rb +219 -0
- data/spec/unit/util/resolution.rb +209 -0
- metadata +31 -2
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
4
|
+
|
5
|
+
require 'facter/util/confine'
|
6
|
+
|
7
|
+
describe Facter::Util::Confine do
|
8
|
+
it "should require a fact name" do
|
9
|
+
Facter::Util::Confine.new("yay", true).fact.should == "yay"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should accept a value specified individually" do
|
13
|
+
Facter::Util::Confine.new("yay", "test").values.should == ["test"]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should accept multiple values specified at once" do
|
17
|
+
Facter::Util::Confine.new("yay", "test", "other").values.should == ["test", "other"]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should convert all values to strings" do
|
21
|
+
Facter::Util::Confine.new("yay", :test).values.should == %w{test}
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should fail if no fact name is provided" do
|
25
|
+
lambda { Facter::Util::Confine.new(nil, :test) }.should raise_error(ArgumentError)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should fail if no values were provided" do
|
29
|
+
lambda { Facter::Util::Confine.new("yay") }.should raise_error(ArgumentError)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have a method for testing whether it matches" do
|
33
|
+
Facter::Util::Confine.new("yay", :test).should respond_to(:true?)
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "when evaluating" do
|
37
|
+
before do
|
38
|
+
@confine = Facter::Util::Confine.new("yay", "one", "two")
|
39
|
+
@fact = mock 'fact'
|
40
|
+
Facter.stubs(:[]).returns @fact
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should return false if the fact does not exist" do
|
44
|
+
Facter.expects(:[]).with("yay").returns nil
|
45
|
+
|
46
|
+
@confine.true?.should be_false
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should use the returned fact to get the value" do
|
50
|
+
Facter.expects(:[]).with("yay").returns @fact
|
51
|
+
|
52
|
+
@fact.expects(:value).returns nil
|
53
|
+
|
54
|
+
@confine.true?
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return false if the fact has no value" do
|
58
|
+
@fact.stubs(:value).returns nil
|
59
|
+
|
60
|
+
@confine.true?.should be_false
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return true if any of the provided values matches the fact's value" do
|
64
|
+
@fact.stubs(:value).returns "two"
|
65
|
+
|
66
|
+
@confine.true?.should be_true
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should return false if none of the provided values matches the fact's value" do
|
70
|
+
@fact.stubs(:value).returns "three"
|
71
|
+
|
72
|
+
@confine.true?.should be_false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
4
|
+
|
5
|
+
require 'facter/util/fact'
|
6
|
+
|
7
|
+
describe Facter::Util::Fact do
|
8
|
+
it "should require a name" do
|
9
|
+
lambda { Facter::Util::Fact.new }.should raise_error(ArgumentError)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should always downcase the name and convert it to a symbol" do
|
13
|
+
Facter::Util::Fact.new("YayNess").name.should == :yayness
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should default to its name converted to a string as its ldapname" do
|
17
|
+
Facter::Util::Fact.new("YayNess").ldapname.should == "yayness"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should allow specifying the ldap name at initialization" do
|
21
|
+
Facter::Util::Fact.new("YayNess", :ldapname => "fooness").ldapname.should == "fooness"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should fail if an unknown option is provided" do
|
25
|
+
lambda { Facter::Util::Fact.new('yay', :foo => :bar) }.should raise_error(ArgumentError)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have a method for adding resolution mechanisms" do
|
29
|
+
Facter::Util::Fact.new("yay").should respond_to(:add)
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "when adding resolution mechanisms" do
|
33
|
+
before do
|
34
|
+
@fact = Facter::Util::Fact.new("yay")
|
35
|
+
|
36
|
+
@resolution = mock 'resolution'
|
37
|
+
@resolution.stub_everything
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should fail if no block is given" do
|
42
|
+
lambda { @fact.add }.should raise_error(ArgumentError)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should create a new resolution instance" do
|
46
|
+
Facter::Util::Resolution.expects(:new).returns @resolution
|
47
|
+
|
48
|
+
@fact.add { }
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should instance_eval the passed block on the new resolution" do
|
52
|
+
@resolution.expects(:instance_eval)
|
53
|
+
|
54
|
+
Facter::Util::Resolution.stubs(:new).returns @resolution
|
55
|
+
|
56
|
+
@fact.add { }
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should re-sort the resolutions by length, so the most restricted resolutions are first" do
|
60
|
+
r1 = stub 'r1', :length => 1
|
61
|
+
r2 = stub 'r2', :length => 2
|
62
|
+
r3 = stub 'r3', :length => 0
|
63
|
+
Facter::Util::Resolution.expects(:new).times(3).returns(r1).returns(r2).returns(r3)
|
64
|
+
@fact.add { }
|
65
|
+
@fact.add { }
|
66
|
+
@fact.add { }
|
67
|
+
|
68
|
+
@fact.instance_variable_get("@resolves").should == [r2, r1, r3]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should be able to return a value" do
|
73
|
+
Facter::Util::Fact.new("yay").should respond_to(:value)
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "when returning a value" do
|
77
|
+
before do
|
78
|
+
@fact = Facter::Util::Fact.new("yay")
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should return nil if there are no resolutions" do
|
82
|
+
Facter::Util::Fact.new("yay").value.should be_nil
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should return the first value returned by a resolution" do
|
86
|
+
r1 = stub 'r1', :length => 2, :value => nil, :suitable? => true
|
87
|
+
r2 = stub 'r2', :length => 1, :value => "yay", :suitable? => true
|
88
|
+
r3 = stub 'r3', :length => 0, :value => "foo", :suitable? => true
|
89
|
+
Facter::Util::Resolution.expects(:new).times(3).returns(r1).returns(r2).returns(r3)
|
90
|
+
@fact.add { }
|
91
|
+
@fact.add { }
|
92
|
+
@fact.add { }
|
93
|
+
|
94
|
+
@fact.value.should == "yay"
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should short-cut returning the value once one is found" do
|
98
|
+
r1 = stub 'r1', :length => 2, :value => "foo", :suitable? => true
|
99
|
+
r2 = stub 'r2', :length => 1, :suitable? => true # would fail if 'value' were asked for
|
100
|
+
Facter::Util::Resolution.expects(:new).times(2).returns(r1).returns(r2)
|
101
|
+
@fact.add { }
|
102
|
+
@fact.add { }
|
103
|
+
|
104
|
+
@fact.value
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should skip unsuitable resolutions" do
|
108
|
+
r1 = stub 'r1', :length => 2, :suitable? => false # would fail if 'value' were asked for'
|
109
|
+
r2 = stub 'r2', :length => 1, :value => "yay", :suitable? => true
|
110
|
+
Facter::Util::Resolution.expects(:new).times(2).returns(r1).returns(r2)
|
111
|
+
@fact.add { }
|
112
|
+
@fact.add { }
|
113
|
+
|
114
|
+
@fact.value.should == "yay"
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should return nil if the value is the empty string" do
|
118
|
+
r1 = stub 'r1', :suitable? => true, :value => ""
|
119
|
+
Facter::Util::Resolution.expects(:new).returns r1
|
120
|
+
@fact.add { }
|
121
|
+
|
122
|
+
@fact.value.should be_nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should have a method for flushing the cached fact" do
|
127
|
+
Facter::Util::Fact.new(:foo).should respond_to(:flush)
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
4
|
+
|
5
|
+
require 'facter/util/ip'
|
6
|
+
|
7
|
+
describe Facter::IPAddress do
|
8
|
+
|
9
|
+
it "should return a list of interfaces" do
|
10
|
+
Facter::IPAddress.should respond_to(:get_interfaces)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return an empty list of interfaces on an unknown kernel" do
|
14
|
+
Facter.stubs(:value).returns("UnknownKernel")
|
15
|
+
Facter::IPAddress.get_interfaces().should == []
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return a list with a single interface on Linux with a single interface" do
|
19
|
+
sample_output_file = File.dirname(__FILE__) + '/../data/linux_ifconfig_all_with_single_interface'
|
20
|
+
linux_ifconfig = File.new(sample_output_file).read()
|
21
|
+
Facter::IPAddress.stubs(:get_all_interface_output).returns(linux_ifconfig)
|
22
|
+
Facter::IPAddress.get_interfaces().should == ["eth0"]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return a value for a specific interface" do
|
26
|
+
Facter::IPAddress.should respond_to(:get_interface_value)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return a human readable netmask on Solaris" do
|
30
|
+
sample_output_file = File.dirname(__FILE__) + "/../data/solaris_ifconfig_single_interface"
|
31
|
+
solaris_ifconfig_interface = File.new(sample_output_file).read()
|
32
|
+
|
33
|
+
Facter::IPAddress.expects(:get_single_interface_output).with("e1000g0").returns(solaris_ifconfig_interface)
|
34
|
+
Facter.stubs(:value).with(:kernel).returns("SunOS")
|
35
|
+
|
36
|
+
Facter::IPAddress.get_interface_value("e1000g0", "netmask").should == "255.255.255.0"
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,219 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
4
|
+
|
5
|
+
require 'facter/util/loader'
|
6
|
+
|
7
|
+
describe Facter::Util::Loader do
|
8
|
+
def with_env(values)
|
9
|
+
old = {}
|
10
|
+
values.each do |var, value|
|
11
|
+
if old_val = ENV[var]
|
12
|
+
old[var] = old_val
|
13
|
+
end
|
14
|
+
ENV[var] = value
|
15
|
+
end
|
16
|
+
yield
|
17
|
+
values.each do |var, value|
|
18
|
+
if old.include?(var)
|
19
|
+
ENV[var] = old[var]
|
20
|
+
else
|
21
|
+
ENV.delete(var)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should have a method for loading individual facts by name" do
|
27
|
+
Facter::Util::Loader.new.should respond_to(:load)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should have a method for loading all facts" do
|
31
|
+
Facter::Util::Loader.new.should respond_to(:load_all)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should have a method for returning directories containing facts" do
|
35
|
+
Facter::Util::Loader.new.should respond_to(:search_path)
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "when determining the search path" do
|
39
|
+
before do
|
40
|
+
@loader = Facter::Util::Loader.new
|
41
|
+
@settings = mock 'settings'
|
42
|
+
@settings.stubs(:value).returns "/eh"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should include the facter subdirectory of all paths in ruby LOAD_PATH" do
|
46
|
+
dirs = $LOAD_PATH.collect { |d| File.join(d, "facter") }
|
47
|
+
paths = @loader.search_path
|
48
|
+
|
49
|
+
dirs.each do |dir|
|
50
|
+
paths.should be_include(dir)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should include all search paths registered with Facter" do
|
55
|
+
Facter.expects(:search_path).returns %w{/one /two}
|
56
|
+
paths = @loader.search_path
|
57
|
+
paths.should be_include("/one")
|
58
|
+
paths.should be_include("/two")
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "and the FACTERLIB environment variable is set" do
|
62
|
+
it "should include all paths in FACTERLIB" do
|
63
|
+
with_env "FACTERLIB" => "/one/path:/two/path" do
|
64
|
+
paths = @loader.search_path
|
65
|
+
%w{/one/path /two/path}.each do |dir|
|
66
|
+
paths.should be_include(dir)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "when loading facts" do
|
74
|
+
before do
|
75
|
+
@loader = Facter::Util::Loader.new
|
76
|
+
@loader.stubs(:search_path).returns []
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should load values from the matching environment variable if one is present" do
|
80
|
+
Facter.expects(:add).with("testing")
|
81
|
+
|
82
|
+
with_env "facter_testing" => "yayness" do
|
83
|
+
@loader.load(:testing)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should load any files in the search path with names matching the fact name" do
|
88
|
+
@loader.expects(:search_path).returns %w{/one/dir /two/dir}
|
89
|
+
FileTest.stubs(:exist?).returns false
|
90
|
+
FileTest.expects(:exist?).with("/one/dir/testing.rb").returns true
|
91
|
+
FileTest.expects(:exist?).with("/two/dir/testing.rb").returns true
|
92
|
+
|
93
|
+
Kernel.expects(:load).with("/one/dir/testing.rb")
|
94
|
+
Kernel.expects(:load).with("/two/dir/testing.rb")
|
95
|
+
|
96
|
+
@loader.load(:testing)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should load any ruby files in directories matching the fact name in the search path" do
|
100
|
+
@loader.expects(:search_path).returns %w{/one/dir}
|
101
|
+
FileTest.stubs(:exist?).returns false
|
102
|
+
FileTest.expects(:directory?).with("/one/dir/testing").returns true
|
103
|
+
|
104
|
+
Dir.expects(:entries).with("/one/dir/testing").returns %w{two.rb}
|
105
|
+
|
106
|
+
Kernel.expects(:load).with("/one/dir/testing/two.rb")
|
107
|
+
|
108
|
+
@loader.load(:testing)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should not load files that don't end in '.rb'" do
|
112
|
+
@loader.expects(:search_path).returns %w{/one/dir}
|
113
|
+
FileTest.stubs(:exist?).returns false
|
114
|
+
FileTest.expects(:directory?).with("/one/dir/testing").returns true
|
115
|
+
|
116
|
+
Dir.expects(:entries).with("/one/dir/testing").returns %w{one}
|
117
|
+
|
118
|
+
Kernel.expects(:load).never
|
119
|
+
|
120
|
+
@loader.load(:testing)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "when loading all facts" do
|
125
|
+
before do
|
126
|
+
@loader = Facter::Util::Loader.new
|
127
|
+
@loader.stubs(:search_path).returns []
|
128
|
+
|
129
|
+
FileTest.stubs(:directory?).returns true
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should skip directories that do not exist" do
|
133
|
+
@loader.expects(:search_path).returns %w{/one/dir}
|
134
|
+
|
135
|
+
FileTest.expects(:directory?).with("/one/dir").returns false
|
136
|
+
|
137
|
+
Dir.expects(:entries).with("/one/dir").never
|
138
|
+
|
139
|
+
@loader.load_all
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should load all files in all search paths" do
|
143
|
+
@loader.expects(:search_path).returns %w{/one/dir /two/dir}
|
144
|
+
|
145
|
+
Dir.expects(:entries).with("/one/dir").returns %w{a.rb b.rb}
|
146
|
+
Dir.expects(:entries).with("/two/dir").returns %w{c.rb d.rb}
|
147
|
+
|
148
|
+
%w{/one/dir/a.rb /one/dir/b.rb /two/dir/c.rb /two/dir/d.rb}.each { |f| Kernel.expects(:load).with(f) }
|
149
|
+
|
150
|
+
@loader.load_all
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should load all files in all subdirectories in all search paths" do
|
154
|
+
@loader.expects(:search_path).returns %w{/one/dir /two/dir}
|
155
|
+
|
156
|
+
Dir.expects(:entries).with("/one/dir").returns %w{a}
|
157
|
+
Dir.expects(:entries).with("/two/dir").returns %w{b}
|
158
|
+
|
159
|
+
%w{/one/dir/a /two/dir/b}.each { |f| File.expects(:directory?).with(f).returns true }
|
160
|
+
|
161
|
+
Dir.expects(:entries).with("/one/dir/a").returns %w{c.rb}
|
162
|
+
Dir.expects(:entries).with("/two/dir/b").returns %w{d.rb}
|
163
|
+
|
164
|
+
%w{/one/dir/a/c.rb /two/dir/b/d.rb}.each { |f| Kernel.expects(:load).with(f) }
|
165
|
+
|
166
|
+
@loader.load_all
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should not load files in the util subdirectory" do
|
170
|
+
@loader.expects(:search_path).returns %w{/one/dir}
|
171
|
+
|
172
|
+
Dir.expects(:entries).with("/one/dir").returns %w{util}
|
173
|
+
|
174
|
+
File.expects(:directory?).with("/one/dir/util").returns true
|
175
|
+
|
176
|
+
Dir.expects(:entries).with("/one/dir/util").never
|
177
|
+
|
178
|
+
@loader.load_all
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should not load files in a lib subdirectory" do
|
182
|
+
@loader.expects(:search_path).returns %w{/one/dir}
|
183
|
+
|
184
|
+
Dir.expects(:entries).with("/one/dir").returns %w{lib}
|
185
|
+
|
186
|
+
File.expects(:directory?).with("/one/dir/lib").returns true
|
187
|
+
|
188
|
+
Dir.expects(:entries).with("/one/dir/lib").never
|
189
|
+
|
190
|
+
@loader.load_all
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should not load files in '.' or '..'" do
|
194
|
+
@loader.expects(:search_path).returns %w{/one/dir}
|
195
|
+
|
196
|
+
Dir.expects(:entries).with("/one/dir").returns %w{. ..}
|
197
|
+
|
198
|
+
File.expects(:entries).with("/one/dir/.").never
|
199
|
+
File.expects(:entries).with("/one/dir/..").never
|
200
|
+
|
201
|
+
@loader.load_all
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should load all facts from the environment" do
|
205
|
+
Facter.expects(:add).with('one')
|
206
|
+
Facter.expects(:add).with('two')
|
207
|
+
|
208
|
+
with_env "facter_one" => "yayness", "facter_two" => "boo" do
|
209
|
+
@loader.load_all
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should only load all facts one time" do
|
214
|
+
@loader.expects(:load_env).once
|
215
|
+
@loader.load_all
|
216
|
+
@loader.load_all
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|