bolt 2.44.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

@@ -166,10 +166,11 @@ module Bolt
166
166
  # Migrates the project-level configuration file to the latest version.
167
167
  #
168
168
  private def migrate_config
169
- migrator = ConfigMigrator.new(@outputter)
169
+ migrator = ConfigMigrator.new(@outputter)
170
+ configfile = @config.project.path + 'bolt.yaml'
170
171
 
171
172
  migrator.migrate(
172
- @config.project.config_file,
173
+ configfile,
173
174
  @config.project.project_file,
174
175
  @config.inventoryfile || @config.project.inventory_file,
175
176
  @config.project.backup_dir
@@ -194,7 +195,7 @@ module Bolt
194
195
 
195
196
  migrator.migrate(
196
197
  @config.project,
197
- @config.modulepath
198
+ @config.modulepath[0...-1]
198
199
  )
199
200
  end
200
201
  end
@@ -6,19 +6,20 @@ module Bolt
6
6
  class ProjectManager
7
7
  class ModuleMigrator < Migrator
8
8
  def migrate(project, configured_modulepath)
9
- return true unless project.modules.nil?
9
+ return true if project.managed_moduledir.exist?
10
10
 
11
11
  @outputter.print_message "Migrating project modules\n\n"
12
12
 
13
13
  config = project.project_file
14
14
  puppetfile = project.puppetfile
15
15
  managed_moduledir = project.managed_moduledir
16
- modulepath = [(project.path + 'modules').to_s,
16
+ new_modulepath = [(project.path + 'modules').to_s]
17
+ old_modulepath = [(project.path + 'modules').to_s,
17
18
  (project.path + 'site-modules').to_s,
18
19
  (project.path + 'site').to_s]
19
20
 
20
21
  # Notify user to manually migrate modules if using non-default modulepath
21
- if configured_modulepath != modulepath
22
+ if configured_modulepath != new_modulepath && configured_modulepath != old_modulepath
22
23
  @outputter.print_action_step(
23
24
  "Project has a non-default configured modulepath, unable to automatically "\
24
25
  "migrate project modules. To migrate project modules manually, see "\
@@ -27,10 +28,10 @@ module Bolt
27
28
  true
28
29
  # Migrate modules from Puppetfile
29
30
  elsif File.exist?(puppetfile)
30
- migrate_modules_from_puppetfile(config, puppetfile, managed_moduledir, modulepath)
31
+ migrate_modules_from_puppetfile(config, puppetfile, managed_moduledir, old_modulepath)
31
32
  # Migrate modules to updated modulepath
32
33
  else
33
- consolidate_modules(modulepath)
34
+ consolidate_modules(old_modulepath)
34
35
  update_project_config([], config)
35
36
  end
36
37
  end
@@ -23,8 +23,7 @@ module Bolt
23
23
  # This lets us know how many targets have Powershell 2, and lets the
24
24
  # user know how many targets they have with PS2
25
25
  msg = "Detected PowerShell 2 on one or more targets.\nPowerShell 2 "\
26
- "is deprecated, and support will be removed in Bolt 3.0. See "\
27
- "bolt-debug.log or run with '--log-level debug' to see the full "\
26
+ "is unsupported. See bolt-debug.log or run with '--log-level debug' to see the full "\
28
27
  "list of targets with PowerShell 2."
29
28
 
30
29
  Bolt::Logger.deprecate_once("powershell_2", msg)
@@ -70,12 +70,17 @@ module Bolt
70
70
  def ps_task(path, arguments)
71
71
  <<~PS
72
72
  $private:tempArgs = Get-ContentAsJson (
73
- $utf8.GetString([System.Convert]::FromBase64String('#{Base64.encode64(JSON.dump(arguments))}'))
73
+ [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('#{Base64.encode64(JSON.dump(arguments))}'))
74
74
  )
75
75
  $allowedArgs = (Get-Command "#{path}").Parameters.Keys
76
76
  $private:taskArgs = @{}
77
77
  $private:tempArgs.Keys | ? { $allowedArgs -contains $_ } | % { $private:taskArgs[$_] = $private:tempArgs[$_] }
78
- try { & "#{path}" @taskArgs } catch { Write-Error $_.Exception; exit 1 }
78
+ try {
79
+ & "#{path}" @taskArgs
80
+ } catch {
81
+ $Host.UI.WriteErrorLine("[$($_.FullyQualifiedErrorId)] Exception $($_.InvocationInfo.PositionMessage).`n$($_.Exception.Message)");
82
+ exit 1;
83
+ }
79
84
  PS
80
85
  end
81
86
 
@@ -102,151 +107,11 @@ module Bolt
102
107
  "${boltBaseDir}\\hiera\\lib;" +
103
108
  $ENV:RUBYLIB
104
109
 
105
- Add-Type -AssemblyName System.ServiceModel.Web, System.Runtime.Serialization
106
- $utf8 = [System.Text.Encoding]::UTF8
107
-
108
- function Write-Stream {
109
- PARAM(
110
- [Parameter(Position=0)] $stream,
111
- [Parameter(ValueFromPipeline=$true)] $string
112
- )
113
- PROCESS {
114
- $bytes = $utf8.GetBytes($string)
115
- $stream.Write( $bytes, 0, $bytes.Length )
116
- }
117
- }
118
-
119
- function Convert-JsonToXml {
120
- PARAM([Parameter(ValueFromPipeline=$true)] [string[]] $json)
121
- BEGIN {
122
- $mStream = New-Object System.IO.MemoryStream
123
- }
124
- PROCESS {
125
- $json | Write-Stream -Stream $mStream
126
- }
127
- END {
128
- $mStream.Position = 0
129
- try {
130
- $jsonReader = [System.Runtime.Serialization.Json.JsonReaderWriterFactory]::CreateJsonReader($mStream,[System.Xml.XmlDictionaryReaderQuotas]::Max)
131
- $xml = New-Object Xml.XmlDocument
132
- $xml.Load($jsonReader)
133
- $xml
134
- } finally {
135
- $jsonReader.Close()
136
- $mStream.Dispose()
137
- }
138
- }
139
- }
140
-
141
- Function ConvertFrom-Xml {
142
- [CmdletBinding(DefaultParameterSetName="AutoType")]
143
- PARAM(
144
- [Parameter(ValueFromPipeline=$true,Mandatory=$true,Position=1)] [Xml.XmlNode] $xml,
145
- [Parameter(Mandatory=$true,ParameterSetName="ManualType")] [Type] $Type,
146
- [Switch] $ForceType
147
- )
148
- PROCESS{
149
- if (Get-Member -InputObject $xml -Name root) {
150
- return $xml.root.Objects | ConvertFrom-Xml
151
- } elseif (Get-Member -InputObject $xml -Name Objects) {
152
- return $xml.Objects | ConvertFrom-Xml
153
- }
154
- $propbag = @{}
155
- foreach ($name in Get-Member -InputObject $xml -MemberType Properties | Where-Object{$_.Name -notmatch "^(__.*|type)$"} | Select-Object -ExpandProperty name) {
156
- Write-Debug "$Name Type: $($xml.$Name.type)" -Debug:$false
157
- $propbag."$Name" = Convert-Properties $xml."$name"
158
- }
159
- if (!$Type -and $xml.HasAttribute("__type")) { $Type = $xml.__Type }
160
- if ($ForceType -and $Type) {
161
- try {
162
- $output = New-Object $Type -Property $propbag
163
- } catch {
164
- $output = New-Object PSObject -Property $propbag
165
- $output.PsTypeNames.Insert(0, $xml.__type)
166
- }
167
- } elseif ($propbag.Count -ne 0) {
168
- $output = New-Object PSObject -Property $propbag
169
- if ($Type) {
170
- $output.PsTypeNames.Insert(0, $Type)
171
- }
172
- }
173
- return $output
174
- }
175
- }
176
-
177
- Function Convert-Properties {
178
- PARAM($InputObject)
179
- switch ($InputObject.type) {
180
- "object" {
181
- return (ConvertFrom-Xml -Xml $InputObject)
182
- }
183
- "string" {
184
- $MightBeADate = $InputObject.get_InnerText() -as [DateTime]
185
- ## Strings that are actually dates (*grumble* JSON is crap)
186
- if ($MightBeADate -and $propbag."$Name" -eq $MightBeADate.ToString("G")) {
187
- return $MightBeADate
188
- } else {
189
- return $InputObject.get_InnerText()
190
- }
191
- }
192
- "number" {
193
- $number = $InputObject.get_InnerText()
194
- if ($number -eq ($number -as [int])) {
195
- return $number -as [int]
196
- } elseif ($number -eq ($number -as [double])) {
197
- return $number -as [double]
198
- } else {
199
- return $number -as [decimal]
200
- }
201
- }
202
- "boolean" {
203
- return [bool]::parse($InputObject.get_InnerText())
204
- }
205
- "null" {
206
- return $null
207
- }
208
- "array" {
209
- [object[]]$Items = $(foreach( $item in $InputObject.GetEnumerator() ) {
210
- Convert-Properties $item
211
- })
212
- return $Items
213
- }
214
- default {
215
- return $InputObject
216
- }
217
- }
218
- }
219
-
220
- Function ConvertFrom-Json2 {
221
- [CmdletBinding()]
222
- PARAM(
223
- [Parameter(ValueFromPipeline=$true,Mandatory=$true,Position=1)] [string] $InputObject,
224
- [Parameter(Mandatory=$true)] [Type] $Type,
225
- [Switch] $ForceType
226
- )
227
- PROCESS {
228
- $null = $PSBoundParameters.Remove("InputObject")
229
- [Xml.XmlElement]$xml = (Convert-JsonToXml $InputObject).Root
230
- if ($xml) {
231
- if ($xml.Objects) {
232
- $xml.Objects.Item.GetEnumerator() | ConvertFrom-Xml @PSBoundParameters
233
- } elseif ($xml.Item -and $xml.Item -isnot [System.Management.Automation.PSParameterizedProperty]) {
234
- $xml.Item | ConvertFrom-Xml @PSBoundParameters
235
- } else {
236
- $xml | ConvertFrom-Xml @PSBoundParameters
237
- }
238
- } else {
239
- Write-Error "Failed to parse JSON with JsonReader" -Debug:$false
240
- }
241
- }
242
- }
243
-
244
110
  function ConvertFrom-PSCustomObject
245
111
  {
246
112
  PARAM([Parameter(ValueFromPipeline = $true)] $InputObject)
247
113
  PROCESS {
248
114
  if ($null -eq $InputObject) { return $null }
249
-
250
115
  if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) {
251
116
  $collection = @(
252
117
  foreach ($object in $InputObject) { ConvertFrom-PSCustomObject $object }
@@ -273,13 +138,8 @@ module Bolt
273
138
  [Parameter(Mandatory = $true)] $Text,
274
139
  [Parameter(Mandatory = $false)] [Text.Encoding] $Encoding = [Text.Encoding]::UTF8
275
140
  )
276
-
277
- # using polyfill cmdlet on PS2, so pass type info
278
- if ($PSVersionTable.PSVersion -lt [Version]'3.0') {
279
- $Text | ConvertFrom-Json2 -Type PSObject | ConvertFrom-PSCustomObject
280
- } else {
281
- $Text | ConvertFrom-Json | ConvertFrom-PSCustomObject
282
- }
141
+
142
+ $Text | ConvertFrom-Json | ConvertFrom-PSCustomObject
283
143
  }
284
144
  PS
285
145
  end
@@ -11,18 +11,10 @@ module Bolt
11
11
  end
12
12
 
13
13
  def with_connection(target)
14
- if target.transport_config['bundled-ruby'] || target.name == 'localhost'
14
+ if target.transport_config['bundled-ruby']
15
15
  target.set_local_defaults
16
16
  end
17
17
 
18
- if target.name != 'localhost' &&
19
- !target.transport_config.key?('bundled-ruby')
20
- msg = "The local transport will default to using Bolt's Ruby interpreter and "\
21
- "setting the 'puppet-agent' feature in Bolt 3.0. Enable or disable these "\
22
- "defaults by setting 'bundled-ruby' in the local transport config."
23
- Bolt::Logger.warn_once("local_default_config", msg)
24
- end
25
-
26
18
  yield Connection.new(target)
27
19
  end
28
20
  end
data/lib/bolt/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '2.44.0'
4
+ VERSION = '3.0.0'
5
5
  end
@@ -352,7 +352,7 @@ module BoltServer
352
352
  end
353
353
 
354
354
  def allowed_helper(metadata, allowlist)
355
- allowed = allowlist.nil? || allowlist.include?(metadata['name']) ? true : false
355
+ allowed = allowlist.nil? || allowlist.include?(metadata['name'])
356
356
  metadata.merge({ 'allowed' => allowed })
357
357
  end
358
358
 
@@ -1,3 +1,24 @@
1
+ # @summary
2
+ # Run a task, command, or script on targets and aggregate the results as
3
+ # a count of targets for each value of a key.
4
+ #
5
+ # This plan accepts an action and a list of targets. The action can be the name
6
+ # of a task, a script, or a command to run. It will run the action on the
7
+ # targets and aggregate the key/value pairs in each Result into a hash, mapping
8
+ # the keys to a hash of each distinct value and how many targets returned that
9
+ # value for the key.
10
+ #
11
+ # @param command
12
+ # The command to run. Mutually exclusive with script and task.
13
+ # @param script
14
+ # The path to the script to run. Mutually exclusive with command and task.
15
+ # @param task
16
+ # The name of the task to run. Mutually exclusive with command and script.
17
+ # @param targets
18
+ # The list of targets to run the action on.
19
+ # @param params
20
+ # A hash of parameters and options to pass to the `run_*` function
21
+ # associated with the action (e.g. run_task).
1
22
  plan aggregate::count(
2
23
  Optional[String[0]] $task = undef,
3
24
  Optional[String[0]] $command = undef,
@@ -1,3 +1,24 @@
1
+ # @summary
2
+ # Run a task, command, or script on targets and aggregate the results as
3
+ # the list of targets for each value of a key in the results.
4
+ #
5
+ # This plan accepts an action and a list of targets. The action can be the name
6
+ # of a task, a script, or a command to run. It will run the action on the
7
+ # targets and aggregate the key/value pairs in each Result into a hash, mapping
8
+ # the keys to a hash of each distinct value and a list of targets returning that
9
+ # value.
10
+ #
11
+ # @param command
12
+ # The command to run. Mutually exclusive with script and task.
13
+ # @param script
14
+ # The path to the script to run. Mutually exclusive with command and task.
15
+ # @param task
16
+ # The name of the task to run. Mutually exclusive with command and script.
17
+ # @param targets
18
+ # The list of targets to run the action on.
19
+ # @param params
20
+ # A hash of parameters and options to pass to the `run_*` function
21
+ # associated with the action (e.g. run_task).
1
22
  plan aggregate::targets(
2
23
  Optional[String[0]] $task = undef,
3
24
  Optional[String[0]] $command = undef,
@@ -0,0 +1,31 @@
1
+ # @summary
2
+ # Tests that the provided Puppet Connect input data is complete, meaning that all consuming inventory targets are connectable.
3
+ #
4
+ # This plan should only be used as part of the copy-pastable "test input data"
5
+ # workflow specified in the Puppet Connect docs.
6
+ #
7
+ # @param targets
8
+ # The set of targets to test. Usually this should be 'all', the default.
9
+ #
10
+ # @return ResultSet the result of invoking the 'is connectable?' query on all
11
+ # the targets. Note that this query currently consists of running the 'echo'
12
+ # command.
13
+ #
14
+ plan puppet_connect::test_input_data(TargetSpec $targets = 'all') {
15
+ $targs = get_targets($targets)
16
+ $targs.each |$target| {
17
+ if $target.transport != 'ssh' and $target.transport != 'winrm' {
18
+ fail_plan("Inventory contains target ${target} with unsupported transport, must be ssh or winrm")
19
+ }
20
+ if $target.transport == 'ssh' {
21
+ # Disable SSH autoloading to prevent false positive results
22
+ # (input data is wrong but target is still connectable due
23
+ # to autoloaded config)
24
+ set_config($target, ['ssh', 'load-config'], false)
25
+ }
26
+ }
27
+ # The SSH/WinRM transports will report an 'unknown host' error for targets where
28
+ # 'host' is unknown so run_command's implementation will take care of raising that
29
+ # error for us.
30
+ return run_command('echo Connected', $targs)
31
+ }
@@ -1,3 +1,13 @@
1
+ # @summary
2
+ # Collect facts for the specified targets from PuppetDB and store them
3
+ # on the Targets.
4
+ #
5
+ # This plan accepts a list of targets to collect facts for from the configured
6
+ # PuppetDB connection. After collecting facts, they are stored on each target's
7
+ # Target object. The updated facts can then be accessed using `$target.facts`.
8
+ #
9
+ # @param targets
10
+ # The targets to collect facts for.
1
11
  plan puppetdb_fact(TargetSpec $targets) {
2
12
  $targs = get_targets($targets)
3
13
  $certnames = $targs.map |$target| { $target.host }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bolt
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.44.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-27 00:00:00.000000000 Z
11
+ date: 2021-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -609,12 +609,12 @@ files:
609
609
  - modules/aggregate/lib/puppet/functions/aggregate/nodes.rb
610
610
  - modules/aggregate/lib/puppet/functions/aggregate/targets.rb
611
611
  - modules/aggregate/plans/count.pp
612
- - modules/aggregate/plans/nodes.pp
613
612
  - modules/aggregate/plans/targets.pp
614
613
  - modules/canary/lib/puppet/functions/canary/merge.rb
615
614
  - modules/canary/lib/puppet/functions/canary/random_split.rb
616
615
  - modules/canary/lib/puppet/functions/canary/skip.rb
617
616
  - modules/canary/plans/init.pp
617
+ - modules/puppet_connect/plans/test_input_data.pp
618
618
  - modules/puppetdb_fact/plans/init.pp
619
619
  homepage: https://github.com/puppetlabs/bolt
620
620
  licenses:
@@ -1,36 +0,0 @@
1
- plan aggregate::nodes(
2
- Optional[String[0]] $task = undef,
3
- Optional[String[0]] $command = undef,
4
- Optional[String[0]] $script = undef,
5
- TargetSpec $nodes,
6
- Hash[String, Data] $params = {}
7
- ) {
8
-
9
- # Validation
10
- $type_count = [$task, $command, $script].reduce(0) |$acc, $v| {
11
- if ($v) {
12
- $acc + 1
13
- } else {
14
- $acc
15
- }
16
- }
17
-
18
- if ($type_count == 0) {
19
- fail_plan("Must specify a command, script, or task to run", 'aggregate/invalid-params')
20
- }
21
-
22
- if ($type_count > 1) {
23
- fail_plan("Must specify only one command, script, or task to run", 'aggregate/invalid-params')
24
- }
25
-
26
- $res = if ($task) {
27
- run_task($task, $nodes, $params)
28
- } elsif ($command) {
29
- run_command($command, $nodes, $params)
30
- } elsif ($script) {
31
- run_script($script, $nodes, $params)
32
- }
33
-
34
- return aggregate::nodes($res)
35
- }
36
-