bolt 0.10.0 → 0.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 bolt might be problematic. Click here for more details.

Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bolt/cli.rb +43 -43
  3. data/lib/bolt/config.rb +25 -5
  4. data/lib/bolt/node.rb +3 -1
  5. data/lib/bolt/node/ssh.rb +15 -2
  6. data/lib/bolt/node/winrm.rb +20 -9
  7. data/lib/bolt/version.rb +1 -1
  8. data/modules/boltlib/lib/puppet/functions/run_plan.rb +1 -1
  9. data/modules/boltlib/lib/puppet/functions/run_task.rb +29 -32
  10. data/vendored/puppet/lib/puppet.rb +2 -5
  11. data/vendored/puppet/lib/puppet/application.rb +18 -1
  12. data/vendored/puppet/lib/puppet/application/agent.rb +8 -1
  13. data/vendored/puppet/lib/puppet/application/config.rb +1 -0
  14. data/vendored/puppet/lib/puppet/application/device.rb +1 -2
  15. data/vendored/puppet/lib/puppet/application/filebucket.rb +10 -2
  16. data/vendored/puppet/lib/puppet/application/help.rb +1 -0
  17. data/vendored/puppet/lib/puppet/application_support.rb +6 -1
  18. data/vendored/puppet/lib/puppet/configurer.rb +8 -3
  19. data/vendored/puppet/lib/puppet/defaults.rb +29 -9
  20. data/vendored/puppet/lib/puppet/environments.rb +2 -0
  21. data/vendored/puppet/lib/puppet/face/config.rb +14 -1
  22. data/vendored/puppet/lib/puppet/face/module/list.rb +1 -1
  23. data/vendored/puppet/lib/puppet/face/module/search.rb +4 -1
  24. data/vendored/puppet/lib/puppet/forge.rb +6 -0
  25. data/vendored/puppet/lib/puppet/functions/convert_to.rb +32 -0
  26. data/vendored/puppet/lib/puppet/gettext/config.rb +135 -37
  27. data/vendored/puppet/lib/puppet/gettext/module_translations.rb +42 -0
  28. data/vendored/puppet/lib/puppet/indirector/catalog/compiler.rb +2 -0
  29. data/vendored/puppet/lib/puppet/module.rb +10 -18
  30. data/vendored/puppet/lib/puppet/network/http/factory.rb +9 -0
  31. data/vendored/puppet/lib/puppet/node/environment.rb +14 -0
  32. data/vendored/puppet/lib/puppet/parser/functions/sprintf.rb +17 -3
  33. data/vendored/puppet/lib/puppet/parser/scope.rb +11 -0
  34. data/vendored/puppet/lib/puppet/pops.rb +0 -1
  35. data/vendored/puppet/lib/puppet/pops/evaluator/epp_evaluator.rb +13 -0
  36. data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +39 -5
  37. data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +64 -24
  38. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +1 -1
  39. data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +21 -70
  40. data/vendored/puppet/lib/puppet/pops/lookup/hiera_config.rb +2 -2
  41. data/vendored/puppet/lib/puppet/pops/parser/parser_support.rb +1 -1
  42. data/vendored/puppet/lib/puppet/pops/pcore.rb +43 -1
  43. data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +4 -0
  44. data/vendored/puppet/lib/puppet/pops/types/types.rb +25 -5
  45. data/vendored/puppet/lib/puppet/provider/selmodule/semodule.rb +5 -3
  46. data/vendored/puppet/lib/puppet/provider/service/smf.rb +2 -0
  47. data/vendored/puppet/lib/puppet/settings/environment_conf.rb +14 -2
  48. data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +1 -1
  49. data/vendored/puppet/lib/puppet/ssl/certificate_signer.rb +6 -0
  50. data/vendored/puppet/lib/puppet/ssl/host.rb +1 -1
  51. data/vendored/puppet/lib/puppet/type/file/checksum.rb +1 -1
  52. data/vendored/puppet/lib/puppet/type/file/checksum_value.rb +4 -3
  53. data/vendored/puppet/lib/puppet/type/k5login.rb +101 -0
  54. data/vendored/puppet/lib/puppet/type/tidy.rb +4 -2
  55. data/vendored/puppet/lib/puppet/util/checksums.rb +82 -1
  56. data/vendored/puppet/lib/puppet/util/command_line.rb +5 -0
  57. data/vendored/puppet/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet.rb +5 -1
  58. data/vendored/puppet/lib/puppet_pal.rb +272 -11
  59. data/vendored/require_vendored.rb +0 -6
  60. metadata +8 -8
  61. data/vendored/puppet/lib/puppet/bindings.rb +0 -147
  62. data/vendored/puppet/lib/puppet/pops/types/task.rb +0 -116
@@ -6,7 +6,7 @@ module Loader
6
6
  class StaticLoader < Loader
7
7
 
8
8
  BUILTIN_TYPE_NAMES = %w{
9
- Auegas
9
+ Augeas
10
10
  Component
11
11
  Computer
12
12
  Cron
@@ -4,7 +4,6 @@ module Puppet::Pops
4
4
  module Loader
5
5
  class TaskInstantiator
6
6
  def self.create(loader, typed_name, source_refs)
7
- ensure_initialized
8
7
  name = typed_name.name
9
8
  metadata = nil
10
9
  task_source = nil
@@ -23,95 +22,47 @@ class TaskInstantiator
23
22
  raise ArgumentError, _('No source besides task metadata was found in directory %{directory} for task %{name}') %
24
23
  { name: name, directory: File.dirname(source_refs[0]) }
25
24
  end
26
- create_task_type(loader, typed_name, task_source, metadata)
25
+ create_task(loader, name, task_source, metadata)
27
26
  end
28
27
 
29
- def self.create_task_type(loader, typed_name, task_source, metadata)
28
+ def self.create_task(loader, name, task_source, metadata)
30
29
  if metadata.nil?
31
- create_task_type_from_hash(loader, typed_name, task_source, EMPTY_HASH)
30
+ create_task_from_hash(loader, name, task_source, EMPTY_HASH)
32
31
  else
33
32
  json_text = loader.get_contents(metadata)
34
33
  begin
35
- hash = JSON.parse(json_text) || EMPTY_HASH
36
- Types::TypeAsserter.assert_instance_of(nil, @type_hash_t, hash) { _('The metadata for task %{name}') % { name: typed_name.name } }
37
- create_task_type_from_hash(loader, typed_name, task_source, hash)
34
+ create_task_from_hash(loader, name, task_source, JSON.parse(json_text) || EMPTY_HASH)
38
35
  rescue JSON::ParserError => ex
39
36
  raise Puppet::ParseError.new(ex.message, metadata)
40
37
  rescue Types::TypeAssertionError => ex
41
38
  # Not strictly a parser error but from the users perspective, the file content didn't parse properly. The
42
39
  # ParserError also conveys file info (even though line is unknown)
43
- raise Puppet::ParseError.new(ex.message, metadata)
40
+ msg = _('Failed to load metadata for task %{name}: %{reason}') % { :name => name, :reason => ex.message }
41
+ raise Puppet::ParseError.new(msg, metadata)
44
42
  end
45
43
  end
46
44
  end
47
45
 
48
- def self.ensure_initialized
49
- return if @initialized
50
- @initialized = true
51
-
52
- tf = Types::TypeFactory
53
- params_t = tf.hash_kv(
54
- Types::Task::PARAMETER_NAME_PATTERN,
55
- tf.struct(
56
- tf.optional('description') => tf.string,
57
- tf.optional('type') => Types::PStringType::NON_EMPTY,
58
- tf.optional('sensitive') => tf.boolean
59
- )
60
- )
61
-
62
- @type_hash_t = tf.struct(
63
- tf.optional('description') => tf.string,
64
- tf.optional('puppet_task_version') => tf.integer,
65
- tf.optional('supports_noop') => tf.boolean,
66
- tf.optional('input_method') => tf.enum('stdin', 'environment'),
67
- 'parameters' => params_t,
68
- tf.optional('output') => params_t
69
- )
70
- end
71
-
72
- def self.create_task_type_from_hash(loader, typed_name, task_source, hash)
73
- attributes = {}
74
- constants = {}
75
- parameters_entry_found = false
46
+ def self.create_task_from_hash(loader, name, task_source, hash)
47
+ arguments = {
48
+ 'name' => name,
49
+ 'executable' => task_source
50
+ }
76
51
  hash.each_pair do |key, value|
77
- if 'parameters' == key
78
- parameters_entry_found = true
79
- value.each_pair do |param_name, param_decl|
80
- attributes[param_name] = create_attribute(loader, param_decl)
52
+ if 'parameters' == key || 'output' == key
53
+ ps = {}
54
+ value.each_pair do |k, v|
55
+ pd = v.dup
56
+ t = v['type']
57
+ pd['type'] = t.nil? ? Types::TypeFactory.data : Types::TypeParser.singleton.parse(t, loader)
58
+ ps[k] = pd
81
59
  end
82
- else
83
- constants[key] = value
60
+ value = ps
84
61
  end
62
+ arguments[key] = value
85
63
  end
86
64
 
87
- if parameters_entry_found
88
- parent_type = 'Task'
89
- else
90
- # No entry means any parameters
91
- attributes = EMPTY_HASH
92
- parent_type = 'GenericTask'
93
- end
94
-
95
- constants['executable'] = Pathname(task_source).relative_path_from(Pathname(loader.path) + 'tasks').to_s
96
-
97
- Types::TypeFactory.object(
98
- {
99
- 'name' => Types::TypeFormatter.singleton.capitalize_segments(typed_name.name),
100
- 'parent' => Types::TypeParser.singleton.parse(parent_type, loader),
101
- 'attributes' => attributes,
102
- 'constants' => constants
103
- }, loader)
104
- end
105
-
106
- def self.create_attribute(loader, param_decl)
107
- result = {}
108
- type = Types::TypeParser.singleton.parse(param_decl['type'] || 'Data', loader)
109
-
110
- # Treat OptionalType as optional attribute entry, i.e. provide a default of undef
111
- result['value'] = nil if type.is_a?(Types::POptionalType)
112
-
113
- result['type'] = type
114
- result
65
+ Types::TypeFactory.task.from_hash(arguments)
115
66
  end
116
67
  end
117
68
  end
@@ -543,8 +543,8 @@ class HieraConfigV5 < HieraConfig
543
543
  tf = Types::TypeFactory
544
544
  nes_t = Types::PStringType::NON_EMPTY
545
545
 
546
- # Need alias here to avoid ridiculously long regexp burp in case of validation errors.
547
- uri_t = Pcore::TYPE_URI_ALIAS
546
+ # Validated using Ruby URI implementation
547
+ uri_t = Types::PStringType::NON_EMPTY
548
548
 
549
549
  # The option name must start with a letter and end with a letter or digit. May contain underscore and dash.
550
550
  option_name_t = tf.pattern(/\A[A-Za-z](:?[0-9A-Za-z_-]*[0-9A-Za-z])?\z/)
@@ -91,7 +91,7 @@ class Parser
91
91
  #
92
92
  def on_error(token,value,stack)
93
93
  if token == 0 # denotes end of file
94
- value_at = 'end of file'
94
+ value_at = 'end of input'
95
95
  else
96
96
  value_at = "'#{value[:value]}'"
97
97
  end
@@ -40,7 +40,6 @@ module Pcore
40
40
  add_alias('Pcore::QRef', TYPE_QUALIFIED_REFERENCE, loader)
41
41
 
42
42
  if Puppet[:tasks]
43
- require_relative 'types/task'
44
43
  require_relative 'types/execution_result'
45
44
 
46
45
  add_object_type('Target', <<-PUPPET, loader)
@@ -51,6 +50,49 @@ module Pcore
51
50
  }
52
51
  }
53
52
  PUPPET
53
+
54
+ add_object_type('Task', <<-PUPPET, loader)
55
+ {
56
+ attributes => {
57
+ # Fully qualified name of the task
58
+ name => { type => Pattern[/\\A[a-z][a-z0-9_]*(?:::[a-z][a-z0-9_]*)*\\z/] },
59
+
60
+ # Full path to executable
61
+ executable => { type => String },
62
+
63
+ # Task description
64
+ description => { type => Optional[String], value => undef },
65
+
66
+ # Puppet Task version
67
+ puppet_task_version => { type => Integer, value => 1 },
68
+
69
+ # Type, description, and sensitive property of each parameter
70
+ parameters => {
71
+ type => Optional[Hash[
72
+ Pattern[/\\A[a-z][a-z0-9_]*\\z/],
73
+ Struct[
74
+ Optional[description] => String,
75
+ Optional[sensitive] => Boolean,
76
+ type => Type[Optional[Data]]]]],
77
+ value => undef
78
+ },
79
+
80
+ # Type, description, and sensitive property of each output
81
+ output => {
82
+ type => Optional[Hash[
83
+ Pattern[/\\A[a-z][a-z0-9_]*\\z/],
84
+ Struct[
85
+ Optional[description] => String,
86
+ Optional[sensitive] => Boolean,
87
+ type => Type[Optional[Data]]]]],
88
+ value => undef
89
+ },
90
+
91
+ supports_noop => { type => Boolean, value => false },
92
+ input_method => { type => String, value => 'both' },
93
+ }
94
+ }
95
+ PUPPET
54
96
  end
55
97
  Types::TypedModelObject.register_ptypes(loader, ir)
56
98
 
@@ -528,6 +528,10 @@ module TypeFactory
528
528
  @target_t ||= TypeParser.singleton.parse('Target')
529
529
  end
530
530
 
531
+ def self.task
532
+ @task_t ||= TypeParser.singleton.parse('Task')
533
+ end
534
+
531
535
  # Produces a type for URI[String or Hash]
532
536
  # @api public
533
537
  #
@@ -60,8 +60,6 @@ class TypedModelObject < Object
60
60
  RubyMethod.register_ptype(loader, ir),
61
61
  ]
62
62
  if Puppet[:tasks]
63
- types << Task.register_ptype(loader, ir)
64
- types << GenericTask.register_ptype(loader, ir)
65
63
  types << ExecutionResult.register_ptype(loader, ir)
66
64
  end
67
65
 
@@ -135,8 +133,11 @@ class PAnyType < TypedModelObject
135
133
  assignable?(o.resolved_type, guard)
136
134
  end
137
135
  when PVariantType
138
- # Assignable if all contained types are assignable
139
- o.types.all? { |vt| assignable?(vt, guard) }
136
+ # Assignable if all contained types are assignable, or if this is exactly Any
137
+ return true if self.class == PAnyType
138
+ # An empty variant may be assignable to NotUndef[T] if T is assignable to empty variant
139
+ return _assignable?(o, guard) if is_a?(PNotUndefType) && o.types.empty?
140
+ !o.types.empty? && o.types.all? { |vt| assignable?(vt, guard) }
140
141
  when POptionalType
141
142
  # Assignable if undef and contained type is assignable
142
143
  assignable?(PUndefType::DEFAULT) && (o.type.nil? || assignable?(o.type))
@@ -655,7 +656,12 @@ class PUnitType < PAnyType
655
656
 
656
657
  DEFAULT = PUnitType.new
657
658
 
659
+ def assignable?(o, guard=nil)
660
+ true
661
+ end
662
+
658
663
  protected
664
+
659
665
  # @api private
660
666
  def _assignable?(o, guard)
661
667
  true
@@ -2443,7 +2449,7 @@ class PCallableType < PAnyType
2443
2449
 
2444
2450
  # @api private
2445
2451
  def callable_args?(required_callable_t, guard)
2446
- # If the required callable is euqal or more specific than self, self is acceptable arguments
2452
+ # If the required callable is equal or more specific than self, self is acceptable arguments
2447
2453
  required_callable_t.assignable?(self, guard)
2448
2454
  end
2449
2455
 
@@ -3020,6 +3026,20 @@ class PVariantType < PAnyType
3020
3026
 
3021
3027
  DEFAULT = PVariantType.new(EMPTY_ARRAY)
3022
3028
 
3029
+ def assignable?(o, guard = nil)
3030
+ # an empty Variant does not match Undef (it is void - not even undef)
3031
+ if o.is_a?(PUndefType) && types.empty?
3032
+ return false
3033
+ end
3034
+
3035
+ return super unless o.is_a?(PVariantType)
3036
+ # If empty, all Variant types match irrespective of the types they hold (including being empty)
3037
+ return true if types.empty?
3038
+ # Since this variant is not empty, an empty Variant cannot match, because it matches nothing
3039
+ # otherwise all types in o must be assignable to this
3040
+ !o.types.empty? && o.types.all? { |vt| super(vt, guard) }
3041
+ end
3042
+
3023
3043
  protected
3024
3044
 
3025
3045
  # @api private
@@ -118,11 +118,13 @@ Puppet::Type.type(:selmodule).provide(:semodule) do
118
118
  end
119
119
 
120
120
  def selmodversion_loaded
121
- lines = ()
121
+ selmod_output = []
122
+ selmodule_cmd = "#{command(:semodule)} --list"
122
123
  begin
123
- execpipe("#{command(:semodule)} --list") do |output|
124
+ execpipe(selmodule_cmd) do |output|
124
125
  output.each_line do |line|
125
126
  line.chomp!
127
+ selmod_output << line
126
128
  bits = line.split
127
129
  if bits[0] == @resource[:name]
128
130
  self.debug "load version #{bits[1]}"
@@ -131,7 +133,7 @@ Puppet::Type.type(:selmodule).provide(:semodule) do
131
133
  end
132
134
  end
133
135
  rescue Puppet::ExecutionFailure
134
- raise Puppet::ExecutionFailure, "Could not list policy modules: #{lines.join(' ').chomp!}", $!.backtrace
136
+ raise Puppet::ExecutionFailure, _("Could not list policy modules: \"%{selmodule_command}\" failed with \"%{selmod_output}\"") % { selmodule_command: selmodule_cmd, selmod_output: selmod_output.join(' ') }
135
137
  end
136
138
  nil
137
139
  end
@@ -107,6 +107,8 @@ Puppet::Type.type(:service).provide :smf, :parent => :base do
107
107
  end
108
108
 
109
109
  def stop
110
+ # Don't try to stop non-existing services (PUP-8167)
111
+ return if self.status == :absent
110
112
  # Wait for the service to actually stop before returning.
111
113
  super
112
114
  self.wait('offline', 'disabled', 'uninitialized')
@@ -138,13 +138,25 @@ class Puppet::Settings::EnvironmentConf
138
138
  section_keys = config.sections.keys
139
139
  main = config.sections[:main]
140
140
  if section_keys.size > 1
141
- Puppet.warning(_("Invalid sections in environment.conf at '%{path_to_conf_file}'. Environment conf may not have sections. The following sections are being ignored: '%{sections}'") % { path_to_conf_file: path_to_conf_file, sections: (section_keys - [:main]).join(',') })
141
+ # warn once per config file path
142
+ Puppet.warn_once(
143
+ :invalid_settings_section, "EnvironmentConf-section:#{path_to_conf_file}",
144
+ _("Invalid sections in environment.conf at '%{path_to_conf_file}'. Environment conf may not have sections. The following sections are being ignored: '%{sections}'") % {
145
+ path_to_conf_file: path_to_conf_file,
146
+ sections: (section_keys - [:main]).join(',')
147
+ })
142
148
  valid = false
143
149
  end
144
150
 
145
151
  extraneous_settings = main.settings.map(&:name) - VALID_SETTINGS
146
152
  if !extraneous_settings.empty?
147
- Puppet.warning(_("Invalid settings in environment.conf at '%{path_to_conf_file}'. The following unknown setting(s) are being ignored: %{ignored_settings}") % { path_to_conf_file: path_to_conf_file, ignored_settings: extraneous_settings.join(', ') })
153
+ # warn once per config file path
154
+ Puppet.warn_once(
155
+ :invalid_settings, "EnvironmentConf-settings:#{path_to_conf_file}",
156
+ _("Invalid settings in environment.conf at '%{path_to_conf_file}'. The following unknown setting(s) are being ignored: %{ignored_settings}") % {
157
+ path_to_conf_file: path_to_conf_file,
158
+ ignored_settings: extraneous_settings.join(', ')
159
+ })
148
160
  valid = false
149
161
  end
150
162
 
@@ -399,7 +399,7 @@ class Puppet::SSL::CertificateAuthority
399
399
 
400
400
  # Check for wildcards in the subjectAltName fields too.
401
401
  if csr.subject_alt_names.any? {|x| x.include? '*' }
402
- raise CertificateSigningError.new(hostname), _("CSR '%{csr}' subjectAltName contains a wildcard, which is not allowed: %{alt_names} To continue, this CSR needs to be cleaned.") % { csr: csr.name, alt_names: csr.subject_alt_names.join(', ') }
402
+ raise CertificateSigningError.new(hostname), _("CSR '%{csr}' subjectAltName contains a wildcard, which is not allowed: %{alt_names}. To continue, this CSR needs to be cleaned.") % { csr: csr.name, alt_names: csr.subject_alt_names.join(', ') }
403
403
  end
404
404
  end
405
405
 
@@ -14,6 +14,12 @@ class Puppet::SSL::CertificateSigner
14
14
  @digest = OpenSSL::Digest::SHA256
15
15
  elsif OpenSSL::Digest.const_defined?('SHA1')
16
16
  @digest = OpenSSL::Digest::SHA1
17
+ elsif OpenSSL::Digest.const_defined?('SHA512')
18
+ @digest = OpenSSL::Digest::SHA512
19
+ elsif OpenSSL::Digest.const_defined?('SHA384')
20
+ @digest = OpenSSL::Digest::SHA384
21
+ elsif OpenSSL::Digest.const_defined?('SHA224')
22
+ @digest = OpenSSL::Digest::SHA224
17
23
  else
18
24
  raise Puppet::Error,
19
25
  "No FIPS 140-2 compliant digest algorithm in OpenSSL::Digest"
@@ -320,7 +320,7 @@ ERROR_STRING
320
320
  # configurable
321
321
  # --jeffweiss 29 aug 2012
322
322
  def suitable_message_digest_algorithms
323
- [:SHA1, :SHA256, :SHA512]
323
+ [:SHA1, :SHA224, :SHA256, :SHA384, :SHA512]
324
324
  end
325
325
 
326
326
  # Attempt to retrieve a cert, if we don't already have one.
@@ -9,7 +9,7 @@ Puppet::Type.type(:file).newparam(:checksum) do
9
9
 
10
10
  The default checksum type is md5."
11
11
 
12
- newvalues "md5", "md5lite", "sha256", "sha256lite", "mtime", "ctime", "none"
12
+ newvalues "md5", "md5lite", "sha224", "sha256", "sha256lite", "sha384", "sha512", "mtime", "ctime", "none"
13
13
 
14
14
  defaultto do
15
15
  Puppet[:digest_algorithm].to_sym
@@ -6,9 +6,10 @@ module Puppet
6
6
  include Puppet::Util::Checksums
7
7
  include Puppet::DataSync
8
8
 
9
- desc "The checksum of the source contents. Only md5 and sha256 are supported when
10
- specifying this parameter. If this parameter is set, source_permissions will be
11
- assumed to be false, and ownership and permissions will not be read from source."
9
+ desc "The checksum of the source contents. Only md5, sha256, sha224, sha384 and sha512
10
+ are supported when specifying this parameter. If this parameter is set,
11
+ source_permissions will be assumed to be false, and ownership and permissions
12
+ will not be read from source."
12
13
 
13
14
  def insync?(is)
14
15
  # If checksum_value and source are specified, manage the file contents.
@@ -1,5 +1,6 @@
1
1
  # Plug-in type for handling k5login files
2
2
  require 'puppet/util'
3
+ require 'puppet/util/selinux'
3
4
 
4
5
  Puppet::Type.newtype(:k5login) do
5
6
  @doc = "Manage the `.k5login` file for a user. Specify the full path to
@@ -31,10 +32,60 @@ Puppet::Type.newtype(:k5login) do
31
32
  defaultto { "644" }
32
33
  end
33
34
 
35
+ # To manage the selinux user of the file
36
+ newproperty(:seluser) do
37
+ desc "What the SELinux user component of the context of the file should be.
38
+ Any valid SELinux user component is accepted. For example `user_u`.
39
+ If not specified it defaults to the value returned by matchpathcon for
40
+ the file, if any exists. Only valid on systems with SELinux support
41
+ enabled."
42
+
43
+ defaultto { "user_u" }
44
+ end
45
+
46
+ # To manage the selinux role of the file
47
+ newproperty(:selrole) do
48
+ desc "What the SELinux role component of the context of the file should be.
49
+ Any valid SELinux role component is accepted. For example `role_r`.
50
+ If not specified it defaults to the value returned by matchpathcon for
51
+ the file, if any exists. Only valid on systems with SELinux support
52
+ enabled."
53
+
54
+ defaultto { "object_r" }
55
+ end
56
+
57
+ # To manage the selinux type of the file
58
+ newproperty(:seltype) do
59
+ desc "What the SELinux type component of the context of the file should be.
60
+ Any valid SELinux type component is accepted. For example `tmp_t`.
61
+ If not specified it defaults to the value returned by matchpathcon for
62
+ the file, if any exists. Only valid on systems with SELinux support
63
+ enabled."
64
+
65
+ # to my knowledge, `krb5_home_t` is the only valid type for .k5login
66
+ defaultto { "krb5_home_t" }
67
+ end
68
+
69
+ # To manage the selinux range of the file
70
+ newproperty(:selrange) do
71
+ desc "What the SELinux range component of the context of the file should be.
72
+ Any valid SELinux range component is accepted. For example `s0` or
73
+ `SystemHigh`. If not specified it defaults to the value returned by
74
+ matchpathcon for the file, if any exists. Only valid on systems with
75
+ SELinux support enabled and that have support for MCS (Multi-Category
76
+ Security)."
77
+
78
+ defaultto { "s0" }
79
+ end
80
+
81
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
82
+
34
83
  provide(:k5login) do
35
84
  desc "The k5login provider is the only provider for the k5login
36
85
  type."
37
86
 
87
+ include Puppet::Util::SELinux
88
+
38
89
  # Does this file exist?
39
90
  def exists?
40
91
  Puppet::FileSystem.exist?(@resource[:name])
@@ -78,6 +129,56 @@ Puppet::Type.newtype(:k5login) do
78
129
  File.chmod(Integer("0#{value}"), @resource[:name])
79
130
  end
80
131
 
132
+ # Set the file seluser
133
+ def seluser
134
+ if selinux_support?
135
+ context = get_selinux_current_context(@resource[:name])
136
+ return parse_selinux_context(:seluser, context)
137
+ end
138
+ end
139
+
140
+ def seluser=(value)
141
+ set_selinux_context(@resource[:name], value, :seluser)
142
+ end
143
+
144
+ # Set the file selrole
145
+ def selrole
146
+ if selinux_support?
147
+ context = get_selinux_current_context(@resource[:name])
148
+ return parse_selinux_context(:selrole, context)
149
+ end
150
+ end
151
+
152
+ # Set the file seltype
153
+ def selrole=(value)
154
+ set_selinux_context(@resource[:name], value, :selrole)
155
+ end
156
+
157
+ # Set the file seltype
158
+ def seltype
159
+ if selinux_support?
160
+ context = get_selinux_current_context(@resource[:name])
161
+ return parse_selinux_context(:seltype, context)
162
+ end
163
+ end
164
+
165
+ # Set the file selrange
166
+ def seltype=(value)
167
+ set_selinux_context(@resource[:name], value, :seltype)
168
+ end
169
+
170
+ # Set the file selrange
171
+ def selrange
172
+ if selinux_support?
173
+ context = get_selinux_current_context(@resource[:name])
174
+ return parse_selinux_context(:selrange, context)
175
+ end
176
+ end
177
+
178
+ def selrange=(value)
179
+ set_selinux_context(@resource[:name], value, :selrange)
180
+ end
181
+
81
182
  private
82
183
  def write(value)
83
184
  Puppet::Util.replace_file(@resource[:name], 0644) do |f|