summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasu1105 <vasundhara.jagdale@msystechnologies.com>2018-01-31 11:47:09 +0000
committervasu1105 <vasundhara.jagdale@msystechnologies.com>2018-04-24 11:32:31 +0530
commit2c665b3e889381062b2faf1f28d4a41ca1a698cb (patch)
tree2d8e1fdc98a9d267c6fa403732d421e6feb6d684
parent5ef14cc77226fe16b734ec90aead1de5d49ca7fb (diff)
downloadchef-2c665b3e889381062b2faf1f28d4a41ca1a698cb.tar.gz
[MSYS-752] windows task rewrite using wind32-taskscheduler
Signed-off-by: Vasu1105 <vasundhara.jagdale@msystechnologies.com>
-rw-r--r--Gemfile.lock5
-rw-r--r--chef-universal-mingw32.gemspec1
-rw-r--r--lib/chef/provider/windows_task.rb927
-rw-r--r--lib/chef/resource/windows_task.rb180
-rw-r--r--spec/functional/resource/windows_task_spec.rb1027
-rw-r--r--spec/unit/provider/windows_task_spec.rb861
-rw-r--r--spec/unit/resource/windows_task_spec.rb88
7 files changed, 1786 insertions, 1303 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index aa7ac2e51a..854d91aabb 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -84,6 +84,7 @@ PATH
win32-mutex (~> 0.4.2)
win32-process (~> 0.8.2)
win32-service (~> 0.8.7)
+ win32-taskscheduler (~> 0.4.0)
windows-api (~> 0.4.4)
wmi-lite (~> 1.0)
@@ -343,6 +344,7 @@ GEM
net-telnet
sfl
sslshake (1.2.0)
+ structured_warnings (0.3.0)
syslog-logger (1.6.8)
systemu (2.6.5)
thor (0.20.0)
@@ -397,6 +399,9 @@ GEM
win32-service (0.8.10)
ffi
ffi-win32-extensions
+ win32-taskscheduler (0.4.0)
+ ffi
+ structured_warnings
windows-api (0.4.4)
win32-api (>= 1.4.5)
winrm (2.2.3)
diff --git a/chef-universal-mingw32.gemspec b/chef-universal-mingw32.gemspec
index 449f909bb2..ea65edbbd6 100644
--- a/chef-universal-mingw32.gemspec
+++ b/chef-universal-mingw32.gemspec
@@ -15,6 +15,7 @@ gemspec.add_dependency "win32-process", "~> 0.8.2"
gemspec.add_dependency "win32-service", "~> 0.8.7"
gemspec.add_dependency "windows-api", "~> 0.4.4"
gemspec.add_dependency "wmi-lite", "~> 1.0"
+gemspec.add_dependency "win32-taskscheduler", "~> 0.4.0"
gemspec.extensions << "ext/win32-eventlog/Rakefile"
gemspec.files += %w{ext/win32-eventlog/Rakefile ext/win32-eventlog/chef-log.man}
diff --git a/lib/chef/provider/windows_task.rb b/lib/chef/provider/windows_task.rb
index 02b68b1296..56c031d163 100644
--- a/lib/chef/provider/windows_task.rb
+++ b/lib/chef/provider/windows_task.rb
@@ -20,6 +20,8 @@ require "chef/mixin/shell_out"
require "rexml/document"
require "iso8601"
require "chef/mixin/powershell_out"
+require "chef/provider"
+require "win32/taskscheduler" if Chef::Platform.windows?
class Chef
class Provider
@@ -27,542 +29,559 @@ class Chef
include Chef::Mixin::ShellOut
include Chef::Mixin::PowershellOut
- provides :windows_task
-
- def load_current_resource
- self.current_resource = Chef::Resource::WindowsTask.new(new_resource.name)
- pathed_task_name = new_resource.task_name.start_with?('\\') ? new_resource.task_name : "\\#{new_resource.task_name}"
-
- current_resource.task_name(pathed_task_name)
- task_hash = load_task_hash(pathed_task_name)
-
- set_current_resource(task_hash) if task_hash.respond_to?(:[]) && task_hash[:TaskName] == pathed_task_name
- current_resource
- end
-
- def set_current_resource(task_hash)
- current_resource.exists = true
- current_resource.command(task_hash[:TaskToRun])
- current_resource.cwd(task_hash[:StartIn]) unless task_hash[:StartIn] == "N/A"
- current_resource.user(task_hash[:RunAsUser])
- set_current_run_level task_hash[:run_level]
- set_current_frequency task_hash
- current_resource.day(task_hash[:day]) if task_hash[:day]
- current_resource.months(task_hash[:months]) if task_hash[:months]
- set_current_idle_time(task_hash[:idle_time]) if task_hash[:idle_time]
- current_resource.random_delay(task_hash[:random_delay]) if task_hash[:random_delay]
- # schtask sets execution_time_limit as PT72H by default
- current_resource.execution_time_limit(task_hash[:execution_time_limit] || "PT72H")
- current_resource.status = :running if task_hash[:Status] == "Running"
- current_resource.enabled = true if task_hash[:ScheduledTaskState] == "Enabled"
- current_resource.start_time = task_hash[:StartTime] if task_hash[:StartTime]
- current_resource.start_day = task_hash[:StartDate] if task_hash[:StartDate]
- end
+ if Chef::Platform.windows?
+ include Win32
+
+ provides :windows_task
+
+ MONTHS = {
+ JAN: TaskScheduler::JANUARY,
+ FEB: TaskScheduler::FEBRUARY,
+ MAR: TaskScheduler::MARCH,
+ APR: TaskScheduler::APRIL,
+ MAY: TaskScheduler::MAY,
+ JUN: TaskScheduler::JUNE,
+ JUL: TaskScheduler::JULY,
+ AUG: TaskScheduler::AUGUST,
+ SEP: TaskScheduler::SEPTEMBER,
+ OCT: TaskScheduler::OCTOBER,
+ NOV: TaskScheduler::NOVEMBER,
+ DEC: TaskScheduler::DECEMBER
+ }
- # This method checks if task and command attributes exist since those two are mandatory attributes to create a schedules task.
- def basic_validation
- validate = []
- validate << "Command" if new_resource.command.nil? || new_resource.command.empty?
- validate << "Task Name" if new_resource.task_name.nil? || new_resource.task_name.empty?
- return true if validate.empty?
- raise Chef::Exceptions::ValidationFailed.new "Value for '#{validate.join(', ')}' option cannot be empty"
- end
+ DAYS_OF_WEEK = { MON: TaskScheduler::MONDAY,
+ TUE: TaskScheduler::TUESDAY,
+ WED: TaskScheduler::WEDNESDAY,
+ THU: TaskScheduler::THURSDAY,
+ FRI: TaskScheduler::FRIDAY,
+ SAT: TaskScheduler::SATURDAY,
+ SUN: TaskScheduler::SUNDAY }
+
+ WEEKS_OF_MONTH = {
+ FIRST: TaskScheduler::FIRST_WEEK,
+ SECOND: TaskScheduler::SECOND_WEEK,
+ THIRD: TaskScheduler::THIRD_WEEK,
+ FOURTH: TaskScheduler::FOURTH_WEEK
+ }
- # get array of windows task resource attributes
- def resource_attributes
- %w{ command user run_level cwd frequency_modifier frequency idle_time random_delay execution_time_limit start_day start_time }
- end
+ DAYS_OF_MONTH = {
+ 1 => TaskScheduler::TASK_FIRST,
+ 2 => TaskScheduler::TASK_SECOND,
+ 3 => TaskScheduler::TASK_THIRD,
+ 4 => TaskScheduler::TASK_FOURTH,
+ 5 => TaskScheduler::TASK_FIFTH,
+ 6 => TaskScheduler::TASK_SIXTH,
+ 7 => TaskScheduler::TASK_SEVENTH,
+ 8 => TaskScheduler::TASK_EIGHTH,
+ 9 => TaskScheduler::TASK_NINETH,
+ 10 => TaskScheduler::TASK_TENTH,
+ 11 => TaskScheduler::TASK_ELEVENTH,
+ 12 => TaskScheduler::TASK_TWELFTH,
+ 13 => TaskScheduler::TASK_THIRTEENTH,
+ 14 => TaskScheduler::TASK_FOURTEENTH,
+ 15 => TaskScheduler::TASK_FIFTEENTH,
+ 16 => TaskScheduler::TASK_SIXTEENTH,
+ 17 => TaskScheduler::TASK_SEVENTEENTH,
+ 18 => TaskScheduler::TASK_EIGHTEENTH,
+ 19 => TaskScheduler::TASK_NINETEENTH,
+ 20 => TaskScheduler::TASK_TWENTIETH,
+ 21 => TaskScheduler::TASK_TWENTY_FIRST,
+ 22 => TaskScheduler::TASK_TWENTY_SECOND,
+ 23 => TaskScheduler::TASK_TWENTY_THIRD,
+ 24 => TaskScheduler::TASK_TWENTY_FOURTH,
+ 25 => TaskScheduler::TASK_TWENTY_FIFTH,
+ 26 => TaskScheduler::TASK_TWENTY_SIXTH,
+ 27 => TaskScheduler::TASK_TWENTY_SEVENTH,
+ 28 => TaskScheduler::TASK_TWENTY_EIGHTH,
+ 29 => TaskScheduler::TASK_TWENTY_NINTH,
+ 30 => TaskScheduler::TASK_THIRTYETH,
+ 31 => TaskScheduler::TASK_THIRTY_FIRST
+ }
- def action_create
- if current_resource.exists
- logger.trace "#{new_resource} task exists"
- if !(task_need_update? || new_resource.force)
- logger.info "#{new_resource} task does not need updating and force is not specified - nothing to do"
- return
- end
- # Setting the attributes of new_resource as current_resource.
- # This is required to handle update scenarios when the user specifies
- # only those attributes in the recipe which require update
- resource_attributes.each do |attribute|
- new_resource_attribute = new_resource.send(attribute)
- current_resource_attribute = current_resource.send(attribute)
- # We accept start_day in mm/dd/yyyy format only. Hence while copying the start_day from system to new_resource.start_day,
- # we are converting from system date format to mm/dd/yyyy
- current_resource_attribute = convert_system_date_to_mm_dd_yyyy(current_resource_attribute) if attribute == "start_day" && current_resource_attribute != "N/A"
- # Convert start_time into 24hr time format
- current_resource_attribute = DateTime.parse(current_resource_attribute).strftime("%H:%M") if attribute == "start_time" && current_resource_attribute != "N/A"
- new_resource.send("#{attribute}=", current_resource_attribute ) if current_resource_attribute && new_resource_attribute.nil?
+ def load_current_resource
+ @current_resource = Chef::Resource::WindowsTask.new(new_resource.name)
+ task = TaskScheduler.new
+ if task.exists?(new_resource.task_name)
+ @current_resource.exists = true
+ task.get_task(new_resource.task_name)
+ @current_resource.task = task
+ pathed_task_name = new_resource.task_name.start_with?('\\') ? new_resource.task_name : "\\#{new_resource.task_name}"
+ @current_resource.task_name(pathed_task_name)
+ else
+ @current_resource.exists = false
end
+ @current_resource
end
- basic_validation
- options = {}
- options["F"] = "" if new_resource.force || task_need_update?
- if schedule == :none
- options["SC"] = :once
- options["ST"] = "00:00"
- options["SD"] = convert_user_date_to_system_date "12/12/2012"
- else
- options["SC"] = schedule
- options["ST"] = new_resource.start_time unless new_resource.start_time.nil? || new_resource.start_time == "N/A"
- options["SD"] = convert_user_date_to_system_date new_resource.start_day unless new_resource.start_day.nil? || new_resource.start_day == "N/A"
- end
- options["MO"] = new_resource.frequency_modifier if frequency_modifier_allowed
- options["I"] = new_resource.idle_time unless new_resource.idle_time.nil?
- options["TR"] = new_resource.command
- options["RU"] = new_resource.user
- options["RP"] = new_resource.password if use_password?
- options["RL"] = "HIGHEST" if new_resource.run_level == :highest
- options["IT"] = "" if new_resource.interactive_enabled
- options["D"] = new_resource.day if new_resource.day
- options["M"] = new_resource.months unless new_resource.months.nil?
- run_schtasks "CREATE", options
- xml_options = []
- xml_options << "cwd" if new_resource.cwd
- xml_options << "random_delay" if new_resource.random_delay
- xml_options << "execution_time_limit" if new_resource.execution_time_limit
-
- converge_by("#{new_resource} task created") do
- update_task_xml(xml_options) unless xml_options.empty?
- end
- end
- def action_run
- if current_resource.exists
- logger.trace "#{new_resource} task exists"
- if current_resource.status == :running
- logger.info "#{new_resource} task is currently running, skipping run"
+ def action_create
+ if current_resource.exists
+ logger.trace "#{new_resource} task exist."
+ unless (task_needs_update?(current_resource.task)) || (new_resource.force)
+ logger.info "#{new_resource} task does not need updating and force is not specified - nothing to do"
+ return
+ end
+
+ # if start_day and start_time is not set by user current date and time will be set while updating any property
+ set_start_day_and_time unless new_resource.frequency == :none
+ update_task(current_resource.task)
else
- converge_by("run scheduled task #{new_resource}") do
- run_schtasks "RUN"
+ basic_validation
+ set_start_day_and_time
+ task = TaskScheduler.new
+ if new_resource.frequency == :none
+ task.new_work_item(new_resource.task_name, {})
+ task.activate(new_resource.task_name)
+ else
+ task.new_work_item(new_resource.task_name, trigger)
+ end
+ task.application_name = new_resource.command
+ task.working_directory = new_resource.cwd if new_resource.cwd
+ task.configure_settings(config_settings)
+ task.configure_principals(principal_settings)
+ task.set_account_information(new_resource.user, new_resource.password)
+ task.creator = new_resource.user
+ converge_by("#{new_resource} task created") do
+ task.activate(new_resource.task_name)
end
end
- else
- logger.warn "#{new_resource} task does not exist - nothing to do"
end
- end
- def action_delete
- if current_resource.exists
- logger.trace "#{new_resource} task exists"
- converge_by("delete scheduled task #{new_resource}") do
- # always need to force deletion
- run_schtasks "DELETE", "F" => ""
+ def action_run
+ if current_resource.exists
+ logger.trace "#{new_resource} task exists"
+ if current_resource.task.status == "running"
+ logger.info "#{new_resource} task is currently running, skipping run"
+ else
+ converge_by("run scheduled task #{new_resource}") do
+ current_resource.task.run
+ end
+ end
+ else
+ logger.warn "#{new_resource} task does not exist - nothing to do"
end
- else
- logger.warn "#{new_resource} task does not exist - nothing to do"
end
- end
- def action_end
- if current_resource.exists
- logger.trace "#{new_resource} task exists"
- if current_resource.status != :running
- logger.trace "#{new_resource} is not running - nothing to do"
- else
- converge_by("#{new_resource} task ended") do
- run_schtasks "END"
+ def action_delete
+ if current_resource.exists
+ logger.trace "#{new_resource} task exists"
+ converge_by("delete scheduled task #{new_resource}") do
+ ts = TaskScheduler.new
+ ts.delete(current_resource.name)
end
+ else
+ logger.warn "#{new_resource} task does not exist - nothing to do"
end
- else
- logger.warn "#{new_resource} task does not exist - nothing to do"
end
- end
- def action_enable
- if current_resource.exists
- logger.trace "#{new_resource} task exists"
- if current_resource.enabled
- logger.trace "#{new_resource} already enabled - nothing to do"
- else
- converge_by("#{new_resource} task enabled") do
- run_schtasks "CHANGE", "ENABLE" => ""
+ def action_end
+ if current_resource.exists
+ logger.trace "#{new_resource} task exists"
+ if current_resource.task.status != "running"
+ logger.trace "#{new_resource} is not running - nothing to do"
+ else
+ converge_by("#{new_resource} task ended") do
+ current_resource.task.stop
+ end
end
+ else
+ logger.warn "#{new_resource} task does not exist - nothing to do"
end
- else
- logger.fatal "#{new_resource} task does not exist - nothing to do"
- raise Errno::ENOENT, "#{new_resource}: task does not exist, cannot enable"
end
- end
- def action_disable
- if current_resource.exists
- logger.info "#{new_resource} task exists"
- if current_resource.enabled
- converge_by("#{new_resource} task disabled") do
- run_schtasks "CHANGE", "DISABLE" => ""
+ def action_enable
+ if current_resource.exists
+ logger.trace "#{new_resource} task exists"
+ if current_resource.task.status == "not scheduled"
+ converge_by("#{new_resource} task enabled") do
+ #TODO wind32-taskscheduler currently not having any method to handle this so using schtasks.exe here
+ run_schtasks "CHANGE", "ENABLE" => ""
+ end
+ else
+ logger.trace "#{new_resource} already enabled - nothing to do"
end
else
- logger.warn "#{new_resource} already disabled - nothing to do"
+ logger.fatal "#{new_resource} task does not exist - nothing to do"
+ raise Errno::ENOENT, "#{new_resource}: task does not exist, cannot enable"
end
- else
- logger.warn "#{new_resource} task does not exist - nothing to do"
end
- end
- private
-
- # rubocop:disable Style/StringLiteralsInInterpolation
- def run_schtasks(task_action, options = {})
- cmd = "schtasks /#{task_action} /TN \"#{new_resource.task_name}\" "
- options.each_key do |option|
- unless option == "TR"
- cmd += "/#{option} "
- cmd += "\"#{options[option].to_s.gsub('"', "\\\"")}\" " unless options[option] == ""
+ def action_disable
+ if current_resource.exists
+ logger.info "#{new_resource} task exists"
+ if %w{ready running}.include?(current_resource.task.status)
+ converge_by("#{new_resource} task disabled") do
+ #TODO: in win32-taskscheduler there is no method whcih disbales the task so currently calling disable with schtasks.exe
+ run_schtasks "CHANGE", "DISABLE" => ""
+ end
+ else
+ logger.warn "#{new_resource} already disabled - nothing to do"
+ end
+ else
+ logger.warn "#{new_resource} task does not exist - nothing to do"
end
end
- # Appending Task Run [TR] option at the end since appending causing sometimes to append other options in option["TR"] value
- if options["TR"]
- cmd += "/TR \"#{options["TR"]} \" " unless task_action == "DELETE"
- end
- logger.trace("running: ")
- logger.trace(" #{cmd}")
- shell_out!(cmd, returns: [0])
- end
- # rubocop:enable Style/StringLiteralsInInterpolation
-
- def task_need_update?
- return true if (new_resource.command &&
- current_resource.command != new_resource.command.tr("'", '"')) ||
- current_resource.user != new_resource.user ||
- current_resource.run_level != new_resource.run_level ||
- current_resource.cwd != new_resource.cwd ||
- current_resource.frequency_modifier != new_resource.frequency_modifier ||
- current_resource.frequency != new_resource.frequency ||
- current_resource.idle_time != new_resource.idle_time ||
- random_delay_updated? || execution_time_limit_updated? ||
- (new_resource.start_day && new_resource.start_day != "N/A" && start_day_updated?) ||
- (new_resource.start_time && new_resource.start_time != "N/A" && start_time_updated?)
- begin
- return true if new_resource.day.to_s.casecmp(current_resource.day.to_s) != 0 ||
- new_resource.months.to_s.casecmp(current_resource.months.to_s) != 0
- rescue
- logger.trace "caught a raise in task_needs_update?"
- end
- false
- end
+ alias_method :action_change, :action_create
- # Comparing random_delay values using ISO8601::Duration object Ref: https://github.com/arnau/ISO8601/blob/master/lib/iso8601/duration.rb#L18-L23
- # di = ISO8601::Duration.new(65707200)
- # ds = ISO8601::Duration.new('P65707200S')
- # dp = ISO8601::Duration.new('P2Y1MT2H')
- # di == dp # => true
- # di == ds # => true
- def random_delay_updated?
- if new_resource.random_delay.nil?
- false
- elsif current_resource.random_delay.nil? && new_resource.random_delay == "PT0S" # when user sets random_dealy to 0 sec
- false
- elsif current_resource.random_delay.nil?
- true
- else
- ISO8601::Duration.new(current_resource.random_delay) != ISO8601::Duration.new(new_resource.random_delay)
- end
- end
+ private
- # Comparing execution_time_limit values using Ref: https://github.com/arnau/ISO8601/blob/master/lib/iso8601/duration.rb#L18-L23
- def execution_time_limit_updated?
- if new_resource.execution_time_limit.nil?
- false
- elsif current_resource.execution_time_limit.nil? && new_resource.execution_time_limit == "PT0S" # when user sets random_dealy to 0 sec
- false
- elsif current_resource.execution_time_limit.nil?
- true
- else
- ISO8601::Duration.new(current_resource.execution_time_limit) != ISO8601::Duration.new(new_resource.execution_time_limit)
+ def set_start_day_and_time
+ new_resource.start_day = Time.now.strftime("%m/%d/%Y") unless new_resource.start_day
+ new_resource.start_time = Time.now.strftime("%H:%M") unless new_resource.start_time
end
- end
-
- def start_day_updated?
- current_day = DateTime.strptime(current_resource.start_day, convert_system_date_format_to_ruby_date_format)
- new_day = parse_day(new_resource.start_day)
- current_day != new_day
- end
- def start_time_updated?
- time = DateTime.parse(current_resource.start_time).strftime("%H:%M")
- time != new_resource.start_time
- end
+ def update_task(task)
+ converge_by("#{new_resource} task updated") do
+ task.set_account_information(new_resource.user, new_resource.password)
+ task.application_name = new_resource.command if new_resource.command
+ task.working_directory = new_resource.cwd if new_resource.cwd
+ task.trigger = trigger unless new_resource.frequency == :none
+ task.configure_settings(config_settings)
+ task.creator = new_resource.user
+ task.configure_principals(principal_settings)
+ end
+ end
- def convert_user_date_to_system_date(date_in_string)
- parse_day(date_in_string).strftime(convert_system_date_format_to_ruby_long_date)
- end
+ def trigger
+ start_month, start_day, start_year = new_resource.start_day.to_s.split("/")
+ start_hour, start_minute = new_resource.start_time.to_s.split(":")
+ #TODO currently end_month, end_year and end_year needs to be set to 0. If not set win32-taskscheduler throwing nil into integer error.
+ trigger_hash = {
+ start_year: start_year.to_i,
+ start_month: start_month.to_i,
+ start_day: start_day.to_i,
+ start_hour: start_hour.to_i,
+ start_minute: start_minute.to_i,
+ end_month: 0,
+ end_day: 0,
+ end_year: 0,
+ trigger_type: trigger_type,
+ type: type,
+ random_minutes_interval: new_resource.random_delay
+ }
+
+ if new_resource.frequency == :minute
+ trigger_hash[:minutes_interval] = new_resource.frequency_modifier
+ end
- def convert_system_date_format_to_ruby_long_date
- date_format = get_system_short_date_format.dup
- date_format.sub!("MMM", "%m")
- common_date_format_conversion(date_format)
- date_format.sub!("yy", "%Y")
- date_format
- end
+ if new_resource.frequency == :hourly
+ minutes = convert_hours_in_minutes(new_resource.frequency_modifier.to_i)
+ trigger_hash[:minutes_interval] = minutes
+ end
- def convert_system_date_format_to_ruby_date_format
- date_format = get_system_short_date_format.dup
- date_format.sub!("MMM", "%b")
- common_date_format_conversion(date_format)
- date_format.sub!("yy", "%y")
- date_format
- end
+ if new_resource.minutes_interval
+ trigger_hash[:minutes_interval] = new_resource.minutes_interval
+ end
- def common_date_format_conversion(date_format)
- date_format.sub!("dd", "d")
- date_format.sub!("d", "%d")
- date_format.sub!("MM", "%m")
- date_format.sub!("M", "%m")
- date_format.sub!("yyyy", "%Y")
- end
+ if new_resource.minutes_duration
+ trigger_hash[:minutes_duration] = new_resource.minutes_duration
+ end
- def get_system_short_date_format
- return @system_short_date_format if @system_short_date_format
- logger.trace "Finding system date format"
- task_script = <<-EOH
- [Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
- [Globalization.Cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern
- EOH
- @system_short_date_format = powershell_out(task_script).stdout.force_encoding("UTF-8").gsub(/[\s+\uFEFF]/, "")
- @system_short_date_format
- end
+ if trigger_type == TaskScheduler::MONTHLYDOW && frequency_modifier_contains_last_week?(new_resource.frequency_modifier)
+ trigger_hash[:run_on_last_week_of_month] = true
+ else
+ trigger_hash[:run_on_last_week_of_month] = false
+ end
- def convert_system_date_to_mm_dd_yyyy(system_date)
- system_date_format = convert_system_date_format_to_ruby_date_format
- unless system_date_format == "%m/%d/%Y"
- system_date = Date.strptime(system_date, system_date_format).strftime("%m/%d/%Y")
+ if trigger_type == TaskScheduler::MONTHLYDATE && day_includes_last_or_lastday?(new_resource.day)
+ trigger_hash[:run_on_last_day_of_month] = true
+ else
+ trigger_hash[:run_on_last_day_of_month] = false
+ end
+ trigger_hash
end
- system_date
- end
- def update_task_xml(options = [])
- # random_delay xml element is different for different frequencies
- random_delay_xml_element = {
- :minute => "Triggers/TimeTrigger/RandomDelay",
- :hourly => "Triggers/TimeTrigger/RandomDelay",
- :once => "Triggers/TimeTrigger/RandomDelay",
- :daily => "Triggers/CalendarTrigger/RandomDelay",
- :weekly => "Triggers/CalendarTrigger/RandomDelay",
- :monthly => "Triggers/CalendarTrigger/RandomDelay",
- :none => "Triggers",
- }
-
- xml_element_mapping = {
- "cwd" => "Actions/Exec/WorkingDirectory",
- "random_delay" => random_delay_xml_element[new_resource.frequency],
- "execution_time_limit" => "Settings/ExecutionTimeLimit",
- }
+ def frequency_modifier_contains_last_week?(frequency_modifier)
+ frequency_modifier = frequency_modifier.to_s.split(",")
+ frequency_modifier.map! { |value| value.strip.upcase }
+ frequency_modifier.include?("LAST")
+ end
- logger.trace "looking for existing tasks"
+ def day_includes_last_or_lastday?(day)
+ day = day.to_s.split(",")
+ day.map! { |value| value.strip.upcase }
+ day.include?("LAST") || day.include?("LASTDAY")
+ end
- task_script = <<-EOH
- [Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
- schtasks /Query /TN \"#{new_resource.task_name}\" /XML
- EOH
- xml_cmd = powershell_out(task_script)
+ def convert_hours_in_minutes(hours)
+ hours.to_i * 60 if hours
+ end
- return if xml_cmd.exitstatus != 0
+ #TODO : Try to optimize this method
+ # known issue : Since start_day and time is not mandatory while updating weekly frequency for which start_day is not mentioned by user idempotency
+ # is not gettting maintained as new_resource.start_day is nil and we fetch the day of week from start_day to set and its currently coming as nil and don't match with current_task
+ def task_needs_update?(task)
+ flag = false
+ if new_resource.frequency == :none
+ flag = (task.account_information != new_resource.user ||
+ task.application_name != new_resource.command ||
+ task.principals[:run_level] != run_level)
+ else
+ current_task_trigger = task.trigger(0)
+ new_task_trigger = trigger
+ flag = (ISO8601::Duration.new(task.idle_settings[:idle_duration])) != (ISO8601::Duration.new(new_resource.idle_time * 60)) if new_resource.frequency == :on_idle
+ flag = (ISO8601::Duration.new(task.execution_time_limit)) != (ISO8601::Duration.new(new_resource.execution_time_limit * 60)) unless new_resource.execution_time_limit.nil?
+
+ # if trigger not found updating the task to add the trigger
+ if current_task_trigger.nil?
+ flag = true
+ else
+ flag = true if start_day_updated?(current_task_trigger, new_task_trigger) == true ||
+ start_time_updated?(current_task_trigger, new_task_trigger) == true ||
+ current_task_trigger[:trigger_type] != new_task_trigger[:trigger_type] ||
+ current_task_trigger[:type] != new_task_trigger[:type] ||
+ current_task_trigger[:random_minutes_interval].to_i != new_task_trigger[:random_minutes_interval].to_i ||
+ current_task_trigger[:minutes_interval].to_i != new_task_trigger[:minutes_interval].to_i ||
+ task.account_information != new_resource.user ||
+ task.application_name != new_resource.command ||
+ task.working_directory != new_resource.cwd.to_s ||
+ task.principals[:logon_type] != logon_type ||
+ task.principals[:run_level] != run_level
+
+ if trigger_type == TaskScheduler::MONTHLYDATE
+ flag = true if current_task_trigger[:run_on_last_day_of_month] != new_task_trigger[:run_on_last_day_of_month]
+ end
+
+ if trigger_type == TaskScheduler::MONTHLYDOW
+ flag = true if current_task_trigger[:run_on_last_week_of_month] != new_task_trigger[:run_on_last_week_of_month]
+ end
+ end
+ end
+ flag
+ end
- doc = REXML::Document.new(xml_cmd.stdout)
+ def start_day_updated?(current_task_trigger, new_task_trigger)
+ ( new_resource.start_day && (current_task_trigger[:start_year].to_i != new_task_trigger[:start_year] ||
+ current_task_trigger[:start_month].to_i != new_task_trigger[:start_month] ||
+ current_task_trigger[:start_day].to_i != new_task_trigger[:start_day]) )
+ end
- if new_resource.frequency == :none
- doc.root.elements.delete(xml_element_mapping["random_delay"])
- trigger_element = REXML::Element.new(xml_element_mapping["random_delay"])
- doc.root.elements.add(trigger_element)
+ def start_time_updated?(current_task_trigger, new_task_trigger)
+ ( new_resource.start_time && ( current_task_trigger[:start_hour].to_i != new_task_trigger[:start_hour] ||
+ current_task_trigger[:start_minute].to_i != new_task_trigger[:start_minute] ) )
end
- options.each do |option|
- logger.trace "Removing former #{option} if any"
- doc.root.elements.delete(xml_element_mapping[option])
- option_value = new_resource.send("#{option}")
-
- if option_value
- logger.trace "Setting #{option} as #{option_value}"
- split_xml_path = xml_element_mapping[option].split("/") # eg. if xml_element_mapping[option] = "Actions/Exec/WorkingDirectory"
- element_name = split_xml_path.last # element_name = "WorkingDirectory"
- cwd_element = REXML::Element.new(element_name)
- cwd_element.add_text(option_value)
- element_root = (split_xml_path - [element_name]).join("/") # element_root = 'Actions/Exec'
- exec_element = doc.root.elements[element_root]
- exec_element.add_element(cwd_element)
+ def trigger_type
+ case new_resource.frequency
+ when :once, :minute, :hourly
+ TaskScheduler::ONCE
+ when :daily
+ TaskScheduler::DAILY
+ when :weekly
+ TaskScheduler::WEEKLY
+ when :monthly
+ # If frequency modifier is set with frequency :monthly we are setting taskscheduler as monthlydow
+ # Ref https://msdn.microsoft.com/en-us/library/windows/desktop/aa382061(v=vs.85).aspx
+ new_resource.frequency_modifier.to_i.between?(1, 12) ? TaskScheduler::MONTHLYDATE : TaskScheduler::MONTHLYDOW
+ when :on_idle
+ TaskScheduler::ON_IDLE
+ when :onstart
+ TaskScheduler::AT_SYSTEMSTART
+ when :on_logon
+ TaskScheduler::AT_LOGON
+ else
+ raise ArgumentError, "Please set frequency"
end
end
- temp_task_file = ::File.join(ENV["TEMP"], "windows_task.xml")
- begin
- ::File.open(temp_task_file, "w:UTF-16LE") do |f|
- doc.write(f)
+ def type
+ case trigger_type
+ when TaskScheduler::ONCE
+ { once: nil }
+ when TaskScheduler::DAILY
+ { days_interval: new_resource.frequency_modifier.to_i }
+ when TaskScheduler::WEEKLY
+ { weeks_interval: new_resource.frequency_modifier.to_i, days_of_week: days_of_week.to_i }
+ when TaskScheduler::MONTHLYDATE
+ { months: months_of_year.to_i, days: days_of_month.to_i }
+ when TaskScheduler::MONTHLYDOW
+ { months: months_of_year.to_i, days_of_week: days_of_week.to_i, weeks_of_month: weeks_of_month.to_i }
+ when TaskScheduler::ON_IDLE
+ # TODO: handle option for this trigger
+ when TaskScheduler::AT_LOGON
+ # TODO: handle option for this trigger
+ when TaskScheduler::AT_SYSTEMSTART
+ # TODO: handle option for this trigger
end
+ end
- options = {}
- options["RU"] = new_resource.user if new_resource.user
- options["RP"] = new_resource.password if new_resource.password
- options["IT"] = "" if new_resource.interactive_enabled
- options["XML"] = temp_task_file
- run_schtasks("DELETE", "F" => "")
- run_schtasks("CREATE", options)
- ensure
- ::File.delete(temp_task_file)
+ # Deleting last from the array of weeks of month since last week is handled in :run_on_last_week_of_month parameter.
+ def weeks_of_month
+ weeks_of_month = []
+ if new_resource.frequency_modifier
+ weeks = new_resource.frequency_modifier.split(",")
+ weeks.map! { |week| week.to_s.strip.upcase }
+ weeks.delete("LAST") if weeks.include?("LAST")
+ weeks_of_month = get_binary_values_from_constants(weeks, WEEKS_OF_MONTH)
+ end
+ weeks_of_month
end
- end
- def load_task_hash(task_name)
- logger.trace "Looking for existing tasks"
-
- task_script = <<-EOH
- [Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
- schtasks /Query /FO LIST /V /TN \"#{task_name}\"
- EOH
-
- output = powershell_out(task_script).stdout.force_encoding("UTF-8")
- if output.empty?
- task = false
- else
- task = {}
-
- output.split("\n").map! do |line|
- line.split(": ").map!(&:strip)
- end.each do |field|
- if field.is_a?(Array) && field[0].respond_to?(:to_sym)
- key = (field - [field.last]).join(": ")
- task[key.gsub(/\s+/, "").to_sym] = field.last
+ # Deleting the "LAST" and "LASTDAY" from days since last day is handled in :run_on_last_day_of_month parameter.
+ def days_of_month
+ days_of_month = []
+ if new_resource.day
+ days = new_resource.day.split(",")
+ days.map! { |day| day.to_s.strip.upcase }
+ days.delete("LAST") if days.include?("LAST")
+ days.delete("LASTDAY") if days.include?("LASTDAY")
+ if days - (1..31).to_a
+ days.each do |day|
+ days_of_month << DAYS_OF_MONTH[day.to_i]
+ end
+ days_of_month = days_of_month.size > 1 ? days_of_month.inject(:|) : days_of_month[0]
end
+ else
+ days_of_month = DAYS_OF_MONTH[1]
end
+ days_of_month
end
- task_xml = load_task_xml task_name
- task.merge!(task_xml) if task && task_xml
-
- task
- end
-
- def load_task_xml(task_name)
- task_script = <<-EOH
- [Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8
- schtasks /Query /TN \"#{task_name}\" /XML
- EOH
- xml_cmd = powershell_out(task_script)
-
- return if xml_cmd.exitstatus != 0
-
- doc = REXML::Document.new(xml_cmd.stdout)
- root = doc.root
-
- task = {}
- task[:run_level] = root.elements["Principals/Principal/RunLevel"].text if root.elements["Principals/Principal/RunLevel"]
-
- # for frequency = :minutes, :hourly
- task[:repetition_interval] = root.elements["Triggers/TimeTrigger/Repetition/Interval"].text if root.elements["Triggers/TimeTrigger/Repetition/Interval"]
+ def days_of_week
+ if new_resource.day
+ #this line of code is just to support backward compatibility of wild card *
+ new_resource.day = "mon, tue, wed, thu, fri, sat, sun" if new_resource.day == "*" && new_resource.frequency == :weekly
+ days = new_resource.day.split(",")
+ days.map! { |day| day.to_s.strip.upcase }
+ weeks_days = get_binary_values_from_constants(days, DAYS_OF_WEEK)
+ else
+ # following condition will make the frequency :weekly idempotent if start_day is not provided by user setting day as the current_resource day
+ if (current_resource) && (current_resource.task) && (current_resource.task.trigger(0)[:type][:days_of_week]) && (new_resource.start_day.nil?)
+ weeks_days = current_resource.task.trigger(0)[:type][:days_of_week]
+ else
+ day = get_day(new_resource.start_day).to_sym if new_resource.start_day
+ DAYS_OF_WEEK[day]
+ end
+ end
+ end
- # for frequency = :daily
- task[:schedule_by_day] = root.elements["Triggers/CalendarTrigger/ScheduleByDay/DaysInterval"].text if root.elements["Triggers/CalendarTrigger/ScheduleByDay/DaysInterval"]
+ def months_of_year
+ months_of_year = []
+ if new_resource.frequency_modifier.to_i.between?(1, 12) && !(new_resource.months)
+ new_resource.months = set_months(new_resource.frequency_modifier.to_i)
+ end
- # for frequency = :weekly
- task[:schedule_by_week] = root.elements["Triggers/CalendarTrigger/ScheduleByWeek/WeeksInterval"].text if root.elements["Triggers/CalendarTrigger/ScheduleByWeek/WeeksInterval"]
- if root.elements["Triggers/CalendarTrigger/ScheduleByWeek/DaysOfWeek"]
- task[:day] = []
- root.elements["Triggers/CalendarTrigger/ScheduleByWeek/DaysOfWeek"].elements.each do |e|
- task[:day] << e.to_s[0..3].delete("<").delete("/>")
+ if new_resource.months
+ #this line of code is just to support backward compatibility of wild card *
+ new_resource.months = "jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec" if new_resource.months == "*" && new_resource.frequency == :monthly
+ months = new_resource.months.split(",")
+ months.map! { |month| month.to_s.strip.upcase }
+ months_of_year = get_binary_values_from_constants(months, MONTHS)
+ else
+ MONTHS.each do |key, value|
+ months_of_year << MONTHS[key]
+ end
+ months_of_year = months_of_year.inject(:|)
end
- task[:day] = task[:day].join(", ")
+ months_of_year
end
- # for frequency = :monthly
- task[:schedule_by_month] = root.elements["Triggers/CalendarTrigger/ScheduleByMonth/DaysOfMonth/Day"].text if root.elements["Triggers/CalendarTrigger/ScheduleByMonth/DaysOfMonth/Day"]
- if root.elements["Triggers/CalendarTrigger/ScheduleByMonth/Months"]
- task[:months] = []
- root.elements["Triggers/CalendarTrigger/ScheduleByMonth/Months"].elements.each do |e|
- task[:months] << e.to_s[0..3].delete("<").delete("/>")
+ # This values are set for frequency_modifier set as 1-12
+ # This is to give backward compatibility validated this values with earlier code and running schtask.exe
+ # Used this as reference https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks#d-dayday--
+ def set_months(frequency_modifier)
+ case frequency_modifier
+ when 1
+ "jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec"
+ when 2
+ "feb, apr, jun, aug, oct, dec"
+ when 3
+ "mar, jun, sep, dec"
+ when 4
+ "apr, aug, dec"
+ when 5
+ "may, oct"
+ when 6
+ "jun, dec"
+ when 7
+ "jul"
+ when 8
+ "aug"
+ when 9
+ "sep"
+ when 10
+ "oct"
+ when 11
+ "nov"
+ when 12
+ "dec"
end
- task[:months] = task[:months].join(", ")
end
- task[:on_logon] = true if root.elements["Triggers/LogonTrigger"]
- task[:onstart] = true if root.elements["Triggers/BootTrigger"]
- task[:on_idle] = true if root.elements["Triggers/IdleTrigger"]
-
- task[:idle_time] = root.elements["Settings/IdleSettings/Duration"].text if root.elements["Settings/IdleSettings/Duration"] && task[:on_idle]
-
- task[:none] = true if root.elements["Triggers/"] && root.elements["Triggers/"].entries.empty?
- task[:once] = true if !(task[:repetition_interval] || task[:schedule_by_day] || task[:schedule_by_week] || task[:schedule_by_month] || task[:on_logon] || task[:onstart] || task[:on_idle] || task[:none])
- task[:execution_time_limit] = root.elements["Settings/ExecutionTimeLimit"].text if root.elements["Settings/ExecutionTimeLimit"] #by default PT72H
- task[:random_delay] = root.elements["Triggers/TimeTrigger/RandomDelay"].text if root.elements["Triggers/TimeTrigger/RandomDelay"]
- task[:random_delay] = root.elements["Triggers/CalendarTrigger/RandomDelay"].text if root.elements["Triggers/CalendarTrigger/RandomDelay"]
- task
- end
-
- SYSTEM_USERS = ['NT AUTHORITY\SYSTEM', "SYSTEM", 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', "USERS"].freeze
-
- def use_password?
- @use_password ||= !SYSTEM_USERS.include?(new_resource.user.upcase)
- end
-
- def schedule
- case new_resource.frequency
- when :on_logon
- "ONLOGON"
- when :on_idle
- "ONIDLE"
- else
- new_resource.frequency
+ def get_binary_values_from_constants(array_values, constant)
+ data = []
+ array_values.each do |value|
+ value = value.to_sym
+ data << constant[value]
+ end
+ data.size > 1 ? data.inject(:|) : data[0]
end
- end
- def frequency_modifier_allowed
- case new_resource.frequency
- when :minute, :hourly, :daily, :weekly
- true
- when :monthly
- new_resource.months.nil? || %w{ FIRST SECOND THIRD FOURTH LAST LASTDAY }.include?(new_resource.frequency_modifier)
- else
- false
+ def run_level
+ case new_resource.run_level
+ when :highest
+ TaskScheduler::TASK_RUNLEVEL_HIGHEST
+ when :limited
+ TaskScheduler::TASK_RUNLEVEL_LUA
+ end
end
- end
- def set_current_run_level(run_level)
- case run_level
- when "HighestAvailable"
- current_resource.run_level(:highest)
- when "LeastPrivilege"
- current_resource.run_level(:limited)
+ #TODO: while creating the configuration settings win32-taskscheduler it accepts execution time limit values in ISO8601 formata
+ def config_settings
+ settings = {
+ execution_time_limit: new_resource.execution_time_limit,
+ enabled: true
+ }
+ settings[:idle_duration] = new_resource.idle_time if new_resource.idle_time
+ settings[:run_only_if_idle] = true if new_resource.idle_time
+ settings
end
- end
- def set_current_frequency(task_hash)
- if task_hash[:repetition_interval]
- duration = ISO8601::Duration.new(task_hash[:repetition_interval])
- if task_hash[:repetition_interval].include?("M")
- current_resource.frequency(:minute)
- current_resource.frequency_modifier(duration.minutes.atom.to_i)
- elsif task_hash[:repetition_interval].include?("H")
- current_resource.frequency(:hourly)
- current_resource.frequency_modifier(duration.hours.atom.to_i)
- end
+ def principal_settings
+ settings = {}
+ settings [:run_level] = run_level
+ settings[:logon_type] = logon_type
+ settings
end
- if task_hash[:schedule_by_day]
- current_resource.frequency(:daily)
- current_resource.frequency_modifier(task_hash[:schedule_by_day].to_i)
+ def logon_type
+ # Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383566(v=vs.85).aspx
+ # if nothing is passed as logon_type the TASK_LOGON_SERVICE_ACCOUNT is getting set as default so using that for comparision.
+ new_resource.password.nil? ? TaskScheduler::TASK_LOGON_SERVICE_ACCOUNT : TaskScheduler::TASK_LOGON_PASSWORD
end
- if task_hash[:schedule_by_week]
- current_resource.frequency(:weekly)
- current_resource.frequency_modifier(task_hash[:schedule_by_week].to_i)
+ # This method checks if task and command attributes exist since those two are mandatory attributes to create a schedules task.
+ def basic_validation
+ validate = []
+ validate << "Command" if new_resource.command.nil? || new_resource.command.empty?
+ validate << "Task Name" if new_resource.task_name.nil? || new_resource.task_name.empty?
+ return true if validate.empty?
+ raise Chef::Exceptions::ValidationFailed.new "Value for '#{validate.join(', ')}' option cannot be empty"
end
- current_resource.frequency(:monthly) if task_hash[:schedule_by_month]
- current_resource.frequency(:on_logon) if task_hash[:on_logon]
- current_resource.frequency(:onstart) if task_hash[:onstart]
- current_resource.frequency(:on_idle) if task_hash[:on_idle]
- current_resource.frequency(:once) if task_hash[:once]
- current_resource.frequency(:none) if task_hash[:none]
- end
-
- def set_current_idle_time(idle_time)
- duration = ISO8601::Duration.new(idle_time)
- current_resource.idle_time(duration.minutes.atom.to_i)
- end
+ # rubocop:disable Style/StringLiteralsInInterpolation
+ def run_schtasks(task_action, options = {})
+ cmd = "schtasks /#{task_action} /TN \"#{new_resource.task_name}\" "
+ options.each_key do |option|
+ unless option == "TR"
+ cmd += "/#{option} "
+ cmd += "\"#{options[option].to_s.gsub('"', "\\\"")}\" " unless options[option] == ""
+ end
+ end
+ # Appending Task Run [TR] option at the end since appending causing sometimes to append other options in option["TR"] value
+ if options["TR"]
+ cmd += "/TR \"#{options["TR"]} \" " unless task_action == "DELETE"
+ end
+ logger.trace("running: ")
+ logger.trace(" #{cmd}")
+ shell_out!(cmd, returns: [0])
+ end
+ # rubocop:enable Style/StringLiteralsInInterpolation
- def parse_day(str)
- Date.strptime(str, "%m/%d/%Y")
+ def get_day(date)
+ Date.strptime(date, "%m/%d/%Y").strftime("%a").upcase
+ end
end
-
end
end
end
diff --git a/lib/chef/resource/windows_task.rb b/lib/chef/resource/windows_task.rb
index 8b4743eecc..38f651d670 100644
--- a/lib/chef/resource/windows_task.rb
+++ b/lib/chef/resource/windows_task.rb
@@ -28,7 +28,7 @@ class Chef
" scheduled task. Requires Windows Server 2008 or later due to API usage."
introduced "13.0"
- allowed_actions :create, :delete, :run, :end, :enable, :disable
+ allowed_actions :create, :delete, :run, :end, :enable, :disable, :change
default_action :create
property :task_name, String, regex: [/\A[^\/\:\*\?\<\>\|]+\z/], name_property: true
@@ -49,7 +49,7 @@ class Chef
:on_logon,
:onstart,
:on_idle,
- :none], default: :hourly
+ :none]
property :start_day, String
property :start_time, String
property :day, [String, Integer]
@@ -57,36 +57,59 @@ class Chef
property :idle_time, Integer
property :random_delay, [String, Integer]
property :execution_time_limit, [String, Integer], default: "PT72H" # 72 hours in ISO8601 duration format
+ property :minutes_duration, [String, Integer]
+ property :minutes_interval, [String, Integer]
- attr_accessor :exists, :status, :enabled
+ attr_accessor :exists, :task
+
+ SYSTEM_USERS = ['NT AUTHORITY\SYSTEM', "SYSTEM", 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', "USERS"].freeze
+ VALID_WEEK_DAYS = %w{ mon tue wed thu fri sat sun * }
+ VALID_DAYS_OF_MONTH = ("1".."31").to_a << "last" << "lastday"
+ VALID_MONTHS = %w{JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC *}
+ VALID_WEEKS = %w{FIRST SECOND THIRD FOURTH LAST LASTDAY}
def after_created
if random_delay
validate_random_delay(random_delay, frequency)
- duration = sec_to_dur(random_delay)
- random_delay(duration)
+ random_delay(sec_to_min(random_delay))
end
if execution_time_limit
- unless execution_time_limit == "PT72H" # don't double convert an ISO8601 format duration
- raise ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(execution_time_limit)
- duration = sec_to_dur(execution_time_limit)
- execution_time_limit(duration)
- end
+ execution_time_limit(259200) if execution_time_limit == "PT72H"
+ raise ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(execution_time_limit)
+ execution_time_limit(sec_to_min(execution_time_limit))
end
+ # Removed the default value :hourly for frequency in Chef 14 following code added for backward compatibility
+ chef_version = ::Chef::VERSION.split(".")
+ if chef_version[0].to_i > 13 || (chef_version[0].to_i >= 0)
+ validate_frequency(frequency) if action.include?(:create) || action.include?(:change)
+ else
+ frequency(:hourly) if frequency.nil?
+ end
validate_start_time(start_time, frequency)
validate_start_day(start_day, frequency) if start_day
validate_user_and_password(user, password)
validate_interactive_setting(interactive_enabled, password)
- validate_create_frequency_modifier(frequency, frequency_modifier)
- validate_create_day(day, frequency) if day
+ validate_create_frequency_modifier(frequency, frequency_modifier) if frequency_modifier
+ validate_create_day(day, frequency, frequency_modifier) if day
validate_create_months(months, frequency) if months
+ validate_frequency_monthly(frequency_modifier, months, day) if frequency == :monthly
validate_idle_time(idle_time, frequency)
+ idempotency_warning_for_frequency_weekly(day, start_day) if frequency == :weekly
end
private
+ ## Resource is not idempotent when day, start_day is not provided with frequency :weekly
+ ## we set start_day when not given by user as current date based on which we set the day property for current current date day is monday ..
+ ## we set the monday as the day so at next run when new_resource.day is nil and current_resource day is monday due to which udpate gets called
+ def idempotency_warning_for_frequency_weekly(day, start_day)
+ if start_day.nil? && day.nil?
+ logger.warn "To maintain idempotency for frequency :weekly provide start_day, start_time and day."
+ end
+ end
+
# Validate the passed value is numeric values only if it is a string
def numeric_value_in_string?(val)
return true if Integer(val)
@@ -94,9 +117,35 @@ class Chef
false
end
+ def validate_frequency(frequency)
+ if frequency.nil? || !([:minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none].include?(frequency))
+ raise ArgumentError, "Frequency needs to be provided. Valid frequencies are :minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none."
+ end
+ end
+
+ def validate_frequency_monthly(frequency_modifier, months, day)
+ # validates the frequency :monthly and raises error if frequency_modifier is first, second, thrid etc and day is not provided
+ if (frequency_modifier != 1) && (frequency_modifier_includes_days_of_weeks?(frequency_modifier)) && !(day)
+ raise ArgumentError, "Please select day on which you want to run the task e.g. 'Mon, Tue'. Multiple values must be seprated by comma."
+ end
+
+ # frequency_modifer 2-12 is used to set every (n) months, so using :months propety with frequency_modifer is not valid since they both used to set months.
+ # Not checking value 1 here for frequecy_modifier since we are setting that as default value it won't break anything since preference is given to months property
+ if (frequency_modifier.to_i.between?(2, 12)) && !(months.nil?)
+ raise ArgumentError, "For frequency :monthly either use property months or frequency_modifier to set months."
+ end
+ end
+
+ # returns true if frequency_modifer has values First, second, third, fourth, last, lastday
+ def frequency_modifier_includes_days_of_weeks?(frequency_modifier)
+ frequency_modifier = frequency_modifier.to_s.split(",")
+ frequency_modifier.map! { |value| value.strip.upcase }
+ (frequency_modifier - VALID_WEEKS).empty?
+ end
+
def validate_random_delay(random_delay, frequency)
- if [:once, :on_logon, :onstart, :on_idle, :none].include? frequency
- raise ArgumentError, "`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly"
+ if [:on_logon, :onstart, :on_idle, :none].include? frequency
+ raise ArgumentError, "`random_delay` property is supported only for frequency :once, :minute, :hourly, :daily, :weekly and :monthly"
end
raise ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(random_delay)
@@ -104,12 +153,14 @@ class Chef
# @todo when we drop ruby 2.3 support this should be converted to .match?() instead of =~f
def validate_start_day(start_day, frequency)
- if [:once, :on_logon, :onstart, :on_idle, :none].include? frequency
+ if start_day && frequency == :none
raise ArgumentError, "`start_day` property is not supported with frequency: #{frequency}"
end
# make sure the start_day is in MM/DD/YYYY format: http://rubular.com/r/cgjHemtWl5
- raise ArgumentError, "`start_day` property must be in the MM/DD/YYYY format." unless /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d$/ =~ start_day
+ if start_day
+ raise ArgumentError, "`start_day` property must be in the MM/DD/YYYY format." unless /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d$/ =~ start_day
+ end
end
# @todo when we drop ruby 2.3 support this should be converted to .match?() instead of =~
@@ -122,8 +173,6 @@ class Chef
end
end
- SYSTEM_USERS = ['NT AUTHORITY\SYSTEM', "SYSTEM", 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', "USERS"].freeze
-
def validate_user_and_password(user, password)
if password_required?(user) && password.nil?
raise ArgumentError, %q{Cannot specify a user other than the system users without specifying a password!. Valid passwordless users: 'NT AUTHORITY\SYSTEM', 'SYSTEM', 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', 'USERS'}
@@ -136,65 +185,79 @@ class Chef
end
def validate_interactive_setting(interactive_enabled, password)
- if interactive_enabled && password.nil?
- raise ArgumentError, "Please provide the password when attempting to set interactive/non-interactive."
- end
+ raise ArgumentError, "Please provide the password when attempting to set interactive/non-interactive." if interactive_enabled && password.nil?
end
def validate_create_frequency_modifier(frequency, frequency_modifier)
- # Currently is handled in create action 'frequency_modifier_allowed' line. Does not allow for frequency_modifier for once,onstart,onlogon,onidle,none
- # Note that 'OnEvent' is not a supported frequency.
- unless frequency.nil? || frequency_modifier.nil?
- case frequency
- when :minute
- unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 1439
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :minute frequency are 1 - 1439."
- end
- when :hourly
- unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 23
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :hourly frequency are 1 - 23."
- end
- when :daily
- unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 365
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :daily frequency are 1 - 365."
- end
- when :weekly
- unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 52
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :weekly frequency are 1 - 52."
- end
- when :monthly
- unless ("1".."12").to_a.push("FIRST", "SECOND", "THIRD", "FOURTH", "LAST", "LASTDAY").include?(frequency_modifier.to_s.upcase)
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'."
+ if ([:on_logon, :onstart, :on_idle, :none].include?(frequency)) && ( frequency_modifier != 1)
+ raise ArgumentError, "frequency_modifier property not supported with frequency :#{frequency}"
+ end
+
+ if frequency == :monthly
+ unless (1..12).cover?(frequency_modifier.to_i) || frequency_modifier_includes_days_of_weeks?(frequency_modifier)
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'."
+ end
+ else
+ unless frequency.nil? || frequency_modifier.nil?
+ frequency_modifier = frequency_modifier.to_i
+ min = 1
+ max = case frequency
+ when :minute
+ 1439
+ when :hourly
+ 23
+ when :daily
+ 365
+ when :weekly
+ 52
+ else
+ min
+ end
+ unless frequency_modifier.between?(min, max)
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :#{frequency} frequency are #{min} - #{max}."
end
end
end
end
- def validate_create_day(day, frequency)
- unless [:weekly, :monthly].include?(frequency)
- raise "day property is only valid for tasks that run monthly or weekly"
- end
+ def validate_create_day(day, frequency, frequency_modifier)
+ raise ArgumentError, "day property is only valid for tasks that run monthly or weekly" unless [:weekly, :monthly].include?(frequency)
+
+ # This has been verified with schtask.exe https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks#d-dayday--
+ # verified with earlier code if day "*" is given with frequency it raised exception Invalid value for /D option
+ raise ArgumentError, "day wild card (*) is only valid with frequency :weekly" if frequency == :monthly && day == "*"
+
if day.is_a?(String) && day.to_i.to_s != day
days = day.split(",")
- days.each do |d|
- unless ["mon", "tue", "wed", "thu", "fri", "sat", "sun", "*"].include?(d.strip.downcase)
- raise ArgumentError, "day property invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma."
+ if days_includes_days_of_months?(days)
+ # Following error will be raise if day is set as 1-31 and frequency is selected as :weekly since those values are valid with only frequency :monthly
+ raise ArgumentError, "day values 1-31 or last is only valid with frequency :monthly" if frequency == :weekly
+ else
+ days.map! { |day| day.to_s.strip.downcase }
+ unless (days - VALID_WEEK_DAYS).empty?
+ raise ArgumentError, "day property invalid. Only valid values are: #{VALID_WEEK_DAYS.map(&:upcase).join(', ')}. Multiple values must be separated by a comma."
end
end
end
end
def validate_create_months(months, frequency)
- raise ArgumentError, "months property is only valid for tasks that run monthly" unless frequency == :monthly
- if months.is_a? String
- months.split(",").each do |month|
- unless ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC", "*"].include?(month.strip.upcase)
- raise ArgumentError, "months property invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma."
- end
+ raise ArgumentError, "months property is only valid for tasks that run monthly" if frequency != :monthly
+ if months.is_a?(String)
+ months = months.split(",")
+ months.map! { |month| month.strip.upcase }
+ unless (months - VALID_MONTHS).empty?
+ raise ArgumentError, "months property invalid. Only valid values are: #{VALID_MONTHS.join(', ')}. Multiple values must be separated by a comma."
end
end
end
+ # This method returns true if day has values from 1-31 which is a days of moths and used with frequency :monthly
+ def days_includes_days_of_months?(days)
+ days.map! { |day| day.to_s.strip.downcase }
+ (days - VALID_DAYS_OF_MONTH).empty?
+ end
+
def validate_idle_time(idle_time, frequency)
if !idle_time.nil? && frequency != :on_idle
raise ArgumentError, "idle_time property is only valid for tasks that run on_idle"
@@ -216,6 +279,9 @@ class Chef
ISO8601::Duration.new(seconds.to_i).to_s
end
+ def sec_to_min(seconds)
+ seconds.to_i / 60
+ end
end
end
end
diff --git a/spec/functional/resource/windows_task_spec.rb b/spec/functional/resource/windows_task_spec.rb
index 2839b12288..70f3e6d92e 100644
--- a/spec/functional/resource/windows_task_spec.rb
+++ b/spec/functional/resource/windows_task_spec.rb
@@ -31,24 +31,29 @@ describe Chef::Resource::WindowsTask, :windows_only do
describe "action :create" do
after { delete_task }
- context "when frequency and frequency_modifier are not passed" do
+ context "when frequency_modifier are not passed" do
subject do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
# Make sure MM/DD/YYYY is accepted
new_resource.start_day "09/20/2017"
+ new_resource.frequency :hourly
new_resource
end
it "creates a scheduled task to run every 1 hr starting on 09/20/2017" do
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:"Repeat:Every"]).to eq("1 Hour(s), 0 Minute(s)")
-
- # This test will not work across locales
- expect(task_details[:StartDate]).to eq("9/20/2017")
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ trigger_details = current_resource.task.trigger(0)
+ expect(trigger_details[:start_year]).to eq("2017")
+ expect(trigger_details[:start_month]).to eq("09")
+ expect(trigger_details[:start_day]).to eq("20")
+ expect(trigger_details[:minutes_interval]).to eq(60)
+ expect(trigger_details[:trigger_type]).to eq(1)
end
it "does not converge the resource if it is already converged" do
@@ -65,16 +70,20 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.run_level :highest
new_resource.frequency :minute
new_resource.frequency_modifier 15
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
it "creates a scheduled task that runs after every 15 minutes" do
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:"Repeat:Every"]).to eq("0 Hour(s), 15 Minute(s)")
- expect(task_details[:run_level]).to eq("HighestAvailable")
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:minutes_interval]).to eq(15)
+ expect(trigger_details[:trigger_type]).to eq(1)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
end
it "does not converge the resource if it is already converged" do
@@ -82,6 +91,24 @@ describe Chef::Resource::WindowsTask, :windows_only do
subject.run_action(:create)
expect(subject).not_to be_updated_by_last_action
end
+
+ it "updates a scheduled task when frequency_modifier updated to 20" do
+ subject.run_action(:create)
+ current_resource = call_for_load_current_resource
+ trigger_details = current_resource.task.trigger(0)
+ expect(trigger_details[:minutes_interval]).to eq(15)
+ subject.frequency_modifier 20
+ subject.run_action(:create)
+ expect(subject).to be_updated_by_last_action
+ # #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:minutes_interval]).to eq(20)
+ expect(trigger_details[:trigger_type]).to eq(1)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ end
end
context "frequency :hourly" do
@@ -91,16 +118,19 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.run_level :highest
new_resource.frequency :hourly
new_resource.frequency_modifier 3
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
it "creates a scheduled task that runs after every 3 hrs" do
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:"Repeat:Every"]).to eq("3 Hour(s), 0 Minute(s)")
- expect(task_details[:run_level]).to eq("HighestAvailable")
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:minutes_interval]).to eq(180)
+ expect(trigger_details[:trigger_type]).to eq(1)
end
it "does not converge the resource if it is already converged" do
@@ -108,6 +138,23 @@ describe Chef::Resource::WindowsTask, :windows_only do
subject.run_action(:create)
expect(subject).not_to be_updated_by_last_action
end
+
+ it "updates a scheduled task to run every 5 hrs when frequency modifer updated to 5" do
+ subject.run_action(:create)
+ current_resource = call_for_load_current_resource
+ trigger_details = current_resource.task.trigger(0)
+ expect(trigger_details[:minutes_interval]).to eq(180)
+ # updating frequency modifer to 5 from 3
+ subject.frequency_modifier 5
+ subject.run_action(:create)
+ expect(subject).to be_updated_by_last_action
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:minutes_interval]).to eq(300)
+ expect(trigger_details[:trigger_type]).to eq(1)
+ end
end
context "frequency :daily" do
@@ -116,17 +163,20 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.command task_name
new_resource.run_level :highest
new_resource.frequency :daily
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
it "creates a scheduled task to run daily" do
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:ScheduleType]).to eq("Daily")
- expect(task_details[:Days]).to eq("Every 1 day(s)")
- expect(task_details[:run_level]).to eq("HighestAvailable")
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(2)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:type][:days_interval]).to eq(1)
end
it "does not converge the resource if it is already converged" do
@@ -136,127 +186,465 @@ describe Chef::Resource::WindowsTask, :windows_only do
end
end
- context "frequency :monthly" do
+ describe "frequency :monthly" do
subject do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
new_resource.run_level :highest
new_resource.frequency :monthly
- new_resource.frequency_modifier 2
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
- it "creates a scheduled task to every 2 months" do
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:ScheduleType]).to eq("Monthly")
- expect(task_details[:Months]).to eq("FEB, APR, JUN, AUG, OCT, DEC")
- expect(task_details[:run_level]).to eq("HighestAvailable")
- end
+ context "with start_day and start_time" do
+ before do
+ subject.start_day "02/12/2018"
+ subject.start_time "05:15"
+ end
- it "does not converge the resource if it is already converged" do
- skip "This functionality needs to be handle"
- subject.run_action(:create)
- subject.run_action(:create)
- expect(subject).not_to be_updated_by_last_action
- end
- end
+ it "if day property is not set creates a scheduled task to run monthly on first day of the month" do
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:type][:days]).to eq(1)
+ expect(trigger_details[:type][:months]).to eq(4095)
+ end
- context "frequency :once" do
- subject do
- new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
- new_resource.command task_name
- new_resource.run_level :highest
- new_resource.frequency :once
- new_resource
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "creates a scheduled task to run monthly on first, second and third day of the month" do
+ subject.day "1, 2, 3"
+ call_for_create_action
+ #loading current resource again to check new task is created and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:type][:days]).to eq(7)
+ expect(trigger_details[:type][:months]).to eq(4095)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.day "1, 2, 3"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "creates a scheduled task to run monthly on 1, 2, 3, 4, 8, 20, 21, 15, 28, 31 day of the month" do
+ subject.day "1, 2, 3, 4, 8, 20, 21, 15, 28, 31"
+ call_for_create_action
+ #loading current resource again to check new task is created and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:type][:days]).to eq(1209548943) #TODO:: windows_task_provider.send(:days_of_month)
+ expect(trigger_details[:type][:months]).to eq(4095) #windows_task_provider.send(:months_of_year)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.day "1, 2, 3, 4, 8, 20, 21, 15, 28, 31"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "creates a scheduled task to run monthly on Jan, Feb, Apr, Dec on 1st 2nd 3rd 4th 8th and 20th day of these months" do
+ subject.day "1, 2, 3, 4, 8, 20, 21, 30"
+ subject.months "Jan, Feb, May, Sep, Dec"
+ call_for_create_action
+ #loading current resource again to check new task is created and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:type][:days]).to eq(538443919) #TODO:windows_task_provider.send(:days_of_month)
+ expect(trigger_details[:type][:months]).to eq(2323) #windows_task_provider.send(:months_of_year)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.day "1, 2, 3, 4, 8, 20, 21, 30"
+ subject.months "Jan, Feb, May, Sep, Dec"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "creates a scheduled task to run monthly by giving day option with frequency_modifier" do
+ subject.frequency_modifier "First"
+ subject.day "Mon, Fri, Sun"
+ call_for_create_action
+ #loading current resource again to check new task is created and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(5)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:type][:days_of_week]).to eq(35)
+ expect(trigger_details[:type][:weeks_of_month]).to eq(1)
+ expect(trigger_details[:type][:months]).to eq(4095) #windows_task_provider.send(:months_of_year)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.frequency_modifier "First"
+ subject.day "Mon, Fri, Sun"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
- context "when start_time is not provided" do
- it "raises argument error" do
- expect { subject.run_action(:create) }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
+ context "with frequency_modifier" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :monthly
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
+ new_resource
+ end
+
+ it "raises argument error if frequency_modifier is 'first, second' and day is not provided." do
+ subject.frequency_modifier "first, second"
+ expect { subject.after_created }.to raise_error("Please select day on which you want to run the task e.g. 'Mon, Tue'. Multiple values must be seprated by comma.")
+ end
+
+ it "raises argument error if months is passed along with frequency_modifier" do
+ subject.frequency_modifier 3
+ subject.months "Jan, Mar"
+ expect { subject.after_created }.to raise_error("For frequency :monthly either use property months or frequency_modifier to set months.")
+ end
+
+ it "not raises any Argument error if frequency_modifier set as 'first, second, third' and day is provided" do
+ subject.frequency_modifier "first, second, third"
+ subject.day "Mon, Fri"
+ expect { subject.after_created }.not_to raise_error(ArgumentError)
+ end
+
+ it "not raises any Argument error if frequency_modifier 2 " do
+ subject.frequency_modifier 2
+ subject.day "Mon, Sun"
+ expect { subject.after_created }.not_to raise_error(ArgumentError)
+ end
+
+ it "raises argument error if frequency_modifier > 12" do
+ subject.frequency_modifier 13
+ expect { subject.after_created }.to raise_error("frequency_modifier value 13 is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'.")
+ end
+
+ it "raises argument error if frequency_modifier < 1" do
+ subject.frequency_modifier 0
+ expect { subject.after_created }.to raise_error("frequency_modifier value 0 is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'.")
+ end
+
+ it "creates scheduled task to run task monthly on Monday and Friday of first, second and thrid week of month" do
+ subject.frequency_modifier "first, second, third"
+ subject.day "Mon, Fri"
+ expect { subject.after_created }.not_to raise_error(ArgumentError)
+ call_for_create_action
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(5)
+ expect(trigger_details[:type][:months]).to eq(4095)
+ expect(trigger_details[:type][:weeks_of_month]).to eq(7)
+ expect(trigger_details[:type][:days_of_week]).to eq(34)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.frequency_modifier "first, second, third"
+ subject.day "Mon, Fri"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "creates scheduled task to run task monthly on every 6 months when frequency_modifier is 6 and to run on 1st and 2nd day of month" do
+ subject.frequency_modifier 6
+ subject.day "1, 2"
+ expect { subject.after_created }.not_to raise_error(ArgumentError)
+ call_for_create_action
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(trigger_details[:type][:months]).to eq(2080)
+ expect(trigger_details[:type][:days]).to eq(3)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.frequency_modifier 6
+ subject.day "1, 2"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
end
end
- context "when start_time is provided" do
- it "creates the scheduled task to run once at 5pm" do
- subject.start_time "17:00"
+ context "when day is set as last or lastday for frequency :monthly" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :monthly
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
+ new_resource
+ end
+
+ it "creates scheduled task to run monthly to run last day of the month" do
+ subject.day "last"
+ expect { subject.after_created }.not_to raise_error(ArgumentError)
+ call_for_create_action
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(trigger_details[:type][:months]).to eq(4095)
+ expect(trigger_details[:type][:days]).to eq(0)
+ expect(trigger_details[:run_on_last_day_of_month]).to eq(true)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.day "last"
+ subject.run_action(:create)
subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:ScheduleType]).to eq("One Time Only")
- expect(task_details[:StartTime]).to eq("5:00:00 PM")
- expect(task_details[:run_level]).to eq("HighestAvailable")
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "day property set as 'lastday' creates scheduled task to run monthly to run last day of the month" do
+ subject.day "lastday"
+ expect { subject.after_created }.not_to raise_error(ArgumentError)
+ call_for_create_action
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(trigger_details[:type][:months]).to eq(4095)
+ expect(trigger_details[:type][:days]).to eq(0)
+ expect(trigger_details[:run_on_last_day_of_month]).to eq(true)
end
it "does not converge the resource if it is already converged" do
- subject.start_time "17:00"
+ subject.day "lastday"
subject.run_action(:create)
subject.run_action(:create)
expect(subject).not_to be_updated_by_last_action
end
end
- end
- context "frequency :none" do
- subject do
- new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
- new_resource.command task_name
- new_resource.run_level :highest
- new_resource.frequency :none
- new_resource
+ context "when frequency_modifier is set as last for frequency :monthly" do
+ it "creates scheduled task to run monthly on last week of the month" do
+ subject.frequency_modifier "last"
+ subject.day "Mon, Fri"
+ expect { subject.after_created }.not_to raise_error(ArgumentError)
+ call_for_create_action
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(5)
+ expect(trigger_details[:type][:months]).to eq(4095)
+ expect(trigger_details[:type][:days_of_week]).to eq(34)
+ expect(trigger_details[:run_on_last_week_of_month]).to eq(true)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.frequency_modifier "last"
+ subject.day "Mon, Fri"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
- it "creates the scheduled task to run on demand only" do
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
+ context "when wild card (*) set as months" do
+ it "creates the scheduled task to run on 1st day of the all months" do
+ subject.months "*"
+ expect { subject.after_created }.not_to raise_error(ArgumentError)
+ call_for_create_action
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(trigger_details[:type][:months]).to eq(4095)
+ expect(trigger_details[:type][:days]).to eq(1)
+ end
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:ScheduleType]).to eq("On demand only")
- expect(task_details[:StartTime]).to eq("N/A")
- expect(task_details[:StartDate]).to eq("N/A")
- expect(task_details[:NextRunTime]).to eq("N/A")
- expect(task_details[:none]).to eq(true)
- expect(task_details[:run_level]).to eq("HighestAvailable")
+ it "does not converge the resource if it is already converged" do
+ subject.months "*"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
- it "does not converge the resource if it is already converged" do
- subject.run_action(:create)
- subject.run_action(:create)
- expect(subject).not_to be_updated_by_last_action
+ context "when wild card (*) set as day" do
+ it "raises argument error" do
+ subject.day "*"
+ expect { subject.after_created }.to raise_error("day wild card (*) is only valid with frequency :weekly")
+ end
+ end
+
+ context "Pass either start day or start time by passing day compulsory or only pass frequency_modifier" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :monthly
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
+ new_resource
+ end
+
+ it "creates a scheduled task to run monthly on second day of the month" do
+ subject.day "2"
+ subject.start_day "03/07/2018"
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:type][:days]).to eq(2)
+ expect(trigger_details[:type][:months]).to eq(4095)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.day "2"
+ subject.start_day "03/07/2018"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "creates a scheduled task to run monthly on first, second and third day of the month" do
+ subject.day "1,2,3"
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:type][:days]).to eq(7)
+ expect(trigger_details[:type][:months]).to eq(4095)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.day "1,2,3"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "creates a scheduled task to run monthly on each wednesday of the month" do
+ subject.frequency_modifier "1"
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:type][:days]).to eq(1)
+ expect(trigger_details[:type][:months]).to eq(4095) #windows_task_provider.send(:months_of_year)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.frequency_modifier "2"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "creates a scheduled task to run monthly on each wednesday of the month" do
+ subject.frequency_modifier "2"
+ subject.months = nil
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ #loading current resource
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(4)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:type][:days]).to eq(1)
+ expect(trigger_details[:type][:months]).to eq(2730) #windows_task_provider.send(:months_of_year)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.frequency_modifier "2"
+ subject.months = nil
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
end
- context "frequency :onstart" do
+ ## ToDO: Add functional specs to handle frequency monthly with frequency modifier set as 1-12
+ context "frequency :once" do
subject do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
new_resource.run_level :highest
- new_resource.frequency :onstart
+ new_resource.frequency :once
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
- it "creates the scheduled task to run at system start up" do
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
-
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:ScheduleType]).to eq("At system start up")
- expect(task_details[:StartTime]).to eq("N/A")
- expect(task_details[:StartDate]).to eq("N/A")
- expect(task_details[:NextRunTime]).to eq("N/A")
- expect(task_details[:onstart]).to eq(true)
- expect(task_details[:run_level]).to eq("HighestAvailable")
+ context "when start_time is not provided" do
+ it "raises argument error" do
+ expect { subject.after_created }.to raise_error("`start_time` needs to be provided with `frequency :once`")
+ end
end
- it "does not converge the resource if it is already converged" do
- subject.run_action(:create)
- subject.run_action(:create)
- expect(subject).not_to be_updated_by_last_action
+ context "when start_time is provided" do
+ it "creates the scheduled task to run once at 5pm" do
+ subject.start_time "17:00"
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(1)
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect("#{trigger_details[:start_hour]}:#{trigger_details[:start_minute]}" ).to eq(subject.start_time)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.start_time "17:00"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
end
@@ -266,60 +654,192 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.command task_name
new_resource.run_level :highest
new_resource.frequency :weekly
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
it "creates the scheduled task to run weekly" do
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:ScheduleType]).to eq("Weekly")
- expect(task_details[:Months]).to eq("Every 1 week(s)")
- expect(task_details[:run_level]).to eq("HighestAvailable")
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:trigger_type]).to eq(3)
+ expect(trigger_details[:type][:weeks_interval]).to eq(1)
end
it "does not converge the resource if it is already converged" do
- skip "This functionality needs to be handle"
subject.run_action(:create)
subject.run_action(:create)
expect(subject).not_to be_updated_by_last_action
end
+ context "when wild card (*) is set as day" do
+ it "creates hte scheduled task for all days of week" do
+ subject.day "*"
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:trigger_type]).to eq(3)
+ expect(trigger_details[:type][:weeks_interval]).to eq(1)
+ expect(trigger_details[:type][:days_of_week]).to eq(127)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.day "*"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+
context "when days are provided" do
it "creates the scheduled task to run on particular days" do
subject.day "Mon, Fri"
subject.frequency_modifier 2
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:trigger_type]).to eq(3)
+ expect(trigger_details[:type][:weeks_interval]).to eq(2)
+ expect(trigger_details[:type][:days_of_week]).to eq(34)
+ end
+
+ it "updates the scheduled task to run on if frequency_modifier is updated" do
+ subject.day "sun"
+ subject.frequency_modifier 2
+ subject.run_action(:create)
+ current_resource = call_for_load_current_resource
+ trigger_details = current_resource.task.trigger(0)
+ expect(trigger_details[:type][:weeks_interval]).to eq(2)
+ expect(trigger_details[:type][:days_of_week]).to eq(1)
+ subject.day "Mon, Sun"
+ subject.frequency_modifier 3
+ # call for update
subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:Days]).to eq("MON, FRI")
- expect(task_details[:ScheduleType]).to eq("Weekly")
- expect(task_details[:Months]).to eq("Every 2 week(s)")
- expect(task_details[:run_level]).to eq("HighestAvailable")
+ expect(subject).to be_updated_by_last_action
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:trigger_type]).to eq(3)
+ expect(trigger_details[:type][:weeks_interval]).to eq(3)
+ expect(trigger_details[:type][:days_of_week]).to eq(3)
end
it "does not converge the resource if it is already converged" do
subject.day "Mon, Fri"
- subject.frequency_modifier 2
+ subject.frequency_modifier 3
subject.run_action(:create)
subject.run_action(:create)
expect(subject).not_to be_updated_by_last_action
end
end
+ context "when day property set as last" do
+ it "raises argument error" do
+ subject.day "last"
+ expect { subject.after_created }.to raise_error("day values 1-31 or last is only valid with frequency :monthly")
+ end
+ end
+
context "when invalid day is passed" do
it "raises error" do
subject.day "abc"
- expect { subject.run_action(:create) }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
+ expect { subject.after_created }.to raise_error("day property invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN, *. Multiple values must be separated by a comma.")
end
end
context "when months are passed" do
it "raises error that months are supported only when frequency=:monthly" do
subject.months "Jan"
- expect { subject.run_action(:create) }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
+ expect { subject.after_created }.to raise_error("months property is only valid for tasks that run monthly")
+ end
+ end
+
+ context "when start_day is not set" do
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "updates the day if start_day is not provided and user updates day property" do
+ skip "Unable to run this test case since start_day is current system date which can be different each time so can't verify the dynamic values"
+ subject.run_action(:create)
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(trigger_details[:type][:days_of_week]).to eq(8)
+ subject.day "Sat"
+ subject.run_action(:create)
+ # #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:trigger_type]).to eq(3)
+ expect(trigger_details[:type][:weeks_interval]).to eq(1)
+ expect(trigger_details[:type][:days_of_week]).to eq(64)
+ end
+ end
+ end
+
+ context "frequency :onstart" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :onstart
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
+ new_resource
+ end
+
+ it "creates the scheduled task to run at system start up" do
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:trigger_type]).to eq(8)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ context "when start_day and start_time is set" do
+ it "creates task to activate on '09/10/2018' at '15:00' when start_day = '09/10/2018' and start_time = '15:00' provided" do
+ subject.start_day "09/10/2018"
+ subject.start_time "15:00"
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(8)
+ expect(trigger_details[:start_year]).to eq("2018")
+ expect(trigger_details[:start_month]).to eq("09")
+ expect(trigger_details[:start_day]).to eq("10")
+ expect(trigger_details[:start_hour]).to eq("15")
+ expect(trigger_details[:start_minute]).to eq("00")
end
end
end
@@ -330,16 +850,19 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.command task_name
new_resource.run_level :highest
new_resource.frequency :on_logon
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
it "creates the scheduled task to on logon" do
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:ScheduleType]).to eq("At logon time")
- expect(task_details[:run_level]).to eq("HighestAvailable")
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:trigger_type]).to eq(9)
end
it "does not converge the resource if it is already converged" do
@@ -347,6 +870,25 @@ describe Chef::Resource::WindowsTask, :windows_only do
subject.run_action(:create)
expect(subject).not_to be_updated_by_last_action
end
+
+ context "when start_day and start_time is set" do
+ it "creates task to activate on '09/10/2018' at '15:00' when start_day = '09/10/2018' and start_time = '15:00' provided" do
+ subject.start_day "09/10/2018"
+ subject.start_time "15:00"
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(9)
+ expect(trigger_details[:start_year]).to eq("2018")
+ expect(trigger_details[:start_month]).to eq("09")
+ expect(trigger_details[:start_day]).to eq("10")
+ expect(trigger_details[:start_hour]).to eq("15")
+ expect(trigger_details[:start_minute]).to eq("00")
+ end
+ end
end
context "frequency :on_idle" do
@@ -355,25 +897,29 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.command task_name
new_resource.run_level :highest
new_resource.frequency :on_idle
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
context "when idle_time is not passed" do
it "raises error" do
- expect { subject.run_action(:create) }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
+ expect { subject.after_created }.to raise_error("idle_time value should be set for :on_idle frequency.")
end
end
context "when idle_time is passed" do
it "creates the scheduled task to run when system is idle" do
subject.idle_time 20
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:ScheduleType]).to eq("At idle time")
- expect(task_details[:run_level]).to eq("HighestAvailable")
- expect(task_details[:idle_time]).to eq("PT20M")
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:trigger_type]).to eq(6)
+ expect(current_resource.task.settings[:idle_settings][:idle_duration]).to eq("PT20M")
+ expect(current_resource.task.settings[:run_only_if_idle]).to eq(true)
end
it "does not converge the resource if it is already converged" do
@@ -383,6 +929,26 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(subject).not_to be_updated_by_last_action
end
end
+
+ context "when start_day and start_time is set" do
+ it "creates task to activate on '09/10/2018' at '15:00' when start_day = '09/10/2018' and start_time = '15:00' provided" do
+ subject.idle_time 20
+ subject.start_day "09/10/2018"
+ subject.start_time "15:00"
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(trigger_details[:trigger_type]).to eq(6)
+ expect(trigger_details[:start_year]).to eq("2018")
+ expect(trigger_details[:start_month]).to eq("09")
+ expect(trigger_details[:start_day]).to eq("10")
+ expect(trigger_details[:start_hour]).to eq("15")
+ expect(trigger_details[:start_minute]).to eq("00")
+ end
+ end
end
context "when random_delay is passed" do
@@ -390,24 +956,27 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
new_resource.run_level :highest
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
it "sets the random_delay for frequency :minute" do
subject.frequency :minute
- subject.random_delay "PT20M"
- subject.run_action(:create)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:TaskName]).to eq("\\chef-client")
- expect(task_details[:ScheduleType]).to eq("One Time Only, Minute")
- expect(task_details[:TaskToRun]).to eq("chef-client")
- expect(task_details[:run_level]).to eq("HighestAvailable")
- expect(task_details[:random_delay]).to eq("PT20M")
+ subject.random_delay "20"
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+ trigger_details = current_resource.task.trigger(0)
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(trigger_details[:trigger_type]).to eq(1)
+ expect(trigger_details[:random_minutes_interval]).to eq(20)
end
it "does not converge the resource if it is already converged" do
subject.frequency :minute
- subject.random_delay "PT20M"
+ subject.random_delay "20"
subject.run_action(:create)
subject.run_action(:create)
expect(subject).not_to be_updated_by_last_action
@@ -421,8 +990,36 @@ describe Chef::Resource::WindowsTask, :windows_only do
it "raises error if random_delay is passed with frequency on_idle" do
subject.frequency :on_idle
- subject.random_delay "PT20M"
- expect { subject.after_created }.to raise_error("`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly")
+ subject.random_delay "20"
+ expect { subject.after_created }.to raise_error("`random_delay` property is supported only for frequency :once, :minute, :hourly, :daily, :weekly and :monthly")
+ end
+ end
+
+ context "frequency :none" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :none
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
+ new_resource
+ end
+
+ it "creates the scheduled task to run on demand only" do
+ call_for_create_action
+ #loading current resource again to check new task is creted and it matches task parameters
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(true)
+
+ expect(current_resource.task.application_name).to eq("chef-client")
+ expect(current_resource.task.principals[:run_level]).to eq(1)
+ expect(current_resource.task.trigger_count).to eq(0)
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
end
end
end
@@ -436,6 +1033,7 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.run_level :highest
new_resource.frequency :once
new_resource.start_time "17:00"
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
@@ -447,7 +1045,6 @@ describe Chef::Resource::WindowsTask, :windows_only do
end
it "create task by adding frequency_modifier as 5" do
- skip "This functionality needs to be handle"
subject.frequency_modifier 5
subject.run_action(:create)
subject.run_action(:create)
@@ -460,6 +1057,7 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
new_resource.run_level :highest
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource.frequency :none
new_resource
end
@@ -472,7 +1070,6 @@ describe Chef::Resource::WindowsTask, :windows_only do
end
it "create task by adding frequency_modifier as 5" do
- skip "This functionality needs to be handle"
subject.frequency_modifier 5
subject.run_action(:create)
subject.run_action(:create)
@@ -486,11 +1083,11 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.command task_name
new_resource.run_level :highest
new_resource.frequency :weekly
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
it "create task by adding start_day" do
- skip "This functionality needs to be handle"
subject.start_day "12/28/2018"
subject.run_action(:create)
subject.run_action(:create)
@@ -498,7 +1095,6 @@ describe Chef::Resource::WindowsTask, :windows_only do
end
it "create task by adding frequency_modifier and random_delay" do
- skip "This functionality needs to be handle"
subject.frequency_modifier 3
subject.random_delay "60"
subject.run_action(:create)
@@ -514,6 +1110,7 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.run_level :highest
new_resource.frequency :once
new_resource.start_time "17:00"
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
@@ -525,7 +1122,6 @@ describe Chef::Resource::WindowsTask, :windows_only do
end
it "create task by adding frequency_modifier as 5" do
- skip "This functionality needs to be handle"
subject.frequency_modifier 5
subject.run_action(:create)
subject.run_action(:create)
@@ -541,11 +1137,11 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.frequency :hourly
new_resource.frequency_modifier 5
new_resource.random_delay "2400"
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
it "create task by adding frequency_modifier and random_delay" do
- skip "This functionality needs to be handle"
subject.run_action(:create)
subject.run_action(:create)
expect(subject).not_to be_updated_by_last_action
@@ -560,11 +1156,11 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.frequency :daily
new_resource.frequency_modifier 2
new_resource.random_delay "2400"
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
it "create task by adding frequency_modifier and random_delay" do
- skip "This functionality needs to be handle"
subject.run_action(:create)
subject.run_action(:create)
expect(subject).not_to be_updated_by_last_action
@@ -576,6 +1172,7 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
new_resource.frequency :on_logon
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
@@ -586,7 +1183,6 @@ describe Chef::Resource::WindowsTask, :windows_only do
end
it "create task by adding frequency_modifier as 5" do
- skip "This functionality needs to be handle"
subject.frequency_modifier 5
subject.run_action(:create)
subject.run_action(:create)
@@ -601,11 +1197,11 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource.run_level :highest
new_resource.frequency :onstart
new_resource.frequency_modifier 20
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
it "create task by adding frequency_modifier as 20" do
- skip "This functionality needs to be handle"
subject.run_action(:create)
subject.run_action(:create)
expect(subject).not_to be_updated_by_last_action
@@ -618,14 +1214,15 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
new_resource.run_level :highest
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
new_resource
end
context "when start_day is passed with frequency :onstart" do
- it "raises error" do
+ it "not raises error" do
subject.frequency :onstart
subject.start_day "09/20/2017"
- expect { subject.after_created }.to raise_error("`start_day` property is not supported with frequency: onstart")
+ expect { subject.after_created }.not_to raise_error
end
end
@@ -653,11 +1250,51 @@ describe Chef::Resource::WindowsTask, :windows_only do
end
end
+ context "when frequency_modifier > 23 is passed for frequency=:minute" do
+ it "raises error" do
+ subject.frequency_modifier 24
+ subject.frequency :hourly
+ expect { subject.after_created }.to raise_error("frequency_modifier value 24 is invalid. Valid values for :hourly frequency are 1 - 23.")
+ end
+ end
+
+ context "when frequency_modifier > 23 is passed for frequency=:minute" do
+ it "raises error" do
+ subject.frequency_modifier 366
+ subject.frequency :daily
+ expect { subject.after_created }.to raise_error("frequency_modifier value 366 is invalid. Valid values for :daily frequency are 1 - 365.")
+ end
+ end
+
+ context "when frequency_modifier > 52 is passed for frequency=:minute" do
+ it "raises error" do
+ subject.frequency_modifier 53
+ subject.frequency :weekly
+ expect { subject.after_created }.to raise_error("frequency_modifier value 53 is invalid. Valid values for :weekly frequency are 1 - 52.")
+ end
+ end
+
+ context "when invalid frequency_modifier is passed for :monthly frequency" do
+ it "raises error" do
+ subject.frequency :monthly
+ subject.frequency_modifier "13"
+ expect { subject.after_created }.to raise_error("frequency_modifier value 13 is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'.")
+ end
+ end
+
+ context "when invalid frequency_modifier is passed for :monthly frequency" do
+ it "raises error" do
+ subject.frequency :monthly
+ subject.frequency_modifier "xyz"
+ expect { subject.after_created }.to raise_error("frequency_modifier value xyz is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'.")
+ end
+ end
+
context "when invalid months are passed" do
it "raises error" do
subject.months "xyz"
subject.frequency :monthly
- expect { subject.after_created }.to raise_error("months property invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma.")
+ expect { subject.after_created }.to raise_error("months property invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC, *. Multiple values must be separated by a comma.")
end
end
@@ -682,14 +1319,16 @@ describe Chef::Resource::WindowsTask, :windows_only do
subject do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this
+ new_resource.frequency :hourly
new_resource
end
- it "deletes the task if it exists" do
+ it "does not converge the resource if it is already converged" do
subject.run_action(:create)
- delete_task
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details).to eq(false)
+ subject.run_action(:delete)
+ subject.run_action(:delete)
+ expect(subject).not_to be_updated_by_last_action
end
it "does not converge the resource if it is already converged" do
@@ -707,15 +1346,16 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command "dir"
new_resource.run_level :highest
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since
+ new_resource.frequency :hourly
new_resource
end
it "runs the existing task" do
- skip "Task status is returned as Ready instead of Running randomly"
subject.run_action(:create)
subject.run_action(:run)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:Status]).to eq("Running")
+ current_resource = call_for_load_current_resource
+ expect(current_resource.task.status).to eq("queued").or eq("running") # queued or can be running
end
end
@@ -726,16 +1366,16 @@ describe Chef::Resource::WindowsTask, :windows_only do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command "dir"
new_resource.run_level :highest
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since
new_resource
end
it "ends the running task" do
subject.run_action(:create)
subject.run_action(:run)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
subject.run_action(:end)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:Status]).to eq("Ready")
+ current_resource = call_for_load_current_resource
+ expect(current_resource.task.status).to eq("queued").or eq("ready") #queued or can be ready
end
end
@@ -745,17 +1385,19 @@ describe Chef::Resource::WindowsTask, :windows_only do
subject do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since
+ new_resource.frequency :hourly
new_resource
end
it "enables the disabled task" do
subject.run_action(:create)
subject.run_action(:disable)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:ScheduledTaskState]).to eq("Disabled")
+ current_resource = call_for_load_current_resource
+ expect(current_resource.task.status).to eq("not scheduled")
subject.run_action(:enable)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:ScheduledTaskState]).to eq("Enabled")
+ current_resource = call_for_load_current_resource
+ expect(current_resource.task.status).to eq("ready")
end
end
@@ -765,14 +1407,32 @@ describe Chef::Resource::WindowsTask, :windows_only do
subject do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since
+ new_resource.frequency :hourly
new_resource
end
it "disables the task" do
subject.run_action(:create)
subject.run_action(:disable)
- task_details = windows_task_provider.send(:load_task_hash, task_name)
- expect(task_details[:ScheduledTaskState]).to eq("Disabled")
+ current_resource = call_for_load_current_resource
+ expect(current_resource.task.status).to eq("not scheduled")
+ end
+ end
+
+ describe "action :change" do
+ after { delete_task }
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since
+ new_resource.frequency :hourly
+ new_resource
+ end
+
+ it "call action_create since change action is alias for create" do
+ subject.run_action(:change)
+ expect(subject).to be_updated_by_last_action
end
end
@@ -780,4 +1440,15 @@ describe Chef::Resource::WindowsTask, :windows_only do
task_to_delete = Chef::Resource::WindowsTask.new(task_name, run_context)
task_to_delete.run_action(:delete)
end
+
+ def call_for_create_action
+ current_resource = call_for_load_current_resource
+ expect(current_resource.exists).to eq(false)
+ subject.run_action(:create)
+ expect(subject).to be_updated_by_last_action
+ end
+
+ def call_for_load_current_resource
+ windows_task_provider.send(:load_current_resource)
+ end
end
diff --git a/spec/unit/provider/windows_task_spec.rb b/spec/unit/provider/windows_task_spec.rb
index a71ce92f56..603c9d1342 100644
--- a/spec/unit/provider/windows_task_spec.rb
+++ b/spec/unit/provider/windows_task_spec.rb
@@ -18,8 +18,9 @@
require "spec_helper"
-describe Chef::Provider::WindowsTask do
+describe Chef::Provider::WindowsTask, :windows_only do
let(:new_resource) { Chef::Resource::WindowsTask.new("sample_task") }
+ let(:current_resource) { Chef::Resource::WindowsTask.new() }
let(:provider) do
node = Chef::Node.new
@@ -28,690 +29,392 @@ describe Chef::Provider::WindowsTask do
Chef::Provider::WindowsTask.new(new_resource, run_context)
end
- let(:task_hash) do
- {
- :"" => "",
- :Folder => "\\",
- :HostName => "NIMISHA-PC",
- :TaskName => "\\sample_task",
- :NextRunTime => "3/30/2017 2:42:00 PM",
- :Status => "Ready",
- :LogonMode => "Interactive/Background",
- :LastRunTime => "3/30/2017 2:27:00 PM",
- :LastResult => "1",
- :Author => "Administrator",
- :TaskToRun => "chef-client -L C:\\tmp\\",
- :StartIn => "N/A",
- :Comment => "N/A",
- :ScheduledTaskState => "Enabled",
- :IdleTime => "Disabled",
- :PowerManagement => "Stop On Battery Mode, No Start On Batteries",
- :RunAsUser => "SYSTEM",
- :DeleteTaskIfNotRescheduled => "Enabled",
- :StopTaskIfRunsXHoursandXMins => "72:00:00",
- :Schedule => "Scheduling data is not available in this format.",
- :ScheduleType => "One Time Only, Minute",
- :StartTime => "1:12:00 PM",
- :StartDate => "3/30/2017",
- :EndDate => "N/A",
- :Days => "N/A",
- :Months => "N/A",
- :"Repeat:Every" => "0 Hour(s), 15 Minute(s)",
- :"Repeat:Until:Time" => "None",
- :"Repeat:Until:Duration" => "Disabled",
- :"Repeat:StopIfStillRunning" => "Disabled",
- :run_level => "HighestAvailable",
- :repetition_interval => "PT15M",
- :execution_time_limit => "PT72H",
- }
- end
-
- let(:task_xml) do
- "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\r\n<Task version=\"1.2\" xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">\r\r\n <RegistrationInfo>\r\r\n <Date>2017-03-31T15:34:44</Date>\r\r\n <Author>Administrator</Author>\r\r\n </RegistrationInfo>\r\r\n<Triggers>\r\r\n <TimeTrigger>\r\r\n <Repetition>\r\r\n <Interval>PT15M</Interval>\r\r\n <StopAtDurationEnd>false</StopAtDurationEnd>\r\r\n </Repetition>\r\r\n <StartBoundary>2017-03-31T15:34:00</StartBoundary>\r\r\n <Enabled>true</Enabled>\r\r\n </TimeTrigger>\r\r\n </Triggers>\r\r\n <Principals>\r\r\n <Principal id=\"Author\">\r\r\n <RunLevel>HighestAvailable</RunLevel>\r\r\n <UserId>S-1-5-18</UserId>\r\r\n </Principal>\r\r\n </Principals>\r\r\n <Settings>\r\r\n <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>\r\r\n <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>\r\r\n <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>\r\r\n <AllowHardTerminate>true</AllowHardTerminate>\r\r\n <StartWhenAvailable>false</StartWhenAvailable>\r\r\n <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>\r\r\n <IdleSettings>\r\r\n <Duration>PT10M</Duration>\r\r\n<WaitTimeout>PT1H</WaitTimeout>\r\r\n <StopOnIdleEnd>true</StopOnIdleEnd>\r\r\n <RestartOnIdle>false</RestartOnIdle>\r\r\n </IdleSettings>\r\r\n <AllowStartOnDemand>true</AllowStartOnDemand>\r\r\n <Enabled>true</Enabled>\r\r\n <Hidden>false</Hidden>\r\r\n<RunOnlyIfIdle>false</RunOnlyIfIdle>\r\r\n <WakeToRun>false</WakeToRun>\r\r\n <ExecutionTimeLimit>PT72H</ExecutionTimeLimit>\r\r\n<Priority>7</Priority>\r\r\n </Settings>\r\r\n <Actions Context=\"Author\">\r\r\n <Exec>\r\r\n <Command>chef-client</Command>\r\r\n </Exec>\r\r\n </Actions>\r\r\n</Task>"
- end
-
describe "#load_current_resource" do
it "returns a current_resource" do
- allow(provider).to receive(:load_task_hash)
expect(provider.load_current_resource).to be_kind_of(Chef::Resource::WindowsTask)
end
+ end
- context "if the given task name already exists" do
- before do
- allow(provider).to receive(:load_task_hash).and_return({ :TaskName => "\\sample_task" })
- end
-
- it "calls set_current_resource" do
- expect(provider).to receive(:set_current_resource)
- provider.load_current_resource
- end
+ describe "#set_start_day_and_time" do
+ it "sets the curret date and time start_day and start_time if nothing is provided by user" do
+ new_resource.start_day = nil
+ new_resource.start_time = nil
+ provider.send(:set_start_day_and_time)
+ expect(new_resource.start_day).not_to be_nil
+ expect(new_resource.start_time).not_to be_nil
end
- it "sets the attributes of current_resource" do
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- current_resource = provider.load_current_resource
- expect(current_resource.exists).to be(true)
- expect(current_resource.command).to eq("chef-client -L C:\\tmp\\")
- expect(current_resource.user).to eq("SYSTEM")
- expect(current_resource.run_level).to eq(:highest)
- expect(current_resource.frequency).to eq(:minute)
- expect(current_resource.frequency_modifier).to eq(15)
- expect(current_resource.execution_time_limit).to eq("PT72H")
- expect(current_resource.enabled).to be(true)
+ it "does not set start_day and start_time if given by user" do
+ new_resource.start_day = "12/02/2017"
+ new_resource.start_time = "17:30"
+ provider.send(:set_start_day_and_time)
+ expect(new_resource.start_day).to eq("12/02/2017")
+ expect(new_resource.start_time).to eq("17:30")
end
end
- describe "#action_create" do
- it "doesn't create the same task if it's already existing" do
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- allow(provider).to receive(:task_need_update?).and_return(false)
- provider.run_action(:create)
- expect(new_resource).not_to be_updated_by_last_action
- end
-
- it "sets the start_time in 24hr format while updating an existing task" do
- # task_hash has start_time = "1:12:00 PM"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- allow(provider).to receive(:task_need_update?).and_return(true)
- allow(provider).to receive(:convert_system_date_to_mm_dd_yyyy).and_return("03/30/2017")
- allow(provider).to receive(:run_schtasks)
- provider.run_action(:create)
- # start_time gets set in 24hr format for new_resource
- expect(new_resource.start_time).to eq("13:12")
- expect(new_resource).to be_updated_by_last_action
- end
-
- it "sets the start_day in mm/dd/yyyy format while updating an existing task" do
- # start_day in yyyy-MM-dd format
- task_hash[:StartDate] = "2017-03-30"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- current_resource = provider.load_current_resource
- allow(provider).to receive(:task_need_update?).and_return(true)
- allow(provider).to receive(:convert_system_date_format_to_ruby_date_format).and_return("%Y-%m-%d")
- allow(provider).to receive(:run_schtasks)
- provider.run_action(:create)
- # start_day gets set in mm/dd/yyyy format for new_resource
- expect(new_resource.start_day).to eq("03/30/2017")
- expect(new_resource).to be_updated_by_last_action
- end
-
- context "when start_day and start_time are N/A for frequency :on_logon" do
- it "doesn't update the start_day and start_time of new_resource" do
- task_hash[:on_logon] = true
- task_hash[:StartDate] = "N/A"
- task_hash[:StartTime] = "N/A"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- current_resource = provider.load_current_resource
- allow(provider).to receive(:task_need_update?).and_return(true)
- allow(provider).to receive(:run_schtasks)
- expect(provider).not_to receive(:convert_system_date_to_mm_dd_yyyy)
- expect(DateTime).not_to receive(:parse)
- expect(new_resource.start_day).to eq(nil)
- expect(new_resource.start_time).to eq(nil)
- end
- end
-
- context "when task is not existing" do
- before do
- allow(provider).to receive(:load_task_hash)
- provider.load_current_resource
- end
-
- it "creates the task if it's not already existing" do
- allow(provider).to receive(:task_need_update?).and_return(true)
- allow(provider).to receive(:basic_validation).and_return(true)
- expect(provider).to receive(:run_schtasks).with("CREATE", { "F" => "", "SC" => :hourly, "MO" => 1, "TR" => nil, "RU" => "SYSTEM" })
- provider.run_action(:create)
- expect(new_resource).to be_updated_by_last_action
- end
-
- it "updates the task XML if random_delay is provided" do
- new_resource.random_delay "20"
- allow(provider).to receive(:task_need_update?).and_return(true)
- allow(provider).to receive(:basic_validation).and_return(true)
- expect(provider).to receive(:run_schtasks).with("CREATE", { "F" => "", "SC" => :hourly, "MO" => 1, "TR" => nil, "RU" => "SYSTEM" })
- expect(provider).to receive(:update_task_xml)
- provider.run_action(:create)
- expect(new_resource).to be_updated_by_last_action
- end
-
- it "updates the task XML if execution_time_limit is provided" do
- new_resource.execution_time_limit "20"
- allow(provider).to receive(:task_need_update?).and_return(true)
- allow(provider).to receive(:basic_validation).and_return(true)
- expect(provider).to receive(:run_schtasks).with("CREATE", { "F" => "", "SC" => :hourly, "MO" => 1, "TR" => nil, "RU" => "SYSTEM" })
- expect(provider).to receive(:update_task_xml)
- provider.run_action(:create)
- expect(new_resource).to be_updated_by_last_action
- end
-
- it "updates the task XML if frequency is set as `:none`" do
- new_resource.frequency :none
- new_resource.random_delay ""
- allow(provider).to receive(:task_need_update?).and_return(true)
- allow(provider).to receive(:basic_validation).and_return(true)
- allow(provider).to receive(:run_schtasks).and_return("CREATE", { "F" => "", "SC" => :once, "ST" => "00:00", "SD" => "12/12/2012", "TR" => nil, "RU" => "SYSTEM" })
- expect(provider).to receive(:update_task_xml)
- provider.run_action(:create)
- expect(new_resource).to be_updated_by_last_action
- end
+ describe "#trigger" do
+ it "returns the trigger values in hash format" do
+ new_resource.start_day "12/02/2017"
+ new_resource.start_time "17:30"
+ new_resource.frequency :minute
+ new_resource.frequency_modifier 15
+ new_resource.random_delay 60
+ result = {
+ :start_year => 2017,
+ :start_month => 12,
+ :start_day => 2,
+ :start_hour => 17,
+ :start_minute => 30,
+ :end_month => 0,
+ :end_day => 0,
+ :end_year => 0,
+ :trigger_type => 1,
+ :type => { :once => nil },
+ :random_minutes_interval => 60,
+ :minutes_interval => 15,
+ :run_on_last_day_of_month => false,
+ :run_on_last_week_of_month => false
+
+ }
+ expect(provider.send(:trigger)).to eq(result)
end
end
- describe "#action_run" do
- it "does nothing if the task doesn't exist" do
- allow(provider).to receive(:load_task_hash)
- provider.load_current_resource
- provider.run_action(:run)
- expect(new_resource).not_to be_updated_by_last_action
- end
-
- context "when the task exists" do
- it "does nothing if the task is already running" do
- task_hash[:Status] = "Running"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- provider.run_action(:run)
- expect(new_resource).not_to be_updated_by_last_action
- end
-
- it "runs the task" do
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- expect(provider).to receive(:run_schtasks).with("RUN")
- provider.run_action(:run)
- expect(new_resource).to be_updated_by_last_action
- end
+ describe "#convert_hours_in_minutes" do
+ it "converts given hours in minutes" do
+ expect(provider.send(:convert_hours_in_minutes, 5)).to eq(300)
end
end
- describe "#action_delete" do
- it "deletes the task if it exists" do
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- expect(provider).to receive(:run_schtasks).with("DELETE", { "F" => "" })
- provider.run_action(:delete)
- expect(new_resource).to be_updated_by_last_action
+ describe "#trigger_type" do
+ it "returns 1 if frequency :once" do
+ new_resource.frequency :once
+ expect(provider.send(:trigger_type)).to eq(1)
end
- it "does nothing if the task doesn't exist" do
- allow(provider).to receive(:load_task_hash)
- provider.load_current_resource
- provider.run_action(:delete)
- expect(new_resource).not_to be_updated_by_last_action
+ it "returns 2 if frequency :daily" do
+ new_resource.frequency :daily
+ expect(provider.send(:trigger_type)).to eq(2)
end
- end
- describe "#action_end" do
- it "does nothing if the task doesn't exist" do
- allow(provider).to receive(:load_task_hash)
- provider.load_current_resource
- provider.run_action(:end)
- expect(new_resource).not_to be_updated_by_last_action
- end
-
- context "when the task exists" do
- it "does nothing if the task is not running" do
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- provider.run_action(:end)
- expect(new_resource).not_to be_updated_by_last_action
- end
-
- it "ends the task if it's running" do
- task_hash[:Status] = "Running"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- expect(provider).to receive(:run_schtasks).with("END")
- provider.run_action(:end)
- expect(new_resource).to be_updated_by_last_action
- end
+ it "returns 3 if frequency :weekly" do
+ new_resource.frequency :weekly
+ expect(provider.send(:trigger_type)).to eq(3)
end
- end
- describe "#action_enable" do
- it "raises error if the task doesn't exist" do
- allow(provider).to receive(:load_task_hash)
- provider.load_current_resource
- expect { provider.run_action(:enable) }.to raise_error(Errno::ENOENT)
- end
-
- context "when the task exists" do
- it "does nothing if the task is already enabled" do
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- provider.run_action(:enable)
- expect(new_resource).not_to be_updated_by_last_action
- end
-
- it "enables the task if it exists" do
- task_hash[:ScheduledTaskState] = "Disabled"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- expect(provider).to receive(:run_schtasks).with("CHANGE", { "ENABLE" => "" })
- provider.run_action(:enable)
- expect(new_resource).to be_updated_by_last_action
- end
+ it "returns 4 if frequency :monthly" do
+ new_resource.frequency :monthly
+ expect(provider.send(:trigger_type)).to eq(4)
+ end
+
+ it "returns 5 if frequency :monthly and frequency_modifier is 'first, second'" do
+ new_resource.frequency :monthly
+ new_resource.frequency_modifier "first, second"
+ expect(provider.send(:trigger_type)).to eq(5)
end
- end
- describe "#action_disable" do
- it "does nothing if the task doesn't exist" do
- allow(provider).to receive(:load_task_hash)
- provider.load_current_resource
- provider.run_action(:disable)
- expect(new_resource).not_to be_updated_by_last_action
- end
-
- context "when the task exists" do
- it "disables the task if it's enabled" do
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- expect(provider).to receive(:run_schtasks).with("CHANGE", { "DISABLE" => "" })
- provider.run_action(:disable)
- expect(new_resource).to be_updated_by_last_action
- end
-
- it "does nothing if the task is already disabled" do
- task_hash[:ScheduledTaskState] = "Disabled"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- provider.run_action(:disable)
- expect(new_resource).not_to be_updated_by_last_action
- end
+ it "returns 6 if frequency :on_idle" do
+ new_resource.frequency :on_idle
+ expect(provider.send(:trigger_type)).to eq(6)
end
- end
- describe "#run_schtasks" do
- before do
- @task_action = "CREATE"
- @options = { "F" => "", "SC" => :minute, "MO" => 15, "TR" => "chef-client", "RU" => "SYSTEM", "RL" => "HIGHEST" }
- @cmd = "schtasks /CREATE /TN \"sample_task\" /F /SC \"minute\" /MO \"15\" /RU \"SYSTEM\" /RL \"HIGHEST\" /TR \"chef-client \" "
+ it "returns 8 if frequency :onstart" do
+ new_resource.frequency :onstart
+ expect(provider.send(:trigger_type)).to eq(8)
end
- it "forms the command properly from the given options" do
- expect(provider).to receive(:shell_out!).with(@cmd, { :returns => [0] })
- provider.send(:run_schtasks, @task_action, @options)
+ it "returns 9 if frequency :on_logon" do
+ new_resource.frequency :on_logon
+ expect(provider.send(:trigger_type)).to eq(9)
end
end
- describe "#basic_validation" do
- context "when command doesn't exist" do
- it "raise error" do
- new_resource.command ""
- expect { provider.send(:basic_validation) }.to raise_error(Chef::Exceptions::ValidationFailed)
- end
+ describe "#type" do
+ it "returns type hash when frequency :once" do
+ new_resource.frequency :once
+ new_resource.frequency_modifier 2
+ result = provider.send(:type)
+ expect(result).to include(:once)
+ expect(result).to eq({ :once => nil })
end
- context "when task_name doesn't exist" do
- let(:new_resource) { Chef::Resource::WindowsTask.new("") }
- it "raise error" do
- expect { provider.send(:basic_validation) }.to raise_error(Chef::Exceptions::ValidationFailed)
- end
+ it "returns type hash when frequency :daily" do
+ new_resource.frequency :daily
+ new_resource.frequency_modifier 2
+ result = provider.send(:type)
+ expect(result).to include(:days_interval)
+ expect(result).to eq({ days_interval: 2 })
end
- context "when task_name and command exists" do
- it "returns true" do
- new_resource.command "cd ~/"
- expect(provider.send(:basic_validation)).to be(true)
- end
+ it "returns type hash when frequency :weekly" do
+ new_resource.start_day "01/02/2018"
+ new_resource.frequency :weekly
+ new_resource.frequency_modifier 2
+ result = provider.send(:type)
+ expect(result).to include(:weeks_interval)
+ expect(result).to include(:days_of_week)
+ expect(result).to eq({ weeks_interval: 2, days_of_week: 4 })
end
- end
- describe "#task_need_update?" do
- context "when task doesn't exist" do
- before do
- allow(provider).to receive(:load_task_hash)
- provider.load_current_resource
- end
-
- it "returns true" do
- new_resource.command "chef-client"
- expect(provider.send(:task_need_update?)).to be(true)
- end
- end
-
- context "when the task exists" do
- before do
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- allow(provider).to receive(:get_system_short_date_format).and_return("MM/dd/yyyy")
- provider.load_current_resource
-
- new_resource.command "chef-client -L C:\\tmp\\"
- new_resource.run_level :highest
- new_resource.frequency :minute
- new_resource.frequency_modifier 15
- new_resource.user "SYSTEM"
- new_resource.execution_time_limit "PT72H"
- new_resource.start_day "03/30/2017"
- new_resource.start_time "13:12"
- end
-
- context "when no attributes are modified" do
- it "returns false" do
- expect(provider.send(:task_need_update?)).to be(false)
- end
- end
-
- context "when frequency_modifier is updated" do
- it "returns true" do
- new_resource.frequency_modifier 25
- expect(provider.send(:task_need_update?)).to be(true)
- end
- end
-
- context "when months are updated" do
- it "returns true" do
- new_resource.months "JAN"
- expect(provider.send(:task_need_update?)).to be(true)
- end
- end
-
- context "when start_day is updated" do
- it "returns true" do
- new_resource.start_day "01/01/2000"
- expect(provider.send(:task_need_update?)).to be(true)
- end
- end
-
- context "when start_time updated" do
- it "returns true" do
- new_resource.start_time "01:01"
- expect(provider.send(:task_need_update?)).to be(true)
- end
- end
-
- context "when command updated" do
- it "return true" do
- new_resource.command "chef-client"
- expect(provider.send(:task_need_update?)).to be(true)
- end
- end
+ it "returns type hash when frequency :monthly" do
+ new_resource.frequency :monthly
+ result = provider.send(:type)
+ expect(result).to include(:months)
+ expect(result).to include(:days)
+ expect(result).to eq({ months: 4095, days: 1 })
end
- end
- describe "#start_day_updated?" do
- before do
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- allow(provider).to receive(:get_system_short_date_format).and_return("MM/dd/yyyy")
- provider.load_current_resource
+ it "returns type hash when frequency :monthly with frequency_modifier 'first, second, third'" do
+ new_resource.start_day "01/02/2018"
+ new_resource.frequency :monthly
+ new_resource.frequency_modifier "First, Second, third"
+ result = provider.send(:type)
+ expect(result).to include(:months)
+ expect(result).to include(:days_of_week)
+ expect(result).to include(:weeks_of_month)
+ expect(result).to eq({ months: 4095, days_of_week: 4, weeks_of_month: 7 })
+ end
- new_resource.command "chef-client"
- new_resource.run_level :highest
- new_resource.frequency :minute
- new_resource.frequency_modifier 15
- new_resource.user "SYSTEM"
- new_resource.execution_time_limit "PT72H"
- new_resource.start_day "03/30/2017"
- new_resource.start_time "13:12"
+ it "returns type hash when frequency :on_idle" do
+ new_resource.frequency :on_idle
+ result = provider.send(:type)
+ expect(result).to eq(nil)
end
- context "when start_day not changed" do
- it "returns false" do
- expect(provider.send(:start_day_updated?)).to be(false)
- end
+
+ it "returns type hash when frequency :onstart" do
+ new_resource.frequency :onstart
+ result = provider.send(:type)
+ expect(result).to eq(nil)
end
- context "when start_day changed" do
- it "returns true" do
- new_resource.start_day "01/01/2000"
- expect(provider.send(:start_day_updated?)).to be(true)
- end
+ it "returns type hash when frequency :on_logon" do
+ new_resource.frequency :on_logon
+ result = provider.send(:type)
+ expect(result).to eq(nil)
end
end
- describe "#start_time_updated?" do
- before do
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
+ describe "#weeks_of_month" do
+ it "returns the binary value 1 if frequency_modifier is set as 'first'" do
+ new_resource.frequency_modifier "first"
+ expect(provider.send(:weeks_of_month)).to eq(1)
+ end
- new_resource.command "chef-client"
- new_resource.run_level :highest
- new_resource.frequency :minute
- new_resource.frequency_modifier 15
- new_resource.user "SYSTEM"
- new_resource.execution_time_limit "PT72H"
- new_resource.start_day "3/30/2017"
- new_resource.start_time "13:12"
+ it "returns the binary value 2 if frequency_modifier is set as 'second'" do
+ new_resource.frequency_modifier "second"
+ expect(provider.send(:weeks_of_month)).to eq(2)
end
- context "when start_time not changed" do
- it "returns false" do
- expect(provider.send(:start_time_updated?)).to be(false)
- end
+
+ it "returns the binary value 4 if frequency_modifier is set as 'third'" do
+ new_resource.frequency_modifier "third"
+ expect(provider.send(:weeks_of_month)).to eq(4)
end
- context "when start_time changed" do
- it "returns true" do
- new_resource.start_time "01:01"
- expect(provider.send(:start_time_updated?)).to be(true)
- end
+ it "returns the binary value 8 if frequency_modifier is set as 'fourth'" do
+ new_resource.frequency_modifier "fourth"
+ expect(provider.send(:weeks_of_month)).to eq(8)
end
- end
- describe "#convert_user_date_to_system_date" do
- it "when current resource start date is '05/30/2017' then returns '30/05/2017'" do
- allow(provider).to receive(:get_system_short_date_format).and_return("dd/MM/yyyy")
- expect(provider.send(:convert_user_date_to_system_date, "05/30/2017")).to eq("30/05/2017")
+ it "returns the binary value 16 if frequency_modifier is set as 'last'" do
+ new_resource.frequency_modifier "last"
+ expect(provider.send(:weeks_of_month)).to eq(nil)
end
end
- describe "#convert_system_date_format_to_ruby_date_format" do
- context "when system date format 'dd-MMM-yy'" do
- it "returns '%d-%b-%y'" do
- allow(provider).to receive(:get_system_short_date_format).and_return("dd-MMM-yy")
- expect(provider.send(:convert_system_date_format_to_ruby_date_format)).to eq("%d-%b-%y")
- end
+ describe "#weeks_of_month" do
+ it "returns the binary value 1 if frequency_modifier is set as 'first'" do
+ new_resource.frequency_modifier "first"
+ expect(provider.send(:weeks_of_month)).to eq(1)
end
- context "when system date format 'dd/MM/yyyy'" do
- it "returns '%d/%m/%Y'" do
- allow(provider).to receive(:get_system_short_date_format).and_return("dd/MM/yyyy")
- expect(provider.send(:convert_system_date_format_to_ruby_date_format)).to eq("%d/%m/%Y")
- end
+ it "returns the binary value 2 if frequency_modifier is set as 'second'" do
+ new_resource.frequency_modifier "second"
+ expect(provider.send(:weeks_of_month)).to eq(2)
end
- end
- describe "#convert_system_date_format_to_ruby_long_date" do
- context "when system date format 'dd-MMM-yy'" do
- it "returns '%d-%m-%Y'" do
- allow(provider).to receive(:get_system_short_date_format).and_return("dd-MMM-yy")
- expect(provider.send(:convert_system_date_format_to_ruby_long_date)).to eq("%d-%m-%Y")
- end
+ it "returns the binary value 4 if frequency_modifier is set as 'third'" do
+ new_resource.frequency_modifier "third"
+ expect(provider.send(:weeks_of_month)).to eq(4)
end
- context "when system date format 'dd/MM/yyyy'" do
- it "returns '%d/%m/%Y'" do
- allow(provider).to receive(:get_system_short_date_format).and_return("dd/MM/yyyy")
- expect(provider.send(:convert_system_date_format_to_ruby_long_date)).to eq("%d/%m/%Y")
- end
+ it "returns the binary value 8 if frequency_modifier is set as 'fourth'" do
+ new_resource.frequency_modifier "fourth"
+ expect(provider.send(:weeks_of_month)).to eq(8)
end
- end
- describe "#common_date_format_conversion" do
- context "when system date format 'dd-MM-yyyy'" do
- it "returns '%d-%m-%Y'" do
- expect(provider.send(:common_date_format_conversion, "dd-MM-yyyy")).to eq("%d-%m-%Y")
- end
+ it "returns the binary value 16 if frequency_modifier is set as 'last'" do
+ new_resource.frequency_modifier "last"
+ expect(provider.send(:weeks_of_month)).to eq(nil)
end
- context "when system date format 'd-M-yyyy'" do
- it "returns '%d-%m-%Y'" do
- expect(provider.send(:common_date_format_conversion, "dd-MM-yyyy")).to eq("%d-%m-%Y")
- end
+ it "returns the binary value 15 if frequency_modifier is set as 'first, second, third, fourth'" do
+ new_resource.frequency_modifier "first, second, third, fourth"
+ expect(provider.send(:weeks_of_month)).to eq(15)
end
end
- describe "#update_task_xml" do
- before do
- new_resource.command "chef-client"
- new_resource.run_level :highest
- new_resource.frequency :minute
- new_resource.frequency_modifier 15
- new_resource.user "SYSTEM"
- new_resource.random_delay "20"
- end
-
- it "does nothing if the task doesn't exist" do
- task_xml = double("xml", :exitstatus => 1)
- allow(provider).to receive(:powershell_out).and_return(task_xml)
- output = provider.send(:update_task_xml, ["random_delay"])
- expect(output).to be(nil)
- end
-
- it "updates the task XML if random_delay is passed" do
- shell_out_obj = double("xml", :exitstatus => 0, :stdout => task_xml)
- allow(provider).to receive(:powershell_out).and_return(shell_out_obj)
- expect(::File).to receive(:join)
- expect(::File).to receive(:open)
- expect(::File).to receive(:delete)
- expect(provider).to receive(:run_schtasks).twice
- output = provider.send(:update_task_xml, ["random_delay"])
- end
-
- it "updates the task XML if frequency is set as `:none`" do
- new_resource.frequency :none
- new_resource.random_delay ""
- shell_out_obj = double("xml", :exitstatus => 0, :stdout => task_xml)
- allow(provider).to receive(:powershell_out).and_return(shell_out_obj)
- expect(::File).to receive(:delete)
- expect(::File).to receive(:join)
- expect(::File).to receive(:open)
- expect(provider).to receive(:run_schtasks).twice
- output = provider.send(:update_task_xml, ["random_delay"])
+ # REF: https://msdn.microsoft.com/en-us/library/windows/desktop/aa382063(v=vs.85).aspx
+ describe "#days_of_month" do
+ it "returns the binary value 1 if day is set as 1" do
+ new_resource.day "1"
+ expect(provider.send(:days_of_month)).to eq(1)
end
- end
- describe "#load_task_hash" do
- it "returns false if the task doesn't exist" do
- allow(provider).to receive_message_chain(:powershell_out, :stdout, :force_encoding).and_return("")
- allow(provider).to receive(:load_task_xml)
- expect(provider.send(:load_task_hash, "chef-client")).to be(false)
+ it "returns the binary value 2 if day is set as 2" do
+ new_resource.day "2"
+ expect(provider.send(:days_of_month)).to eq(2)
end
- it "returns task hash if the task exists" do
- powershell_output = "\r\nFolder: \\\r\nHostName: NIMISHA-PC\r\nTaskName: \\chef-client\r\n"
- task_h = { :"" => "", :Folder => "\\", :HostName => "NIMISHA-PC", :TaskName => "\\chef-client" }
- allow(provider).to receive_message_chain(:powershell_out, :stdout, :force_encoding).and_return(powershell_output)
- allow(provider).to receive(:load_task_xml).with("chef-client")
- expect(provider.send(:load_task_hash, "chef-client")).to eq(task_h)
+ it "returns the binary value 1073741824 if day is set as 31" do
+ new_resource.day "31"
+ expect(provider.send(:days_of_month)).to eq(1073741824)
+ end
+
+ it "returns the binary value 131072 if day is set as 18" do
+ new_resource.day "18"
+ expect(provider.send(:days_of_month)).to eq(131072)
end
end
- describe "#frequency_modifier_allowed" do
- it "returns true for frequency :hourly" do
- new_resource.frequency :hourly
- expect(provider.send(:frequency_modifier_allowed)).to be(true)
+ #Ref : https://msdn.microsoft.com/en-us/library/windows/desktop/aa380729(v=vs.85).aspx
+ describe "#days_of_week" do
+ it "returns the binary value 2 if day is set as 'Mon'" do
+ new_resource.day "Mon"
+ expect(provider.send(:days_of_week)).to eq(2)
end
- it "returns true for frequency :monthly if frequency_modifier is THIRD" do
- new_resource.frequency :monthly
- new_resource.frequency_modifier "THIRD"
- expect(provider.send(:frequency_modifier_allowed)).to be(true)
+ it "returns the binary value 4 if day is set as 'Tue'" do
+ new_resource.day "Tue"
+ expect(provider.send(:days_of_week)).to eq(4)
end
- it "returns false for frequency :once" do
- new_resource.frequency :once
- expect(provider.send(:frequency_modifier_allowed)).to be(false)
+ it "returns the binary value 8 if day is set as 'Wed'" do
+ new_resource.day "Wed"
+ expect(provider.send(:days_of_week)).to eq(8)
+ end
+
+ it "returns the binary value 16 if day is set as 'Thu'" do
+ new_resource.day "Thu"
+ expect(provider.send(:days_of_week)).to eq(16)
end
- it "returns false for frequency :none" do
- new_resource.frequency :none
- expect(provider.send(:frequency_modifier_allowed)).to be(false)
+ it "returns the binary value 32 if day is set as 'Fri'" do
+ new_resource.day "Fri"
+ expect(provider.send(:days_of_week)).to eq(32)
+ end
+
+ it "returns the binary value 64 if day is set as 'Sat'" do
+ new_resource.day "Sat"
+ expect(provider.send(:days_of_week)).to eq(64)
+ end
+
+ it "returns the binary value 1 if day is set as 'Sun'" do
+ new_resource.day "Sun"
+ expect(provider.send(:days_of_week)).to eq(1)
+ end
+
+ it "returns the binary value 127 if day is set as 'Mon, tue, wed, thu, fri, sat, sun'" do
+ new_resource.day "Mon, tue, wed, thu, fri, sat, sun"
+ expect(provider.send(:days_of_week)).to eq(127)
end
end
- # In windows_task resource sec_to_dur method converts seconds to duration in format 60 == 'PT60S'
- # random_delay_updated? method use the value return by sec_to_dur as input for comparison for new_resource.random_delay mocking the same here
- describe "#random_delay_updated?" do
- before do
- new_resource.command "chef-client"
- new_resource.run_level :highest
- new_resource.frequency :minute
- new_resource.frequency_modifier 15
- new_resource.user "SYSTEM"
+ # REf: https://msdn.microsoft.com/en-us/library/windows/desktop/aa382064(v=vs.85).aspx
+ describe "#monts_of_year" do
+ it "returns the binary value 1 if day is set as 'Jan'" do
+ new_resource.months "Jan"
+ expect(provider.send(:months_of_year)).to eq(1)
end
- it "returns false if current_resource.random_delay = nil & random_delay is set to '0' seconds" do
- task_hash[:random_delay] = nil
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- new_resource.random_delay = "PT0S"
- expect(provider.send(:random_delay_updated?)).to be(false)
+ it "returns the binary value 2 if day is set as 'Feb'" do
+ new_resource.months "Feb"
+ expect(provider.send(:months_of_year)).to eq(2)
end
- it "returns false if current_resource.random_delay = 'P7D' & random_delay is set to '604800' seconds " do
- task_hash[:random_delay] = "P7D"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- new_resource.random_delay = "PT604800S"
- expect(provider.send(:random_delay_updated?)).to be(false)
+ it "returns the binary value 4 if day is set as 'Mar'" do
+ new_resource.months "Mar"
+ expect(provider.send(:months_of_year)).to eq(4)
end
- it "returns false if current_resource.random_delay = 'P7DT1S' & random_delay is set to '604801' seconds" do
- task_hash[:random_delay] = "P7DT1S"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- new_resource.random_delay = "PT604801S"
- expect(provider.send(:random_delay_updated?)).to be(false)
+ it "returns the binary value 8 if day is set as 'Apr'" do
+ new_resource.months "Apr"
+ expect(provider.send(:months_of_year)).to eq(8)
end
- it "returns true if current_resource.random_delay = 'PT1S' & random_delay is set to '3600' seconds" do
- task_hash[:random_delay] = "PT1S"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- new_resource.random_delay = "PT3600S"
- expect(provider.send(:random_delay_updated?)).to be(true)
+ it "returns the binary value 16 if day is set as 'May'" do
+ new_resource.months "May"
+ expect(provider.send(:months_of_year)).to eq(16)
end
- it "returns false if current_resource.random_delay = 'P2Y1MT2H' & random_delay is set to '65707200' seconds" do
- task_hash[:random_delay] = "P2Y1MT2H"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- new_resource.random_delay = "PT65707200S"
- expect(provider.send(:random_delay_updated?)).to be(false)
+ it "returns the binary value 32 if day is set as 'Jun'" do
+ new_resource.months "Jun"
+ expect(provider.send(:months_of_year)).to eq(32)
+ end
+
+ it "returns the binary value 64 if day is set as 'Jul'" do
+ new_resource.months "Jul"
+ expect(provider.send(:months_of_year)).to eq(64)
+ end
+
+ it "returns the binary value 128 if day is set as 'Aug'" do
+ new_resource.months "Aug"
+ expect(provider.send(:months_of_year)).to eq(128)
+ end
+
+ it "returns the binary value 256 if day is set as 'Sep'" do
+ new_resource.months "Sep"
+ expect(provider.send(:months_of_year)).to eq(256)
+ end
+
+ it "returns the binary value 512 if day is set as 'Oct'" do
+ new_resource.months "Oct"
+ expect(provider.send(:months_of_year)).to eq(512)
+ end
+
+ it "returns the binary value 1024 if day is set as 'Nov'" do
+ new_resource.months "Nov"
+ expect(provider.send(:months_of_year)).to eq(1024)
+ end
+
+ it "returns the binary value 2048 if day is set as 'Dec'" do
+ new_resource.months "Dec"
+ expect(provider.send(:months_of_year)).to eq(2048)
+ end
+
+ it "returns the binary value 4095 if day is set as 'jan, Feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec'" do
+ new_resource.months "jan, Feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec"
+ expect(provider.send(:months_of_year)).to eq(4095)
end
end
- describe "#execution_time_limit_updated?" do
- before do
- new_resource.command "chef-client"
+ describe "#run_level" do
+ it "return binary value 1 for run_level highest" do
new_resource.run_level :highest
- new_resource.frequency :minute
- new_resource.frequency_modifier 15
- new_resource.user "SYSTEM"
+ expect(provider.send(:run_level)).to be(1)
end
- it "returns false if current_resource.execution_time_limit = 'P7D' & execution_time_limit is set to 604800 seconds " do
- task_hash[:execution_time_limit] = "P7D"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- new_resource.execution_time_limit = "PT604800S"
- expect(provider.send(:execution_time_limit_updated?)).to be(false)
+ it "return binary value 1 for run_level limited" do
+ new_resource.run_level :limited
+ expect(provider.send(:run_level)).to be(0)
end
+ end
- it "returns false if current_resource.execution_time_limit = 'P7DT1S' & execution_time_limit is set to 604801 seconds" do
- task_hash[:execution_time_limit] = "P7DT1S"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- new_resource.execution_time_limit = "PT604801S"
- expect(provider.send(:execution_time_limit_updated?)).to be(false)
+ describe "#logon_type" do
+ it "return logon_type bindary value as 5 as if password is nil" do
+ new_resource.password = nil
+ expect(provider.send(:logon_type)).to be(5)
end
- it "returns true if current_resource.execution_time_limit = 'PT1S' & execution_time_limit is set to '3600' seconds" do
- task_hash[:execution_time_limit] = "PT1S"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- new_resource.execution_time_limit = "PT3600S"
- expect(provider.send(:execution_time_limit_updated?)).to be(true)
+ it "return logon_type bindary value as 1 as if password is not nil" do
+ new_resource.password = "abc"
+ expect(provider.send(:logon_type)).to be(1)
end
+ end
- it "returns false if current_resource.execution_time_limit = 'P2Y1MT2H' & execution_time_limit is set to '65707200' seconds" do
- task_hash[:execution_time_limit] = "P2Y1MT2H"
- allow(provider).to receive(:load_task_hash).and_return(task_hash)
- provider.load_current_resource
- new_resource.execution_time_limit = "PT65707200S"
- expect(provider.send(:execution_time_limit_updated?)).to be(false)
+ describe "#get_day" do
+ it "return day if date is provided" do
+ expect(provider.send(:get_day, "01/02/2018")).to eq("TUE")
end
end
end
diff --git a/spec/unit/resource/windows_task_spec.rb b/spec/unit/resource/windows_task_spec.rb
index 4b74a4f78a..6dbda35274 100644
--- a/spec/unit/resource/windows_task_spec.rb
+++ b/spec/unit/resource/windows_task_spec.rb
@@ -18,7 +18,7 @@
require "spec_helper"
-describe Chef::Resource::WindowsTask do
+describe Chef::Resource::WindowsTask, :windows_only do
let(:resource) { Chef::Resource::WindowsTask.new("sample_task") }
it "sets resource name as :windows_task" do
@@ -53,11 +53,16 @@ describe Chef::Resource::WindowsTask do
expect(resource.frequency_modifier).to eql(1)
end
- it "sets the default frequency as :hourly" do
- expect(resource.frequency).to eql(:hourly)
+ context "when frequency is not provided" do
+ it "raises ArgumentError to provide frequency" do
+ expect { resource.after_created }.to raise_error(ArgumentError, "Frequency needs to be provided. Valid frequencies are :minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none." )
+ end
end
context "when user is set but password is not" do
+ before do
+ resource.frequency :hourly
+ end
it "raises an error if the user is a non-system user" do
resource.user "bob"
expect { resource.after_created }.to raise_error(ArgumentError, %q{Cannot specify a user other than the system users without specifying a password!. Valid passwordless users: 'NT AUTHORITY\SYSTEM', 'SYSTEM', 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', 'USERS'})
@@ -75,10 +80,12 @@ describe Chef::Resource::WindowsTask do
end
context "when random_delay is passed" do
- it "raises error if frequency is `:once`" do
+ # changed this sepc since random_delay property is valid with it frequency :once
+ it "not raises error if frequency is `:once`" do
resource.frequency :once
resource.random_delay "20"
- expect { resource.after_created }.to raise_error(ArgumentError, "`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly")
+ resource.start_time "15:00"
+ expect { resource.after_created }.to_not raise_error(ArgumentError, "`random_delay` property is supported only for frequency :once, :minute, :hourly, :daily, :weekly and :monthly")
end
it "raises error for invalid random_delay" do
@@ -93,29 +100,30 @@ describe Chef::Resource::WindowsTask do
expect { resource.after_created }.to raise_error(ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60').")
end
- it "converts seconds String into iso8601 duration format" do
+ it "converts '60' seconds into integer 1 minute format" do
resource.frequency :monthly
resource.random_delay "60"
resource.after_created
- expect(resource.random_delay).to eq("PT60S")
+ expect(resource.random_delay).to eq(1)
end
- it "converts seconds Integer into iso8601 duration format" do
+ it "converts 60 Integer into integer 1 minute format" do
resource.frequency :monthly
resource.random_delay 60
resource.after_created
- expect(resource.random_delay).to eq("PT60S")
+ expect(resource.random_delay).to eq(1)
end
it "raises error that random_delay is not supported" do
- expect { resource.send(:validate_random_delay, 60, :on_idle) }.to raise_error(ArgumentError, "`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly")
+ expect { resource.send(:validate_random_delay, 60, :on_idle) }.to raise_error(ArgumentError, "`random_delay` property is supported only for frequency :once, :minute, :hourly, :daily, :weekly and :monthly")
end
end
context "when execution_time_limit isn't specified" do
- it "sets the default value to PT72H" do
+ it "sets the default value to PT72H which get converted to minute as 4320" do
+ resource.frequency :hourly
resource.after_created
- expect(resource.execution_time_limit).to eq("PT72H")
+ expect(resource.execution_time_limit).to eq(4320)
end
end
@@ -130,16 +138,18 @@ describe Chef::Resource::WindowsTask do
expect { resource.after_created }.to raise_error(ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60').")
end
- it "converts seconds Integer into iso8601 format" do
+ it "converts seconds Integer into integer minute format" do
+ resource.frequency :hourly
resource.execution_time_limit 60
resource.after_created
- expect(resource.execution_time_limit).to eq("PT60S")
+ expect(resource.execution_time_limit).to eq(1)
end
- it "converts seconds String into iso8601 format" do
+ it "converts seconds String into integer minute format" do
+ resource.frequency :hourly
resource.execution_time_limit "60"
resource.after_created
- expect(resource.execution_time_limit).to eq("PT60S")
+ expect(resource.execution_time_limit).to eq(1)
end
end
@@ -166,15 +176,23 @@ describe Chef::Resource::WindowsTask do
end
context "#validate_start_day" do
- it "raise error if start_day is passed with invalid frequency (:on_logon)" do
- expect { resource.send(:validate_start_day, "02/07/1984", :on_logon) }.to raise_error(ArgumentError, "`start_day` property is not supported with frequency: on_logon")
+ it "not to raise error if start_day is passed with invalid frequency (:onstart)" do
+ expect { resource.send(:validate_start_day, "02/07/1984", :onstart) }.not_to raise_error
+ end
+
+ it "not to raise error if start_day is passed with invalid frequency (:on_idle)" do
+ expect { resource.send(:validate_start_day, "02/07/1984", :on_idle) }.not_to raise_error
+ end
+
+ it "not to raise error if start_day is passed with invalid frequency (:on_logon)" do
+ expect { resource.send(:validate_start_day, "02/07/1984", :on_logon) }.not_to raise_error
end
- it "does not raise error if start_day is passed with valid frequency (:weekly)" do
+ it "not raise error if start_day is passed with valid frequency (:weekly)" do
expect { resource.send(:validate_start_day, "02/07/1984", :weekly) }.not_to raise_error
end
- it "raise error if start_day is passed with invalid date format (DD/MM/YYYY)" do
+ it "not to raise error if start_day is passed with invalid date format (DD/MM/YYYY)" do
expect { resource.send(:validate_start_day, "28/12/2009", :weekly) }.to raise_error(ArgumentError, "`start_day` property must be in the MM/DD/YYYY format.")
end
@@ -224,73 +242,73 @@ describe Chef::Resource::WindowsTask do
context "when frequency is :monthly" do
it "raises error if frequency_modifier > 12" do
- expect { resource.send(:validate_create_frequency_modifier, :monthly, 14) }.to raise_error("frequency_modifier value 14 is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'.")
+ expect { resource.send(:validate_create_frequency_modifier, :monthly, 14) }.to raise_error("frequency_modifier value 14 is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'.")
end
it "raises error if frequency_modifier is invalid" do
- expect { resource.send(:validate_create_frequency_modifier, :monthly, "abc") }.to raise_error("frequency_modifier value abc is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'.")
+ expect { resource.send(:validate_create_frequency_modifier, :monthly, "abc") }.to raise_error("frequency_modifier value abc is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'.")
end
end
end
context "#validate_create_day" do
it "raises error if frequency is not :weekly or :monthly" do
- expect { resource.send(:validate_create_day, "Mon", :once) }.to raise_error("day property is only valid for tasks that run monthly or weekly")
+ expect { resource.send(:validate_create_day, "Mon", :once, 1) }.to raise_error("day property is only valid for tasks that run monthly or weekly")
end
it "accepts a valid single day" do
- expect { resource.send(:validate_create_day, "Mon", :weekly) }.not_to raise_error
+ expect { resource.send(:validate_create_day, "Mon", :weekly, 1) }.not_to raise_error
end
it "accepts a comma separated list of valid days" do
- expect { resource.send(:validate_create_day, "Mon, tue, THU", :weekly) }.not_to raise_error
+ expect { resource.send(:validate_create_day, "Mon, tue, THU", :weekly, 1) }.not_to raise_error
end
it "raises error for invalid day value" do
- expect { resource.send(:validate_create_day, "xyz", :weekly) }.to raise_error(ArgumentError, "day property invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma.")
+ expect { resource.send(:validate_create_day, "xyz", :weekly, 1) }.to raise_error(ArgumentError, "day property invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN, *. Multiple values must be separated by a comma.")
end
end
context "#validate_create_months" do
it "raises error if frequency is not :monthly" do
- expect { resource.send(:validate_create_months, "Jan", :once) }.to raise_error(ArgumentError, "months property is only valid for tasks that run monthly")
+ expect { resource.send(:validate_create_months, "Jan", :once) }.to raise_error(ArgumentError, "months property is only valid for tasks that run monthly")
end
it "accepts a valid single month" do
- expect { resource.send(:validate_create_months, "Feb", :monthly) }.not_to raise_error
+ expect { resource.send(:validate_create_months, "Feb", :monthly) }.not_to raise_error
end
it "accepts a comma separated list of valid months" do
- expect { resource.send(:validate_create_months, "Jan, mar, AUG", :monthly) }.not_to raise_error
+ expect { resource.send(:validate_create_months, "Jan, mar, AUG", :monthly) }.not_to raise_error
end
it "raises error for invalid month value" do
- expect { resource.send(:validate_create_months, "xyz", :monthly) }.to raise_error(ArgumentError, "months property invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma.")
+ expect { resource.send(:validate_create_months, "xyz", :monthly) }.to raise_error(ArgumentError, "months property invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC, *. Multiple values must be separated by a comma.")
end
end
context "#validate_idle_time" do
it "raises error if frequency is not :on_idle" do
[:minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :none].each do |frequency|
- expect { resource.send(:validate_idle_time, 5, frequency) }.to raise_error(ArgumentError, "idle_time property is only valid for tasks that run on_idle")
+ expect { resource.send(:validate_idle_time, 5, frequency) }.to raise_error(ArgumentError, "idle_time property is only valid for tasks that run on_idle")
end
end
it "raises error if idle_time > 999" do
- expect { resource.send(:validate_idle_time, 1000, :on_idle) }.to raise_error(ArgumentError, "idle_time value 1000 is invalid. Valid values for :on_idle frequency are 1 - 999.")
+ expect { resource.send(:validate_idle_time, 1000, :on_idle) }.to raise_error(ArgumentError, "idle_time value 1000 is invalid. Valid values for :on_idle frequency are 1 - 999.")
end
it "raises error if idle_time < 0" do
- expect { resource.send(:validate_idle_time, -5, :on_idle) }.to raise_error(ArgumentError, "idle_time value -5 is invalid. Valid values for :on_idle frequency are 1 - 999.")
+ expect { resource.send(:validate_idle_time, -5, :on_idle) }.to raise_error(ArgumentError, "idle_time value -5 is invalid. Valid values for :on_idle frequency are 1 - 999.")
end
it "raises error if idle_time is not set" do
- expect { resource.send(:validate_idle_time, nil, :on_idle) }.to raise_error(ArgumentError, "idle_time value should be set for :on_idle frequency.")
+ expect { resource.send(:validate_idle_time, nil, :on_idle) }.to raise_error(ArgumentError, "idle_time value should be set for :on_idle frequency.")
end
it "does not raises error if idle_time is not set for other frequencies" do
[:minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :none].each do |frequency|
- expect { resource.send(:validate_idle_time, nil, frequency) }.not_to raise_error
+ expect { resource.send(:validate_idle_time, nil, frequency) }.not_to raise_error
end
end
end