1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
#
# Author:: Bryan McLellan <btm@loftninjas.org>
# Copyright:: Copyright (c) Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require_relative "../mixin/uris"
require_relative "package"
require_relative "../provider/package/windows"
require_relative "../win32/error" if RUBY_PLATFORM.match?(/mswin|mingw|windows/)
require "chef-utils/dist" unless defined?(ChefUtils::Dist)
class Chef
class Resource
class WindowsPackage < Chef::Resource::Package
include Chef::Mixin::Uris
unified_mode true
provides(:windows_package) { true }
provides :package, os: "windows"
description <<~DESC
Use the **windows_package** resource to manage packages on the Microsoft Windows platform.
The **windows_package** resource supports these installer formats:
* Microsoft Installer Package (MSI)
* Nullsoft Scriptable Install System (NSIS)
* Inno Setup (inno)
* Wise
* InstallShield
* Custom installers such as installing a non-.msi file that embeds an .msi-based installer
To enable idempotence of the `:install` action or to enable the `:remove` action with no source property specified,
`package_name` MUST be an exact match of the name used by the package installer. The names of installed packages
Windows knows about can be found in **Add/Remove programs**, in the output of `ohai packages`, or in the
`DisplayName` property in one of the following in the Windows registry:
* `HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall`
* `HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall`
* `HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall`
Note: If there are multiple versions of a package installed with the same display name, all of those packages will
be removed unless a version is provided in the **version** property or unless it can be discovered in the installer
file specified by the **source** property.
DESC
introduced "11.12"
examples <<~DOC
**Install a package**:
```ruby
windows_package '7zip' do
action :install
source 'C:\\7z920.msi'
end
```
**Specify a URL for the source attribute**:
```ruby
windows_package '7zip' do
source 'http://www.7-zip.org/a/7z938-x64.msi'
end
```
**Specify path and checksum**:
```ruby
windows_package '7zip' do
source 'http://www.7-zip.org/a/7z938-x64.msi'
checksum '7c8e873991c82ad9cfc123415254ea6101e9a645e12977dcd518979e50fdedf3'
end
```
**Modify remote_file resource attributes**:
The windows_package resource may specify a package at a remote location using the remote_file_attributes property. This uses the remote_file resource to download the contents at the specified URL and passes in a Hash that modifies the properties of the remote_file resource.
```ruby
windows_package '7zip' do
source 'http://www.7-zip.org/a/7z938-x64.msi'
remote_file_attributes ({
:path => 'C:\\7zip.msi',
:checksum => '7c8e873991c82ad9cfc123415254ea6101e9a645e12977dcd518979e50fdedf3'
})
end
```
**Download a nsis (Nullsoft) package resource**:
```ruby
windows_package 'Mercurial 3.6.1 (64-bit)' do
source 'http://mercurial.selenic.com/release/windows/Mercurial-3.6.1-x64.exe'
checksum 'febd29578cb6736163d232708b834a2ddd119aa40abc536b2c313fc5e1b5831d'
end
```
**Download a custom package**:
```ruby
windows_package 'Microsoft Visual C++ 2005 Redistributable' do
source 'https://download.microsoft.com/download/6/B/B/6BB661D6-A8AE-4819-B79F-236472F6070C/vcredist_x86.exe'
installer_type :custom
options '/Q'
end
```
DOC
allowed_actions :install, :remove
def initialize(name, run_context = nil)
super
@source ||= source(@package_name) if @package_name.downcase.end_with?(".msi")
end
property :package_name, String,
description: "An optional property to set the package name if it differs from the resource block's name.",
identity: true
# we don't redefine the version property as a string here since we store the current value
# of version and that may be an array if multiple versions of a package are present on the system
# windows can't take array options yet
property :options, String,
description: "One (or more) additional options that are passed to the command."
# Unique to this resource
property :installer_type, Symbol,
equal_to: %i{custom inno installshield msi nsis wise},
description: "A symbol that specifies the type of package. Possible values: :custom (such as installing a non-.msi file that embeds an .msi-based installer), :inno (Inno Setup), :installshield (InstallShield), :msi (Microsoft Installer Package (MSI)), :nsis (Nullsoft Scriptable Install System (NSIS)), :wise (Wise)."
property :timeout, [ String, Integer ], default: 600,
default_description: "600 (seconds)",
description: "The amount of time (in seconds) to wait before timing out.",
desired_state: false
# In the past we accepted return code 127 for an unknown reason and 42 because of a bug
# we accept 3010 which means success, but a reboot is necessary
property :returns, [ String, Integer, Array ], default: [ 0, 3010 ],
desired_state: false,
description: "A comma-delimited list of return codes that indicate the success or failure of the package command that was run.",
default_description: "0 (success) and 3010 (success where a reboot is necessary)"
property :source, String,
coerce: (proc do |s|
unless s.nil?
uri_scheme?(s) ? s : Chef::Util::PathHelper.canonical_path(s, false)
end
end),
default_description: "The resource block's name", # this property is basically a name_property but not really so we need to spell it out
description: "The path to a package in the local file system or the URL of a remote file that will be downloaded."
property :checksum, String,
desired_state: false, coerce: (proc { |c| c.downcase }),
description: "The SHA-256 checksum of the file. Use to prevent a file from being re-downloaded. When the local file matches the checksum, #{ChefUtils::Dist::Infra::PRODUCT} does not download it. Use when a URL is specified by the `source` property."
property :remote_file_attributes, Hash,
desired_state: false,
description: "If the source package to install is at a remote location, this property allows you to define a hash of properties which will be used by the underlying **remote_file** resource used to fetch the source."
end
end
end
|