Initial Chef repository

This commit is contained in:
Greg Karékinian
2015-07-21 19:45:23 +02:00
parent 7e5401fc71
commit ee4079fa85
1151 changed files with 185163 additions and 0 deletions

View File

@@ -0,0 +1,320 @@
windows Cookbook CHANGELOG
=======================
This file is used to list changes made in each version of the windows cookbook.
v1.36.6 (2014-12-18)
--------------------
- reverting all chef_gem compile_time work
v1.36.5 (2014-12-18)
--------------------
- Fix zipfile provider
v1.36.4 (2014-12-18)
--------------------
- Fix Chef chef_gem with Chef::Resource::ChefGem.method_defined?(:compile_time)
v1.36.3 (2014-12-18)
--------------------
- Fix Chef chef_gem below 12.1.0
v1.36.2 (2014-12-17)
--------------------
- Being explicit about usage of the chef_gem's compile_time property.
- Eliminating future deprecation warnings in Chef 12.1.0
v1.36.1 (2014-12-17)
--------------------
- [PR 160](https://github.com/chef-cookbooks/windows/pull/160) - Fix Chef 11.10 / versions without windows_package in core
v1.36.0 (2014-12-16)
--------------------
- [PR 145](https://github.com/chef-cookbooks/windows/pull/145) - do not fail on non-existant task
- [PR 144](https://github.com/chef-cookbooks/windows/pull/144) - Add a zip example to the README
- [PR 110](https://github.com/chef-cookbooks/windows/pull/110) - More zip documentation
- [PR 148](https://github.com/chef-cookbooks/windows/pull/148) - Add an LWRP for font installation
- [PR 151](https://github.com/chef-cookbooks/windows/pull/151) - Fix windows_package on Chef 12, add integration tests
- [PR 129](https://github.com/chef-cookbooks/windows/pull/129) - Add enable/disable actions to task LWRP
- [PR 115](https://github.com/chef-cookbooks/windows/pull/115) - require Chef::Mixin::PowershellOut before using it
- [PR 88](https://github.com/chef-cookbooks/windows/pull/88) - Code 1003 from servermanagercmd.exe is valid
v1.34.8 (2014-10-31)
--------------------
- [Issue 137](https://github.com/chef-cookbooks/windows/issues/137) - windows_path resource breaks with ruby 2.x
v1.34.6 (2014-09-22)
--------------------
- [Chef-2009](https://github.com/chef/chef/issues/2009) - Patch to work around a regression in [Chef](https://github.com/chef/chef)
v1.34.2 (2014-08-12)
--------------------
- [Issue 99](https://github.com/chef-cookbooks/windows/issues/99) - Remove rubygems / Internet wmi-lite dependency (PR #108)
v1.34.0 (2014-08-04)
--------------------
- [Issue 99](https://github.com/chef-cookbooks/windows/issues/99) - Use wmi-lite to fix Chef 11.14.2 break in rdp-ruby-wmi dependency
v1.32.1 (2014-07-15)
--------------------
- Fixes broken cookbook release
v1.32.0 (2014-07-11)
--------------------
- Add ChefSpec resource methods to allow notification testing (@sneal)
- Add use_inline_resources to providers (@micgo)
- [COOK-4728] - Allow reboot handler to be used as an exception handler
- [COOK-4620] - Ensure win_friendly_path doesn't error out when ALT_SEPARATOR is nil
v1.31.0 (2014-05-07)
--------------------
- [COOK-2934] - Add windows_feature support for 2 new DISM attributes: all, source
v1.30.2 (2014-04-02)
--------------------
- [COOK-4414] - Adding ChefSpec matchers
v1.30.0 (2014-02-14)
--------------------
- [COOK-3715] - Unable to create a startup task with no login
- [COOK-4188] - Add powershell_version method to return Powershell version
v1.12.8 (2014-01-21)
--------------------
- [COOK-3988] Don't unescape URI before constructing it.
v1.12.6 (2014-01-03)
--------------------
- [COOK-4168] Circular dep on powershell - moving powershell libraries into windows. removing dependency on powershell
v1.12.4
-------
Fixing depend/depends typo in metadata.rb
v1.12.2
-------
### Bug
- **[COOK-4110](https://tickets.chef.io/browse/COOK-4110)** - feature_servermanager installed? method regex bug
v1.12.0
-------
### Bug
- **[COOK-3793](https://tickets.chef.io/browse/COOK-3793)** - parens inside parens of README.md don't render
### New Feature
- **[COOK-3714](https://tickets.chef.io/browse/COOK-3714)** - Powershell features provider and delete support.
v1.11.0
-------
### Improvement
- **[COOK-3724](https://tickets.chef.io/browse/COOK-3724)** - Rrecommend built-in resources over cookbook resources
- **[COOK-3515](https://tickets.chef.io/browse/COOK-3515)** - Remove unprofessional comment from library
- **[COOK-3455](https://tickets.chef.io/browse/COOK-3455)** - Add Windows Server 2012R2 to windows cookbook version helper
### Bug
- **[COOK-3542](https://tickets.chef.io/browse/COOK-3542)** - Fix an issue where `windows_zipfile` fails with LoadError
- **[COOK-3447](https://tickets.chef.io/browse/COOK-3447)** - Allow Overriding Of The Default Reboot Timeout In windows_reboot_handler
- **[COOK-3382](https://tickets.chef.io/browse/COOK-3382)** - Allow windows_task to create `on_logon` tasks
- **[COOK-2098](https://tickets.chef.io/browse/COOK-2098)** - Fix and issue where the `windows_reboot` handler is ignoring the reboot time
### New Feature
- **[COOK-3458](https://tickets.chef.io/browse/COOK-3458)** - Add support for `start_date` and `start_time` in `windows_task`
v1.10.0
-------
### Improvement
- [COOK-3126]: `windows_task` should support the on start frequency
- [COOK-3127]: Support the force option on task create and delete
v1.9.0
------
### Bug
- [COOK-2899]: windows_feature fails when a feature install requires a
reboot
- [COOK-2914]: Foodcritic failures in Cookbooks
- [COOK-2983]: windows cookbook has foodcritic failures
### Improvement
- [COOK-2686]: Add Windows Server 2012 to version.rb so other
depending chef scripts can detect Windows Server 2012
v1.8.10
-------
When using Windows qualified filepaths (C:/foo), the #absolute? method
for URI returns true, because "C" is the scheme.
This change checks that the URI is http or https scheme, so it can be
passed off to remote_file appropriately.
* [COOK-2729] - allow only http, https URI schemes
v1.8.8
------
* [COOK-2729] - helper should use URI rather than regex and bare string
v1.8.6
------
* [COOK-968] - `windows_package` provider should gracefully handle paths with spaces
* [COOK-222] - `windows_task` resource does not declare :change action
* [COOK-241] - Windows cookbook should check for redefined constants
* [COOK-248] - Windows package install type is case sensitive
v1.8.4
------
* [COOK-2336] - MSI That requires reboot returns with RC 3010 and
causes chef run failure
* [COOK-2368] - `version` attribute of the `windows_package` provider
should be documented
v1.8.2
------
**Important**: Use powershell in nodes expanded run lists to ensure
powershell is downloaded, as powershell has a dependency on this
cookbook; v1.8.0 created a circular dependency.
* [COOK-2301] - windows 1.8.0 has circular dependency on powershell
v1.8.0
------
* [COOK-2126] - Add checksum attribute to `windows_zipfile`
* [COOK-2142] - Add printer and `printer_port` LWRPs
* [COOK-2149] - Chef::Log.debug Windows Package command line
* [COOK-2155] -`windows_package` does not send checksum to
`cached_file` in `installer_type`
v1.7.0
------
* [COOK-1745] - allow for newer versions of rubyzip
v1.6.0
------
* [COOK-2048] - undefined method for Falseclass on task :change when
action is :nothing (and task doesn't exist)
* [COOK-2049] - Add `windows_pagefile` resource
v1.5.0
------
* [COOK-1251] - Fix LWRP "NotImplementedError"
* [COOK-1921] - Task LWRP will return true for resource exists when no
other scheduled tasks exist
* [COOK-1932] - Include :change functionality to windows task lwrp
v1.4.0:
------
* [COOK-1571] - `windows_package` resource (with msi provider) does not
accept spaces in filename
* [COOK-1581] - Windows cookbook needs a scheduled tasks LWRP
* [COOK-1584] - `windows_registry` should support all registry types
v1.3.4
------
* [COOK-1173] - `windows_registry` throws Win32::Registry::Error for
action :remove on a nonexistent key
* [COOK-1182] - windows package sets start window title instead of
quoting a path
* [COOK-1476] - zipfile lwrp should support :zip action
* [COOK-1485] - package resource fails to perform install correctly
when "source" contains quote
* [COOK-1519] - add action :remove for path lwrp
v1.3.2
------
* [COOK-1033] - remove the `libraries/ruby_19_patches.rb` file which
causes havoc on non-Windows systems.
* [COOK-811] - add a timeout parameter attribute for `windows_package`
v1.3.0
------
* [COOK-1323] - Update for changes in Chef 0.10.10.
- Setting file mode doesn't make sense on Windows (package provider
- and `reboot_handler` recipe)
- Prefix ::Win32 to avoid namespace collision with Chef::Win32
- (`registry_helper` library)
- Use chef_gem instead of gem_package so gems get installed correctly
under the Ruby environment Chef runs in (reboot_handler recipe,
zipfile provider)
v1.2.12
-------
* [COOK-1037] - specify version for rubyzip gem
* [COOK-1007] - `windows_feature` does not work to remove features with
dism
* [COOK-667] - shortcut resource + provider for Windows platforms
v1.2.10
-------
* [COOK-939] - add `type` parameter to `windows_registry` to allow binary registry keys.
* [COOK-940] - refactor logic so multiple values get created.
v1.2.8
------
* FIX: Older Windows (Windows Server 2003) sometimes return 127 on successful forked commands
* FIX: `windows_package`, ensure we pass the WOW* registry redirection flags into reg.open
v1.2.6
------
* patch to fix [CHEF-2684], Open4 is named Open3 in Ruby 1.9
* Ruby 1.9's Open3 returns 0 and 42 for successful commands
* retry keyword can only be used in a rescue block in Ruby 1.9
v1.2.4
------
* `windows_package` - catch Win32::Registry::Error that pops up when searching certain keys
v1.2.2
------
* combined numerous helper libarires for easier sharing across libaries/LWRPs
* renamed Chef::Provider::WindowsFeature::Base file to the more descriptive `feature_base.rb`
* refactored `windows_path` LWRP
* :add action should MODIFY the the underlying ENV variable (vs CREATE)
* deleted greedy :remove action until it could be made more idempotent
* added a `windows_batch` resource/provider for running batch scripts remotely
v1.2.0
------
* [COOK-745] gracefully handle required server restarts on Windows platform
* WindowsRebootHandler for requested and pending reboots
* `windows_reboot` LWRP for requesting (receiving notifies) reboots
* `reboot_handler` recipe for enabling WindowsRebootHandler as a report handler
* [COOK-714] Correct initialize misspelling
* RegistryHelper - new `get_values` method which returns all values for a particular key.
v1.0.8
------
* [COOK-719] resource/provider for managing windows features
* [COOK-717] remove `windows_env_vars` resource as env resource exists in core chef
* new `Windows::Version` helper class
* refactored `Windows::Helper` mixin
v1.0.6
------
* added `force_modify` action to `windows_registry` resource
* add `win_friendly_path` helper
* re-purpose default recipe to install useful supporting windows related gems
v1.0.4
------
* [COOK-700] new resources and improvements to the `windows_registry` provider (thanks Paul Morton!)
* Open the registry in the bitednes of the OS
* Provide convenience methods to check if keys and values exit
* Provide convenience method for reading registry values
* NEW - `windows_auto_run` resource/provider
* NEW - `windows_env_vars` resource/provider
* NEW - `windows_path` resource/provider
* re-write of the `windows_package` logic for determining current installed packages
* new checksum attribute for `windows_package` resource...useful for remote packages
v1.0.2
------
* [COOK-647] account for Wow6432Node registry redirecter
* [COOK-656] begin/rescue on win32/registry
v1.0.0
------
* [COOK-612] initial release

749
cookbooks/windows/README.md Normal file
View File

@@ -0,0 +1,749 @@
Windows Cookbook
================
Provides a set of Windows-specific primitives (Chef resources) meant to aid in the creation of cookbooks/recipes targeting the Windows platform.
Requirements
-------------
Version 1.3.0+ of this cookbook requires Chef 0.10.10+.
### Platforms
* Windows XP
* Windows Vista
* Windows Server 2003 R2
* Windows 7
* Windows Server 2008 (R1, R2)
The `windows_task` LWRP requires Windows Server 2008 due to its API usage.
### Cookbooks
The following cookbooks provided by Chef Software are required as noted:
* chef_handler (`windows::reboot_handler` leverages the chef_handler LWRP)
Attributes
----------
* `node['windows']['allow_pending_reboots']` - used to configure the `WindowsRebootHandler` (via the `windows::reboot_handler` recipe) to act on pending reboots. default is true (ie act on pending reboots). The value of this attribute only has an effect if the `windows::reboot_handler` is in a node's run list.
* `node['windows']['allow_reboot_on_failure']` - used to register the `WindowsRebootHandler` (via the `windows::reboot_handler` recipe) as an exception handler too to act on reboots not only at the end of successful Chef runs, but even at the end of failed runs. default is false (ie reboot only after successful runs). The value of this attribute only has an effect if the `windows::reboot_handler` is in a node's run list.
Resource/Provider
-----------------
### windows_auto_run
#### Actions
- :create: Create an item to be run at login
- :remove: Remove an item that was previously setup to run at login
#### Attribute Parameters
- :name: Name attribute. The name of the value to be stored in the registry
- :program: The program to be run at login
- :args: The arguments for the program
#### Examples
Run BGInfo at login
```ruby
windows_auto_run 'BGINFO' do
program 'C:/Sysinternals/bginfo.exe'
args '\'C:/Sysinternals/Config.bgi\' /NOLICPROMPT /TIMER:0'
not_if { Registry.value_exists?(AUTO_RUN_KEY, 'BGINFO') }
action :create
end
```
### windows_batch
(Chef 11.6.0 includes a built-in [batch](http://docs.chef.io/resource_batch.html) resource, so use that in preference to `windows_batch` if possible.)
Execute a batch script using the cmd.exe interpreter (much like the script resources for bash, csh, powershell, perl, python and ruby). A temporary file is created and executed like other script resources, rather than run inline. By their nature, Script resources are not idempotent, as they are completely up to the user's imagination. Use the `not_if` or `only_if` meta parameters to guard the resource for idempotence.
#### Actions
- :run: run the batch file
#### Attribute Parameters
- command: name attribute. Name of the command to execute.
- code: quoted string of code to execute.
- creates: a file this command creates - if the file exists, the command will not be run.
- cwd: current working directory to run the command from.
- flags: command line flags to pass to the interpreter when invoking.
- user: A user name or user ID that we should change to before running this command.
- group: A group name or group ID that we should change to before running this command.
#### Examples
```ruby
windows_batch 'unzip_and_move_ruby' do
code <<-EOH
7z.exe x #{Chef::Config[:file_cache_path]}/ruby-1.8.7-p352-i386-mingw32.7z -oC:\\source -r -y
xcopy C:\\source\\ruby-1.8.7-p352-i386-mingw32 C:\\ruby /e /y
EOH
end
```
```ruby
windows_batch 'echo some env vars' do
code <<-EOH
echo %TEMP%
echo %SYSTEMDRIVE%
echo %PATH%
echo %WINDIR%
EOH
end
```
### windows_feature
Windows Roles and Features can be thought of as built-in operating system packages that ship with the OS. A server role is a set of software programs that, when they are installed and properly configured, lets a computer perform a specific function for multiple users or other computers within a network. A Role can have multiple Role Services that provide functionality to the Role. Role services are software programs that provide the functionality of a role. Features are software programs that, although they are not directly parts of roles, can support or augment the functionality of one or more roles, or improve the functionality of the server, regardless of which roles are installed. Collectively we refer to all of these attributes as 'features'.
This resource allows you to manage these 'features' in an unattended, idempotent way.
There are two providers for the `windows_features` which map into Microsoft's two major tools for managing roles/features: [Deployment Image Servicing and Management (DISM)](http://msdn.microsoft.com/en-us/library/dd371719%28v=vs.85%29.aspx) and [Servermanagercmd](http://technet.microsoft.com/en-us/library/ee344834%28WS.10%29.aspx) (The CLI for Server Manager). As Servermanagercmd is deprecated, Chef will set the default provider to `Chef::Provider::WindowsFeature::DISM` if DISM is present on the system being configured. The default provider will fall back to `Chef::Provider::WindowsFeature::ServerManagerCmd`.
For more information on Roles, Role Services and Features see the [Microsoft TechNet article on the topic](http://technet.microsoft.com/en-us/library/cc754923.aspx). For a complete list of all features that are available on a node type either of the following commands at a command prompt:
```text
dism /online /Get-Features
servermanagercmd -query
```
#### Actions
- :install: install a Windows role/feature
- :remove: remove a Windows role/feature
#### Attribute Parameters
- feature_name: name of the feature/role to install. The same feature may have different names depending on the provider used (ie DHCPServer vs DHCP; DNS-Server-Full-Role vs DNS).
- all: Boolean. Optional. Default: false. DISM provider only. Forces all dependencies to be installed.
- source: String. Optional. DISM provider only. Uses local repository for feature install.
#### Providers
- **Chef::Provider::WindowsFeature::DISM**: Uses Deployment Image Servicing and Management (DISM) to manage roles/features.
- **Chef::Provider::WindowsFeature::ServerManagerCmd**: Uses Server Manager to manage roles/features.
- **Chef::Provider::WindowsFeaturePowershell**: Uses Powershell to manage roles/features. (see [COOK-3714](https://tickets.chef.io/browse/COOK-3714)
#### Examples
Enable the node as a DHCP Server
```ruby
windows_feature 'DHCPServer' do
action :install
end
```
Enable TFTP
```ruby
windows_feature 'TFTP' do
action :install
end
```
Enable .Net 3.5.1 on Server 2012 using repository files on DVD and
install all dependencies
```ruby
windows_feature "NetFx3" do
action :install
all true
source "d:\sources\sxs"
end
```
Disable Telnet client/server
```ruby
%w[TelnetServer TelnetClient].each do |feature|
windows_feature feature do
action :remove
end
end
```
### windows_font
Installs a font.
Font files should be included in the cookbooks
#### Actions
- :install: install a font to the system fonts directory.
#### Attribute Parameters
- file: The name of the font file name to install. It should exist in the files/default directory of the cookbook you're calling windows_font from. Defaults to the resource name.
#### Examples
```ruby
windows_font 'Code New Roman.otf'
```
### windows_package
Manage Windows application packages in an unattended, idempotent way.
The following application installers are currently supported:
* MSI packages
* InstallShield
* Wise InstallMaster
* Inno Setup
* Nullsoft Scriptable Install System
If the proper installer type is not passed into the resource's installer_type attribute, the provider will do it's best to identify the type by introspecting the installation package. If the installation type cannot be properly identified the `:custom` value can be passed into the installer_type attribute along with the proper flags for silent/quiet installation (using the `options` attribute..see example below).
__PLEASE NOTE__ - For proper idempotence the resource's `package_name` should be the same as the 'DisplayName' registry value in the uninstallation data that is created during package installation. The easiest way to definitively find the proper 'DisplayName' value is to install the package on a machine and search for the uninstall information under the following registry keys:
* `HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall`
* `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall`
* `HKEY_LOCAL_MACHINE\Software\Wow6464Node\Microsoft\Windows\CurrentVersion\Uninstall`
For maximum flexibility the `source` attribute supports both remote and local installation packages.
#### Actions
- :install: install a package
- :remove: remove a package. The remove action is completely hit or miss as many application uninstallers do not support a full silent/quiet mode.
#### Attribute Parameters
- package_name: name attribute. The 'DisplayName' of the application installation package.
- source: The source of the windows installer. This can either be a URI or a local path.
- installer_type: They type of windows installation package. valid values are: :msi, :inno, :nsis, :wise, :installshield, :custom. If this value is not provided, the provider will do it's best to identify the installer type through introspection of the file.
- checksum: useful if source is remote, the SHA-256 checksum of the file--if the local file matches the checksum, Chef will not download it
- options: Additional options to pass the underlying installation command
- timeout: set a timeout for the package download (default 600 seconds)
- version: The version number of this package, as indicated by the 'DisplayVersion' value in one of the 'Uninstall' registry keys. If the given version number does equal the 'DisplayVersion' in the registry, the package will be installed.
- success_codes: set an array of possible successful installation
return codes. Previously this was hardcoded, but certain MSIs may
have a different return code, e.g. 3010 for reboot required. Must be
an array, and defaults to `[0, 42, 127]`.
#### Examples
Install PuTTY (InnoSetup installer)
```ruby
windows_package 'PuTTY version 0.60' do
source 'http://the.earth.li/~sgtatham/putty/latest/x86/putty-0.60-installer.exe'
installer_type :inno
action :install
end
```
Install 7-Zip (MSI installer)
```ruby
windows_package '7-Zip 9.20 (x64 edition)' do
source 'http://downloads.sourceforge.net/sevenzip/7z920-x64.msi'
action :install
end
```
Install Notepad++ (Y U No Emacs?) using a local installer
```ruby
windows_package 'Notepad++' do
source 'c:/installation_files/npp.5.9.2.Installer.exe'
action :install
end
```
Install VLC for that Xvid (NSIS installer)
```ruby
windows_package 'VLC media player 1.1.10' do
source 'http://superb-sea2.dl.sourceforge.net/project/vlc/1.1.10/win32/vlc-1.1.10-win32.exe'
action :install
end
```
Install Firefox as custom installer and manually set the silent install flags
```ruby
windows_package 'Mozilla Firefox 5.0 (x86 en-US)' do
source 'http://archive.mozilla.org/pub/mozilla.org/mozilla.org/firefox/releases/5.0/win32/en-US/Firefox%20Setup%205.0.exe'
options '-ms'
installer_type :custom
action :install
end
```
Google Chrome FTW (MSI installer)
```ruby
windows_package 'Google Chrome' do
source 'https://dl-ssl.google.com/tag/s/appguid%3D%7B8A69D345-D564-463C-AFF1-A69D9E530F96%7D%26iid%3D%7B806F36C0-CB54-4A84-A3F3-0CF8A86575E0%7D%26lang%3Den%26browser%3D3%26usagestats%3D0%26appname%3DGoogle%2520Chrome%26needsadmin%3Dfalse/edgedl/chrome/install/GoogleChromeStandaloneEnterprise.msi'
action :install
end
```
Remove Google Chrome
```ruby
windows_package 'Google Chrome' do
action :remove
end
```
Remove 7-Zip
```ruby
windows_package '7-Zip 9.20 (x64 edition)' do
action :remove
end
```
### windows_printer_port
Create and delete TCP/IPv4 printer ports.
#### Actions
- :create: Create a TCIP/IPv4 printer port. This is the default action.
- :delete: Delete a TCIP/IPv4 printer port
#### Attribute Parameters
- :ipv4_address: Name attribute. Required. IPv4 address, e.g. '10.0.24.34'
- :port_name: Port name. Optional. Defaults to 'IP_' + :ipv4_address
- :port_number: Port number. Optional. Defaults to 9100.
- :port_description: Port description. Optional.
- :snmp_enabled: Boolean. Optional. Defaults to false.
- :port_protocol: Port protocol, 1 (RAW), or 2 (LPR). Optional. Defaults to 1.
#### Examples
Create a TCP/IP printer port named 'IP_10.4.64.37' with all defaults
```ruby
windows_printer_port '10.4.64.37' do
end
```
Delete a printer port
```ruby
windows_printer_port '10.4.64.37' do
action :delete
end
```
Delete a port with a custom port_name
```ruby
windows_printer_port '10.4.64.38' do
port_name 'My awesome port'
action :delete
end
```
Create a port with more options
```ruby
windows_printer_port '10.4.64.39' do
port_name 'My awesome port'
snmp_enabled true
port_protocol 2
end
```
### windows_printer
Create Windows printer. Note that this doesn't currently install a printer
driver. You must already have the driver installed on the system.
The Windows Printer LWRP will automatically create a TCP/IP printer port for you using the `ipv4_address` property. If you want more granular control over the printer port, just create it using the `windows_printer_port` LWRP before creating the printer.
#### Actions
- :create: Create a new printer
- :delete: Delete a new printer
#### Attribute Parameters
- :device_id: Name attribute. Required. Printer queue name, e.g. 'HP LJ 5200 in fifth floor copy room'
- :comment: Optional string describing the printer queue.
- :default: Boolean. Optional. Defaults to false. Note that Windows sets the first printer defined to the default printer regardless of this setting.
- :driver_name: String. Required. Exact name of printer driver. Note that the printer driver must already be installed on the node.
- :location: Printer location, e.g. 'Fifth floor copy room', or 'US/NYC/Floor42/Room4207'
- :shared: Boolean. Defaults to false.
- :share_name: Printer share name.
- :ipv4_address: Printer IPv4 address, e.g. '10.4.64.23'. You don't have to be able to ping the IP addresss to set it. Required.
An error of "Set-WmiInstance : Generic failure" is most likely due to the printer driver name not matching or not being installed.
#### Examples
Create a printer
```ruby
windows_printer 'HP LaserJet 5th Floor' do
driver_name 'HP LaserJet 4100 Series PCL6'
ipv4_address '10.4.64.38'
end
```
Delete a printer. Note: this doesn't delete the associated printer port. See `windows_printer_port` above for how to delete the port.
```ruby
windows_printer 'HP LaserJet 5th Floor' do
action :delete
end
```
### windows_reboot
Sets required data in the node's run_state to notify `WindowsRebootHandler` a reboot is requested. If Chef run completes successfully a reboot will occur if the `WindowsRebootHandler` is properly registered as a report handler. As an action of `:request` will cause a node to reboot every Chef run, this resource is usually notified by other resources...ie restart node after a package is installed (see example below).
#### Actions
- :request: requests a reboot at completion of successful Cher run. requires `WindowsRebootHandler` to be registered as a report handler.
- :cancel: remove reboot request from node.run_state. this will cancel *ALL* previously requested reboots as this is a binary state.
#### Attribute Parameters
- :timeout: Name attribute. timeout delay in seconds to wait before proceeding with the requested reboot. default is 60 seconds
- :reason: comment on the reason for the reboot. default is 'Chef Software Chef initiated reboot'
#### Examples
If the package installs, schedule a reboot at end of chef run
```ruby
windows_reboot 60 do
reason 'cause chef said so'
action :nothing
end
windows_package 'some_package' do
action :install
notifies :request, 'windows_reboot[60]'
end
```
Cancel the previously requested reboot
```ruby
windows_reboot 60 do
action :cancel
end
```
### windows_registry
(Chef 11.6.0 includes a built-in [registry_key](http://docs.chef.io/resource_registry_key.html) resource, so use that in preference to `windows_registry` if possible.)
Creates and modifies Windows registry keys.
*Change in v1.3.0: The Win32 classes use `::Win32` to avoid namespace conflict with `Chef::Win32` (introduced in Chef 0.10.10).*
#### Actions
- :create: create a new registry key with the provided values.
- :modify: modify an existing registry key with the provided values.
- :force_modify: modify an existing registry key with the provided values. ensures the value is actually set by checking multiple times. useful for fighting race conditions where two processes are trying to set the same registry key. This will be updated in the near future to use 'RegNotifyChangeKeyValue' which is exposed by the WinAPI and allows a process to register for notification on a registry key change.
- :remove: removes a value from an existing registry key
#### Attribute Parameters
- key_name: name attribute. The registry key to create/modify.
- values: hash of the values to set under the registry key. The individual hash items will become respective 'Value name' => 'Value data' items in the registry key.
- type: Type of key to create, defaults to REG_SZ. Must be a symbol, see the overview below for valid values.
#### Registry key types
- :binary: REG_BINARY
- :string: REG_SZ
- :multi_string: REG_MULTI_SZ
- :expand_string: REG_EXPAND_SZ
- :dword: REG_DWORD
- :dword_big_endian: REG_DWORD_BIG_ENDIAN
- :qword: REG_QWORD
#### Examples
Make the local windows proxy match the one set for Chef
```ruby
proxy = URI.parse(Chef::Config[:http_proxy])
windows_registry 'HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings' do
values 'ProxyEnable' => 1, 'ProxyServer' => "#{proxy.host}:#{proxy.port}", 'ProxyOverride' => '<local>'
end
```
Enable Remote Desktop and poke the firewall hole
```ruby
windows_registry 'HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server' do
values 'FdenyTSConnections' => 0
end
```
Delete an item from the registry
```ruby
windows_registry 'HKCU\Software\Test' do
#Key is the name of the value that you want to delete the value is always empty
values 'ValueToDelete' => ''
action :remove
end
```
Add a REG_MULTI_SZ value to the registry
```ruby
windows_registry 'HKCU\Software\Test' do
values 'MultiString' => ['line 1', 'line 2', 'line 3']
type :multi_string
end
```
#### Library Methods
```ruby
Registry.value_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run','BGINFO')
Registry.key_exists?('HKLM\SOFTWARE\Microsoft')
BgInfo = Registry.get_value('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run','BGINFO')
```
### windows_path
#### Actions
- :add: Add an item to the system path
- :remove: Remove an item from the system path
#### Attribute Parameters
- :path: Name attribute. The name of the value to add to the system path
#### Examples
Add Sysinternals to the system path
```ruby
windows_path 'C:\Sysinternals' do
action :add
end
```
Remove 7-Zip from the system path
```ruby
windows_path 'C:\7-Zip' do
action :remove
end
```
### windows_task
Creates, deletes or runs a Windows scheduled task. Requires Windows
Server 2008 due to API usage.
#### Actions
- :create: creates a task
- :delete: deletes a task
- :run: runs a task
- :change: changes the un/pw or command of a task
- :enable: enable a task
- :disable: disable a task
#### Attribute Parameters
- name: name attribute, The task name.
- command: The command the task will run.
- cwd: The directory the task will be run from.
- user: The user to run the task as. (requires password)
- password: The user's password. (requires user)
- run_level: Run with limited or highest privileges.
- frequency: Frequency with which to run the task. (hourly, daily, ect.)
- frequency_modifier: Multiple for frequency. (15 minutes, 2 days)
- start_day: Specifies the first date on which the task runs. Optional string (MM/DD/YYYY)
- start_time: Specifies the start time to run the task. Optional string (HH:mm)
#### Examples
Run Chef every 15 minutes
```ruby
windows_task 'Chef client' do
user 'Administrator'
password '$ecR3t'
cwd 'C:\chef\bin'
command 'chef-client -L C:\tmp\'
run_level :highest
frequency :minute
frequency_modifier 15
end
```
Update Chef Client task with new password and log location
```ruby
windows_task 'Chef client' do
user 'Administrator'
password 'N3wPassW0Rd'
cwd 'C:\chef\bin'
command 'chef-client -L C:\chef\logs\'
action :change
end
```
Delete a taks named 'old task'
```ruby
windows_task 'old task' do
action :delete
end
```
Enable a task named 'Chef client'
```ruby
windows_task 'Chef client' do
action :enable
end
```
Disable a task named 'Chef client'
```ruby
windows_task 'Chef client' do
action :disable
end
```
### windows_zipfile
Most version of Windows do not ship with native cli utility for managing compressed files. This resource provides a pure-ruby implementation for managing zip files. Be sure to use the `not_if` or `only_if` meta parameters to guard the resource for idempotence or action will be taken every Chef run.
#### Actions
- :unzip: unzip a compressed file
- :zip: zip a directory (recursively)
#### Attribute Parameters
- path: name attribute. The path where files will be (un)zipped to.
- source: source of the zip file (either a URI or local path) for :unzip, or directory to be zipped for :zip.
- overwrite: force an overwrite of the files if they already exist.
- checksum: for :unzip, useful if source is remote, if the local file matches the SHA-256 checksum, Chef will not download it.
#### Examples
Unzip a remote zip file locally
```ruby
windows_zipfile 'c:/bin' do
source 'http://download.sysinternals.com/Files/SysinternalsSuite.zip'
action :unzip
not_if {::File.exists?('c:/bin/PsExec.exe')}
end
```
Unzip a local zipfile
```ruby
windows_zipfile 'c:/the_codez' do
source 'c:/foo/baz/the_codez.zip'
action :unzip
end
```
Create a local zipfile
```ruby
windows_zipfile 'c:/foo/baz/the_codez.zip' do
source 'c:/the_codez'
action :zip
end
```
Libraries
-------------------------
### WindowsHelper
Helper that allows you to use helpful functions in windows
#### installed_packages
Returns a hash of all DisplayNames installed
```ruby
# usage in a recipe
::Chef::Recipe.send(:include, Windows::Helper)
hash_of_installed_packages = installed_packages
```
#### is_package_installed?
- `package_name`: The name of the package you want to query to see if it is installed
- `returns`: true if the package is installed, false if it the package is not installed
Download a file if a package isn't installed
```ruby
# usage in a recipe to not download a file if package is already installed
::Chef::Recipe.send(:include, Windows::Helper)
is_win_sdk_installed = is_package_installed?('Windows Software Development Kit')
remote_file 'C:\windows\temp\windows_sdk.zip' do
source 'http://url_to_download/windows_sdk.zip'
action :create_if_missing
not_if {is_win_sdk_installed}
end
```
Do something if a package is installed
```ruby
# usage in a provider
include Windows::Helper
if is_package_installed?('Windows Software Development Kit')
# do something if package is installed
end
```
Exception/Report Handlers
-------------------------
### WindowsRebootHandler
Required reboots are a necessary evil of configuring and managing Windows nodes. This report handler (ie fires at the end of Chef runs) acts on requested (Chef initiated) or pending (as determined by the OS per configuration action we performed) reboots. The `allow_pending_reboots` initialization argument should be set to false if you do not want the handler to automatically reboot a node if it has been determined a reboot is pending. Reboots can still be requested explicitly via the `windows_reboot` LWRP.
### Initialization Arguments
- `allow_pending_reboots`: indicator on whether the handler should act on a the Window's 'pending reboot' state. default is true
- `timeout`: timeout delay in seconds to wait before proceeding with the reboot. default is 60 seconds
- `reason`: comment on the reason for the reboot. default is 'Chef Software Chef initiated reboot'
Windows ChefSpec Matchers
-------------------------
The Windows cookbook includes custom [ChefSpec](https://github.com/sethvargo/chefspec) matchers you can use to test your own cookbooks that consume Windows cookbook LWRPs.
###Example Matcher Usage
```ruby
expect(chef_run).to install_windows_package('Node.js').with(
source: 'http://nodejs.org/dist/v0.10.26/x64/node-v0.10.26-x64.msi')
```
###Windows Cookbook Matchers
* install_windows_package
* remove_windows_package
* install_windows_feature
* remove_windows_feature
* delete_windows_feature
* create_windows_task
* delete_windows_task
* run_windows_task
* change_windows_task
* add_windows_path
* remove_windows_path
* run_windows_batch
* set_windows_pagefile
* unzip_windows_zipfile_to
* zip_windows_zipfile_to
* create_windows_shortcut
* create_windows_auto_run
* remove_windows_auto_run
* create_windows_printer
* delete_windows_printer
* create_windows_printer_port
* delete_windows_printer_port
* request_windows_reboot
* cancel_windows_reboot
* create_windows_shortcut
Usage
-----
Place an explicit dependency on this cookbook (using depends in the cookbook's metadata.rb) from any cookbook where you would like to use the Windows-specific resources/providers that ship with this cookbook.
```ruby
depends 'windows'
```
### default
Convenience recipe that installs supporting gems for many of the resources/providers that ship with this cookbook.
*Change in v1.3.0: Uses chef_gem instead of gem_package to ensure gem installation in Chef 0.10.10.*
### reboot_handler
Leverages the `chef_handler` LWRP to register the `WindowsRebootHandler` report handler that ships as part of this cookbook. By default this handler is set to automatically act on pending reboots. If you would like to change this behavior override `node['windows']['allow_pending_reboots']` and set the value to false. For example:
```ruby
name 'base'
description 'base role'
override_attributes(
'windows' => {
'allow_pending_reboots' => false
}
)
```
This will still allow a reboot to be explicitly requested via the `windows_reboot` LWRP.
By default, the handler will only be registered as a report handler, meaning that it will only fire at the end of successful Chef runs. If the run fails, pending or requested reboots will be ignored. This can lead to a situation where some package was installed and notified a reboot request via the `windows_reboot` LWRP, and then the run fails for some unrelated reason, and the reboot request gets dropped because the resource that notified the reboot request will already be up-to-date at the next run and will not request a reboot again, and thus the requested reboot will never be performed. To change this behavior and register the handler as an exception handler that fires at the end of failed runs too, override `node['windows']['allow_reboot_on_failure']` and set the value to true.
License & Authors
-----------------
- Author:: Seth Chisamore (<schisamo@chef.io>)
- Author:: Doug MacEachern (<dougm@vmware.com>)
- Author:: Paul Morton (<pmorton@biaprotect.com>)
- Author:: Doug Ireton (<doug.ireton@nordstrom.com>)
```text
Copyright 2011-2013, Chef Software, Inc.
Copyright 2010, VMware, Inc.
Copyright 2011, Business Intelligence Associates, Inc
Copyright 2012, Nordstrom, Inc.
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.
```

View File

@@ -0,0 +1,24 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Attribute:: default
#
# Copyright 2011, Chef Software, Inc
#
# 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.
#
default['windows']['allow_pending_reboots'] = true
default['windows']['allow_reboot_on_failure'] = false
default['windows']['rubyzipversion'] = nil
default['windows']['reboot_timeout'] = 60

View File

@@ -0,0 +1,76 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Copyright:: Copyright (c) 2011 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.
#
class WindowsRebootHandler < Chef::Handler
include Chef::Mixin::ShellOut
def initialize(allow_pending_reboots = true, timeout = 60, reason = "Chef Software Chef initiated reboot")
@allow_pending_reboots = allow_pending_reboots
@timeout = timeout
@reason = reason
end
def report
log_message, reboot = begin
if reboot_requested?
["chef_handler[#{self.class}] requested reboot will occur in #{timeout} seconds", true]
elsif reboot_pending?
if @allow_pending_reboots
["chef_handler[#{self.class}] reboot pending - automatic reboot will occur in #{timeout} seconds", true]
else
["chef_handler[#{self.class}] reboot pending but handler not configured to act on pending reboots - please reboot node manually", false]
end
else
["chef_handler[#{self.class}] no reboot requested or pending", false]
end
end
Chef::Log.warn(log_message)
shell_out!("shutdown /r /t #{timeout} /c \"#{reason}\"") if reboot
end
private
# reboot cause CHEF says so:
# reboot explicitly requested in our cookbook code
def reboot_requested?
node.run_state[:reboot_requested] == true
end
# reboot cause WIN says so:
# reboot pending because of some configuration action we performed
def reboot_pending?
# Any files listed here means reboot needed
(Registry.key_exists?('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations') &&
Registry.get_value('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager','PendingFileRenameOperations').any?) ||
# 1 for any value means reboot pending
# "9306cdfc-c4a1-4a22-9996-848cb67eddc3"=1
(Registry.key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired') &&
Registry.get_values('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired').select{|v| v[2] == 1 }.any?) ||
# 1 or 2 for 'Flags' value means reboot pending
(Registry.key_exists?('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile') &&
[1,2].include?(Registry::get_value('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile','Flags')))
end
def timeout
node.run_state[:reboot_timeout] || node['windows']['reboot_timeout'] || @timeout
end
def reason
node.run_state[:reboot_reason] || @reason
end
end

View File

@@ -0,0 +1,59 @@
class Chef
class Provider
class WindowsFeature
module Base
def action_install
unless installed?
install_feature(@new_resource.feature_name)
@new_resource.updated_by_last_action(true)
Chef::Log.info("#{@new_resource} installed feature")
else
Chef::Log.debug("#{@new_resource} is already installed - nothing to do")
end
end
def action_remove
if installed?
remove_feature(@new_resource.feature_name)
@new_resource.updated_by_last_action(true)
Chef::Log.info("#{@new_resource} removed")
else
Chef::Log.debug("#{@new_resource} feature does not exist - nothing to do")
end
end
def action_delete
if available?
delete_feature(@new_resource.feature_name)
@new_resource.updated_by_last_action(true)
Chef::Log.info("#{@new_resource} deleted")
else
Chef::Log.debug("#{@new_resource} feature is not installed - nothing to do")
end
end
def install_feature(name)
raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :install"
end
def remove_feature(name)
raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :remove"
end
def delete_feature(name)
raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :delete"
end
def installed?
raise Chef::Exceptions::Override, "You must override installed? in #{self.to_s}"
end
def available?
raise Chef::Exceptions::Override, "You must override available? in #{self.to_s}"
end
end
end
end
end

View File

@@ -0,0 +1,465 @@
if defined?(ChefSpec)
chefspec_version = Gem.loaded_specs["chefspec"].version
if chefspec_version < Gem::Version.new('4.1.0')
define_method = ChefSpec::Runner.method(:define_runner_method)
else
define_method = ChefSpec.method(:define_matcher)
end
define_method.call :windows_package
define_method.call :windows_feature
define_method.call :windows_task
define_method.call :windows_path
define_method.call :windows_batch
define_method.call :windows_pagefile
define_method.call :windows_zipfile
define_method.call :windows_shortcut
define_method.call :windows_auto_run
define_method.call :windows_printer
define_method.call :windows_printer_port
define_method.call :windows_reboot
#
# Assert that a +windows_package+ resource exists in the Chef run with the
# action +:install+. Given a Chef Recipe that installs "Node.js" as a
# +windows_package+:
#
# windows_package 'Node.js' do
# source 'http://nodejs.org/dist/v0.10.26/x64/node-v0.10.26-x64.msi'
# action :install
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_package+ resource with ChefSpec.
#
# @example Assert that a +windows_package+ was installed
# expect(chef_run).to install_windows_package('Node.js')
#
# @example Assert that a +windows_package+ was _not_ installed
# expect(chef_run).to_not install_windows_package('7-zip')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def install_windows_package(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_package, :install, resource_name)
end
#
# Assert that a +windows_package+ resource exists in the Chef run with the
# action +:remove+. Given a Chef Recipe that removes "Node.js" as a
# +windows_package+:
#
# windows_package 'Node.js' do
# action :remove
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_package+ resource with ChefSpec.
#
# @example Assert that a +windows_package+ was installed
# expect(chef_run).to remove_windows_package('Node.js')
#
# @example Assert that a +windows_package+ was _not_ removed
# expect(chef_run).to_not remove_windows_package('7-zip')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def remove_windows_package(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_package, :remove, resource_name)
end
#
# Assert that a +windows_feature+ resource exists in the Chef run with the
# action +:install+. Given a Chef Recipe that installs "NetFX3" as a
# +windows_feature+:
#
# windows_feature 'NetFX3' do
# action :install
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_feature+ resource with ChefSpec.
#
# @example Assert that a +windows_feature+ was installed
# expect(chef_run).to install_windows_feature('NetFX3')
#
# @example Assert that a +windows_feature+ was _not_ installed
# expect(chef_run).to_not install_windows_feature('NetFX3')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def install_windows_feature(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_feature, :install, resource_name)
end
#
# Assert that a +windows_feature+ resource exists in the Chef run with the
# action +:remove+. Given a Chef Recipe that removes "NetFX3" as a
# +windows_feature+:
#
# windows_feature 'NetFX3' do
# action :remove
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_feature+ resource with ChefSpec.
#
# @example Assert that a +windows_feature+ was removed
# expect(chef_run).to remove_windows_feature('NetFX3')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def remove_windows_feature(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_feature, :remove, resource_name)
end
#
# Assert that a +windows_feature+ resource exists in the Chef run with the
# action +:delete+. Given a Chef Recipe that deletes "NetFX3" as a
# +windows_feature+:
#
# windows_feature 'NetFX3' do
# action :delete
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_feature+ resource with ChefSpec.
#
# @example Assert that a +windows_feature+ was deleted
# expect(chef_run).to delete_windows_feature('NetFX3')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def delete_windows_feature(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_feature, :delete, resource_name)
end
#
# Assert that a +windows_task+ resource exists in the Chef run with the
# action +:create+. Given a Chef Recipe that creates "mytask" as a
# +windows_task+:
#
# windows_task 'mytask' do
# command 'mybatch.bat'
# action :create
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_task+ resource with ChefSpec.
#
# @example Assert that a +windows_task+ was created
# expect(chef_run).to create_windows_task('mytask')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def create_windows_task(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :create, resource_name)
end
#
# Assert that a +windows_task+ resource exists in the Chef run with the
# action +:delete+. Given a Chef Recipe that deletes "mytask" as a
# +windows_task+:
#
# windows_task 'mytask' do
# action :delete
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_task+ resource with ChefSpec.
#
# @example Assert that a +windows_task+ was deleted
# expect(chef_run).to delete_windows_task('mytask')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def delete_windows_task(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :delete, resource_name)
end
#
# Assert that a +windows_task+ resource exists in the Chef run with the
# action +:run+. Given a Chef Recipe that runs "mytask" as a
# +windows_task+:
#
# windows_task 'mytask' do
# action :run
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_task+ resource with ChefSpec.
#
# @example Assert that a +windows_task+ was run
# expect(chef_run).to run_windows_task('mytask')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def run_windows_task(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :run, resource_name)
end
#
# Assert that a +windows_task+ resource exists in the Chef run with the
# action +:change+. Given a Chef Recipe that changes "mytask" as a
# +windows_task+:
#
# windows_task 'mytask' do
# action :change
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_task+ resource with ChefSpec.
#
# @example Assert that a +windows_task+ was changed
# expect(chef_run).to change_windows_task('mytask')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def change_windows_task(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_task, :change, resource_name)
end
#
# Assert that a +windows_path+ resource exists in the Chef run with the
# action +:add+. Given a Chef Recipe that adds "C:\7-Zip" to the Windows
# PATH env var
#
# windows_path 'C:\7-Zip' do
# action :add
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_path+ resource with ChefSpec.
#
# @example Assert that a +windows_path+ was added
# expect(chef_run).to add_windows_path('C:\7-Zip')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def add_windows_path(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_path, :add, resource_name)
end
#
# Assert that a +windows_path+ resource exists in the Chef run with the
# action +:remove+. Given a Chef Recipe that removes "C:\7-Zip" from the
# Windows PATH env var
#
# windows_path 'C:\7-Zip' do
# action :remove
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_path+ resource with ChefSpec.
#
# @example Assert that a +windows_path+ was removed
# expect(chef_run).to remove_windows_path('C:\7-Zip')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def remove_windows_path(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_path, :remove, resource_name)
end
#
# Assert that a +windows_batch+ resource exists in the Chef run with the
# action +:run+. Given a Chef Recipe that runs a batch script
#
# windows_batch "unzip_and_move_ruby" do
# code <<-EOH
# 7z.exe x #{Chef::Config[:file_cache_path]}/ruby-1.8.7-p352-i386-mingw32.7z
# -oC:\\source -r -y
# xcopy C:\\source\\ruby-1.8.7-p352-i386-mingw32 C:\\ruby /e /y
# EOH
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_path+ resource with ChefSpec.
#
# @example Assert that a +windows_path+ was removed
# expect(chef_run).to run_windows_batch('unzip_and_move_ruby')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def run_windows_batch(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_batch, :run, resource_name)
end
#
# Assert that a +windows_pagefile+ resource exists in the Chef run with the
# action +:set+. Given a Chef Recipe that sets a pagefile
#
# windows_pagefile "pagefile" do
# system_managed true
# initial_size 1024
# maximum_size 4096
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_pagefile+ resource with ChefSpec.
#
# @example Assert that a +windows_pagefile+ was set
# expect(chef_run).to set_windows_pagefile('pagefile').with(
# initial_size: 1024)
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def set_windows_pagefile(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_pagefile, :set, resource_name)
end
#
# Assert that a +windows_zipfile+ resource exists in the Chef run with the
# action +:unzip+. Given a Chef Recipe that extracts "SysinternalsSuite.zip"
# to c:/bin
#
# windows_zipfile "c:/bin" do
# source "http://download.sysinternals.com/Files/SysinternalsSuite.zip"
# action :unzip
# not_if {::File.exists?("c:/bin/PsExec.exe")}
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_zipfile+ resource with ChefSpec.
#
# @example Assert that a +windows_zipfile+ was unzipped
# expect(chef_run).to unzip_windows_zipfile_to('c:/bin')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def unzip_windows_zipfile_to(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_zipfile, :unzip, resource_name)
end
#
# Assert that a +windows_zipfile+ resource exists in the Chef run with the
# action +:zip+. Given a Chef Recipe that zips "c:/src"
# to c:/code.zip
#
# windows_zipfile "c:/code.zip" do
# source "c:/src"
# action :zip
# end
#
# The Examples section demonstrates the different ways to test a
# +windows_zipfile+ resource with ChefSpec.
#
# @example Assert that a +windows_zipfile+ was zipped
# expect(chef_run).to zip_windows_zipfile_to('c:/code.zip')
#
#
# @param [String, Regex] resource_name
# the name of the resource to match
#
# @return [ChefSpec::Matchers::ResourceMatcher]
#
def zip_windows_zipfile_to(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_zipfile, :zip, resource_name)
end
# All the other less commonly used LWRPs
def create_windows_shortcut(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_shortcut, :create, resource_name)
end
def create_windows_auto_run(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_auto_run, :create, resource_name)
end
def remove_windows_auto_run(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_auto_run, :remove, resource_name)
end
def create_windows_printer(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_printer, :create, resource_name)
end
def delete_windows_printer(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_printer, :delete, resource_name)
end
def create_windows_printer_port(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_printer_port, :create, resource_name)
end
def delete_windows_printer_port(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_printer_port, :delete, resource_name)
end
def request_windows_reboot(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_reboot, :request, resource_name)
end
def cancel_windows_reboot(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(:windows_reboot, :cancel, resource_name)
end
end

View File

@@ -0,0 +1,59 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Library:: helper
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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 'chef/mixin/shell_out'
module Powershell
module Helper
include Chef::Mixin::ShellOut
def powershell_installed?
!powershell_version.nil?
end
def interpreter
# force 64-bit powershell from 32-bit ruby process
if ::File.exist?("#{ENV['WINDIR']}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe")
"#{ENV['WINDIR']}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe"
elsif ::File.exist?("#{ENV['WINDIR']}\\system32\\WindowsPowershell\\v1.0\\powershell.exe")
"#{ENV['WINDIR']}\\system32\\WindowsPowershell\\v1.0\\powershell.exe"
else
"powershell.exe"
end
end
def powershell_version
begin
cmd = shell_out("#{interpreter} -InputFormat none -Command \"& echo $PSVersionTable.psversion.major\"")
if cmd.stdout.empty? # PowerShell 1.0 doesn't have a $PSVersionTable
1
else
if cmd.stdout =~ /^(\d+)/
$1.to_i
else
nil
end
end
rescue Errno::ENOENT
nil
end
end
end
end

View File

@@ -0,0 +1,79 @@
class Chef
module Mixin
module PowershellOut
include Chef::Mixin::ShellOut
begin
include Chef::Mixin::WindowsArchitectureHelper
rescue
# nothing to do, as the include will happen when windows_architecture_helper.rb
# is loaded. This is for ease of removal of that library when either
# powershell_out is core chef or powershell cookbook depends upon version
# of chef that has Chef::Mixin::WindowsArchitectureHelper in core chef
end
def powershell_out(*command_args)
script = command_args.first
options = command_args.last.is_a?(Hash) ? command_args.last : nil
run_command(script, options)
end
def powershell_out!(*command_args)
cmd = powershell_out(*command_args)
cmd.error!
cmd
end
private
def run_command(script, options)
if options && options[:architecture]
architecture = options[:architecture]
options.delete(:architecture)
else
architecture = node_windows_architecture(node)
end
disable_redirection = wow64_architecture_override_required?(node, architecture)
if disable_redirection
original_redirection_state = disable_wow64_file_redirection(node)
end
command = build_command(script)
if options
cmd = shell_out(command, options)
else
cmd = shell_out(command)
end
if disable_redirection
restore_wow64_file_redirection(node, original_redirection_state)
end
cmd
end
def build_command(script)
flags = [
# Hides the copyright banner at startup.
"-NoLogo",
# Does not present an interactive prompt to the user.
"-NonInteractive",
# Does not load the Windows PowerShell profile.
"-NoProfile",
# always set the ExecutionPolicy flag
# see http://technet.microsoft.com/en-us/library/ee176961.aspx
"-ExecutionPolicy RemoteSigned",
# Powershell will hang if STDIN is redirected
# http://connect.microsoft.com/PowerShell/feedback/details/572313/powershell-exe-can-hang-if-stdin-is-redirected
"-InputFormat None"
]
command = "powershell.exe #{flags.join(' ')} -Command \"#{script}\""
command
end
end
end
end

View File

@@ -0,0 +1,364 @@
#
# Author:: Doug MacEachern (<dougm@vmware.com>)
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Author:: Paul Morton (<pmorton@biaprotect.com>)
# Cookbook Name:: windows
# Provider:: registry
#
# Copyright:: 2010, VMware, Inc.
# Copyright:: 2011, Chef Software, Inc.
# Copyright:: 2011, Business Intelligence Associates, Inc
#
# 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.
#
if RUBY_PLATFORM =~ /mswin|mingw32|windows/
require 'win32/registry'
require_relative 'wmi_helper'
end
module Windows
module RegistryHelper
@@native_registry_constant = ENV['PROCESSOR_ARCHITEW6432'] == 'AMD64' ? 0x0100 : 0x0200
def get_hive_name(path)
Chef::Log.debug("Resolving registry shortcuts to full names")
reg_path = path.split("\\")
hive_name = reg_path.shift
hkey = {
"HKLM" => "HKEY_LOCAL_MACHINE",
"HKCU" => "HKEY_CURRENT_USER",
"HKU" => "HKEY_USERS"
}[hive_name] || hive_name
Chef::Log.debug("Hive resolved to #{hkey}")
return hkey
end
def get_hive(path)
Chef::Log.debug("Getting hive for #{path}")
reg_path = path.split("\\")
hive_name = reg_path.shift
hkey = get_hive_name(path)
hive = {
"HKEY_LOCAL_MACHINE" => ::Win32::Registry::HKEY_LOCAL_MACHINE,
"HKEY_USERS" => ::Win32::Registry::HKEY_USERS,
"HKEY_CURRENT_USER" => ::Win32::Registry::HKEY_CURRENT_USER
}[hkey]
unless hive
Chef::Application.fatal!("Unsupported registry hive '#{hive_name}'")
end
Chef::Log.debug("Registry hive resolved to #{hkey}")
return hive
end
def unload_hive(path)
hive = get_hive(path)
if hive == ::Win32::Registry::HKEY_USERS
reg_path = path.split("\\")
priv = Chef::WindowsPrivileged.new
begin
priv.reg_unload_key(reg_path[1])
rescue
end
end
end
def set_value(mode,path,values,type=nil)
hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path)
key_name = reg_path.join("\\")
Chef::Log.debug("Creating #{path}")
if !key_exists?(path,true)
create_key(path)
end
hive.send(mode, key_name, ::Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do |reg|
changed_something = false
values.each do |k,val|
key = k.to_s #wtf. avoid "can't modify frozen string" in win32/registry.rb
cur_val = nil
begin
cur_val = reg[key]
rescue
#subkey does not exist (ok)
end
if cur_val != val
Chef::Log.debug("setting #{key}=#{val}")
if type.nil?
type = :string
end
reg_type = {
:binary => ::Win32::Registry::REG_BINARY,
:string => ::Win32::Registry::REG_SZ,
:multi_string => ::Win32::Registry::REG_MULTI_SZ,
:expand_string => ::Win32::Registry::REG_EXPAND_SZ,
:dword => ::Win32::Registry::REG_DWORD,
:dword_big_endian => ::Win32::Registry::REG_DWORD_BIG_ENDIAN,
:qword => ::Win32::Registry::REG_QWORD
}[type]
reg.write(key, reg_type, val)
ensure_hive_unloaded(hive_loaded)
changed_something = true
end
end
return changed_something
end
return false
end
def get_value(path,value)
hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path)
key = reg_path.join("\\")
hive.open(key, ::Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do | reg |
begin
return reg[value]
rescue
return nil
ensure
ensure_hive_unloaded(hive_loaded)
end
end
end
def get_values(path)
hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path)
key = reg_path.join("\\")
hive.open(key, ::Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do | reg |
values = []
begin
reg.each_value do |name, type, data|
values << [name, type, data]
end
rescue
ensure
ensure_hive_unloaded(hive_loaded)
end
values
end
end
def delete_value(path,values)
hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path)
key = reg_path.join("\\")
Chef::Log.debug("Deleting values in #{path}")
hive.open(key, ::Win32::Registry::KEY_ALL_ACCESS | @@native_registry_constant) do | reg |
values.each_key { |key|
name = key.to_s
# Ensure delete operation is idempotent.
if value_exists?(path, key)
Chef::Log.debug("Deleting value #{name} in #{path}")
reg.delete_value(name)
else
Chef::Log.debug("Value #{name} in #{path} does not exist, skipping.")
end
}
end
end
def create_key(path)
hive, reg_path, hive_name, root_key, hive_loaded = get_reg_path_info(path)
key = reg_path.join("\\")
Chef::Log.debug("Creating registry key #{path}")
hive.create(key)
end
def value_exists?(path,value)
if key_exists?(path,true)
hive, reg_path, hive_name, root_key , hive_loaded = get_reg_path_info(path)
key = reg_path.join("\\")
Chef::Log.debug("Attempting to open #{key}");
Chef::Log.debug("Native Constant #{@@native_registry_constant}")
Chef::Log.debug("Hive #{hive}")
hive.open(key, ::Win32::Registry::KEY_READ | @@native_registry_constant) do | reg |
begin
rtn_value = reg[value]
return true
rescue
return false
ensure
ensure_hive_unloaded(hive_loaded)
end
end
end
return false
end
# TODO: Does not load user registry...
def key_exists?(path, load_hive = false)
if load_hive
hive, reg_path, hive_name, root_key , hive_loaded = get_reg_path_info(path)
key = reg_path.join("\\")
else
hive = get_hive(path)
reg_path = path.split("\\")
hive_name = reg_path.shift
root_key = reg_path[0]
key = reg_path.join("\\")
hive_loaded = false
end
begin
hive.open(key, ::Win32::Registry::Constants::KEY_READ | @@native_registry_constant )
return true
rescue
return false
ensure
ensure_hive_unloaded(hive_loaded)
end
end
def get_user_hive_location(sid)
reg_key = "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\#{sid}"
Chef::Log.debug("Looking for profile at #{reg_key}")
if key_exists?(reg_key)
return get_value(reg_key,'ProfileImagePath')
else
return nil
end
end
def resolve_user_to_sid(username)
begin
user_query = execute_wmi_query("select * from Win32_UserAccount where Name='#{username}'")
sid = nil
user_query.each do |user|
sid = wmi_object_property(user, 'sid')
break
end
Chef::Log.debug("Resolved user SID to #{sid}")
return sid
rescue
return nil
end
end
def hive_loaded?(path)
hive = get_hive(path)
reg_path = path.split("\\")
hive_name = reg_path.shift
user_hive = path[0]
if is_user_hive?(hive)
return key_exists?("#{hive_name}\\#{user_hive}")
else
return true
end
end
def is_user_hive?(hive)
if hive == ::Win32::Registry::HKEY_USERS
return true
else
return true
end
end
def get_reg_path_info(path)
hive = get_hive(path)
reg_path = path.split("\\")
hive_name = reg_path.shift
root_key = reg_path[0]
hive_loaded = false
if is_user_hive?(hive) && !key_exists?("#{hive_name}\\#{root_key}")
reg_path, hive_loaded = load_user_hive(hive,reg_path,root_key)
root_key = reg_path[0]
Chef::Log.debug("Resolved user (#{path}) to (#{reg_path.join('/')})")
end
return hive, reg_path, hive_name, root_key, hive_loaded
end
def load_user_hive(hive,reg_path,user_hive)
Chef::Log.debug("Reg Path #{reg_path}")
# See if the hive is loaded. Logged in users will have a key that is named their SID
# if the user has specified the a path by SID and the user is logged in, this function
# should not be executed.
if is_user_hive?(hive) && !key_exists?("HKU\\#{user_hive}")
Chef::Log.debug("The user is not logged in and has not been specified by SID")
sid = resolve_user_to_sid(user_hive)
Chef::Log.debug("User SID resolved to (#{sid})")
# Now that the user has been resolved to a SID, check and see if the hive exists.
# If this exists by SID, the user is logged in and we should use that key.
# TODO: Replace the username with the sid and send it back because the username
# does not exist as the key location.
load_reg = false
if key_exists?("HKU\\#{sid}")
reg_path[0] = sid #use the active profile (user is logged on)
Chef::Log.debug("HKEY_USERS Mapped: #{user_hive} -> #{sid}")
else
Chef::Log.debug("User is not logged in")
load_reg = true
end
# The user is not logged in, so we should load the registry from disk
if load_reg
profile_path = get_user_hive_location(sid)
if profile_path != nil
ntuser_dat = "#{profile_path}\\NTUSER.DAT"
if ::File.exists?(ntuser_dat)
priv = Chef::WindowsPrivileged.new
if priv.reg_load_key(sid,ntuser_dat)
Chef::Log.debug("RegLoadKey(#{sid}, #{user_hive}, #{ntuser_dat})")
reg_path[0] = sid
else
Chef::Log.debug("Failed RegLoadKey(#{sid}, #{user_hive}, #{ntuser_dat})")
end
end
end
end
end
return reg_path, load_reg
end
private
def ensure_hive_unloaded(hive_loaded=false)
if(hive_loaded)
Chef::Log.debug("Hive was loaded, we really should unload it")
unload_hive(path)
end
end
end
end
module Registry
module_function
extend Windows::RegistryHelper
end

View File

@@ -0,0 +1,207 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Library:: version
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
if RUBY_PLATFORM =~ /mswin|mingw32|windows/
require_relative 'wmi_helper'
require 'Win32API'
end
module Windows
class Version
# http://msdn.microsoft.com/en-us/library/ms724833(v=vs.85).aspx
# Suite Masks
# Microsoft BackOffice components are installed.
VER_SUITE_BACKOFFICE = 0x00000004.freeze unless defined?(VER_SUITE_BACKOFFICE)
# Windows Server 2003, Web Edition is installed.
VER_SUITE_BLADE = 0x00000400.freeze unless defined?(VER_SUITE_BLADE)
# Windows Server 2003, Compute Cluster Edition is installed.
VER_SUITE_COMPUTE_SERVER = 0x00004000.freeze unless defined?(VER_SUITE_COMPUTE_SERVER)
# Windows Server 2008 Datacenter, Windows Server 2003, Datacenter Edition, or Windows 2000 Datacenter Server is installed.
VER_SUITE_DATACENTER = 0x00000080.freeze unless defined?(VER_SUITE_DATACENTER)
# Windows Server 2008 Enterprise, Windows Server 2003, Enterprise Edition, or Windows 2000 Advanced Server is installed. Refer to the Remarks section for more information about this bit flag.
VER_SUITE_ENTERPRISE = 0x00000002.freeze unless defined?(VER_SUITE_ENTERPRISE)
# Windows XP Embedded is installed.
VER_SUITE_EMBEDDEDNT = 0x00000040.freeze unless defined?(VER_SUITE_EMBEDDEDNT)
# Windows Vista Home Premium, Windows Vista Home Basic, or Windows XP Home Edition is installed.
VER_SUITE_PERSONAL = 0x00000200.freeze unless defined?(VER_SUITE_PERSONAL)
# Remote Desktop is supported, but only one interactive session is supported. This value is set unless the system is running in application server mode.
VER_SUITE_SINGLEUSERTS = 0x00000100.freeze unless defined?(VER_SUITE_SINGLEUSERTS)
# Microsoft Small Business Server was once installed on the system, but may have been upgraded to another version of Windows. Refer to the Remarks section for more information about this bit flag.
VER_SUITE_SMALLBUSINESS = 0x00000001.freeze unless defined?(VER_SUITE_SMALLBUSINESS)
# Microsoft Small Business Server is installed with the restrictive client license in force. Refer to the Remarks section for more information about this bit flag.
VER_SUITE_SMALLBUSINESS_RESTRICTED = 0x00000020.freeze unless defined?(VER_SUITE_SMALLBUSINESS_RESTRICTED)
# Windows Storage Server 2003 R2 or Windows Storage Server 2003is installed.
VER_SUITE_STORAGE_SERVER = 0x00002000.freeze unless defined?(VER_SUITE_STORAGE_SERVER)
# Terminal Services is installed. This value is always set.
# If VER_SUITE_TERMINAL is set but VER_SUITE_SINGLEUSERTS is not set, the system is running in application server mode.
VER_SUITE_TERMINAL = 0x00000010.freeze unless defined?(VER_SUITE_TERMINAL)
# Windows Home Server is installed.
VER_SUITE_WH_SERVER = 0x00008000.freeze unless defined?(VER_SUITE_WH_SERVER)
# Product Type
# The system is a domain controller and the operating system is Windows Server 2012, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, or Windows 2000 Server.
VER_NT_DOMAIN_CONTROLLER = 0x0000002.freeze unless defined?(VER_NT_DOMAIN_CONTROLLER)
# The operating system is Windows Server 2012, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, or Windows 2000 Server.
# Note that a server that is also a domain controller is reported as VER_NT_DOMAIN_CONTROLLER, not VER_NT_SERVER.
VER_NT_SERVER = 0x0000003.freeze unless defined?(VER_NT_SERVER)
# The operating system is Windows 7, Windows Vista, Windows XP Professional, Windows XP Home Edition, or Windows 2000 Professional.
VER_NT_WORKSTATION = 0x0000001.freeze unless defined?(VER_NT_WORKSTATION)
# GetSystemMetrics
# The build number if the system is Windows Server 2003 R2; otherwise, 0.
SM_SERVERR2 = 89.freeze unless defined?(SM_SERVERR2)
# http://msdn.microsoft.com/en-us/library/ms724358(v=vs.85).aspx
SKU = {
0x00000006 => {:ms_const => 'PRODUCT_BUSINESS', :name => 'Business'},
0x00000010 => {:ms_const => 'PRODUCT_BUSINESS_N', :name => 'Business N'},
0x00000012 => {:ms_const => 'PRODUCT_CLUSTER_SERVER', :name => 'HPC Edition'},
0x00000008 => {:ms_const => 'PRODUCT_DATACENTER_SERVER', :name => 'Server Datacenter (full installation)'},
0x0000000C => {:ms_const => 'PRODUCT_DATACENTER_SERVER_CORE', :name => 'Server Datacenter (core installation)'},
0x00000027 => {:ms_const => 'PRODUCT_DATACENTER_SERVER_CORE_V', :name => 'Server Datacenter without Hyper-V (core installation)'},
0x00000025 => {:ms_const => 'PRODUCT_DATACENTER_SERVER_V', :name => 'Server Datacenter without Hyper-V (full installation)'},
0x00000004 => {:ms_const => 'PRODUCT_ENTERPRISE', :name => 'Enterprise'},
0x00000046 => {:ms_const => 'PRODUCT_ENTERPRISE_E', :name => 'Not supported'},
0x0000001B => {:ms_const => 'PRODUCT_ENTERPRISE_N', :name => 'Enterprise N'},
0x0000000A => {:ms_const => 'PRODUCT_ENTERPRISE_SERVER', :name => 'Server Enterprise (full installation)'},
0x0000000E => {:ms_const => 'PRODUCT_ENTERPRISE_SERVER_CORE', :name => 'Server Enterprise (core installation)'},
0x00000029 => {:ms_const => 'PRODUCT_ENTERPRISE_SERVER_CORE_V', :name => 'Server Enterprise without Hyper-V (core installation)'},
0x0000000F => {:ms_const => 'PRODUCT_ENTERPRISE_SERVER_IA64', :name => 'Server Enterprise for Itanium-based Systems'},
0x00000026 => {:ms_const => 'PRODUCT_ENTERPRISE_SERVER_V', :name => 'Server Enterprise without Hyper-V (full installation)'},
0x00000002 => {:ms_const => 'PRODUCT_HOME_BASIC', :name => 'Home Basic'},
0x00000043 => {:ms_const => 'PRODUCT_HOME_BASIC_E', :name => 'Not supported'},
0x00000005 => {:ms_const => 'PRODUCT_HOME_BASIC_N', :name => 'Home Basic N'},
0x00000003 => {:ms_const => 'PRODUCT_HOME_PREMIUM', :name => 'Home Premium'},
0x00000044 => {:ms_const => 'PRODUCT_HOME_PREMIUM_E', :name => 'Not supported'},
0x0000001A => {:ms_const => 'PRODUCT_HOME_PREMIUM_N', :name => 'Home Premium N'},
0x0000002A => {:ms_const => 'PRODUCT_HYPERV', :name => 'Microsoft Hyper-V Server'},
0x0000001E => {:ms_const => 'PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT', :name => 'Windows Essential Business Server Management Server'},
0x00000020 => {:ms_const => 'PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING', :name => 'Windows Essential Business Server Messaging Server'},
0x0000001F => {:ms_const => 'PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY', :name => 'Windows Essential Business Server Security Server'},
0x00000030 => {:ms_const => 'PRODUCT_PROFESSIONAL', :name => 'Professional'},
0x00000045 => {:ms_const => 'PRODUCT_PROFESSIONAL_E', :name => 'Not supported'},
0x00000031 => {:ms_const => 'PRODUCT_PROFESSIONAL_N', :name => 'Professional N'},
0x00000067 => {:ms_const => 'PRODUCT_PROFESSIONAL_WMC', :name => 'Professional with Media Center'},
0x00000018 => {:ms_const => 'PRODUCT_SERVER_FOR_SMALLBUSINESS', :name => 'Windows Server 2008 for Windows Essential Server Solutions'},
0x00000023 => {:ms_const => 'PRODUCT_SERVER_FOR_SMALLBUSINESS_V', :name => 'Windows Server 2008 without Hyper-V for Windows Essential Server Solutions'},
0x00000021 => {:ms_const => 'PRODUCT_SERVER_FOUNDATION', :name => 'Server Foundation'},
0x00000022 => {:ms_const => 'PRODUCT_HOME_PREMIUM_SERVER', :name => 'Windows Home Server 2011'},
0x00000032 => {:ms_const => 'PRODUCT_SB_SOLUTION_SERVER', :name => 'Windows Small Business Server 2011 Essentials'},
0x00000013 => {:ms_const => 'PRODUCT_HOME_SERVER', :name => 'Windows Storage Server 2008 R2 Essentials'},
0x00000009 => {:ms_const => 'PRODUCT_SMALLBUSINESS_SERVER', :name => 'Windows Small Business Server'},
0x00000038 => {:ms_const => 'PRODUCT_SOLUTION_EMBEDDEDSERVER', :name => 'Windows MultiPoint Server'},
0x00000007 => {:ms_const => 'PRODUCT_STANDARD_SERVER', :name => 'Server Standard (full installation)'},
0x0000000D => {:ms_const => 'PRODUCT_STANDARD_SERVER_CORE', :name => 'Server Standard (core installation)'},
0x00000028 => {:ms_const => 'PRODUCT_STANDARD_SERVER_CORE_V', :name => 'Server Standard without Hyper-V (core installation)'},
0x00000024 => {:ms_const => 'PRODUCT_STANDARD_SERVER_V', :name => 'Server Standard without Hyper-V (full installation)'},
0x0000000B => {:ms_const => 'PRODUCT_STARTER', :name => 'Starter'},
0x00000042 => {:ms_const => 'PRODUCT_STARTER_E', :name => 'Not supported'},
0x0000002F => {:ms_const => 'PRODUCT_STARTER_N', :name => 'Starter N'},
0x00000017 => {:ms_const => 'PRODUCT_STORAGE_ENTERPRISE_SERVER', :name => 'Storage Server Enterprise'},
0x00000014 => {:ms_const => 'PRODUCT_STORAGE_EXPRESS_SERVER', :name => 'Storage Server Express'},
0x00000015 => {:ms_const => 'PRODUCT_STORAGE_STANDARD_SERVER', :name => 'Storage Server Standard'},
0x00000016 => {:ms_const => 'PRODUCT_STORAGE_WORKGROUP_SERVER', :name => 'Storage Server Workgroup'},
0x00000000 => {:ms_const => 'PRODUCT_UNDEFINED', :name => 'An unknown product'},
0x00000001 => {:ms_const => 'PRODUCT_ULTIMATE', :name => 'Ultimate'},
0x00000047 => {:ms_const => 'PRODUCT_ULTIMATE_E', :name => 'Not supported'},
0x0000001C => {:ms_const => 'PRODUCT_ULTIMATE_N', :name => 'Ultimate N'},
0x00000011 => {:ms_const => 'PRODUCT_WEB_SERVER', :name => 'Web Server (full installation)'},
0x0000001D => {:ms_const => 'PRODUCT_WEB_SERVER_CORE', :name => 'Web Server (core installation)'}
}.freeze unless defined?(SKU)
attr_reader :major_version, :minor_version, :build_number, :service_pack_major_version, :service_pack_minor_version
attr_reader :version, :product_type, :product_suite, :sku
def initialize
unless RUBY_PLATFORM =~ /mswin|mingw32|windows/
raise NotImplementedError, 'only valid on Windows platform'
end
@version, @product_type, @product_suite, @sku, @service_pack_major_version, @service_pack_minor_version = get_os_info
@major_version, @minor_version, @build_number = version.split('.').map{|v| v.to_i }
end
WIN_VERSIONS = {
"Windows Server 2012 R2" => {:major => 6, :minor => 3, :callable => lambda{ @product_type != VER_NT_WORKSTATION }},
"Windows 8" => {:major => 6, :minor => 2, :callable => lambda{ @product_type == VER_NT_WORKSTATION }},
"Windows Server 2012" => {:major => 6, :minor => 2, :callable => lambda{ @product_type != VER_NT_WORKSTATION }},
"Windows 7" => {:major => 6, :minor => 1, :callable => lambda{ @product_type == VER_NT_WORKSTATION }},
"Windows Server 2008 R2" => {:major => 6, :minor => 1, :callable => lambda{ @product_type != VER_NT_WORKSTATION }},
"Windows Server 2008" => {:major => 6, :minor => 0, :callable => lambda{ @product_type != VER_NT_WORKSTATION }},
"Windows Vista" => {:major => 6, :minor => 0, :callable => lambda{ @product_type == VER_NT_WORKSTATION }},
"Windows Server 2003 R2" => {:major => 5, :minor => 2, :callable => lambda{ Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(SM_SERVERR2) != 0 }},
"Windows Home Server" => {:major => 5, :minor => 2, :callable => lambda{ (@product_suite & VER_SUITE_WH_SERVER) == VER_SUITE_WH_SERVER }},
"Windows Server 2003" => {:major => 5, :minor => 2, :callable => lambda{ Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(SM_SERVERR2) == 0 }},
"Windows XP" => {:major => 5, :minor => 1},
"Windows 2000" => {:major => 5, :minor => 0}
}.freeze unless defined?(WIN_VERSIONS)
marketing_names = Array.new
# General Windows checks
WIN_VERSIONS.each do |k,v|
method_name = "#{k.gsub(/\s/, '_').downcase}?"
define_method(method_name) do
(@major_version == v[:major]) &&
(@minor_version == v[:minor]) &&
(v[:callable] ? v[:callable].call : true)
end
marketing_names << [k, method_name]
end
define_method(:marketing_name) do
marketing_names.each do |mn|
break mn[0] if self.send(mn[1])
end
end
# Server Type checks
%w{ core full datacenter }.each do |m|
define_method("server_#{m}?") do
if @sku
!(SKU[@sku][:name] =~ /#{m}/i).nil?
else
false
end
end
end
private
# Win32API call to GetSystemMetrics(SM_SERVERR2)
# returns: The build number if the system is Windows Server 2003 R2; otherwise, 0.
def sm_serverr2
@sm_serverr2 ||= Win32API.new('user32', 'GetSystemMetrics', 'I', 'I').call(SM_SERVERR2)
end
# query WMI Win32_OperatingSystem for required OS info
def get_os_info
cols = %w{ Version ProductType OSProductSuite OperatingSystemSKU ServicePackMajorVersion ServicePackMinorVersion }
os_info = execute_wmi_query("select * from Win32_OperatingSystem").each.next
cols.map do |c|
begin
wmi_object_property(os_info, c)
rescue # OperatingSystemSKU doesn't exist in all versions of Windows
nil
end
end
end
end
end

View File

@@ -0,0 +1,87 @@
# Try to include from core chef, if error then monkey patch it in.
begin
include Chef::Mixin::WindowsArchitectureHelper
rescue
Chef::Log.debug("Chef::Mixin::WindowsArchitectureHelper not in core version, Monkey patching in.")
require 'chef/exceptions'
require 'win32/api' if Chef::Platform.windows?
class Chef
module Mixin
module WindowsArchitectureHelper
def node_windows_architecture(node)
node['kernel']['machine'].to_sym
end
def wow64_architecture_override_required?(node, desired_architecture)
is_i386_windows_process? &&
node_windows_architecture(node) == :x86_64 &&
desired_architecture == :x86_64
end
def node_supports_windows_architecture?(node, desired_architecture)
assert_valid_windows_architecture!(desired_architecture)
return (node_windows_architecture(node) == :x86_64 ||
desired_architecture == :i386) ? true : false
end
def valid_windows_architecture?(architecture)
return (architecture == :x86_64) || (architecture == :i386)
end
def assert_valid_windows_architecture!(architecture)
if ! valid_windows_architecture?(architecture)
raise Chef::Exceptions::Win32ArchitectureIncorrect,
"The specified architecture was not valid. It must be one of :i386 or :x86_64"
end
end
def is_i386_windows_process?
Chef::Platform.windows? && 'X86'.casecmp(ENV['PROCESSOR_ARCHITECTURE']) == 0
end
def disable_wow64_file_redirection(node)
original_redirection_state = ['0'].pack('P')
if ((node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows?)
win32_wow_64_disable_wow_64_fs_redirection =
::Win32::API.new('Wow64DisableWow64FsRedirection', 'P', 'L', 'kernel32')
succeeded = win32_wow_64_disable_wow_64_fs_redirection.call(original_redirection_state)
if succeeded == 0
raise Win32APIError "Failed to disable Wow64 file redirection"
end
end
original_redirection_state
end
def restore_wow64_file_redirection(node, original_redirection_state)
if ( (node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows?)
win32_wow_64_revert_wow_64_fs_redirection =
::Win32::API.new('Wow64RevertWow64FsRedirection', 'P', 'L', 'kernel32')
succeeded = win32_wow_64_revert_wow_64_fs_redirection.call(original_redirection_state)
if succeeded == 0
raise Win32APIError "Failed to revert Wow64 file redirection"
end
end
end
end
end
end
end
# Making sure this library is available to Chef::Mixin::PowershellOut
# Required for clients that don't have Chef::Mixin::WindowsArchitectureHelper in
# core chef.
if ::Chef::Platform.windows?
require_relative 'powershell_out'
Chef::Mixin::PowershellOut.send(:include, Chef::Mixin::WindowsArchitectureHelper)
end

View File

@@ -0,0 +1,148 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Library:: helper
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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 'uri'
require 'Win32API' if Chef::Platform.windows?
require 'chef/exceptions'
module Windows
module Helper
AUTO_RUN_KEY = 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run'.freeze unless defined?(AUTO_RUN_KEY)
ENV_KEY = 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'.freeze unless defined?(ENV_KEY)
ExpandEnvironmentStrings = Win32API.new('kernel32', 'ExpandEnvironmentStrings', ['P', 'P', 'L'], 'L') if Chef::Platform.windows?
# returns windows friendly version of the provided path,
# ensures backslashes are used everywhere
def win_friendly_path(path)
path.gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR || '\\') if path
end
# account for Window's wacky File System Redirector
# http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx
# especially important for 32-bit processes (like Ruby) on a
# 64-bit instance of Windows.
def locate_sysnative_cmd(cmd)
if ::File.exists?("#{ENV['WINDIR']}\\sysnative\\#{cmd}")
"#{ENV['WINDIR']}\\sysnative\\#{cmd}"
elsif ::File.exists?("#{ENV['WINDIR']}\\system32\\#{cmd}")
"#{ENV['WINDIR']}\\system32\\#{cmd}"
else
cmd
end
end
# Create a feature provider dependent value object.
# mainly created becasue Windows Feature names are
# different based on whether dism.exe or servicemanagercmd.exe
# is used for installation
def value_for_feature_provider(provider_hash)
p = Chef::Platform.find_provider_for_node(node, :windows_feature)
key = p.to_s.downcase.split('::').last
provider_hash[key] || provider_hash[key.to_sym]
end
# singleton instance of the Windows Version checker
def win_version
@win_version ||= Windows::Version.new
end
# if a file is local it returns a windows friendly path version
# if a file is remote it caches it locally
def cached_file(source, checksum=nil, windows_path=true)
@installer_file_path ||= begin
if source =~ ::URI::ABS_URI && %w[ftp http https].include?(URI.parse(source).scheme)
uri = ::URI.parse(source)
cache_file_path = "#{Chef::Config[:file_cache_path]}/#{::File.basename(::URI.unescape(uri.path))}"
Chef::Log.debug("Caching a copy of file #{source} at #{cache_file_path}")
r = Chef::Resource::RemoteFile.new(cache_file_path, run_context)
r.source(source)
r.backup(false)
r.checksum(checksum) if checksum
r.run_action(:create)
else
cache_file_path = source
end
windows_path ? win_friendly_path(cache_file_path) : cache_file_path
end
end
# Expands the environment variables
def expand_env_vars(path)
# We pick 32k because that is the largest it could be:
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms724265%28v=vs.85%29.aspx
buf = 0.chr * 32 * 1024 # 32k
if ExpandEnvironmentStrings.call(path.dup, buf, buf.length) == 0
raise Chef::Exceptions::Win32APIError, "Failed calling ExpandEnvironmentStrings (received 0)"
end
buf.strip
end
def is_package_installed?(package_name)
installed_packages.include?(package_name)
end
def installed_packages
@installed_packages || begin
installed_packages = {}
# Computer\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
installed_packages.merge!(extract_installed_packages_from_key(::Win32::Registry::HKEY_LOCAL_MACHINE)) #rescue nil
# 64-bit registry view
# Computer\HKEY_LOCAL_MACHINE\Software\Wow6464Node\Microsoft\Windows\CurrentVersion\Uninstall
installed_packages.merge!(extract_installed_packages_from_key(::Win32::Registry::HKEY_LOCAL_MACHINE, (::Win32::Registry::Constants::KEY_READ | 0x0100))) #rescue nil
# 32-bit registry view
# Computer\HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
installed_packages.merge!(extract_installed_packages_from_key(::Win32::Registry::HKEY_LOCAL_MACHINE, (::Win32::Registry::Constants::KEY_READ | 0x0200))) #rescue nil
# Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall
installed_packages.merge!(extract_installed_packages_from_key(::Win32::Registry::HKEY_CURRENT_USER)) #rescue nil
installed_packages
end
end
private
def extract_installed_packages_from_key(hkey = ::Win32::Registry::HKEY_LOCAL_MACHINE, desired = ::Win32::Registry::Constants::KEY_READ)
uninstall_subkey = 'Software\Microsoft\Windows\CurrentVersion\Uninstall'
packages = {}
begin
::Win32::Registry.open(hkey, uninstall_subkey, desired) do |reg|
reg.each_key do |key, wtime|
begin
k = reg.open(key, desired)
display_name = k["DisplayName"] rescue nil
version = k["DisplayVersion"] rescue "NO VERSION"
uninstall_string = k["UninstallString"] rescue nil
if display_name
packages[display_name] = {:name => display_name,
:version => version,
:uninstall_string => uninstall_string}
end
rescue ::Win32::Registry::Error
end
end
end
rescue ::Win32::Registry::Error
end
packages
end
end
end
Chef::Recipe.send(:include, Windows::Helper)

View File

@@ -0,0 +1,224 @@
require 'chef/resource/lwrp_base'
require 'chef/provider/lwrp_base'
if RUBY_PLATFORM =~ /mswin|mingw32|windows/
require 'win32/registry'
end
require 'chef/mixin/shell_out'
require 'chef/mixin/language'
class Chef
class Provider
class WindowsCookbookPackage < Chef::Provider::LWRPBase
include Chef::Mixin::ShellOut
include Windows::Helper
# the logic in all action methods mirror that of
# the Chef::Provider::Package which will make
# refactoring into core chef easy
action :install do
# If we specified a version, and it's not the current version, move to the specified version
if @new_resource.version != nil && @new_resource.version != @current_resource.version
install_version = @new_resource.version
# If it's not installed at all, install it
elsif @current_resource.version == nil
install_version = candidate_version
end
if install_version
Chef::Log.info("Installing #{@new_resource} version #{install_version}")
status = install_package(@new_resource.package_name, install_version)
if status
new_resource.updated_by_last_action(true)
end
end
end
action :upgrade do
if @current_resource.version != candidate_version
orig_version = @current_resource.version || "uninstalled"
Chef::Log.info("Upgrading #{@new_resource} version from #{orig_version} to #{candidate_version}")
status = upgrade_package(@new_resource.package_name, candidate_version)
if status
new_resource.updated_by_last_action(true)
end
end
end
action :remove do
if removing_package?
Chef::Log.info("Removing #{@new_resource}")
remove_package(@current_resource.package_name, @new_resource.version)
new_resource.updated_by_last_action(true)
else
end
end
def removing_package?
if @current_resource.version.nil?
false # nothing to remove
elsif @new_resource.version.nil?
true # remove any version of a package
elsif @new_resource.version == @current_resource.version
true # remove the version we have
else
false # we don't have the version we want to remove
end
end
def expand_options(options)
options ? " #{options}" : ""
end
# these methods are the required overrides of
# a provider that extends from Chef::Provider::Package
# so refactoring into core Chef should be easy
def load_current_resource
@current_resource = Chef::Resource::WindowsPackage.new(@new_resource.name)
@current_resource.package_name(@new_resource.package_name)
@current_resource.version(nil)
unless current_installed_version.nil?
@current_resource.version(current_installed_version)
end
@current_resource
end
def current_installed_version
@current_installed_version ||= begin
if installed_packages.include?(@new_resource.package_name)
installed_packages[@new_resource.package_name][:version]
end
end
end
def candidate_version
@candidate_version ||= begin
@new_resource.version || 'latest'
end
end
def install_package(name,version)
Chef::Log.debug("Processing #{@new_resource} as a #{installer_type} installer.")
install_args = [cached_file(@new_resource.source, @new_resource.checksum), expand_options(unattended_installation_flags), expand_options(@new_resource.options)]
Chef::Log.info("Starting installation...this could take awhile.")
Chef::Log.debug "Install command: #{ sprintf(install_command_template, *install_args) }"
shell_out!(sprintf(install_command_template, *install_args), {:timeout => @new_resource.timeout, :returns => @new_resource.success_codes})
end
def remove_package(name, version)
uninstall_string = installed_packages[@new_resource.package_name][:uninstall_string]
Chef::Log.info("Registry provided uninstall string for #{@new_resource} is '#{uninstall_string}'")
uninstall_command = begin
if uninstall_string =~ /msiexec/i
"#{uninstall_string} /qn"
else
uninstall_string.gsub!('"','')
"start \"\" /wait /d\"#{::File.dirname(uninstall_string)}\" #{::File.basename(uninstall_string)}#{expand_options(@new_resource.options)} /S & exit %%%%ERRORLEVEL%%%%"
end
end
Chef::Log.info("Removing #{@new_resource} with uninstall command '#{uninstall_command}'")
shell_out!(uninstall_command, {:returns => @new_resource.success_codes})
end
private
def install_command_template
case installer_type
when :msi
"msiexec%2$s \"%1$s\"%3$s"
else
"start \"\" /wait \"%1$s\"%2$s%3$s & exit %%%%ERRORLEVEL%%%%"
end
end
# http://unattended.sourceforge.net/installers.php
def unattended_installation_flags
case installer_type
when :msi
# this is no-ui
"/qn /i"
when :installshield
"/s /sms"
when :nsis
"/S /NCRC"
when :inno
#"/sp- /silent /norestart"
"/verysilent /norestart"
when :wise
"/s"
else
end
end
def installer_type
@installer_type || begin
if @new_resource.installer_type
@new_resource.installer_type
else
basename = ::File.basename(cached_file(@new_resource.source, @new_resource.checksum))
if basename.split(".").last.downcase == "msi" # Microsoft MSI
:msi
else
# search the binary file for installer type
contents = ::Kernel.open(::File.expand_path(cached_file(@new_resource.source)), "rb") {|io| io.read } # TODO limit data read in
case contents
when /inno/i # Inno Setup
:inno
when /wise/i # Wise InstallMaster
:wise
when /nsis/i # Nullsoft Scriptable Install System
:nsis
else
# if file is named 'setup.exe' assume installshield
if basename == "setup.exe"
:installshield
else
raise Chef::Exceptions::AttributeNotFound, "installer_type could not be determined, please set manually"
end
end
end
end
end
end
end
end
end
class Chef
class Resource
class WindowsCookbookPackage < Chef::Resource::LWRPBase
if Gem::Version.new(Chef::VERSION) >= Gem::Version.new('12')
provides :windows_package, os: "windows"
end
actions :install, :remove
default_action :install
attribute :package_name, :kind_of => String, :name_attribute => true
attribute :source, :kind_of => String, :required => true
attribute :version, :kind_of => String
attribute :options, :kind_of => String
attribute :installer_type, :kind_of => Symbol, :default => nil, :equal_to => [:msi, :inno, :nsis, :wise, :installshield, :custom]
attribute :checksum, :kind_of => String
attribute :timeout, :kind_of => Integer, :default => 600
attribute :success_codes, :kind_of => Array, :default => [0, 42, 127]
self.resource_name = 'windows_package'
def initialize(*args)
super
@provider = Chef::Provider::WindowsCookbookPackage
end
end
end
end
if Gem::Version.new(Chef::VERSION) < Gem::Version.new('12')
Chef::Resource.send(:remove_const, :WindowsPackage) if defined? Chef::Resource::WindowsPackage
Chef::Resource.const_set("WindowsPackage", Chef::Resource::WindowsCookbookPackage)
end

View File

@@ -0,0 +1,94 @@
#
# Author:: Doug MacEachern <dougm@vmware.com>
# Author:: Paul Morton (<pmorton@biaprotect.com>)
# Cookbook Name:: windows
# Library:: windows_privileged
#
# Copyright:: 2010, VMware, Inc.
# Copyright:: 2011, Business Intelligence Associates, Inc
#
# 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.
#
if RUBY_PLATFORM =~ /mswin|mingw32|windows/
require 'windows/error'
require 'windows/registry'
require 'windows/process'
require 'windows/security'
end
#helpers for Windows API calls that require privilege adjustments
class Chef
class WindowsPrivileged
if RUBY_PLATFORM =~ /mswin|mingw32|windows/
include Windows::Error
include Windows::Registry
include Windows::Process
include Windows::Security
end
#File -> Load Hive... in regedit.exe
def reg_load_key(name, file)
run(SE_BACKUP_NAME, SE_RESTORE_NAME) do
rc = RegLoadKey(HKEY_USERS, name.to_s, file)
if rc == ERROR_SUCCESS
return true
elsif rc == ERROR_SHARING_VIOLATION
return false
else
raise get_last_error(rc)
end
end
end
#File -> Unload Hive... in regedit.exe
def reg_unload_key(name)
run(SE_BACKUP_NAME, SE_RESTORE_NAME) do
rc = RegUnLoadKey(HKEY_USERS, name.to_s)
if rc != ERROR_SUCCESS
raise get_last_error(rc)
end
end
end
def run(*privileges)
token = [0].pack('L')
unless OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, token)
raise get_last_error
end
token = token.unpack('L')[0]
privileges.each do |name|
unless adjust_privilege(token, name, SE_PRIVILEGE_ENABLED)
raise get_last_error
end
end
begin
yield
ensure #disable privs
privileges.each do |name|
adjust_privilege(token, name, 0)
end
end
end
def adjust_privilege(token, priv, attr=0)
luid = [0,0].pack('Ll')
if LookupPrivilegeValue(nil, priv, luid)
new_state = [1, luid.unpack('Ll'), attr].flatten.pack('LLlL')
AdjustTokenPrivileges(token, 0, new_state, new_state.size, 0, 0)
end
end
end
end

View File

@@ -0,0 +1,32 @@
#
# Author:: Adam Edwards (<adamed@chef.io>)
#
# Copyright:: 2014, Chef Software, Inc.
#
# 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.
#
if RUBY_PLATFORM =~ /mswin|mingw32|windows/
require 'win32ole'
def execute_wmi_query(wmi_query)
wmi = ::WIN32OLE.connect("winmgmts://")
result = wmi.ExecQuery(wmi_query)
return nil unless result.each.count > 0
result
end
def wmi_object_property(wmi_object, wmi_property)
wmi_object.send(wmi_property)
end
end

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
#
# Author:: Paul Morton (<pmorton@biaprotect.com>)
# Cookbook Name:: windows
# Provider:: auto_run
#
# Copyright:: 2011, Business Intelligence Associates, Inc
#
# 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.
#
use_inline_resources if defined?(use_inline_resources)
action :create do
windows_registry 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' do
values new_resource.name => "\"#{new_resource.program}\" #{new_resource.args}"
end
end
action :remove do
windows_registry 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' do
values new_resource.name => ''
action :remove
end
end

View File

@@ -0,0 +1,63 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windws
# Provider:: batch
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
use_inline_resources if defined?(use_inline_resources)
require 'tempfile'
require 'chef/resource/execute'
action :run do
begin
script_file.puts(@new_resource.code)
script_file.close
set_owner_and_group
# cwd hax...shell_out on windows needs to support proper 'cwd'
# follow CHEF-2357 for more
cwd = @new_resource.cwd ? "cd \"#{@new_resource.cwd}\" & " : ""
r = Chef::Resource::Execute.new(@new_resource.name, run_context)
r.user(@new_resource.user)
r.group(@new_resource.group)
r.command("#{cwd}call \"#{script_file.path}\" #{@new_resource.flags}")
r.creates(@new_resource.creates)
r.returns(@new_resource.returns)
r.run_action(:run)
@new_resource.updated_by_last_action(r.updated_by_last_action?)
ensure
unlink_script_file
end
end
private
def set_owner_and_group
# FileUtils itself implements a no-op if +user+ or +group+ are nil
# You can prove this by running FileUtils.chown(nil,nil,'/tmp/file')
# as an unprivileged user.
FileUtils.chown(@new_resource.user, @new_resource.group, script_file.path)
end
def script_file
@script_file ||= Tempfile.open(['chef-script', '.bat'])
end
def unlink_script_file
@script_file && @script_file.close!
end

View File

@@ -0,0 +1,64 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Provider:: feature_dism
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
include Chef::Provider::WindowsFeature::Base
include Chef::Mixin::ShellOut
include Windows::Helper
def install_feature(name)
addsource = @new_resource.source ? "/LimitAccess /Source:\"#{@new_resource.source}\"" : ""
addall = @new_resource.all ? "/All" : ""
shell_out!("#{dism} /online /enable-feature /featurename:#{@new_resource.feature_name} /norestart #{addsource} #{addall}", {:returns => [0,42,127,3010]})
end
def remove_feature(name)
shell_out!("#{dism} /online /disable-feature /featurename:#{@new_resource.feature_name} /norestart", {:returns => [0,42,127,3010]})
end
def delete_feature(name)
if win_version.major_version >= 6 and win_version.minor_version >=2
shell_out!("#{dism} /online /disable-feature /featurename:#{@new_resource.feature_name} /Remove /norestart", {:returns => [0,42,127,3010]})
else
raise Chef::Exceptions::UnsupportedAction, "#{self.to_s} :delete action not support on #{win_version.sku}"
end
end
def installed?
@installed ||= begin
cmd = shell_out("#{dism} /online /Get-Features", {:returns => [0,42,127]})
cmd.stderr.empty? && (cmd.stdout =~ /^Feature Name : #{@new_resource.feature_name}.?$\n^State : Enabled.?$/i)
end
end
def available?
@available ||= begin
cmd = shell_out("#{dism} /online /Get-Features", {:returns => [0,42,127]})
cmd.stderr.empty? && (cmd.stdout !~ /^Feature Name : #{@new_resource.feature_name}.?$\n^State : .* with payload removed.?$/i)
end
end
private
# account for File System Redirector
# http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx
def dism
@dism ||= begin
locate_sysnative_cmd("dism.exe")
end
end

View File

@@ -0,0 +1,38 @@
#
# Author:: Greg Zapp (<greg.zapp@gmail.com>)
# Cookbook Name:: windows
# Provider:: feature_powershell
#
include Chef::Provider::WindowsFeature::Base
include Chef::Mixin::PowershellOut
include Windows::Helper
def install_feature(name)
cmd = powershell_out("Install-WindowsFeature #{@new_resource.feature_name}")
Chef::Log.info(cmd.stdout)
end
def remove_feature(name)
cmd = powershell_out("Uninstall-WindowsFeature #{@new_resource.feature_name}")
Chef::Log.info(cmd.stdout)
end
def delete_feature(name)
cmd = powershell_out("Uninstall-WindowsFeature #{@new_resource.feature_name} -Remove")
Chef::Log.info(cmd.stdout)
end
def installed?
@installed ||= begin
cmd = powershell_out("Get-WindowsFeature #{@new_resource.feature_name} | Select Installed | % { Write-Host $_.Installed }")
cmd.stderr.empty? && cmd.stdout =~ /True/i
end
end
def available?
@available ||= begin
cmd = powershell_out("Get-WindowsFeature #{@new_resource.feature_name}")
cmd.stderr.empty? && cmd.stdout !~ /Removed/i
end
end

View File

@@ -0,0 +1,61 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Provider:: feature_servermanagercmd
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
include Chef::Provider::WindowsFeature::Base
include Chef::Mixin::ShellOut
include Windows::Helper
# Exit codes are listed at http://technet.microsoft.com/en-us/library/cc749128(v=ws.10).aspx
def check_reboot(result, feature)
if result.exitstatus == 3010 # successful, but needs reboot
node.run_state[:reboot_requested] = true
Chef::Log.warn("Require reboot to install #{feature}")
elsif result.exitstatus == 1001 # failure, but needs reboot before we can do anything else
node.run_state[:reboot_requested] = true
Chef::Log.warn("Failed installing #{feature} and need to reboot")
end
result.error! # throw for any other bad results. The above results will also get raised, and should cause a reboot via the handler.
end
def install_feature(name)
check_reboot(shell_out("#{servermanagercmd} -install #{@new_resource.feature_name}", {:returns => [0,42,127,1003,3010]}), @new_resource.feature_name)
end
def remove_feature(name)
check_reboot(shell_out("#{servermanagercmd} -remove #{@new_resource.feature_name}", {:returns => [0,42,127,1003,3010]}), @new_resource.feature_name)
end
def installed?
@installed ||= begin
cmd = shell_out("#{servermanagercmd} -query", {:returns => [0,42,127,1003]})
cmd.stderr.empty? && (cmd.stdout =~ /^\s*?\[X\]\s.+?\s\[#{@new_resource.feature_name}\]\s*$/i)
end
end
private
# account for File System Redirector
# http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx
def servermanagercmd
@servermanagercmd ||= begin
locate_sysnative_cmd("servermanagercmd.exe")
end
end

View File

@@ -0,0 +1,69 @@
#
# Author:: Sander Botman <sbotman@schubergphilis.com>
# Cookbook Name:: windows
# Provider:: font
#
# Copyright:: 2014, Schuberg Philis BV.
#
# 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.
#
include Windows::Helper
def load_current_resource
require 'win32ole'
fonts_dir = WIN32OLE.new("WScript.Shell").SpecialFolders("Fonts")
@current_resource = Chef::Resource::WindowsFont.new(@new_resource.name)
@current_resource.file(win_friendly_path(::File.join(fonts_dir, @new_resource.file)))
@current_resource
end
# Check to see if the font is installed
#
# === Returns
# <true>:: If the font is installed
# <false>:: If the font is not instaled
def font_exists?
::File.exists?(@current_resource.file)
end
def get_cookbook_font
r = Chef::Resource::CookbookFile.new(@new_resource.file, run_context)
r.path(win_friendly_path(::File.join(ENV['TEMP'], @new_resource.file)))
r.cookbook(cookbook_name.to_s)
r.run_action(:create)
end
def del_cookbook_font
r = Chef::Resource::File.new(::File.join(ENV['TEMP'], @new_resource.file), run_context)
r.run_action(:delete)
end
def install_font
require 'win32ole'
fonts_dir = WIN32OLE.new("WScript.Shell").SpecialFolders("Fonts")
folder = WIN32OLE.new("Shell.Application").Namespace(fonts_dir)
folder.CopyHere(win_friendly_path(::File.join(ENV['TEMP'], @new_resource.file)))
Chef::Log.debug("Installing font: #{@new_resource.file}")
end
def action_install
unless font_exists?
get_cookbook_font
install_font
del_cookbook_font
new_resource.updated_by_last_action(true)
else
Chef::Log.debug("Not installing font: #{@new_resource.file}, font already installed.")
new_resource.updated_by_last_action(false)
end
end

View File

@@ -0,0 +1,153 @@
#
# Author:: Kevin Moser (<kevin.moser@nordstrom.com>)
# Cookbook Name:: windows
# Provider:: pagefile
#
# Copyright:: 2012, Nordstrom, Inc.
#
# 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.
#
include Chef::Mixin::ShellOut
include Windows::Helper
action :set do
pagefile = @new_resource.name
initial_size = @new_resource.initial_size
maximum_size = @new_resource.maximum_size
system_managed = @new_resource.system_managed
automatic_managed = @new_resource.automatic_managed
updated = false
if automatic_managed
unless automatic_managed?
set_automatic_managed
updated = true
end
else
if automatic_managed?
unset_automatic_managed
updated = true
end
# Check that the resource is not just trying to unset automatic managed, if it is do nothing more
if (initial_size && maximum_size) || system_managed
unless exists?(pagefile)
create(pagefile)
end
if system_managed
unless max_and_min_set?(pagefile, 0, 0)
set_system_managed(pagefile)
updated = true
end
else
unless max_and_min_set?(pagefile, initial_size, maximum_size)
set_custom_size(pagefile, initial_size, maximum_size)
updated = true
end
end
end
end
new_resource.updated_by_last_action(updated)
end
action :delete do
pagefile = @new_resource.name
updated = false
if exists?(pagefile)
delete(pagefile)
updated = true
end
new_resource.updated_by_last_action(updated)
end
private
def exists?(pagefile)
@exists ||= begin
cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" list /format:list", {:returns => [0]})
cmd.stderr.empty? && (cmd.stdout =~ /SettingID=#{get_setting_id(pagefile)}/i)
end
end
def max_and_min_set?(pagefile, min, max)
@max_and_min_set ||= begin
cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" list /format:list", {:returns => [0]})
cmd.stderr.empty? && (cmd.stdout =~ /InitialSize=#{min}/i) && (cmd.stdout =~ /MaximumSize=#{max}/i)
end
end
def create(pagefile)
Chef::Log.debug("Creating pagefile #{pagefile}")
cmd = shell_out("#{wmic} pagefileset create name=\"#{win_friendly_path(pagefile)}\"")
check_for_errors(cmd.stderr)
end
def delete(pagefile)
Chef::Log.debug("Removing pagefile #{pagefile}")
cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" delete")
check_for_errors(cmd.stderr)
end
def automatic_managed?
@automatic_managed ||= begin
cmd = shell_out("#{wmic} computersystem where name=\"%computername%\" get AutomaticManagedPagefile /format:list")
cmd.stderr.empty? && (cmd.stdout =~ /AutomaticManagedPagefile=TRUE/i)
end
end
def set_automatic_managed
Chef::Log.debug("Setting pagefile to Automatic Managed")
cmd = shell_out("#{wmic} computersystem where name=\"%computername%\" set AutomaticManagedPagefile=True")
check_for_errors(cmd.stderr)
end
def unset_automatic_managed
Chef::Log.debug("Setting pagefile to User Managed")
cmd = shell_out("#{wmic} computersystem where name=\"%computername%\" set AutomaticManagedPagefile=False")
check_for_errors(cmd.stderr)
end
def set_custom_size(pagefile, min, max)
Chef::Log.debug("Setting #{pagefile} to InitialSize=#{min} & MaximumSize=#{max}")
cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" set InitialSize=#{min},MaximumSize=#{max}", {:returns => [0]})
check_for_errors(cmd.stderr)
end
def set_system_managed(pagefile)
Chef::Log.debug("Setting #{pagefile} to System Managed")
cmd = shell_out("#{wmic} pagefileset where SettingID=\"#{get_setting_id(pagefile)}\" set InitialSize=0,MaximumSize=0", {:returns => [0]})
check_for_errors(cmd.stderr)
end
def get_setting_id(pagefile)
pagefile = win_friendly_path(pagefile)
pagefile = pagefile.split("\\")
"#{pagefile[1]} @ #{pagefile[0]}"
end
def check_for_errors(stderr)
unless stderr.empty?
Chef::Log.fatal(stderr)
end
end
def wmic
@wmic ||= begin
locate_sysnative_cmd("wmic.exe")
end
end

View File

@@ -0,0 +1,52 @@
#
# Author:: Paul Morton (<pmorton@biaprotect.com>)
# Cookbook Name:: windows
# Provider:: path
#
# Copyright:: 2011, Business Intelligence Associates, Inc
#
# 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.
#
use_inline_resources if defined?(use_inline_resources)
include Windows::Helper
action :add do
env "path" do
action :modify
delim ::File::PATH_SEPARATOR
value new_resource.path
notifies :run, "ruby_block[fix ruby ENV['PATH']]", :immediately
end
# The windows Env provider does not correctly expand variables in
# the PATH environment variable. Ruby expects these to be expanded.
# This is a temporary fix for that.
#
# Follow at https://github.com/chef/chef/pull/1876
#
ruby_block "fix ruby ENV['PATH']" do
block do
ENV['PATH'] = expand_env_vars(ENV['PATH'])
end
action :nothing
end
end
action :remove do
env "path" do
action :delete
delim ::File::PATH_SEPARATOR
value new_resource.path
end
end

View File

@@ -0,0 +1,101 @@
#
# Author:: Doug Ireton (<doug.ireton@nordstrom.com>)
# Cookbook Name:: windows
# Provider:: printer
#
# Copyright:: 2012, Nordstrom, Inc.
#
# 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.
#
use_inline_resources if defined?(use_inline_resources)
# Support whyrun
def whyrun_supported?
true
end
action :create do
if @current_resource.exists
Chef::Log.info "#{ @new_resource } already exists - nothing to do."
else
converge_by("Create #{ @new_resource }") do
create_printer
end
end
end
action :delete do
if @current_resource.exists
converge_by("Delete #{ @new_resource }") do
delete_printer
end
else
Chef::Log.info "#{ @current_resource } doesn't exist - can't delete."
end
end
def load_current_resource
@current_resource = Chef::Resource::WindowsPrinter.new(@new_resource.name)
@current_resource.name(@new_resource.name)
if printer_exists?(@current_resource.name)
# TODO: Set @current_resource printer properties from registry
@current_resource.exists = true
end
end
private
PRINTERS_REG_KEY = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\\'.freeze unless defined?(PRINTERS_REG_KEY)
def printer_exists?(name)
printer_reg_key = PRINTERS_REG_KEY + name
Chef::Log.debug "Checking to see if this reg key exists: '#{ printer_reg_key }'"
Registry.key_exists?(printer_reg_key)
end
def create_printer
# Create the printer port first
windows_printer_port new_resource.ipv4_address do
end
port_name = "IP_#{ new_resource.ipv4_address }"
powershell_script "Creating printer: #{ new_resource.name }" do
code <<-EOH
Set-WmiInstance -class Win32_Printer `
-EnableAllPrivileges `
-Argument @{ DeviceID = "#{ new_resource.device_id }";
Comment = "#{ new_resource.comment }";
Default = "$#{ new_resource.default }";
DriverName = "#{ new_resource.driver_name }";
Location = "#{ new_resource.location }";
PortName = "#{ port_name }";
Shared = "$#{ new_resource.shared }";
ShareName = "#{ new_resource.share_name }";
}
EOH
end
end
def delete_printer
powershell_script "Deleting printer: #{ new_resource.name }" do
code <<-EOH
$printer = Get-WMIObject -class Win32_Printer -EnableAllPrivileges -Filter "name = '#{ new_resource.name }'"
$printer.Delete()
EOH
end
end

View File

@@ -0,0 +1,103 @@
#
# Author:: Doug Ireton (<doug.ireton@nordstrom.com>)
# Cookbook Name:: windows
# Provider:: printer_port
#
# Copyright:: 2012, Nordstrom, Inc.
#
# 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.
#
use_inline_resources if defined?(use_inline_resources)
# Support whyrun
def whyrun_supported?
true
end
action :create do
if @current_resource.exists
Chef::Log.info "#{ @new_resource } already exists - nothing to do."
else
converge_by("Create #{ @new_resource }") do
create_printer_port
end
end
end
action :delete do
if @current_resource.exists
converge_by("Delete #{ @new_resource }") do
delete_printer_port
end
else
Chef::Log.info "#{ @current_resource } doesn't exist - can't delete."
end
end
def load_current_resource
@current_resource = Chef::Resource::WindowsPrinterPort.new(@new_resource.name)
@current_resource.name(@new_resource.name)
@current_resource.ipv4_address(@new_resource.ipv4_address)
@current_resource.port_name(@new_resource.port_name || "IP_#{ @new_resource.ipv4_address }")
if port_exists?(@current_resource.port_name)
# TODO: Set @current_resource port properties from registry
@current_resource.exists = true
end
end
private
PORTS_REG_KEY = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors\Standard TCP/IP Port\Ports\\'.freeze unless defined?(PORTS_REG_KEY)
def port_exists?(name)
port_reg_key = PORTS_REG_KEY + name
Chef::Log.debug "Checking to see if this reg key exists: '#{ port_reg_key }'"
Registry.key_exists?(port_reg_key)
end
def create_printer_port
port_name = new_resource.port_name || "IP_#{ new_resource.ipv4_address }"
# create the printer port using PowerShell
powershell_script "Creating printer port #{ new_resource.port_name }" do
code <<-EOH
Set-WmiInstance -class Win32_TCPIPPrinterPort `
-EnableAllPrivileges `
-Argument @{ HostAddress = "#{ new_resource.ipv4_address }";
Name = "#{ port_name }";
Description = "#{ new_resource.port_description }";
PortNumber = "#{ new_resource.port_number }";
Protocol = "#{ new_resource.port_protocol }";
SNMPEnabled = "$#{ new_resource.snmp_enabled }";
}
EOH
end
end
def delete_printer_port
port_name = new_resource.port_name || "IP_#{ new_resource.ipv4_address }"
powershell_script "Deleting printer port: #{ new_resource.port_name }" do
code <<-EOH
$port = Get-WMIObject -class Win32_TCPIPPrinterPort -EnableAllPrivileges -Filter "name = '#{ port_name }'"
$port.Delete()
EOH
end
end

View File

@@ -0,0 +1,33 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Provider:: reboot
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
action :request do
node.run_state[:reboot_requested] = true
node.run_state[:reboot_timeout] = @new_resource.timeout
node.run_state[:reboot_reason] = @new_resource.reason
new_resource.updated_by_last_action(true)
end
action :cancel do
node.run_state.delete(:reboot_requested)
node.run_state.delete(:reboot_timeout)
node.run_state.delete(:reboot_reason)
new_resource.updated_by_last_action(true)
end

View File

@@ -0,0 +1,75 @@
#
# Author:: Doug MacEachern (<dougm@vmware.com>)
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Author:: Paul Morton (<pmorton@biaprotect.com>)
# Cookbook Name:: windows
# Provider:: registry
#
# Copyright:: 2010, VMware, Inc.
# Copyright:: 2011, Chef Software, Inc.
# Copyright:: 2011, Business Intelligence Associates, Inc
#
# 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.
#
include Windows::RegistryHelper
action :create do
updated = registry_update(:create)
new_resource.updated_by_last_action(updated)
end
action :modify do
updated = registry_update(:open)
new_resource.updated_by_last_action(updated)
end
action :force_modify do
require 'timeout'
Timeout.timeout(120) do
@new_resource.values.each do |value_name, value_data|
i = 1
until i > 5 do
desired_value_data = value_data
current_value_data = get_value(@new_resource.key_name.dup, value_name.dup)
if current_value_data.to_s == desired_value_data.to_s
Chef::Log.debug("#{@new_resource} value [#{value_name}] desired [#{desired_value_data}] data already set. Check #{i}/5.")
i+=1
else
Chef::Log.debug("#{@new_resource} value [#{value_name}] current [#{current_value_data}] data not equal to desired [#{desired_value_data}] data. Setting value and restarting check loop.")
begin
updated = registry_update(:open)
new_resource.updated_by_last_action(updated)
rescue Exception
updated = registry_update(:create)
new_resource.updated_by_last_action(updated)
end
i=0 # start count loop over
end
end
end
break
end
end
action :remove do
delete_value(@new_resource.key_name,@new_resource.values)
new_resource.updated_by_last_action(true)
end
private
def registry_update(mode)
Chef::Log.debug("Registry Mode (#{mode})")
updated = set_value(mode,@new_resource.key_name,@new_resource.values,@new_resource.type)
end

View File

@@ -0,0 +1,56 @@
#
# Author:: Doug MacEachern <dougm@vmware.com>
# Cookbook Name:: windows
# Provider:: shortcut
#
# Copyright:: 2010, VMware, Inc.
#
# 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.
#
def load_current_resource
require 'win32ole'
@link = WIN32OLE.new("WScript.Shell").CreateShortcut(@new_resource.name)
@current_resource = Chef::Resource::WindowsShortcut.new(@new_resource.name)
@current_resource.name(@new_resource.name)
@current_resource.target(@link.TargetPath)
@current_resource.arguments(@link.Arguments)
@current_resource.description(@link.Description)
@current_resource.cwd(@link.WorkingDirectory)
end
# Check to see if the shorcut needs any changes
#
# === Returns
# <true>:: If a change is required
# <false>:: If the shorcuts are identical
def compare_shortcut
[:target, :arguments, :description, :cwd].any? do |attr|
!@new_resource.send(attr).nil? && @current_resource.send(attr) != @new_resource.send(attr)
end
end
def action_create
if compare_shortcut
@link.TargetPath = @new_resource.target if @new_resource.target != nil
@link.Arguments = @new_resource.arguments if @new_resource.arguments != nil
@link.Description = @new_resource.description if @new_resource.description != nil
@link.WorkingDirectory = @new_resource.cwd if @new_resource.cwd != nil
#ignoring: WindowStyle, Hotkey, IconLocation
@link.Save
Chef::Log.info("Added #{@new_resource} shortcut")
new_resource.updated_by_last_action(true)
end
end

View File

@@ -0,0 +1,167 @@
#
# Author:: Paul Mooring (<paul@chef.io>)
# Cookbook Name:: windows
# Provider:: task
#
# Copyright:: 2012, Chef Software, Inc.
#
# 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 'chef/mixin/shell_out'
include Chef::Mixin::ShellOut
action :create do
if @current_resource.exists
Chef::Log.info "#{@new_resource} task already exists - nothing to do"
else
if @new_resource.user and @new_resource.password.nil? then Chef::Log.debug "#{@new_resource} did not specify a password, creating task without a password" end
use_force = @new_resource.force ? '/F' : ''
cmd = "schtasks /Create #{use_force} /TN \"#{@new_resource.name}\" "
schedule = @new_resource.frequency == :on_logon ? "ONLOGON" : @new_resource.frequency
cmd += "/SC #{schedule} "
cmd += "/MO #{@new_resource.frequency_modifier} " if [:minute, :hourly, :daily, :weekly, :monthly].include?(@new_resource.frequency)
cmd += "/SD \"#{@new_resource.start_day}\" " unless @new_resource.start_day.nil?
cmd += "/ST \"#{@new_resource.start_time}\" " unless @new_resource.start_time.nil?
cmd += "/TR \"#{@new_resource.command}\" "
cmd += "/RU \"#{@new_resource.user}\" " if @new_resource.user
cmd += "/RP \"#{@new_resource.password}\" " if @new_resource.user and @new_resource.password
cmd += "/RL HIGHEST " if @new_resource.run_level == :highest
shell_out!(cmd, {:returns => [0]})
new_resource.updated_by_last_action true
Chef::Log.info "#{@new_resource} task created"
end
end
action :run do
if @current_resource.exists
if @current_resource.status == :running
Chef::Log.info "#{@new_resource} task is currently running, skipping run"
else
cmd = "schtasks /Run /TN \"#{@current_resource.name}\""
shell_out!(cmd, {:returns => [0]})
new_resource.updated_by_last_action true
Chef::Log.info "#{@new_resource} task ran"
end
else
Chef::Log.debug "#{@new_resource} task doesn't exists - nothing to do"
end
end
action :change do
if @current_resource.exists
cmd = "schtasks /Change /TN \"#{@current_resource.name}\" "
cmd += "/TR \"#{@new_resource.command}\" " if @new_resource.command
if @new_resource.user && @new_resource.password
cmd += "/RU \"#{@new_resource.user}\" /RP \"#{@new_resource.password}\" "
elsif (@new_resource.user and !@new_resource.password) || (@new_resource.password and !@new_resource.user)
Chef::Log.fatal "#{@new_resource.name}: Can't specify user or password without both!"
end
shell_out!(cmd, {:returns => [0]})
new_resource.updated_by_last_action true
Chef::Log.info "Change #{@new_resource} task ran"
else
Chef::Log.debug "#{@new_resource} task doesn't exists - nothing to do"
end
end
action :delete do
if @current_resource.exists
use_force = @new_resource.force ? '/F' : ''
cmd = "schtasks /Delete #{use_force} /TN \"#{@current_resource.name}\""
shell_out!(cmd, {:returns => [0]})
new_resource.updated_by_last_action true
Chef::Log.info "#{@new_resource} task deleted"
else
Chef::Log.debug "#{@new_resource} task doesn't exists - nothing to do"
end
end
action :enable do
if @current_resource.exists
if @current_resource.enabled
Chef::Log.debug "#{@new_resource} already enabled - nothing to do"
else
cmd = "schtasks /Change /TN \"#{@current_resource.name}\" "
cmd += "/ENABLE"
shell_out!(cmd, {:returns => [0]})
@new_resource.updated_by_last_action true
Chef::Log.info "#{@new_resource} task enabled"
end
else
Chef::Log.fatal "#{@new_resource} task doesn't exist - nothing to do"
raise Errno::ENOENT, "#{@new_resource}: task does not exist, cannot enable"
end
end
action :disable do
if @current_resource.exists
if @current_resource.enabled
cmd = "schtasks /Change /TN \"#{@current_resource.name}\" "
cmd += "/DISABLE"
shell_out!(cmd, {:returns => [0]})
@new_resource.updated_by_last_action true
Chef::Log.info "#{@new_resource} task disabled"
else
Chef::Log.debug "#{@new_resource} already disabled - nothing to do"
end
else
Chef::Log.debug "#{@new_resource} task doesn't exist - nothing to do"
end
end
def load_current_resource
@current_resource = Chef::Resource::WindowsTask.new(@new_resource.name)
@current_resource.name(@new_resource.name)
task_hash = load_task_hash(@current_resource.name)
if task_hash[:TaskName] == '\\' + @new_resource.name
@current_resource.exists = true
if task_hash[:Status] == "Running"
@current_resource.status = :running
end
if task_hash[:ScheduledTaskState] == "Enabled"
@current_resource.enabled = true
end
@current_resource.cwd(task_hash[:Folder])
@current_resource.command(task_hash[:TaskToRun])
@current_resource.user(task_hash[:RunAsUser])
end if task_hash.respond_to? :[]
end
private
def load_task_hash(task_name)
Chef::Log.debug "looking for existing tasks"
# we use shell_out here instead of shell_out! because a failure implies that the task does not exist
output = shell_out("schtasks /Query /FO LIST /V /TN \"#{task_name}\"").stdout
if output.empty?
task = false
else
task = Hash.new
output.split("\n").map! do |line|
line.split(":", 2).map! do |field|
field.strip
end
end.each do |field|
if field.kind_of? Array and field[0].respond_to? :to_sym
task[field[0].gsub(/\s+/,"").to_sym] = field[1]
end
end
end
task
end

View File

@@ -0,0 +1,93 @@
#
# Author:: Doug MacEachern (<dougm@vmware.com>)
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Provider:: zipfile
#
# Copyright:: 2010, VMware, Inc.
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
include Windows::Helper
require 'find'
action :unzip do
ensure_rubyzip_gem_installed
Chef::Log.debug("unzip #{@new_resource.source} => #{@new_resource.path} (overwrite=#{@new_resource.overwrite})")
Zip::File.open(cached_file(@new_resource.source, @new_resource.checksum)) do |zip|
zip.each do |entry|
path = ::File.join(@new_resource.path, entry.name)
FileUtils.mkdir_p(::File.dirname(path))
if @new_resource.overwrite && ::File.exists?(path) && !::File.directory?(path)
FileUtils.rm(path)
end
zip.extract(entry, path)
end
end
new_resource.updated_by_last_action(true)
end
action :zip do
ensure_rubyzip_gem_installed
# sanitize paths for windows.
@new_resource.source.downcase.gsub!(::File::SEPARATOR, ::File::ALT_SEPARATOR)
@new_resource.path.downcase.gsub!(::File::SEPARATOR, ::File::ALT_SEPARATOR)
Chef::Log.debug("zip #{@new_resource.source} => #{@new_resource.path} (overwrite=#{@new_resource.overwrite})")
if @new_resource.overwrite == false && ::File.exists?(@new_resource.path)
Chef::Log.info("file #{@new_resource.path} already exists and overwrite is set to false, exiting")
else
# delete the archive if it already exists, because we are recreating it.
if ::File.exists?(@new_resource.path)
::File.unlink(@new_resource.path)
end
# only supporting compression of a single directory (recursively).
if ::File.directory?(@new_resource.source)
z = Zip::File.new(@new_resource.path, true)
unless @new_resource.source =~ /::File::ALT_SEPARATOR$/
@new_resource.source << ::File::ALT_SEPARATOR
end
Find.find(@new_resource.source) do |f|
f.downcase.gsub!(::File::SEPARATOR, ::File::ALT_SEPARATOR)
# don't add root directory to the zipfile.
next if f == @new_resource.source
# strip the root directory from the filename before adding it to the zipfile.
zip_fname = f.sub(@new_resource.source, '')
Chef::Log.debug("adding #{zip_fname} to archive, sourcefile is: #{f}")
z.add(zip_fname, f)
end
z.close
new_resource.updated_by_last_action(true)
else
Chef::Log.info("Single directory must be specified for compression, and #{@new_resource.source} does not meet that criteria.")
end
end
end
private
def ensure_rubyzip_gem_installed
begin
require 'zip'
rescue LoadError
Chef::Log.info("Missing gem 'rubyzip'...installing now.")
chef_gem "rubyzip" do
version node['windows']['rubyzipversion']
action :install
end
require 'zip'
end
end

View File

@@ -0,0 +1,34 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Recipe:: default
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
# gems with precompiled binaries
%w{ win32-api win32-service }.each do |win_gem|
chef_gem win_gem do
options '--platform=mswin32'
action :install
end
end
# the rest
%w{ windows-api windows-pr win32-dir win32-event win32-mutex }.each do |win_gem|
chef_gem win_gem do
action :install
end
end

View File

@@ -0,0 +1,32 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Recipe:: restart_handler
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
remote_directory node['chef_handler']['handler_path'] do
source 'handlers'
recursive true
action :create
end
chef_handler 'WindowsRebootHandler' do
source "#{node['chef_handler']['handler_path']}/windows_reboot_handler.rb"
arguments node['windows']['allow_pending_reboots']
supports :report => true, :exception => node['windows']['allow_reboot_on_failure']
action :enable
end

View File

@@ -0,0 +1,30 @@
#
# Author:: Paul Morton (<pmorton@biaprotect.com>)
# Cookbook Name:: windows
# Resource:: auto_run
#
# Copyright:: 2011, Business Intelligence Associates, Inc
#
# 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.
#
def initialize(name,run_context=nil)
super
@action = :create
end
actions :create, :remove
attribute :program, :kind_of => String
attribute :name, :kind_of => String, :name_attribute => true
attribute :args, :kind_of => String, :default => ''

View File

@@ -0,0 +1,36 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Resource:: batch
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
actions :run
attribute :command, :kind_of => String, :name_attribute => true
attribute :cwd, :kind_of => String, :default => nil
attribute :code, :kind_of => String, :default => nil
attribute :user, :kind_of => [ String, Integer ], :default => nil
attribute :group, :kind_of => [ String, Integer ], :default => nil
attribute :creates, :kind_of => [ String ], :default => nil
attribute :flags, :kind_of => [ String ], :default => nil
attribute :returns, :kind_of => [Integer, Array], :default => 0
def initialize(name, run_context=nil)
super
@action = :run
@command = name
end

View File

@@ -0,0 +1,44 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Resource:: feature
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
include Windows::Helper
actions :install, :remove, :delete
attribute :feature_name, :kind_of => String, :name_attribute => true
attribute :source, :kind_of => String
attribute :all, :kind_of => [ TrueClass, FalseClass ], :default => false
def initialize(name, run_context=nil)
super
@action = :install
@provider = lookup_provider_constant(locate_default_provider)
end
private
def locate_default_provider
if node['windows'].attribute?(:feature_provider)
"windows_feature_#{node['windows']['feature_provider']}"
elsif ::File.exists?(locate_sysnative_cmd('dism.exe'))
:windows_feature_dism
elsif ::File.exists?(locate_sysnative_cmd('servermanagercmd.exe'))
:windows_feature_servermanagercmd
end
end

View File

@@ -0,0 +1,25 @@
#
# Author:: Sander Botman <sbotman@schubergphilis.com>
# Cookbook Name:: windows
# Resource:: font
#
# Copyright:: 2014, Schuberg Philis BV.
#
# 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.
#
actions :install
default_action :install
attribute :file, :kind_of => String, :name_attribute => true

View File

@@ -0,0 +1,29 @@
#
# Author:: Kevin Moser (<kevin.moser@nordstrom.com>)
# Cookbook Name:: windows
# Resource:: pagefile
#
# Copyright:: 2012, Nordstrom, Inc.
#
# 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.
#
actions :set, :delete
attribute :name, :kind_of => String, :name_attribute => true
attribute :system_managed, :kind_of => [TrueClass, FalseClass]
attribute :automatic_managed, :kind_of => [TrueClass, FalseClass], :default => false
attribute :initial_size, :kind_of => Integer
attribute :maximum_size, :kind_of => Integer
default_action :set

View File

@@ -0,0 +1,28 @@
#
# Author:: Paul Morton (<pmorton@biaprotect.com>)
# Cookbook Name:: windows
# Resource:: path
#
# Copyright:: 2011, Business Intelligence Associates, Inc
#
# 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.
#
def initialize(name,run_context=nil)
super
@action = :add
end
actions :add, :remove
attribute :path, :kind_of => String, :name_attribute => true

View File

@@ -0,0 +1,41 @@
#
# Author:: Doug Ireton (<doug.ireton@nordstrom.com>)
# Cookbook Name:: windows
# Resource:: printer
#
# Copyright:: 2012, Nordstrom, Inc.
#
# 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.
#
# See here for more info:
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa394492(v=vs.85).aspx
require 'resolv'
actions :create, :delete
default_action :create
attribute :device_id, :kind_of => String, :name_attribute => true,
:required => true
attribute :comment, :kind_of => String
attribute :default, :kind_of => [ TrueClass, FalseClass ], :default => false
attribute :driver_name, :kind_of => String, :required => true
attribute :location, :kind_of => String
attribute :shared, :kind_of => [ TrueClass, FalseClass ], :default => false
attribute :share_name, :kind_of => String
attribute :ipv4_address, :kind_of => String, :regex => Resolv::IPv4::Regex
attr_accessor :exists

View File

@@ -0,0 +1,40 @@
#
# Author:: Doug Ireton (<doug.ireton@nordstrom.com>)
# Cookbook Name:: windows
# Resource:: printer_port
#
# Copyright:: 2012, Nordstrom, Inc.
#
# 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.
#
# See here for more info:
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa394492(v=vs.85).aspx
require 'resolv'
actions :create, :delete
default_action :create
attribute :ipv4_address, :name_attribute => true, :kind_of => String,
:required => true, :regex => Resolv::IPv4::Regex
attribute :port_name , :kind_of => String
attribute :port_number , :kind_of => Fixnum, :default => 9100
attribute :port_description, :kind_of => String
attribute :snmp_enabled , :kind_of => [ TrueClass, FalseClass ],
:default => false
attribute :port_protocol, :kind_of => Fixnum, :default => 1, :equal_to => [1, 2]
attr_accessor :exists

View File

@@ -0,0 +1,29 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Resource:: reboot
#
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
actions :request, :cancel
attribute :timeout, :kind_of => Integer, :name_attribute => true
attribute :reason, :kind_of => String, :default => ''
def initialize(name,run_context=nil)
super
@action = :request
end

View File

@@ -0,0 +1,34 @@
#
# Author:: Doug MacEachern (<dougm@vmware.com>)
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Resource:: registry
#
# Copyright:: 2010, VMware, Inc.
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
actions :create, :modify, :force_modify, :remove
attribute :key_name, :kind_of => String, :name_attribute => true
attribute :values, :kind_of => Hash
attribute :type, :kind_of => Symbol, :default => nil, :equal_to => [:binary, :string, :multi_string, :expand_string, :dword, :dword_big_endian, :qword]
def initialize(name, run_context=nil)
super
@action = :modify
@key_name = name
Chef::Log.warn("Please use the registry_key resource in Chef Client 11. The windows_registry LWRP is still supported for Chef Client 10, but is deprecated in future versions.")
end

View File

@@ -0,0 +1,35 @@
#
# Author:: Doug MacEachern <dougm@vmware.com>
# Cookbook Name:: windows
# Resource:: shortcut
#
# Copyright:: 2010, VMware, Inc.
#
# 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.
#
actions :create
default_action :create
attribute :name, :kind_of => String
attribute :target, :kind_of => String
attribute :arguments, :kind_of => String
attribute :description, :kind_of => String
attribute :cwd, :kind_of => String
# Covers 0.10.8 and earlier
def initialize(*args)
super
@action = :create
end

View File

@@ -0,0 +1,50 @@
#
# Author:: Paul Mooring (<paul@chef.io>)
# Cookbook Name:: windows
# Resource:: task
#
# Copyright:: 2012, Chef Software, Inc.
#
# 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.
#
# Passwords can't be loaded for existing tasks, making :modify both confusing
# and not very useful
actions :create, :delete, :run, :change, :enable, :disable
attribute :name, :kind_of => String, :name_attribute => true, :regex => [ /\A[^\\\/\:\*\?\<\>\|]+\z/ ]
attribute :command, :kind_of => String
attribute :cwd, :kind_of => String
attribute :user, :kind_of => String, :default => nil
attribute :password, :kind_of => String, :default => nil
attribute :run_level, :equal_to => [:highest, :limited], :default => :limited
attribute :force, :kind_of => [ TrueClass, FalseClass ], :default => false
attribute :frequency_modifier, :kind_of => Integer, :default => 1
attribute :frequency, :equal_to => [:minute,
:hourly,
:daily,
:weekly,
:monthly,
:once,
:on_logon,
:onstart,
:on_idle], :default => :hourly
attribute :start_day, :kind_of => String, :default => nil
attribute :start_time, :kind_of => String, :default => nil
attr_accessor :exists, :status, :enabled
def initialize(name, run_context=nil)
super
@action = :create
end

View File

@@ -0,0 +1,33 @@
#
# Author:: Doug MacEachern (<dougm@vmware.com>)
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Cookbook Name:: windows
# Resource:: zipfile
#
# Copyright:: 2010, VMware, Inc.
# Copyright:: 2011, Chef Software, Inc.
#
# 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.
#
actions :unzip, :zip
attribute :path, :kind_of => String, :name_attribute => true
attribute :source, :kind_of => String
attribute :overwrite, :kind_of => [ TrueClass, FalseClass ], :default => false
attribute :checksum, :kind_of => String
def initialize(name, run_context=nil)
super
@action = :unzip
end