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.
- checksums.yaml +4 -4
- data/Gemfile.lock +12 -12
- data/README.md +1 -1
- data/ext/project_data.yaml +1 -1
- data/lib/puppet.rb +22 -7
- data/lib/puppet/application/resource.rb +1 -1
- data/lib/puppet/configurer.rb +8 -13
- data/lib/puppet/defaults.rb +83 -49
- data/lib/puppet/environments.rb +26 -18
- data/lib/puppet/face/facts.rb +8 -5
- data/lib/puppet/file_system/memory_file.rb +6 -0
- data/lib/puppet/file_system/memory_impl.rb +13 -0
- data/lib/puppet/file_system/windows.rb +7 -10
- data/lib/puppet/http.rb +2 -0
- data/lib/puppet/http/client.rb +30 -0
- data/lib/puppet/http/errors.rb +2 -0
- data/lib/puppet/http/service.rb +61 -2
- data/lib/puppet/http/service/compiler.rb +86 -0
- data/lib/puppet/http/service/file_server.rb +85 -0
- data/lib/puppet/http/service/report.rb +4 -8
- data/lib/puppet/http/session.rb +8 -1
- data/lib/puppet/indirector/catalog/compiler.rb +10 -0
- data/lib/puppet/indirector/file_bucket_file/file.rb +1 -1
- data/lib/puppet/indirector/json.rb +1 -1
- data/lib/puppet/indirector/msgpack.rb +1 -1
- data/lib/puppet/network/http/connection.rb +4 -0
- data/lib/puppet/network/http/nocache_pool.rb +1 -0
- data/lib/puppet/network/http/pool.rb +5 -1
- data/lib/puppet/parser/ast/pops_bridge.rb +6 -11
- data/lib/puppet/pops/evaluator/access_operator.rb +2 -2
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +1 -1
- data/lib/puppet/pops/loader/puppet_plan_instantiator.rb +12 -3
- data/lib/puppet/pops/parser/evaluating_parser.rb +5 -7
- data/lib/puppet/pops/types/p_object_type_extension.rb +10 -0
- data/lib/puppet/pops/types/type_calculator.rb +24 -0
- data/lib/puppet/pops/validation/checker4_0.rb +1 -1
- data/lib/puppet/pops/validation/tasks_checker.rb +5 -1
- data/lib/puppet/provider/aix_object.rb +4 -2
- data/lib/puppet/provider/group/aix.rb +1 -0
- data/lib/puppet/provider/group/groupadd.rb +52 -24
- data/lib/puppet/provider/package/apt.rb +14 -3
- data/lib/puppet/provider/package/dnfmodule.rb +9 -2
- data/lib/puppet/provider/package/dpkg.rb +14 -7
- data/lib/puppet/provider/package/fink.rb +20 -3
- data/lib/puppet/provider/package/openbsd.rb +13 -1
- data/lib/puppet/provider/package/pkg.rb +18 -5
- data/lib/puppet/provider/package/yum.rb +9 -5
- data/lib/puppet/provider/user/aix.rb +1 -0
- data/lib/puppet/provider/user/directoryservice.rb +30 -5
- data/lib/puppet/provider/user/useradd.rb +6 -7
- data/lib/puppet/reports/store.rb +1 -1
- data/lib/puppet/settings.rb +2 -0
- data/lib/puppet/ssl/certificate.rb +2 -1
- data/lib/puppet/test/test_helper.rb +4 -0
- data/lib/puppet/transaction/resource_harness.rb +1 -1
- data/lib/puppet/type/group.rb +2 -2
- data/lib/puppet/type/package.rb +63 -9
- data/lib/puppet/type/user.rb +2 -2
- data/lib/puppet/util/log/destinations.rb +1 -1
- data/lib/puppet/util/pidlock.rb +26 -6
- data/lib/puppet/util/plist.rb +6 -0
- data/lib/puppet/util/storage.rb +0 -1
- data/lib/puppet/util/yaml.rb +1 -1
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +127 -115
- data/man/man5/puppet.conf.5 +21 -7
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- 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
- 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
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_update_if_content_differs_on_disk.yml +0 -37
- 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
- data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_no_header_specified.yml +0 -33
- 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
- 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
- data/spec/integration/configurer_spec.rb +26 -7
- data/spec/integration/indirector/facts/facter_spec.rb +4 -0
- data/spec/unit/application/apply_spec.rb +2 -12
- data/spec/unit/application/resource_spec.rb +2 -2
- data/spec/unit/configurer/fact_handler_spec.rb +0 -4
- data/spec/unit/configurer_spec.rb +0 -3
- data/spec/unit/defaults_spec.rb +1 -1
- data/spec/unit/environments_spec.rb +57 -28
- data/spec/unit/face/facts_spec.rb +24 -20
- data/spec/unit/file_system_spec.rb +16 -2
- data/spec/unit/http/client_spec.rb +6 -0
- data/spec/unit/http/service/compiler_spec.rb +322 -0
- data/spec/unit/http/service/file_server_spec.rb +219 -0
- data/spec/unit/http/service/report_spec.rb +8 -1
- data/spec/unit/http/service_spec.rb +4 -0
- data/spec/unit/http/session_spec.rb +31 -0
- data/spec/unit/indirector/catalog/compiler_spec.rb +46 -29
- data/spec/unit/network/http/connection_spec.rb +23 -1
- data/spec/unit/network/http/nocache_pool_spec.rb +3 -3
- data/spec/unit/network/http/pool_spec.rb +32 -0
- data/spec/unit/node/facts_spec.rb +2 -1
- data/spec/unit/node_spec.rb +7 -4
- data/spec/unit/pops/serialization/to_from_hr_spec.rb +6 -1
- data/spec/unit/pops/validator/validator_spec.rb +7 -2
- data/spec/unit/provider/aix_object_spec.rb +16 -2
- data/spec/unit/provider/group/groupadd_spec.rb +167 -56
- data/spec/unit/provider/package/apt_spec.rb +13 -2
- data/spec/unit/provider/package/aptitude_spec.rb +1 -0
- data/spec/unit/provider/package/dnfmodule_spec.rb +22 -0
- data/spec/unit/provider/package/dpkg_spec.rb +28 -6
- data/spec/unit/provider/package/openbsd_spec.rb +17 -0
- data/spec/unit/provider/package/pkg_spec.rb +15 -1
- data/spec/unit/provider/package/yum_spec.rb +50 -0
- data/spec/unit/provider/user/directoryservice_spec.rb +41 -0
- data/spec/unit/provider/user/useradd_spec.rb +13 -8
- data/spec/unit/puppet_pal_2pec.rb +3 -0
- data/spec/unit/puppet_pal_catalog_spec.rb +3 -0
- data/spec/unit/puppet_spec.rb +14 -0
- data/spec/unit/ssl/certificate_spec.rb +7 -0
- data/spec/unit/transaction/persistence_spec.rb +1 -10
- data/spec/unit/type/package_spec.rb +8 -0
- data/spec/unit/type/user_spec.rb +0 -1
- data/spec/unit/util/pidlock_spec.rb +38 -16
- data/spec/unit/util/plist_spec.rb +20 -0
- data/spec/unit/util/storage_spec.rb +1 -8
- metadata +10 -4
@@ -1,6 +1,5 @@
|
|
1
1
|
class Puppet::HTTP::Service::Report < Puppet::HTTP::Service
|
2
2
|
API = '/puppet/v3'.freeze
|
3
|
-
EXCLUDED_FORMATS = [:yaml, :b64_zlib_yaml, :dot]
|
4
3
|
|
5
4
|
# puppet major version where JSON is enabled by default
|
6
5
|
MAJOR_VERSION_JSON_DEFAULT = 5
|
@@ -12,17 +11,14 @@ class Puppet::HTTP::Service::Report < Puppet::HTTP::Service
|
|
12
11
|
|
13
12
|
def put_report(name, report, environment:, ssl_context: nil)
|
14
13
|
formatter = Puppet::Network::FormatHandler.format_for(Puppet[:preferred_serialization_format])
|
15
|
-
|
16
|
-
model = Puppet::Transaction::Report
|
17
|
-
network_formats = model.supported_formats - EXCLUDED_FORMATS
|
18
|
-
mime_types = network_formats.map { |f| model.get_format(f).mime }
|
14
|
+
headers = add_puppet_headers('Accept' => get_mime_types(Puppet::Transaction::Report).join(', '))
|
19
15
|
|
20
16
|
response = @client.put(
|
21
17
|
with_base_url("/report/#{name}"),
|
22
|
-
headers:
|
23
|
-
params: { :
|
18
|
+
headers: headers,
|
19
|
+
params: { environment: environment },
|
24
20
|
content_type: formatter.mime,
|
25
|
-
body: formatter
|
21
|
+
body: serialize(formatter, report),
|
26
22
|
ssl_context: ssl_context
|
27
23
|
)
|
28
24
|
|
data/lib/puppet/http/session.rb
CHANGED
@@ -6,9 +6,16 @@ class Puppet::HTTP::Session
|
|
6
6
|
@resolution_exceptions = []
|
7
7
|
end
|
8
8
|
|
9
|
-
def route_to(name, ssl_context: nil)
|
9
|
+
def route_to(name, url: nil, ssl_context: nil)
|
10
10
|
raise ArgumentError, "Unknown service #{name}" unless Puppet::HTTP::Service.valid_name?(name)
|
11
11
|
|
12
|
+
# short circuit if explicit URL host & port given
|
13
|
+
if url && url.host != nil && !url.host.empty?
|
14
|
+
service = Puppet::HTTP::Service.create_service(@client, name, url.host, url.port)
|
15
|
+
service.connect(ssl_context: ssl_context)
|
16
|
+
return service
|
17
|
+
end
|
18
|
+
|
12
19
|
cached = @resolved_services[name]
|
13
20
|
return cached if cached
|
14
21
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'puppet/environments'
|
1
2
|
require 'puppet/node'
|
2
3
|
require 'puppet/resource/catalog'
|
3
4
|
require 'puppet/indirector/code'
|
@@ -173,6 +174,7 @@ class Puppet::Resource::Catalog::Compiler < Puppet::Indirector::Code
|
|
173
174
|
# Initially restricted to files sourced from codedir via puppet:/// uri.
|
174
175
|
def inline_metadata(catalog, checksum_type)
|
175
176
|
environment_path = Pathname.new File.join(Puppet[:environmentpath], catalog.environment, "")
|
177
|
+
environment_path = Puppet::Environments::Directories.real_path(environment_path)
|
176
178
|
list_of_resources = catalog.resources.find_all { |res| res.type == "File" }
|
177
179
|
|
178
180
|
# TODO: get property/parameter defaults if entries are nil in the resource
|
@@ -393,9 +395,17 @@ class Puppet::Resource::Catalog::Compiler < Puppet::Indirector::Code
|
|
393
395
|
|
394
396
|
# Initialize our server fact hash; we add these to each client, and they
|
395
397
|
# won't change while we're running, so it's safe to cache the values.
|
398
|
+
#
|
399
|
+
# See also set_server_facts in Puppet::Server::Compiler in puppetserver.
|
396
400
|
def set_server_facts
|
397
401
|
@server_facts = {}
|
398
402
|
|
403
|
+
# Add our server Puppet Enterprise version, if available.
|
404
|
+
pe_version_file = '/opt/puppetlabs/server/pe_version'
|
405
|
+
if File.readable?(pe_version_file) and !File.zero?(pe_version_file)
|
406
|
+
@server_facts['pe_serverversion'] = File.read(pe_version_file).chomp
|
407
|
+
end
|
408
|
+
|
399
409
|
# Add our server version to the fact list
|
400
410
|
@server_facts["serverversion"] = Puppet.version.to_s
|
401
411
|
|
@@ -250,7 +250,7 @@ module Puppet::FileBucketFile
|
|
250
250
|
# @return [void]
|
251
251
|
# @api private
|
252
252
|
def copy_bucket_file_to_contents_file(contents_file, bucket_file)
|
253
|
-
Puppet::
|
253
|
+
Puppet::FileSystem.replace_file(contents_file, 0440) do |of|
|
254
254
|
# PUP-1044 writes all of the contents
|
255
255
|
bucket_file.stream() do |src|
|
256
256
|
FileUtils.copy_stream(src, of)
|
@@ -14,7 +14,7 @@ class Puppet::Indirector::JSON < Puppet::Indirector::Terminus
|
|
14
14
|
filename = path(request.key)
|
15
15
|
FileUtils.mkdir_p(File.dirname(filename))
|
16
16
|
|
17
|
-
Puppet::
|
17
|
+
Puppet::FileSystem.replace_file(filename, 0660) {|f| f.print to_json(request.instance).force_encoding(Encoding::BINARY) }
|
18
18
|
rescue TypeError => detail
|
19
19
|
Puppet.log_exception(detail, _("Could not save %{json} %{request}: %{detail}") % { json: self.name, request: request.key, detail: detail })
|
20
20
|
end
|
@@ -21,7 +21,7 @@ class Puppet::Indirector::Msgpack < Puppet::Indirector::Terminus
|
|
21
21
|
filename = path(request.key)
|
22
22
|
FileUtils.mkdir_p(File.dirname(filename))
|
23
23
|
|
24
|
-
Puppet::
|
24
|
+
Puppet::FileSystem.replace_file(filename, 0660) {|f| f.print to_msgpack(request.instance) }
|
25
25
|
rescue TypeError => detail
|
26
26
|
Puppet.log_exception(detail, _("Could not save %{name} %{request}: %{detail}") % { name: self.name, request: request.key, detail: detail })
|
27
27
|
end
|
@@ -213,6 +213,10 @@ module Puppet::Network::HTTP
|
|
213
213
|
current_request[header] = value
|
214
214
|
end
|
215
215
|
when 429, 503
|
216
|
+
if connection.started?
|
217
|
+
Puppet.debug("Closing connection for #{current_site}")
|
218
|
+
connection.finish
|
219
|
+
end
|
216
220
|
response = handle_retry_after(current_response)
|
217
221
|
else
|
218
222
|
response = current_response
|
@@ -33,7 +33,7 @@ class Puppet::Network::HTTP::Pool < Puppet::Network::HTTP::BasePool
|
|
33
33
|
reuse = false
|
34
34
|
raise detail
|
35
35
|
ensure
|
36
|
-
if reuse
|
36
|
+
if reuse && http.started?
|
37
37
|
release(site, verifier, http)
|
38
38
|
else
|
39
39
|
close_connection(site, http)
|
@@ -56,13 +56,17 @@ class Puppet::Network::HTTP::Pool < Puppet::Network::HTTP::BasePool
|
|
56
56
|
end
|
57
57
|
|
58
58
|
# Safely close a persistent connection.
|
59
|
+
# Don't try to close a connection that's already closed.
|
59
60
|
#
|
60
61
|
# @api private
|
61
62
|
def close_connection(site, http)
|
63
|
+
return false unless http.started?
|
62
64
|
Puppet.debug("Closing connection for #{site}")
|
63
65
|
http.finish
|
66
|
+
true
|
64
67
|
rescue => detail
|
65
68
|
Puppet.log_exception(detail, _("Failed to close connection for %{site}: %{detail}") % { site: site, detail: detail })
|
69
|
+
nil
|
66
70
|
end
|
67
71
|
|
68
72
|
# Borrow and take ownership of a persistent connection. If a new
|
@@ -13,12 +13,6 @@ class Puppet::Parser::AST::PopsBridge
|
|
13
13
|
# expression.
|
14
14
|
#
|
15
15
|
class Expression < Puppet::Parser::AST::Leaf
|
16
|
-
|
17
|
-
def initialize args
|
18
|
-
super
|
19
|
-
@@evaluator ||= Puppet::Pops::Parser::EvaluatingParser.new()
|
20
|
-
end
|
21
|
-
|
22
16
|
def to_s
|
23
17
|
Puppet::Pops::Model::ModelTreeDumper.new.dump(@value)
|
24
18
|
end
|
@@ -29,8 +23,9 @@ class Puppet::Parser::AST::PopsBridge
|
|
29
23
|
end
|
30
24
|
|
31
25
|
def evaluate(scope)
|
32
|
-
|
33
|
-
|
26
|
+
evaluator = Puppet::Pops::Parser::EvaluatingParser.singleton
|
27
|
+
object = evaluator.evaluate(scope, @value)
|
28
|
+
evaluator.convert_to_3x(object, scope)
|
34
29
|
end
|
35
30
|
|
36
31
|
# Adapts to 3x where top level constructs needs to have each to iterate over children. Short circuit this
|
@@ -87,7 +82,6 @@ class Puppet::Parser::AST::PopsBridge
|
|
87
82
|
@program_model = program_model
|
88
83
|
@context = context
|
89
84
|
@ast_transformer ||= Puppet::Pops::Model::AstTransformer.new(@context[:file])
|
90
|
-
@@evaluator ||= Puppet::Pops::Parser::EvaluatingParser.new()
|
91
85
|
end
|
92
86
|
|
93
87
|
# This is the 3x API, the 3x AST searches through all code to find the instructions that can be instantiated.
|
@@ -122,7 +116,7 @@ class Puppet::Parser::AST::PopsBridge
|
|
122
116
|
end
|
123
117
|
|
124
118
|
def evaluate(scope)
|
125
|
-
|
119
|
+
Puppet::Pops::Parser::EvaluatingParser.singleton.evaluate(scope, program_model)
|
126
120
|
end
|
127
121
|
|
128
122
|
# Adapts to 3x where top level constructs needs to have each to iterate over children. Short circuit this
|
@@ -178,8 +172,9 @@ class Puppet::Parser::AST::PopsBridge
|
|
178
172
|
#
|
179
173
|
scope = obtain_scope
|
180
174
|
if scope
|
175
|
+
evaluator = Puppet::Pops::Parser::EvaluatingParser.singleton
|
181
176
|
typed_parameters.each do |p|
|
182
|
-
result[p.name] =
|
177
|
+
result[p.name] = evaluator.evaluate(scope, p.type_expr)
|
183
178
|
end
|
184
179
|
end
|
185
180
|
result
|
@@ -20,14 +20,14 @@ class AccessOperator
|
|
20
20
|
@semantic = access_expression
|
21
21
|
end
|
22
22
|
|
23
|
-
def access
|
23
|
+
def access(o, scope, *keys)
|
24
24
|
@@access_visitor.visit_this_2(self, o, scope, keys)
|
25
25
|
end
|
26
26
|
|
27
27
|
protected
|
28
28
|
|
29
29
|
def access_Object(o, scope, keys)
|
30
|
-
type = Puppet::Pops::Types::TypeCalculator.
|
30
|
+
type = Puppet::Pops::Types::TypeCalculator.infer_callable_methods_t(o)
|
31
31
|
if type.is_a?(Puppet::Pops::Types::TypeWithMembers)
|
32
32
|
access_func = type['[]']
|
33
33
|
return access_func.invoke(o, scope, keys) unless access_func.nil?
|
@@ -959,7 +959,7 @@ class EvaluatorImpl
|
|
959
959
|
name = name.value # the string function name
|
960
960
|
|
961
961
|
obj = receiver[0]
|
962
|
-
receiver_type = Types::TypeCalculator.
|
962
|
+
receiver_type = Types::TypeCalculator.infer_callable_methods_t(obj)
|
963
963
|
if receiver_type.is_a?(Types::TypeWithMembers)
|
964
964
|
member = receiver_type[name]
|
965
965
|
unless member.nil?
|
@@ -19,8 +19,17 @@ class PuppetPlanInstantiator
|
|
19
19
|
|
20
20
|
# parse and validate
|
21
21
|
result = parser.parse_string(pp_code_string, source_ref)
|
22
|
-
|
23
|
-
|
22
|
+
|
23
|
+
# The parser attaches all definitions, including those nested in apply
|
24
|
+
# blocks, to the Program object. Node definitions in apply blocks are
|
25
|
+
# perfectly legal and don't count as the file containing multiple
|
26
|
+
# definitions for this purpose. By this point, we've already validated that
|
27
|
+
# there are no node definitions *outside* apply blocks, so we simply ignore
|
28
|
+
# them here.
|
29
|
+
definitions = result.definitions.reject { |definition| definition.is_a?(Puppet::Pops::Model::NodeDefinition) }
|
30
|
+
|
31
|
+
# Only one plan is allowed (and no other definitions)
|
32
|
+
case definitions.size
|
24
33
|
when 0
|
25
34
|
raise ArgumentError, _("The code loaded from %{source_ref} does not define the plan '%{plan_name}' - it is empty.") % { source_ref: source_ref, plan_name: typed_name.name }
|
26
35
|
when 1
|
@@ -28,7 +37,7 @@ class PuppetPlanInstantiator
|
|
28
37
|
else
|
29
38
|
raise ArgumentError, _("The code loaded from %{source_ref} must contain only the plan '%{plan_name}' - it has additional definitions.") % { source_ref: source_ref, plan_name: typed_name.name }
|
30
39
|
end
|
31
|
-
the_plan_definition =
|
40
|
+
the_plan_definition = definitions[0]
|
32
41
|
|
33
42
|
unless the_plan_definition.is_a?(Model::PlanDefinition)
|
34
43
|
raise ArgumentError, _("The code loaded from %{source_ref} does not define the plan '%{plan_name}' - no plan found.") % { source_ref: source_ref, plan_name: typed_name.name }
|
@@ -15,7 +15,6 @@ class EvaluatingParser
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def parse_string(s, file_source = nil)
|
18
|
-
@file_source = file_source
|
19
18
|
clear()
|
20
19
|
# Handling of syntax error can be much improved (in general), now it bails out of the parser
|
21
20
|
# and does not have as rich information (when parsing a string), need to update it with the file source
|
@@ -24,20 +23,19 @@ class EvaluatingParser
|
|
24
23
|
# Also a possible improvement (if the YAML parser returns positions) is to provide correct output of position.
|
25
24
|
#
|
26
25
|
begin
|
27
|
-
assert_and_report(parser.parse_string(s, file_source)).model
|
26
|
+
assert_and_report(parser.parse_string(s, file_source), file_source).model
|
28
27
|
rescue Puppet::ParseErrorWithIssue => e
|
29
28
|
raise e
|
30
29
|
rescue Puppet::ParseError => e
|
31
30
|
# TODO: This is not quite right, why does not the exception have the correct file?
|
32
|
-
e.file =
|
31
|
+
e.file = file_source unless e.file.is_a?(String) && !e.file.empty?
|
33
32
|
raise e
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
37
36
|
def parse_file(file)
|
38
|
-
@file_source = file
|
39
37
|
clear()
|
40
|
-
assert_and_report(parser.parse_file(file)).model
|
38
|
+
assert_and_report(parser.parse_file(file), file).model
|
41
39
|
end
|
42
40
|
|
43
41
|
def evaluate_string(scope, s, file_source = nil)
|
@@ -96,10 +94,10 @@ class EvaluatingParser
|
|
96
94
|
Validation::ValidatorFactory_4_0.new().validator(acceptor)
|
97
95
|
end
|
98
96
|
|
99
|
-
def assert_and_report(parse_result)
|
97
|
+
def assert_and_report(parse_result, file_source)
|
100
98
|
return nil unless parse_result
|
101
99
|
if parse_result['source_ref'].nil? || parse_result['source_ref'] == ''
|
102
|
-
parse_result['source_ref'] =
|
100
|
+
parse_result['source_ref'] = file_source
|
103
101
|
end
|
104
102
|
validation_result = validate(parse_result.model)
|
105
103
|
|
@@ -153,6 +153,16 @@ class PObjectTypeExtension < PAnyType
|
|
153
153
|
@base_type.simple_name
|
154
154
|
end
|
155
155
|
|
156
|
+
# @api private
|
157
|
+
def implementation_class(create = true)
|
158
|
+
@base_type.implementation_class(create)
|
159
|
+
end
|
160
|
+
|
161
|
+
# @api private
|
162
|
+
def parameter_info(impl_class)
|
163
|
+
@base_type.parameter_info(impl_class)
|
164
|
+
end
|
165
|
+
|
156
166
|
protected
|
157
167
|
|
158
168
|
# Checks that the given `param_values` hash contains all keys present in the `parameters` of
|
@@ -123,6 +123,30 @@ class TypeCalculator
|
|
123
123
|
singleton.infer(o)
|
124
124
|
end
|
125
125
|
|
126
|
+
# Infers a type if given object may have callable members, else returns nil.
|
127
|
+
# Caller must check for nil or if returned type supports members.
|
128
|
+
# This is a much cheaper call than doing a call to the general infer(o) method.
|
129
|
+
#
|
130
|
+
# @api private
|
131
|
+
def self.infer_callable_methods_t(o)
|
132
|
+
# If being a value that cannot have Pcore based methods callable from Puppet Language
|
133
|
+
if (o.is_a?(String) ||
|
134
|
+
o.is_a?(Numeric) ||
|
135
|
+
o.is_a?(TrueClass) ||
|
136
|
+
o.is_a?(FalseClass) ||
|
137
|
+
o.is_a?(Regexp) ||
|
138
|
+
o.instance_of?(Array) ||
|
139
|
+
o.instance_of?(Hash) ||
|
140
|
+
Types::PUndefType::DEFAULT.instance?(o)
|
141
|
+
)
|
142
|
+
return nil
|
143
|
+
end
|
144
|
+
# For other objects (e.g. PObjectType instances, and runtime types) full inference needed, since that will
|
145
|
+
# cover looking into the runtime type registry.
|
146
|
+
#
|
147
|
+
infer(o)
|
148
|
+
end
|
149
|
+
|
126
150
|
# @api public
|
127
151
|
def self.generalize(o)
|
128
152
|
singleton.generalize(o)
|
@@ -93,7 +93,7 @@ class Checker4_0 < Evaluator::LiteralEvaluator
|
|
93
93
|
o = container(idx)
|
94
94
|
idx -= 1
|
95
95
|
case o
|
96
|
-
when NilClass, Model::HostClassDefinition, Model::Program
|
96
|
+
when NilClass, Model::ApplyExpression, Model::HostClassDefinition, Model::Program
|
97
97
|
# ok, stop scanning parents
|
98
98
|
when Model::BlockExpression
|
99
99
|
c = container(idx)
|
@@ -330,8 +330,10 @@ class Puppet::Provider::AixObject < Puppet::Provider
|
|
330
330
|
end
|
331
331
|
|
332
332
|
def ia_module_args
|
333
|
-
|
334
|
-
["-R", @resource[:ia_load_module].to_s]
|
333
|
+
raise ArgumentError, _("Cannot have both 'forcelocal' and 'ia_load_module' at the same time!") if @resource[:ia_load_module] && @resource[:forcelocal]
|
334
|
+
return ["-R", @resource[:ia_load_module].to_s] if @resource[:ia_load_module]
|
335
|
+
return ["-R", "files"] if @resource[:forcelocal]
|
336
|
+
[]
|
335
337
|
end
|
336
338
|
|
337
339
|
def lscmd
|
@@ -18,6 +18,7 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
|
|
18
18
|
# Provider features
|
19
19
|
has_features :manages_aix_lam
|
20
20
|
has_features :manages_members
|
21
|
+
has_features :manages_local_users_and_groups
|
21
22
|
|
22
23
|
class << self
|
23
24
|
# Used by the AIX user provider. Returns a hash of:
|
@@ -2,9 +2,7 @@ require 'puppet/provider/nameservice/objectadd'
|
|
2
2
|
require 'puppet/util/libuser'
|
3
3
|
|
4
4
|
Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameService::ObjectAdd do
|
5
|
-
desc "Group management via `groupadd` and its ilk. The default for most platforms.
|
6
|
-
|
7
|
-
"
|
5
|
+
desc "Group management via `groupadd` and its ilk. The default for most platforms."
|
8
6
|
|
9
7
|
commands :add => "groupadd", :delete => "groupdel", :modify => "groupmod"
|
10
8
|
|
@@ -16,7 +14,9 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
|
|
16
14
|
|
17
15
|
optional_commands :localadd => "lgroupadd", :localdelete => "lgroupdel", :localmodify => "lgroupmod"
|
18
16
|
|
19
|
-
has_feature :
|
17
|
+
has_feature :manages_local_users_and_groups, :manages_members if Puppet.features.libuser?
|
18
|
+
|
19
|
+
options :members, :flag => '-M', :method => :mem
|
20
20
|
|
21
21
|
def exists?
|
22
22
|
return !!localgid if @resource.forcelocal?
|
@@ -28,25 +28,9 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
|
|
28
28
|
get(:gid)
|
29
29
|
end
|
30
30
|
|
31
|
-
def findgroup(key, value)
|
32
|
-
group_file = "/etc/group"
|
33
|
-
group_keys = ['group_name', 'password', 'gid', 'user_list']
|
34
|
-
index = group_keys.index(key)
|
35
|
-
File.open(group_file) do |f|
|
36
|
-
f.each_line do |line|
|
37
|
-
group = line.split(":")
|
38
|
-
if group[index] == value
|
39
|
-
f.close
|
40
|
-
return group
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
false
|
45
|
-
end
|
46
|
-
|
47
31
|
def localgid
|
48
|
-
group = findgroup(
|
49
|
-
return group[
|
32
|
+
group = findgroup(:group_name, resource[:name])
|
33
|
+
return group[:gid] if group
|
50
34
|
false
|
51
35
|
end
|
52
36
|
|
@@ -56,7 +40,7 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
|
|
56
40
|
# to ensure consistent behaviour of the useradd provider when
|
57
41
|
# using both useradd and luseradd
|
58
42
|
if not @resource.allowdupe? and @resource.forcelocal?
|
59
|
-
if @resource.should(:gid) and findgroup(
|
43
|
+
if @resource.should(:gid) and findgroup(:gid, @resource.should(:gid).to_s)
|
60
44
|
raise(Puppet::Error, _("GID %{resource} already exists, use allowdupe to force group creation") % { resource: @resource.should(:gid).to_s })
|
61
45
|
end
|
62
46
|
elsif @resource.allowdupe? and not @resource.forcelocal?
|
@@ -65,6 +49,11 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
|
|
65
49
|
[]
|
66
50
|
end
|
67
51
|
|
52
|
+
def create
|
53
|
+
super
|
54
|
+
set(:members, @resource[:members]) if @resource[:members]
|
55
|
+
end
|
56
|
+
|
68
57
|
def addcmd
|
69
58
|
if @resource.forcelocal?
|
70
59
|
cmd = [command(:localadd)]
|
@@ -86,12 +75,18 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
|
|
86
75
|
end
|
87
76
|
|
88
77
|
def modifycmd(param, value)
|
89
|
-
if @resource.forcelocal?
|
78
|
+
if @resource.forcelocal? || @resource[:members]
|
90
79
|
cmd = [command(:localmodify)]
|
91
80
|
@custom_environment = Puppet::Util::Libuser.getenv
|
92
81
|
else
|
93
82
|
cmd = [command(:modify)]
|
94
83
|
end
|
84
|
+
|
85
|
+
if param == :members
|
86
|
+
value = members_to_s(value)
|
87
|
+
purge_members if @resource[:auth_membership] && !members.empty?
|
88
|
+
end
|
89
|
+
|
95
90
|
cmd << flag(param) << value
|
96
91
|
# TODO the group type only really manages gid, so there are currently no
|
97
92
|
# tests for this behavior
|
@@ -109,4 +104,37 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
|
|
109
104
|
[command(:delete), @resource[:name]]
|
110
105
|
end
|
111
106
|
end
|
107
|
+
|
108
|
+
def members_insync?(current, should)
|
109
|
+
current.uniq.sort == @resource.parameter(:members).actual_should(current, should)
|
110
|
+
end
|
111
|
+
|
112
|
+
def members_to_s(current)
|
113
|
+
return '' if current.nil? || !current.kind_of?(Array)
|
114
|
+
current.join(',')
|
115
|
+
end
|
116
|
+
|
117
|
+
def purge_members
|
118
|
+
localmodify('-m', members_to_s(members), @resource.name)
|
119
|
+
end
|
120
|
+
|
121
|
+
def member_valid?(user)
|
122
|
+
!!Etc.getpwnam(user)
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
def findgroup(key, value)
|
128
|
+
group_file = "/etc/group"
|
129
|
+
group_keys = [:group_name, :password, :gid, :user_list]
|
130
|
+
index = group_keys.index(key)
|
131
|
+
@group_content ||= File.read(group_file)
|
132
|
+
@group_content.each_line do |line|
|
133
|
+
group = line.split(":")
|
134
|
+
if group[index] == value
|
135
|
+
return Hash[group_keys.zip(group)]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
false
|
139
|
+
end
|
112
140
|
end
|