puppet 2.7.6 → 2.7.8
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +168 -0
- data/conf/auth.conf +5 -4
- data/conf/redhat/puppet.spec +16 -1
- data/conf/solaris/pkginfo +2 -2
- data/conf/suse/puppet.spec +9 -3
- data/ext/upload_facts.rb +120 -0
- data/install.rb +11 -16
- data/lib/puppet.rb +1 -1
- data/lib/puppet/application/agent.rb +0 -3
- data/lib/puppet/application/apply.rb +0 -3
- data/lib/puppet/application/queue.rb +21 -1
- data/lib/puppet/defaults.rb +6 -4
- data/lib/puppet/face/file/store.rb +1 -1
- data/lib/puppet/feature/base.rb +2 -1
- data/lib/puppet/file_bucket/dipper.rb +3 -2
- data/lib/puppet/file_serving/content.rb +1 -1
- data/lib/puppet/file_serving/metadata.rb +5 -2
- data/lib/puppet/indirector/facts/inventory_service.rb +20 -0
- data/lib/puppet/indirector/file_bucket_file/file.rb +3 -2
- data/lib/puppet/indirector/report/processor.rb +1 -1
- data/lib/puppet/network/handler/filebucket.rb +2 -0
- data/lib/puppet/network/handler/fileserver.rb +1 -1
- data/lib/puppet/network/handler/master.rb +1 -0
- data/lib/puppet/network/handler/report.rb +2 -0
- data/lib/puppet/network/handler/runner.rb +1 -0
- data/lib/puppet/network/handler/status.rb +2 -0
- data/lib/puppet/network/http/mongrel/rest.rb +8 -1
- data/lib/puppet/network/http_server.rb +3 -0
- data/lib/puppet/network/http_server/mongrel.rb +129 -0
- data/lib/puppet/network/rest_authconfig.rb +12 -4
- data/lib/puppet/parameter.rb +18 -0
- data/lib/puppet/parser/compiler.rb +1 -1
- data/lib/puppet/parser/grammar.ra +1 -1
- data/lib/puppet/parser/parser.rb +360 -350
- data/lib/puppet/property.rb +3 -3
- data/lib/puppet/provider/augeas/augeas.rb +1 -1
- data/lib/puppet/provider/exec/windows.rb +6 -7
- data/lib/puppet/provider/file/windows.rb +9 -2
- data/lib/puppet/provider/group/aix.rb +8 -8
- data/lib/puppet/provider/group/groupadd.rb +1 -3
- data/lib/puppet/provider/group/ldap.rb +8 -10
- data/lib/puppet/provider/group/windows_adsi.rb +8 -2
- data/lib/puppet/provider/package/aix.rb +1 -1
- data/lib/puppet/provider/package/macports.rb +3 -3
- data/lib/puppet/provider/package/msi.rb +12 -5
- data/lib/puppet/provider/package/nim.rb +1 -1
- data/lib/puppet/provider/package/pkgdmg.rb +3 -3
- data/lib/puppet/provider/package/ports.rb +1 -1
- data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +560 -0
- data/lib/puppet/provider/service/base.rb +2 -2
- data/lib/puppet/provider/service/bsd.rb +4 -3
- data/lib/puppet/provider/service/daemontools.rb +25 -25
- data/lib/puppet/provider/service/debian.rb +6 -4
- data/lib/puppet/provider/service/freebsd.rb +1 -1
- data/lib/puppet/provider/service/gentoo.rb +4 -3
- data/lib/puppet/provider/service/init.rb +3 -8
- data/lib/puppet/provider/service/launchd.rb +129 -96
- data/lib/puppet/provider/service/redhat.rb +2 -3
- data/lib/puppet/provider/service/runit.rb +20 -20
- data/lib/puppet/provider/service/smf.rb +8 -7
- data/lib/puppet/provider/service/src.rb +5 -6
- data/lib/puppet/provider/service/systemd.rb +1 -1
- data/lib/puppet/provider/service/upstart.rb +3 -5
- data/lib/puppet/provider/service/windows.rb +7 -7
- data/lib/puppet/provider/sshkey/parsed.rb +2 -3
- data/lib/puppet/provider/user/aix.rb +21 -21
- data/lib/puppet/provider/user/hpux.rb +3 -1
- data/lib/puppet/provider/user/ldap.rb +7 -7
- data/lib/puppet/provider/user/user_role_add.rb +10 -6
- data/lib/puppet/provider/user/useradd.rb +3 -1
- data/lib/puppet/provider/user/windows_adsi.rb +4 -3
- data/lib/puppet/rb_tree_map.rb +388 -0
- data/lib/puppet/reference/configuration.rb +7 -7
- data/lib/puppet/reference/indirection.rb +5 -6
- data/lib/puppet/reference/metaparameter.rb +3 -1
- data/lib/puppet/reference/network.rb +8 -8
- data/lib/puppet/reference/providers.rb +17 -21
- data/lib/puppet/reference/type.rb +12 -9
- data/lib/puppet/resource.rb +2 -5
- data/lib/puppet/resource/catalog.rb +1 -1
- data/lib/puppet/ssl/certificate_request.rb +70 -0
- data/lib/puppet/ssl/host.rb +6 -0
- data/lib/puppet/transaction.rb +158 -55
- data/lib/puppet/transaction/event_manager.rb +1 -1
- data/lib/puppet/type.rb +60 -30
- data/lib/puppet/type/augeas.rb +83 -49
- data/lib/puppet/type/computer.rb +1 -1
- data/lib/puppet/type/cron.rb +11 -11
- data/lib/puppet/type/exec.rb +28 -21
- data/lib/puppet/type/file.rb +17 -7
- data/lib/puppet/type/file/content.rb +2 -2
- data/lib/puppet/type/file/ensure.rb +15 -12
- data/lib/puppet/type/file/mode.rb +30 -5
- data/lib/puppet/type/file/source.rb +11 -10
- data/lib/puppet/type/file/target.rb +2 -2
- data/lib/puppet/type/filebucket.rb +1 -1
- data/lib/puppet/type/group.rb +4 -5
- data/lib/puppet/type/host.rb +1 -1
- data/lib/puppet/type/interface.rb +13 -10
- data/lib/puppet/type/k5login.rb +6 -6
- data/lib/puppet/type/macauthorization.rb +37 -36
- data/lib/puppet/type/maillist.rb +2 -2
- data/lib/puppet/type/mcx.rb +6 -6
- data/lib/puppet/type/mount.rb +3 -2
- data/lib/puppet/type/notify.rb +1 -1
- data/lib/puppet/type/package.rb +24 -23
- data/lib/puppet/type/router.rb +4 -1
- data/lib/puppet/type/schedule.rb +52 -44
- data/lib/puppet/type/scheduled_task.rb +222 -0
- data/lib/puppet/type/selmodule.rb +10 -6
- data/lib/puppet/type/service.rb +11 -11
- data/lib/puppet/type/ssh_authorized_key.rb +2 -5
- data/lib/puppet/type/sshkey.rb +1 -1
- data/lib/puppet/type/stage.rb +1 -1
- data/lib/puppet/type/tidy.rb +10 -8
- data/lib/puppet/type/user.rb +61 -53
- data/lib/puppet/type/vlan.rb +4 -4
- data/lib/puppet/type/whit.rb +6 -2
- data/lib/puppet/type/yumrepo.rb +33 -31
- data/lib/puppet/type/zfs.rb +34 -32
- data/lib/puppet/type/zone.rb +21 -19
- data/lib/puppet/type/zpool.rb +3 -3
- data/lib/puppet/util.rb +24 -6
- data/lib/puppet/util/adsi.rb +12 -7
- data/lib/puppet/util/checksums.rb +1 -1
- data/lib/puppet/util/diff.rb +1 -1
- data/lib/puppet/util/nagios_maker.rb +2 -2
- data/lib/puppet/util/reference.rb +16 -17
- data/lib/puppet/util/settings/file_setting.rb +14 -2
- data/lib/puppet/util/windows/security.rb +96 -32
- data/spec/integration/file_serving/terminus_helper_spec.rb +1 -1
- data/spec/integration/indirector/direct_file_server_spec.rb +9 -15
- data/spec/integration/indirector/file_content/file_server_spec.rb +1 -1
- data/spec/integration/indirector/file_metadata/file_server_spec.rb +1 -1
- data/spec/integration/provider/package_spec.rb +4 -0
- data/spec/integration/provider/service/init_spec.rb +8 -2
- data/spec/integration/reference/providers_spec.rb +1 -1
- data/spec/integration/ssl/certificate_request_spec.rb +1 -2
- data/spec/integration/ssl/certificate_revocation_list_spec.rb +1 -2
- data/spec/integration/ssl/host_spec.rb +1 -2
- data/spec/integration/transaction_spec.rb +25 -17
- data/spec/integration/type/exec_spec.rb +77 -0
- data/spec/integration/type/file_spec.rb +322 -2
- data/spec/integration/util/windows/security_spec.rb +393 -230
- data/spec/integration/util_spec.rb +16 -0
- data/spec/lib/puppet_spec/files.rb +3 -7
- data/spec/unit/application/apply_spec.rb +0 -9
- data/spec/unit/application/inspect_spec.rb +1 -0
- data/spec/unit/configurer/downloader_spec.rb +3 -3
- data/spec/unit/face/certificate_spec.rb +6 -2
- data/spec/unit/file_bucket/dipper_spec.rb +67 -10
- data/spec/unit/file_bucket/file_spec.rb +22 -28
- data/spec/unit/file_serving/content_spec.rb +1 -1
- data/spec/unit/file_serving/metadata_spec.rb +30 -3
- data/spec/unit/indirector/facts/inventory_service_spec.rb +22 -0
- data/spec/unit/indirector/file_bucket_file/file_spec.rb +21 -24
- data/spec/unit/indirector/node/store_configs_spec.rb +1 -0
- data/spec/unit/indirector/resource/ral_spec.rb +1 -1
- data/spec/unit/indirector/resource_type/parser_spec.rb +2 -2
- data/spec/unit/indirector/rest_spec.rb +1 -1
- data/spec/unit/network/handler/ca_spec.rb +1 -1
- data/spec/unit/network/http/mongrel/rest_spec.rb +54 -25
- data/spec/unit/parameter_spec.rb +36 -0
- data/spec/unit/parser/parser_spec.rb +4 -0
- data/spec/unit/property_spec.rb +2 -2
- data/spec/unit/provider/exec/windows_spec.rb +2 -8
- data/spec/unit/provider/file/posix_spec.rb +6 -0
- data/spec/unit/provider/file/windows_spec.rb +18 -0
- data/spec/unit/provider/group/windows_adsi_spec.rb +22 -6
- data/spec/unit/provider/mount/parsed_spec.rb +1 -1
- data/spec/unit/provider/package/msi_spec.rb +2 -2
- data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +1571 -0
- data/spec/unit/provider/service/launchd_spec.rb +143 -130
- data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +5 -0
- data/spec/unit/provider/user/user_role_add_spec.rb +39 -9
- data/spec/unit/provider/user/useradd_spec.rb +1 -1
- data/spec/unit/provider/user/windows_adsi_spec.rb +8 -1
- data/spec/unit/rb_tree_map_spec.rb +572 -0
- data/spec/unit/resource/catalog_spec.rb +1 -1
- data/spec/unit/simple_graph_spec.rb +9 -9
- data/spec/unit/ssl/host_spec.rb +60 -12
- data/spec/unit/transaction/report_spec.rb +3 -3
- data/spec/unit/transaction_spec.rb +394 -11
- data/spec/unit/type/exec_spec.rb +35 -15
- data/spec/unit/type/file/content_spec.rb +11 -10
- data/spec/unit/type/file/mode_spec.rb +73 -19
- data/spec/unit/type/file/source_spec.rb +1 -1
- data/spec/unit/type/file_spec.rb +15 -0
- data/spec/unit/type/group_spec.rb +1 -1
- data/spec/unit/type/mount_spec.rb +5 -5
- data/spec/unit/type/resources_spec.rb +3 -3
- data/spec/unit/type/scheduled_task_spec.rb +102 -0
- data/spec/unit/type/ssh_authorized_key_spec.rb +2 -3
- data/spec/unit/type/user_spec.rb +2 -1
- data/spec/unit/type_spec.rb +48 -4
- data/spec/unit/util/adsi_spec.rb +18 -7
- data/spec/unit/util/checksums_spec.rb +20 -2
- data/spec/unit/util/execution_stub_spec.rb +10 -5
- data/spec/unit/util/logging_spec.rb +6 -6
- data/spec/unit/util/rdoc/parser_spec.rb +1 -1
- data/spec/unit/util/reference_spec.rb +29 -0
- data/spec/unit/util/settings/file_setting_spec.rb +8 -2
- data/spec/unit/util_spec.rb +115 -0
- data/test/other/transactions.rb +5 -11
- data/test/ral/type/exec.rb +1 -1
- metadata +24 -11
data/lib/puppet/property.rb
CHANGED
@@ -100,11 +100,11 @@ class Puppet::Property < Puppet::Parameter
|
|
100
100
|
def change_to_s(current_value, newvalue)
|
101
101
|
begin
|
102
102
|
if current_value == :absent
|
103
|
-
return "defined '#{name}' as
|
103
|
+
return "defined '#{name}' as #{self.class.format_value_for_display should_to_s(newvalue)}"
|
104
104
|
elsif newvalue == :absent or newvalue == [:absent]
|
105
|
-
return "undefined '#{name}' from
|
105
|
+
return "undefined '#{name}' from #{self.class.format_value_for_display is_to_s(current_value)}"
|
106
106
|
else
|
107
|
-
return "#{name} changed
|
107
|
+
return "#{name} changed #{self.class.format_value_for_display is_to_s(current_value)} to #{self.class.format_value_for_display should_to_s(newvalue)}"
|
108
108
|
end
|
109
109
|
rescue Puppet::Error, Puppet::DevError
|
110
110
|
raise
|
@@ -298,7 +298,7 @@ Puppet::Type.type(:augeas).provide(:augeas) do
|
|
298
298
|
saved_files.each do |key|
|
299
299
|
saved_file = @aug.get(key).to_s.sub(/^\/files/, root)
|
300
300
|
if Puppet[:show_diff]
|
301
|
-
|
301
|
+
notice "\n" + diff(saved_file, saved_file + ".augnew")
|
302
302
|
end
|
303
303
|
if resource.noop?
|
304
304
|
File.delete(saved_file + ".augnew")
|
@@ -3,8 +3,8 @@ require 'puppet/provider/exec'
|
|
3
3
|
Puppet::Type.type(:exec).provide :windows, :parent => Puppet::Provider::Exec do
|
4
4
|
include Puppet::Util::Execution
|
5
5
|
|
6
|
-
confine
|
7
|
-
defaultfor :
|
6
|
+
confine :operatingsystem => :windows
|
7
|
+
defaultfor :operatingsystem => :windows
|
8
8
|
|
9
9
|
desc "Execute external binaries directly, on Windows systems.
|
10
10
|
This does not pass through a shell, or perform any interpolation, but
|
@@ -23,11 +23,10 @@ only directly calls the command with the arguments given."
|
|
23
23
|
return
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
return if exts.any? {|ext| which(exe + ext) }
|
26
|
+
if resource[:path]
|
27
|
+
withenv :PATH => resource[:path].join(File::PATH_SEPARATOR) do
|
28
|
+
return if which(exe)
|
29
|
+
end
|
31
30
|
end
|
32
31
|
|
33
32
|
raise ArgumentError, "Could not find command '#{exe}'"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Puppet::Type.type(:file).provide :windows do
|
2
2
|
desc "Uses Microsoft Windows functionality to manage file's users and rights."
|
3
3
|
|
4
|
-
confine :
|
4
|
+
confine :operatingsystem => :windows
|
5
5
|
|
6
6
|
include Puppet::Util::Warnings
|
7
7
|
|
@@ -81,7 +81,8 @@ Puppet::Type.type(:file).provide :windows do
|
|
81
81
|
|
82
82
|
def mode
|
83
83
|
if resource.exist?
|
84
|
-
get_mode(resource[:path])
|
84
|
+
mode = get_mode(resource[:path])
|
85
|
+
mode ? mode.to_s(8) : :absent
|
85
86
|
else
|
86
87
|
:absent
|
87
88
|
end
|
@@ -97,4 +98,10 @@ Puppet::Type.type(:file).provide :windows do
|
|
97
98
|
end
|
98
99
|
:file_changed
|
99
100
|
end
|
101
|
+
|
102
|
+
def validate
|
103
|
+
if [:owner, :group, :mode].any?{|p| resource[p]} and !supports_acl?(resource[:path])
|
104
|
+
resource.fail("Can only manage owner, group, and mode on filesystems that support Windows ACLs, such as NTFS")
|
105
|
+
end
|
106
|
+
end
|
100
107
|
end
|
@@ -3,11 +3,11 @@
|
|
3
3
|
# mkgroup, rmgroup, lsgroup, chgroup
|
4
4
|
#
|
5
5
|
# Author:: Hector Rivas Gandara <keymon@gmail.com>
|
6
|
-
#
|
6
|
+
#
|
7
7
|
require 'puppet/provider/aixobject'
|
8
8
|
|
9
9
|
Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject do
|
10
|
-
desc "Group management for AIX
|
10
|
+
desc "Group management for AIX."
|
11
11
|
|
12
12
|
# This will the the default provider for this platform
|
13
13
|
defaultfor :operatingsystem => :aix
|
@@ -29,7 +29,7 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# AIX attributes to properties mapping.
|
32
|
-
#
|
32
|
+
#
|
33
33
|
# Valid attributes to be managed by this provider.
|
34
34
|
# It is a list with of hash
|
35
35
|
# :aix_attr AIX command attribute name
|
@@ -43,10 +43,10 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
|
|
43
43
|
:from => :users_from_attr},
|
44
44
|
{:aix_attr => :attributes, :puppet_prop => :attributes},
|
45
45
|
]
|
46
|
-
|
46
|
+
|
47
47
|
#--------------
|
48
48
|
# Command definition
|
49
|
-
|
49
|
+
|
50
50
|
# Return the IA module arguments based on the resource param ia_load_module
|
51
51
|
def get_ia_module_args
|
52
52
|
if @resource[:ia_load_module]
|
@@ -55,7 +55,7 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
|
|
55
55
|
[]
|
56
56
|
end
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def lscmd(value=@resource[:name])
|
60
60
|
[self.class.command(:list)] +
|
61
61
|
self.get_ia_module_args +
|
@@ -80,7 +80,7 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
|
|
80
80
|
def modifycmd(hash = property_hash)
|
81
81
|
args = self.hash2args(hash)
|
82
82
|
return nil if args.empty?
|
83
|
-
|
83
|
+
|
84
84
|
[self.class.command(:modify)] +
|
85
85
|
self.get_ia_module_args +
|
86
86
|
args + [@resource[:name]]
|
@@ -123,7 +123,7 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
|
|
123
123
|
#self.class.validate(param, value)
|
124
124
|
param = :attributes
|
125
125
|
cmd = modifycmd({param => filter_attributes(attr_hash)})
|
126
|
-
if cmd
|
126
|
+
if cmd
|
127
127
|
begin
|
128
128
|
execute(cmd)
|
129
129
|
rescue Puppet::ExecutionFailure => detail
|
@@ -1,9 +1,7 @@
|
|
1
1
|
require 'puppet/provider/nameservice/objectadd'
|
2
2
|
|
3
3
|
Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameService::ObjectAdd do
|
4
|
-
desc "Group management via `groupadd` and its ilk.
|
5
|
-
|
6
|
-
The default for most platforms
|
4
|
+
desc "Group management via `groupadd` and its ilk. The default for most platforms.
|
7
5
|
|
8
6
|
"
|
9
7
|
|
@@ -1,18 +1,16 @@
|
|
1
1
|
require 'puppet/provider/ldap'
|
2
2
|
|
3
3
|
Puppet::Type.type(:group).provide :ldap, :parent => Puppet::Provider::Ldap do
|
4
|
-
desc "Group management via
|
4
|
+
desc "Group management via LDAP.
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
This provider requires that you have valid values for all of the
|
7
|
+
LDAP-related settings in `puppet.conf`, including `ldapbase`. You will
|
8
|
+
almost definitely need settings for `ldapuser` and `ldappassword` in order
|
9
|
+
for your clients to write to LDAP.
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
"
|
11
|
+
Note that this provider will automatically generate a GID for you if you do
|
12
|
+
not specify one, but it is a potentially expensive operation, as it
|
13
|
+
iterates across all existing groups to pick the appropriate next one."
|
16
14
|
|
17
15
|
confine :true => Puppet.features.ldap?, :false => (Puppet[:ldapuser] == "")
|
18
16
|
|
@@ -4,8 +4,7 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
4
4
|
desc "Group management for Windows"
|
5
5
|
|
6
6
|
defaultfor :operatingsystem => :windows
|
7
|
-
confine
|
8
|
-
confine :feature => :microsoft_windows
|
7
|
+
confine :operatingsystem => :windows
|
9
8
|
|
10
9
|
has_features :manages_members
|
11
10
|
|
@@ -23,6 +22,8 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
23
22
|
|
24
23
|
def create
|
25
24
|
@group = Puppet::Util::ADSI::Group.create(@resource[:name])
|
25
|
+
@group.commit
|
26
|
+
|
26
27
|
self.members = @resource[:members]
|
27
28
|
end
|
28
29
|
|
@@ -34,6 +35,11 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
34
35
|
Puppet::Util::ADSI::Group.delete(@resource[:name])
|
35
36
|
end
|
36
37
|
|
38
|
+
# Only flush if we created or modified a group, not deleted
|
39
|
+
def flush
|
40
|
+
@group.commit if @group
|
41
|
+
end
|
42
|
+
|
37
43
|
def gid
|
38
44
|
Puppet::Util::ADSI.sid_for_account(@resource[:name])
|
39
45
|
end
|
@@ -2,7 +2,7 @@ require 'puppet/provider/package'
|
|
2
2
|
require 'puppet/util/package'
|
3
3
|
|
4
4
|
Puppet::Type.type(:package).provide :aix, :parent => Puppet::Provider::Package do
|
5
|
-
desc "Installation from AIX
|
5
|
+
desc "Installation from the AIX software directory."
|
6
6
|
|
7
7
|
# The commands we are using on an AIX box are installed standard
|
8
8
|
# (except nimclient) nimclient needs the bos.sysmgt.nim.client fileset.
|
@@ -4,10 +4,10 @@ Puppet::Type.type(:package).provide :macports, :parent => Puppet::Provider::Pack
|
|
4
4
|
desc "Package management using MacPorts on OS X.
|
5
5
|
|
6
6
|
Supports MacPorts versions and revisions, but not variants.
|
7
|
-
Variant preferences may be specified using
|
8
|
-
http://guide.macports.org/chunked/internals.configuration-files.html#internals.configuration-files.variants-conf
|
7
|
+
Variant preferences may be specified using
|
8
|
+
[the MacPorts variants.conf file](http://guide.macports.org/chunked/internals.configuration-files.html#internals.configuration-files.variants-conf).
|
9
9
|
|
10
|
-
When specifying a version in the Puppet DSL, only specify the version, not the revision
|
10
|
+
When specifying a version in the Puppet DSL, only specify the version, not the revision.
|
11
11
|
Revisions are only used internally for ensuring the latest version/revision of a port.
|
12
12
|
"
|
13
13
|
|
@@ -38,32 +38,39 @@ Puppet::Type.type(:package).provide(:msi, :parent => Puppet::Provider::Package)
|
|
38
38
|
# Unfortunately, we can't use the msiexec method defined earlier,
|
39
39
|
# because of the special quoting we need to do around the MSI
|
40
40
|
# properties to use.
|
41
|
-
execute ['msiexec.exe', '/qn', '/norestart', '/i', shell_quote(
|
41
|
+
execute ['msiexec.exe', '/qn', '/norestart', '/i', shell_quote(msi_source), properties_for_command].flatten.compact.join(' ')
|
42
42
|
|
43
43
|
File.open(state_file, 'w') do |f|
|
44
44
|
metadata = {
|
45
45
|
'name' => resource[:name],
|
46
46
|
'install_options' => resource[:install_options],
|
47
|
-
'source' =>
|
47
|
+
'source' => msi_source
|
48
48
|
}
|
49
49
|
|
50
|
-
f.puts(YAML.dump
|
50
|
+
f.puts(YAML.dump(metadata))
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
54
|
def uninstall
|
55
|
-
msiexec '/qn', '/norestart', '/x',
|
55
|
+
msiexec '/qn', '/norestart', '/x', msi_source
|
56
56
|
|
57
57
|
File.delete state_file
|
58
58
|
end
|
59
59
|
|
60
60
|
def validate_source(value)
|
61
|
-
fail("The source parameter is required when using the MSI provider.") if value.nil?
|
62
61
|
fail("The source parameter cannot be empty when using the MSI provider.") if value.empty?
|
63
62
|
end
|
64
63
|
|
65
64
|
private
|
66
65
|
|
66
|
+
def msi_source
|
67
|
+
resource[:source] ||= YAML.load_file(state_file)['source'] rescue nil
|
68
|
+
|
69
|
+
fail("The source parameter is required when using the MSI provider.") unless resource[:source]
|
70
|
+
|
71
|
+
resource[:source]
|
72
|
+
end
|
73
|
+
|
67
74
|
def self.installed_listing_dir
|
68
75
|
listing_dir = File.join(Puppet[:vardir], 'db', 'package', 'msi')
|
69
76
|
|
@@ -2,7 +2,7 @@ require 'puppet/provider/package'
|
|
2
2
|
require 'puppet/util/package'
|
3
3
|
|
4
4
|
Puppet::Type.type(:package).provide :nim, :parent => :aix, :source => :aix do
|
5
|
-
desc "Installation from NIM LPP source"
|
5
|
+
desc "Installation from NIM LPP source."
|
6
6
|
|
7
7
|
# The commands we are using on an AIX box are installed standard
|
8
8
|
# (except nimclient) nimclient needs the bos.sysmgt.nim.client fileset.
|
@@ -15,9 +15,9 @@ Puppet::Type.type(:package).provide :pkgdmg, :parent => Puppet::Provider::Packag
|
|
15
15
|
desc "Package management based on Apple's Installer.app and
|
16
16
|
DiskUtility.app. This package works by checking the contents of a
|
17
17
|
DMG image for Apple pkg or mpkg files. Any number of pkg or mpkg
|
18
|
-
files may exist in the root directory of the DMG file system.
|
19
|
-
|
20
|
-
|
18
|
+
files may exist in the root directory of the DMG file system.
|
19
|
+
Subdirectories are not checked for packages. See
|
20
|
+
[the wiki docs on this provider](http://projects.puppetlabs.com/projects/puppet/wiki/Package_Management_With_Dmg_Patterns)
|
21
21
|
for more detail."
|
22
22
|
|
23
23
|
confine :operatingsystem => :darwin
|
@@ -1,5 +1,5 @@
|
|
1
1
|
Puppet::Type.type(:package).provide :ports, :parent => :freebsd, :source => :freebsd do
|
2
|
-
desc "Support for FreeBSD's ports.
|
2
|
+
desc "Support for FreeBSD's ports. Note that this, too, mixes packages and ports."
|
3
3
|
|
4
4
|
commands :portupgrade => "/usr/local/sbin/portupgrade",
|
5
5
|
:portversion => "/usr/local/sbin/portversion",
|
@@ -0,0 +1,560 @@
|
|
1
|
+
require 'puppet/parameter'
|
2
|
+
|
3
|
+
if Puppet.features.microsoft_windows?
|
4
|
+
require 'win32/taskscheduler'
|
5
|
+
require 'puppet/util/adsi'
|
6
|
+
end
|
7
|
+
|
8
|
+
Puppet::Type.type(:scheduled_task).provide(:win32_taskscheduler) do
|
9
|
+
desc 'This uses the win32-taskscheduler gem to provide support for
|
10
|
+
managing scheduled tasks on Windows.'
|
11
|
+
|
12
|
+
defaultfor :operatingsystem => :windows
|
13
|
+
confine :operatingsystem => :windows
|
14
|
+
|
15
|
+
def self.instances
|
16
|
+
Win32::TaskScheduler.new.tasks.collect do |job_file|
|
17
|
+
job_title = File.basename(job_file, '.job')
|
18
|
+
|
19
|
+
new(
|
20
|
+
:provider => :win32_taskscheduler,
|
21
|
+
:name => job_title
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def exists?
|
27
|
+
Win32::TaskScheduler.new.exists? resource[:name]
|
28
|
+
end
|
29
|
+
|
30
|
+
def task
|
31
|
+
return @task if @task
|
32
|
+
|
33
|
+
@task ||= Win32::TaskScheduler.new
|
34
|
+
@task.activate(resource[:name] + '.job') if exists?
|
35
|
+
|
36
|
+
@task
|
37
|
+
end
|
38
|
+
|
39
|
+
def clear_task
|
40
|
+
@task = nil
|
41
|
+
@triggers = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def enabled
|
45
|
+
task.flags & Win32::TaskScheduler::DISABLED == 0 ? :true : :false
|
46
|
+
end
|
47
|
+
|
48
|
+
def command
|
49
|
+
task.application_name
|
50
|
+
end
|
51
|
+
|
52
|
+
def arguments
|
53
|
+
task.parameters
|
54
|
+
end
|
55
|
+
|
56
|
+
def working_dir
|
57
|
+
task.working_directory
|
58
|
+
end
|
59
|
+
|
60
|
+
def user
|
61
|
+
account = task.account_information
|
62
|
+
return 'system' if account == ''
|
63
|
+
account
|
64
|
+
end
|
65
|
+
|
66
|
+
def trigger
|
67
|
+
return @triggers if @triggers
|
68
|
+
|
69
|
+
@triggers = []
|
70
|
+
task.trigger_count.times do |i|
|
71
|
+
trigger = begin
|
72
|
+
task.trigger(i)
|
73
|
+
rescue Win32::TaskScheduler::Error => e
|
74
|
+
# Win32::TaskScheduler can't handle all of the
|
75
|
+
# trigger types Windows uses, so we need to skip the
|
76
|
+
# unhandled types to prevent "puppet resource" from
|
77
|
+
# blowing up.
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
next unless trigger and scheduler_trigger_types.include?(trigger['trigger_type'])
|
81
|
+
|
82
|
+
puppet_trigger = {}
|
83
|
+
case trigger['trigger_type']
|
84
|
+
when Win32::TaskScheduler::TASK_TIME_TRIGGER_DAILY
|
85
|
+
puppet_trigger['schedule'] = 'daily'
|
86
|
+
puppet_trigger['every'] = trigger['type']['days_interval'].to_s
|
87
|
+
when Win32::TaskScheduler::TASK_TIME_TRIGGER_WEEKLY
|
88
|
+
puppet_trigger['schedule'] = 'weekly'
|
89
|
+
puppet_trigger['every'] = trigger['type']['weeks_interval'].to_s
|
90
|
+
puppet_trigger['on'] = days_of_week_from_bitfield(trigger['type']['days_of_week'])
|
91
|
+
when Win32::TaskScheduler::TASK_TIME_TRIGGER_MONTHLYDATE
|
92
|
+
puppet_trigger['schedule'] = 'monthly'
|
93
|
+
puppet_trigger['months'] = months_from_bitfield(trigger['type']['months'])
|
94
|
+
puppet_trigger['on'] = days_from_bitfield(trigger['type']['days'])
|
95
|
+
when Win32::TaskScheduler::TASK_TIME_TRIGGER_MONTHLYDOW
|
96
|
+
puppet_trigger['schedule'] = 'monthly'
|
97
|
+
puppet_trigger['months'] = months_from_bitfield(trigger['type']['months'])
|
98
|
+
puppet_trigger['which_occurrence'] = occurrence_constant_to_name(trigger['type']['weeks'])
|
99
|
+
puppet_trigger['day_of_week'] = days_of_week_from_bitfield(trigger['type']['days_of_week'])
|
100
|
+
when Win32::TaskScheduler::TASK_TIME_TRIGGER_ONCE
|
101
|
+
puppet_trigger['schedule'] = 'once'
|
102
|
+
end
|
103
|
+
puppet_trigger['start_date'] = self.class.normalized_date("#{trigger['start_year']}-#{trigger['start_month']}-#{trigger['start_day']}")
|
104
|
+
puppet_trigger['start_time'] = self.class.normalized_time("#{trigger['start_hour']}:#{trigger['start_minute']}")
|
105
|
+
puppet_trigger['enabled'] = trigger['flags'] & Win32::TaskScheduler::TASK_TRIGGER_FLAG_DISABLED == 0
|
106
|
+
puppet_trigger['index'] = i
|
107
|
+
|
108
|
+
@triggers << puppet_trigger
|
109
|
+
end
|
110
|
+
@triggers = @triggers[0] if @triggers.length == 1
|
111
|
+
|
112
|
+
@triggers
|
113
|
+
end
|
114
|
+
|
115
|
+
def user_insync?(current, should)
|
116
|
+
return false unless current
|
117
|
+
|
118
|
+
# Win32::TaskScheduler can return the 'SYSTEM' account as the
|
119
|
+
# empty string.
|
120
|
+
current = 'system' if current == ''
|
121
|
+
|
122
|
+
# By comparing account SIDs we don't have to worry about case
|
123
|
+
# sensitivity, or canonicalization of the account name.
|
124
|
+
Puppet::Util::ADSI.sid_for_account(current) == Puppet::Util::ADSI.sid_for_account(should[0])
|
125
|
+
end
|
126
|
+
|
127
|
+
def trigger_insync?(current, should)
|
128
|
+
should = [should] unless should.is_a?(Array)
|
129
|
+
current = [current] unless current.is_a?(Array)
|
130
|
+
return false unless current.length == should.length
|
131
|
+
|
132
|
+
current_in_sync = current.all? do |c|
|
133
|
+
should.any? {|s| triggers_same?(c, s)}
|
134
|
+
end
|
135
|
+
|
136
|
+
should_in_sync = should.all? do |s|
|
137
|
+
current.any? {|c| triggers_same?(c,s)}
|
138
|
+
end
|
139
|
+
|
140
|
+
current_in_sync && should_in_sync
|
141
|
+
end
|
142
|
+
|
143
|
+
def command=(value)
|
144
|
+
task.application_name = value
|
145
|
+
end
|
146
|
+
|
147
|
+
def arguments=(value)
|
148
|
+
task.parameters = value
|
149
|
+
end
|
150
|
+
|
151
|
+
def working_dir=(value)
|
152
|
+
task.working_directory = value
|
153
|
+
end
|
154
|
+
|
155
|
+
def enabled=(value)
|
156
|
+
if value == :true
|
157
|
+
task.flags = task.flags & ~Win32::TaskScheduler::DISABLED
|
158
|
+
else
|
159
|
+
task.flags = task.flags | Win32::TaskScheduler::DISABLED
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def trigger=(value)
|
164
|
+
desired_triggers = value.is_a?(Array) ? value : [value]
|
165
|
+
current_triggers = trigger.is_a?(Array) ? trigger : [trigger]
|
166
|
+
|
167
|
+
extra_triggers = []
|
168
|
+
desired_to_search = desired_triggers.dup
|
169
|
+
current_triggers.each do |current|
|
170
|
+
if found = desired_to_search.find {|desired| triggers_same?(current, desired)}
|
171
|
+
desired_to_search.delete(found)
|
172
|
+
else
|
173
|
+
extra_triggers << current['index']
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
needed_triggers = []
|
178
|
+
current_to_search = current_triggers.dup
|
179
|
+
desired_triggers.each do |desired|
|
180
|
+
if found = current_to_search.find {|current| triggers_same?(current, desired)}
|
181
|
+
current_to_search.delete(found)
|
182
|
+
else
|
183
|
+
needed_triggers << desired
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
extra_triggers.reverse_each do |index|
|
188
|
+
task.delete_trigger(index)
|
189
|
+
end
|
190
|
+
|
191
|
+
needed_triggers.each do |trigger_hash|
|
192
|
+
# Even though this is an assignment, the API for
|
193
|
+
# Win32::TaskScheduler ends up appending this trigger to the
|
194
|
+
# list of triggers for the task, while #add_trigger is only able
|
195
|
+
# to replace existing triggers. *shrug*
|
196
|
+
task.trigger = translate_hash_to_trigger(trigger_hash)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def user=(value)
|
201
|
+
self.fail("Invalid user: #{value}") unless Puppet::Util::ADSI.sid_for_account(value)
|
202
|
+
|
203
|
+
if value.to_s.downcase != 'system'
|
204
|
+
task.set_account_information(value, resource[:password])
|
205
|
+
else
|
206
|
+
# Win32::TaskScheduler treats a nil/empty username & password as
|
207
|
+
# requesting the SYSTEM account.
|
208
|
+
task.set_account_information(nil, nil)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def create
|
213
|
+
clear_task
|
214
|
+
@task = Win32::TaskScheduler.new(resource[:name], dummy_time_trigger)
|
215
|
+
|
216
|
+
self.command = resource[:command]
|
217
|
+
|
218
|
+
[:arguments, :working_dir, :enabled, :trigger, :user].each do |prop|
|
219
|
+
send("#{prop}=", resource[prop]) if resource[prop]
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def destroy
|
224
|
+
Win32::TaskScheduler.new.delete(resource[:name] + '.job')
|
225
|
+
end
|
226
|
+
|
227
|
+
def flush
|
228
|
+
unless resource[:ensure] == :absent
|
229
|
+
self.fail('Parameter command is required.') unless resource[:command]
|
230
|
+
task.save
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def triggers_same?(current_trigger, desired_trigger)
|
235
|
+
return false unless current_trigger['schedule'] == desired_trigger['schedule']
|
236
|
+
return false if current_trigger.has_key?('enabled') && !current_trigger['enabled']
|
237
|
+
|
238
|
+
desired = desired_trigger.dup
|
239
|
+
|
240
|
+
desired['every'] ||= current_trigger['every'] if current_trigger.has_key?('every')
|
241
|
+
desired['months'] ||= current_trigger['months'] if current_trigger.has_key?('months')
|
242
|
+
desired['on'] ||= current_trigger['on'] if current_trigger.has_key?('on')
|
243
|
+
desired['day_of_week'] ||= current_trigger['day_of_week'] if current_trigger.has_key?('day_of_week')
|
244
|
+
|
245
|
+
translate_hash_to_trigger(current_trigger) == translate_hash_to_trigger(desired)
|
246
|
+
end
|
247
|
+
|
248
|
+
def self.normalized_date(date_string)
|
249
|
+
date = Date.parse("#{date_string}")
|
250
|
+
"#{date.year}-#{date.month}-#{date.day}"
|
251
|
+
end
|
252
|
+
|
253
|
+
def self.normalized_time(time_string)
|
254
|
+
Time.parse("#{time_string}").strftime('%H:%M')
|
255
|
+
end
|
256
|
+
|
257
|
+
def dummy_time_trigger
|
258
|
+
now = Time.now
|
259
|
+
|
260
|
+
{
|
261
|
+
'flags' => 0,
|
262
|
+
'random_minutes_interval' => 0,
|
263
|
+
'end_day' => 0,
|
264
|
+
"end_year" => 0,
|
265
|
+
"trigger_type" => 0,
|
266
|
+
"minutes_interval" => 0,
|
267
|
+
"end_month" => 0,
|
268
|
+
"minutes_duration" => 0,
|
269
|
+
'start_year' => now.year,
|
270
|
+
'start_month' => now.month,
|
271
|
+
'start_day' => now.day,
|
272
|
+
'start_hour' => now.hour,
|
273
|
+
'start_minute' => now.min,
|
274
|
+
'trigger_type' => Win32::TaskScheduler::ONCE,
|
275
|
+
}
|
276
|
+
end
|
277
|
+
|
278
|
+
def translate_hash_to_trigger(puppet_trigger, user_provided_input=false)
|
279
|
+
trigger = dummy_time_trigger
|
280
|
+
|
281
|
+
if user_provided_input
|
282
|
+
self.fail "'enabled' is read-only on triggers" if puppet_trigger.has_key?('enabled')
|
283
|
+
self.fail "'index' is read-only on triggers" if puppet_trigger.has_key?('index')
|
284
|
+
end
|
285
|
+
puppet_trigger.delete('index')
|
286
|
+
|
287
|
+
if puppet_trigger.delete('enabled') == false
|
288
|
+
trigger['flags'] |= Win32::TaskScheduler::TASK_TRIGGER_FLAG_DISABLED
|
289
|
+
else
|
290
|
+
trigger['flags'] &= ~Win32::TaskScheduler::TASK_TRIGGER_FLAG_DISABLED
|
291
|
+
end
|
292
|
+
|
293
|
+
extra_keys = puppet_trigger.keys.sort - ['schedule', 'start_date', 'start_time', 'every', 'months', 'on', 'which_occurrence', 'day_of_week']
|
294
|
+
self.fail "Unknown trigger option(s): #{Puppet::Parameter.format_value_for_display(extra_keys)}" unless extra_keys.empty?
|
295
|
+
self.fail "Must specify 'start_time' when defining a trigger" unless puppet_trigger['start_time']
|
296
|
+
|
297
|
+
case puppet_trigger['schedule']
|
298
|
+
when 'daily'
|
299
|
+
trigger['trigger_type'] = Win32::TaskScheduler::DAILY
|
300
|
+
trigger['type'] = {
|
301
|
+
'days_interval' => Integer(puppet_trigger['every'] || 1)
|
302
|
+
}
|
303
|
+
when 'weekly'
|
304
|
+
trigger['trigger_type'] = Win32::TaskScheduler::WEEKLY
|
305
|
+
trigger['type'] = {
|
306
|
+
'weeks_interval' => Integer(puppet_trigger['every'] || 1)
|
307
|
+
}
|
308
|
+
|
309
|
+
trigger['type']['days_of_week'] = if puppet_trigger['day_of_week']
|
310
|
+
bitfield_from_days_of_week(puppet_trigger['day_of_week'])
|
311
|
+
else
|
312
|
+
scheduler_days_of_week.inject(0) {|day_flags,day| day_flags |= day}
|
313
|
+
end
|
314
|
+
when 'monthly'
|
315
|
+
trigger['type'] = {
|
316
|
+
'months' => bitfield_from_months(puppet_trigger['months'] || (1..12).to_a),
|
317
|
+
}
|
318
|
+
|
319
|
+
if puppet_trigger.keys.include?('on')
|
320
|
+
if puppet_trigger.has_key?('day_of_week') or puppet_trigger.has_key?('which_occurrence')
|
321
|
+
self.fail "Neither 'day_of_week' nor 'which_occurrence' can be specified when creating a monthly date-based trigger"
|
322
|
+
end
|
323
|
+
|
324
|
+
trigger['trigger_type'] = Win32::TaskScheduler::MONTHLYDATE
|
325
|
+
trigger['type']['days'] = bitfield_from_days(puppet_trigger['on'])
|
326
|
+
elsif puppet_trigger.keys.include?('which_occurrence') or puppet_trigger.keys.include?('day_of_week')
|
327
|
+
self.fail 'which_occurrence cannot be specified as an array' if puppet_trigger['which_occurrence'].is_a?(Array)
|
328
|
+
%w{day_of_week which_occurrence}.each do |field|
|
329
|
+
self.fail "#{field} must be specified when creating a monthly day-of-week based trigger" unless puppet_trigger.has_key?(field)
|
330
|
+
end
|
331
|
+
|
332
|
+
trigger['trigger_type'] = Win32::TaskScheduler::MONTHLYDOW
|
333
|
+
trigger['type']['weeks'] = occurrence_name_to_constant(puppet_trigger['which_occurrence'])
|
334
|
+
trigger['type']['days_of_week'] = bitfield_from_days_of_week(puppet_trigger['day_of_week'])
|
335
|
+
else
|
336
|
+
self.fail "Don't know how to create a 'monthly' schedule with the options: #{puppet_trigger.keys.sort.join(', ')}"
|
337
|
+
end
|
338
|
+
when 'once'
|
339
|
+
self.fail "Must specify 'start_date' when defining a one-time trigger" unless puppet_trigger['start_date']
|
340
|
+
|
341
|
+
trigger['trigger_type'] = Win32::TaskScheduler::ONCE
|
342
|
+
else
|
343
|
+
self.fail "Unknown schedule type: #{puppet_trigger["schedule"].inspect}"
|
344
|
+
end
|
345
|
+
|
346
|
+
if start_date = puppet_trigger['start_date']
|
347
|
+
start_date = Date.parse(start_date)
|
348
|
+
self.fail "start_date must be on or after 1753-01-01" unless start_date >= Date.new(1753, 1, 1)
|
349
|
+
|
350
|
+
trigger['start_year'] = start_date.year
|
351
|
+
trigger['start_month'] = start_date.month
|
352
|
+
trigger['start_day'] = start_date.day
|
353
|
+
end
|
354
|
+
|
355
|
+
start_time = Time.parse(puppet_trigger['start_time'])
|
356
|
+
trigger['start_hour'] = start_time.hour
|
357
|
+
trigger['start_minute'] = start_time.min
|
358
|
+
|
359
|
+
trigger
|
360
|
+
end
|
361
|
+
|
362
|
+
def validate_trigger(value)
|
363
|
+
value = [value] unless value.is_a?(Array)
|
364
|
+
|
365
|
+
# translate_hash_to_trigger handles the same validation that we
|
366
|
+
# would be doing here at the individual trigger level.
|
367
|
+
value.each {|t| translate_hash_to_trigger(t, true)}
|
368
|
+
|
369
|
+
true
|
370
|
+
end
|
371
|
+
|
372
|
+
private
|
373
|
+
|
374
|
+
def bitfield_from_months(months)
|
375
|
+
bitfield = 0
|
376
|
+
|
377
|
+
months = [months] unless months.is_a?(Array)
|
378
|
+
months.each do |month|
|
379
|
+
integer_month = Integer(month) rescue nil
|
380
|
+
self.fail 'Month must be specified as an integer in the range 1-12' unless integer_month == month.to_f and integer_month.between?(1,12)
|
381
|
+
|
382
|
+
bitfield |= scheduler_months[integer_month - 1]
|
383
|
+
end
|
384
|
+
|
385
|
+
bitfield
|
386
|
+
end
|
387
|
+
|
388
|
+
def bitfield_from_days(days)
|
389
|
+
bitfield = 0
|
390
|
+
|
391
|
+
days = [days] unless days.is_a?(Array)
|
392
|
+
days.each do |day|
|
393
|
+
# The special "day" of 'last' is represented by day "number"
|
394
|
+
# 32. 'last' has the special meaning of "the last day of the
|
395
|
+
# month", no matter how many days there are in the month.
|
396
|
+
day = 32 if day == 'last'
|
397
|
+
|
398
|
+
integer_day = Integer(day)
|
399
|
+
self.fail "Day must be specified as an integer in the range 1-31, or as 'last'" unless integer_day = day.to_f and integer_day.between?(1,32)
|
400
|
+
|
401
|
+
bitfield |= 1 << integer_day - 1
|
402
|
+
end
|
403
|
+
|
404
|
+
bitfield
|
405
|
+
end
|
406
|
+
|
407
|
+
def bitfield_from_days_of_week(days_of_week)
|
408
|
+
bitfield = 0
|
409
|
+
|
410
|
+
days_of_week = [days_of_week] unless days_of_week.is_a?(Array)
|
411
|
+
days_of_week.each do |day_of_week|
|
412
|
+
bitfield |= day_of_week_name_to_constant(day_of_week)
|
413
|
+
end
|
414
|
+
|
415
|
+
bitfield
|
416
|
+
end
|
417
|
+
|
418
|
+
def months_from_bitfield(bitfield)
|
419
|
+
months = []
|
420
|
+
|
421
|
+
scheduler_months.each do |month|
|
422
|
+
if bitfield & month != 0
|
423
|
+
months << month_constant_to_number(month)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
months
|
428
|
+
end
|
429
|
+
|
430
|
+
def days_from_bitfield(bitfield)
|
431
|
+
days = []
|
432
|
+
|
433
|
+
i = 0
|
434
|
+
while bitfield > 0
|
435
|
+
if bitfield & 1 > 0
|
436
|
+
# Day 32 has the special meaning of "the last day of the
|
437
|
+
# month", no matter how many days there are in the month.
|
438
|
+
days << (i == 31 ? 'last' : i + 1)
|
439
|
+
end
|
440
|
+
|
441
|
+
bitfield = bitfield >> 1
|
442
|
+
i += 1
|
443
|
+
end
|
444
|
+
|
445
|
+
days
|
446
|
+
end
|
447
|
+
|
448
|
+
def days_of_week_from_bitfield(bitfield)
|
449
|
+
days_of_week = []
|
450
|
+
|
451
|
+
scheduler_days_of_week.each do |day_of_week|
|
452
|
+
if bitfield & day_of_week != 0
|
453
|
+
days_of_week << day_of_week_constant_to_name(day_of_week)
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
days_of_week
|
458
|
+
end
|
459
|
+
|
460
|
+
def scheduler_trigger_types
|
461
|
+
[
|
462
|
+
Win32::TaskScheduler::TASK_TIME_TRIGGER_DAILY,
|
463
|
+
Win32::TaskScheduler::TASK_TIME_TRIGGER_WEEKLY,
|
464
|
+
Win32::TaskScheduler::TASK_TIME_TRIGGER_MONTHLYDATE,
|
465
|
+
Win32::TaskScheduler::TASK_TIME_TRIGGER_MONTHLYDOW,
|
466
|
+
Win32::TaskScheduler::TASK_TIME_TRIGGER_ONCE
|
467
|
+
]
|
468
|
+
end
|
469
|
+
|
470
|
+
def scheduler_days_of_week
|
471
|
+
[
|
472
|
+
Win32::TaskScheduler::SUNDAY,
|
473
|
+
Win32::TaskScheduler::MONDAY,
|
474
|
+
Win32::TaskScheduler::TUESDAY,
|
475
|
+
Win32::TaskScheduler::WEDNESDAY,
|
476
|
+
Win32::TaskScheduler::THURSDAY,
|
477
|
+
Win32::TaskScheduler::FRIDAY,
|
478
|
+
Win32::TaskScheduler::SATURDAY
|
479
|
+
]
|
480
|
+
end
|
481
|
+
|
482
|
+
def scheduler_months
|
483
|
+
[
|
484
|
+
Win32::TaskScheduler::JANUARY,
|
485
|
+
Win32::TaskScheduler::FEBRUARY,
|
486
|
+
Win32::TaskScheduler::MARCH,
|
487
|
+
Win32::TaskScheduler::APRIL,
|
488
|
+
Win32::TaskScheduler::MAY,
|
489
|
+
Win32::TaskScheduler::JUNE,
|
490
|
+
Win32::TaskScheduler::JULY,
|
491
|
+
Win32::TaskScheduler::AUGUST,
|
492
|
+
Win32::TaskScheduler::SEPTEMBER,
|
493
|
+
Win32::TaskScheduler::OCTOBER,
|
494
|
+
Win32::TaskScheduler::NOVEMBER,
|
495
|
+
Win32::TaskScheduler::DECEMBER
|
496
|
+
]
|
497
|
+
end
|
498
|
+
|
499
|
+
def scheduler_occurrences
|
500
|
+
[
|
501
|
+
Win32::TaskScheduler::FIRST_WEEK,
|
502
|
+
Win32::TaskScheduler::SECOND_WEEK,
|
503
|
+
Win32::TaskScheduler::THIRD_WEEK,
|
504
|
+
Win32::TaskScheduler::FOURTH_WEEK,
|
505
|
+
Win32::TaskScheduler::LAST_WEEK
|
506
|
+
]
|
507
|
+
end
|
508
|
+
|
509
|
+
def day_of_week_constant_to_name(constant)
|
510
|
+
case constant
|
511
|
+
when Win32::TaskScheduler::SUNDAY; 'sun'
|
512
|
+
when Win32::TaskScheduler::MONDAY; 'mon'
|
513
|
+
when Win32::TaskScheduler::TUESDAY; 'tues'
|
514
|
+
when Win32::TaskScheduler::WEDNESDAY; 'wed'
|
515
|
+
when Win32::TaskScheduler::THURSDAY; 'thurs'
|
516
|
+
when Win32::TaskScheduler::FRIDAY; 'fri'
|
517
|
+
when Win32::TaskScheduler::SATURDAY; 'sat'
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
def day_of_week_name_to_constant(name)
|
522
|
+
case name
|
523
|
+
when 'sun'; Win32::TaskScheduler::SUNDAY
|
524
|
+
when 'mon'; Win32::TaskScheduler::MONDAY
|
525
|
+
when 'tues'; Win32::TaskScheduler::TUESDAY
|
526
|
+
when 'wed'; Win32::TaskScheduler::WEDNESDAY
|
527
|
+
when 'thurs'; Win32::TaskScheduler::THURSDAY
|
528
|
+
when 'fri'; Win32::TaskScheduler::FRIDAY
|
529
|
+
when 'sat'; Win32::TaskScheduler::SATURDAY
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
def month_constant_to_number(constant)
|
534
|
+
month_num = 1
|
535
|
+
while constant >> month_num - 1 > 1
|
536
|
+
month_num += 1
|
537
|
+
end
|
538
|
+
month_num
|
539
|
+
end
|
540
|
+
|
541
|
+
def occurrence_constant_to_name(constant)
|
542
|
+
case constant
|
543
|
+
when Win32::TaskScheduler::FIRST_WEEK; 'first'
|
544
|
+
when Win32::TaskScheduler::SECOND_WEEK; 'second'
|
545
|
+
when Win32::TaskScheduler::THIRD_WEEK; 'third'
|
546
|
+
when Win32::TaskScheduler::FOURTH_WEEK; 'fourth'
|
547
|
+
when Win32::TaskScheduler::LAST_WEEK; 'last'
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
def occurrence_name_to_constant(name)
|
552
|
+
case name
|
553
|
+
when 'first'; Win32::TaskScheduler::FIRST_WEEK
|
554
|
+
when 'second'; Win32::TaskScheduler::SECOND_WEEK
|
555
|
+
when 'third'; Win32::TaskScheduler::THIRD_WEEK
|
556
|
+
when 'fourth'; Win32::TaskScheduler::FOURTH_WEEK
|
557
|
+
when 'last'; Win32::TaskScheduler::LAST_WEEK
|
558
|
+
end
|
559
|
+
end
|
560
|
+
end
|