Class: Locd::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/locd/config.rb,
lib/locd/config/types.rb

Overview

A hash-like container providing access to a layered tree of config values sourced from YAML files and ENV vars.

Keys

Config keys are arrays of strings that

Defined Under Namespace

Modules: Types Classes: FileLoad

Constant Summary collapse

DEFAULT_CONFIG_PATH =

Absolute path to the default config file (//config/default.yml).

Has to be defined as a constant because no other config is loaded before it and it contains the ENV var prefix.

Locd::ROOT / 'config' / 'default.yml'
DEV_CONFIG_PATH =

Absolute path to the dev override config, which will be loaded last if it exists.

Locd::ROOT / 'dev' / 'config.yml'
KEY_SEPARATOR =

What to split string keys into key path segments on.

'.'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(default_config_path: DEFAULT_CONFIG_PATH, dev_config_path: DEV_CONFIG_PATH) ⇒ Config

Instantiate a new Locd::Config.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/locd/config.rb', line 106

def initialize  default_config_path: DEFAULT_CONFIG_PATH,
                dev_config_path: DEV_CONFIG_PATH
  @default_config_path = default_config_path.to_pn
  @dev_config_path = dev_config_path.to_pn
  
  @file_loads = []
  @from_files = {}
  
  begin
    load_file! default_config_path, name: :default
  rescue StandardError => error
    logger.error "Failed to load default config!", error
  end
  
  begin
    if user_config_path.exist?
      load_file! user_config_path, name: :user
    end
  rescue Exception => error
    logger.error "Failed to load user config!", error
  end
  
  begin
    if dev_config_path && dev_config_path.exist?
      load_file! dev_config_path, name: :dev
    end
  rescue Exception => error
    logger.error "Failed to load dev config!", error
  end
end

Instance Attribute Details

#default_config_pathPathname (readonly)

Absolute path to the built-in default configuration file in use.



92
93
94
# File 'lib/locd/config.rb', line 92

def default_config_path
  @default_config_path
end

#file_loadsArray<FileLoad> (readonly)

TODO document file_loads attribute.



99
100
101
# File 'lib/locd/config.rb', line 99

def file_loads
  @file_loads
end

Class Method Details

.key_path_for(*key) ⇒ Object



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

def self.key_path_for *key
  key.flat_map { |k| k.to_s.split KEY_SEPARATOR }
end

Instance Method Details

#[]=(*key, value) ⇒ Object

Proxy to #set orthogonal to #[] / #get (though in this case we need to do a little more work than an alias on account of how #[]= handled keyword args).

Examples:

Single string key

Locd.config[ 'cli.bash_comp.log.level' ] = :debug

List key

Locd.config[ :cli, :bash_comp, :log, :level ] = :debug

Checking the type

Locd.config[ 'home', type: t.abs_path ] = user_input


278
279
280
281
282
283
284
285
286
287
# File 'lib/locd/config.rb', line 278

def []= *key, value
  if Hash === key[-1]
    kwds = key[-1]
    key = key[0..-2]
  else
    kwds = {}
  end
  
  set *key, value, **kwds
end

#cli_ARGV_looks_like_bash_comp?Boolean

Does ARGV look like we're executing Bash completion?

We want to change how we're logging during Bash completion runs.



351
352
353
# File 'lib/locd/config.rb', line 351

def cli_ARGV_looks_like_bash_comp?
  ARGV[0] == 'bash-complete'
end

#cli_log_configHash<Symbol, ] @todo Document return value.

Get the logging config, taking account of the Bash completion environment.

Output from this



390
391
392
393
394
395
396
397
# File 'lib/locd/config.rb', line 390

def cli_log_config
  {
    application: get( 'cli.log.application' ),
    level: cli_log_level,
    dest: cli_log_dest,
    sync: true
  }
end

#cli_log_dest$stderr



369
370
371
372
373
374
375
376
377
378
379
380
# File 'lib/locd/config.rb', line 369

def cli_log_dest
  dest = if cli_ARGV_looks_like_bash_comp?
    get 'cli.bash_comp.log.dest'
  else
    get 'cli.log.dest'
  end
  
  {
    **( IO === dest ? { io: dest } : { file_name: dest.to_s } ),
    formatter: NRSER::Log::Formatters::Color.new,
  }
end

#cli_log_levelSymbol

Level to log at when CLI'ing.



361
362
363
364
# File 'lib/locd/config.rb', line 361

def cli_log_level
  get( cli_ARGV_looks_like_bash_comp? ? 'bash_comp.log.level' :
                                        'cli.log.level' )
end

#env_key_for(*key) ⇒ Object



198
199
200
201
202
203
# File 'lib/locd/config.rb', line 198

def env_key_for *key
  [
    from_files( :namespace, :env, type: t.non_empty_str ),
    *key_path_for( *key )
  ].join( '_' ).upcase
end

#from_env(*key, type: nil) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/locd/config.rb', line 229

def from_env *key, type: nil
  env_key = env_key_for *key
  
  value = ENV[env_key]
  
  case value
  when nil, ''
    nil
  else
    parse_and_check key, value, type: type
  end
end

#from_files(*key, type: nil) ⇒ Object

Get a value from the config files only.



186
187
188
189
190
191
192
193
194
195
# File 'lib/locd/config.rb', line 186

def from_files *key, type: nil
  key_path = key_path_for *key
  value = @from_files.dig Locd::GEM_NAME, *key_path
  
  if value.nil?
    nil
  else
    parse_and_check key, value, type: type
  end
end

#get(*key, type: nil, default: nil) ⇒ Object Also known as: []



243
244
245
246
247
248
249
250
251
# File 'lib/locd/config.rb', line 243

def get *key, type: nil, default: nil
  env_value = from_env *key, type: type
  return env_value unless env_value.nil?
  
  files_value = from_files *key, type: type
  return files_value unless files_value.nil?
  
  parse_and_check key, default, type: type
end

#home_dirPathname

Absolute path to Loc'd home directory (it's workspace). Doesn't check that the directory exists or anything.



309
310
311
# File 'lib/locd/config.rb', line 309

def home_dir
  self[:home].to_pn
end

#key_path_for(*key) ⇒ Object



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

def key_path_for *key
  self.class.key_path_for *key
end

#log_dirPathname

Directory to save system logs in (proxy, newsyslog, etc...)



318
319
320
321
322
323
324
# File 'lib/locd/config.rb', line 318

def log_dir
  self[
    :log,
    :dir,
    default: (home_dir / 'log')
  ]
end

#parse_and_check(key, value, type: nil) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/locd/config.rb', line 206

def parse_and_check key, value, type: nil
  type = Types.for_key( *key ) if type.nil?
  
  return value if type.nil?
  
  begin
    if value.is_a?( String ) && type.has_from_s?
      type.from_s value
    else
      type.check! value
    end
  rescue NRSER::TypeError => error
    error.context.merge! \
      key: key,
      value: value,
      type: type,
      current_config_from_files: @from_files

    raise error
  end
end

#set(*key, value, type: nil) ⇒ Object



256
257
258
259
260
261
262
# File 'lib/locd/config.rb', line 256

def set *key, value, type: nil
  value_str = value.to_s
  
  parse_and_check key, value_str, type: type
  
  ENV[ env_key_for( *key ) ] = value_str
end

#tmp_dirObject



327
328
329
330
331
332
333
# File 'lib/locd/config.rb', line 327

def tmp_dir
  self[
    :tmp,
    :dir,
    default: ( home_dir / 'tmp' )
  ]
end

#to_hObject



290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/locd/config.rb', line 290

def to_h
  @from_files.merge \
    "locd" => @from_files["locd"].map_leaves { |key_path, value|
      env_value = from_env *key_path
      
      if env_value.nil?
        value
      else
        env_value
      end
    }
end

#user_config_pathPathname



340
341
342
# File 'lib/locd/config.rb', line 340

def user_config_path
  home_dir / 'config.yml'
end