« Previous 1 2
Setting up Windows clients with Chef
Menu of the Day
Chef and PowerShell, Hand in Hand
In an ideal world, all resources of the target system can be addressed directly by Chef. Unfortunately, this never happens in practice, because – in addition to features not implemented in Chef – legacy code also needs attention. The developer team met this problem through the introduction of command-line resources – resources embedded in recipes that are executed directly by the respective shell.
The command sequence that follows starts dxdiag
, which is pre-installed on most Windows machines and is used as an example. Ruby experts will see immediately that this is a classic piece of embedded PowerShell code:
powershell_script "run-dxdiag" do code <-EOH dxdiag EOH end
Be sure to customize the node list. Several cookbooks can be entered as follows:
"run_list": [ "recipe[adminbook]", "recipe[dxdiagbook]" ]
If you run the dxdiag
cookbook several times in a row, you should not expect negative consequences; at worst, the assistant will train its multitasking capability by evaluating two configuration windows in parallel. Also, make sure that Chef is stopped until the dxdiag
process is finished.
The situation is different if you consider, for example, creating a share (Listing 5). This is more critical, in that the PowerShell command invoked to create the folder returns an error if the share already exists (Figure 1). This error terminates script execution, which makes the subsequent node configurations impossible.
Listing 5
Creating a Share
directory 'c:\\adminlog' do action :create inherits true end powershell_script "shareFolder" do code 'new-smbshare adminshare c:\adminlog' end
Chef's popularity is attributable to, among other things, the fact that any configurations you create are idempotent: Applying the same resource multiple times will not cause problems, because the run time detects that the changes already exist.
In the case of an embedded PowerShell resource, this contextual information is missing. Chef gets around this problem by introducing "guards," a programming construct that is executed before the actual execution of the command. Its return value allows conditional execution of a payload. The simplest form of a guard uses a Ruby block or a classic command-line utility:
template '/tmp/myfile' do mode 00644 source 'myfile.erb' not_if {File.exists?('/etc/passwd')} end
In addition to the not_if
guard shown here, you have only_if
.
The share manager can be protected by a guard that checks the share list for the existence of the shares to be created. This is another PowerShell resource – all told, the cookbook looks like Listing 6.
Listing 6
The Cookbook
directory 'c:\\adminlog' do action :create inherits true end powershell_script "shareFolder" do guard_interpreter :powershell_script code 'new-smbshare adminshare c:\adminlog' not_if 'get-smbshare adminshare' end
From now on, chef-client
can be run as often as you like; the PowerShell transaction has become idempotent, as reflected in the command line by the statements:
INFO: Processing powershell_script[Guard resource] action run (dynamically defined) INFO: powershell_script[Guard resource] ran successfully (skipped due to not_if)
Chef runs guards in several ways, which can sometimes return completely different results. The video recording of a lecture by Adam Edwards [5] is mandatory for anyone wanting to add guards to their Chef scripts.
Scripting the Client's Target State
Microsoft's PowerShell has supported scripting since time immemorial, and frequently used commands can thus be easily repeated. Scripts like this reach their limits when features are to be delivered incrementally. The Desired State Configuration (DSC) concept introduced in 2013 makes some serious changes here. A DSC-based installation script is not a linear sequence of commands, but a complete description of the target condition. The run time can compare the tree with the actual state to resolve differences through targeted transactions – similarities to Chef are purely coincidental.
Windows 8.1 comes with PowerShell state providers, as shown in Table 1. To discover the list applicable to your server, just type get-dscresource
in PowerShell. The Name
and Properties
columns are important for administrators. Name
is used to select the provider to be addressed, whereas the attribute list describes the properties that are available. Microsoft offers an extension SDK [6]; once it is installed, more than 100 different state providers are available.
Table 1
PowerShell State Providers in Windows 8.1
Implemented as | Name | Module | Properties |
---|---|---|---|
Binary | File
|
{DestinationPath, Attributes, Checksum, Con...}
|
|
PowerShell | Archive
|
PSDesiredStateConfiguration
|
{Destination, Path, Checksum, Credential...}
|
PowerShell | Environment
|
PSDesiredStateConfiguration
|
{Name, DependsOn, Ensure, Path...}
|
PowerShell | Group
|
PSDesiredStateConfiguration
|
{GroupName, Credential, DependsOn, Descript...}
|
Binary | Log
|
PSDesiredStateConfiguration
|
{Message, DependsOn}
|
PowerShell | Package
|
PSDesiredStateConfiguration
|
{Name, Path, ProductId, Arguments...}
|
PowerShell | Registry
|
PSDesiredStateConfiguration
|
{Key, ValueName, DependsOn, Ensure...}
|
PowerShell | Script
|
PSDesiredStateConfiguration
|
{GetScript, SetScript, TestScript, Credenti...}
|
PowerShell | Service
|
PSDesiredStateConfiguration
|
{Name, BuiltInAccount, Credential, DependsO...}
|
PowerShell | User
|
PSDesiredStateConfiguration
|
{UserName, DependsOn, Description, Disabled...}
|
PowerShell | WindowsFeature
|
PSDesiredStateConfiguration
|
{Name, Credential, DependsOn, Ensure...}
|
PowerShell | WindowsProcess
|
PSDesiredStateConfiguration
|
{Arguments, Path, Credential, DependsOn...}
|
You can deliver the file with Chef – to do so, create a new cookbook called powershell-extender
. knife
then create the following folder structure:
tamhan@ubuntu:~/Desktop/chefHaus/chef-repo/cookbooks/powershellextender$ ls attributes definitions libraries providers recipes templates CHANGELOG.md files metadata.rb README.md resources
The previously unused file directory becomes relevant at this point. Files deployed there are transferred to the nodes on request. Download the ZIP file from the Microsoft website and store the file in /files/default
; then, customize default.rb
as in Listing 7.
Listing 7
Changes to default.rb
cookbook_file 'C:\\sdkfile.zip' do source 'sdk.zip' action :create end dsc_resource 'unpackextender' do resource_name :archive property :ensure, 'Present' property :path, 'C:\\sdkfile.zip' property :destination, 'C:\\Program Files\\WindowsPowerShell\\ Modules' end
The resource beginning with cookbook_file
transfers the sdk.zip
file to its new home on the client. Because PowerShell only parses the first subfolder level of the modules directory, you need to repackage the archive provided by Microsoft.
File extraction in Chef usually involves calling a command-line program, but I am going to use a different trick here. The PowerShell contains a DSC provider, which is responsible for unzipping various archives. Access to the provider always follows the same pattern. The string passed to resource_name
determines the DSC providers to use, whereas the individual attributes are declared per property.
At the moment, the various DSC extensions are available in the form of cookbooks that you need to include in your own cookbook (Figure 2). To do so, edit metadata.rb
(Listing 8). Note that communication between the DSC and PowerShell relies on WinRM – the service is disabled by default on Windows 8.1. Fortunately this can be resolved using winrm quickconfig
. You are now ready. Wire up the new recipe and enjoy the abundance of resources after running.
Listing 8
metdata.rb Edits
name 'powershellextender' maintainer 'YOUR_COMPANY_NAME' maintainer_email 'YOUR_EMAIL' license 'All rights reserved' description 'Installs/Configures powershellextender' long_description IO.read(File. join(File.dirname(__FILE__),'README.md')) version '0.1.0' depends 'dsc'
The git
command is used as before,
git clone https://github.com/opscode-cookbooks/dsc.git
to download the cookbook code.
Conclusions
The learning curve for Chef is anything but easy: if you want to run chef-client
on a non-Windows Server, you are by and large on your own. The instructions presented here – in conjunction with basic knowledge of the Ruby programming language – facilitate these critical first steps. There is no question that hacking together a batch file is much faster. But Chef has its strengths when you need to use the same image on multiple systems. The batch solution reaches its limits, once existing workstations or clients need to be updated to the latest version. Chef has also established itself in smaller deployments. This is because a server group created on the basis of the management tool is 100 percent in sync – Chef eliminates any imbalance when executing the client.
Infos
- Chef: [https://www.chef.io]
- Chef server download, also 64-bit: [https://downloads.chef.io/chef-server]
- Installing a Chef client on Windows: [https://docs.chef.io/install_windows.html]
- Chef documents: [http://docs.chef.io/resources.html]
- Video of a lecture by Adam Edwards: [https://www.youtube.com/watch?v=BNV2jZUjKlc]
- DSC Resource Kit: [https://gallery.technet.microsoft.com/scriptcenter/DSC-Resource-Kit-All-c449312d]
« Previous 1 2
Buy this article as PDF
(incl. VAT)