bolt 2.2.0 → 2.3.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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7875970096b75c44b55dc718b1586f8b360e11041198893207c9c146649b89b7
4
- data.tar.gz: f81ded40f2a72fd9e83b0f63f1ea0d7d4a5148589d1bdb65de82c023335ed611
3
+ metadata.gz: cbe3b4d356f06d8d5505a490420103678f6cca7551b66eb01d6bdf3e4ab7b41a
4
+ data.tar.gz: 7d785e1159fea305c370bc5e18b868aa63a176a6666c3d3c469833d310a90729
5
5
  SHA512:
6
- metadata.gz: 2e4c8c1857380c9177284ce567228058f2bd516541020c7926ebc7ea3af23ab89525f5a3d146b3c40a62721e89401b960e3b7071b3473094caaed00b4225bbb3
7
- data.tar.gz: a299f639f5e211c4cee1d3dbca7fb3a5ce4b5a770840c8a7e2da1f620a92b7045637113522fe6e0856fe70a7d3e286d5d5563fae6c53bfc852ec893e87250b86
6
+ metadata.gz: b7c494d958d4dcbbe61da8dbf9d6a7ab2712ad9e19f91f9917a0e8ec4c95fb9fe463fae868027529c5b7ef51ca410d9d16a22a120bbd0f275e7474c569606041
7
+ data.tar.gz: 62facbdda41d27006d5f8ece2f79deab5f9df8e2c1fc48890029094348847014e7682bb2586561159230bcaf390eda6d216ab4f1d275aa25e8e89a0a2bb27e06
data/Puppetfile CHANGED
@@ -24,16 +24,16 @@ mod 'puppetlabs-zone_core', '1.0.3'
24
24
  # Useful additional modules
25
25
  mod 'puppetlabs-package', '1.1.0'
26
26
  mod 'puppetlabs-puppet_conf', '0.6.0'
27
- mod 'puppetlabs-python_task_helper', '0.3.0'
27
+ mod 'puppetlabs-python_task_helper', '0.4.0'
28
28
  mod 'puppetlabs-reboot', '3.0.0'
29
- mod 'puppetlabs-ruby_task_helper', '0.4.0'
29
+ mod 'puppetlabs-ruby_task_helper', '0.5.1'
30
30
  mod 'puppetlabs-ruby_plugin_helper', '0.1.0'
31
31
 
32
32
  # Plugin modules
33
33
  mod 'puppetlabs-azure_inventory', '0.3.0'
34
34
  mod 'puppetlabs-terraform', '0.4.0'
35
35
  mod 'puppetlabs-vault', '0.3.0'
36
- mod 'puppetlabs-aws_inventory', '0.4.0'
36
+ mod 'puppetlabs-aws_inventory', '0.5.0'
37
37
  mod 'puppetlabs-yaml', '0.2.0'
38
38
 
39
39
  # If we don't list these modules explicitly, r10k will purge them
@@ -28,8 +28,12 @@ module Bolt
28
28
 
29
29
  def self.build_client
30
30
  logger = Logging.logger[self]
31
- config_file = File.expand_path('~/.puppetlabs/bolt/analytics.yaml')
32
- config = load_config(config_file, logger)
31
+ begin
32
+ config_file = File.expand_path('~/.puppetlabs/bolt/analytics.yaml')
33
+ config = load_config(config_file, logger)
34
+ rescue ArgumentError
35
+ config = { 'disabled' => true }
36
+ end
33
37
 
34
38
  if config['disabled'] || ENV['BOLT_DISABLE_ANALYTICS']
35
39
  logger.debug "Analytics opt-out is set, analytics will be disabled"
@@ -76,7 +76,7 @@ module Bolt
76
76
  when 'project'
77
77
  case action
78
78
  when 'init'
79
- { flags: OPTIONS[:global],
79
+ { flags: OPTIONS[:global] + %w[modules],
80
80
  banner: PROJECT_INIT_HELP }
81
81
  when 'migrate'
82
82
  { flags: OPTIONS[:global] + %w[inventoryfile boltdir configfile],
@@ -391,6 +391,8 @@ module Bolt
391
391
  bolt project init
392
392
  Create a new Bolt project at a specified path.
393
393
  bolt project init ~/path/to/project
394
+ Create a new Bolt project with existing modules.
395
+ bolt project init --modules puppetlabs-apt,puppetlabs-ntp
394
396
  HELP
395
397
 
396
398
  PROJECT_MIGRATE_HELP = <<~HELP
@@ -763,6 +765,13 @@ module Bolt
763
765
  @options[:trace] = true
764
766
  end
765
767
 
768
+ separator "\nADDITIONAL OPTIONS"
769
+ define('--modules MODULES',
770
+ 'A comma-separated list of modules to install from the Puppet Forge',
771
+ 'when initializing a project. Resolves and installs all dependencies.') do |modules|
772
+ @options[:modules] = modules.split(',')
773
+ end
774
+
766
775
  separator "\nGLOBAL OPTIONS"
767
776
  define('-h', '--help', 'Display help') do |_|
768
777
  @options[:help] = true
data/lib/bolt/cli.rb CHANGED
@@ -564,19 +564,116 @@ module Bolt
564
564
  0
565
565
  end
566
566
 
567
+ # Initializes a specified directory as a Bolt project and installs any modules
568
+ # specified by the user, along with their dependencies
567
569
  def initialize_project
568
- path = File.expand_path(options[:object] || Dir.pwd)
569
- FileUtils.mkdir_p(path)
570
- ok = FileUtils.touch(File.join(path, 'bolt.yaml'))
570
+ boltdir = Pathname.new(File.expand_path(options[:object] || Dir.pwd))
571
+ config = boltdir + 'bolt.yaml'
572
+ puppetfile = boltdir + 'Puppetfile'
573
+ modulepath = [boltdir + 'modules']
574
+
575
+ # If modules were specified, first check if there is already a Puppetfile at the project
576
+ # directory, erroring if there is. If there is no Puppetfile, generate the Puppetfile
577
+ # content by resolving the specified modules and all their dependencies.
578
+ # We generate the Puppetfile first so that any errors in resolving modules and their
579
+ # dependencies are caught early and do not create a project directory.
580
+ if options[:modules]
581
+ if puppetfile.exist?
582
+ raise Bolt::CLIError,
583
+ "Found existing Puppetfile at #{puppetfile}, unable to initialize project with "\
584
+ "#{options[:modules].join(', ')}"
585
+ else
586
+ puppetfile_specs = resolve_puppetfile_specs
587
+ end
588
+ end
571
589
 
572
- result = if ok
573
- "Successfully created Bolt project directory at #{path}"
574
- else
575
- "Could not create Bolt project directory at #{path}"
576
- end
577
- outputter.print_message result
590
+ # Warn the user if the project directory already exists. We don't error here since users
591
+ # might not have installed any modules yet.
592
+ if config.exist?
593
+ @logger.warn "Found existing project directory at #{boltdir}"
594
+ end
578
595
 
579
- ok ? 0 : 1
596
+ # Create the project directory
597
+ FileUtils.mkdir_p(boltdir)
598
+
599
+ # Bless the project directory as a boltdir
600
+ if FileUtils.touch(config)
601
+ outputter.print_message "Successfully created Bolt project at #{boltdir}"
602
+ else
603
+ raise Bolt::FileError.new("Could not create Bolt project directory at #{boltdir}", nil)
604
+ end
605
+
606
+ # Write the generated Puppetfile to the fancy new boltdir
607
+ if puppetfile_specs
608
+ File.write(puppetfile, puppetfile_specs.join("\n"))
609
+ outputter.print_message "Successfully created Puppetfile at #{puppetfile}"
610
+ # Install the modules from our shiny new Puppetfile
611
+ if install_puppetfile({}, puppetfile, modulepath)
612
+ outputter.print_message "Successfully installed #{options[:modules].join(', ')}"
613
+ else
614
+ raise Bolt::CLIError, "Could not install #{options[:modules].join(', ')}"
615
+ end
616
+ end
617
+
618
+ 0
619
+ end
620
+
621
+ # Resolves Puppetfile specs from user-specified modules and dependencies resolved
622
+ # by the puppetfile-resolver gem.
623
+ def resolve_puppetfile_specs
624
+ require 'puppetfile-resolver'
625
+
626
+ # Build the document model from the module names, defaulting to the latest version of each module
627
+ model = PuppetfileResolver::Puppetfile::Document.new('')
628
+ options[:modules].each do |mod_name|
629
+ model.add_module(
630
+ PuppetfileResolver::Puppetfile::ForgeModule.new(mod_name).tap { |mod| mod.version = :latest }
631
+ )
632
+ end
633
+
634
+ # Make sure the Puppetfile model is valid
635
+ unless model.valid?
636
+ raise Bolt::ValidationError,
637
+ "Unable to resolve dependencies for #{options[:modules].join(', ')}"
638
+ end
639
+
640
+ # Create the resolver using the Puppetfile model. nil disables Puppet version restrictions.
641
+ resolver = PuppetfileResolver::Resolver.new(model, nil)
642
+
643
+ # Configure and resolve the dependency graph
644
+ result = resolver.resolve(
645
+ cache: nil,
646
+ ui: nil,
647
+ module_paths: [],
648
+ allow_missing_modules: true
649
+ )
650
+
651
+ # Validate that the modules exist
652
+ missing_graph = result.specifications.select do |_name, spec|
653
+ spec.instance_of? PuppetfileResolver::Models::MissingModuleSpecification
654
+ end
655
+
656
+ if missing_graph.any?
657
+ titles = model.modules.each_with_object({}) do |mod, acc|
658
+ acc[mod.name] = mod.title
659
+ end
660
+
661
+ names = titles.values_at(*missing_graph.keys)
662
+ plural = names.count == 1 ? '' : 's'
663
+
664
+ raise Bolt::ValidationError,
665
+ "Unknown module name#{plural} #{names.join(', ')}"
666
+ end
667
+
668
+ # Filter the dependency graph to only include module specifications
669
+ spec_graph = result.specifications.select do |_name, spec|
670
+ spec.instance_of? PuppetfileResolver::Models::ModuleSpecification
671
+ end
672
+
673
+ # Map specification models to a Puppetfile specification
674
+ spec_graph.values.map do |spec|
675
+ "mod '#{spec.owner}-#{spec.name}', '#{spec.version}'"
676
+ end
580
677
  end
581
678
 
582
679
  def migrate_project
data/lib/bolt/config.rb CHANGED
@@ -137,10 +137,15 @@ module Bolt
137
137
  else
138
138
  Pathname.new(File.join('/etc', 'puppetlabs', 'bolt', 'bolt.yaml'))
139
139
  end
140
- user_path = Pathname.new(File.expand_path(File.join('~', '.puppetlabs', 'etc', 'bolt', 'bolt.yaml')))
141
-
142
- [{ filepath: system_path, data: Bolt::Util.read_optional_yaml_hash(system_path, 'config') },
143
- { filepath: user_path, data: Bolt::Util.read_optional_yaml_hash(user_path, 'config') }]
140
+ user_path = begin
141
+ Pathname.new(File.expand_path(File.join('~', '.puppetlabs', 'etc', 'bolt', 'bolt.yaml')))
142
+ rescue ArgumentError
143
+ nil
144
+ end
145
+
146
+ confs = [{ filepath: system_path, data: Bolt::Util.read_optional_yaml_hash(system_path, 'config') }]
147
+ confs << { filepath: user_path, data: Bolt::Util.read_optional_yaml_hash(user_path, 'config') } if user_path
148
+ confs
144
149
  end
145
150
 
146
151
  def initialize(boltdir, config_data, overrides = {})
@@ -8,6 +8,8 @@ module Bolt
8
8
  module Transport
9
9
  class WinRM < Base
10
10
  OPTIONS = {
11
+ "basic-auth-only" => { type: TrueClass,
12
+ desc: "Force basic authentication. This option is only available when using SSL." },
11
13
  "cacert" => { type: String,
12
14
  desc: "The path to the CA certificate." },
13
15
  "connect-timeout" => { type: Integer,
@@ -50,6 +52,7 @@ module Bolt
50
52
  }.freeze
51
53
 
52
54
  DEFAULTS = {
55
+ "basic-auth-only" => false,
53
56
  "connect-timeout" => 10,
54
57
  "ssl" => true,
55
58
  "ssl-verify" => true,
@@ -70,6 +73,10 @@ module Bolt
70
73
  end
71
74
  end
72
75
 
76
+ if !@config['ssl'] && @config['basic-auth-only']
77
+ raise Bolt::ValidationError, "Basic auth is only allowed when using SSL"
78
+ end
79
+
73
80
  if @config['interpreters']
74
81
  @config['interpreters'] = normalize_interpreters(@config['interpreters'])
75
82
  end
@@ -49,6 +49,7 @@ module Bolt
49
49
  password: target.options['realm'] ? 'dummy' : target.password,
50
50
  retry_limit: 1,
51
51
  transport: transport,
52
+ basic_auth_only: target.options['basic-auth-only'],
52
53
  ca_trust_path: cacert,
53
54
  realm: target.options['realm'],
54
55
  no_ssl_peer_verification: !target.options['ssl-verify'] }
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.2.0'
4
+ VERSION = '2.3.0'
5
5
  end
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.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-10 00:00:00.000000000 Z
11
+ date: 2020-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -212,6 +212,20 @@ dependencies:
212
212
  - - "~>"
213
213
  - !ruby/object:Gem::Version
214
214
  version: '2.3'
215
+ - !ruby/object:Gem::Dependency
216
+ name: puppetfile-resolver
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - "~>"
220
+ - !ruby/object:Gem::Version
221
+ version: 0.1.0
222
+ type: :runtime
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - "~>"
227
+ - !ruby/object:Gem::Version
228
+ version: 0.1.0
215
229
  - !ruby/object:Gem::Dependency
216
230
  name: r10k
217
231
  requirement: !ruby/object:Gem::Requirement