puppet 6.19.1 → 6.20.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.

Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +2 -16
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +30 -25
  5. data/lib/puppet/application.rb +10 -6
  6. data/lib/puppet/application/agent.rb +1 -0
  7. data/lib/puppet/application/apply.rb +3 -2
  8. data/lib/puppet/application/device.rb +1 -0
  9. data/lib/puppet/application/filebucket.rb +2 -2
  10. data/lib/puppet/application/script.rb +1 -0
  11. data/lib/puppet/application_support.rb +7 -0
  12. data/lib/puppet/configurer.rb +28 -18
  13. data/lib/puppet/defaults.rb +24 -18
  14. data/lib/puppet/environments.rb +38 -54
  15. data/lib/puppet/face/config.rb +10 -0
  16. data/lib/puppet/face/epp.rb +12 -2
  17. data/lib/puppet/face/facts.rb +60 -0
  18. data/lib/puppet/ffi/posix.rb +10 -0
  19. data/lib/puppet/ffi/posix/constants.rb +14 -0
  20. data/lib/puppet/ffi/posix/functions.rb +24 -0
  21. data/lib/puppet/functions/epp.rb +1 -0
  22. data/lib/puppet/functions/inline_epp.rb +1 -0
  23. data/lib/puppet/indirector/fact_search.rb +60 -0
  24. data/lib/puppet/indirector/facts/json.rb +27 -0
  25. data/lib/puppet/indirector/facts/yaml.rb +3 -58
  26. data/lib/puppet/indirector/json.rb +5 -1
  27. data/lib/puppet/indirector/node/json.rb +8 -0
  28. data/lib/puppet/indirector/report/json.rb +34 -0
  29. data/lib/puppet/module_tool/applications/installer.rb +48 -2
  30. data/lib/puppet/module_tool/errors/shared.rb +17 -2
  31. data/lib/puppet/network/formats.rb +2 -1
  32. data/lib/puppet/pal/pal_impl.rb +70 -17
  33. data/lib/puppet/parser/ast/leaf.rb +3 -2
  34. data/lib/puppet/parser/templatewrapper.rb +1 -1
  35. data/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
  36. data/lib/puppet/pops/evaluator/evaluator_impl.rb +22 -3
  37. data/lib/puppet/pops/model/ast_transformer.rb +1 -1
  38. data/lib/puppet/provider/package/apt.rb +4 -0
  39. data/lib/puppet/provider/user/aix.rb +2 -2
  40. data/lib/puppet/reference/configuration.rb +6 -5
  41. data/lib/puppet/settings.rb +33 -28
  42. data/lib/puppet/settings/alias_setting.rb +37 -0
  43. data/lib/puppet/settings/base_setting.rb +26 -2
  44. data/lib/puppet/util/autoload.rb +1 -8
  45. data/lib/puppet/util/fact_dif.rb +62 -0
  46. data/lib/puppet/util/posix.rb +54 -5
  47. data/lib/puppet/util/rubygems.rb +5 -1
  48. data/lib/puppet/version.rb +1 -1
  49. data/locales/puppet.pot +188 -164
  50. data/man/man5/puppet.conf.5 +6 -6
  51. data/man/man8/puppet-agent.8 +2 -2
  52. data/man/man8/puppet-apply.8 +2 -2
  53. data/man/man8/puppet-catalog.8 +1 -1
  54. data/man/man8/puppet-config.8 +1 -1
  55. data/man/man8/puppet-describe.8 +1 -1
  56. data/man/man8/puppet-device.8 +2 -2
  57. data/man/man8/puppet-doc.8 +1 -1
  58. data/man/man8/puppet-epp.8 +1 -1
  59. data/man/man8/puppet-facts.8 +32 -1
  60. data/man/man8/puppet-filebucket.8 +3 -3
  61. data/man/man8/puppet-generate.8 +1 -1
  62. data/man/man8/puppet-help.8 +1 -1
  63. data/man/man8/puppet-key.8 +1 -1
  64. data/man/man8/puppet-lookup.8 +1 -1
  65. data/man/man8/puppet-man.8 +1 -1
  66. data/man/man8/puppet-module.8 +1 -1
  67. data/man/man8/puppet-node.8 +4 -1
  68. data/man/man8/puppet-parser.8 +1 -1
  69. data/man/man8/puppet-plugin.8 +1 -1
  70. data/man/man8/puppet-report.8 +4 -1
  71. data/man/man8/puppet-resource.8 +1 -1
  72. data/man/man8/puppet-script.8 +2 -2
  73. data/man/man8/puppet-ssl.8 +1 -1
  74. data/man/man8/puppet-status.8 +1 -1
  75. data/man/man8/puppet.8 +2 -2
  76. data/spec/fixtures/integration/application/agent/cached_deferred_catalog.json +91 -0
  77. data/spec/fixtures/unit/provider/user/aix/aix_passwd_file.out +4 -0
  78. data/spec/integration/application/agent_spec.rb +127 -3
  79. data/spec/integration/application/apply_spec.rb +19 -0
  80. data/spec/integration/defaults_spec.rb +0 -7
  81. data/spec/integration/environments/setting_hooks_spec.rb +1 -1
  82. data/spec/integration/resource/type_collection_spec.rb +2 -6
  83. data/spec/integration/transaction_spec.rb +4 -9
  84. data/spec/integration/util/windows/adsi_spec.rb +3 -1
  85. data/spec/integration/util/windows/registry_spec.rb +0 -10
  86. data/spec/lib/puppet_spec/settings.rb +6 -1
  87. data/spec/spec_helper.rb +1 -4
  88. data/spec/unit/agent_spec.rb +8 -6
  89. data/spec/unit/application/agent_spec.rb +0 -1
  90. data/spec/unit/application/config_spec.rb +224 -4
  91. data/spec/unit/application/filebucket_spec.rb +0 -2
  92. data/spec/unit/application_spec.rb +51 -9
  93. data/spec/unit/confine/feature_spec.rb +1 -1
  94. data/spec/unit/confine_spec.rb +8 -2
  95. data/spec/unit/defaults_spec.rb +20 -1
  96. data/spec/unit/environments_spec.rb +96 -19
  97. data/spec/unit/face/config_spec.rb +27 -32
  98. data/spec/unit/face/node_spec.rb +0 -11
  99. data/spec/unit/file_serving/configuration/parser_spec.rb +0 -1
  100. data/spec/unit/file_serving/metadata_spec.rb +3 -3
  101. data/spec/unit/file_serving/terminus_helper_spec.rb +11 -4
  102. data/spec/unit/forge/module_release_spec.rb +2 -7
  103. data/spec/unit/functions/inline_epp_spec.rb +26 -1
  104. data/spec/unit/http/service/compiler_spec.rb +49 -0
  105. data/spec/unit/http/service_spec.rb +1 -1
  106. data/spec/unit/indirector/face_spec.rb +0 -1
  107. data/spec/unit/indirector/facts/facter_spec.rb +0 -1
  108. data/spec/unit/indirector/facts/json_spec.rb +255 -0
  109. data/spec/unit/indirector/file_bucket_file/selector_spec.rb +26 -8
  110. data/spec/unit/indirector/indirection_spec.rb +8 -12
  111. data/spec/unit/indirector/key/file_spec.rb +0 -1
  112. data/spec/unit/indirector/node/json_spec.rb +33 -0
  113. data/spec/{integration/indirector/report/yaml.rb → unit/indirector/report/json_spec.rb} +13 -24
  114. data/spec/unit/indirector/report/yaml_spec.rb +72 -8
  115. data/spec/unit/indirector_spec.rb +2 -2
  116. data/spec/unit/module_tool/applications/installer_spec.rb +66 -0
  117. data/spec/unit/network/authconfig_spec.rb +0 -3
  118. data/spec/unit/network/http/api/indirected_routes_spec.rb +0 -9
  119. data/spec/unit/network/http/handler_spec.rb +0 -5
  120. data/spec/unit/parser/compiler_spec.rb +3 -19
  121. data/spec/unit/parser/resource_spec.rb +14 -8
  122. data/spec/unit/parser/templatewrapper_spec.rb +4 -3
  123. data/spec/unit/pops/evaluator/deferred_resolver_spec.rb +20 -0
  124. data/spec/unit/property_spec.rb +1 -0
  125. data/spec/unit/provider/nameservice_spec.rb +66 -65
  126. data/spec/unit/provider/package/apt_spec.rb +4 -8
  127. data/spec/unit/provider/package/base_spec.rb +6 -5
  128. data/spec/unit/provider/package/pacman_spec.rb +18 -12
  129. data/spec/unit/provider/package/pip_spec.rb +6 -11
  130. data/spec/unit/provider/package/pkgdmg_spec.rb +0 -4
  131. data/spec/unit/provider/user/aix_spec.rb +5 -0
  132. data/spec/unit/provider/user/hpux_spec.rb +1 -1
  133. data/spec/unit/provider/user/pw_spec.rb +2 -0
  134. data/spec/unit/provider/user/useradd_spec.rb +1 -0
  135. data/spec/unit/provider_spec.rb +8 -10
  136. data/spec/unit/puppet_pal_catalog_spec.rb +45 -0
  137. data/spec/unit/resource/capability_finder_spec.rb +6 -1
  138. data/spec/unit/resource/type_spec.rb +1 -1
  139. data/spec/unit/resource_spec.rb +11 -10
  140. data/spec/unit/settings_spec.rb +419 -242
  141. data/spec/unit/ssl/base_spec.rb +0 -1
  142. data/spec/unit/ssl/host_spec.rb +0 -5
  143. data/spec/unit/ssl/ssl_provider_spec.rb +14 -8
  144. data/spec/unit/transaction/additional_resource_generator_spec.rb +3 -7
  145. data/spec/unit/transaction/event_manager_spec.rb +14 -11
  146. data/spec/unit/transaction_spec.rb +13 -4
  147. data/spec/unit/type/file/content_spec.rb +0 -1
  148. data/spec/unit/type/file/selinux_spec.rb +0 -2
  149. data/spec/unit/type/file_spec.rb +0 -6
  150. data/spec/unit/type/group_spec.rb +13 -6
  151. data/spec/unit/type/resources_spec.rb +7 -7
  152. data/spec/unit/type/service_spec.rb +1 -1
  153. data/spec/unit/type/tidy_spec.rb +0 -1
  154. data/spec/unit/type_spec.rb +2 -2
  155. data/spec/unit/util/at_fork_spec.rb +2 -2
  156. data/spec/unit/util/autoload_spec.rb +5 -1
  157. data/spec/unit/util/backups_spec.rb +1 -2
  158. data/spec/unit/util/execution_spec.rb +15 -11
  159. data/spec/unit/util/inifile_spec.rb +6 -14
  160. data/spec/unit/util/log_spec.rb +8 -7
  161. data/spec/unit/util/logging_spec.rb +3 -3
  162. data/spec/unit/util/posix_spec.rb +363 -15
  163. data/spec/unit/util/rubygems_spec.rb +2 -2
  164. data/spec/unit/util/selinux_spec.rb +76 -52
  165. data/spec/unit/util/storage_spec.rb +3 -1
  166. data/spec/unit/util/suidmanager_spec.rb +44 -41
  167. data/spec/unit/util_spec.rb +13 -6
  168. metadata +21 -10
  169. data/spec/integration/application/config_spec.rb +0 -74
  170. data/spec/unit/face/catalog_spec.rb +0 -6
  171. data/spec/unit/face/module_spec.rb +0 -3
@@ -15,13 +15,6 @@ describe Puppet::Face[:node, '0.0.1'] do
15
15
  end
16
16
 
17
17
  describe 'when running #clean' do
18
- before :each do
19
- allow(Puppet::Node::Facts.indirection).to receive(:terminus_class=)
20
- allow(Puppet::Node::Facts.indirection).to receive(:cache_class=)
21
- allow(Puppet::Node).to receive(:terminus_class=)
22
- allow(Puppet::Node).to receive(:cache_class=)
23
- end
24
-
25
18
  it 'should invoke #cleanup' do
26
19
  expect(subject).to receive(:cleanup).with('hostname')
27
20
  subject.clean('hostname')
@@ -30,10 +23,6 @@ describe Puppet::Face[:node, '0.0.1'] do
30
23
 
31
24
  describe "clean action" do
32
25
  before :each do
33
- allow(Puppet::Node::Facts.indirection).to receive(:terminus_class=)
34
- allow(Puppet::Node::Facts.indirection).to receive(:cache_class=)
35
- allow(Puppet::Node).to receive(:terminus_class=)
36
- allow(Puppet::Node).to receive(:cache_class=)
37
26
  allow(subject).to receive(:cleanup)
38
27
  end
39
28
 
@@ -87,7 +87,6 @@ describe Puppet::FileServing::Configuration::Parser do
87
87
  before do
88
88
  @mount = double('testmount', :name => "one", :validate => true)
89
89
  expect(Puppet::FileServing::Mount::File).to receive(:new).with("one").and_return(@mount)
90
- allow(@parser).to receive(:add_modules_mount)
91
90
  end
92
91
 
93
92
  it "should set the mount path to the path attribute from that section" do
@@ -266,9 +266,9 @@ describe Puppet::FileServing::Metadata, :uses_checksums => true do
266
266
  path = tmpfile('bar')
267
267
  FileUtils.touch(path)
268
268
 
269
- allow(Puppet::Util::Windows::Security).to receive(:get_owner).with(path, :use).and_raise(invalid_error)
270
- allow(Puppet::Util::Windows::Security).to receive(:get_group).with(path, :use).and_raise(invalid_error)
271
- allow(Puppet::Util::Windows::Security).to receive(:get_mode).with(path, :use).and_raise(invalid_error)
269
+ allow(Puppet::Util::Windows::Security).to receive(:get_owner).with(path).and_raise(invalid_error)
270
+ allow(Puppet::Util::Windows::Security).to receive(:get_group).with(path).and_raise(invalid_error)
271
+ allow(Puppet::Util::Windows::Security).to receive(:get_mode).with(path).and_raise(invalid_error)
272
272
 
273
273
  stat = Puppet::FileSystem.stat(path)
274
274
 
@@ -2,13 +2,20 @@ require 'spec_helper'
2
2
 
3
3
  require 'puppet/file_serving/terminus_helper'
4
4
 
5
+ class Puppet::FileServing::TestHelper
6
+ include Puppet::FileServing::TerminusHelper
7
+
8
+ attr_reader :model
9
+
10
+ def initialize(model)
11
+ @model = model
12
+ end
13
+ end
14
+
5
15
  describe Puppet::FileServing::TerminusHelper do
6
16
  before do
7
- @helper = Object.new
8
- @helper.extend(Puppet::FileServing::TerminusHelper)
9
-
10
17
  @model = double('model')
11
- allow(@helper).to receive(:model).and_return(@model)
18
+ @helper = Puppet::FileServing::TestHelper.new(@model)
12
19
 
13
20
  @request = double('request', :key => "url", :options => {})
14
21
 
@@ -22,13 +22,8 @@ describe Puppet::Forge::ModuleRelease do
22
22
  let(:uri) { " "}
23
23
  let(:release) { Puppet::Forge::ModuleRelease.new(ssl_repository, JSON.parse(release_json)) }
24
24
 
25
- let(:mock_file) {
26
- mock_io = StringIO.new
27
- allow(mock_io).to receive(:path).and_return('/dev/null')
28
- mock_io
29
- }
30
-
31
- let(:mock_dir) { '/tmp' }
25
+ let(:mock_file) { double('file', path: '/dev/null') }
26
+ let(:mock_dir) { tmpdir('dir') }
32
27
 
33
28
  let(:destination) { tmpfile('forge_module_release') }
34
29
 
@@ -1,8 +1,10 @@
1
-
2
1
  require 'spec_helper'
3
2
 
3
+ require 'puppet_spec/compiler'
4
+
4
5
  describe "the inline_epp function" do
5
6
  include PuppetSpec::Files
7
+ include PuppetSpec::Compiler
6
8
 
7
9
  let :node do Puppet::Node.new('localhost') end
8
10
  let :compiler do Puppet::Parser::Compiler.new(node) end
@@ -73,6 +75,29 @@ describe "the inline_epp function" do
73
75
  expect(eval_template("string was: <%= $string %>")).to eq("string was: the string value")
74
76
  end
75
77
 
78
+ context "when using Sensitive" do
79
+ it "returns an unwrapped sensitive value as a String" do
80
+ expect(eval_and_collect_notices(<<~END)).to eq(["opensesame"])
81
+ notice(inline_epp("<%= Sensitive('opensesame').unwrap %>"))
82
+ END
83
+ end
84
+
85
+ it "rewraps a sensitive value" do
86
+ # note entire result is redacted, not just sensitive part
87
+ expect(eval_and_collect_notices(<<~END)).to eq(["Sensitive [value redacted]"])
88
+ notice(inline_epp("This is sensitive <%= Sensitive('opensesame') %>"))
89
+ END
90
+ end
91
+
92
+ it "can be double wrapped" do
93
+ catalog = compile_to_catalog(<<~END)
94
+ notify { 'title':
95
+ message => Sensitive(inline_epp("<%= Sensitive('opensesame') %>"))
96
+ }
97
+ END
98
+ expect(catalog.resource(:notify, 'title')['message']).to eq('opensesame')
99
+ end
100
+ end
76
101
 
77
102
  def eval_template_with_args(content, args_hash)
78
103
  epp_function.call(scope, content, args_hash)
@@ -131,6 +131,26 @@ describe Puppet::HTTP::Service::Compiler do
131
131
  subject.post_catalog(certname, environment: 'production', facts: facts, checksum_type: %w[sha256 sha384])
132
132
  end
133
133
 
134
+ it 'does not accept msgpack by default' do
135
+ stub_request(:post, uri)
136
+ .with(headers: {'Accept' => 'application/vnd.puppet.rich+json, application/json, text/pson'})
137
+ .to_return(**catalog_response)
138
+
139
+ allow(Puppet.features).to receive(:msgpack?).and_return(false)
140
+
141
+ subject.post_catalog(certname, environment: environment, facts: facts)
142
+ end
143
+
144
+ it 'accepts msgpack & rich_json_msgpack if the gem is present' do
145
+ stub_request(:post, uri)
146
+ .with(headers: {'Accept' => 'application/vnd.puppet.rich+json, application/json, application/vnd.puppet.rich+msgpack, application/x-msgpack, text/pson'})
147
+ .to_return(**catalog_response)
148
+
149
+ allow(Puppet.features).to receive(:msgpack?).and_return(true)
150
+
151
+ subject.post_catalog(certname, environment: environment, facts: facts)
152
+ end
153
+
134
154
  it 'returns a deserialized catalog' do
135
155
  stub_request(:post, uri)
136
156
  .to_return(**catalog_response)
@@ -140,6 +160,35 @@ describe Puppet::HTTP::Service::Compiler do
140
160
  expect(cat.name).to eq(certname)
141
161
  end
142
162
 
163
+ it 'deserializes the catalog from msgpack', if: Puppet.features.msgpack? do
164
+ body = catalog.to_msgpack
165
+ formatter = Puppet::Network::FormatHandler.format(:msgpack)
166
+ catalog_response = { body: body, headers: {'Content-Type' => formatter.mime }}
167
+
168
+ stub_request(:post, uri)
169
+ .to_return(**catalog_response)
170
+
171
+ _, cat = subject.post_catalog(certname, environment: 'production', facts: facts)
172
+ expect(cat).to be_a(Puppet::Resource::Catalog)
173
+ expect(cat.name).to eq(certname)
174
+ end
175
+
176
+ it 'deserializes the catalog from rich msgpack', if: Puppet.features.msgpack? do
177
+ body = Puppet.override(rich_data: true) do
178
+ catalog.to_msgpack
179
+ end
180
+
181
+ formatter = Puppet::Network::FormatHandler.format(:rich_data_msgpack)
182
+ catalog_response = { body: body, headers: {'Content-Type' => formatter.mime }}
183
+
184
+ stub_request(:post, uri)
185
+ .to_return(**catalog_response)
186
+
187
+ _, cat = subject.post_catalog(certname, environment: 'production', facts: facts)
188
+ expect(cat).to be_a(Puppet::Resource::Catalog)
189
+ expect(cat.name).to eq(certname)
190
+ end
191
+
143
192
  it 'returns the request response' do
144
193
  stub_request(:post, uri)
145
194
  .to_return(**catalog_response)
@@ -137,7 +137,7 @@ describe Puppet::HTTP::Service do
137
137
  catalog_mimes = if Puppet.features.msgpack?
138
138
  %w[application/vnd.puppet.rich+json application/json application/vnd.puppet.rich+msgpack application/x-msgpack text/pson]
139
139
  else
140
- %w[application/vnd.puppet.rich+json application/json application/vnd.puppet.rich+msgpack text/pson]
140
+ %w[application/vnd.puppet.rich+json application/json text/pson]
141
141
  end
142
142
  expect(service.mime_types(Puppet::Resource::Catalog)).to eq(catalog_mimes)
143
143
  end
@@ -33,7 +33,6 @@ describe Puppet::Indirector::Face do
33
33
  describe "as an instance" do
34
34
  it "should be able to determine its indirection" do
35
35
  # Loading actions here can get, um, complicated
36
- allow(Puppet::Face).to receive(:load_actions)
37
36
  expect(Puppet::Indirector::Face.new(:catalog, '0.0.1').indirection).to equal(Puppet::Resource::Catalog.indirection)
38
37
  end
39
38
  end
@@ -22,7 +22,6 @@ describe Puppet::Node::Facts::Facter do
22
22
  end
23
23
 
24
24
  before :each do
25
- allow(Puppet::Node::Facts::Facter).to receive(:reload_facter)
26
25
  @facter = Puppet::Node::Facts::Facter.new
27
26
  allow(Facter).to receive(:to_hash).and_return({})
28
27
  @name = "me"
@@ -0,0 +1,255 @@
1
+ require 'spec_helper'
2
+
3
+ require 'puppet/node/facts'
4
+ require 'puppet/indirector/facts/json'
5
+
6
+ def dir_containing_json_facts(hash)
7
+ jsondir = tmpdir('json_facts')
8
+
9
+ Puppet[:client_datadir] = jsondir
10
+ dir = File.join(jsondir, 'facts')
11
+ Dir.mkdir(dir)
12
+ hash.each_pair do |file, facts|
13
+ File.open(File.join(dir, file), 'wb') do |f|
14
+ f.write(JSON.dump(facts))
15
+ end
16
+ end
17
+ end
18
+
19
+ describe Puppet::Node::Facts::Json do
20
+ include PuppetSpec::Files
21
+
22
+ it "should be a subclass of the Json terminus" do
23
+ expect(Puppet::Node::Facts::Json.superclass).to equal(Puppet::Indirector::JSON)
24
+ end
25
+
26
+ it "should have documentation" do
27
+ expect(Puppet::Node::Facts::Json.doc).not_to be_nil
28
+ expect(Puppet::Node::Facts::Json.doc).not_to be_empty
29
+ end
30
+
31
+ it "should be registered with the facts indirection" do
32
+ indirection = Puppet::Indirector::Indirection.instance(:facts)
33
+ expect(Puppet::Node::Facts::Json.indirection).to equal(indirection)
34
+ end
35
+
36
+ it "should have its name set to :json" do
37
+ expect(Puppet::Node::Facts::Json.name).to eq(:json)
38
+ end
39
+
40
+ it "should allow network requests" do
41
+ # Doesn't allow json as a network format, but allows `puppet facts upload`
42
+ # to update the JSON cache on a master.
43
+ expect(Puppet::Node::Facts::Json.new.allow_remote_requests?).to be(true)
44
+ end
45
+
46
+ describe "#search" do
47
+ def assert_search_matches(matching, nonmatching, query)
48
+ request = Puppet::Indirector::Request.new(:inventory, :search, nil, nil, query)
49
+
50
+ dir_containing_json_facts(matching.merge(nonmatching))
51
+
52
+ results = Puppet::Node::Facts::Json.new.search(request)
53
+ expect(results).to match_array(matching.values.map {|facts| facts.name})
54
+ end
55
+
56
+ it "should return node names that match the search query options" do
57
+ assert_search_matches({
58
+ 'matching.json' => Puppet::Node::Facts.new("matchingnode", "architecture" => "i386", 'processor_count' => '4'),
59
+ 'matching1.json' => Puppet::Node::Facts.new("matchingnode1", "architecture" => "i386", 'processor_count' => '4', 'randomfact' => 'foo')
60
+ },
61
+ {
62
+ "nonmatching.json" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '4'),
63
+ "nonmatching1.json" => Puppet::Node::Facts.new("nonmatchingnode1", "architecture" => "powerpc", 'processor_count' => '5'),
64
+ "nonmatching2.json" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '5'),
65
+ "nonmatching3.json" => Puppet::Node::Facts.new("nonmatchingnode3", 'processor_count' => '4'),
66
+ },
67
+ {'facts.architecture' => 'i386', 'facts.processor_count' => '4'}
68
+ )
69
+ end
70
+
71
+ it "should return empty array when no nodes match the search query options" do
72
+ assert_search_matches({}, {
73
+ "nonmatching.json" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '10'),
74
+ "nonmatching1.json" => Puppet::Node::Facts.new("nonmatchingnode1", "architecture" => "powerpc", 'processor_count' => '5'),
75
+ "nonmatching2.json" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '5'),
76
+ "nonmatching3.json" => Puppet::Node::Facts.new("nonmatchingnode3", 'processor_count' => '4'),
77
+ },
78
+ {'facts.processor_count.lt' => '4', 'facts.processor_count.gt' => '4'}
79
+ )
80
+ end
81
+
82
+ it "should return node names that match the search query options with the greater than operator" do
83
+ assert_search_matches({
84
+ 'matching.json' => Puppet::Node::Facts.new("matchingnode", "architecture" => "i386", 'processor_count' => '5'),
85
+ 'matching1.json' => Puppet::Node::Facts.new("matchingnode1", "architecture" => "powerpc", 'processor_count' => '10', 'randomfact' => 'foo')
86
+ },
87
+ {
88
+ "nonmatching.json" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '4'),
89
+ "nonmatching2.json" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '3'),
90
+ "nonmatching3.json" => Puppet::Node::Facts.new("nonmatchingnode3" ),
91
+ },
92
+ {'facts.processor_count.gt' => '4'}
93
+ )
94
+ end
95
+
96
+ it "should return node names that match the search query options with the less than operator" do
97
+ assert_search_matches({
98
+ 'matching.json' => Puppet::Node::Facts.new("matchingnode", "architecture" => "i386", 'processor_count' => '5'),
99
+ 'matching1.json' => Puppet::Node::Facts.new("matchingnode1", "architecture" => "powerpc", 'processor_count' => '30', 'randomfact' => 'foo')
100
+ },
101
+ {
102
+ "nonmatching.json" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '50' ),
103
+ "nonmatching2.json" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '100'),
104
+ "nonmatching3.json" => Puppet::Node::Facts.new("nonmatchingnode3" ),
105
+ },
106
+ {'facts.processor_count.lt' => '50'}
107
+ )
108
+ end
109
+
110
+ it "should return node names that match the search query options with the less than or equal to operator" do
111
+ assert_search_matches({
112
+ 'matching.json' => Puppet::Node::Facts.new("matchingnode", "architecture" => "i386", 'processor_count' => '5'),
113
+ 'matching1.json' => Puppet::Node::Facts.new("matchingnode1", "architecture" => "powerpc", 'processor_count' => '50', 'randomfact' => 'foo')
114
+ },
115
+ {
116
+ "nonmatching.json" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '100' ),
117
+ "nonmatching2.json" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '5000'),
118
+ "nonmatching3.json" => Puppet::Node::Facts.new("nonmatchingnode3" ),
119
+ },
120
+ {'facts.processor_count.le' => '50'}
121
+ )
122
+ end
123
+
124
+ it "should return node names that match the search query options with the greater than or equal to operator" do
125
+ assert_search_matches({
126
+ 'matching.json' => Puppet::Node::Facts.new("matchingnode", "architecture" => "i386", 'processor_count' => '100'),
127
+ 'matching1.json' => Puppet::Node::Facts.new("matchingnode1", "architecture" => "powerpc", 'processor_count' => '50', 'randomfact' => 'foo')
128
+ },
129
+ {
130
+ "nonmatching.json" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '40'),
131
+ "nonmatching2.json" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '9' ),
132
+ "nonmatching3.json" => Puppet::Node::Facts.new("nonmatchingnode3" ),
133
+ },
134
+ {'facts.processor_count.ge' => '50'}
135
+ )
136
+ end
137
+
138
+ it "should return node names that match the search query options with the not equal operator" do
139
+ assert_search_matches({
140
+ 'matching.json' => Puppet::Node::Facts.new("matchingnode", "architecture" => 'arm' ),
141
+ 'matching1.json' => Puppet::Node::Facts.new("matchingnode1", "architecture" => 'powerpc', 'randomfact' => 'foo')
142
+ },
143
+ {
144
+ "nonmatching.json" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "i386" ),
145
+ "nonmatching2.json" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '9' ),
146
+ "nonmatching3.json" => Puppet::Node::Facts.new("nonmatchingnode3" ),
147
+ },
148
+ {'facts.architecture.ne' => 'i386'}
149
+ )
150
+ end
151
+
152
+ def apply_timestamp(facts, timestamp)
153
+ facts.timestamp = timestamp
154
+ facts
155
+ end
156
+
157
+ it "should be able to query based on meta.timestamp.gt" do
158
+ assert_search_matches({
159
+ '2010-11-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
160
+ '2010-11-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
161
+ },
162
+ {
163
+ '2010-10-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
164
+ '2010-10-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
165
+ '2010-10-15.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
166
+ },
167
+ {'meta.timestamp.gt' => '2010-10-15'}
168
+ )
169
+ end
170
+
171
+ it "should be able to query based on meta.timestamp.le" do
172
+ assert_search_matches({
173
+ '2010-10-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
174
+ '2010-10-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
175
+ '2010-10-15.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
176
+ },
177
+ {
178
+ '2010-11-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
179
+ '2010-11-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
180
+ },
181
+ {'meta.timestamp.le' => '2010-10-15'}
182
+ )
183
+ end
184
+
185
+ it "should be able to query based on meta.timestamp.lt" do
186
+ assert_search_matches({
187
+ '2010-10-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
188
+ '2010-10-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
189
+ },
190
+ {
191
+ '2010-11-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
192
+ '2010-11-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
193
+ '2010-10-15.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
194
+ },
195
+ {'meta.timestamp.lt' => '2010-10-15'}
196
+ )
197
+ end
198
+
199
+ it "should be able to query based on meta.timestamp.ge" do
200
+ assert_search_matches({
201
+ '2010-11-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
202
+ '2010-11-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
203
+ '2010-10-15.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
204
+ },
205
+ {
206
+ '2010-10-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
207
+ '2010-10-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
208
+ },
209
+ {'meta.timestamp.ge' => '2010-10-15'}
210
+ )
211
+ end
212
+
213
+ it "should be able to query based on meta.timestamp.eq" do
214
+ assert_search_matches({
215
+ '2010-10-15.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
216
+ },
217
+ {
218
+ '2010-11-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
219
+ '2010-11-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
220
+ '2010-10-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
221
+ '2010-10-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
222
+ },
223
+ {'meta.timestamp.eq' => '2010-10-15'}
224
+ )
225
+ end
226
+
227
+ it "should be able to query based on meta.timestamp" do
228
+ assert_search_matches({
229
+ '2010-10-15.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
230
+ },
231
+ {
232
+ '2010-11-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
233
+ '2010-11-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
234
+ '2010-10-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
235
+ '2010-10-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
236
+ },
237
+ {'meta.timestamp' => '2010-10-15'}
238
+ )
239
+ end
240
+
241
+ it "should be able to query based on meta.timestamp.ne" do
242
+ assert_search_matches({
243
+ '2010-11-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
244
+ '2010-11-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
245
+ '2010-10-01.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
246
+ '2010-10-10.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
247
+ },
248
+ {
249
+ '2010-10-15.json' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
250
+ },
251
+ {'meta.timestamp.ne' => '2010-10-15'}
252
+ )
253
+ end
254
+ end
255
+ end