lib/bolt/config.rb in bolt-2.37.0 vs lib/bolt/config.rb in bolt-2.38.0

- old
+ new

@@ -5,11 +5,11 @@ require 'pathname' require 'bolt/project' require 'bolt/logger' require 'bolt/util' require 'bolt/config/options' -require 'bolt/config/validator' +require 'bolt/validator' module Bolt class UnknownTransportError < Bolt::Error def initialize(transport, uri = nil) msg = uri.nil? ? "Unknown transport #{transport}" : "Unknown transport #{transport} found for #{uri}" @@ -41,11 +41,11 @@ else c = Bolt::Util.read_optional_yaml_hash(project.config_file, 'config') # Validate the config against the schema. This will raise a single error # with all validation errors. - Validator.new.tap do |validator| + Bolt::Validator.new.tap do |validator| validator.validate(c, bolt_schema, project.config_file.to_s) validator.warnings.each { |warning| logs << { warn: warning } } validator.deprecations.each do |dep| @@ -54,11 +54,10 @@ end logs << { debug: "Loaded configuration from #{project.config_file}" } if File.exist?(project.config_file) c end - data = load_defaults(project).push( filepath: project.config_file, data: conf, logs: logs, deprecations: deprecations @@ -77,11 +76,11 @@ else c = Bolt::Util.read_yaml_hash(configfile, 'config') # Validate the config against the schema. This will raise a single error # with all validation errors. - Validator.new.tap do |validator| + Bolt::Validator.new.tap do |validator| validator.validate(c, bolt_schema, project.config_file.to_s) validator.warnings.each { |warning| logs << { warn: warning } } validator.deprecations.each do |dep| @@ -101,26 +100,40 @@ ) new(project, data, overrides) end - def self.defaults_schema - base = OPTIONS.slice(*BOLT_DEFAULTS_OPTIONS) - inventory = INVENTORY_OPTIONS.each_with_object({}) do |(option, definition), acc| + # Builds a hash of definitions for transport configuration. + # + def self.transport_definitions + INVENTORY_OPTIONS.each_with_object({}) do |(option, definition), acc| acc[option] = TRANSPORT_CONFIG.key?(option) ? definition.merge(TRANSPORT_CONFIG[option].schema) : definition end + end - base['inventory-config'][:properties] = inventory - base + # Builds the schema for bolt-defaults.yaml used by the validator. + # + def self.defaults_schema + schema = { + type: Hash, + properties: BOLT_DEFAULTS_OPTIONS.map { |opt| [opt, _ref: opt] }.to_h, + definitions: OPTIONS.merge(transport_definitions) + } + + schema[:definitions]['inventory-config'][:properties] = transport_definitions + + schema end + # Builds the schema for bolt.yaml used by the validator. + # def self.bolt_schema - inventory = INVENTORY_OPTIONS.each_with_object({}) do |(option, definition), acc| - acc[option] = TRANSPORT_CONFIG.key?(option) ? definition.merge(TRANSPORT_CONFIG[option].schema) : definition - end - - OPTIONS.slice(*BOLT_OPTIONS).merge(inventory) + { + type: Hash, + properties: (BOLT_OPTIONS + INVENTORY_OPTIONS.keys).map { |opt| [opt, _ref: opt] }.to_h, + definitions: OPTIONS.merge(transport_definitions) + } end def self.system_path if Bolt::Util.windows? Pathname.new(File.join(ENV['ALLUSERSPROFILE'], 'PuppetLabs', 'bolt', 'etc')) @@ -152,11 +165,11 @@ ) end # Validate the config against the schema. This will raise a single error # with all validation errors. - Validator.new.tap do |validator| + Bolt::Validator.new.tap do |validator| validator.validate(data, defaults_schema, filepath) validator.warnings.each { |warning| logs << { warn: warning } } validator.deprecations.each do |dep| @@ -219,11 +232,11 @@ msg: "Configuration file #{filepath} is deprecated and will be removed in Bolt 3.0. "\ "See https://pup.pt/update-bolt-config for how to update to the latest Bolt practices." }] # Validate the config against the schema. This will raise a single error # with all validation errors. - Validator.new.tap do |validator| + Bolt::Validator.new.tap do |validator| validator.validate(data, bolt_schema, filepath) validator.warnings.each { |warning| logs << { warn: warning } } validator.deprecations.each do |dep| @@ -281,16 +294,18 @@ 'color' => true, 'compile-concurrency' => Etc.nprocessors, 'concurrency' => default_concurrency, 'format' => 'human', 'log' => { 'console' => {} }, + 'module-install' => {}, 'plugin-hooks' => {}, 'plugin_hooks' => {}, 'plugins' => {}, 'puppetdb' => {}, 'puppetfile' => {}, 'save-rerun' => true, + 'spinner' => true, 'transport' => 'ssh' } if project.path.directory? default_data['log']['bolt-debug.log'] = { @@ -351,11 +366,11 @@ end overrides['trace'] = opts['trace'] if opts.key?('trace') # Validate the overrides - Validator.new.validate(overrides, OPTIONS, 'command line') + Bolt::Validator.new.validate(overrides, self.class.bolt_schema, 'command line') overrides end # Merge configuration from all sources into a single hash. Precedence from lowest to highest: @@ -406,11 +421,11 @@ %w[hiera-config inventoryfile trusted-external-command].each do |opt| @data[opt] = File.expand_path(@data[opt], @project.path) if @data.key?(opt) end # Filter hashes to only include valid options - %w[apply-settings apply_settings puppetfile].each do |opt| + %w[apply-settings apply_settings module-install puppetfile].each do |opt| @data[opt] = @data[opt].slice(*OPTIONS.dig(opt, :properties).keys) end end private def normalize_log(target) @@ -495,10 +510,29 @@ end unless TRANSPORT_CONFIG.include?(transport) raise UnknownTransportError, transport end + + # Warn the user how they should be using the 'puppetfile' or + # 'module-install' config options. We don't error here since these + # settings can be set at the user or system level. + if @project.modules && puppetfile_config.any? && module_install.empty? + command = Bolt::Util.powershell? ? 'Update-BoltProject' : 'bolt project migrate' + @logs << { warn: "Detected configuration for 'puppetfile'. This setting is not "\ + "used when 'modules' is configured. Use 'module-install' instead. "\ + "To automatically update your project configuration, run '#{command}'." } + elsif @project.modules.nil? && puppetfile_config.empty? && module_install.any? + @logs << { warn: "Detected configuration for 'module-install'. This setting is not "\ + "used when 'modules' is not configured. Use 'puppetfile' instead." } + elsif @project.modules && puppetfile_config.any? && module_install.any? + @logs << { warn: "Detected configuration for 'puppetfile' and 'module-install'. Using "\ + "configuration for 'module-install' because 'modules' is also configured." } + elsif @project.modules.nil? && puppetfile_config.any? && module_install.any? + @logs << { warn: "Detected configuration for 'puppetfile' and 'module-install'. Using "\ + "configuration for 'puppetfile' because 'modules' is not configured." } + end end def default_inventoryfile @project.inventory_file end @@ -563,10 +597,14 @@ def save_rerun @data['save-rerun'] end + def spinner + @data['spinner'] + end + def inventoryfile @data['inventoryfile'] end def compile_concurrency @@ -615,9 +653,13 @@ end end def transport @data['transport'] + end + + def module_install + @project.module_install || @data['module-install'] end # Check if there is a case-insensitive match to the path def check_path_case(type, paths) return if paths.nil?