puppet 3.4.2 → 3.4.3

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 (47) hide show
  1. checksums.yaml +7 -0
  2. data/ext/build_defaults.yaml +1 -1
  3. data/ext/redhat/puppet.spec.erb +8 -8
  4. data/lib/puppet/defaults.rb +5 -1
  5. data/lib/puppet/indirector/resource_type/parser.rb +58 -38
  6. data/lib/puppet/metatype/manager.rb +0 -1
  7. data/lib/puppet/network/http/connection.rb +8 -0
  8. data/lib/puppet/network/http/webrick.rb +4 -1
  9. data/lib/puppet/node/environment.rb +13 -32
  10. data/lib/puppet/parser/compiler.rb +1 -2
  11. data/lib/puppet/parser/functions/each.rb +4 -4
  12. data/lib/puppet/parser/type_loader.rb +20 -1
  13. data/lib/puppet/provider/package/dpkg.rb +13 -54
  14. data/lib/puppet/provider/package/rpm.rb +7 -11
  15. data/lib/puppet/transaction/resource_harness.rb +17 -17
  16. data/lib/puppet/type.rb +83 -117
  17. data/lib/puppet/type/exec.rb +42 -20
  18. data/lib/puppet/type/file.rb +4 -0
  19. data/lib/puppet/type/interface.rb +4 -0
  20. data/lib/puppet/type/mount.rb +4 -2
  21. data/lib/puppet/type/package.rb +4 -0
  22. data/lib/puppet/type/schedule.rb +14 -13
  23. data/lib/puppet/type/service.rb +9 -6
  24. data/lib/puppet/type/stage.rb +17 -9
  25. data/lib/puppet/type/user.rb +1 -1
  26. data/lib/puppet/util/monkey_patches.rb +16 -11
  27. data/lib/puppet/util/rdoc/code_objects.rb +4 -0
  28. data/lib/puppet/util/windows.rb +1 -0
  29. data/lib/puppet/util/windows/file.rb +36 -13
  30. data/lib/puppet/util/windows/process.rb +7 -4
  31. data/lib/puppet/util/windows/registry.rb +35 -1
  32. data/lib/puppet/util/windows/string.rb +14 -0
  33. data/lib/puppet/version.rb +1 -1
  34. data/spec/integration/util_spec.rb +31 -0
  35. data/spec/unit/node/environment_spec.rb +5 -13
  36. data/spec/unit/provider/package/aptitude_spec.rb +13 -10
  37. data/spec/unit/provider/package/aptrpm_spec.rb +2 -2
  38. data/spec/unit/provider/package/dpkg_spec.rb +93 -234
  39. data/spec/unit/provider/package/rpm_spec.rb +50 -74
  40. data/spec/unit/provider/package/yum_spec.rb +5 -6
  41. data/spec/unit/transaction/resource_harness_spec.rb +111 -3
  42. data/spec/unit/type/user_spec.rb +7 -5
  43. data/spec/unit/util/windows/registry_spec.rb +54 -0
  44. data/spec/unit/util/windows/string_spec.rb +54 -0
  45. data/tasks/benchmark.rake +110 -0
  46. data/tasks/ci.rake +1 -1
  47. metadata +11 -15
@@ -16,12 +16,10 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
16
16
 
17
17
  # Note: self:: is required here to keep these constants in the context of what will
18
18
  # eventually become this Puppet::Type::Package::ProviderRpm class.
19
- self::RPM_DESCRIPTION_DELIMITER = ':DESC:'
20
19
  # The query format by which we identify installed packages
21
- self::NEVRA_FORMAT = %Q{%{NAME} %|EPOCH?{%{EPOCH}}:{0}| %{VERSION} %{RELEASE} %{ARCH} #{self::RPM_DESCRIPTION_DELIMITER} %{SUMMARY}\\n}
22
- self::NEVRA_REGEX = %r{^(\S+) (\S+) (\S+) (\S+) (\S+)(?: #{self::RPM_DESCRIPTION_DELIMITER} ?(.*))?$}
23
- self::RPM_PACKAGE_NOT_FOUND_REGEX = /package .+ is not installed/
24
- self::NEVRA_FIELDS = [:name, :epoch, :version, :release, :arch, :description]
20
+ self::NEVRA_FORMAT = %Q{%{NAME} %|EPOCH?{%{EPOCH}}:{0}| %{VERSION} %{RELEASE} %{ARCH}\\n}
21
+ self::NEVRA_REGEX = %r{^(\S+) (\S+) (\S+) (\S+) (\S+)$}
22
+ self::NEVRA_FIELDS = [:name, :epoch, :version, :release, :arch]
25
23
 
26
24
  commands :rpm => "rpm"
27
25
 
@@ -82,6 +80,7 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
82
80
  begin
83
81
  output = rpm(*cmd)
84
82
  rescue Puppet::ExecutionFailure
83
+ # rpm -q exits 1 if package not found
85
84
  return nil
86
85
  end
87
86
  # FIXME: We could actually be getting back multiple packages
@@ -179,21 +178,18 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
179
178
 
180
179
  # @param line [String] one line of rpm package query information
181
180
  # @return [Hash] of NEVRA_FIELDS strings parsed from package info
182
- # if we failed to parse
183
- # @note warns if failed to match a line, and returns an empty Hash.
181
+ # or an empty hash if we failed to parse
184
182
  # @api private
185
183
  def self.nevra_to_hash(line)
186
184
  line.strip!
187
185
  hash = {}
188
186
 
189
- if self::RPM_PACKAGE_NOT_FOUND_REGEX.match(line)
190
- # pass through, package was not found
191
- elsif match = self::NEVRA_REGEX.match(line)
187
+ if match = self::NEVRA_REGEX.match(line)
192
188
  self::NEVRA_FIELDS.zip(match.captures) { |f, v| hash[f] = v }
193
189
  hash[:provider] = self.name
194
190
  hash[:ensure] = "#{hash[:version]}-#{hash[:release]}"
195
191
  else
196
- Puppet.warning "Failed to match rpm line #{line}"
192
+ Puppet.debug("Failed to match rpm line #{line}")
197
193
  end
198
194
 
199
195
  return hash
@@ -1,6 +1,8 @@
1
1
  require 'puppet/resource/status'
2
2
 
3
3
  class Puppet::Transaction::ResourceHarness
4
+ NO_ACTION = Object.new
5
+
4
6
  extend Forwardable
5
7
  def_delegators :@transaction, :relationship_graph
6
8
 
@@ -74,9 +76,14 @@ class Puppet::Transaction::ResourceHarness
74
76
  cache(resource, param, context.current_values[param])
75
77
  end
76
78
 
77
- managed_via_ensure = manage_via_ensure_if_possible(resource, context)
79
+ ensure_param = resource.parameter(:ensure)
80
+ if ensure_param && ensure_param.should
81
+ ensure_event = sync_if_needed(ensure_param, context)
82
+ else
83
+ ensure_event = NO_ACTION
84
+ end
78
85
 
79
- if !managed_via_ensure
86
+ if ensure_event == NO_ACTION
80
87
  if context.resource_present?
81
88
  resource.properties.each do |param|
82
89
  sync_if_needed(param, context)
@@ -101,15 +108,6 @@ class Puppet::Transaction::ResourceHarness
101
108
  end
102
109
  end
103
110
 
104
- def manage_via_ensure_if_possible(resource, context)
105
- ensure_param = resource.parameter(:ensure)
106
- if ensure_param && ensure_param.should
107
- sync_if_needed(ensure_param, context)
108
- else
109
- false
110
- end
111
- end
112
-
113
111
  def sync_if_needed(param, context)
114
112
  historical_value = context.historical_values[param.name]
115
113
  current_value = context.current_values[param.name]
@@ -130,9 +128,9 @@ class Puppet::Transaction::ResourceHarness
130
128
  sync(event, param, current_value, brief_audit_message)
131
129
  end
132
130
 
133
- true
131
+ event
134
132
  else
135
- false
133
+ NO_ACTION
136
134
  end
137
135
  rescue => detail
138
136
  # Execution will continue on StandardErrors, just store the event
@@ -141,7 +139,7 @@ class Puppet::Transaction::ResourceHarness
141
139
  event = create_change_event(param, current_value, historical_value)
142
140
  event.status = "failure"
143
141
  event.message = "change from #{param.is_to_s(current_value)} to #{param.should_to_s(param.should)} failed: #{detail}"
144
- false
142
+ event
145
143
  rescue Exception => detail
146
144
  # Execution will halt on Exceptions, they get raised to the application
147
145
  event = create_change_event(param, current_value, historical_value)
@@ -214,13 +212,15 @@ class Puppet::Transaction::ResourceHarness
214
212
  end
215
213
 
216
214
  # @api private
217
- ResourceApplicationContext = Struct.new(:current_values,
215
+ ResourceApplicationContext = Struct.new(:resource,
216
+ :current_values,
218
217
  :historical_values,
219
218
  :audited_params,
220
219
  :synced_params,
221
220
  :status) do
222
221
  def self.from_resource(resource, status)
223
- ResourceApplicationContext.new(resource.retrieve_resource.to_hash,
222
+ ResourceApplicationContext.new(resource,
223
+ resource.retrieve_resource.to_hash,
224
224
  Puppet::Util::Storage.cache(resource).dup,
225
225
  (resource[:audit] || []).map { |p| p.to_sym },
226
226
  [],
@@ -228,7 +228,7 @@ class Puppet::Transaction::ResourceHarness
228
228
  end
229
229
 
230
230
  def resource_present?
231
- current_values[:ensure] != :absent
231
+ resource.present?(current_values)
232
232
  end
233
233
 
234
234
  def record(event)
@@ -1065,6 +1065,13 @@ class Type
1065
1065
  resource
1066
1066
  end
1067
1067
 
1068
+ # Given the hash of current properties, should this resource be treated as if it
1069
+ # currently exists on the system. May need to be overridden by types that offer up
1070
+ # more than just :absent and :present.
1071
+ def present?(current_values)
1072
+ current_values[:ensure] != :absent
1073
+ end
1074
+
1068
1075
  # Returns a hash of the current properties and their values.
1069
1076
  # If a resource is absent, its value is the symbol `:absent`
1070
1077
  # @return [Hash{Puppet::Property => Object}] mapping of property instance to its value
@@ -1228,21 +1235,24 @@ class Type
1228
1235
  end
1229
1236
 
1230
1237
  newmetaparam(:schedule) do
1231
- desc "On what schedule the object should be managed. You must create a
1232
- schedule object, and then reference the name of that object to use
1233
- that for your schedule:
1234
-
1235
- schedule { 'daily':
1238
+ desc "A schedule to govern when Puppet is allowed to manage this resource.
1239
+ The value of this metaparameter must be the `name` of a `schedule`
1240
+ resource. This means you must declare a schedule resource, then
1241
+ refer to it by name; see
1242
+ [the docs for the `schedule` type](http://docs.puppetlabs.com/references/latest/type.html#schedule)
1243
+ for more info.
1244
+
1245
+ schedule { 'everyday':
1236
1246
  period => daily,
1237
1247
  range => \"2-4\"
1238
1248
  }
1239
1249
 
1240
1250
  exec { \"/usr/bin/apt-get update\":
1241
- schedule => 'daily'
1251
+ schedule => 'everyday'
1242
1252
  }
1243
1253
 
1244
- The creation of the schedule object does not need to appear in the
1245
- configuration before objects that use it."
1254
+ Note that you can declare the schedule resource anywhere in your
1255
+ manifests, as long as it ends up in the final compiled catalog."
1246
1256
  end
1247
1257
 
1248
1258
  newmetaparam(:audit) do
@@ -1392,12 +1402,9 @@ class Type
1392
1402
  }
1393
1403
 
1394
1404
  Tags are useful for things like applying a subset of a host's configuration
1395
- with [the `tags` setting](/references/latest/configuration.html#tags):
1396
-
1397
- puppet agent --test --tags bootstrap
1398
-
1399
- This way, you can easily isolate the portion of the configuration you're
1400
- trying to test."
1405
+ with [the `tags` setting](/references/latest/configuration.html#tags)
1406
+ (e.g. `puppet agent --test --tags bootstrap`) or filtering alerts with
1407
+ [the `tagmail` report processor](http://docs.puppetlabs.com/references/latest/report.html#tagmail)."
1401
1408
 
1402
1409
  munge do |tags|
1403
1410
  tags = [tags] unless tags.is_a? Array
@@ -1512,134 +1519,93 @@ class Type
1512
1519
  # solution, but it works.
1513
1520
 
1514
1521
  newmetaparam(:require, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :NONE}) do
1515
- desc "References to one or more objects that this object depends on.
1516
- This is used purely for guaranteeing that changes to required objects
1517
- happen before the dependent object. For instance:
1522
+ desc "One or more resources that this resource depends on, expressed as
1523
+ [resource references](http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#resource-references).
1524
+ Multiple resources can be specified as an array of references. When this
1525
+ attribute is present:
1518
1526
 
1519
- # Create the destination directory before you copy things down
1520
- file { \"/usr/local/scripts\":
1521
- ensure => directory
1522
- }
1527
+ * The required resource(s) will be applied **before** this resource.
1523
1528
 
1524
- file { \"/usr/local/scripts/myscript\":
1525
- source => \"puppet://server/module/myscript\",
1526
- mode => 755,
1527
- require => File[\"/usr/local/scripts\"]
1528
- }
1529
-
1530
- Multiple dependencies can be specified by providing a comma-separated list
1531
- of resources, enclosed in square brackets:
1532
-
1533
- require => [ File[\"/usr/local\"], File[\"/usr/local/scripts\"] ]
1534
-
1535
- Note that Puppet will autorequire everything that it can, and
1536
- there are hooks in place so that it's easy for resources to add new
1537
- ways to autorequire objects, so if you think Puppet could be
1538
- smarter here, let us know.
1539
-
1540
- In fact, the above code was redundant --- Puppet will autorequire
1541
- any parent directories that are being managed; it will
1542
- automatically realize that the parent directory should be created
1543
- before the script is pulled down.
1544
-
1545
- Currently, exec resources will autorequire their CWD (if it is
1546
- specified) plus any fully qualified paths that appear in the
1547
- command. For instance, if you had an `exec` command that ran
1548
- the `myscript` mentioned above, the above code that pulls the
1549
- file down would be automatically listed as a requirement to the
1550
- `exec` code, so that you would always be running againts the
1551
- most recent version.
1552
- "
1529
+ This is one of the four relationship metaparameters, along with
1530
+ `before`, `notify`, and `subscribe`. For more context, including the
1531
+ alternate chaining arrow (`->` and `~>`) syntax, see
1532
+ [the language page on relationships](http://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html)."
1553
1533
  end
1554
1534
 
1555
1535
  newmetaparam(:subscribe, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :ALL_EVENTS, :callback => :refresh}) do
1556
- desc "References to one or more objects that this object depends on. This
1557
- metaparameter creates a dependency relationship like **require,**
1558
- and also causes the dependent object to be refreshed when the
1559
- subscribed object is changed. For instance:
1560
-
1561
- class nagios {
1562
- file { 'nagconf':
1563
- path => \"/etc/nagios/nagios.conf\"
1564
- source => \"puppet://server/module/nagios.conf\",
1565
- }
1566
- service { 'nagios':
1567
- ensure => running,
1568
- subscribe => File['nagconf']
1569
- }
1570
- }
1536
+ desc "One or more resources that this resource depends on, expressed as
1537
+ [resource references](http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#resource-references).
1538
+ Multiple resources can be specified as an array of references. When this
1539
+ attribute is present:
1571
1540
 
1572
- Currently the `exec`, `mount` and `service` types support
1573
- refreshing.
1574
- "
1541
+ * The subscribed resource(s) will be applied _before_ this resource.
1542
+ * If Puppet makes changes to any of the subscribed resources, it will cause
1543
+ this resource to _refresh._ (Refresh behavior varies by resource
1544
+ type: services will restart, mounts will unmount and re-mount, etc. Not
1545
+ all types can refresh.)
1546
+
1547
+ This is one of the four relationship metaparameters, along with
1548
+ `before`, `require`, and `notify`. For more context, including the
1549
+ alternate chaining arrow (`->` and `~>`) syntax, see
1550
+ [the language page on relationships](http://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html)."
1575
1551
  end
1576
1552
 
1577
1553
  newmetaparam(:before, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :NONE}) do
1578
- desc %{References to one or more objects that depend on this object. This
1579
- parameter is the opposite of **require** --- it guarantees that
1580
- the specified object is applied later than the specifying object:
1581
-
1582
- file { "/var/nagios/configuration":
1583
- source => "...",
1584
- recurse => true,
1585
- before => Exec["nagios-rebuid"]
1586
- }
1554
+ desc "One or more resources that depend on this resource, expressed as
1555
+ [resource references](http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#resource-references).
1556
+ Multiple resources can be specified as an array of references. When this
1557
+ attribute is present:
1587
1558
 
1588
- exec { "nagios-rebuild":
1589
- command => "/usr/bin/make",
1590
- cwd => "/var/nagios/configuration"
1591
- }
1559
+ * This resource will be applied _before_ the dependent resource(s).
1592
1560
 
1593
- This will make sure all of the files are up to date before the
1594
- make command is run.}
1561
+ This is one of the four relationship metaparameters, along with
1562
+ `require`, `notify`, and `subscribe`. For more context, including the
1563
+ alternate chaining arrow (`->` and `~>`) syntax, see
1564
+ [the language page on relationships](http://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html)."
1595
1565
  end
1596
1566
 
1597
1567
  newmetaparam(:notify, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :ALL_EVENTS, :callback => :refresh}) do
1598
- desc %{References to one or more objects that depend on this object. This
1599
- parameter is the opposite of **subscribe** --- it creates a
1600
- dependency relationship like **before,** and also causes the
1601
- dependent object(s) to be refreshed when this object is changed. For
1602
- instance:
1603
-
1604
- file { "/etc/sshd_config":
1605
- source => "....",
1606
- notify => Service['sshd']
1607
- }
1568
+ desc "One or more resources that depend on this resource, expressed as
1569
+ [resource references](http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#resource-references).
1570
+ Multiple resources can be specified as an array of references. When this
1571
+ attribute is present:
1608
1572
 
1609
- service { 'sshd':
1610
- ensure => running
1611
- }
1573
+ * This resource will be applied _before_ the notified resource(s).
1574
+ * If Puppet makes changes to this resource, it will cause all of the
1575
+ notified resources to _refresh._ (Refresh behavior varies by resource
1576
+ type: services will restart, mounts will unmount and re-mount, etc. Not
1577
+ all types can refresh.)
1612
1578
 
1613
- This will restart the sshd service if the sshd config file changes.}
1579
+ This is one of the four relationship metaparameters, along with
1580
+ `before`, `require`, and `subscribe`. For more context, including the
1581
+ alternate chaining arrow (`->` and `~>`) syntax, see
1582
+ [the language page on relationships](http://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html)."
1614
1583
  end
1615
1584
 
1616
1585
  newmetaparam(:stage) do
1617
- desc %{Which run stage a given resource should reside in. This just creates
1618
- a dependency on or from the named milestone. For instance, saying that
1619
- this is in the 'bootstrap' stage creates a dependency on the 'bootstrap'
1620
- milestone.
1586
+ desc %{Which run stage this class should reside in.
1621
1587
 
1622
- By default, all classes get directly added to the
1623
- 'main' stage. You can create new stages as resources:
1588
+ **Note: This metaparameter can only be used on classes,** and only when
1589
+ declaring them with the resource-like syntax. It cannot be used on normal
1590
+ resources or on classes declared with `include`.
1624
1591
 
1625
- stage { ['pre', 'post']: }
1592
+ By default, all classes are declared in the `main` stage. To assign a class
1593
+ to a different stage, you must:
1626
1594
 
1627
- To order stages, use standard relationships:
1595
+ * Declare the new stage as a [`stage` resource](http://docs.puppetlabs.com/references/latest/type.html#stage).
1596
+ * Declare an order relationship between the new stage and the `main` stage.
1597
+ * Use the resource-like syntax to declare the class, and set the `stage`
1598
+ metaparameter to the name of the desired stage.
1628
1599
 
1629
- stage { 'pre': before => Stage['main'] }
1600
+ For example:
1630
1601
 
1631
- Or use the new relationship syntax:
1632
-
1633
- Stage['pre'] -> Stage['main'] -> Stage['post']
1634
-
1635
- Then use the new class parameters to specify a stage:
1636
-
1637
- class { 'foo': stage => 'pre' }
1638
-
1639
- Stages can only be set on classes, not individual resources. This will
1640
- fail:
1602
+ stage { 'pre':
1603
+ before => Stage['main'],
1604
+ }
1641
1605
 
1642
- file { '/foo': stage => 'pre', ensure => file }
1606
+ class { 'apt-updates':
1607
+ stage => 'pre',
1608
+ }
1643
1609
  }
1644
1610
  end
1645
1611
 
@@ -3,26 +3,48 @@ module Puppet
3
3
  include Puppet::Util::Execution
4
4
  require 'timeout'
5
5
 
6
- @doc = "Executes external commands. It is critical that all commands
7
- executed using this mechanism can be run multiple times without
8
- harm, i.e., they are *idempotent*. One useful way to create idempotent
9
- commands is to use the checks like `creates` to avoid running the
10
- command unless some condition is met.
11
-
12
- Note that you can restrict an `exec` to only run when it receives
13
- events by using the `refreshonly` parameter; this is a useful way to
14
- have your configuration respond to events with arbitrary commands.
15
-
16
- Note also that if an `exec` receives an event from another resource,
17
- it will get executed again (or execute the command specified in `refresh`, if there is one).
18
-
19
- There is a strong tendency to use `exec` to do whatever work Puppet
20
- can't already do; while this is obviously acceptable (and unavoidable)
21
- in the short term, it is highly recommended to migrate work from `exec`
22
- to native Puppet types as quickly as possible. If you find that
23
- you are doing a lot of work with `exec`, please at least notify
24
- us at Puppet Labs what you are doing, and hopefully we can work with
25
- you to get a native resource type for the work you are doing.
6
+ @doc = "Executes external commands.
7
+
8
+ Any command in an `exec` resource **must** be able to run multiple times
9
+ without causing harm --- that is, it must be *idempotent*. There are three
10
+ main ways for an exec to be idempotent:
11
+
12
+ * The command itself is already idempotent. (For example, `apt-get update`.)
13
+ * The exec has an `onlyif`, `unless`, or `creates` attribute, which prevents
14
+ Puppet from running the command unless some condition is met.
15
+ * The exec has `refreshonly => true`, which only allows Puppet to run the
16
+ command when some other resource is changed. (See the notes on refreshing
17
+ below.)
18
+
19
+ A caution: There's a widespread tendency to use collections of execs to
20
+ manage resources that aren't covered by an existing resource type. This
21
+ works fine for simple tasks, but once your exec pile gets complex enough
22
+ that you really have to think to understand what's happening, you should
23
+ consider developing a custom resource type instead, as it will be much
24
+ more predictable and maintainable.
25
+
26
+ **Refresh:** `exec` resources can respond to refresh events (via
27
+ `notify`, `subscribe`, or the `~>` arrow). The refresh behavior of execs
28
+ is non-standard, and can be affected by the `refresh` and
29
+ `refreshonly` attributes:
30
+
31
+ * If `refreshonly` is set to true, the exec will _only_ run when it receives an
32
+ event. This is the most reliable way to use refresh with execs.
33
+ * If the exec already would have run and receives an event, it will run its
34
+ command **up to two times.** (If an `onlyif`, `unless`, or `creates` condition
35
+ is no longer met after the first run, the second run will not occur.)
36
+ * If the exec already would have run, has a `refresh` command, and receives an
37
+ event, it will run its normal command, then run its `refresh` command
38
+ (as long as any `onlyif`, `unless`, or `creates` conditions are still met
39
+ after the normal command finishes).
40
+ * If the exec would **not** have run (due to an `onlyif`, `unless`, or `creates`
41
+ attribute) and receives an event, it still will not run.
42
+ * If the exec has `noop => true`, would otherwise have run, and receives
43
+ an event from a non-noop resource, it will run once (or run its `refresh`
44
+ command instead, if it has one).
45
+
46
+ In short: If there's a possibility of your exec receiving refresh events,
47
+ it becomes doubly important to make sure the run conditions are restricted.
26
48
 
27
49
  **Autorequires:** If Puppet is managing an exec's cwd or the executable
28
50
  file used in an exec's command, the exec resource will autorequire those