puppet 3.7.5-x64-mingw32 → 3.8.1-x64-mingw32

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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/ext/build_defaults.yaml +5 -5
  3. data/lib/hiera/puppet_function.rb +15 -4
  4. data/lib/puppet.rb +5 -2
  5. data/lib/puppet/application/agent.rb +5 -0
  6. data/lib/puppet/application/apply.rb +5 -0
  7. data/lib/puppet/application/device.rb +8 -3
  8. data/lib/puppet/application/master.rb +5 -0
  9. data/lib/puppet/defaults.rb +8 -0
  10. data/lib/puppet/error.rb +27 -1
  11. data/lib/puppet/file_system.rb +13 -0
  12. data/lib/puppet/file_system/file19windows.rb +8 -0
  13. data/lib/puppet/file_system/file_impl.rb +4 -0
  14. data/lib/puppet/file_system/memory_impl.rb +4 -0
  15. data/lib/puppet/functions.rb +25 -3
  16. data/lib/puppet/functions/defined.rb +130 -0
  17. data/lib/puppet/functions/hiera_include.rb +1 -1
  18. data/lib/puppet/node/environment.rb +4 -0
  19. data/lib/puppet/parser/compiler.rb +5 -2
  20. data/lib/puppet/parser/functions/defined.rb +26 -1
  21. data/lib/puppet/parser/functions/file.rb +3 -1
  22. data/lib/puppet/parser/templatewrapper.rb +2 -1
  23. data/lib/puppet/pops.rb +5 -0
  24. data/lib/puppet/pops/evaluator/access_operator.rb +25 -5
  25. data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -11
  26. data/lib/puppet/pops/evaluator/compare_operator.rb +43 -0
  27. data/lib/puppet/pops/evaluator/evaluator_impl.rb +43 -28
  28. data/lib/puppet/pops/evaluator/runtime3_support.rb +9 -5
  29. data/lib/puppet/pops/functions/dispatch.rb +6 -1
  30. data/lib/puppet/pops/issue_reporter.rb +42 -16
  31. data/lib/puppet/pops/issues.rb +96 -0
  32. data/lib/puppet/pops/loader/module_loaders.rb +3 -1
  33. data/lib/puppet/pops/loaders.rb +6 -4
  34. data/lib/puppet/pops/migration/migration_checker.rb +45 -0
  35. data/lib/puppet/pops/model/factory.rb +1 -1
  36. data/lib/puppet/pops/model/model_meta.rb +1 -1
  37. data/lib/puppet/pops/parser/egrammar.ra +1 -1
  38. data/lib/puppet/pops/parser/eparser.rb +1 -1
  39. data/lib/puppet/pops/parser/epp_support.rb +18 -9
  40. data/lib/puppet/pops/parser/evaluating_parser.rb +7 -1
  41. data/lib/puppet/pops/parser/heredoc_support.rb +12 -11
  42. data/lib/puppet/pops/parser/interpolation_support.rb +7 -1
  43. data/lib/puppet/pops/parser/lexer2.rb +8 -8
  44. data/lib/puppet/pops/parser/lexer_support.rb +46 -20
  45. data/lib/puppet/pops/parser/parser_support.rb +11 -14
  46. data/lib/puppet/pops/parser/slurp_support.rb +22 -6
  47. data/lib/puppet/pops/types/type_calculator.rb +156 -55
  48. data/lib/puppet/pops/types/type_factory.rb +67 -14
  49. data/lib/puppet/pops/types/type_parser.rb +22 -13
  50. data/lib/puppet/pops/types/types.rb +21 -3
  51. data/lib/puppet/pops/types/types_meta.rb +13 -2
  52. data/lib/puppet/pops/validation.rb +25 -2
  53. data/lib/puppet/pops/validation/checker4_0.rb +25 -5
  54. data/lib/puppet/provider/group/windows_adsi.rb +18 -6
  55. data/lib/puppet/provider/mount/parsed.rb +145 -2
  56. data/lib/puppet/provider/package/pip.rb +4 -5
  57. data/lib/puppet/provider/package/zypper.rb +17 -7
  58. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +35 -10
  59. data/lib/puppet/provider/service/init.rb +7 -0
  60. data/lib/puppet/provider/user/windows_adsi.rb +8 -1
  61. data/lib/puppet/provider/zpool/zpool.rb +7 -2
  62. data/lib/puppet/resource.rb +1 -1
  63. data/lib/puppet/type/group.rb +1 -1
  64. data/lib/puppet/type/mount.rb +14 -3
  65. data/lib/puppet/type/scheduled_task.rb +21 -6
  66. data/lib/puppet/util/log.rb +50 -8
  67. data/lib/puppet/util/log/destinations.rb +23 -2
  68. data/lib/puppet/util/logging.rb +37 -1
  69. data/lib/puppet/util/windows/adsi.rb +36 -11
  70. data/lib/puppet/version.rb +1 -1
  71. data/spec/fixtures/unit/provider/mount/parsed/aix.filesystems +93 -85
  72. data/spec/fixtures/unit/provider/mount/parsed/aix.mount +11 -7
  73. data/spec/integration/parser/collector_spec.rb +7 -0
  74. data/spec/integration/parser/future_compiler_spec.rb +9 -0
  75. data/spec/integration/parser/resource_expressions_spec.rb +3 -0
  76. data/spec/unit/file_system_spec.rb +38 -0
  77. data/spec/unit/functions/defined_spec.rb +291 -0
  78. data/spec/unit/functions/hiera_spec.rb +8 -6
  79. data/spec/unit/functions4_spec.rb +97 -2
  80. data/spec/unit/parser/functions/file_spec.rb +8 -2
  81. data/spec/unit/parser/functions/template_spec.rb +1 -1
  82. data/spec/unit/parser/templatewrapper_spec.rb +1 -1
  83. data/spec/unit/pops/evaluator/access_ops_spec.rb +19 -0
  84. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +61 -8
  85. data/spec/unit/pops/issues_spec.rb +16 -16
  86. data/spec/unit/pops/loaders/module_loaders_spec.rb +5 -0
  87. data/spec/unit/pops/migration_spec.rb +180 -0
  88. data/spec/unit/pops/parser/lexer2_spec.rb +152 -1
  89. data/spec/unit/pops/parser/parse_heredoc_spec.rb +26 -0
  90. data/spec/unit/pops/transformer/transform_calls_spec.rb +1 -1
  91. data/spec/unit/pops/types/type_calculator_spec.rb +204 -11
  92. data/spec/unit/pops/validation_spec.rb +66 -0
  93. data/spec/unit/provider/group/windows_adsi_spec.rb +65 -1
  94. data/spec/unit/provider/mount/parsed_spec.rb +31 -5
  95. data/spec/unit/provider/package/pip_spec.rb +19 -7
  96. data/spec/unit/provider/package/zypper_spec.rb +25 -14
  97. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +312 -70
  98. data/spec/unit/provider/service/base_spec.rb +42 -31
  99. data/spec/unit/provider/service/freebsd_spec.rb +1 -0
  100. data/spec/unit/provider/service/gentoo_spec.rb +1 -0
  101. data/spec/unit/provider/service/init_spec.rb +18 -0
  102. data/spec/unit/provider/service/openbsd_spec.rb +1 -0
  103. data/spec/unit/provider/service/redhat_spec.rb +1 -0
  104. data/spec/unit/provider/user/windows_adsi_spec.rb +21 -0
  105. data/spec/unit/provider/zpool/zpool_spec.rb +47 -10
  106. data/spec/unit/util/log_spec.rb +113 -0
  107. data/spec/unit/util/windows/adsi_spec.rb +106 -26
  108. metadata +10 -2
@@ -36,11 +36,10 @@ Puppet::Type.type(:package).provide :pip,
36
36
  end
37
37
 
38
38
  def self.cmd
39
- case Facter.value(:osfamily)
40
- when "RedHat"
41
- "pip-python"
42
- else
43
- "pip"
39
+ if Facter.value(:osfamily) == "RedHat" and Facter.value(:operatingsystemmajrelease).to_i < 7
40
+ "pip-python"
41
+ else
42
+ "pip"
44
43
  end
45
44
  end
46
45
 
@@ -34,10 +34,9 @@ Puppet::Type.type(:package).provide :zypper, :parent => :rpm do
34
34
  end
35
35
 
36
36
  #This has been tested with following zypper versions
37
- #SLE 10.2: 0.6.104
38
- #SLE 11.0: 1.0.8
39
- #OpenSuse 10.2: 0.6.13
40
- #OpenSuse 11.2: 1.2.8
37
+ #SLE 10.4: 0.6.201
38
+ #SLE 11.3: 1.6.307
39
+ #SLE 12.0: 1.11.14
41
40
  #Assume that this will work on newer zypper versions
42
41
 
43
42
  #extract version numbers and convert to integers
@@ -51,13 +50,24 @@ Puppet::Type.type(:package).provide :zypper, :parent => :rpm do
51
50
  quiet = '--quiet'
52
51
  end
53
52
 
54
- options = [quiet, :install]
53
+ inst_opts = []
54
+ inst_opts = install_options if resource[:install_options]
55
+
56
+
57
+ options = []
58
+ options << quiet
59
+ options << '--no-gpg-check' unless inst_opts.delete('--no-gpg-check').nil?
60
+ options << :install
55
61
 
56
62
  #zypper 0.6.13 (OpenSuSE 10.2) does not support auto agree with licenses
57
63
  options << '--auto-agree-with-licenses' unless major < 1 and minor <= 6 and patch <= 13
58
64
  options << '--no-confirm'
59
- options << '--name' unless @resource.allow_virtual? || should
60
- options += install_options if resource[:install_options]
65
+ options += inst_opts unless inst_opts.empty?
66
+
67
+ # Zypper 0.6.201 doesn't recognize '--name'
68
+ # It is unclear where this functionality was introduced, but it
69
+ # is present as early as 1.0.13
70
+ options << '--name' unless major < 1 || @resource.allow_virtual? || should
61
71
  options << wanted
62
72
 
63
73
  zypper *options
@@ -10,6 +10,8 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
10
10
  defaultfor :operatingsystem => :windows
11
11
  confine :operatingsystem => :windows
12
12
 
13
+ MINUTES_IN_DAY = 1440
14
+
13
15
  def self.instances
14
16
  Win32::TaskScheduler.new.tasks.collect do |job_file|
15
17
  job_title = File.basename(job_file, '.job')
@@ -76,16 +78,15 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
76
78
  nil
77
79
  end
78
80
  next unless trigger and scheduler_trigger_types.include?(trigger['trigger_type'])
79
-
80
81
  puppet_trigger = {}
81
82
  case trigger['trigger_type']
82
83
  when Win32::TaskScheduler::TASK_TIME_TRIGGER_DAILY
83
84
  puppet_trigger['schedule'] = 'daily'
84
85
  puppet_trigger['every'] = trigger['type']['days_interval'].to_s
85
86
  when Win32::TaskScheduler::TASK_TIME_TRIGGER_WEEKLY
86
- puppet_trigger['schedule'] = 'weekly'
87
- puppet_trigger['every'] = trigger['type']['weeks_interval'].to_s
88
- puppet_trigger['on'] = days_of_week_from_bitfield(trigger['type']['days_of_week'])
87
+ puppet_trigger['schedule'] = 'weekly'
88
+ puppet_trigger['every'] = trigger['type']['weeks_interval'].to_s
89
+ puppet_trigger['day_of_week'] = days_of_week_from_bitfield(trigger['type']['days_of_week'])
89
90
  when Win32::TaskScheduler::TASK_TIME_TRIGGER_MONTHLYDATE
90
91
  puppet_trigger['schedule'] = 'monthly'
91
92
  puppet_trigger['months'] = months_from_bitfield(trigger['type']['months'])
@@ -101,6 +102,8 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
101
102
  puppet_trigger['start_date'] = self.class.normalized_date("#{trigger['start_year']}-#{trigger['start_month']}-#{trigger['start_day']}")
102
103
  puppet_trigger['start_time'] = self.class.normalized_time("#{trigger['start_hour']}:#{trigger['start_minute']}")
103
104
  puppet_trigger['enabled'] = trigger['flags'] & Win32::TaskScheduler::TASK_TRIGGER_FLAG_DISABLED == 0
105
+ puppet_trigger['minutes_interval'] = trigger['minutes_interval'] ||= 0
106
+ puppet_trigger['minutes_duration'] = trigger['minutes_duration'] ||= 0
104
107
  puppet_trigger['index'] = i
105
108
 
106
109
  @triggers << puppet_trigger
@@ -209,7 +212,6 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
209
212
  def create
210
213
  clear_task
211
214
  @task = Win32::TaskScheduler.new(resource[:name], dummy_time_trigger)
212
-
213
215
  self.command = resource[:command]
214
216
 
215
217
  [:arguments, :working_dir, :enabled, :trigger, :user].each do |prop|
@@ -258,10 +260,10 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
258
260
  'flags' => 0,
259
261
  'random_minutes_interval' => 0,
260
262
  'end_day' => 0,
261
- "end_year" => 0,
262
- "minutes_interval" => 0,
263
- "end_month" => 0,
264
- "minutes_duration" => 0,
263
+ 'end_year' => 0,
264
+ 'minutes_interval' => 0,
265
+ 'end_month' => 0,
266
+ 'minutes_duration' => 0,
265
267
  'start_year' => now.year,
266
268
  'start_month' => now.month,
267
269
  'start_day' => now.day,
@@ -280,7 +282,7 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
280
282
  trigger['flags'] &= ~Win32::TaskScheduler::TASK_TRIGGER_FLAG_DISABLED
281
283
  end
282
284
 
283
- extra_keys = puppet_trigger.keys.sort - ['index', 'enabled', 'schedule', 'start_date', 'start_time', 'every', 'months', 'on', 'which_occurrence', 'day_of_week']
285
+ extra_keys = puppet_trigger.keys.sort - ['index', 'enabled', 'schedule', 'start_date', 'start_time', 'every', 'months', 'on', 'which_occurrence', 'day_of_week', 'minutes_interval', 'minutes_duration']
284
286
  self.fail "Unknown trigger option(s): #{Puppet::Parameter.format_value_for_display(extra_keys)}" unless extra_keys.empty?
285
287
  self.fail "Must specify 'start_time' when defining a trigger" unless puppet_trigger['start_time']
286
288
 
@@ -333,6 +335,29 @@ Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
333
335
  self.fail "Unknown schedule type: #{puppet_trigger["schedule"].inspect}"
334
336
  end
335
337
 
338
+ integer_interval = -1
339
+ if puppet_trigger['minutes_interval']
340
+ integer_interval = Integer(puppet_trigger['minutes_interval'])
341
+ self.fail 'minutes_interval must be an integer greater or equal to 0' if integer_interval < 0
342
+ trigger['minutes_interval'] = integer_interval
343
+ end
344
+
345
+ integer_duration = -1
346
+ if puppet_trigger['minutes_duration']
347
+ integer_duration = Integer(puppet_trigger['minutes_duration'])
348
+ self.fail 'minutes_duration must be an integer greater than minutes_interval and equal to or greater than 0' if integer_duration <= integer_interval && integer_duration != 0
349
+ trigger['minutes_duration'] = integer_duration
350
+ end
351
+
352
+ if integer_interval > 0 && integer_duration == -1
353
+ integer_duration = MINUTES_IN_DAY
354
+ trigger['minutes_duration'] = MINUTES_IN_DAY
355
+ end
356
+
357
+ if integer_interval >= integer_duration && integer_interval > 0
358
+ self.fail 'minutes_interval cannot be set without minutes_duration also being set to a number greater than 0'
359
+ end
360
+
336
361
  if start_date = puppet_trigger['start_date']
337
362
  start_date = Date.parse(start_date)
338
363
  self.fail "start_date must be on or after 1753-01-01" unless start_date >= Date.new(1753, 1, 1)
@@ -152,6 +152,13 @@ Puppet::Type.type(:service).provide :init, :parent => :base do
152
152
  (@resource[:hasrestart] == :true) && [initscript, :restart]
153
153
  end
154
154
 
155
+ def texecute(type, command, fof = true, squelch = false, combine = true)
156
+ if type == :start && Facter.value(:osfamily) == "Solaris"
157
+ command = ["/usr/bin/ctrun -l none", command].flatten.join(" ")
158
+ end
159
+ super(type, command, fof, squelch, combine)
160
+ end
161
+
155
162
  # If it was specified that the init script has a 'status' command, then
156
163
  # we just return that; otherwise, we return false, which causes it to
157
164
  # fallback to other mechanisms.
@@ -8,6 +8,11 @@ Puppet::Type.type(:user).provide :windows_adsi do
8
8
 
9
9
  has_features :manages_homedir, :manages_passwords
10
10
 
11
+ def initialize(value={})
12
+ super(value)
13
+ @deleted = false
14
+ end
15
+
11
16
  def user
12
17
  @user ||= Puppet::Util::Windows::ADSI::User.new(@resource[:name])
13
18
  end
@@ -47,11 +52,13 @@ Puppet::Type.type(:user).provide :windows_adsi do
47
52
  if sid
48
53
  Puppet::Util::Windows::ADSI::UserProfile.delete(sid)
49
54
  end
55
+
56
+ @deleted = true
50
57
  end
51
58
 
52
59
  # Only flush if we created or modified a user, not deleted
53
60
  def flush
54
- @user.commit if @user
61
+ @user.commit if @user && !@deleted
55
62
  end
56
63
 
57
64
  def comment
@@ -79,14 +79,19 @@ Puppet::Type.type(:zpool).provide(:zpool) do
79
79
  @resource[:raid_parity] ? @resource[:raid_parity] : "raidz1"
80
80
  end
81
81
 
82
+ #handle mirror or raid
83
+ def handle_multi_arrays(prefix, array)
84
+ array.collect{ |a| [prefix] + a.split(' ') }.flatten
85
+ end
86
+
82
87
  #builds up the vdevs for create command
83
88
  def build_vdevs
84
89
  if disk = @resource[:disk]
85
90
  disk.collect { |d| d.split(' ') }.flatten
86
91
  elsif mirror = @resource[:mirror]
87
- ["mirror"] + mirror
92
+ handle_multi_arrays("mirror", mirror)
88
93
  elsif raidz = @resource[:raidz]
89
- [raidzarity] + raidz
94
+ handle_multi_arrays(raidzarity, raidz)
90
95
  end
91
96
  end
92
97
 
@@ -488,7 +488,7 @@ class Puppet::Resource
488
488
  parameters.each do |name, value|
489
489
  next unless t = arg_types[name.to_s] # untyped, and parameters are symbols here (aargh, strings in the type)
490
490
  unless Puppet::Pops::Types::TypeCalculator.instance?(t, value.value)
491
- inferred_type = Puppet::Pops::Types::TypeCalculator.infer(value.value)
491
+ inferred_type = Puppet::Pops::Types::TypeCalculator.infer_set(value.value)
492
492
  actual = Puppet::Pops::Types::TypeCalculator.generalize!(inferred_type)
493
493
  fail Puppet::ParseError, "Expected parameter '#{name}' of '#{self}' to have type #{t.to_s}, got #{actual.to_s}"
494
494
  end
@@ -107,7 +107,7 @@ module Puppet
107
107
  alias :should_to_s :is_to_s
108
108
  end
109
109
 
110
- newparam(:auth_membership) do
110
+ newparam(:auth_membership, :boolean => true, :parent => Puppet::Parameter::Boolean) do
111
111
  desc "whether the provider is authoritative for group membership."
112
112
  defaultto true
113
113
  end
@@ -168,8 +168,11 @@ module Puppet
168
168
  end
169
169
 
170
170
  newproperty(:options) do
171
- desc "Mount options for the mounts, as they would
172
- appear in the fstab."
171
+ desc "Mount options for the mounts, comma-separated as they would appear
172
+ in the fstab on Linux. AIX options other than dev, nodename, or vfs may
173
+ be defined here. If specified, AIX options of account, boot, check, free,
174
+ mount, size, type, vol, log, and quota must be alphabetically sorted at
175
+ the end of the list."
173
176
 
174
177
  validate do |value|
175
178
  raise Puppet::Error, "option must not contain whitespace: #{value}" if value =~ /\s/
@@ -253,8 +256,16 @@ module Puppet
253
256
  newvalues(:true, :false)
254
257
  defaultto do
255
258
  case Facter.value(:operatingsystem)
256
- when "FreeBSD", "Darwin", "AIX", "DragonFly", "OpenBSD"
259
+ when "FreeBSD", "Darwin", "DragonFly", "OpenBSD"
257
260
  false
261
+ when "AIX"
262
+ if Facter.value(:kernelmajversion) == "5300"
263
+ false
264
+ elsif resource[:device] and resource[:device].match(%r{^[^/]+:/})
265
+ false
266
+ else
267
+ true
268
+ end
258
269
  else
259
270
  true
260
271
  end
@@ -92,30 +92,35 @@ Puppet::Type.newtype(:scheduled_task) do
92
92
  A trigger can contain the following keys:
93
93
 
94
94
  * For all triggers:
95
- * `schedule` **(Required)** --- The schedule type. Valid values are
96
- `daily`, `weekly`, `monthly`, or `once`.
95
+ * `schedule` **(Required)** --- What kind of trigger this is.
96
+ Valid values are `daily`, `weekly`, `monthly`, or `once`. Each kind
97
+ of trigger is configured with a different set of keys; see the
98
+ sections below. (`once` triggers only need a start time/date.)
97
99
  * `start_time` **(Required)** --- The time of day when the trigger should
98
100
  first become active. Several time formats will work, but we
99
101
  suggest 24-hour time formatted as HH:MM.
100
102
  * `start_date` --- The date when the trigger should first become active.
101
103
  Defaults to the current date. You should format dates as YYYY-MM-DD,
102
104
  although other date formats may work. (Under the hood, this uses `Date.parse`.)
103
- * For daily triggers:
105
+ * `minutes_interval` --- The repeat interval in minutes.
106
+ * `minutes_duration` --- The duration in minutes, needs to be greater than the
107
+ minutes_interval.
108
+ * For `daily` triggers:
104
109
  * `every` --- How often the task should run, as a number of days. Defaults
105
110
  to 1. ("2" means every other day, "3" means every three days, etc.)
106
- * For weekly triggers:
111
+ * For `weekly` triggers:
107
112
  * `every` --- How often the task should run, as a number of weeks. Defaults
108
113
  to 1. ("2" means every other week, "3" means every three weeks, etc.)
109
114
  * `day_of_week` --- Which days of the week the task should run, as an array.
110
115
  Defaults to all days. Each day must be one of `mon`, `tues`,
111
116
  `wed`, `thurs`, `fri`, `sat`, `sun`, or `all`.
112
- * For monthly-by-date triggers:
117
+ * For `monthly` (by date) triggers:
113
118
  * `months` --- Which months the task should run, as an array. Defaults to
114
119
  all months. Each month must be an integer between 1 and 12.
115
120
  * `on` **(Required)** --- Which days of the month the task should run,
116
121
  as an array. Each day must beeither an integer between 1 and 31,
117
122
  or the special value `last,` which is always the last day of the month.
118
- * For monthly-by-weekday triggers:
123
+ * For `monthly` (by weekday) triggers:
119
124
  * `months` --- Which months the task should run, as an array. Defaults to
120
125
  all months. Each month must be an integer between 1 and 12.
121
126
  * `day_of_week` **(Required)** --- Which day of the week the task should
@@ -125,6 +130,7 @@ Puppet::Type.newtype(:scheduled_task) do
125
130
  when the task should run. Must be one of `first`, `second`, `third`,
126
131
  `fourth`, `fifth`, or `last`.
127
132
 
133
+
128
134
  Examples:
129
135
 
130
136
  # Run at 8am on the 1st, 15th, and last day of the month in January, March,
@@ -148,6 +154,15 @@ Puppet::Type.newtype(:scheduled_task) do
148
154
  day_of_week => [mon], # Must be specified
149
155
  }
150
156
 
157
+ # Run daily repeating every 30 minutes between 9am and 5pm (480 minutes) starting after August 31st, 2011.
158
+ trigger => {
159
+ schedule => daily,
160
+ start_date => '2011-08-31', # Defaults to current date
161
+ start_time => '8:00', # Must be specified
162
+ minutes_interval => 30,
163
+ minutes_duration => 480,
164
+ }
165
+
151
166
  EOT
152
167
 
153
168
  validate do |value|
@@ -244,7 +244,7 @@ class Puppet::Util::Log
244
244
  self.from_data_hash(data)
245
245
  end
246
246
 
247
- attr_accessor :time, :remote, :file, :line, :source
247
+ attr_accessor :time, :remote, :file, :line, :pos, :source, :issue_code, :environment, :node, :backtrace
248
248
  attr_reader :level, :message
249
249
 
250
250
  def initialize(args)
@@ -258,9 +258,10 @@ class Puppet::Util::Log
258
258
  tags.each { |t| self.tag(t) }
259
259
  end
260
260
 
261
- [:file, :line].each do |attr|
261
+ # Don't add these unless defined (preserve 3.x API as much as possible)
262
+ [:file, :line, :pos, :issue_code, :environment, :node, :backtrace].each do |attr|
262
263
  next unless value = args[attr]
263
- send(attr.to_s + "=", value)
264
+ send(attr.to_s + '=', value)
264
265
  end
265
266
 
266
267
  Log.newmessage(self)
@@ -275,8 +276,11 @@ class Puppet::Util::Log
275
276
  if @time.is_a? String
276
277
  @time = Time.parse(@time)
277
278
  end
278
- @file = data['file'] if data['file']
279
- @line = data['line'] if data['line']
279
+ # Don't add these unless defined (preserve 3.x API as much as possible)
280
+ %w(file line pos issue_code environment node backtrace).each do |name|
281
+ next unless value = data[name]
282
+ send(name + '=', value)
283
+ end
280
284
  end
281
285
 
282
286
  def to_hash
@@ -286,15 +290,30 @@ class Puppet::Util::Log
286
290
  def to_data_hash
287
291
  {
288
292
  'level' => @level,
289
- 'message' => @message,
293
+ 'message' => to_s,
290
294
  'source' => @source,
291
- 'tags' => @tags,
295
+ 'tags' => @tags.to_a,
292
296
  'time' => @time.iso8601(9),
293
297
  'file' => @file,
294
298
  'line' => @line,
295
299
  }
296
300
  end
297
301
 
302
+ def to_structured_hash
303
+ hash = {
304
+ 'level' => @level,
305
+ 'message' => @message,
306
+ 'source' => @source,
307
+ 'tags' => @tags.to_a,
308
+ 'time' => @time.iso8601(9),
309
+ }
310
+ %w(file line pos issue_code environment node backtrace).each do |name|
311
+ attr_name = "@#{name}"
312
+ hash[name] = instance_variable_get(attr_name) if instance_variable_defined?(attr_name)
313
+ end
314
+ hash
315
+ end
316
+
298
317
  def to_pson(*args)
299
318
  to_data_hash.to_pson(*args)
300
319
  end
@@ -332,7 +351,30 @@ class Puppet::Util::Log
332
351
  end
333
352
 
334
353
  def to_s
335
- message
354
+ msg = message
355
+
356
+ # Issue based messages do not have details in the message. It
357
+ # must be appended here
358
+ unless issue_code.nil?
359
+ msg = "Could not parse for environment #{environment}: #{msg}" unless environment.nil?
360
+ if file && line && pos
361
+ msg = "#{msg} at #{file}:#{line}:#{pos}"
362
+ elsif file and line
363
+ msg = "#{msg} at #{file}:#{line}"
364
+ elsif line && pos
365
+ msg = "#{msg} at line #{line}:#{pos}"
366
+ elsif line
367
+ msg = "#{msg} at line #{line}"
368
+ elsif file
369
+ msg = "#{msg} in #{file}"
370
+ end
371
+ msg = "#{msg} on node #{node}" unless node.nil?
372
+ if @backtrace.is_a?(Array)
373
+ msg += "\n"
374
+ msg += @backtrace.join("\n")
375
+ end
376
+ end
377
+ msg
336
378
  end
337
379
 
338
380
  end
@@ -65,6 +65,8 @@ Puppet::Util::Log.newdesttype :file do
65
65
 
66
66
  def initialize(path)
67
67
  @name = path
68
+ @json = path.end_with?('.json') ? 1 : 0
69
+
68
70
  # first make sure the directory exists
69
71
  # We can't just use 'Config.use' here, because they've
70
72
  # specified a "special" destination.
@@ -74,7 +76,21 @@ Puppet::Util::Log.newdesttype :file do
74
76
  end
75
77
 
76
78
  # create the log file, if it doesn't already exist
77
- file = File.open(path, File::WRONLY|File::CREAT|File::APPEND)
79
+ need_array_start = false
80
+ if @json == 1
81
+ need_array_start = true
82
+ if File.exists?(path)
83
+ sz = File.size(path)
84
+ need_array_start = sz == 0
85
+
86
+ # Assume that entries have been written and that a comma
87
+ # is needed before next entry
88
+ @json = 2 if sz > 2
89
+ end
90
+ end
91
+
92
+ file = File.open(path, File::WRONLY|File::CREAT|File::APPEND)
93
+ file.puts('[') if need_array_start
78
94
 
79
95
  # Give ownership to the user and group puppet will run as
80
96
  begin
@@ -89,7 +105,12 @@ Puppet::Util::Log.newdesttype :file do
89
105
  end
90
106
 
91
107
  def handle(msg)
92
- @file.puts("#{msg.time} #{msg.source} (#{msg.level}): #{msg}")
108
+ if @json > 0
109
+ @json > 1 ? @file.puts(',') : @json = 2
110
+ JSON.dump(msg.to_structured_hash, @file)
111
+ else
112
+ @file.puts("#{msg.time} #{msg.source} (#{msg.level}): #{msg}")
113
+ end
93
114
 
94
115
  @file.flush if @autoflush
95
116
  end