puppet 6.12.0 → 6.13.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 (144) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +12 -12
  3. data/README.md +1 -1
  4. data/ext/project_data.yaml +1 -1
  5. data/lib/puppet.rb +22 -7
  6. data/lib/puppet/application/resource.rb +1 -1
  7. data/lib/puppet/configurer.rb +8 -13
  8. data/lib/puppet/defaults.rb +83 -49
  9. data/lib/puppet/environments.rb +26 -18
  10. data/lib/puppet/face/facts.rb +8 -5
  11. data/lib/puppet/file_system/memory_file.rb +6 -0
  12. data/lib/puppet/file_system/memory_impl.rb +13 -0
  13. data/lib/puppet/file_system/windows.rb +7 -10
  14. data/lib/puppet/http.rb +2 -0
  15. data/lib/puppet/http/client.rb +30 -0
  16. data/lib/puppet/http/errors.rb +2 -0
  17. data/lib/puppet/http/service.rb +61 -2
  18. data/lib/puppet/http/service/compiler.rb +86 -0
  19. data/lib/puppet/http/service/file_server.rb +85 -0
  20. data/lib/puppet/http/service/report.rb +4 -8
  21. data/lib/puppet/http/session.rb +8 -1
  22. data/lib/puppet/indirector/catalog/compiler.rb +10 -0
  23. data/lib/puppet/indirector/file_bucket_file/file.rb +1 -1
  24. data/lib/puppet/indirector/json.rb +1 -1
  25. data/lib/puppet/indirector/msgpack.rb +1 -1
  26. data/lib/puppet/network/http/connection.rb +4 -0
  27. data/lib/puppet/network/http/nocache_pool.rb +1 -0
  28. data/lib/puppet/network/http/pool.rb +5 -1
  29. data/lib/puppet/parser/ast/pops_bridge.rb +6 -11
  30. data/lib/puppet/pops/evaluator/access_operator.rb +2 -2
  31. data/lib/puppet/pops/evaluator/evaluator_impl.rb +1 -1
  32. data/lib/puppet/pops/loader/puppet_plan_instantiator.rb +12 -3
  33. data/lib/puppet/pops/parser/evaluating_parser.rb +5 -7
  34. data/lib/puppet/pops/types/p_object_type_extension.rb +10 -0
  35. data/lib/puppet/pops/types/type_calculator.rb +24 -0
  36. data/lib/puppet/pops/validation/checker4_0.rb +1 -1
  37. data/lib/puppet/pops/validation/tasks_checker.rb +5 -1
  38. data/lib/puppet/provider/aix_object.rb +4 -2
  39. data/lib/puppet/provider/group/aix.rb +1 -0
  40. data/lib/puppet/provider/group/groupadd.rb +52 -24
  41. data/lib/puppet/provider/package/apt.rb +14 -3
  42. data/lib/puppet/provider/package/dnfmodule.rb +9 -2
  43. data/lib/puppet/provider/package/dpkg.rb +14 -7
  44. data/lib/puppet/provider/package/fink.rb +20 -3
  45. data/lib/puppet/provider/package/openbsd.rb +13 -1
  46. data/lib/puppet/provider/package/pkg.rb +18 -5
  47. data/lib/puppet/provider/package/yum.rb +9 -5
  48. data/lib/puppet/provider/user/aix.rb +1 -0
  49. data/lib/puppet/provider/user/directoryservice.rb +30 -5
  50. data/lib/puppet/provider/user/useradd.rb +6 -7
  51. data/lib/puppet/reports/store.rb +1 -1
  52. data/lib/puppet/settings.rb +2 -0
  53. data/lib/puppet/ssl/certificate.rb +2 -1
  54. data/lib/puppet/test/test_helper.rb +4 -0
  55. data/lib/puppet/transaction/resource_harness.rb +1 -1
  56. data/lib/puppet/type/group.rb +2 -2
  57. data/lib/puppet/type/package.rb +63 -9
  58. data/lib/puppet/type/user.rb +2 -2
  59. data/lib/puppet/util/log/destinations.rb +1 -1
  60. data/lib/puppet/util/pidlock.rb +26 -6
  61. data/lib/puppet/util/plist.rb +6 -0
  62. data/lib/puppet/util/storage.rb +0 -1
  63. data/lib/puppet/util/yaml.rb +1 -1
  64. data/lib/puppet/version.rb +1 -1
  65. data/locales/puppet.pot +127 -115
  66. data/man/man5/puppet.conf.5 +21 -7
  67. data/man/man8/puppet-agent.8 +1 -1
  68. data/man/man8/puppet-apply.8 +1 -1
  69. data/man/man8/puppet-catalog.8 +1 -1
  70. data/man/man8/puppet-config.8 +1 -1
  71. data/man/man8/puppet-describe.8 +1 -1
  72. data/man/man8/puppet-device.8 +1 -1
  73. data/man/man8/puppet-doc.8 +1 -1
  74. data/man/man8/puppet-epp.8 +1 -1
  75. data/man/man8/puppet-facts.8 +1 -1
  76. data/man/man8/puppet-filebucket.8 +1 -1
  77. data/man/man8/puppet-generate.8 +1 -1
  78. data/man/man8/puppet-help.8 +1 -1
  79. data/man/man8/puppet-key.8 +1 -1
  80. data/man/man8/puppet-lookup.8 +1 -1
  81. data/man/man8/puppet-man.8 +1 -1
  82. data/man/man8/puppet-module.8 +1 -1
  83. data/man/man8/puppet-node.8 +1 -1
  84. data/man/man8/puppet-parser.8 +1 -1
  85. data/man/man8/puppet-plugin.8 +1 -1
  86. data/man/man8/puppet-report.8 +1 -1
  87. data/man/man8/puppet-resource.8 +1 -1
  88. data/man/man8/puppet-script.8 +1 -1
  89. data/man/man8/puppet-ssl.8 +1 -1
  90. data/man/man8/puppet-status.8 +1 -1
  91. data/man/man8/puppet.8 +2 -2
  92. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_fetch_if_not_on_the_local_disk.yml +0 -35
  93. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_not_update_if_content_on_disk_is_up-to-date.yml +0 -37
  94. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_update_if_content_differs_on_disk.yml +0 -37
  95. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_mtime_is_older_on_disk.yml +0 -35
  96. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_no_header_specified.yml +0 -33
  97. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_not_on_the_local_disk.yml +0 -35
  98. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_not_update_if_mtime_is_newer_on_disk.yml +0 -35
  99. data/spec/integration/configurer_spec.rb +26 -7
  100. data/spec/integration/indirector/facts/facter_spec.rb +4 -0
  101. data/spec/unit/application/apply_spec.rb +2 -12
  102. data/spec/unit/application/resource_spec.rb +2 -2
  103. data/spec/unit/configurer/fact_handler_spec.rb +0 -4
  104. data/spec/unit/configurer_spec.rb +0 -3
  105. data/spec/unit/defaults_spec.rb +1 -1
  106. data/spec/unit/environments_spec.rb +57 -28
  107. data/spec/unit/face/facts_spec.rb +24 -20
  108. data/spec/unit/file_system_spec.rb +16 -2
  109. data/spec/unit/http/client_spec.rb +6 -0
  110. data/spec/unit/http/service/compiler_spec.rb +322 -0
  111. data/spec/unit/http/service/file_server_spec.rb +219 -0
  112. data/spec/unit/http/service/report_spec.rb +8 -1
  113. data/spec/unit/http/service_spec.rb +4 -0
  114. data/spec/unit/http/session_spec.rb +31 -0
  115. data/spec/unit/indirector/catalog/compiler_spec.rb +46 -29
  116. data/spec/unit/network/http/connection_spec.rb +23 -1
  117. data/spec/unit/network/http/nocache_pool_spec.rb +3 -3
  118. data/spec/unit/network/http/pool_spec.rb +32 -0
  119. data/spec/unit/node/facts_spec.rb +2 -1
  120. data/spec/unit/node_spec.rb +7 -4
  121. data/spec/unit/pops/serialization/to_from_hr_spec.rb +6 -1
  122. data/spec/unit/pops/validator/validator_spec.rb +7 -2
  123. data/spec/unit/provider/aix_object_spec.rb +16 -2
  124. data/spec/unit/provider/group/groupadd_spec.rb +167 -56
  125. data/spec/unit/provider/package/apt_spec.rb +13 -2
  126. data/spec/unit/provider/package/aptitude_spec.rb +1 -0
  127. data/spec/unit/provider/package/dnfmodule_spec.rb +22 -0
  128. data/spec/unit/provider/package/dpkg_spec.rb +28 -6
  129. data/spec/unit/provider/package/openbsd_spec.rb +17 -0
  130. data/spec/unit/provider/package/pkg_spec.rb +15 -1
  131. data/spec/unit/provider/package/yum_spec.rb +50 -0
  132. data/spec/unit/provider/user/directoryservice_spec.rb +41 -0
  133. data/spec/unit/provider/user/useradd_spec.rb +13 -8
  134. data/spec/unit/puppet_pal_2pec.rb +3 -0
  135. data/spec/unit/puppet_pal_catalog_spec.rb +3 -0
  136. data/spec/unit/puppet_spec.rb +14 -0
  137. data/spec/unit/ssl/certificate_spec.rb +7 -0
  138. data/spec/unit/transaction/persistence_spec.rb +1 -10
  139. data/spec/unit/type/package_spec.rb +8 -0
  140. data/spec/unit/type/user_spec.rb +0 -1
  141. data/spec/unit/util/pidlock_spec.rb +38 -16
  142. data/spec/unit/util/plist_spec.rb +20 -0
  143. data/spec/unit/util/storage_spec.rb +1 -8
  144. metadata +10 -4
@@ -186,6 +186,13 @@ module Puppet::Environments
186
186
  end
187
187
  end
188
188
 
189
+ def self.real_path(dir)
190
+ if Puppet::FileSystem.symlink?(dir) && Puppet[:versioned_environment_dirs]
191
+ dir = Puppet::FileSystem.expand_path(Puppet::FileSystem.readlink(dir))
192
+ end
193
+ return dir
194
+ end
195
+
189
196
  # @!macro loader_search_paths
190
197
  def search_paths
191
198
  ["file://#{@environment_dir}"]
@@ -193,27 +200,26 @@ module Puppet::Environments
193
200
 
194
201
  # @!macro loader_list
195
202
  def list
196
- valid_directories.collect do |envdir|
197
- name = Puppet::FileSystem.basename_string(envdir).intern
198
-
203
+ valid_environment_names.collect do |name|
199
204
  create_environment(name)
200
205
  end
201
206
  end
202
207
 
203
208
  # @!macro loader_get
204
209
  def get(name)
205
- if valid_directory?(File.join(@environment_dir, name.to_s))
210
+ if validated_directory(File.join(@environment_dir, name.to_s))
206
211
  create_environment(name)
207
212
  end
208
213
  end
209
214
 
210
215
  # @!macro loader_get_conf
211
216
  def get_conf(name)
212
- envdir = File.join(@environment_dir, name.to_s)
213
- if valid_directory?(envdir)
214
- return Puppet::Settings::EnvironmentConf.load_from(envdir, @global_module_path)
217
+ envdir = validated_directory(File.join(@environment_dir, name.to_s))
218
+ if envdir
219
+ Puppet::Settings::EnvironmentConf.load_from(envdir, @global_module_path)
220
+ else
221
+ nil
215
222
  end
216
- nil
217
223
  end
218
224
 
219
225
  private
@@ -230,19 +236,21 @@ module Puppet::Environments
230
236
  env
231
237
  end
232
238
 
233
- def valid_directory?(envdir)
234
- name = Puppet::FileSystem.basename_string(envdir)
235
- Puppet::FileSystem.directory?(envdir) &&
236
- Puppet::Node::Environment.valid_name?(name)
239
+ def validated_directory(envdir)
240
+ env_name = Puppet::FileSystem.basename_string(envdir)
241
+ envdir = Puppet::Environments::Directories.real_path(envdir)
242
+ if Puppet::FileSystem.directory?(envdir) && Puppet::Node::Environment.valid_name?(env_name)
243
+ envdir
244
+ else
245
+ nil
246
+ end
237
247
  end
238
248
 
239
- def valid_directories
249
+ def valid_environment_names
240
250
  if Puppet::FileSystem.directory?(@environment_dir)
241
- Puppet::FileSystem.children(@environment_dir).select do |child|
242
- valid_directory?(child)
243
- end
244
- else
245
- []
251
+ Puppet::FileSystem.children(@environment_dir).map do |child|
252
+ Puppet::FileSystem.basename_string(child).intern if validated_directory(child)
253
+ end.compact
246
254
  end
247
255
  end
248
256
  end
@@ -75,13 +75,16 @@ Puppet::Indirector::Face.define(:facts, '0.0.1') do
75
75
  facts.name = Puppet[:node_name_value]
76
76
  end
77
77
 
78
- Puppet::Node::Facts.indirection.terminus_class = :rest
79
- server = Puppet::Node::Facts::Rest.server
80
- Puppet.notice(_("Uploading facts for '%{node}' to: '%{server}'") % {
78
+ client = Puppet.runtime['http']
79
+ session = client.create_session
80
+ puppet = session.route_to(:puppet)
81
+
82
+ Puppet.notice(_("Uploading facts for '%{node}' to '%{server}'") % {
81
83
  node: Puppet[:node_name_value],
82
- server: server})
84
+ server: puppet.url.hostname})
83
85
 
84
- Puppet::Node::Facts.indirection.save(facts, nil, :environment => Puppet.lookup(:current_environment))
86
+ puppet.put_facts(Puppet[:node_name_value], facts: facts, environment: Puppet.lookup(:current_environment).name.to_s)
87
+ nil
85
88
  end
86
89
  end
87
90
  end
@@ -23,6 +23,10 @@ class Puppet::FileSystem::MemoryFile
23
23
  :children => children)
24
24
  end
25
25
 
26
+ def self.a_symlink(target_path, source_path)
27
+ new(target_path, :exist? => true, :symlink? => true, :source_path => source_path)
28
+ end
29
+
26
30
  def initialize(path, properties)
27
31
  @path = path
28
32
  @properties = properties
@@ -34,6 +38,8 @@ class Puppet::FileSystem::MemoryFile
34
38
  def directory?; @properties[:directory?]; end
35
39
  def exist?; @properties[:exist?]; end
36
40
  def executable?; @properties[:executable?]; end
41
+ def symlink?; @properties[:symlink?]; end
42
+ def source_path; @properties[:source_path]; end
37
43
 
38
44
  def each_line(&block)
39
45
  handle.each_line(&block)
@@ -23,6 +23,19 @@ class Puppet::FileSystem::MemoryImpl
23
23
  path.executable?
24
24
  end
25
25
 
26
+ def symlink?(path)
27
+ path.symlink?
28
+ end
29
+
30
+ def readlink(path)
31
+ path = path.path
32
+ link = find(path)
33
+ return Puppet::FileSystem::MemoryFile.a_missing_file(path) unless link
34
+ source = link.source_path
35
+ return Puppet::FileSystem::MemoryFile.a_missing_file(link) unless source
36
+ find(source) || Puppet::FileSystem::MemoryFile.a_missing_file(source)
37
+ end
38
+
26
39
  def children(path)
27
40
  path.children
28
41
  end
@@ -117,6 +117,7 @@ class Puppet::FileSystem::Windows < Puppet::FileSystem::Posix
117
117
  end
118
118
 
119
119
  # https://docs.microsoft.com/en-us/windows/desktop/debug/system-error-codes--0-499-
120
+ FILE_NOT_FOUND = 2
120
121
  ACCESS_DENIED = 5
121
122
  SHARING_VIOLATION = 32
122
123
  LOCK_VIOLATION = 33
@@ -132,12 +133,12 @@ class Puppet::FileSystem::Windows < Puppet::FileSystem::Posix
132
133
  dacl = secure_dacl(current_sid)
133
134
  dacl.allow(Puppet::Util::Windows::SID::BuiltinUsers, FILE_READ)
134
135
  dacl
135
- when 0640, 0600
136
+ when 0660, 0640, 0600, 0440
136
137
  secure_dacl(current_sid)
137
138
  when nil
138
139
  get_dacl_from_file(path) || secure_dacl(current_sid)
139
140
  else
140
- raise ArgumentError, "Only modes 0644, 0640 and 0600 are allowed"
141
+ raise ArgumentError, "#{mode} is invalid: Only modes 0644, 0640, 0660, and 0440 are allowed"
141
142
  end
142
143
 
143
144
 
@@ -180,9 +181,9 @@ class Puppet::FileSystem::Windows < Puppet::FileSystem::Posix
180
181
  def secure_dacl(current_sid)
181
182
  dacl = Puppet::Util::Windows::AccessControlList.new
182
183
  [
183
- Puppet::Util::Windows::SID::LocalSystem,
184
- Puppet::Util::Windows::SID::BuiltinAdministrators,
185
- current_sid
184
+ Puppet::Util::Windows::SID::LocalSystem,
185
+ Puppet::Util::Windows::SID::BuiltinAdministrators,
186
+ current_sid
186
187
  ].uniq.map do |sid|
187
188
  dacl.allow(sid, FULL_CONTROL)
188
189
  end
@@ -193,11 +194,7 @@ class Puppet::FileSystem::Windows < Puppet::FileSystem::Posix
193
194
  sd = Puppet::Util::Windows::Security.get_security_descriptor(Puppet::FileSystem.path_string(path))
194
195
  sd.dacl
195
196
  rescue Puppet::Util::Windows::Error => e
196
- if e.code == 2 # ERROR_FILE_NOT_FOUND
197
- nil
198
- else
199
- raise e
200
- end
197
+ raise e unless e.code == FILE_NOT_FOUND
201
198
  end
202
199
 
203
200
  def raise_if_symlinks_unsupported
data/lib/puppet/http.rb CHANGED
@@ -18,6 +18,8 @@ module Puppet
18
18
  require 'puppet/http/response'
19
19
  require 'puppet/http/service'
20
20
  require 'puppet/http/service/ca'
21
+ require 'puppet/http/service/compiler'
22
+ require 'puppet/http/service/file_server'
21
23
  require 'puppet/http/service/report'
22
24
  require 'puppet/http/session'
23
25
  require 'puppet/http/resolver'
@@ -171,7 +171,37 @@ class Puppet::HTTP::Client
171
171
  end
172
172
  end
173
173
 
174
+ def expand_into_parameters(data)
175
+ data.inject([]) do |params, key_value|
176
+ key, value = key_value
177
+
178
+ expanded_value = case value
179
+ when Array
180
+ value.collect { |val| [key, val] }
181
+ else
182
+ [key_value]
183
+ end
184
+
185
+ params.concat(expand_primitive_types_into_parameters(expanded_value))
186
+ end
187
+ end
188
+
189
+ def expand_primitive_types_into_parameters(data)
190
+ data.inject([]) do |params, key_value|
191
+ key, value = key_value
192
+ case value
193
+ when nil
194
+ params
195
+ when true, false, String, Symbol, Integer, Float
196
+ params << [key, value]
197
+ else
198
+ raise Puppet::HTTP::SerializationError, _("HTTP REST queries cannot handle values of type '%{klass}'") % { klass: value.class }
199
+ end
200
+ end
201
+ end
202
+
174
203
  def encode_params(params)
204
+ params = expand_into_parameters(params)
175
205
  params.map do |key, value|
176
206
  "#{key}=#{Puppet::Util.uri_query_encode(value.to_s)}"
177
207
  end.join('&')
@@ -7,6 +7,8 @@ module Puppet::HTTP
7
7
 
8
8
  class ProtocolError < HTTPError; end
9
9
 
10
+ class SerializationError < HTTPError; end
11
+
10
12
  class ResponseError < HTTPError
11
13
  attr_reader :response
12
14
 
@@ -1,12 +1,17 @@
1
1
  class Puppet::HTTP::Service
2
2
  attr_reader :url
3
3
 
4
- SERVICE_NAMES = [:ca, :report].freeze
4
+ SERVICE_NAMES = [:ca, :fileserver, :puppet, :report].freeze
5
+ EXCLUDED_FORMATS = [:yaml, :b64_zlib_yaml, :dot].freeze
5
6
 
6
7
  def self.create_service(client, name, server = nil, port = nil)
7
8
  case name
8
9
  when :ca
9
10
  Puppet::HTTP::Service::Ca.new(client, server, port)
11
+ when :fileserver
12
+ Puppet::HTTP::Service::FileServer.new(client, server, port)
13
+ when :puppet
14
+ ::Puppet::HTTP::Service::Compiler.new(client, server, port)
10
15
  when :report
11
16
  Puppet::HTTP::Service::Report.new(client, server, port)
12
17
  else
@@ -25,7 +30,7 @@ class Puppet::HTTP::Service
25
30
 
26
31
  def with_base_url(path)
27
32
  u = @url.dup
28
- u.path += path
33
+ u.path += Puppet::Util.uri_encode(path)
29
34
  u
30
35
  end
31
36
 
@@ -47,4 +52,58 @@ class Puppet::HTTP::Service
47
52
  path: api
48
53
  ).freeze
49
54
  end
55
+
56
+ def get_mime_types(model)
57
+ unless @mime_types
58
+ network_formats = model.supported_formats - EXCLUDED_FORMATS
59
+ @mime_types = network_formats.map { |f| model.get_format(f).mime }
60
+ end
61
+ @mime_types
62
+ end
63
+
64
+ def formatter_for_response(response)
65
+ header = response['Content-Type']
66
+ raise Puppet::HTTP::ProtocolError.new(_("No content type in http response; cannot parse")) unless header
67
+
68
+ header.gsub!(/\s*;.*$/,'') # strip any charset
69
+
70
+ formatter = Puppet::Network::FormatHandler.mime(header)
71
+ raise Puppet::HTTP::ProtocolError.new("Content-Type is unsupported") if EXCLUDED_FORMATS.include?(formatter.name)
72
+
73
+ formatter
74
+ end
75
+
76
+ def serialize(formatter, object)
77
+ begin
78
+ formatter.render(object)
79
+ rescue => err
80
+ raise Puppet::HTTP::SerializationError.new("Failed to serialize #{object.class} to #{formatter.name}: #{err.message}", err)
81
+ end
82
+ end
83
+
84
+ def serialize_multiple(formatter, object)
85
+ begin
86
+ formatter.render_multiple(object)
87
+ rescue => err
88
+ raise Puppet::HTTP::SerializationError.new("Failed to serialize multiple #{object.class} to #{formatter.name}: #{err.message}", err)
89
+ end
90
+ end
91
+
92
+ def deserialize(response, model)
93
+ formatter = formatter_for_response(response)
94
+ begin
95
+ formatter.intern(model, response.body.to_s)
96
+ rescue => err
97
+ raise Puppet::HTTP::SerializationError.new("Failed to deserialize #{model} from #{formatter.name}: #{err.message}", err)
98
+ end
99
+ end
100
+
101
+ def deserialize_multiple(response, model)
102
+ formatter = formatter_for_response(response)
103
+ begin
104
+ formatter.intern_multiple(model, response.body.to_s)
105
+ rescue => err
106
+ raise Puppet::HTTP::SerializationError.new("Failed to deserialize multiple #{model} from #{formatter.name}: #{err.message}", err)
107
+ end
108
+ end
50
109
  end
@@ -0,0 +1,86 @@
1
+ class Puppet::HTTP::Service::Compiler < Puppet::HTTP::Service
2
+ API = '/puppet/v3'.freeze
3
+
4
+ def initialize(client, server, port)
5
+ url = build_url(API, server || Puppet[:server], port || Puppet[:masterport])
6
+ super(client, url)
7
+ end
8
+
9
+ def get_node(name, environment:, configured_environment: nil, transaction_uuid: nil)
10
+ headers = add_puppet_headers('Accept' => get_mime_types(Puppet::Node).join(', '))
11
+
12
+ response = @client.get(
13
+ with_base_url("/node/#{name}"),
14
+ headers: headers,
15
+ params: {
16
+ environment: environment,
17
+ configured_environment: configured_environment || environment,
18
+ transaction_uuid: transaction_uuid,
19
+ },
20
+ )
21
+
22
+ return deserialize(response, Puppet::Node) if response.success?
23
+
24
+ raise Puppet::HTTP::ResponseError.new(response)
25
+ end
26
+
27
+ def get_catalog(name, facts:, environment:, configured_environment: nil, transaction_uuid: nil, job_uuid: nil, static_catalog: true, checksum_type: Puppet[:supported_checksum_types])
28
+ if Puppet[:preferred_serialization_format] == "pson"
29
+ formatter = Puppet::Network::FormatHandler.format_for(:pson)
30
+ # must use 'pson' instead of 'text/pson'
31
+ facts_format = 'pson'
32
+ else
33
+ formatter = Puppet::Network::FormatHandler.format_for(:json)
34
+ facts_format = formatter.mime
35
+ end
36
+
37
+ facts_as_string = serialize(formatter, facts)
38
+
39
+ # query parameters are sent in the POST request body
40
+ body = {
41
+ facts_format: facts_format,
42
+ facts: Puppet::Util.uri_query_encode(facts_as_string),
43
+ environment: environment,
44
+ configured_environment: configured_environment || environment,
45
+ transaction_uuid: transaction_uuid,
46
+ job_uuid: job_uuid,
47
+ static_catalog: static_catalog,
48
+ checksum_type: checksum_type.join('.')
49
+ }.map do |key, value|
50
+ "#{key}=#{Puppet::Util.uri_query_encode(value.to_s)}"
51
+ end.join("&")
52
+
53
+ headers = add_puppet_headers('Accept' => get_mime_types(Puppet::Resource::Catalog).join(', '))
54
+
55
+ response = @client.post(
56
+ with_base_url("/catalog/#{name}"),
57
+ headers: headers,
58
+ # for legacy reasons we always send environment as a query parameter too
59
+ params: { environment: environment },
60
+ content_type: 'application/x-www-form-urlencoded',
61
+ body: body,
62
+ )
63
+
64
+ return deserialize(response, Puppet::Resource::Catalog) if response.success?
65
+
66
+ raise Puppet::HTTP::ResponseError.new(response)
67
+ end
68
+
69
+ def put_facts(name, environment:, facts:)
70
+ formatter = Puppet::Network::FormatHandler.format_for(Puppet[:preferred_serialization_format])
71
+
72
+ headers = add_puppet_headers('Accept' => get_mime_types(Puppet::Node::Facts).join(', '))
73
+
74
+ response = @client.put(
75
+ with_base_url("/facts/#{name}"),
76
+ headers: headers,
77
+ params: { environment: environment },
78
+ content_type: formatter.mime,
79
+ body: serialize(formatter, facts),
80
+ )
81
+
82
+ return true if response.success?
83
+
84
+ raise Puppet::HTTP::ResponseError.new(response)
85
+ end
86
+ end
@@ -0,0 +1,85 @@
1
+ require 'puppet/file_serving/metadata'
2
+
3
+ class Puppet::HTTP::Service::FileServer < Puppet::HTTP::Service
4
+ API = '/puppet/v3'.freeze
5
+ PATH_REGEX = /^\//
6
+
7
+ def initialize(client, server, port)
8
+ url = build_url(API, server || Puppet[:server], port || Puppet[:masterport])
9
+ super(client, url)
10
+ end
11
+
12
+ def get_file_metadata(path:, environment:, links: :manage, checksum_type: Puppet[:digest_algorithm], source_permissions: :ignore, ssl_context: nil)
13
+ validate_path(path)
14
+
15
+ headers = add_puppet_headers({ 'Accept' => get_mime_types(Puppet::FileServing::Metadata).join(', ') })
16
+
17
+ response = @client.get(
18
+ with_base_url("/file_metadata#{path}"),
19
+ headers: headers,
20
+ params: {
21
+ links: links,
22
+ checksum_type: checksum_type,
23
+ source_permissions: source_permissions,
24
+ environment: environment
25
+ },
26
+ ssl_context: ssl_context
27
+ )
28
+
29
+ return deserialize(response, Puppet::FileServing::Metadata) if response.success?
30
+
31
+ raise Puppet::HTTP::ResponseError.new(response)
32
+ end
33
+
34
+ def get_file_metadatas(path: nil, environment:, recurse: :false, recurselimit: nil, ignore: nil, links: :manage, checksum_type: Puppet[:digest_algorithm], source_permissions: :ignore, ssl_context: nil)
35
+ validate_path(path)
36
+
37
+ headers = add_puppet_headers({ 'Accept' => get_mime_types(Puppet::FileServing::Metadata).join(', ') })
38
+
39
+ response = @client.get(
40
+ with_base_url("/file_metadatas#{path}"),
41
+ headers: headers,
42
+ params: {
43
+ recurse: recurse,
44
+ recurselimit: recurselimit,
45
+ ignore: ignore,
46
+ links: links,
47
+ checksum_type: checksum_type,
48
+ source_permissions: source_permissions,
49
+ environment: environment,
50
+ },
51
+ ssl_context: ssl_context
52
+ )
53
+
54
+ return deserialize_multiple(response, Puppet::FileServing::Metadata) if response.success?
55
+
56
+ raise Puppet::HTTP::ResponseError.new(response)
57
+ end
58
+
59
+ def get_file_content(path:, environment:, ssl_context: nil, &block)
60
+ validate_path(path)
61
+
62
+ headers = add_puppet_headers({'Accept' => 'application/octet-stream' })
63
+ response = @client.get(
64
+ with_base_url("/file_content#{path}"),
65
+ headers: headers,
66
+ params: {
67
+ environment: environment
68
+ },
69
+ ssl_context: ssl_context
70
+ ) do |res|
71
+ if res.success?
72
+ res.read_body(&block)
73
+ end
74
+ end
75
+
76
+ return nil if response.success?
77
+
78
+ raise Puppet::HTTP::ResponseError.new(response)
79
+ end
80
+ private
81
+
82
+ def validate_path(path)
83
+ raise ArgumentError, "Path must start with a slash" unless path =~ PATH_REGEX
84
+ end
85
+ end