puppet 6.10.1 → 6.11.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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -4
  3. data/Gemfile.lock +20 -12
  4. data/ext/project_data.yaml +3 -2
  5. data/ext/regexp_nodes/regexp_nodes.rb +4 -4
  6. data/ext/windows/service/daemon.rb +33 -8
  7. data/install.rb +6 -6
  8. data/lib/puppet.rb +8 -0
  9. data/lib/puppet/application.rb +1 -1
  10. data/lib/puppet/application/agent.rb +3 -0
  11. data/lib/puppet/application/apply.rb +2 -2
  12. data/lib/puppet/application/describe.rb +3 -9
  13. data/lib/puppet/application/device.rb +3 -0
  14. data/lib/puppet/application/doc.rb +1 -1
  15. data/lib/puppet/application/lookup.rb +1 -1
  16. data/lib/puppet/application/script.rb +2 -2
  17. data/lib/puppet/application/ssl.rb +25 -21
  18. data/lib/puppet/configurer.rb +42 -0
  19. data/lib/puppet/configurer/downloader.rb +2 -6
  20. data/lib/puppet/context/trusted_information.rb +42 -4
  21. data/lib/puppet/defaults.rb +19 -4
  22. data/lib/puppet/face/module/list.rb +5 -5
  23. data/lib/puppet/face/module/search.rb +1 -1
  24. data/lib/puppet/face/module/uninstall.rb +1 -1
  25. data/lib/puppet/face/module/upgrade.rb +1 -1
  26. data/lib/puppet/file_serving/http_metadata.rb +1 -1
  27. data/lib/puppet/file_system.rb +0 -8
  28. data/lib/puppet/file_system/memory_file.rb +1 -1
  29. data/lib/puppet/file_system/posix.rb +3 -2
  30. data/lib/puppet/forge.rb +3 -3
  31. data/lib/puppet/functions.rb +1 -2
  32. data/lib/puppet/gettext/module_translations.rb +1 -1
  33. data/lib/puppet/graph/rb_tree_map.rb +2 -2
  34. data/lib/puppet/graph/simple_graph.rb +4 -3
  35. data/lib/puppet/http.rb +29 -0
  36. data/lib/puppet/http/client.rb +156 -0
  37. data/lib/puppet/http/errors.rb +30 -0
  38. data/lib/puppet/http/redirector.rb +48 -0
  39. data/lib/puppet/http/resolver.rb +5 -0
  40. data/lib/puppet/http/resolver/settings.rb +5 -0
  41. data/lib/puppet/http/resolver/srv.rb +13 -0
  42. data/lib/puppet/http/response.rb +34 -0
  43. data/lib/puppet/http/retry_after_handler.rb +47 -0
  44. data/lib/puppet/http/service.rb +18 -0
  45. data/lib/puppet/http/service/ca.rb +49 -0
  46. data/lib/puppet/http/session.rb +55 -0
  47. data/lib/puppet/indirector/file_bucket_file/file.rb +1 -1
  48. data/lib/puppet/indirector/hiera.rb +2 -0
  49. data/lib/puppet/indirector/request.rb +1 -1
  50. data/lib/puppet/indirector/resource/ral.rb +1 -3
  51. data/lib/puppet/indirector/resource/validator.rb +1 -1
  52. data/lib/puppet/interface.rb +2 -1
  53. data/lib/puppet/interface/documentation.rb +1 -1
  54. data/lib/puppet/loaders.rb +0 -1
  55. data/lib/puppet/metatype/manager.rb +1 -1
  56. data/lib/puppet/module.rb +1 -1
  57. data/lib/puppet/module/task.rb +20 -4
  58. data/lib/puppet/module_tool/applications/installer.rb +1 -1
  59. data/lib/puppet/module_tool/applications/uninstaller.rb +3 -3
  60. data/lib/puppet/module_tool/metadata.rb +1 -1
  61. data/lib/puppet/module_tool/shared_behaviors.rb +4 -4
  62. data/lib/puppet/module_tool/tar/mini.rb +1 -1
  63. data/lib/puppet/network/http.rb +2 -6
  64. data/lib/puppet/network/http/api/indirected_routes.rb +12 -11
  65. data/lib/puppet/network/http/connection.rb +10 -12
  66. data/lib/puppet/network/http/pool.rb +2 -0
  67. data/lib/puppet/network/http/site.rb +5 -1
  68. data/lib/puppet/network/resolver.rb +4 -4
  69. data/lib/puppet/node/environment.rb +4 -2
  70. data/lib/puppet/pal/pal_impl.rb +2 -2
  71. data/lib/puppet/parser/ast.rb +1 -1
  72. data/lib/puppet/parser/ast/resourceparam.rb +1 -1
  73. data/lib/puppet/parser/functions.rb +1 -1
  74. data/lib/puppet/parser/scope.rb +8 -7
  75. data/lib/puppet/pops/evaluator/collectors/catalog_collector.rb +1 -1
  76. data/lib/puppet/pops/evaluator/collectors/exported_collector.rb +1 -1
  77. data/lib/puppet/pops/evaluator/external_syntax_support.rb +3 -2
  78. data/lib/puppet/pops/evaluator/runtime3_support.rb +4 -7
  79. data/lib/puppet/pops/loader/module_loaders.rb +1 -1
  80. data/lib/puppet/pops/loader/task_instantiator.rb +4 -0
  81. data/lib/puppet/pops/loaders.rb +1 -1
  82. data/lib/puppet/pops/lookup/hiera_config.rb +1 -0
  83. data/lib/puppet/pops/lookup/sub_lookup.rb +1 -1
  84. data/lib/puppet/pops/merge_strategy.rb +22 -18
  85. data/lib/puppet/pops/parser/heredoc_support.rb +1 -1
  86. data/lib/puppet/pops/parser/interpolation_support.rb +4 -4
  87. data/lib/puppet/pops/parser/locator.rb +1 -1
  88. data/lib/puppet/pops/parser/pn_parser.rb +17 -16
  89. data/lib/puppet/pops/puppet_stack.rb +52 -48
  90. data/lib/puppet/pops/types/p_sensitive_type.rb +1 -1
  91. data/lib/puppet/pops/types/p_uri_type.rb +1 -1
  92. data/lib/puppet/pops/types/string_converter.rb +10 -10
  93. data/lib/puppet/pops/types/types.rb +3 -3
  94. data/lib/puppet/property.rb +1 -1
  95. data/lib/puppet/property/ensure.rb +1 -1
  96. data/lib/puppet/provider/exec.rb +6 -2
  97. data/lib/puppet/provider/nameservice/directoryservice.rb +1 -1
  98. data/lib/puppet/provider/nameservice/pw.rb +2 -2
  99. data/lib/puppet/provider/package/apt.rb +5 -1
  100. data/lib/puppet/provider/package/dnfmodule.rb +87 -0
  101. data/lib/puppet/provider/package/dpkg.rb +31 -17
  102. data/lib/puppet/provider/package/openbsd.rb +1 -1
  103. data/lib/puppet/provider/package/pip.rb +34 -9
  104. data/lib/puppet/provider/package/portage.rb +1 -1
  105. data/lib/puppet/provider/package/rpm.rb +5 -5
  106. data/lib/puppet/provider/package/windows/package.rb +1 -1
  107. data/lib/puppet/provider/package/yum.rb +1 -1
  108. data/lib/puppet/provider/parsedfile.rb +1 -1
  109. data/lib/puppet/provider/service/daemontools.rb +9 -9
  110. data/lib/puppet/provider/service/openbsd.rb +1 -1
  111. data/lib/puppet/provider/service/rcng.rb +2 -2
  112. data/lib/puppet/provider/service/runit.rb +2 -8
  113. data/lib/puppet/provider/service/systemd.rb +10 -10
  114. data/lib/puppet/provider/user/directoryservice.rb +1 -1
  115. data/lib/puppet/provider/user/user_role_add.rb +1 -1
  116. data/lib/puppet/provider/user/useradd.rb +22 -13
  117. data/lib/puppet/provider/user/windows_adsi.rb +4 -5
  118. data/lib/puppet/reference/indirection.rb +2 -2
  119. data/lib/puppet/reference/metaparameter.rb +1 -3
  120. data/lib/puppet/reference/providers.rb +1 -1
  121. data/lib/puppet/reference/type.rb +3 -9
  122. data/lib/puppet/reports.rb +1 -1
  123. data/lib/puppet/resource.rb +1 -1
  124. data/lib/puppet/resource/catalog.rb +1 -1
  125. data/lib/puppet/rest/errors.rb +1 -0
  126. data/lib/puppet/rest/response.rb +1 -0
  127. data/lib/puppet/rest/route.rb +1 -0
  128. data/lib/puppet/rest/routes.rb +3 -0
  129. data/lib/puppet/runtime.rb +25 -0
  130. data/lib/puppet/settings.rb +3 -3
  131. data/lib/puppet/settings/environment_conf.rb +1 -0
  132. data/lib/puppet/ssl/host.rb +1 -1
  133. data/lib/puppet/ssl/oids.rb +1 -1
  134. data/lib/puppet/ssl/state_machine.rb +23 -15
  135. data/lib/puppet/test/test_helper.rb +1 -1
  136. data/lib/puppet/transaction/report.rb +1 -1
  137. data/lib/puppet/trusted_external.rb +13 -0
  138. data/lib/puppet/type.rb +1 -3
  139. data/lib/puppet/type/exec.rb +7 -3
  140. data/lib/puppet/type/file.rb +1 -2
  141. data/lib/puppet/type/file/source.rb +2 -2
  142. data/lib/puppet/type/package.rb +10 -3
  143. data/lib/puppet/type/schedule.rb +1 -1
  144. data/lib/puppet/type/service.rb +1 -1
  145. data/lib/puppet/util.rb +2 -2
  146. data/lib/puppet/util/command_line/trollop.rb +1 -1
  147. data/lib/puppet/util/http_proxy.rb +2 -10
  148. data/lib/puppet/util/log.rb +2 -2
  149. data/lib/puppet/util/log/destinations.rb +2 -2
  150. data/lib/puppet/util/logging.rb +2 -2
  151. data/lib/puppet/util/metric.rb +2 -2
  152. data/lib/puppet/util/platform.rb +15 -4
  153. data/lib/puppet/util/provider_features.rb +2 -4
  154. data/lib/puppet/util/rdoc.rb +1 -1
  155. data/lib/puppet/util/reference.rb +1 -1
  156. data/lib/puppet/util/resource_template.rb +1 -1
  157. data/lib/puppet/util/selinux.rb +3 -1
  158. data/lib/puppet/util/windows/registry.rb +7 -5
  159. data/lib/puppet/vendor.rb +1 -1
  160. data/lib/puppet/vendor/require_vendored.rb +0 -1
  161. data/lib/puppet/version.rb +1 -1
  162. data/lib/puppet/x509/cert_provider.rb +4 -1
  163. data/locales/puppet.pot +279 -203
  164. data/man/man5/puppet.conf.5 +30 -8
  165. data/man/man8/puppet-agent.8 +4 -1
  166. data/man/man8/puppet-apply.8 +1 -1
  167. data/man/man8/puppet-catalog.8 +1 -1
  168. data/man/man8/puppet-config.8 +1 -1
  169. data/man/man8/puppet-describe.8 +1 -1
  170. data/man/man8/puppet-device.8 +1 -1
  171. data/man/man8/puppet-doc.8 +1 -1
  172. data/man/man8/puppet-epp.8 +1 -1
  173. data/man/man8/puppet-facts.8 +1 -1
  174. data/man/man8/puppet-filebucket.8 +1 -1
  175. data/man/man8/puppet-generate.8 +1 -1
  176. data/man/man8/puppet-help.8 +1 -1
  177. data/man/man8/puppet-key.8 +1 -1
  178. data/man/man8/puppet-lookup.8 +1 -1
  179. data/man/man8/puppet-man.8 +1 -1
  180. data/man/man8/puppet-module.8 +1 -1
  181. data/man/man8/puppet-node.8 +1 -1
  182. data/man/man8/puppet-parser.8 +1 -1
  183. data/man/man8/puppet-plugin.8 +1 -1
  184. data/man/man8/puppet-report.8 +1 -1
  185. data/man/man8/puppet-resource.8 +1 -1
  186. data/man/man8/puppet-script.8 +1 -1
  187. data/man/man8/puppet-ssl.8 +1 -1
  188. data/man/man8/puppet-status.8 +1 -1
  189. data/man/man8/puppet.8 +2 -2
  190. data/spec/fixtures/unit/provider/package/dnfmodule/dnf-module-list-installed.txt +11 -0
  191. data/spec/integration/configurer_spec.rb +52 -0
  192. data/spec/lib/puppet/certificate_factory.rb +2 -2
  193. data/spec/spec_helper.rb +24 -0
  194. data/spec/unit/application/device_spec.rb +6 -0
  195. data/spec/unit/application/ssl_spec.rb +4 -7
  196. data/spec/unit/configurer_spec.rb +1 -0
  197. data/spec/unit/context/trusted_information_spec.rb +41 -2
  198. data/spec/unit/http/client_spec.rb +440 -0
  199. data/spec/unit/http/resolver_spec.rb +45 -0
  200. data/spec/unit/http/service/ca_spec.rb +106 -0
  201. data/spec/unit/http/service_spec.rb +32 -0
  202. data/spec/unit/http/session_spec.rb +102 -0
  203. data/spec/unit/indirector/resource/ral_spec.rb +4 -4
  204. data/spec/unit/network/http/connection_spec.rb +119 -145
  205. data/spec/unit/network/http/site_spec.rb +7 -0
  206. data/spec/unit/parser/scope_spec.rb +10 -0
  207. data/spec/unit/pops/loaders/loaders_spec.rb +13 -2
  208. data/spec/unit/pops/loaders/module_loaders_spec.rb +37 -0
  209. data/spec/unit/provider/exec_spec.rb +209 -0
  210. data/spec/unit/provider/package/dnfmodule_spec.rb +186 -0
  211. data/spec/unit/provider/package/dpkg_spec.rb +238 -78
  212. data/spec/unit/provider/package/pip_spec.rb +51 -6
  213. data/spec/unit/provider/service/daemontools_spec.rb +24 -0
  214. data/spec/unit/provider/service/runit_spec.rb +24 -0
  215. data/spec/unit/provider/service/systemd_spec.rb +25 -25
  216. data/spec/unit/provider/user/useradd_spec.rb +46 -0
  217. data/spec/unit/ssl/host_spec.rb +0 -5
  218. data/spec/unit/ssl/state_machine_spec.rb +16 -10
  219. data/spec/unit/type/exec_spec.rb +6 -12
  220. data/spec/unit/type/file_spec.rb +9 -4
  221. data/spec/unit/type/package_spec.rb +5 -0
  222. data/spec/unit/util/execution_spec.rb +16 -0
  223. data/spec/unit/util/http_proxy_spec.rb +79 -27
  224. data/spec/unit/util/log/destinations_spec.rb +7 -3
  225. metadata +45 -22
  226. data/lib/puppet/pops/loader/null_loader.rb +0 -60
  227. data/lib/puppet/vendor/deep_merge/CHANGELOG +0 -45
  228. data/lib/puppet/vendor/deep_merge/Gemfile +0 -3
  229. data/lib/puppet/vendor/deep_merge/LICENSE +0 -21
  230. data/lib/puppet/vendor/deep_merge/PUPPET_README.md +0 -6
  231. data/lib/puppet/vendor/deep_merge/README.md +0 -113
  232. data/lib/puppet/vendor/deep_merge/Rakefile +0 -19
  233. data/lib/puppet/vendor/deep_merge/deep_merge.gemspec +0 -35
  234. data/lib/puppet/vendor/deep_merge/lib/deep_merge.rb +0 -2
  235. data/lib/puppet/vendor/deep_merge/lib/deep_merge/core.rb +0 -210
  236. data/lib/puppet/vendor/deep_merge/lib/deep_merge/deep_merge_hash.rb +0 -28
  237. data/lib/puppet/vendor/deep_merge/lib/deep_merge/rails_compat.rb +0 -27
  238. data/lib/puppet/vendor/deep_merge/test/test_deep_merge.rb +0 -608
  239. data/lib/puppet/vendor/load_deep_merge.rb +0 -1
  240. data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_get/should_yield_to_the_block.yml +0 -24
  241. data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_head/should_yield_to_the_block.yml +0 -24
  242. data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_post/should_yield_to_the_block.yml +0 -24
@@ -8,11 +8,13 @@ describe Puppet::Type.type(:package).provider(:dpkg), unless: Puppet::Util::Plat
8
8
  let(:vim_installed_output) { "install ok installed vim 2:7.3.547-6ubuntu5\n" }
9
9
  let(:all_installed_io) { StringIO.new([bash_installed_output, vim_installed_output].join) }
10
10
  let(:args) { ['-W', '--showformat', %Q{'${Status} ${Package} ${Version}\\n'}] }
11
+ let(:args_with_provides) { ['/bin/dpkg-query','-W', '--showformat', %Q{'${Status} ${Package} ${Version} [${Provides}]\\n'}]}
11
12
  let(:execute_options) do
12
13
  {:failonfail => true, :combine => true, :custom_environment => {}}
13
14
  end
14
- let(:resource_name) { 'package' }
15
+ let(:resource_name) { 'python' }
15
16
  let(:resource) { double('resource', :[] => resource_name) }
17
+ let(:dpkg_query_result) { 'install ok installed python 2.7.13' }
16
18
  let(:provider) { described_class.new(resource) }
17
19
 
18
20
  it "has documentation" do
@@ -68,105 +70,247 @@ describe Puppet::Type.type(:package).provider(:dpkg), unless: Puppet::Util::Plat
68
70
  expect(Puppet::Util::Execution).to receive(:execute).with(query_args, execute_options).and_return(Puppet::Util::Execution::ProcessOutput.new(output, 0))
69
71
  end
70
72
 
73
+ def dpkg_query_execution_with_multiple_args_returns(output, *args)
74
+ args.each do |arg|
75
+ allow(Puppet::Util::Execution).to receive(:execute).with(arg, execute_options).and_return(Puppet::Util::Execution::ProcessOutput.new(output, 0))
76
+ end
77
+ end
78
+
71
79
  before do
72
80
  allow(Puppet::Util).to receive(:which).with('/usr/bin/dpkg-query').and_return(dpkgquery_path)
73
81
  end
74
82
 
75
83
  it "considers the package purged if dpkg-query fails" do
84
+ allow(resource).to receive(:allow_virtual?).and_return(false)
76
85
  allow(Puppet::Util::Execution).to receive(:execute).with(query_args, execute_options).and_raise(Puppet::ExecutionFailure.new("eh"))
77
86
 
78
87
  expect(provider.query[:ensure]).to eq(:purged)
79
88
  end
80
89
 
81
- it "returns a hash of the found package status for an installed package" do
82
- dpkg_query_execution_returns(bash_installed_output)
83
-
84
- expect(provider.query).to eq({:ensure => "4.2-5ubuntu3", :error => "ok", :desired => "install", :name => "bash", :status => "installed", :provider => :dpkg})
85
- end
86
-
87
- it "considers the package absent if the dpkg-query result cannot be interpreted" do
88
- dpkg_query_execution_returns('some-bad-data')
89
-
90
- expect(provider.query[:ensure]).to eq(:absent)
91
- end
92
-
93
- it "fails if an error is discovered" do
94
- dpkg_query_execution_returns(bash_installed_output.gsub("ok","error"))
90
+ context "allow_virtual true" do
91
+ before do
92
+ allow(resource).to receive(:allow_virtual?).and_return(true)
93
+ end
95
94
 
96
- expect { provider.query }.to raise_error(Puppet::Error)
95
+ context "virtual_packages" do
96
+ let(:query_output) { 'install ok installed python 2.7.13 [python-ctypes, python-email, python-importlib, python-profiler, python-wsgiref, python-gold]' }
97
+ let(:virtual_packages_query_args) do
98
+ result = args_with_provides.dup
99
+ result.push(resource_name)
100
+ end
101
+
102
+ it "considers the package purged if dpkg-query fails" do
103
+ allow(Puppet::Util::Execution).to receive(:execute).with(args_with_provides, execute_options).and_raise(Puppet::ExecutionFailure.new("eh"))
104
+ expect(provider.query[:ensure]).to eq(:purged)
105
+ end
106
+
107
+ it "returns a hash of the found package status for an installed package" do
108
+ dpkg_query_execution_with_multiple_args_returns(query_output, args_with_provides,virtual_packages_query_args)
109
+ dpkg_query_execution_with_multiple_args_returns(dpkg_query_result, args, query_args)
110
+ expect(provider.query).to eq(:ensure => "2.7.13", :error => "ok", :desired => "install", :name => "python", :status => "installed", :provider => :dpkg)
111
+ end
112
+
113
+ it "considers the package absent if the dpkg-query result cannot be interpreted" do
114
+ dpkg_query_execution_with_multiple_args_returns('some-bad-data',args_with_provides,virtual_packages_query_args)
115
+ dpkg_query_execution_with_multiple_args_returns('some-bad-data', args, query_args)
116
+ expect(provider.query[:ensure]).to eq(:absent)
117
+ end
118
+
119
+ it "fails if an error is discovered" do
120
+ dpkg_query_execution_with_multiple_args_returns(query_output.gsub("ok","error"),args_with_provides,virtual_packages_query_args)
121
+ dpkg_query_execution_with_multiple_args_returns(dpkg_query_result.gsub("ok","error"), args, query_args)
122
+ expect { provider.query }.to raise_error(Puppet::Error, /Package python, version 2.7.13 is in error state: error/)
123
+ end
124
+
125
+ it "considers the package purged if it is marked 'not-installed" do
126
+ not_installed_query = query_output.gsub("installed", "not-installed").delete!('2.7.13')
127
+ dpkg_query_execution_with_multiple_args_returns(not_installed_query, args_with_provides,virtual_packages_query_args)
128
+ dpkg_query_execution_with_multiple_args_returns(dpkg_query_result.gsub("installed", "not-installed").delete!('2.7.13'), args, query_args)
129
+ expect(provider.query[:ensure]).to eq(:purged)
130
+ end
131
+
132
+ it "considers the package absent if it is marked 'config-files'" do
133
+ dpkg_query_execution_with_multiple_args_returns(query_output.gsub("installed","config-files"),args_with_provides,virtual_packages_query_args)
134
+ dpkg_query_execution_with_multiple_args_returns(dpkg_query_result.gsub("installed","config-files"), args, query_args)
135
+ expect(provider.query[:ensure]).to eq(:absent)
136
+ end
137
+
138
+ it "considers the package absent if it is marked 'half-installed'" do
139
+ dpkg_query_execution_with_multiple_args_returns(query_output.gsub("installed","half-installed"),args_with_provides,virtual_packages_query_args)
140
+ dpkg_query_execution_with_multiple_args_returns(dpkg_query_result.gsub("installed","half-installed"), args, query_args)
141
+ expect(provider.query[:ensure]).to eq(:absent)
142
+ end
143
+
144
+ it "considers the package absent if it is marked 'unpacked'" do
145
+ dpkg_query_execution_with_multiple_args_returns(query_output.gsub("installed","unpacked"),args_with_provides,virtual_packages_query_args)
146
+ dpkg_query_execution_with_multiple_args_returns(dpkg_query_result.gsub("installed","unpacked"), args, query_args)
147
+ expect(provider.query[:ensure]).to eq(:absent)
148
+ end
149
+
150
+ it "considers the package absent if it is marked 'half-configured'" do
151
+ dpkg_query_execution_with_multiple_args_returns(query_output.gsub("installed","half-configured"),args_with_provides,virtual_packages_query_args)
152
+ dpkg_query_execution_with_multiple_args_returns(dpkg_query_result.gsub("installed","half-configured"), args, query_args)
153
+ expect(provider.query[:ensure]).to eq(:absent)
154
+ end
155
+
156
+ it "considers the package held if its state is 'hold'" do
157
+ dpkg_query_execution_with_multiple_args_returns(query_output.gsub("install","hold"),args_with_provides,virtual_packages_query_args)
158
+ dpkg_query_execution_with_multiple_args_returns(dpkg_query_result.gsub("install","hold"), args, query_args)
159
+ expect(provider.query[:ensure]).to eq(:held)
160
+ end
161
+
162
+ context "regex check for query search" do
163
+ let(:resource_name) { 'python-email' }
164
+ let(:resource) { instance_double('Puppet::Type::Package') }
165
+ before do
166
+ allow(resource).to receive(:[]).with(:name).and_return(resource_name)
167
+ allow(resource).to receive(:[]=)
168
+ end
169
+
170
+ it "checks if virtual package regex for query is correctand phisical package is installed" do
171
+ dpkg_query_execution_with_multiple_args_returns(query_output,args_with_provides,virtual_packages_query_args)
172
+ dpkg_query_execution_with_multiple_args_returns(dpkg_query_result, args, query_args)
173
+ expect(provider.query).to match({:desired=>"install", :ensure=>"2.7.13", :error=>"ok", :name=>"python", :provider=>:dpkg, :status=>"installed"})
174
+ end
175
+
176
+ context "regex check with no partial matching" do
177
+ let(:resource_name) { 'python-em' }
178
+
179
+ it "checks if virtual package regex for query is correct and regext dosen't make partial matching" do
180
+ expect(provider).to receive(:dpkgquery).with('-W', '--showformat', %Q{'${Status} ${Package} ${Version} [${Provides}]\\n'}).and_return(query_output)
181
+ expect(provider).to receive(:dpkgquery).with('-W', '--showformat', %Q{'${Status} ${Package} ${Version}\\n'}, resource_name).and_return("#{dpkg_query_result} #{resource_name}")
182
+
183
+ provider.query
184
+ end
185
+
186
+ context "regex check with special characters" do
187
+ let(:resource_name) { 'g++' }
188
+
189
+ it "checks if virtual package regex for query is correct and regext dosen't make partial matching" do
190
+ expect(Puppet).to_not receive(:info).with(/is virtual/)
191
+ expect(provider).to receive(:dpkgquery).with('-W', '--showformat', %Q{'${Status} ${Package} ${Version} [${Provides}]\\n'}).and_return(query_output)
192
+ expect(provider).to receive(:dpkgquery).with('-W', '--showformat', %Q{'${Status} ${Package} ${Version}\\n'}, resource_name).and_return("#{dpkg_query_result} #{resource_name}")
193
+
194
+ provider.query
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
97
200
  end
98
201
 
99
- it "considers the package purged if it is marked 'not-installed'" do
100
- not_installed_bash = bash_installed_output.gsub("installed", "not-installed")
101
- not_installed_bash.gsub!(bash_version, "")
102
- dpkg_query_execution_returns(not_installed_bash)
103
-
104
- expect(provider.query[:ensure]).to eq(:purged)
105
- end
202
+ context "allow_virtual false" do
203
+ before do
204
+ allow(resource).to receive(:allow_virtual?).and_return(false)
205
+ end
106
206
 
107
- it "considers the package absent if it is marked 'config-files'" do
108
- dpkg_query_execution_returns(bash_installed_output.gsub("installed","config-files"))
109
- expect(provider.query[:ensure]).to eq(:absent)
110
- end
207
+ it "returns a hash of the found package status for an installed package" do
208
+ dpkg_query_execution_returns(bash_installed_output)
111
209
 
112
- it "considers the package absent if it is marked 'half-installed'" do
113
- dpkg_query_execution_returns(bash_installed_output.gsub("installed","half-installed"))
114
- expect(provider.query[:ensure]).to eq(:absent)
115
- end
210
+ expect(provider.query).to eq({:ensure => "4.2-5ubuntu3", :error => "ok", :desired => "install", :name => "bash", :status => "installed", :provider => :dpkg})
211
+ end
116
212
 
117
- it "considers the package absent if it is marked 'unpacked'" do
118
- dpkg_query_execution_returns(bash_installed_output.gsub("installed","unpacked"))
119
- expect(provider.query[:ensure]).to eq(:absent)
120
- end
213
+ it "considers the package absent if the dpkg-query result cannot be interpreted" do
214
+ allow(resource).to receive(:allow_virtual?).and_return(false)
215
+ dpkg_query_execution_returns('some-bad-data')
216
+ expect(provider.query[:ensure]).to eq(:absent)
217
+ end
121
218
 
122
- it "considers the package absent if it is marked 'half-configured'" do
123
- dpkg_query_execution_returns(bash_installed_output.gsub("installed","half-configured"))
124
- expect(provider.query[:ensure]).to eq(:absent)
125
- end
219
+ it "fails if an error is discovered" do
220
+ dpkg_query_execution_returns(bash_installed_output.gsub("ok","error"))
221
+ expect { provider.query }.to raise_error(Puppet::Error)
222
+ end
126
223
 
127
- it "considers the package held if its state is 'hold'" do
128
- dpkg_query_execution_returns(bash_installed_output.gsub("install","hold"))
129
- expect(provider.query[:ensure]).to eq(:held)
130
- end
224
+ it "considers the package purged if it is marked 'not-installed'" do
225
+ not_installed_bash = bash_installed_output.gsub("installed", "not-installed")
226
+ not_installed_bash.gsub!(bash_version, "")
227
+ dpkg_query_execution_returns(not_installed_bash)
131
228
 
132
- context "parsing tests" do
133
- let(:resource_name) { 'name' }
134
- let(:package_hash) do
135
- {
136
- :desired => 'desired',
137
- :error => 'ok',
138
- :status => 'status',
139
- :name => resource_name,
140
- :ensure => 'ensure',
141
- :provider => :dpkg,
142
- }
143
- end
144
- let(:package_not_found_hash) do
145
- {:ensure => :purged, :status => 'missing', :name => resource_name, :error => 'ok'}
229
+ expect(provider.query[:ensure]).to eq(:purged)
146
230
  end
147
231
 
148
- def parser_test(dpkg_output_string, gold_hash, number_of_debug_logs = 0)
149
- dpkg_query_execution_returns(dpkg_output_string)
150
- expect(Puppet).not_to receive(:warning)
151
- expect(Puppet).to receive(:debug).exactly(number_of_debug_logs).times
232
+ it "considers the package absent if it is marked 'config-files'" do
233
+ dpkg_query_execution_returns(bash_installed_output.gsub("installed","config-files"))
234
+ expect(provider.query[:ensure]).to eq(:absent)
235
+ end
152
236
 
153
- expect(provider.query).to eq(gold_hash)
237
+ it "considers the package absent if it is marked 'half-installed'" do
238
+ dpkg_query_execution_returns(bash_installed_output.gsub("installed","half-installed"))
239
+ expect(provider.query[:ensure]).to eq(:absent)
154
240
  end
155
241
 
156
- it "parses properly even if optional ensure field is missing" do
157
- no_ensure = 'desired ok status name '
158
- parser_test(no_ensure, package_hash.merge(:ensure => ''))
242
+ it "considers the package absent if it is marked 'unpacked'" do
243
+ dpkg_query_execution_returns(bash_installed_output.gsub("installed","unpacked"))
244
+ expect(provider.query[:ensure]).to eq(:absent)
159
245
  end
160
246
 
161
- it "provides debug logging of unparsable lines" do
162
- parser_test('an unexpected dpkg msg with an exit code of 0', package_not_found_hash.merge(:ensure => :absent), 1)
247
+ it "considers the package absent if it is marked 'half-configured'" do
248
+ dpkg_query_execution_returns(bash_installed_output.gsub("installed","half-configured"))
249
+ expect(provider.query[:ensure]).to eq(:absent)
163
250
  end
164
251
 
165
- it "does not log if execution returns with non-zero exit code" do
166
- expect(Puppet::Util::Execution).to receive(:execute).with(query_args, execute_options).and_raise(Puppet::ExecutionFailure.new("failed"))
167
- expect(Puppet).not_to receive(:debug)
252
+ it "considers the package held if its state is 'hold'" do
253
+ dpkg_query_execution_returns(bash_installed_output.gsub("install","hold"))
254
+ expect(provider.query[:ensure]).to eq(:held)
255
+ end
168
256
 
169
- expect(provider.query).to eq(package_not_found_hash)
257
+ context "parsing tests" do
258
+ let(:resource_name) { 'name' }
259
+ let(:package_hash) do
260
+ {
261
+ :desired => 'desired',
262
+ :error => 'ok',
263
+ :status => 'status',
264
+ :name => resource_name,
265
+ :ensure => 'ensure',
266
+ :provider => :dpkg,
267
+ }
268
+ end
269
+
270
+ let(:package_not_found_hash) do
271
+ {:ensure => :purged, :status => 'missing', :name => resource_name, :error => 'ok'}
272
+ end
273
+
274
+ let(:output) {'an unexpected dpkg msg with an exit code of 0'}
275
+
276
+ def parser_test(dpkg_output_string, gold_hash, number_of_debug_logs = 0)
277
+ dpkg_query_execution_returns(dpkg_output_string)
278
+ expect(Puppet).not_to receive(:warning)
279
+ expect(Puppet).to receive(:debug).exactly(number_of_debug_logs).times
280
+
281
+ expect(provider.query).to eq(gold_hash)
282
+ end
283
+
284
+ it "parses properly even if optional ensure field is missing" do
285
+ no_ensure = 'desired ok status name '
286
+ parser_test(no_ensure, package_hash.merge(:ensure => ''))
287
+ end
288
+
289
+ it "provides debug logging of unparsable lines with allow_virtual enabled" do
290
+ allow(resource).to receive(:allow_virtual?).and_return(true)
291
+ dpkg_query_execution_with_multiple_args_returns(output, args_with_provides, query_args)
292
+ expect(Puppet).not_to receive(:warning)
293
+ expect(Puppet).to receive(:debug).exactly(1).times
294
+ expect(provider.query).to eq(package_not_found_hash.merge(:ensure => :absent))
295
+ end
296
+
297
+ it "provides debug logging of unparsable lines" do
298
+ parser_test('an unexpected dpkg msg with an exit code of 0', package_not_found_hash.merge(:ensure => :absent), 1)
299
+ end
300
+
301
+ it "does not log if execution returns with non-zero exit code with allow_virtual enabled" do
302
+ allow(resource).to receive(:allow_virtual?).and_return(true)
303
+ expect(Puppet::Util::Execution).to receive(:execute).with(args_with_provides, execute_options).and_raise(Puppet::ExecutionFailure.new("failed"))
304
+ expect(Puppet).not_to receive(:debug)
305
+ expect(provider.query).to eq(package_not_found_hash)
306
+ end
307
+
308
+ it "does not log if execution returns with non-zero exit code" do
309
+ expect(Puppet::Util::Execution).to receive(:execute).with(query_args, execute_options).and_raise(Puppet::ExecutionFailure.new("failed"))
310
+ expect(Puppet).not_to receive(:debug)
311
+
312
+ expect(provider.query).to eq(package_not_found_hash)
313
+ end
170
314
  end
171
315
  end
172
316
  end
@@ -222,7 +366,6 @@ describe Puppet::Type.type(:package).provider(:dpkg), unless: Puppet::Util::Plat
222
366
  end
223
367
 
224
368
  it "installs first if package is not present and ensure holding" do
225
-
226
369
  allow(provider).to receive(:execute)
227
370
  allow(provider).to receive(:package_not_installed?).and_return(true)
228
371
  expect(provider).to receive(:install).once
@@ -258,8 +401,8 @@ describe Puppet::Type.type(:package).provider(:dpkg), unless: Puppet::Util::Plat
258
401
 
259
402
  context "when determining latest available version" do
260
403
  it "returns the version found by dpkg-deb" do
261
- expect(resource).to receive(:[]).with(:source).and_return("myfile")
262
- expect(provider).to receive(:dpkg_deb).with(any_args, "myfile").and_return("package\t1.0")
404
+ expect(resource).to receive(:[]).with(:source).and_return("python")
405
+ expect(provider).to receive(:dpkg_deb).with('--show', "python").and_return("package\t1.0")
263
406
  expect(provider.latest).to eq("1.0")
264
407
  end
265
408
 
@@ -287,9 +430,26 @@ describe Puppet::Type.type(:package).provider(:dpkg), unless: Puppet::Util::Plat
287
430
  provider.purge
288
431
  end
289
432
 
290
- it "raises error if package name is nil" do
291
- expect {provider.package_not_installed?(nil)}.to raise_error(ArgumentError,"Package name is nil or empty")
292
- expect {provider.package_not_installed?("")}.to raise_error(ArgumentError,"Package name is nil or empty")
433
+ context "package_not_installed?" do
434
+ context "allow_virtual false" do
435
+ before do
436
+ allow(resource).to receive(:allow_virtual?).and_return(false)
437
+ end
438
+
439
+ it "returns true if package is not found" do
440
+ expect(provider).to receive(:dpkgquery).with("-W", "--showformat", "'${Status} ${Package} ${Version}\\n'", resource_name).and_raise(Puppet::ExecutionFailure.new("eh"))
441
+ expect(provider.package_not_installed?).to eq(true)
442
+ end
443
+
444
+ it "returns true if package is not installed" do
445
+ expect(provider).to receive(:dpkgquery).with("-W", "--showformat", "'${Status} ${Package} ${Version}\\n'", resource_name).and_return("unknown ok not-installed #{resource_name}")
446
+ expect(provider.package_not_installed?).to eq(true)
447
+ end
448
+
449
+ it "returns false if package is installed" do
450
+ expect(provider).to receive(:dpkgquery).with("-W", "--showformat", "'${Status} ${Package} ${Version}\\n'", resource_name).and_return("install ok installed resource_name 1.2.3")
451
+ expect(provider.package_not_installed?).to eq(false)
452
+ end
453
+ end
293
454
  end
294
455
  end
295
-
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- osfamilies = { 'windows' => ['pip.exe'], 'other' => ['pip', 'pip-python'] }
3
+ osfamilies = { 'windows' => ['pip.exe'], 'other' => ['pip', 'pip-python', 'pip2', 'pip-2'] }
4
4
 
5
5
  describe Puppet::Type.type(:package).provider(:pip) do
6
6
 
@@ -205,6 +205,13 @@ describe Puppet::Type.type(:package).provider(:pip) do
205
205
  @resource[:name] = "fake_package"
206
206
  expect(@provider.latest).to eq(nil)
207
207
  end
208
+
209
+ it "should use 'install_options' when specified" do
210
+ expect(Puppet::Util::Execution).to receive(:execpipe).with(array_including([["--index=https://fake.example.com"]])).once
211
+ @resource[:name] = "fake_package"
212
+ @resource[:install_options] = ['--index' => 'https://fake.example.com']
213
+ expect(@provider.latest).to eq(nil)
214
+ end
208
215
  end
209
216
 
210
217
  context "with pip version >= 1.5.4" do
@@ -259,6 +266,13 @@ describe Puppet::Type.type(:package).provider(:pip) do
259
266
  latest = @provider.latest
260
267
  expect(latest).to eq('15.0.2')
261
268
  end
269
+
270
+ it "should use 'install_options' when specified" do
271
+ expect(Puppet::Util::Execution).to receive(:execpipe).with(array_including([["--index=https://fake.example.com"]])).once
272
+ @resource[:name] = "fake_package"
273
+ @resource[:install_options] = ['--index' => 'https://fake.example.com']
274
+ expect(@provider.latest).to eq(nil)
275
+ end
262
276
  end
263
277
  end
264
278
 
@@ -349,12 +363,43 @@ describe Puppet::Type.type(:package).provider(:pip) do
349
363
  end
350
364
 
351
365
  context "pip_version" do
366
+ let(:pip) { '/fake/bin/pip' }
367
+
352
368
  it "should look up version if pip is present" do
353
- allow(described_class).to receive(:pip_cmd).and_return('/fake/bin/pip')
354
- p = double("process")
355
- expect(p).to receive(:collect).and_yield('pip 8.0.2 from /usr/local/lib/python2.7/dist-packages (python 2.7)')
356
- expect(described_class).to receive(:execpipe).with(['/fake/bin/pip', '--version']).and_yield(p)
357
- expect(described_class.pip_version('/fake/bin/pip')).to eq('8.0.2')
369
+ allow(described_class).to receive(:pip_cmd).and_return(pip)
370
+ process = ['pip 8.0.2 from /usr/local/lib/python2.7/dist-packages (python 2.7)']
371
+ allow(described_class).to receive(:execpipe).with([pip, '--version']).and_yield(process)
372
+
373
+ expect(described_class.pip_version(pip)).to eq('8.0.2')
374
+ end
375
+
376
+ it "parses multiple lines of output" do
377
+ allow(described_class).to receive(:pip_cmd).and_return(pip)
378
+ process = [
379
+ "/usr/local/lib/python2.7/dist-packages/urllib3/contrib/socks.py:37: DependencyWarning: SOCKS support in urllib3 requires the installation of optional dependencies: specifically, PySocks. For more information, see https://urllib3.readthedocs.io/en/latest/contrib.html#socks-proxies",
380
+ " DependencyWarning",
381
+ "pip 1.5.6 from /usr/lib/python2.7/dist-packages (python 2.7)"
382
+ ]
383
+ allow(described_class).to receive(:execpipe).with([pip, '--version']).and_yield(process)
384
+
385
+ expect(described_class.pip_version(pip)).to eq('1.5.6')
386
+ end
387
+
388
+ it "raises if there isn't a version string" do
389
+ allow(described_class).to receive(:pip_cmd).and_return(pip)
390
+ allow(described_class).to receive(:execpipe).with([pip, '--version']).and_yield([""])
391
+ expect {
392
+ described_class.pip_version(pip)
393
+ }.to raise_error(Puppet::Error, 'Cannot resolve pip version')
394
+ end
395
+
396
+ it "quotes commands with spaces" do
397
+ pip = 'C:\Program Files\Python27\Scripts\pip.exe'
398
+ allow(described_class).to receive(:pip_cmd).and_return(pip)
399
+ process = ["pip 18.1 from c:\program files\python27\lib\site-packages\pip (python 2.7)\r\n"]
400
+ allow(described_class).to receive(:execpipe).with(["\"#{pip}\"", '--version']).and_yield(process)
401
+
402
+ expect(described_class.pip_version(pip)).to eq('18.1')
358
403
  end
359
404
  end
360
405