Note: Please go to docs.rightscale.com to access the current RightScale documentation set. Also, feel free to Chat with us!
Home > Guides > RightLink 6 > Using RightLink > Windows ChefNodeCmdlet

Windows ChefNodeCmdlet

Overview

The Windows ChefNodeCmdlet.dll module provides a set of cmdlets which extend the functionality of the PowerShell environment to include tools useful for writing Chef recipes for Windows. This module is pre-built and installed by the RightLink Installer and is available from the installed RightLink directory on cloud instances.  (You can search for it by name.)

Each cmdlet adds an executable tool to the PowerShell command line interface. Our cmdlets extend PowerShell by providing direct access to the Chef variables normally used in Chef providers to inspect the current state of the machine, perform an action, and update the persisted state. Recipes can thus be written to invoke actions which are implemented in PowerShell and which result in updates to the Chef node, current resource, and new resource objects (the latter two objects being local to each resource named in a recipe). The semantics of using these cmdlets differ from what is familiar in the Ruby language due to their being native to the PowerShell runtime, but an effort has been made to make their use as seamless as possible for the script writer.

RightLink will automatically import the cmdlet module into the running PowerShell environment at the start of execution. The PowerShell scripts which implement the actions associated with a dynamic Powershell Chef Provider can therefore invoke these cmdlets at any point in their execution. See Powershell Chef Providers for more details.

Powershell cmdlets are normally self-documenting and this information can be accessed by invoking "help" followed by the specific cmdlet name in the PowerShell console (assuming the "ChefNodeCmdlet.dll" is loaded). To load the module yourself at the console and retrieve help, run the following commands:

import-module "<path to DLL>"
help Get-ChefNode

The cmdlets need to connect to a running instance of RightLink to function properly (i.e. they will time-out if they are unable to connect) and the window of opportunity only lasts while RightLink is running recipes. See below for tips on debugging with these cmdlets.

As with most things in PowerShell, cmdlets and their parameter names are case-insensitive and in the case of parameters, can be abbreviated so long as the abbreviations are not ambiguous.

The convention for PowerShell is to use camel-case variable names but you should adhere to the Ruby convention of snake-case when getting and setting Chef node variables by path.

The Ruby convention for non-ASCII characters is to encode using UTF-8. The PowerShell convention is to use UTF-16 (Unicode). Conversion between the two encodings is handled automatically by our cmdlets, but is something to be aware of when retrieving string data on either side of the connection.

 


Cmdlets

The following cmdlets are available from the PowerShell environment as launched from RightLink during recipe execution:

Get-ChefNode

This cmdlet allows PowerShell scripts to query for current machine state from the Chef node which is currently used by RightLink. Of course there are other sources of machine state in PowerShell (e.g. WMI), but some of the information you need may be retrieved from the Chef node with a quick cmdlet call. In addition to containing details about the local machine state, the Chef node can also preserve details discovered by PowerShell scripts for use by other recipes (see Set-ChefNode). As a general rule, you have to know what to ask for before you ask for it in the course of writing an action script. The trick is knowing what to ask for. If you request a node path which is not valid in the Chef node, a $NULL will be returned. It is possible to distinguish between an unknown value and a value which is set to null by testing the parent hash to see if the key exists (i.e. get the parent hash and call .Contains("<key name>")) See below for tips on exploring the node tree in debug mode.

Parameter Description Examples
Path Array of strings representing the path to a Chef node to query with each element in the array corresponding to a hash index on the Chef node object. The -Path qualifier is optional and can be omitted for brevity. A special feature is support for the empty path, which returns a list of key names at the root of the Chef node, which is useful for exploring the Chef node from the root in debug mode. It is not possible to retrieve the entire node hierarchy in a single call (although requesting children of the root will result in some deep hashes) (required). get-chefnode -Path ""
get-chefnode kernel
get-chefnode languages, ruby
get-chefnode @("languages", "ruby")
<ReturnType> Supported types are $NULL, $TRUE, $FALSE, strings, numbers, arrays and hashes. Hashes and arrays may contain child hashes and arrays, as well as simple values. The exact type of the return value depends on what is stored in the Chef node. Any complex types stored in the Chef node on the Ruby side will be converted to a stringized form which may not contain all of the object's details. The type of the returned object can be tested by calling .GetType() on the return value (unless it is $NULL) as with all objects in PowerShell. If you wish to test for the nullity of the returned value, then use the -eq $NULL conditional. $kernelOS = get-chefnode kernel, os

 

Set-ChefNode

It can be useful to persist both static and dynamic information in a convenient form for future recipes to query. Doing so will allow those recipes to execute faster and make it easier for the scripts to be idempotent. The alternative would be to query needed information directly from the machine each time, which could present a bottleneck for getting an instance online quickly if the same-named resource is referenced to perform multiple actions. For example, it is much quicker to check a stored list of databases and their backup/restore history than to get a database connection and make a SQL query for the appropriate records. The speed advantage of using cached information which may become stale over querying machine state directly each time load_current_resource is called depends on the problem being solved. If your script relies on cached information, then it will need to be more robust in handling errors which result from using stale information.

The Set-ChefNode cmdlet solves this problem by giving the PowerShell script a convenient tool for persisting any needed information. A variety of basic data types are supported which include arrays and hashes that allow for building complex data structures in the Chef node. When the Path parameter indicates a deep path (i.e. multiple array elements in Path), then a hierarchy of hashes is implied and will be automatically created during the Set-ChefNode operation if it does not already exist. If a similarly named hash already exists, then it is extended by insertion or replacement of value. If a similarly named non-hash value exists, then it is replaced by a new hash containing only the value to be set. There is no warning for replacing an existing non-hash value. It is poor practice to replace any of the pre-existing Chef node values, so be sure to use only unique hash keys for storing your custom node information.

Although the value type can be inferred in many cases by Set-ChefNode, it is best practice to explicitly qualify value type when setting a value retrieved by function call to ensure the retrieved value matches your expected type. If you were to rely on inference for brevity in these cases then automatic type coercion might result in an unexpected type being stored in the Chef node, leading to failures in other scripts (on either the Ruby or PowerShell side). As any type may be safely coerced to string type, explicit use of -StringValue will not provide extra protection and so string values can always be abbreviated. If you require type checking on strings, then you must write an if-check surrounding the Set-ChefNode call.

Example:

$foo = FunctionCall()
if ($foo -and ($foo.GetType() -eq [System.Type]::GetType("System.String")))
{ set-chefnode x,y,z $foo }
else
{ Write-Error 'not a string' }

The value type parameters (-StringValue, -Int32Value, etc.) are mutually exclusive; you can only declare one type per value, per call to Set-ChefNode. Although none of the type parameters are required, it is required that exactly one type parameter be used in each call to Set-ChefNode.

 

Parameter Description Examples
Path Array of strings representing the path to a Chef node to query with each element in the array corresponding to a hash index on the Chef node object (required).  An empty Path parameter is not a legal command for Set-ChefNode. See Get-ChefNode for examples of the Path parameter.
StringValue Set a string value. This is the default type so that the -StringValue qualifier can be omitted for brevity as any type of object can be coerced to string. PowerShell allows either single or double quotes surrounding a literal string value. set-chefnode -Path my_str -StringValue 'hello world'
set-chefnode my_str "hello world"
set-chefnode my_hash, first_word hello
Int32Value Sets a 32-bit integer value. This is an inferred type so that the -Int32Value qualifier can be omitted for brevity when an Int32 type can be inferred. set-chefnode my_int32 -Int32Value 123
set-chefnode my_int32 123
BooleanValue Sets a Boolean value. This is an inferred type so that the -BooleanValue qualifier can be omitted for brevity when a Boolean type can be inferred. set-chefnode my_bool -BooleanValue $TRUE
set-chefnode my_bool $false
set-chefnode my_bool (1 -lt 2)
Int64Value Sets a 64-bit integer value. This type cannot be inferred. set-chefnode my_int64 -Int64Value 1234567890123456789
DoubleValue Sets a double-precision floating point value. This type cannot be inferred. set-chefnode my_dbl -DoubleValue 0.123456789012345
NullValue Sets a value to null (coerced to nil in Ruby and $NULL in Powershell). This value type has no right-hand argument. Nulling a value causes any stored value to be forgotten and can be used to remove hashes and arrays. set-chefnode my_value -NullValue
ArrayValue Sets an array value. This type cannot be inferred (due to PowerShell's eagerness to convert any ambiguous type to an array). set-chefnode my_array -ArrayValue a, b, c
set-chefnode my_array -ArrayValue @("a", "b", "c")
HashValue Sets a hash value. This is an inferred type so that the -HashValue qualifier can be omitted for brevity when an IDictionary type can be inferred. A hash may contain any supported type of value and a given hash may contain multiple types of values. Hashes retrieved by a call to Get-ChefNode do not implicitly coerce to IDictionary when set back on the Chef node, so the explicit qualifier is required in this case. A better practice may be to set individual values on a hash by multiple calls to Set-ChefNode instead of by setting the entire hash in one call. See the code sample below for hash examples.

 

Example:

Here is an example of combining Get-ChefNode and Set-ChefNode using hash values:

set-chefnode my_hash @{x="X";y="Y"}      # effect on Ruby side: @node["my_hash"] = {"x" => "X", "y" => "Y"}
$myHash = get-chefnode my_hash           # retrieve hash stored on Ruby side
$myHash.y = @{a="A";b="B"}               # alter the y value from string value "Y" to a subhash locally
$myHash.z = 123                          # insert and set the z value to 123 locally
set-chefnode my_hash -HashValue $myHash  # effect on Ruby side: @node["my_hash"] = {"x" => "X", "y" => {"a" => "A", "b" => "b"}, "z" = 123}
set-chefnode my_hash,y,c C               # effect on Ruby side: @node["my_hash"]["y"]["c"] = "C"

Get-NewResource

When a recipe references a resource and invokes an action upon it, a resource object is created and passed to the action for execution. The resource contains attributes which the action needs to reference during execution. PowerShell scripts also need to reference the resource object's attributes in order to function. The mechanism provided for this is the Get-NewResource cmdlet.

The lifetime of each new_resource object in Chef is the duration of the load_current_resource method plus the action method. The identity of the new_resource object is context-sensitive and the context will be maintained properly between invocations of PowerShell scripts (i.e. the new_resource context will change appropriately between invocations of the same action script).

The interface for Get-NewResource is identical to the Get-ChefNode cmdlet with the following differences:

  • The Path parameter represents the name of a public attribute from the resource object. If the attribute is a hash, then the comma-delimited Path parameter represents an index into that hash beginning with the named hash attribute.
  • The empty Path parameter will return a hash of all available attributes from the resource object.

Set-NewResource

A recipe may wish to alter specific attributes in the new_resource object between load_current_resource and the execution of an action script. The script may wish to supply default values, for example, for any value set to nil.

Note that any changes to new_resource are not persisted and are not available to other recipes;

The interface for Set-NewResource is identical to the Set-ChefNode cmdlet with the following differences:

  • The Path parameter behaves as described in Get-NewResource.
  • Setting values on the new_resource is subject to any validation behavior coded into the lightweight resource class. Validation errors will appear in the $Error list object in PowerShell as a result of attempting to set an invalid value on new_resource. It is standard practice to invoke $Error.Clear() on the list prior to making a call which may result in an error so that you can test if the error list is non-empty after the call.

Get-CurrentResource

Some providers may want to record the current state of a given resource in an object with the same set of attributes as the new_resource (but not necessarily the same values as new_resource). For this purpose, Chef providers maintain a temporary object known as current_resource between invocation of load_current_resource and the action methods. Chef does not initialize this object; it is the provider implementation (i.e. the PowerShell scripts) which must initialize this object (see Set-CurrentResource) or else ignore it entirely.

The lifetime of each current_resource object in Chef is the duration of load_current_resource method plus the action method. The identity of the current_resource object is context-sensitive and the context will be maintained properly between invocations of PowerShell scripts (i.e. the current_resource context will change appropriately between invocations of the same action script).

The interface for Get-CurrentResource is identical to the Get-NewResource cmdlet.

Set-CurrentResource

The load_current_resource script may wish to configure the current_resource object to represent the existing state of the resource. The Set-CurrentResource cmdlet provides this functionality.

Note that any changes to current_resource are not persisted and are not available to other recipes.

The interface for Set-CurrentResource is identical to the Set-NewResource cmdlet.

Get-NextAction

This cmdlet is used internally by RightLink to drive the PowerShell process. PowerShell scripts must avoid any attempt to invoke this cmdlet directly as this will lead to unexpected behavior.

 

You must to post a comment.
Last modified
14:01, 19 Feb 2014

Tags

Classifications

This page has no classifications.

Announcements

None


© 2006-2014 RightScale, Inc. All rights reserved.
RightScale is a registered trademark of RightScale, Inc. All other products and services may be trademarks or servicemarks of their respective owners.