# Disabling IPv6 via Chef on Windows

While there are lots of resources on the Internet for disabling IPv6 on Linux, there are very few that show how to disable IPv6 on Windows.  Here is a quick recipe that I put together that will disable IPv6 and restart if needed.

powershell_script "disable_ipv6" do
    guard_interpreter :powershell_script
    code "New-ItemProperty 'HKLM:\\SYSTEM\\CurrentControlSet\\services\\TCPIP6\\Parameters\\' -Name 'DisabledComponents' -Value '0xffffffff' -PropertyType 'DWord'"
    notifies :reboot_now, 'reboot[disable_ipv6_requires_reboot]', :immediately
    not_if "(Get-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\services\\TCPIP6\\Parameters' -Name DisabledComponents -ErrorAction SilentlyContinue).DisabledComponents -ne \$null"
end

reboot 'disable_ipv6_requires_reboot' do
    action :nothing
    reason 'Disabling IPv6 requires a reboot to take effect.'
end

Before you use this, you should know that Microsoft do not recommend you disable IPv6.  You will experience a 5 second delay during the boot up process and Microsoft does not explicitly test this scenario.

Another interesting thing about this recipe is the condition used in the not_if.  I initially wanted to use Test-Path, but it turns out that Test-Path doesn’t work on registry values, it only works on registry paths.   I got around this using Get-ItemProperty and testing for a null value.

# Deploying Multiple files using Chef and Arrays

This post is one of a number of posts I’m making on nifty little tricks for Chef beginners.  These posts will try and detail solutions to common problems I found when learning Chef.  Hopefully I will save some people some time.

When I first started using Chef I would write the same lines of code over and over again to deploy files to a server.  This code would look something like the following:

cookbook_file "/etc/test/file1.txt"
   source "/my/files/file1.txt"
end

While this works for a few files it soon becomes unmanageable when you need to deploy more than a few.  The easiest way to keep your recipe nice and tidy is to create an array of the files and loop through the array performing the Chef action on the file that’s needed.  This will reduce the number of lines in your recipe and will be easier to maintain going forward.  This looks like this:

# Location of the files and templates within the cookbook
# the following location would translation to files/default/my/files
files_directory="/my/files"

# Location to deploy to
etc_directory="/etc/test"

# Array of the files that require to be deployed
file_array = [
'file1.txt',
'file1.txt',
'file1.txt',
'file1.txt']

# For each file in the array
file_array.each do |this_file|
   cookbook_file "#{etc_directory}/" + this_file do
      source "#{files_directory}/#{this_file}"
   end
end

The inner code works with cookbook_file, template or anything else you may need to do multiple times.

# Creating Directories Including Parents using Chef on Windows

I’ve recently been building some test environments on Microsoft Windows 2008 R2 using Chef. One thing that Chef misses is an easy way to create parent directories if needed when creating a directory.

The standard method of creating a directory will not work if D:\foo\bar doesn’t already exist:

directory "D:\\foo\\bar\\buzz" do
   action :create
end

You can create a parent directories by placing each element of a path into an array, then loop through the array creating each folder:

%w[ D:\\foo \\foo\\bar \\foo\\bar\\baz ].each do |path|
   directory path do
      action :create
   end
end

I already had my path declared in a variable for other uses. I didn’t want to store it twice and I didn’t want to create a block of Ruby to try and break the path up from the variable.

After some research I discovered that its easier to simply run the New-Item command in a PowerShell block:

# Location of the install and patch directory
install_directory="D:\\foo\\bar\\buzz"

# Create the directory, including parents
powershell_script "create_install_directoy_if_not_exists" do
   guard_interpreter :powershell_script
   code "New-Item -ItemType Directory -Path #{install_directory} -Force"
   not_if "Test-Path #{install_directory}"
end

This will create the directory, including parent directories if needed. On Windows this appears to be the easiest way of coping with missing parent directories.