Class: Bolt::Config
- Inherits:
-
Object
- Object
- Bolt::Config
- Defined in:
- lib/bolt/config.rb
Constant Summary collapse
- OPTIONS =
{ "apply_settings" => "A map of Puppet settings to use when applying Puppet code", "color" => "Whether to use colored output when printing messages to the console.", "compile-concurrency" => "The maximum number of simultaneous manifest block compiles.", "concurrency" => "The number of threads to use when executing on remote targets.", "format" => "The format to use when printing results. Options are `human` and `json`.", "hiera-config" => "The path to your Hiera config.", "inventoryfile" => "The path to a structured data inventory file used to refer to groups of "\ "targets on the command line and from plans.", "log" => "The configuration of the logfile output. Configuration can be set for "\ "`console` and the path to a log file, such as `~/.puppetlabs/bolt/debug.log`.", "modulepath" => "The module path for loading tasks and plan code. This is either an array "\ "of directories or a string containing a list of directories separated by the "\ "OS-specific PATH separator.", "plugin_hooks" => "Which plugins a specific hook should use.", "plugins" => "A map of plugins and their configuration data.", "puppetdb" => "A map containing options for configuring the Bolt PuppetDB client.", "puppetfile" => "A map containing options for the `bolt puppetfile install` command.", "save-rerun" => "Whether to update `.rerun.json` in the Bolt project directory. If "\ "your target names include passwords, set this value to `false` to avoid "\ "writing passwords to disk.", "transport" => "The default transport to use when the transport for a target is not "\ "specified in the URL or inventory.", "trusted-external-command" => "The path to an executable on the Bolt controller that can produce "\ "external trusted facts. **External trusted facts are experimental in both "\ "Puppet and Bolt and this API may change or be removed.**" }.freeze
- DEFAULT_OPTIONS =
{ "color" => true, "concurrency" => 100, "compile-concurrency" => "Number of cores", "format" => "human", "hiera-config" => "Boltdir/hiera.yaml", "inventoryfile" => "Boltdir/inventory.yaml", "modulepath" => ["Boltdir/modules", "Boltdir/site-modules", "Boltdir/site"], "save-rerun" => true }.freeze
- PUPPETFILE_OPTIONS =
{ "forge" => "A subsection that can have its own `proxy` setting to set an HTTP proxy for Forge operations "\ "only, and a `baseurl` setting to specify a different Forge host.", "proxy" => "The HTTP proxy to use for Git and Forge operations." }.freeze
- LOG_OPTIONS =
{ "append" => "Add output to an existing log file. Available only for logs output to a "\ "filepath.", "level" => "The type of information in the log. Either `debug`, `info`, `notice`, "\ "`warn`, or `error`." }.freeze
- DEFAULT_LOG_OPTIONS =
{ "append" => true, "level" => "`warn` for console, `notice` for file" }.freeze
- APPLY_SETTINGS =
{ "show_diff" => "Whether to log and report a contextual diff when files are being replaced. "\ "See [Puppet documentation](https://puppet.com/docs/puppet/latest/configuration.html#showdiff) "\ "for details" }.freeze
- DEFAULT_APPLY_SETTINGS =
{ "show_diff" => false }.freeze
Instance Attribute Summary collapse
-
#apply_settings ⇒ Object
Returns the value of attribute apply_settings.
-
#boltdir ⇒ Object
Returns the value of attribute boltdir.
-
#color ⇒ Object
Returns the value of attribute color.
-
#compile_concurrency ⇒ Object
Returns the value of attribute compile_concurrency.
-
#concurrency ⇒ Object
Returns the value of attribute concurrency.
-
#config_files ⇒ Object
readonly
Returns the value of attribute config_files.
-
#format ⇒ Object
Returns the value of attribute format.
-
#inventoryfile ⇒ Object
Returns the value of attribute inventoryfile.
-
#log ⇒ Object
Returns the value of attribute log.
- #modulepath ⇒ Object
-
#plugin_hooks ⇒ Object
Returns the value of attribute plugin_hooks.
-
#plugins ⇒ Object
Returns the value of attribute plugins.
-
#puppetdb ⇒ Object
Returns the value of attribute puppetdb.
-
#puppetfile_config ⇒ Object
Returns the value of attribute puppetfile_config.
-
#save_rerun ⇒ Object
Returns the value of attribute save_rerun.
-
#trace ⇒ Object
Returns the value of attribute trace.
-
#transport ⇒ Object
Returns the value of attribute transport.
-
#transports ⇒ Object
Returns the value of attribute transports.
-
#trusted_external ⇒ Object
Returns the value of attribute trusted_external.
-
#warnings ⇒ Object
readonly
Returns the value of attribute warnings.
Class Method Summary collapse
- .default ⇒ Object
- .from_boltdir(boltdir, overrides = {}) ⇒ Object
- .from_file(configfile, overrides = {}) ⇒ Object
- .load_defaults ⇒ Object
- .normalize_interpreters(interpreters) ⇒ Object
- .update_transport_hash(boltdir, existing, data) ⇒ Object
Instance Method Summary collapse
- #apply_overrides(options) ⇒ Object
- #casefold(path) ⇒ Object
-
#check_path_case(type, paths) ⇒ Object
Check if there is a case-insensitive match to the path.
- #deep_clone ⇒ Object
- #default_inventoryfile ⇒ Object
- #hiera_config ⇒ Object
-
#initialize(boltdir, config_data, overrides = {}) ⇒ Config
constructor
A new instance of Config.
- #matching_paths(paths) ⇒ Object
-
#merge_config_data(config_data) ⇒ Object
Merge configuration Precedence from highest to lowest is: project, user-level, system-wide.
- #normalize_log(target) ⇒ Object
- #overwrite_transport_data(transport, transports) ⇒ Object
- #puppetfile ⇒ Object
- #rerunfile ⇒ Object
- #transport_conf ⇒ Object
- #transport_data_get ⇒ Object
- #update_from_inventory(data) ⇒ Object
- #update_logs(logs) ⇒ Object
- #update_transports(data) ⇒ Object
- #validate ⇒ Object
Constructor Details
#initialize(boltdir, config_data, overrides = {}) ⇒ Config
Returns a new instance of Config.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/bolt/config.rb', line 151 def initialize(boltdir, config_data, overrides = {}) unless config_data.is_a?(Array) config_data = [{ filepath: boltdir.config_file, data: config_data }] end @logger = Logging.logger[self] @boltdir = boltdir @concurrency = 100 @compile_concurrency = Etc.nprocessors @transport = 'ssh' @format = 'human' @puppetdb = {} @color = true @save_rerun = true @puppetfile_config = {} @plugins = {} @plugin_hooks = {} @apply_settings = {} @warnings = [] # add an entry for the default console logger @log = { 'console' => {} } @transports = {} TRANSPORTS.each do |key, transport| @transports[key] = transport. end @config_files = config_data.map { |config| config[:filepath] } config_data = merge_config_data(config_data) update_from_file(config_data) apply_overrides(overrides) validate end |
Instance Attribute Details
#apply_settings ⇒ Object
Returns the value of attribute apply_settings.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def apply_settings @apply_settings end |
#boltdir ⇒ Object
Returns the value of attribute boltdir.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def boltdir @boltdir end |
#color ⇒ Object
Returns the value of attribute color.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def color @color end |
#compile_concurrency ⇒ Object
Returns the value of attribute compile_concurrency.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def compile_concurrency @compile_concurrency end |
#concurrency ⇒ Object
Returns the value of attribute concurrency.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def concurrency @concurrency end |
#config_files ⇒ Object (readonly)
Returns the value of attribute config_files.
40 41 42 |
# File 'lib/bolt/config.rb', line 40 def config_files @config_files end |
#format ⇒ Object
Returns the value of attribute format.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def format @format end |
#inventoryfile ⇒ Object
Returns the value of attribute inventoryfile.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def inventoryfile @inventoryfile end |
#log ⇒ Object
Returns the value of attribute log.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def log @log end |
#modulepath ⇒ Object
394 395 396 |
# File 'lib/bolt/config.rb', line 394 def modulepath @modulepath || @boltdir.modulepath end |
#plugin_hooks ⇒ Object
Returns the value of attribute plugin_hooks.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def plugin_hooks @plugin_hooks end |
#plugins ⇒ Object
Returns the value of attribute plugins.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def plugins @plugins end |
#puppetdb ⇒ Object
Returns the value of attribute puppetdb.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def puppetdb @puppetdb end |
#puppetfile_config ⇒ Object
Returns the value of attribute puppetfile_config.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def puppetfile_config @puppetfile_config end |
#save_rerun ⇒ Object
Returns the value of attribute save_rerun.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def save_rerun @save_rerun end |
#trace ⇒ Object
Returns the value of attribute trace.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def trace @trace end |
#transport ⇒ Object
Returns the value of attribute transport.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def transport @transport end |
#transports ⇒ Object
Returns the value of attribute transports.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def transports @transports end |
#trusted_external ⇒ Object
Returns the value of attribute trusted_external.
35 36 37 |
# File 'lib/bolt/config.rb', line 35 def trusted_external @trusted_external end |
#warnings ⇒ Object (readonly)
Returns the value of attribute warnings.
40 41 42 |
# File 'lib/bolt/config.rb', line 40 def warnings @warnings end |
Class Method Details
.default ⇒ Object
109 110 111 |
# File 'lib/bolt/config.rb', line 109 def self.default new(Bolt::Boltdir.new('.'), {}) end |
.from_boltdir(boltdir, overrides = {}) ⇒ Object
113 114 115 116 117 118 119 120 121 122 |
# File 'lib/bolt/config.rb', line 113 def self.from_boltdir(boltdir, overrides = {}) data = { filepath: boltdir.config_file, data: Bolt::Util.read_optional_yaml_hash(boltdir.config_file, 'config') } data = load_defaults.push(data).select { |config| config[:data]&.any? } new(boltdir, data, overrides) end |
.from_file(configfile, overrides = {}) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/bolt/config.rb', line 124 def self.from_file(configfile, overrides = {}) boltdir = Bolt::Boltdir.new(Pathname.new(configfile)..dirname) data = { filepath: boltdir.config_file, data: Bolt::Util.read_yaml_hash(configfile, 'config') } data = load_defaults.push(data).select { |config| config[:data]&.any? } new(boltdir, data, overrides) end |
.load_defaults ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/bolt/config.rb', line 136 def self.load_defaults # Lazy-load expensive gem code require 'win32/dir' if Bolt::Util.windows? system_path = if Bolt::Util.windows? Pathname.new(File.join(Dir::COMMON_APPDATA, 'PuppetLabs', 'bolt', 'etc', 'bolt.yaml')) else Pathname.new(File.join('/etc', 'puppetlabs', 'bolt', 'bolt.yaml')) end user_path = Pathname.new(File.(File.join('~', '.puppetlabs', 'etc', 'bolt', 'bolt.yaml'))) [{ filepath: system_path, data: Bolt::Util.read_optional_yaml_hash(system_path, 'config') }, { filepath: user_path, data: Bolt::Util.read_optional_yaml_hash(user_path, 'config') }] end |
.normalize_interpreters(interpreters) ⇒ Object
367 368 369 370 371 |
# File 'lib/bolt/config.rb', line 367 def self.normalize_interpreters(interpreters) Bolt::Util.walk_keys(interpreters) do |key| key.chars[0] == '.' ? key : '.' + key end end |
.update_transport_hash(boltdir, existing, data) ⇒ Object
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 |
# File 'lib/bolt/config.rb', line 348 def self.update_transport_hash(boltdir, existing, data) TRANSPORTS.each do |key, impl| if data[key.to_s] selected = impl.(data[key.to_s]) # Expand file paths relative to the Boltdir = %w[private-key cacert token-file] & selected.keys .each do |opt| selected[opt] = File.(selected[opt], boltdir) if selected[opt].is_a?(String) end existing[key] = Bolt::Util.deep_merge(existing[key], selected) end if existing[key]['interpreters'] existing[key]['interpreters'] = normalize_interpreters(existing[key]['interpreters']) end end end |
Instance Method Details
#apply_overrides(options) ⇒ Object
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'lib/bolt/config.rb', line 300 def apply_overrides() %i[concurrency transport format trace modulepath inventoryfile color].each do |key| send("#{key}=", [key]) if .key?(key) end @puppetfile = [:puppetfile] if .key?(:puppetfile) @save_rerun = [:'save-rerun'] if .key?(:'save-rerun') if [:debug] @log['console'][:level] = :debug end @compile_concurrency = [:'compile-concurrency'] if [:'compile-concurrency'] TRANSPORTS.each_key do |transport| # Get the options first since transport is modified in the next line = TRANSPORTS[transport]::OPTIONS.keys.map(&:to_sym) transport = @transports[transport] .each do |key| if [key] transport[key.to_s] = Bolt::Util.walk_keys([key], &:to_s) end end end if .key?(:ssl) # this defaults to true so we need to check the presence of the key @transports[:winrm]['ssl'] = [:ssl] end if .key?(:'ssl-verify') # this defaults to true so we need to check the presence of the key @transports[:winrm]['ssl-verify'] = [:'ssl-verify'] end if .key?(:'host-key-check') # this defaults to true so we need to check the presence of the key @transports[:ssh]['host-key-check'] = [:'host-key-check'] end end |
#casefold(path) ⇒ Object
454 455 456 457 458 |
# File 'lib/bolt/config.rb', line 454 def casefold(path) path.chars.map do |l| l =~ /[A-Za-z]/ ? "[#{l.upcase}#{l.downcase}]" : l end.join end |
#check_path_case(type, paths) ⇒ Object
Check if there is a case-insensitive match to the path
439 440 441 442 443 444 445 446 447 448 |
# File 'lib/bolt/config.rb', line 439 def check_path_case(type, paths) return if paths.nil? matches = matching_paths(paths) if matches.any? msg = "WARNING: Bolt is case sensitive when specifying a #{type}. Did you mean:\n" matches.each { |path| msg += " #{path}\n" } @logger.warn msg end end |
#deep_clone ⇒ Object
222 223 224 |
# File 'lib/bolt/config.rb', line 222 def deep_clone Bolt::Util.deep_clone(self) end |
#default_inventoryfile ⇒ Object
378 379 380 |
# File 'lib/bolt/config.rb', line 378 def default_inventoryfile @boltdir.inventory_file end |
#hiera_config ⇒ Object
386 387 388 |
# File 'lib/bolt/config.rb', line 386 def hiera_config @hiera_config || @boltdir.hiera_config end |
#matching_paths(paths) ⇒ Object
450 451 452 |
# File 'lib/bolt/config.rb', line 450 def matching_paths(paths) [*paths].map { |p| Dir.glob([p, casefold(p)]) }.flatten.uniq.reject { |p| [*paths].include?(p) } end |
#merge_config_data(config_data) ⇒ Object
Merge configuration Precedence from highest to lowest is: project, user-level, system-wide
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/bolt/config.rb', line 192 def merge_config_data(config_data) config_data.inject({}) do |acc, config| acc.merge(config[:data]) do |key, val1, val2| case key # Plugin config is shallow merged for each plugin when 'plugins' val1.merge(val2) { |_, v1, v2| v1.merge(v2) } # Transports are deep merged when *TRANSPORTS.keys.map(&:to_s) Bolt::Util.deep_merge(val1, val2) # Hash values are shallow mergeed when 'puppetdb', 'plugin_hooks', 'apply_settings', 'log' val1.merge(val2) # All other values are overwritten else val2 end end end end |
#normalize_log(target) ⇒ Object
226 227 228 229 230 |
# File 'lib/bolt/config.rb', line 226 def normalize_log(target) return target if target == 'console' target = target[5..-1] if target.start_with?('file:') 'file:' + File.(target, @boltdir.path) end |
#overwrite_transport_data(transport, transports) ⇒ Object
213 214 215 216 |
# File 'lib/bolt/config.rb', line 213 def overwrite_transport_data(transport, transports) @transport = transport @transports = transports end |
#puppetfile ⇒ Object
390 391 392 |
# File 'lib/bolt/config.rb', line 390 def puppetfile @puppetfile || @boltdir.puppetfile end |
#rerunfile ⇒ Object
382 383 384 |
# File 'lib/bolt/config.rb', line 382 def rerunfile @boltdir.rerunfile end |
#transport_conf ⇒ Object
373 374 375 376 |
# File 'lib/bolt/config.rb', line 373 def transport_conf { transport: @transport, transports: @transports } end |
#transport_data_get ⇒ Object
218 219 220 |
# File 'lib/bolt/config.rb', line 218 def transport_data_get { transport: @transport, transports: @transports } end |
#update_from_inventory(data) ⇒ Object
339 340 341 |
# File 'lib/bolt/config.rb', line 339 def update_from_inventory(data) update_transports(data) end |
#update_logs(logs) ⇒ Object
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/bolt/config.rb', line 232 def update_logs(logs) logs.each_pair do |k, v| log_name = normalize_log(k) @log[log_name] ||= {} log = @log[log_name] next unless v.is_a?(Hash) if v.key?('level') log[:level] = v['level'].to_s end if v.key?('append') log[:append] = v['append'] end end end |
#update_transports(data) ⇒ Object
343 344 345 346 |
# File 'lib/bolt/config.rb', line 343 def update_transports(data) self.class.update_transport_hash(@boltdir.path, @transports, data) @transport = data['transport'] if data.key?('transport') end |
#validate ⇒ Object
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 |
# File 'lib/bolt/config.rb', line 398 def validate @log.each_pair do |name, params| if params.key?(:level) && !Bolt::Logger.valid_level?(params[:level]) raise Bolt::ValidationError, "level of log #{name} must be one of: #{Bolt::Logger.levels.join(', ')}; received #{params[:level]}" end if params.key?(:append) && params[:append] != true && params[:append] != false raise Bolt::ValidationError, "append flag of log #{name} must be a Boolean, received #{params[:append]}" end end unless @concurrency.is_a?(Integer) && @concurrency > 0 raise Bolt::ValidationError, 'Concurrency must be a positive integer' end unless @compile_concurrency.is_a?(Integer) && @compile_concurrency > 0 raise Bolt::ValidationError, 'Compile concurrency must be a positive integer' end compile_limit = 2 * Etc.nprocessors unless @compile_concurrency < compile_limit raise Bolt::ValidationError, "Compilation is CPU-intensive, set concurrency less than #{compile_limit}" end unless %w[human json].include? @format raise Bolt::ValidationError, "Unsupported format: '#{@format}'" end Bolt::Util.validate_file('hiera-config', @hiera_config) if @hiera_config Bolt::Util.validate_file('trusted-external-command', @trusted_external) if @trusted_external unless @transport.nil? || Bolt::TRANSPORTS.include?(@transport.to_sym) raise UnknownTransportError, @transport end TRANSPORTS.each do |transport, impl| impl.validate(@transports[transport]) end end |