Class: Bolt::Config

Inherits:
Struct
  • Object
show all
Defined in:
lib/bolt/config.rb

Constant Summary collapse

DEFAULTS =
{
  concurrency: 100,
  'compile-concurrency': Concurrent.processor_count,
  transport: 'ssh',
  format: 'human',
  modulepath: [],
  puppetdb: {},
  color: true
}.freeze
TRANSPORT_OPTIONS =
%i[password run-as sudo-password extensions
private-key tty tmpdir user connect-timeout
cacert token-file service-url].freeze
TRANSPORT_DEFAULTS =
{
  'connect-timeout' => 10,
  'tty' => false
}.freeze
TRANSPORT_SPECIFIC_DEFAULTS =
{
  ssh: {
    'host-key-check' => true
  },
  winrm: {
    'ssl' => true,
    'ssl-verify' => true
  },
  pcp: {
    'task-environment' => 'production',
    'local-validation' => false
  },
  local: {}
}.freeze
BOLTDIR_NAME =
'Boltdir'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**kwargs) ⇒ Config

Returns a new instance of Config.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/bolt/config.rb', line 78

def initialize(**kwargs)
  super()
  @logger = Logging.logger[self]
  @pwd = kwargs.delete(:pwd)

  DEFAULTS.merge(kwargs).each { |k, v| self[k] = v }

  # add an entry for the default console logger
  self[:log] ||= {}
  self[:log]['console'] ||= {}

  self[:transports] ||= {}
  TRANSPORTS.each_key do |transport|
    self[:transports][transport] ||= {}

    TRANSPORT_DEFAULTS.each do |k, v|
      unless self[:transports][transport][k]
        self[:transports][transport][k] = v
      end
    end

    TRANSPORT_SPECIFIC_DEFAULTS[transport].each do |k, v|
      unless self[:transports][transport].key? k
        self[:transports][transport][k] = v
      end
    end
  end
end

Instance Attribute Details

#colorObject

Returns the value of attribute color

Returns:

  • (Object)

    the current value of color



27
28
29
# File 'lib/bolt/config.rb', line 27

def color
  @color
end

#concurrencyObject

Returns the value of attribute concurrency

Returns:

  • (Object)

    the current value of concurrency



27
28
29
# File 'lib/bolt/config.rb', line 27

def concurrency
  @concurrency
end

#formatObject

Returns the value of attribute format

Returns:

  • (Object)

    the current value of format



27
28
29
# File 'lib/bolt/config.rb', line 27

def format
  @format
end

#inventoryfileObject

Returns the value of attribute inventoryfile

Returns:

  • (Object)

    the current value of inventoryfile



27
28
29
# File 'lib/bolt/config.rb', line 27

def inventoryfile
  @inventoryfile
end

#logObject

Returns the value of attribute log

Returns:

  • (Object)

    the current value of log



27
28
29
# File 'lib/bolt/config.rb', line 27

def log
  @log
end

#modulepathObject

Returns the value of attribute modulepath

Returns:

  • (Object)

    the current value of modulepath



27
28
29
# File 'lib/bolt/config.rb', line 27

def modulepath
  @modulepath
end

#puppetdbObject

Returns the value of attribute puppetdb

Returns:

  • (Object)

    the current value of puppetdb



27
28
29
# File 'lib/bolt/config.rb', line 27

def puppetdb
  @puppetdb
end

#traceObject

Returns the value of attribute trace

Returns:

  • (Object)

    the current value of trace



27
28
29
# File 'lib/bolt/config.rb', line 27

def trace
  @trace
end

#transportObject

Returns the value of attribute transport

Returns:

  • (Object)

    the current value of transport



27
28
29
# File 'lib/bolt/config.rb', line 27

def transport
  @transport
end

#transportsObject

Returns the value of attribute transports

Returns:

  • (Object)

    the current value of transports



27
28
29
# File 'lib/bolt/config.rb', line 27

def transports
  @transports
end

Instance Method Details

#boltdirObject



168
169
170
# File 'lib/bolt/config.rb', line 168

def boltdir
  @boltdir ||= find_boltdir(pwd) || default_boltdir
end

#deep_cloneObject



107
108
109
# File 'lib/bolt/config.rb', line 107

def deep_clone
  Bolt::Util.deep_clone(self)
end

#default_boltdirObject



172
173
174
# File 'lib/bolt/config.rb', line 172

def default_boltdir
  File.expand_path(File.join('~', '.puppetlabs', 'bolt'))
end

#default_configObject



195
196
197
198
# File 'lib/bolt/config.rb', line 195

def default_config
  path = File.join(boltdir, 'bolt.yaml')
  File.exist?(path) ? path : legacy_conf
end

#default_hieraObject



204
205
206
# File 'lib/bolt/config.rb', line 204

def default_hiera
  File.join(boltdir, 'hiera.yaml')
end

#default_inventoryObject



200
201
202
# File 'lib/bolt/config.rb', line 200

def default_inventory
  File.join(boltdir, 'inventory.yaml')
end

#default_modulepathObject



176
177
178
# File 'lib/bolt/config.rb', line 176

def default_modulepath
  [File.join(boltdir, "modules")]
end

#find_boltdir(dir) ⇒ Object



153
154
155
156
157
158
159
160
161
162
# File 'lib/bolt/config.rb', line 153

def find_boltdir(dir)
  path = dir
  boltdir = nil
  while boltdir.nil? && path && path != File.dirname(path)
    maybe_boltdir = File.join(path, BOLTDIR_NAME)
    boltdir = maybe_boltdir if File.directory?(maybe_boltdir)
    path = File.dirname(path)
  end
  boltdir
end

#legacy_confObject

TODO: This is deprecated in 0.21.0 and can be removed in release 0.22.0.



181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/bolt/config.rb', line 181

def legacy_conf
  return @legacy_conf if defined?(@legacy_conf)
  root_path = File.expand_path(File.join('~', '.puppetlabs'))
  legacy_paths = [File.join(root_path, 'bolt.yaml'), File.join(root_path, 'bolt.yml')]
  @legacy_conf = legacy_paths.find { |path| File.exist?(path) }
  @legacy_conf ||= legacy_paths[0]
  if @legacy_conf
    correct_path = File.join(default_boltdir, 'bolt.yaml')
    msg = "Found configfile at deprecated location #{@legacy_conf}. Global config should be in #{correct_path}"
    @logger.warn(msg)
  end
  @legacy_conf
end

#load_file(path) ⇒ Object



257
258
259
260
261
# File 'lib/bolt/config.rb', line 257

def load_file(path)
  data = Bolt::Util.read_config_file(path, [default_config], 'config')
  update_from_file(data) if data
  validate_hiera_conf(data ? data['hiera-config'] : nil)
end

#normalize_log(target) ⇒ Object



111
112
113
114
115
# File 'lib/bolt/config.rb', line 111

def normalize_log(target)
  return target if target == 'console'
  target = target[5..-1] if target.start_with?('file:')
  'file:' + File.expand_path(target)
end

#pwdObject



164
165
166
# File 'lib/bolt/config.rb', line 164

def pwd
  @pwd ||= Dir.pwd
end

#transport_confObject



271
272
273
274
# File 'lib/bolt/config.rb', line 271

def transport_conf
  { transport: self[:transport],
    transports: self[:transports] }
end

#update(options) ⇒ Object

The order in which config is processed is important



251
252
253
254
255
# File 'lib/bolt/config.rb', line 251

def update(options)
  update_from_defaults
  load_file(options[:configfile])
  update_from_cli(options)
end

#update_from_cli(options) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/bolt/config.rb', line 208

def update_from_cli(options)
  %i[concurrency compile-concurrency transport format trace modulepath inventoryfile color].each do |key|
    self[key] = options[key] if options.key?(key)
  end

  if options[:debug]
    self[:log]['console'][:level] = :debug
  elsif options[:verbose]
    self[:log]['console'][:level] = :info
  end

  TRANSPORTS.each_key do |transport|
    transport = self[:transports][transport]
    TRANSPORT_OPTIONS.each do |key|
      if options[key]
        transport[key.to_s] = Bolt::Util.walk_keys(options[key], &:to_s)
      end
    end
  end

  if options.key?(:ssl) # this defaults to true so we need to check the presence of the key
    self[:transports][:winrm]['ssl'] = options[:ssl]
  end

  if options.key?(:'ssl-verify') # this defaults to true so we need to check the presence of the key
    self[:transports][:winrm]['ssl-verify'] = options[:'ssl-verify']
  end

  if options.key?(:'host-key-check') # this defaults to true so we need to check the presence of the key
    self[:transports][:ssh]['host-key-check'] = options[:'host-key-check']
  end
end

#update_from_defaultsObject

Defaults that do not vary based on boltdir should not be included here.

Defaults which are treated differently from specified values like ‘inventoryfile’ cannot be included here or they will not be handled correctly.



245
246
247
248
# File 'lib/bolt/config.rb', line 245

def update_from_defaults
  self[:modulepath] = default_modulepath
  self[:'hiera-config'] = default_hiera
end

#update_from_inventory(data) ⇒ Object



263
264
265
266
267
268
269
# File 'lib/bolt/config.rb', line 263

def update_from_inventory(data)
  update_from_file(data)

  if data['transport']
    self[:transport] = data['transport']
  end
end

#validateObject



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/bolt/config.rb', line 280

def validate
  self[: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 self[:concurrency].is_a?(Integer) && self[:concurrency] > 0
    raise Bolt::ValidationError, 'Concurrency must be a positive integer'
  end

  unless self[:'compile-concurrency'].is_a?(Integer) && self[:'compile-concurrency'] > 0
    raise Bolt::ValidationError, 'Compile concurrency must be a positive integer'
  end

  compile_limit = 2 * Concurrent.processor_count
  unless self[:'compile-concurrency'] < compile_limit
    raise Bolt::ValidationError, "Compilation is CPU-intensive, set concurrency less than #{compile_limit}"
  end

  unless %w[human json].include? self[:format]
    raise Bolt::ValidationError, "Unsupported format: '#{self[:format]}'"
  end

  unless self[:transport].nil? || Bolt::TRANSPORTS.include?(self[:transport].to_sym)
    raise UnknownTransportError, self[:transport]
  end

  TRANSPORTS.each do |transport, impl|
    impl.validate(self[:transports][transport])
  end
end

#validate_hiera_conf(path) ⇒ Object



276
277
278
# File 'lib/bolt/config.rb', line 276

def validate_hiera_conf(path)
  Bolt::Util.read_config_file(path, [default_hiera], 'hiera-config')
end