Puppet Bolt now ships (as of version 2.20.0) with PowerShell native cmdlets that are auto-generated from Bolt source code with correct PowerShell verb-noun semantics, familiar PowerShell parameter conventions, and identical Bolt help documentation. All of these features work together to surface Bolt commands in a discoverable and understandable manner and enable using powerful PowerShell language features with Bolt.
What to do
How do you find out what tool to use, if you don't know what tools are available? One of the first things you learn when using PowerShell is how to get help using Get-Command
and Get-Help
. These are two very powerful cmdlets that enable intuitive discovery of the available tooling and how to use the chosen tool.
Get-Command
is a versatile tool that can find any PowerShell command on the system using a variety of filters, and returns information on both the command and where the command comes from. Previously we only shipped the bolt
command with Bolt:
PS > Get-Command bolt
CommandType Name Version Source
----------- ---- ------- ------
Function bolt 2.23.0 PuppetBolt
This doesn't do much for discoverability and requires you to run the bolt
command to find out what it can do. If we instead start to surface Bolt commands as PowerShell cmdlets, we can start to take advantage of both Get-Command
and PowerShell's cmdlet conventions to increase discoverability:
PS > Get-Command *bolt*
CommandType Name Version Source
----------- ---- ------- ------
Function bolt 2.23.0 PuppetBolt
Function Convert-BoltPlan 2.23.0 PuppetBolt
Function Get-BoltGroup 2.23.0 PuppetBolt
Function Get-BoltInventory 2.23.0 PuppetBolt
Function Get-BoltPlan 2.23.0 PuppetBolt
Function Get-BoltPuppetfileModules 2.23.0 PuppetBolt
Function Get-BoltTask 2.23.0 PuppetBolt
Function Install-BoltPuppetfile 2.23.0 PuppetBolt
Function Invoke-BoltApply 2.23.0 PuppetBolt
Function Invoke-BoltCommand 2.23.0 PuppetBolt
Function Invoke-BoltPlan 2.23.0 PuppetBolt
Function Invoke-BoltScript 2.23.0 PuppetBolt
Function Invoke-BoltTask 2.23.0 PuppetBolt
Function New-BoltPlan 2.23.0 PuppetBolt
Function New-BoltProject 2.23.0 PuppetBolt
Function New-BoltSecretKey 2.23.0 PuppetBolt
Function Protect-BoltSecret 2.23.0 PuppetBolt
Function Receive-BoltFile 2.23.0 PuppetBolt
Function Register-BoltPuppetfileTypes 2.23.0 PuppetBolt
Function Send-BoltFile 2.23.0 PuppetBolt
Function Unprotect-BoltSecret 2.23.0 PuppetBolt
Function Update-BoltProject 2.23.0 PuppetBolt
Now we can see a large list of commands using PowerShell's verb-noun syntax. Even if you aren't familiar with PowerShell's verb-noun conventions, reading the list of commands gives you an immediate general idea of what's possible with Bolt. There's plans
and scripts
, tasks
and projects
, concepts like invoking commands and getting information from the system. Scanning the list gets you immediate information you can use to choose what tool to complete your task.
If you're familiar with PowerShell's verb-noun conventions, you can start to drill down and quickly decide what command will do what you want. For example, you may want to find out how to get a list of Bolt tasks on the system. You know that PowerShell's verb-noun conventions dictate that all commands that return information use Get
as the verb, and that the noun should contain the word related to the information returned, Task
. Using this information, you run Get-Command
and tell it to search the PuppetBolt
module for all commands that use the verb Get
and have a noun with the word task
in it using a wildcard:
PS > Get-Command -Module PuppetBolt -Verb Get -Noun *task*
CommandType Name Version Source
----------- ---- ------- ------
Function Get-BoltTask 2.23.0 PuppetBolt
With Get-Command
we found Get-BoltTask
quickly in one attempt, whereas we would have to call bolt --help
, then bolt task --help
to find the same information. We didn't really need to read documentation to know which command to run, we already knew from PowerShell's conventions that any Get
command would return a one or more items and that a command with a noun BoltTask
returns information about tasks.
All of this is great for figuring out which command we need to run, but how do we know how to use it ? In the next section we'll explore using Get-Help
for this purpose, but before we do we can use Get-Command
one last time to find out some quick bits of syntax:
PS > Get-Command Get-BoltTask -Syntax
Get-BoltTask [[-Name] <string>] [-LogLevel <string>] [-Modulepath <string>] [-Project <string>] [-Configfile <string>] [-Filter <string>] [-Format <string>] [-Version] [<CommonParameters>]
The output returned by Get-Command
calls back to the opening paragraphs of this post. We used Bolt source code to generate these PowerShell cmdlets, so each cmdlet is populated with the parameters and help text for each Bolt command. Since they are formatted using PowerShell conventions, commands like Get-Command
and Get-Help
can parse these new Bolt PowerShell cmdlets and return structured information. When we ran Get-Command Get-BoltTask -Syntax
, PowerShell parsed the Bolt cmdlets and returned structured parameter information for us. This is immensely powerful for command discovery.
Getting Help
We now know the command we want to run, but how do we find out how to run it? We can use Get-Help
for that. While we can get far with a few conventions using Get-Command
, the cmdlet Get-Help
really shines in helping us understand how to use them. Since Get-BoltTask
is a PowerShell cmdlet and contains PowerShell comment based help, we can use Get-Help
to read more detailed information about how to use it:
PS > Get-Help Get-BoltTask
NAME
Get-BoltTask
SYNOPSIS
bolt task show [task] [options]
SYNTAX
Get-BoltTask [[-Name] <String>] [-LogLevel <String>] [-Modulepath <String>] [-Project
<String>] [-Configfile <String>] [-Filter <String>] [-Format <String>] [-Version]
[<CommonParameters>]
DESCRIPTION
Show available tasks and task documentation. Omitting the name of a task will display a
list of tasks available in the Bolt project. Providing the name of a task will display
detailed documentation for the task, including a list of available parameters.
RELATED LINKS
https://puppet.com/products/bolt
https://puppet.com/docs/bolt/latest/bolt_command_reference.html
REMARKS
To see the examples, type: "get-help Get-BoltTask -examples".
For more information, type: "get-help Get-BoltTask -detailed".
For technical information, type: "get-help Get-BoltTask -full".
For online help, type: "get-help Get-BoltTask -online"
We get formatted help immediatly with one command using Get-Help
. Looking through the output using Get-Help Get-BoltTask -Detailed
, you can see each Bolt PowerShell cmdlet contains all the Bolt help text for each command and parameter:
PARAMETERS
-Name <String>
The task to show
-LogLevel <String>
Set the log level for the console. Available options are
debug, info, notice, warn, error, fatal, any.
-Modulepath <String>
List of directories containing modules, separated by ';'
Directories are case-sensitive
-Project <String>
Specify what project to load config from (default: autodiscovered from current working
dir)
-Configfile <String>
Specify where to load config from (default: ~/.puppetlabs/bolt/bolt.yaml).
Directory containing bolt.yaml will be used as the project directory.
This shows that the generated the PowerShell cmdlets have typed parameters. Parameters that accept strings are cast to [string]
, parameters that accept a range of values now have [ValidateSet()]
, and so on. Most of Bolt's parameters translate naturally to PowerShell conventions. We spent a lot of time making sure these translation fit PowerShell semantics. A small list of considerations for parameters follows:
- Required parameters are detected and set as
Mandatory
- Detects when Validation attributes can be applied at the PowerShell level
- Detects common parameter sets for commands
- Added new
name
parameters to commands likecommand
,task
, orplan
and set asMandatory
andpositional
- Boolean parameters (
--[no]-ssl-verify
) are collapsed into one PowerShellswitch
parameter--SslVerify
All of this shows up in the Get-Help
output, using commands you're familiar with, without having to page through several pages of bolt command run --help
to find out what parameter will do what.
Using what you have learned
Putting all this effort into making these Bolt commands and parameters have PowerShell types and validation pays dividends not only with the PowerShell help system, but also enables some very powerful ways to invoke Bolt commands.
We can see how by using what we've covered so far in a real world example. Let's say we want to get the status of the Print Spooler service on a remote target. Using bolt --help
, then bolt task --help
, then bolt task show
, then bolt task show service
we can see that we need to run bolt task run -t localhost service name=spooler action=status
in order to check the status of the Print Spooler.
That was around 3 commands and alot of reading through pages of parameters to find out what to do. If the params we want to pass to the service
task become complicated, we can use JSON instead but that is yet another line to write.
If we remember that the new Bolt PowerShell cmdlets follow PowerShell verb-noun conventions, we can use the same discovery process we saw earlier in this post to find the command to use. We know that Invoke
is the PowerShell verb convention for executing something and we know BoltTask
is the noun we need by applying PowerShell noun conventions. Without having to think about it much or run a series of commands we know to use Invoke-BoltTask
to execute tasks. To find out how to use Invoke-BoltTask
we run Get-Help Invoke-BoltTask -detailed
and see the list of parameters needed to run the command and come up with:
PS > Invoke-BoltTask -Targets localhost -Name service -Params @{ name = 'spooler'; action = 'status' }
Started on localhost...
Finished on localhost:
{
"status": "running",
"enabled": "true"
}
Successful on 1 target: localhost
Ran on 1 target in 9.24 sec
This shows the power of using PowerShell language constructs to make passing input to Bolt easier. The -params
parameter accepts a PowerShell hash and converts it under the covers to a JSON string to pass to Bolt. This means we can get as simple or as complicated as we want defining it and PowerShell will handle the complexity of sending it to Bolt.
We can take it one step further and use PowerShell parameter splatting inside a PowerShell script, so that we can reuse the same data for multiple commands in our scripts:
PS > gc .\getserviceinfo.ps1
$spoolerParams = @{
Name = 'service'
Params = @{
name = 'spooler'
action = 'status'
}
Targets = 'localhost'
}
Invoke-BoltTask @spoolerParams
PS > .\getserviceinfo.ps1
Started on localhost...
Finished on localhost:
{
"status": "running",
"enabled": "true"
}
Successful on 1 target: localhost
Ran on 1 target in 9.68 sec
Wrapping Up
We think taking the time and effort to surface Bolt commands as native PowerShell cmdlets is proven effective by the ease of use demonstrated above. Using some simple scenarios we have shown how PowerShell cmdlets increase discoverability of our toolset and make it easier to understand how to use it. Then we covered how the PowerShell language also makes it easier to express complicated parameter sets to Bolt and enables powerful scripting scenarios.
Top comments (0)