chef 14.7.17 → 14.8.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef/mixin/which.rb +3 -1
  3. data/lib/chef/provider/apt_repository.rb +1 -1
  4. data/lib/chef/provider/execute.rb +1 -1
  5. data/lib/chef/provider/osx_profile.rb +1 -1
  6. data/lib/chef/provider/package/apt.rb +15 -3
  7. data/lib/chef/provider/package/cab.rb +6 -2
  8. data/lib/chef/provider/package/chocolatey.rb +1 -1
  9. data/lib/chef/provider/package/dnf/python_helper.rb +2 -1
  10. data/lib/chef/provider/package/openbsd.rb +1 -1
  11. data/lib/chef/provider/package/rubygems.rb +38 -16
  12. data/lib/chef/resource/apt_package.rb +1 -1
  13. data/lib/chef/resource/apt_preference.rb +1 -1
  14. data/lib/chef/resource/apt_repository.rb +1 -1
  15. data/lib/chef/resource/chocolatey_config.rb +1 -1
  16. data/lib/chef/resource/chocolatey_source.rb +1 -1
  17. data/lib/chef/resource/cron.rb +27 -8
  18. data/lib/chef/resource/cron_access.rb +1 -1
  19. data/lib/chef/resource/cron_d.rb +8 -8
  20. data/lib/chef/resource/directory.rb +1 -1
  21. data/lib/chef/resource/dmg_package.rb +9 -9
  22. data/lib/chef/resource/execute.rb +2 -2
  23. data/lib/chef/resource/homebrew_cask.rb +1 -1
  24. data/lib/chef/resource/homebrew_tap.rb +1 -1
  25. data/lib/chef/resource/hostname.rb +2 -2
  26. data/lib/chef/resource/kernel_module.rb +1 -1
  27. data/lib/chef/resource/link.rb +1 -1
  28. data/lib/chef/resource/ohai_hint.rb +1 -1
  29. data/lib/chef/resource/package.rb +1 -1
  30. data/lib/chef/resource/scm.rb +1 -1
  31. data/lib/chef/resource/swap_file.rb +1 -1
  32. data/lib/chef/resource/sysctl.rb +1 -1
  33. data/lib/chef/resource/systemd_unit.rb +1 -1
  34. data/lib/chef/resource/template.rb +11 -3
  35. data/lib/chef/resource/windows_ad_join.rb +1 -1
  36. data/lib/chef/resource/windows_auto_run.rb +1 -1
  37. data/lib/chef/resource/windows_certificate.rb +2 -1
  38. data/lib/chef/resource/windows_feature.rb +6 -6
  39. data/lib/chef/resource/windows_feature_dism.rb +13 -17
  40. data/lib/chef/resource/windows_feature_powershell.rb +1 -1
  41. data/lib/chef/resource/windows_share.rb +9 -3
  42. data/lib/chef/resource/windows_task.rb +230 -231
  43. data/lib/chef/resource/windows_workgroup.rb +32 -23
  44. data/lib/chef/resource/yum_repository.rb +1 -1
  45. data/lib/chef/version.rb +1 -1
  46. data/spec/functional/resource/msu_package_spec.rb +14 -0
  47. data/spec/integration/knife/raw_spec.rb +11 -7
  48. data/spec/integration/knife/redirection_spec.rb +6 -4
  49. data/spec/support/shared/integration/app_server_support.rb +2 -2
  50. data/spec/unit/provider/apt_repository_spec.rb +3 -3
  51. data/spec/unit/provider/package/apt_spec.rb +81 -4
  52. data/spec/unit/provider/package/rubygems_spec.rb +47 -9
  53. data/spec/unit/resource/windows_certificate.rb +30 -0
  54. data/spec/unit/resource/windows_feature.rb +4 -0
  55. data/spec/unit/resource/windows_workgroup_spec.rb +27 -0
  56. metadata +4 -4
@@ -65,7 +65,7 @@ class Chef
65
65
  description: "The current working directory from which the command will be run."
66
66
 
67
67
  property :environment, Hash,
68
- description: "Specify a Hash of environment variables to be set."
68
+ description: "A Hash of environment variables in the form of ({'ENV_VARIABLE' => 'VALUE'})."
69
69
 
70
70
  alias :env :environment
71
71
 
@@ -87,7 +87,7 @@ class Chef
87
87
  description: "The amount of time (in seconds) a command is to wait before timing out."
88
88
 
89
89
  property :user, [ String, Integer ],
90
- description: "The user name of the user identity with which to launch the new process. The user name may optionally be specifed with a domain, i.e. domainuser or user@my.dns.domain.com via Universal Principal Name (UPN)format. It can also be specified without a domain simply as user if the domain is instead specified using the domain attribute. On Windows only, if this property is specified, the password property must be specified."
90
+ description: "The user name of the user identity with which to launch the new process. The user name may optionally be specifed with a domain, i.e. domainuser or user@my.dns.domain.com via Universal Principal Name (UPN)format. It can also be specified without a domain simply as user if the domain is instead specified using the domain property. On Windows only, if this property is specified, the password property must be specified."
91
91
 
92
92
  property :domain, String,
93
93
  introduced: "12.21",
@@ -32,7 +32,7 @@ class Chef
32
32
  include Chef::Mixin::HomebrewUser
33
33
 
34
34
  property :cask_name, String,
35
- description: "The name of the Homebrew cask, if it differs from the resource block name.",
35
+ description: "An optional property to set the cask name if it differs from the resource block's name.",
36
36
  regex: %r{^[\w/-]+$},
37
37
  validation_message: "The provided Homebrew cask name is not valid. Cask names can contain alphanumeric characters, _, -, or / only!",
38
38
  name_property: true
@@ -32,7 +32,7 @@ class Chef
32
32
  include Chef::Mixin::HomebrewUser
33
33
 
34
34
  property :tap_name, String,
35
- description: "Optional tap name to override the resource name",
35
+ description: "An optional property to set the tap name if it differs from the resource block's name.",
36
36
  validation_message: "Homebrew tap names must be in the form REPO/TAP format!",
37
37
  regex: %r{^[\w-]+(?:\/[\w-]+)+$},
38
38
  name_property: true
@@ -27,7 +27,7 @@ class Chef
27
27
  introduced "14.0"
28
28
 
29
29
  property :hostname, String,
30
- description: "Used to specify the hostname if it is different than the resource's name.",
30
+ description: "An optional property to set the hostname if it differs from the resource block's name.",
31
31
  name_property: true
32
32
 
33
33
  property :compile_time, [ TrueClass, FalseClass ],
@@ -36,7 +36,7 @@ class Chef
36
36
 
37
37
  property :ipaddress, String,
38
38
  description: "The IP address to use when configuring the hosts file.",
39
- default: lazy { node["ipaddress"] }
39
+ default: lazy { node["ipaddress"] }, default_description: "The node's IP address as determined by Ohai."
40
40
 
41
41
  property :aliases, [ Array, nil ],
42
42
  description: "An array of hostname aliases to use when configuring the hosts file.",
@@ -18,7 +18,7 @@ class Chef
18
18
  introduced "14.3"
19
19
 
20
20
  property :modname, String,
21
- description: "The name of the kernel module.",
21
+ description: "An optional property to set the kernel module name if it differs from the resource block's name.",
22
22
  name_property: true, identity: true
23
23
 
24
24
  property :load_dir, String,
@@ -48,7 +48,7 @@ class Chef
48
48
  end
49
49
 
50
50
  property :target_file, String,
51
- description: "The name of the link. Default value: the name of the resource block.",
51
+ description: "An optional property to set the target file if it differs from the resource block's name.",
52
52
  name_property: true, identity: true
53
53
 
54
54
  property :to, String,
@@ -27,7 +27,7 @@ class Chef
27
27
  introduced "14.0"
28
28
 
29
29
  property :hint_name, String,
30
- description: "The name of the hints file, if it differs from the resource name.",
30
+ description: "An optional property to set the hint name if it differs from the resource block's name.",
31
31
  name_property: true
32
32
 
33
33
  property :content, Hash,
@@ -42,7 +42,7 @@ class Chef
42
42
  end
43
43
 
44
44
  property :package_name, [ String, Array ],
45
- description: "The name of the package. Defaults to the name of the resourse block unless specified.",
45
+ description: "An optional property to set the package name if it differs from the resource block's name.",
46
46
  identity: true
47
47
 
48
48
  property :version, [ String, Array ],
@@ -66,7 +66,7 @@ class Chef
66
66
  default: "deploy"
67
67
 
68
68
  property :environment, [Hash, nil],
69
- description: "A Hash of environment variables in the form of ({'ENV_VARIABLE' => 'VALUE'}). (These variables must exist for a command to be run successfully.)",
69
+ description: "A Hash of environment variables in the form of ({'ENV_VARIABLE' => 'VALUE'}).",
70
70
  default: nil
71
71
 
72
72
  alias :env :environment
@@ -27,7 +27,7 @@ class Chef
27
27
  introduced "14.0"
28
28
 
29
29
  property :path, String,
30
- description: "The path where the swap file will be created on the system, if it differs from the resource block name.",
30
+ description: "The path where the swap file will be created on the system, if it differs from the resource block's name.",
31
31
  name_property: true
32
32
 
33
33
  property :size, Integer,
@@ -33,7 +33,7 @@ class Chef
33
33
  introduced "14.0"
34
34
 
35
35
  property :key, String,
36
- description: "The kernel parameter key in dotted format, if it differs from the resource block name.",
36
+ description: "The kernel parameter key in dotted format, if it differs from the resource block's name.",
37
37
  name_property: true
38
38
 
39
39
  property :ignore_error, [TrueClass, FalseClass],
@@ -60,7 +60,7 @@ class Chef
60
60
 
61
61
  property :unit_name, String, desired_state: false,
62
62
  identity: true, name_property: true,
63
- description: "The name of the unit file if it differs from the resource block name.",
63
+ description: "The name of the unit file if it differs from the resource block's name.",
64
64
  introduced: "13.7"
65
65
 
66
66
  def to_ini
@@ -57,9 +57,17 @@ class Chef
57
57
  )
58
58
  end
59
59
 
60
- property :variables, Hash, default: lazy { Hash.new }
61
- property :cookbook, String
62
- property :local, [ TrueClass, FalseClass ], default: false
60
+ property :variables, Hash,
61
+ description: "The variables property of the template resource can be used to reference a partial template file by using a Hash.",
62
+ default: lazy { Hash.new }
63
+
64
+ property :cookbook, String,
65
+ description: "The cookbook in which a file is located (if it is not located in the current cookbook). The default value is the current cookbook.",
66
+ desired_state: false
67
+
68
+ property :local, [ TrueClass, FalseClass ],
69
+ default: false, desired_state: false,
70
+ description: "Load a template from a local path. By default, the chef-client loads templates from a cookbook’s /templates directory. When this property is set to true, use the source property to specify the path to a template on the local node."
63
71
 
64
72
  # Declares a helper method to be defined in the template context when
65
73
  # rendering.
@@ -65,7 +65,7 @@ class Chef
65
65
 
66
66
  unless on_domain?
67
67
  cmd = "$pswd = ConvertTo-SecureString \'#{new_resource.domain_password}\' -AsPlainText -Force;"
68
- cmd << "$credential = New-Object System.Management.Automation.PSCredential (\"#{new_resource.domain_user}\",$pswd);"
68
+ cmd << "$credential = New-Object System.Management.Automation.PSCredential (\"#{new_resource.domain_user}@#{new_resource.domain_name}\",$pswd);"
69
69
  cmd << "Add-Computer -DomainName #{new_resource.domain_name} -Credential $credential"
70
70
  cmd << " -OUPath \"#{new_resource.ou_path}\"" if new_resource.ou_path
71
71
  cmd << " -NewName \"#{new_resource.new_hostname}\"" if new_resource.new_hostname
@@ -28,7 +28,7 @@ class Chef
28
28
  introduced "14.0"
29
29
 
30
30
  property :program_name, String,
31
- description: "The name of the program to run at login, if it differs from the resource block name.",
31
+ description: "The name of the program to run at login, if it differs from the resource block's name.",
32
32
  name_property: true
33
33
 
34
34
  property :path, String,
@@ -17,6 +17,7 @@
17
17
  # limitations under the License.
18
18
  #
19
19
 
20
+ require "chef/util/path_helper"
20
21
  require "chef/resource"
21
22
  require "win32-certstore" if Chef::Platform.windows?
22
23
  require "openssl"
@@ -180,7 +181,7 @@ class Chef
180
181
 
181
182
  def cert_script(persist)
182
183
  cert_script = "$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2"
183
- file = win_friendly_path(new_resource.source)
184
+ file = Chef::Util::PathHelper.cleanpath(new_resource.source)
184
185
  cert_script << " \"#{file}\""
185
186
  if ::File.extname(file.downcase) == ".pfx"
186
187
  cert_script << ", \"#{new_resource.pfx_password}\""
@@ -28,7 +28,7 @@ class Chef
28
28
  introduced "14.0"
29
29
 
30
30
  property :feature_name, [Array, String],
31
- description: "The name of the feature(s) or role(s) to install, if it differs from the resource block name. The same feature may have different names depending on the underlying installation method being used (ie DHCPServer vs DHCP; DNS-Server-Full-Role vs DNS).",
31
+ description: "The name of the feature(s) or role(s) to install, if it differs from the resource block's name. The same feature may have different names depending on the underlying installation method being used (ie DHCPServer vs DHCP; DNS-Server-Full-Role vs DNS).",
32
32
  name_property: true
33
33
 
34
34
  property :source, String,
@@ -44,7 +44,8 @@ class Chef
44
44
 
45
45
  property :install_method, Symbol,
46
46
  description: "The underlying installation method to use for feature installation. Specify ':windows_feature_dism' for DISM or ':windows_feature_powershell' for PowerShell.",
47
- equal_to: [:windows_feature_dism, :windows_feature_powershell, :windows_feature_servermanagercmd]
47
+ equal_to: [:windows_feature_dism, :windows_feature_powershell, :windows_feature_servermanagercmd],
48
+ default: :windows_feature_dism
48
49
 
49
50
  property :timeout, Integer,
50
51
  description: "Specifies a timeout (in seconds) for the feature installation.",
@@ -72,16 +73,15 @@ class Chef
72
73
  # call the appropriate windows_feature resource based on the specified subresource
73
74
  # @return [void]
74
75
  def run_default_subresource(desired_action)
75
- raise "Support for Windows feature installation via servermanagercmd.exe has been removed as this support is no longer needed in Windows 2008 R2 and above. You will need to update your cookbook to install either via dism or powershell (preferred)." if new_resource.install_method == :windows_feature_servermanagercmd
76
+ raise "Support for Windows feature installation via servermanagercmd.exe has been removed as this support is no longer needed in Windows 2008 R2 and above. You will need to update your recipe to install either via dism or powershell (preferred)." if new_resource.install_method == :windows_feature_servermanagercmd
76
77
 
77
- subresource = new_resource.install_method || :windows_feature_dism
78
- declare_resource(subresource, new_resource.name) do
78
+ declare_resource(new_resource.install_method, new_resource.name) do
79
79
  action desired_action
80
80
  feature_name new_resource.feature_name
81
81
  source new_resource.source if new_resource.source
82
82
  all new_resource.all
83
83
  timeout new_resource.timeout
84
- management_tools new_resource.management_tools if subresource == :windows_feature_powershell
84
+ management_tools new_resource.management_tools if new_resource.install_method == :windows_feature_powershell
85
85
  end
86
86
  end
87
87
  end
@@ -57,7 +57,6 @@ class Chef
57
57
 
58
58
  reload_cached_dism_data unless node["dism_features_cache"]
59
59
  fail_if_unavailable # fail if the features don't exist
60
- fail_if_removed # fail if the features are in removed state
61
60
 
62
61
  logger.trace("Windows features needing installation: #{features_to_install.empty? ? 'none' : features_to_install.join(',')}")
63
62
  unless features_to_install.empty?
@@ -66,8 +65,12 @@ class Chef
66
65
  install_command = "dism.exe /online /enable-feature #{features_to_install.map { |f| "/featurename:#{f}" }.join(' ')} /norestart"
67
66
  install_command << " /LimitAccess /Source:\"#{new_resource.source}\"" if new_resource.source
68
67
  install_command << " /All" if new_resource.all
69
-
70
- shell_out!(install_command, returns: [0, 42, 127, 3010], timeout: new_resource.timeout)
68
+ begin
69
+ shell_out!(install_command, returns: [0, 42, 127, 3010], timeout: new_resource.timeout)
70
+ rescue Mixlib::ShellOut::ShellCommandFailed => e
71
+ raise "Error 50 returned by DISM related to parent features, try setting the 'all' property to 'true' on the 'windows_feature_dism' resource." if required_parent_feature?(e.inspect)
72
+ raise e.message
73
+ end
71
74
 
72
75
  reload_cached_dism_data # Reload cached dism feature state
73
76
  end
@@ -118,10 +121,10 @@ class Chef
118
121
  # disabled features are always available to install
119
122
  available_for_install = node["dism_features_cache"]["disabled"].dup
120
123
 
121
- # if the user passes a source then removed features are also available for installation
122
- available_for_install.concat(node["dism_features_cache"]["removed"]) if new_resource.source
124
+ # removed features are also available for installation
125
+ available_for_install.concat(node["dism_features_cache"]["removed"])
123
126
 
124
- # the intersection of the features to install & disabled/removed(if passing source) features are what needs installing
127
+ # the intersection of the features to install & disabled/removed features are what needs installing
125
128
  new_resource.feature_name & available_for_install
126
129
  end
127
130
  end
@@ -204,22 +207,15 @@ class Chef
204
207
  node.override["dism_features_cache"][feature_type] << feature_details
205
208
  end
206
209
 
207
- # Fail if any of the packages are in a removed state
208
- # @return [void]
209
- def fail_if_removed
210
- return if new_resource.source # if someone provides a source then all is well
211
- if node["platform_version"].to_f > 6.2 # 2012R2 or later
212
- return if registry_key_exists?('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Servicing') && registry_value_exists?('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Servicing', name: "LocalSourcePath") # if source is defined in the registry, still fine
213
- end
214
- removed = new_resource.feature_name & node["dism_features_cache"]["removed"]
215
- raise "The Windows feature#{'s' if removed.count > 1} #{removed.join(',')} #{removed.count > 1 ? 'are' : 'is'} removed from the host and cannot be installed." unless removed.empty?
216
- end
217
-
218
210
  # Fail unless we're on windows 8+ / 2012+ where deleting a feature is supported
219
211
  # @return [void]
220
212
  def raise_if_delete_unsupported
221
213
  raise Chef::Exceptions::UnsupportedAction, "#{self} :delete action not supported on Windows releases before Windows 8/2012. Cannot continue!" if older_than_win_2012_or_8?
222
214
  end
215
+
216
+ def required_parent_feature?(error_message)
217
+ error_message.include?("Error: 50") && error_message.include?("required parent feature")
218
+ end
223
219
  end
224
220
  end
225
221
  end
@@ -31,7 +31,7 @@ class Chef
31
31
  introduced "14.0"
32
32
 
33
33
  property :feature_name, [Array, String],
34
- description: "The name of the feature(s) or role(s) to install, if it differs from the resource block name.",
34
+ description: "The name of the feature(s) or role(s) to install, if it differs from the resource block's name.",
35
35
  coerce: proc { |x| to_formatted_array(x) },
36
36
  name_property: true
37
37
 
@@ -102,7 +102,7 @@ class Chef
102
102
  # this command selects individual objects because EncryptData & CachingMode have underlying
103
103
  # types that get converted to their Integer values by ConvertTo-Json & we need to make sure
104
104
  # those get written out as strings
105
- share_state_cmd = "Get-SmbShare -Name '#{desired.share_name}' | Select-Object Name,Path, Description, Temporary, CATimeout, ContinuouslyAvailable, ConcurrentUserLimit, EncryptData | ConvertTo-Json"
105
+ share_state_cmd = "Get-SmbShare -Name '#{desired.share_name}' | Select-Object Name,Path, Description, Temporary, CATimeout, ContinuouslyAvailable, ConcurrentUserLimit, EncryptData | ConvertTo-Json -Compress"
106
106
 
107
107
  Chef::Log.debug("Running '#{share_state_cmd}' to determine share state'")
108
108
  ps_results = powershell_out(share_state_cmd)
@@ -126,7 +126,7 @@ class Chef
126
126
  encrypt_data results["EncryptData"]
127
127
  # folder_enumeration_mode results['FolderEnumerationMode']
128
128
 
129
- perm_state_cmd = %{Get-SmbShareAccess -Name "#{desired.share_name}" | Select-Object AccountName,AccessControlType,AccessRight | ConvertTo-Json}
129
+ perm_state_cmd = %{Get-SmbShareAccess -Name "#{desired.share_name}" | Select-Object AccountName,AccessControlType,AccessRight | ConvertTo-Json -Compress}
130
130
 
131
131
  Chef::Log.debug("Running '#{perm_state_cmd}' to determine share permissions state'")
132
132
  ps_perm_results = powershell_out(perm_state_cmd)
@@ -242,6 +242,10 @@ class Chef
242
242
 
243
243
  Chef::Log.debug("Running '#{share_cmd}' to create the share")
244
244
  powershell_out!(share_cmd)
245
+
246
+ # New-SmbShare adds the "Everyone" user with read access no matter what so we need to remove it
247
+ # before we add our permissions
248
+ revoke_user_permissions(["Everyone"])
245
249
  end
246
250
 
247
251
  # determine what users in the current state don't exist in the desired state
@@ -297,8 +301,10 @@ class Chef
297
301
  false
298
302
  end
299
303
 
304
+ # revoke user permissions from a share
305
+ # @param [Array] users
300
306
  def revoke_user_permissions(users)
301
- revoke_command = "Revoke-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{users.join(',')}\" -Force"
307
+ revoke_command = "Revoke-SmbShareAccess -Name '#{new_resource.share_name}' -AccountName \"#{users.join('","')}\" -Force"
302
308
  Chef::Log.debug("Running '#{revoke_command}' to revoke share permissions")
303
309
  powershell_out!(revoke_command)
304
310
  end
@@ -22,319 +22,318 @@ require "chef/win32/security" if Chef::Platform.windows?
22
22
  class Chef
23
23
  class Resource
24
24
  class WindowsTask < Chef::Resource
25
- if Chef::Platform.windows?
26
- resource_name :windows_task
27
- provides(:windows_task) { true }
25
+ resource_name :windows_task
26
+ provides(:windows_task) { true }
28
27
 
29
- description "Use the windows_task resource to create, delete or run a Windows scheduled task. Requires Windows Server 2008 or later due to API usage."
30
- introduced "13.0"
28
+ description "Use the windows_task resource to create, delete or run a Windows scheduled task. Requires Windows Server 2008 or later due to API usage."
29
+ introduced "13.0"
31
30
 
32
- allowed_actions :create, :delete, :run, :end, :enable, :disable, :change
33
- default_action :create
31
+ allowed_actions :create, :delete, :run, :end, :enable, :disable, :change
32
+ default_action :create
34
33
 
35
- property :task_name, String, regex: [/\A[^\/\:\*\?\<\>\|]+\z/],
36
- description: "The task name, such as 'Task Name' or '/Task Name'",
37
- name_property: true
34
+ property :task_name, String, regex: [/\A[^\/\:\*\?\<\>\|]+\z/],
35
+ description: "The task name, such as 'Task Name' or '/Task Name'",
36
+ name_property: true
38
37
 
39
- property :command, String,
40
- description: "The command to be executed by the windows scheduled task."
38
+ property :command, String,
39
+ description: "The command to be executed by the windows scheduled task."
41
40
 
42
- property :cwd, String,
43
- description: "The directory the task will be run from."
41
+ property :cwd, String,
42
+ description: "The directory the task will be run from."
44
43
 
45
- property :user, String,
46
- description: "The user to run the task as.",
47
- default: Chef::ReservedNames::Win32::Security::SID.LocalSystem.account_simple_name
44
+ property :user, String,
45
+ description: "The user to run the task as.",
46
+ default: lazy { Chef::ReservedNames::Win32::Security::SID.LocalSystem.account_simple_name if Chef::Platform.windows? },
47
+ default_description: "The localized SYSTEM user for the node."
48
48
 
49
- property :password, String,
50
- description: "The user’s password. The user property must be set if using this property."
49
+ property :password, String,
50
+ description: "The user’s password. The user property must be set if using this property."
51
51
 
52
- property :run_level, Symbol, equal_to: [:highest, :limited],
53
- description: "Run with ':limited' or ':highest' privileges.",
54
- default: :limited
52
+ property :run_level, Symbol, equal_to: [:highest, :limited],
53
+ description: "Run with ':limited' or ':highest' privileges.",
54
+ default: :limited
55
55
 
56
- property :force, [TrueClass, FalseClass],
57
- description: "When used with create, will update the task.",
58
- default: false
56
+ property :force, [TrueClass, FalseClass],
57
+ description: "When used with create, will update the task.",
58
+ default: false
59
59
 
60
- property :interactive_enabled, [TrueClass, FalseClass],
61
- description: "Allow task to run interactively or non-interactively. Requires user and password to also be set.",
62
- default: false
60
+ property :interactive_enabled, [TrueClass, FalseClass],
61
+ description: "Allow task to run interactively or non-interactively. Requires user and password to also be set.",
62
+ default: false
63
63
 
64
- property :frequency_modifier, [Integer, String],
65
- default: 1
64
+ property :frequency_modifier, [Integer, String],
65
+ default: 1
66
66
 
67
- property :frequency, Symbol, equal_to: [:minute,
68
- :hourly,
69
- :daily,
70
- :weekly,
71
- :monthly,
72
- :once,
73
- :on_logon,
74
- :onstart,
75
- :on_idle,
76
- :none],
77
- description: "The frequency with which to run the task."
67
+ property :frequency, Symbol, equal_to: [:minute,
68
+ :hourly,
69
+ :daily,
70
+ :weekly,
71
+ :monthly,
72
+ :once,
73
+ :on_logon,
74
+ :onstart,
75
+ :on_idle,
76
+ :none],
77
+ description: "The frequency with which to run the task."
78
78
 
79
- property :start_day, String,
80
- description: "Specifies the first date on which the task runs in MM/DD/YYYY format."
79
+ property :start_day, String,
80
+ description: "Specifies the first date on which the task runs in MM/DD/YYYY format."
81
81
 
82
- property :start_time, String,
83
- description: "Specifies the start time to run the task, in HH:mm format."
82
+ property :start_time, String,
83
+ description: "Specifies the start time to run the task, in HH:mm format."
84
84
 
85
- property :day, [String, Integer],
86
- description: "The day(s) on which the task runs."
85
+ property :day, [String, Integer],
86
+ description: "The day(s) on which the task runs."
87
87
 
88
- property :months, String,
89
- description: "The Months of the year on which the task runs, such as: 'JAN, FEB' or '\*'. Multiple months should be comma delimited. e.g. 'Jan, Feb, Mar, Dec'."
88
+ property :months, String,
89
+ description: "The Months of the year on which the task runs, such as: 'JAN, FEB' or '\*'. Multiple months should be comma delimited. e.g. 'Jan, Feb, Mar, Dec'."
90
90
 
91
- property :idle_time, Integer,
92
- description: "For :on_idle frequency, the time (in minutes) without user activity that must pass to trigger the task, from 1 - 999."
91
+ property :idle_time, Integer,
92
+ description: "For :on_idle frequency, the time (in minutes) without user activity that must pass to trigger the task, from 1 - 999."
93
93
 
94
- property :random_delay, [String, Integer],
95
- description: "Delays the task up to a given time (in seconds)."
94
+ property :random_delay, [String, Integer],
95
+ description: "Delays the task up to a given time (in seconds)."
96
96
 
97
- property :execution_time_limit, [String, Integer],
98
- description: "The maximum time (in seconds) the task will run.",
99
- default: "PT72H" # 72 hours in ISO8601 duration format
97
+ property :execution_time_limit, [String, Integer],
98
+ description: "The maximum time (in seconds) the task will run.",
99
+ default: "PT72H" # 72 hours in ISO8601 duration format
100
100
 
101
- property :minutes_duration, [String, Integer],
102
- description: ""
101
+ property :minutes_duration, [String, Integer],
102
+ description: ""
103
103
 
104
- property :minutes_interval, [String, Integer],
105
- description: ""
104
+ property :minutes_interval, [String, Integer],
105
+ description: ""
106
106
 
107
- property :priority, Integer,
108
- description: "Use to set Priority Levels range from 0 to 10.",
109
- default: 7, callbacks: { "should be in range of 0 to 10" => proc { |v| v >= 0 && v <= 10 } }
107
+ property :priority, Integer,
108
+ description: "Use to set Priority Levels range from 0 to 10.",
109
+ default: 7, callbacks: { "should be in range of 0 to 10" => proc { |v| v >= 0 && v <= 10 } }
110
110
 
111
- property :disallow_start_if_on_batteries, [TrueClass, FalseClass],
112
- introduced: "14.4", default: false,
113
- description: "Disallow start of the task if the system is running on battery power."
111
+ property :disallow_start_if_on_batteries, [TrueClass, FalseClass],
112
+ introduced: "14.4", default: false,
113
+ description: "Disallow start of the task if the system is running on battery power."
114
114
 
115
- property :stop_if_going_on_batteries, [TrueClass, FalseClass],
116
- introduced: "14.4", default: false,
117
- description: "Scheduled task option when system is switching on battery."
115
+ property :stop_if_going_on_batteries, [TrueClass, FalseClass],
116
+ introduced: "14.4", default: false,
117
+ description: "Scheduled task option when system is switching on battery."
118
118
 
119
- property :description, String,
120
- introduced: "14.7",
121
- description: "The task description."
119
+ property :description, String,
120
+ introduced: "14.7",
121
+ description: "The task description."
122
122
 
123
- attr_accessor :exists, :task, :command_arguments
123
+ attr_accessor :exists, :task, :command_arguments
124
124
 
125
- VALID_WEEK_DAYS = %w{ mon tue wed thu fri sat sun * }.freeze
126
- VALID_DAYS_OF_MONTH = ("1".."31").to_a << "last" << "lastday"
127
- VALID_MONTHS = %w{JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC *}.freeze
128
- VALID_WEEKS = %w{FIRST SECOND THIRD FOURTH LAST LASTDAY}.freeze
125
+ VALID_WEEK_DAYS = %w{ mon tue wed thu fri sat sun * }.freeze
126
+ VALID_DAYS_OF_MONTH = ("1".."31").to_a << "last" << "lastday"
127
+ VALID_MONTHS = %w{JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC *}.freeze
128
+ VALID_WEEKS = %w{FIRST SECOND THIRD FOURTH LAST LASTDAY}.freeze
129
129
 
130
- def after_created
131
- if random_delay
132
- validate_random_delay(random_delay, frequency)
133
- random_delay(sec_to_min(random_delay))
134
- end
135
-
136
- if execution_time_limit
137
- execution_time_limit(259200) if execution_time_limit == "PT72H"
138
- 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)
139
- execution_time_limit(sec_to_min(execution_time_limit))
140
- end
130
+ def after_created
131
+ if random_delay
132
+ validate_random_delay(random_delay, frequency)
133
+ random_delay(sec_to_min(random_delay))
134
+ end
141
135
 
142
- validate_frequency(frequency) if action.include?(:create) || action.include?(:change)
143
- validate_start_time(start_time, frequency)
144
- validate_start_day(start_day, frequency) if start_day
145
- validate_user_and_password(user, password)
146
- validate_interactive_setting(interactive_enabled, password)
147
- validate_create_frequency_modifier(frequency, frequency_modifier) if frequency_modifier
148
- validate_create_day(day, frequency, frequency_modifier) if day
149
- validate_create_months(months, frequency) if months
150
- validate_frequency_monthly(frequency_modifier, months, day) if frequency == :monthly
151
- validate_idle_time(idle_time, frequency)
152
- idempotency_warning_for_frequency_weekly(day, start_day) if frequency == :weekly
136
+ if execution_time_limit
137
+ execution_time_limit(259200) if execution_time_limit == "PT72H"
138
+ 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)
139
+ execution_time_limit(sec_to_min(execution_time_limit))
153
140
  end
154
141
 
155
- private
142
+ validate_frequency(frequency) if action.include?(:create) || action.include?(:change)
143
+ validate_start_time(start_time, frequency)
144
+ validate_start_day(start_day, frequency) if start_day
145
+ validate_user_and_password(user, password)
146
+ validate_interactive_setting(interactive_enabled, password)
147
+ validate_create_frequency_modifier(frequency, frequency_modifier) if frequency_modifier
148
+ validate_create_day(day, frequency, frequency_modifier) if day
149
+ validate_create_months(months, frequency) if months
150
+ validate_frequency_monthly(frequency_modifier, months, day) if frequency == :monthly
151
+ validate_idle_time(idle_time, frequency)
152
+ idempotency_warning_for_frequency_weekly(day, start_day) if frequency == :weekly
153
+ end
154
+
155
+ private
156
156
 
157
157
  ## Resource is not idempotent when day, start_day is not provided with frequency :weekly
158
158
  ## 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 ..
159
159
  ## 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
160
- def idempotency_warning_for_frequency_weekly(day, start_day)
161
- if start_day.nil? && day.nil?
162
- logger.warn "To maintain idempotency for frequency :weekly provide start_day, start_time and day."
163
- end
160
+ def idempotency_warning_for_frequency_weekly(day, start_day)
161
+ if start_day.nil? && day.nil?
162
+ logger.warn "To maintain idempotency for frequency :weekly provide start_day, start_time and day."
164
163
  end
164
+ end
165
165
 
166
166
  # Validate the passed value is numeric values only if it is a string
167
- def numeric_value_in_string?(val)
168
- return true if Integer(val)
169
- rescue ArgumentError
170
- false
171
- end
167
+ def numeric_value_in_string?(val)
168
+ return true if Integer(val)
169
+ rescue ArgumentError
170
+ false
171
+ end
172
172
 
173
- def validate_frequency(frequency)
174
- if frequency.nil? || !([:minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none].include?(frequency))
175
- raise ArgumentError, "Frequency needs to be provided. Valid frequencies are :minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none."
176
- end
173
+ def validate_frequency(frequency)
174
+ if frequency.nil? || !([:minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none].include?(frequency))
175
+ raise ArgumentError, "Frequency needs to be provided. Valid frequencies are :minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none."
177
176
  end
177
+ end
178
178
 
179
- def validate_frequency_monthly(frequency_modifier, months, day)
180
- # validates the frequency :monthly and raises error if frequency_modifier is first, second, thrid etc and day is not provided
181
- if (frequency_modifier != 1) && (frequency_modifier_includes_days_of_weeks?(frequency_modifier)) && !(day)
182
- raise ArgumentError, "Please select day on which you want to run the task e.g. 'Mon, Tue'. Multiple values must be seprated by comma."
183
- end
184
-
185
- # 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.
186
- # 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
187
- if (frequency_modifier.to_i.between?(2, 12)) && !(months.nil?)
188
- raise ArgumentError, "For frequency :monthly either use property months or frequency_modifier to set months."
189
- end
179
+ def validate_frequency_monthly(frequency_modifier, months, day)
180
+ # validates the frequency :monthly and raises error if frequency_modifier is first, second, thrid etc and day is not provided
181
+ if (frequency_modifier != 1) && (frequency_modifier_includes_days_of_weeks?(frequency_modifier)) && !(day)
182
+ raise ArgumentError, "Please select day on which you want to run the task e.g. 'Mon, Tue'. Multiple values must be seprated by comma."
190
183
  end
191
184
 
192
- # returns true if frequency_modifer has values First, second, third, fourth, last, lastday
193
- def frequency_modifier_includes_days_of_weeks?(frequency_modifier)
194
- frequency_modifier = frequency_modifier.to_s.split(",")
195
- frequency_modifier.map! { |value| value.strip.upcase }
196
- (frequency_modifier - VALID_WEEKS).empty?
185
+ # 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.
186
+ # 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
187
+ if (frequency_modifier.to_i.between?(2, 12)) && !(months.nil?)
188
+ raise ArgumentError, "For frequency :monthly either use property months or frequency_modifier to set months."
197
189
  end
190
+ end
198
191
 
199
- def validate_random_delay(random_delay, frequency)
200
- if [:on_logon, :onstart, :on_idle, :none].include? frequency
201
- raise ArgumentError, "`random_delay` property is supported only for frequency :once, :minute, :hourly, :daily, :weekly and :monthly"
202
- end
192
+ # returns true if frequency_modifer has values First, second, third, fourth, last, lastday
193
+ def frequency_modifier_includes_days_of_weeks?(frequency_modifier)
194
+ frequency_modifier = frequency_modifier.to_s.split(",")
195
+ frequency_modifier.map! { |value| value.strip.upcase }
196
+ (frequency_modifier - VALID_WEEKS).empty?
197
+ end
203
198
 
204
- 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)
199
+ def validate_random_delay(random_delay, frequency)
200
+ if [:on_logon, :onstart, :on_idle, :none].include? frequency
201
+ raise ArgumentError, "`random_delay` property is supported only for frequency :once, :minute, :hourly, :daily, :weekly and :monthly"
205
202
  end
206
203
 
204
+ 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)
205
+ end
206
+
207
207
  # @todo when we drop ruby 2.3 support this should be converted to .match?() instead of =~f
208
- def validate_start_day(start_day, frequency)
209
- if start_day && frequency == :none
210
- raise ArgumentError, "`start_day` property is not supported with frequency: #{frequency}"
211
- end
208
+ def validate_start_day(start_day, frequency)
209
+ if start_day && frequency == :none
210
+ raise ArgumentError, "`start_day` property is not supported with frequency: #{frequency}"
211
+ end
212
212
 
213
- # make sure the start_day is in MM/DD/YYYY format: http://rubular.com/r/cgjHemtWl5
214
- if start_day
215
- 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
216
- end
213
+ # make sure the start_day is in MM/DD/YYYY format: http://rubular.com/r/cgjHemtWl5
214
+ if start_day
215
+ 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
217
216
  end
217
+ end
218
218
 
219
219
  # @todo when we drop ruby 2.3 support this should be converted to .match?() instead of =~
220
- def validate_start_time(start_time, frequency)
221
- if start_time
222
- raise ArgumentError, "`start_time` property is not supported with `frequency :none`" if frequency == :none
223
- raise ArgumentError, "`start_time` property must be in the HH:mm format (e.g. 6:20pm -> 18:20)." unless /^[0-2][0-9]:[0-5][0-9]$/ =~ start_time
224
- else
225
- raise ArgumentError, "`start_time` needs to be provided with `frequency :once`" if frequency == :once
226
- end
220
+ def validate_start_time(start_time, frequency)
221
+ if start_time
222
+ raise ArgumentError, "`start_time` property is not supported with `frequency :none`" if frequency == :none
223
+ raise ArgumentError, "`start_time` property must be in the HH:mm format (e.g. 6:20pm -> 18:20)." unless /^[0-2][0-9]:[0-5][0-9]$/ =~ start_time
224
+ else
225
+ raise ArgumentError, "`start_time` needs to be provided with `frequency :once`" if frequency == :once
227
226
  end
227
+ end
228
228
 
229
- def validate_user_and_password(user, password)
230
- if password_required?(user) && password.nil?
231
- raise ArgumentError, "Cannot specify a user other than the system users without specifying a password!. Valid passwordless users: '#{Chef::ReservedNames::Win32::Security::SID::SYSTEM_USER.join("', '")}'"
232
- end
229
+ def validate_user_and_password(user, password)
230
+ if password_required?(user) && password.nil?
231
+ raise ArgumentError, "Cannot specify a user other than the system users without specifying a password!. Valid passwordless users: '#{Chef::ReservedNames::Win32::Security::SID::SYSTEM_USER.join("', '")}'"
233
232
  end
233
+ end
234
234
 
235
- def password_required?(user)
236
- return false if user.nil?
237
- @password_required ||= !Chef::ReservedNames::Win32::Security::SID.system_user?(user)
238
- end
235
+ def password_required?(user)
236
+ return false if user.nil?
237
+ @password_required ||= !Chef::ReservedNames::Win32::Security::SID.system_user?(user)
238
+ end
239
+
240
+ def validate_interactive_setting(interactive_enabled, password)
241
+ raise ArgumentError, "Please provide the password when attempting to set interactive/non-interactive." if interactive_enabled && password.nil?
242
+ end
239
243
 
240
- def validate_interactive_setting(interactive_enabled, password)
241
- raise ArgumentError, "Please provide the password when attempting to set interactive/non-interactive." if interactive_enabled && password.nil?
244
+ def validate_create_frequency_modifier(frequency, frequency_modifier)
245
+ if ([:on_logon, :onstart, :on_idle, :none].include?(frequency)) && ( frequency_modifier != 1)
246
+ raise ArgumentError, "frequency_modifier property not supported with frequency :#{frequency}"
242
247
  end
243
248
 
244
- def validate_create_frequency_modifier(frequency, frequency_modifier)
245
- if ([:on_logon, :onstart, :on_idle, :none].include?(frequency)) && ( frequency_modifier != 1)
246
- raise ArgumentError, "frequency_modifier property not supported with frequency :#{frequency}"
249
+ if frequency == :monthly
250
+ unless (1..12).cover?(frequency_modifier.to_i) || frequency_modifier_includes_days_of_weeks?(frequency_modifier)
251
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'."
247
252
  end
248
-
249
- if frequency == :monthly
250
- unless (1..12).cover?(frequency_modifier.to_i) || frequency_modifier_includes_days_of_weeks?(frequency_modifier)
251
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST'."
252
- end
253
- else
254
- unless frequency.nil? || frequency_modifier.nil?
255
- frequency_modifier = frequency_modifier.to_i
256
- min = 1
257
- max = case frequency
258
- when :minute
259
- 1439
260
- when :hourly
261
- 23
262
- when :daily
263
- 365
264
- when :weekly
265
- 52
266
- else
267
- min
268
- end
269
- unless frequency_modifier.between?(min, max)
270
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :#{frequency} frequency are #{min} - #{max}."
271
- end
253
+ else
254
+ unless frequency.nil? || frequency_modifier.nil?
255
+ frequency_modifier = frequency_modifier.to_i
256
+ min = 1
257
+ max = case frequency
258
+ when :minute
259
+ 1439
260
+ when :hourly
261
+ 23
262
+ when :daily
263
+ 365
264
+ when :weekly
265
+ 52
266
+ else
267
+ min
268
+ end
269
+ unless frequency_modifier.between?(min, max)
270
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :#{frequency} frequency are #{min} - #{max}."
272
271
  end
273
272
  end
274
273
  end
274
+ end
275
275
 
276
- def validate_create_day(day, frequency, frequency_modifier)
277
- raise ArgumentError, "day property is only valid for tasks that run monthly or weekly" unless [:weekly, :monthly].include?(frequency)
278
-
279
- # This has been verified with schtask.exe https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks#d-dayday--
280
- # verified with earlier code if day "*" is given with frequency it raised exception Invalid value for /D option
281
- raise ArgumentError, "day wild card (*) is only valid with frequency :weekly" if frequency == :monthly && day == "*"
282
-
283
- if day.is_a?(String) && day.to_i.to_s != day
284
- days = day.split(",")
285
- if days_includes_days_of_months?(days)
286
- # 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
287
- raise ArgumentError, "day values 1-31 or last is only valid with frequency :monthly" if frequency == :weekly
288
- else
289
- days.map! { |day| day.to_s.strip.downcase }
290
- unless (days - VALID_WEEK_DAYS).empty?
291
- raise ArgumentError, "day property invalid. Only valid values are: #{VALID_WEEK_DAYS.map(&:upcase).join(', ')}. Multiple values must be separated by a comma."
292
- end
276
+ def validate_create_day(day, frequency, frequency_modifier)
277
+ raise ArgumentError, "day property is only valid for tasks that run monthly or weekly" unless [:weekly, :monthly].include?(frequency)
278
+
279
+ # This has been verified with schtask.exe https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks#d-dayday--
280
+ # verified with earlier code if day "*" is given with frequency it raised exception Invalid value for /D option
281
+ raise ArgumentError, "day wild card (*) is only valid with frequency :weekly" if frequency == :monthly && day == "*"
282
+
283
+ if day.is_a?(String) && day.to_i.to_s != day
284
+ days = day.split(",")
285
+ if days_includes_days_of_months?(days)
286
+ # 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
287
+ raise ArgumentError, "day values 1-31 or last is only valid with frequency :monthly" if frequency == :weekly
288
+ else
289
+ days.map! { |day| day.to_s.strip.downcase }
290
+ unless (days - VALID_WEEK_DAYS).empty?
291
+ raise ArgumentError, "day property invalid. Only valid values are: #{VALID_WEEK_DAYS.map(&:upcase).join(', ')}. Multiple values must be separated by a comma."
293
292
  end
294
293
  end
295
294
  end
295
+ end
296
296
 
297
- def validate_create_months(months, frequency)
298
- raise ArgumentError, "months property is only valid for tasks that run monthly" if frequency != :monthly
299
- if months.is_a?(String)
300
- months = months.split(",")
301
- months.map! { |month| month.strip.upcase }
302
- unless (months - VALID_MONTHS).empty?
303
- raise ArgumentError, "months property invalid. Only valid values are: #{VALID_MONTHS.join(', ')}. Multiple values must be separated by a comma."
304
- end
297
+ def validate_create_months(months, frequency)
298
+ raise ArgumentError, "months property is only valid for tasks that run monthly" if frequency != :monthly
299
+ if months.is_a?(String)
300
+ months = months.split(",")
301
+ months.map! { |month| month.strip.upcase }
302
+ unless (months - VALID_MONTHS).empty?
303
+ raise ArgumentError, "months property invalid. Only valid values are: #{VALID_MONTHS.join(', ')}. Multiple values must be separated by a comma."
305
304
  end
306
305
  end
306
+ end
307
307
 
308
308
  # This method returns true if day has values from 1-31 which is a days of moths and used with frequency :monthly
309
- def days_includes_days_of_months?(days)
310
- days.map! { |day| day.to_s.strip.downcase }
311
- (days - VALID_DAYS_OF_MONTH).empty?
312
- end
309
+ def days_includes_days_of_months?(days)
310
+ days.map! { |day| day.to_s.strip.downcase }
311
+ (days - VALID_DAYS_OF_MONTH).empty?
312
+ end
313
313
 
314
- def validate_idle_time(idle_time, frequency)
315
- if !idle_time.nil? && frequency != :on_idle
316
- raise ArgumentError, "idle_time property is only valid for tasks that run on_idle"
317
- end
318
- if idle_time.nil? && frequency == :on_idle
319
- raise ArgumentError, "idle_time value should be set for :on_idle frequency."
320
- end
321
- unless idle_time.nil? || idle_time > 0 && idle_time <= 999
322
- raise ArgumentError, "idle_time value #{idle_time} is invalid. Valid values for :on_idle frequency are 1 - 999."
323
- end
314
+ def validate_idle_time(idle_time, frequency)
315
+ if !idle_time.nil? && frequency != :on_idle
316
+ raise ArgumentError, "idle_time property is only valid for tasks that run on_idle"
317
+ end
318
+ if idle_time.nil? && frequency == :on_idle
319
+ raise ArgumentError, "idle_time value should be set for :on_idle frequency."
324
320
  end
321
+ unless idle_time.nil? || idle_time > 0 && idle_time <= 999
322
+ raise ArgumentError, "idle_time value #{idle_time} is invalid. Valid values for :on_idle frequency are 1 - 999."
323
+ end
324
+ end
325
325
 
326
326
  # Converts the number of seconds to an ISO8601 duration format and returns it.
327
327
  # Ref : https://github.com/arnau/ISO8601/blob/master/lib/iso8601/duration.rb#L18-L23
328
328
  # e.g.
329
329
  # ISO8601::Duration.new(65707200).to_s
330
330
  # returns 'PT65707200S'
331
- def sec_to_dur(seconds)
332
- ISO8601::Duration.new(seconds.to_i).to_s
333
- end
331
+ def sec_to_dur(seconds)
332
+ ISO8601::Duration.new(seconds.to_i).to_s
333
+ end
334
334
 
335
- def sec_to_min(seconds)
336
- seconds.to_i / 60
337
- end
335
+ def sec_to_min(seconds)
336
+ seconds.to_i / 60
338
337
  end
339
338
  end
340
339
  end