Class: CemAcpt::Config::Base
- Inherits:
-
Object
- Object
- CemAcpt::Config::Base
- Defined in:
- lib/cem_acpt/config/base.rb
Overview
Base class for other config classes Child classes should provide the following constant:
- VALID_KEYS - provide an array of valid top-level keys for the config as symbols
Child classes should implement the following methods:
- defaults - provide a hash of default values for the config
- env_var_prefix - provide a string to prefix environment variables with (defaults to 'CEM_ACPT').
This will be converted to uppercase, have all non-alphanumeric characters replaced with
underscores, and be joined with the key name with an underscore to form the environment
variable name.
However, they can override any of the methods in this class.
Direct Known Subclasses
Constant Summary collapse
- BASE_VALID_KEYS =
%i[ ci_mode config_file log_level log_file log_format no_destroy_nodes no_ephemeral_ssh_key platform puppet quiet secrets terraform user_config verbose ].freeze
- DEEP_MERGE_OPTS =
{ overwrite_arrays: true, merge_nil_values: true, }.freeze
Instance Attribute Summary collapse
-
#config ⇒ Object
(also: #to_h)
readonly
Returns the value of attribute config.
-
#env_vars ⇒ Object
readonly
Returns the value of attribute env_vars.
Class Method Summary collapse
- .inherited(subclass) ⇒ Object
-
.load_hook(&block) ⇒ Object
Add a block to be called after the config is loaded but before it is validated and frozen.
Instance Method Summary collapse
- #[](key) ⇒ Object
- #ci_mode? ⇒ Boolean (also: #ci?)
- #debug_mode? ⇒ Boolean (also: #debug?)
-
#defaults ⇒ Hash
The default configuration.
- #empty? ⇒ Boolean
-
#env_var_prefix ⇒ String
The prefix for environment variables.
-
#explain ⇒ Object
Returns a string representation of how the config was loaded.
- #get(dot_key) ⇒ Object (also: #dget)
- #has?(dot_key) ⇒ Boolean
-
#initialize(opts: {}, config_file: nil, load_user_config: true) ⇒ Base
constructor
A new instance of Base.
- #inspect ⇒ Object
-
#load(opts: {}, config_file: nil) ⇒ self
Load the configuration from the environment variables, config file, and opts The order of precedence is: 1.
- #quiet_mode? ⇒ Boolean (also: #quiet?)
- #scan? ⇒ Boolean
-
#scan_mode? ⇒ Boolean
Whether this config represents a scan run (cem_acpt_scan).
- #to_json(*args, expose_secrets: false) ⇒ Object
- #to_yaml(expose_secrets: false) ⇒ Object
-
#valid_keys ⇒ Array<Symbol>
Valid top-level keys for the config.
- #verbose_mode? ⇒ Boolean (also: #verbose?)
Constructor Details
#initialize(opts: {}, config_file: nil, load_user_config: true) ⇒ Base
Returns a new instance of Base.
84 85 86 87 88 |
# File 'lib/cem_acpt/config/base.rb', line 84 def initialize(opts: {}, config_file: nil, load_user_config: true) @load_user_config = load_user_config @explanation = {} load(opts: opts, config_file: config_file) end |
Instance Attribute Details
#config ⇒ Object Also known as: to_h
Returns the value of attribute config.
82 83 84 |
# File 'lib/cem_acpt/config/base.rb', line 82 def config @config end |
#env_vars ⇒ Object (readonly)
Returns the value of attribute env_vars.
82 83 84 |
# File 'lib/cem_acpt/config/base.rb', line 82 def env_vars @env_vars end |
Class Method Details
.inherited(subclass) ⇒ Object
68 69 70 |
# File 'lib/cem_acpt/config/base.rb', line 68 def self.inherited(subclass) subclass.instance_variable_set(:@load_hook, nil) end |
.load_hook(&block) ⇒ Object
Add a block to be called after the config is loaded but before it is validated and frozen. The block will be passed the config hash and can be used to modify the config before it is finalized.
74 75 76 77 78 79 80 |
# File 'lib/cem_acpt/config/base.rb', line 74 def self.load_hook(&block) if block_given? @load_hook = block else @load_hook end end |
Instance Method Details
#[](key) ⇒ Object
164 165 166 167 168 169 170 171 172 |
# File 'lib/cem_acpt/config/base.rb', line 164 def [](key) if key.is_a?(Symbol) @config[key].dup elsif key.is_a?(String) get(key) else raise ArgumentError, "Invalid key type '#{key.class}'" end end |
#ci_mode? ⇒ Boolean Also known as: ci?
187 188 189 |
# File 'lib/cem_acpt/config/base.rb', line 187 def ci_mode? !!get('ci_mode') || !!(ENV['GITHUB_ACTIONS'] || ENV['CI']) end |
#debug_mode? ⇒ Boolean Also known as: debug?
202 203 204 |
# File 'lib/cem_acpt/config/base.rb', line 202 def debug_mode? get('log_level') == 'debug' end |
#defaults ⇒ Hash
Returns The default configuration.
109 110 111 |
# File 'lib/cem_acpt/config/base.rb', line 109 def defaults {} end |
#empty? ⇒ Boolean
183 184 185 |
# File 'lib/cem_acpt/config/base.rb', line 183 def empty? @config.empty? end |
#env_var_prefix ⇒ String
Returns The prefix for environment variables.
95 96 97 |
# File 'lib/cem_acpt/config/base.rb', line 95 def env_var_prefix 'CEM_ACPT' end |
#explain ⇒ Object
Returns a string representation of how the config was loaded
158 159 160 161 162 |
# File 'lib/cem_acpt/config/base.rb', line 158 def explain @explanation.each_with_object([]) { |(key, values), ary| ary << "#{key}:\n -->#{values.join("\n -->")}" }.join("\n") end |
#get(dot_key) ⇒ Object Also known as: dget
174 175 176 |
# File 'lib/cem_acpt/config/base.rb', line 174 def get(dot_key) @dot_key_cache[dot_key] ||= @config.dget(dot_key).dup end |
#has?(dot_key) ⇒ Boolean
179 180 181 |
# File 'lib/cem_acpt/config/base.rb', line 179 def has?(dot_key) !!get(dot_key) end |
#inspect ⇒ Object
90 91 92 |
# File 'lib/cem_acpt/config/base.rb', line 90 def inspect "#<#{self.class}:#{object_id.to_s(16)}>" end |
#load(opts: {}, config_file: nil) ⇒ self
Load the configuration from the environment variables, config file, and opts The order of precedence is:
1. static options (set in this class)
2. Runtime options
3. Runtime config file
4. User config file
5. Environment variables
6. Defaults
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/cem_acpt/config/base.rb', line 124 def load(opts: {}, config_file: nil) create_config_dirs! init_config!(opts: opts, config_file: config_file) add_env_vars!(@config) @config.deep_merge!(user_config, **DEEP_MERGE_OPTS) if user_config && @load_user_config @config.deep_merge!(config_from_file, **DEEP_MERGE_OPTS) if config_from_file if @options @config.deep_merge!(@options, **DEEP_MERGE_OPTS) @options.each do |key, _value| add_config_explanation(key, "runtime option") end end (@config) # Run the load hook if it is defined. This allows child classes to modify the config after it has been loaded # but before it is validated and frozen. block = self.class.load_hook instance_eval(&block) if block @config.format! # Symbolize keys of all hashes # Remove any keys that are not in the valid keys list for this config. This prevents invalid config options # from being set. @config.select! { |key, _| valid_keys.include?(key) } # Wrap secrets in the config with the Secret class to prevent them from being accidentally printed in logs # or error messages. WARNING: Secrets can leak from Terraform logging. wrap_secrets! validate_config! @dot_key_cache = {} # Freeze the config so it can't be modified # This helps with thread safety and deterministic behavior @config.freeze self end |
#quiet_mode? ⇒ Boolean Also known as: quiet?
212 213 214 |
# File 'lib/cem_acpt/config/base.rb', line 212 def quiet_mode? !!get('quiet') end |
#scan? ⇒ Boolean
198 199 200 |
# File 'lib/cem_acpt/config/base.rb', line 198 def scan? scan_mode? end |
#scan_mode? ⇒ Boolean
Whether this config represents a scan run (cem_acpt_scan). Subclasses that drive a scan workflow override to true.
194 195 196 |
# File 'lib/cem_acpt/config/base.rb', line 194 def scan_mode? false end |
#to_json(*args, expose_secrets: false) ⇒ Object
224 225 226 227 228 229 |
# File 'lib/cem_acpt/config/base.rb', line 224 def to_json(*args, expose_secrets: false) return @config.to_json(*args) unless @config.key?(:secrets) serializable_secrets = @config[:secrets].transform_values { |v| v.is_a?(Secret) ? (expose_secrets ? v.value : v.to_s) : v } @config.merge(secrets: serializable_secrets).to_json(*args) end |
#to_yaml(expose_secrets: false) ⇒ Object
217 218 219 220 221 222 |
# File 'lib/cem_acpt/config/base.rb', line 217 def to_yaml(expose_secrets: false) return @config.to_yaml unless @config.key?(:secrets) serializable_secrets = @config[:secrets].transform_values { |v| v.is_a?(Secret) ? (expose_secrets ? v.value : v.to_s) : v } @config.merge(secrets: serializable_secrets).to_yaml end |
#valid_keys ⇒ Array<Symbol>
Returns Valid top-level keys for the config.
100 101 102 103 104 105 106 |
# File 'lib/cem_acpt/config/base.rb', line 100 def valid_keys if self.class.const_defined?(:VALID_KEYS) (BASE_VALID_KEYS + self.class.const_get(:VALID_KEYS)).uniq else BASE_VALID_KEYS end end |
#verbose_mode? ⇒ Boolean Also known as: verbose?
207 208 209 |
# File 'lib/cem_acpt/config/base.rb', line 207 def verbose_mode? !!get('verbose') end |