How to use PowerShell in Chef to install Windows Server features

chef-logo-370x275Chef — the wildly popular configuration management system, whose motto is “infrastructure as code” — treats Windows as a second-class client, despite all protestations from from its creator, Opscode, to the contrary.

Still, you can do some cool stuff with Windows and Chef in PowerShell, as long as you can stand the Ruby “domain specific language” that Opscode (the creator of Chef) has based the system on.

Recently, I needed to selectively install IIS on a Windows Server. There is, of course, a “community cookbook” for IIS on GitHub. But it only installs a basic set of IIS features and, apparently, isn’t idempotent.

What follows is my simple, maybe even simplistic and certainly not very Ruby-ized, attempt to achieve the objective.

First, in your coobooks/your-cookbook-name/attributes/defaults.rb file:

default['your_cookbook_name']['iis_feature_required']  = ['Web-Server','Web-Static-Content','Web-Default-Doc','Web-Dir-Browsing','Web-Http-Errors','Web-Http-Redirect','Web-Asp-Net','Web-Net-Ext','Web-ASP','Web-CGI','Web-ISAPI-Ext','Web-ISAPI-Filter','Web-Http-Logging','Web-Request-Monitor','Web-Http-Tracing','Web-Custom-Logging','Web-Url-Auth','Web-Filtering','Web-Stat-Compression','Web-Mgmt-Console','Web-Scripting-Tools','Web-Mgmt-Service']

Here, I create a Ruby array with the 22 (!) features that this IIS application will need installed.

Next, the good stuff: a recipe that will process each element of this array and run a PowerShell Add-WindowsFeature to install the feature.

node.your_cookbook_name.iis_feature_required.each do |feat|
  powershell_script 'install-required-iis-features' do
    code <<-EOH
    $winfeat = '#{feat}'
    Add-WindowsFeature -Name $winfeat
    not_if <<-EOH
    if ( ( Get-WindowsFeature -name $winfeat).Installed )

I hope this is mostly transparent to you. Two things to note:

  • I wasn’t able to use Ruby variable substitution directly in a PowerShell cmdlet, so you see a stylistic no-no: the assignment to a variable used in the cmdlet ($winfeat = '#{feat}'), and
  • Making PowerShell scripts idempotent is totally up to you. That’s what the not_if logic does. In this case, we call the Get-WindowsFeature cmdlet to test if the feature is installed, which then causes Chef to bypass installation.



, , , ,



Leave a Reply

Your email address will not be published. Required fields are marked *