container_config 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/main.yml +35 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +28 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +64 -0
- data/LICENSE.txt +21 -0
- data/README.md +116 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/container_config.gemspec +37 -0
- data/lib/container_config.rb +185 -0
- data/lib/container_config/coercer.rb +61 -0
- data/lib/container_config/coercer/base.rb +39 -0
- data/lib/container_config/coercer/boolean.rb +34 -0
- data/lib/container_config/coercer/float.rb +33 -0
- data/lib/container_config/coercer/integer.rb +33 -0
- data/lib/container_config/coercer/ssl_certificate.rb +47 -0
- data/lib/container_config/coercer/ssl_key.rb +45 -0
- data/lib/container_config/coercer/ssl_verify_mode.rb +42 -0
- data/lib/container_config/coercer/string.rb +31 -0
- data/lib/container_config/coercer/symbol.rb +33 -0
- data/lib/container_config/logger.rb +9 -0
- data/lib/container_config/provider.rb +66 -0
- data/lib/container_config/provider/base.rb +39 -0
- data/lib/container_config/provider/default.rb +30 -0
- data/lib/container_config/provider/env.rb +29 -0
- data/lib/container_config/provider/rails_credential.rb +31 -0
- data/lib/container_config/provider/secret_volume.rb +58 -0
- data/lib/container_config/rails.rb +10 -0
- data/lib/container_config/rails/mailer.rb +81 -0
- data/lib/container_config/redis.rb +95 -0
- data/lib/container_config/version.rb +6 -0
- metadata +167 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "container_config"
|
4
|
+
require "container_config/coercer/base"
|
5
|
+
require "container_config/coercer/boolean"
|
6
|
+
require "container_config/coercer/float"
|
7
|
+
require "container_config/coercer/integer"
|
8
|
+
require "container_config/coercer/string"
|
9
|
+
require "container_config/coercer/symbol"
|
10
|
+
require "container_config/coercer/ssl_verify_mode"
|
11
|
+
require "container_config/coercer/ssl_certificate"
|
12
|
+
require "container_config/coercer/ssl_key"
|
13
|
+
|
14
|
+
module ContainerConfig
|
15
|
+
# Contains classes and methods for type coercion
|
16
|
+
module Coercer
|
17
|
+
#
|
18
|
+
# Coerces a given value into a requested type
|
19
|
+
#
|
20
|
+
# @param [Object] value value to coerce
|
21
|
+
# @param [Symbol] value_type requested type such as :boolean, :integer, :string, :symbol,
|
22
|
+
# :ssl_verify_mode, :ssl_certificate, or :ssl_key
|
23
|
+
# @param [Hash] options Options Hash
|
24
|
+
# @option options [Boolean] :coerce_nil where to coerce nil values (defaults to true)
|
25
|
+
#
|
26
|
+
# @return [Object] coerced value
|
27
|
+
#
|
28
|
+
def self.coerce_value(value, value_type = nil, options = {})
|
29
|
+
return value unless value_type
|
30
|
+
|
31
|
+
return value if options[:coerce_nil] == false && value.nil?
|
32
|
+
|
33
|
+
value_type = value_type.to_sym
|
34
|
+
|
35
|
+
ContainerConfig.coercers.each do |coercer|
|
36
|
+
return coercer.coerce(value) if coercer.type == value_type
|
37
|
+
end
|
38
|
+
|
39
|
+
ContainerConfig.logger.warn { "Could not find valid coercion type for #{value_type}" }
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Array of default coercers
|
45
|
+
#
|
46
|
+
# @return [Array<ContainerConfig::Coercer::Base>] default coercers
|
47
|
+
#
|
48
|
+
def self.default_coercers
|
49
|
+
[
|
50
|
+
ContainerConfig::Coercer::Boolean.new,
|
51
|
+
ContainerConfig::Coercer::Float.new,
|
52
|
+
ContainerConfig::Coercer::Integer.new,
|
53
|
+
ContainerConfig::Coercer::SslCertificate.new,
|
54
|
+
ContainerConfig::Coercer::SslKey.new,
|
55
|
+
ContainerConfig::Coercer::SslVerifyMode.new,
|
56
|
+
ContainerConfig::Coercer::String.new,
|
57
|
+
ContainerConfig::Coercer::Symbol.new
|
58
|
+
]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ContainerConfig
|
4
|
+
module Coercer
|
5
|
+
# Base type coercer
|
6
|
+
class Base
|
7
|
+
#
|
8
|
+
# Returns name of the coercer
|
9
|
+
#
|
10
|
+
# @return [String] coercer name
|
11
|
+
#
|
12
|
+
def name
|
13
|
+
raise ContainerConfig::MissingOverride, "Must override name method in derived class #{self.class}"
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Returns the type of the coercer
|
18
|
+
# This is used by the ContainerConfig::Coercer.coerce_value method to determine
|
19
|
+
# whether this coercer should be used for a given type
|
20
|
+
#
|
21
|
+
# @return [Symbol] coercer type
|
22
|
+
#
|
23
|
+
def type
|
24
|
+
raise ContainerConfig::MissingOverride, "Must override type method in derived class #{self.class}"
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Coerces the given value into the coercer type
|
29
|
+
#
|
30
|
+
# @param [Object] _value given value
|
31
|
+
#
|
32
|
+
# @return [Object] coerced value
|
33
|
+
#
|
34
|
+
def coerce(_value)
|
35
|
+
raise ContainerConfig::MissingOverride, "Must override coerce method in derived class #{self.class}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "container_config/coercer/base"
|
4
|
+
|
5
|
+
module ContainerConfig
|
6
|
+
module Coercer
|
7
|
+
# Boolean type coercer
|
8
|
+
class Boolean < Base
|
9
|
+
# @see ContainerConfig::Coercer::Base#name
|
10
|
+
def name
|
11
|
+
"Boolean"
|
12
|
+
end
|
13
|
+
|
14
|
+
# @see ContainerConfig::Coercer::Base#type
|
15
|
+
def type
|
16
|
+
:boolean
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Coerces the given value into a boolean
|
21
|
+
#
|
22
|
+
# @param [Object] value given value
|
23
|
+
#
|
24
|
+
# @return [Boolean] coerced value
|
25
|
+
#
|
26
|
+
def coerce(value)
|
27
|
+
# If a digit is passed, check if it is non-zero and return true for non-zero values
|
28
|
+
return value.to_i != 0 if value.respond_to?(:to_i) && value.to_i.to_s == value.to_s
|
29
|
+
|
30
|
+
value.to_s.casecmp?("true")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "container_config/coercer/base"
|
4
|
+
|
5
|
+
module ContainerConfig
|
6
|
+
module Coercer
|
7
|
+
# Float type coercer
|
8
|
+
class Float < Base
|
9
|
+
# @see ContainerConfig::Coercer::Base#name
|
10
|
+
def name
|
11
|
+
"Float"
|
12
|
+
end
|
13
|
+
|
14
|
+
# @see ContainerConfig::Coercer::Base#type
|
15
|
+
def type
|
16
|
+
:float
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Coerces the given value into a float
|
21
|
+
#
|
22
|
+
# @param [Object] value given value
|
23
|
+
#
|
24
|
+
# @return [Float] coerced value
|
25
|
+
#
|
26
|
+
def coerce(value)
|
27
|
+
return 0.0 unless value.respond_to?(:to_f)
|
28
|
+
|
29
|
+
value.to_f
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "container_config/coercer/base"
|
4
|
+
|
5
|
+
module ContainerConfig
|
6
|
+
module Coercer
|
7
|
+
# Integer type coercer
|
8
|
+
class Integer < Base
|
9
|
+
# @see ContainerConfig::Coercer::Base#name
|
10
|
+
def name
|
11
|
+
"Integer"
|
12
|
+
end
|
13
|
+
|
14
|
+
# @see ContainerConfig::Coercer::Base#type
|
15
|
+
def type
|
16
|
+
:integer
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Coerces the given value into an integer
|
21
|
+
#
|
22
|
+
# @param [Object] value given value
|
23
|
+
#
|
24
|
+
# @return [Integer] coerced value
|
25
|
+
#
|
26
|
+
def coerce(value)
|
27
|
+
return 0 unless value.respond_to?(:to_i)
|
28
|
+
|
29
|
+
value.to_i
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "container_config"
|
4
|
+
require "container_config/coercer/base"
|
5
|
+
require "openssl"
|
6
|
+
|
7
|
+
module ContainerConfig
|
8
|
+
module Coercer
|
9
|
+
# SSL certificate type coercer
|
10
|
+
class SslCertificate < Base
|
11
|
+
# @see ContainerConfig::Coercer::Base#name
|
12
|
+
def name
|
13
|
+
"SSL Certificate"
|
14
|
+
end
|
15
|
+
|
16
|
+
# @see ContainerConfig::Coercer::Base#type
|
17
|
+
def type
|
18
|
+
:ssl_certificate
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Coerces the given value into an SSL certificate
|
23
|
+
#
|
24
|
+
# @param [Object] value SSL certificate path
|
25
|
+
#
|
26
|
+
# @return [OpenSSL::X509::Certificate] coerced value
|
27
|
+
#
|
28
|
+
def coerce(value)
|
29
|
+
return if value.nil?
|
30
|
+
|
31
|
+
return value if value.is_a?(OpenSSL::X509::Certificate)
|
32
|
+
|
33
|
+
cert_path = value.to_s
|
34
|
+
|
35
|
+
unless File.exist?(cert_path)
|
36
|
+
ContainerConfig.logger.warn { "Could not find SSL certificate at #{cert_path}" }
|
37
|
+
return nil
|
38
|
+
end
|
39
|
+
|
40
|
+
OpenSSL::X509::Certificate.new(File.read(cert_path))
|
41
|
+
rescue OpenSSL::X509::CertificateError => e
|
42
|
+
ContainerConfig.logger.warn { "Could not parse SSL certificate #{cert_path} successfully: #{e}" }
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "container_config"
|
4
|
+
require "container_config/coercer/base"
|
5
|
+
require "openssl"
|
6
|
+
|
7
|
+
module ContainerConfig
|
8
|
+
module Coercer
|
9
|
+
# SSL key type coercer
|
10
|
+
class SslKey < Base
|
11
|
+
# @see ContainerConfig::Coercer::Base#name
|
12
|
+
def name
|
13
|
+
"SSL Private Key"
|
14
|
+
end
|
15
|
+
|
16
|
+
# @see ContainerConfig::Coercer::Base#type
|
17
|
+
def type
|
18
|
+
:ssl_key
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Coerces the given value into an SSL key
|
23
|
+
#
|
24
|
+
# @param [Object] value SSL key path
|
25
|
+
#
|
26
|
+
# @return [OpenSSL::PKey::RSA] coerced value
|
27
|
+
#
|
28
|
+
def coerce(value)
|
29
|
+
return if value.nil?
|
30
|
+
|
31
|
+
key_path = value.to_s
|
32
|
+
|
33
|
+
unless File.exist?(key_path)
|
34
|
+
ContainerConfig.logger.warn { "Could not find SSL key at #{key_path}" }
|
35
|
+
return
|
36
|
+
end
|
37
|
+
|
38
|
+
OpenSSL::PKey::RSA.new(File.read(key_path))
|
39
|
+
rescue OpenSSL::PKey::RSAError => e
|
40
|
+
ContainerConfig.logger.warn { "Could not parse SSL key #{key_path} successfully: #{e}" }
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "container_config"
|
4
|
+
require "container_config/coercer/base"
|
5
|
+
require "openssl"
|
6
|
+
|
7
|
+
module ContainerConfig
|
8
|
+
module Coercer
|
9
|
+
# SSL verification mode type coercer
|
10
|
+
class SslVerifyMode < Base
|
11
|
+
# Array of valid SSL verification modes
|
12
|
+
VALID_MODES = OpenSSL::SSL.constants.select { |c| c.to_s.start_with?("VERIFY") }.map(&:to_s)
|
13
|
+
|
14
|
+
# @see ContainerConfig::Coercer::Base#name
|
15
|
+
def name
|
16
|
+
"SSL Verification Mode"
|
17
|
+
end
|
18
|
+
|
19
|
+
# @see ContainerConfig::Coercer::Base#type
|
20
|
+
def type
|
21
|
+
:ssl_verify_mode
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Coerces the given value into an SSL verification mode
|
26
|
+
#
|
27
|
+
# @param [Object] value SSL verification mode string ("VERIFY_NONE", "VERIFY_PEER", etc.)
|
28
|
+
#
|
29
|
+
# @return [Integer] coerced value
|
30
|
+
#
|
31
|
+
def coerce(value)
|
32
|
+
value = value.to_s
|
33
|
+
return Object.const_get("OpenSSL::SSL::#{value}") if VALID_MODES.include?(value)
|
34
|
+
|
35
|
+
ContainerConfig.logger.warn do
|
36
|
+
"Could not convert #{value.inspect} into a valid OpenSSL verification mode.\nValid modes: #{VALID_MODES.join(", ")}"
|
37
|
+
end
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "container_config/coercer/base"
|
4
|
+
|
5
|
+
module ContainerConfig
|
6
|
+
module Coercer
|
7
|
+
# String type coercer
|
8
|
+
class String < Base
|
9
|
+
# @see ContainerConfig::Coercer::Base#name
|
10
|
+
def name
|
11
|
+
"String"
|
12
|
+
end
|
13
|
+
|
14
|
+
# @see ContainerConfig::Coercer::Base#type
|
15
|
+
def type
|
16
|
+
:string
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Coerces the given value into a string
|
21
|
+
#
|
22
|
+
# @param [Object] value given value
|
23
|
+
#
|
24
|
+
# @return [String] coerced value
|
25
|
+
#
|
26
|
+
def coerce(value)
|
27
|
+
value.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "container_config/coercer/base"
|
4
|
+
|
5
|
+
module ContainerConfig
|
6
|
+
module Coercer
|
7
|
+
# Symbol type coercer
|
8
|
+
class Symbol < Base
|
9
|
+
# @see ContainerConfig::Coercer::Base#name
|
10
|
+
def name
|
11
|
+
"Symbol"
|
12
|
+
end
|
13
|
+
|
14
|
+
# @see ContainerConfig::Coercer::Base#type
|
15
|
+
def type
|
16
|
+
:symbol
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Coerces the given value into a symbol
|
21
|
+
#
|
22
|
+
# @param [Object] value given value
|
23
|
+
#
|
24
|
+
# @return [Symbol] coerced value
|
25
|
+
#
|
26
|
+
def coerce(value)
|
27
|
+
return if value.nil?
|
28
|
+
|
29
|
+
value.to_s.to_sym
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "container_config"
|
4
|
+
require "container_config/provider/base"
|
5
|
+
require "container_config/provider/default"
|
6
|
+
require "container_config/provider/env"
|
7
|
+
require "container_config/provider/rails_credential"
|
8
|
+
require "container_config/provider/secret_volume"
|
9
|
+
|
10
|
+
module ContainerConfig
|
11
|
+
# Contains classes and methods for config value providers
|
12
|
+
module Provider
|
13
|
+
#
|
14
|
+
# Loads a value from the config value providers
|
15
|
+
#
|
16
|
+
# @param [String] key Configuration key to load
|
17
|
+
# @param [Array] dig_keys Variable keys to use to load from providers that accept a dig structure
|
18
|
+
# defaults to the lowercase key split by underscores
|
19
|
+
# "MY_PASSWORD" => ["my", "password"]
|
20
|
+
# @param [Hash] options Options Hash
|
21
|
+
# @option options [String] :default default value if the configuration setting cannot be found
|
22
|
+
# @option options [String] :secret_mount_directory directory where secret files are mounted
|
23
|
+
# @option options [Symbol] :type type to use such as :boolean, :integer, :string, :symbol,
|
24
|
+
# :ssl_verify_mode, :ssl_certificate, or :ssl_key
|
25
|
+
#
|
26
|
+
# @return [Object] configuration setting value
|
27
|
+
#
|
28
|
+
def self.load_value(key, *dig_keys, **options)
|
29
|
+
value = nil
|
30
|
+
ContainerConfig.providers.each do |p|
|
31
|
+
value = p.load(key, *dig_keys, **options)
|
32
|
+
break unless value.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
value
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Array of default providers
|
40
|
+
#
|
41
|
+
# @return [Array<ContainerConfig::Provider::Base>] default providers
|
42
|
+
#
|
43
|
+
def self.default_providers
|
44
|
+
defaults = [
|
45
|
+
ContainerConfig::Provider::Env.new,
|
46
|
+
ContainerConfig::Provider::SecretVolume.new
|
47
|
+
]
|
48
|
+
|
49
|
+
defaults |= rails_providers if ContainerConfig.rails_app?
|
50
|
+
defaults << ContainerConfig::Provider::Default.new
|
51
|
+
|
52
|
+
defaults
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Array of Rails providers
|
57
|
+
# These are only included in the default providers when this gem is included
|
58
|
+
# as part of a rails application
|
59
|
+
#
|
60
|
+
# @return [Array<ContainerConfig::Provider::Base>] default providers
|
61
|
+
#
|
62
|
+
def self.rails_providers
|
63
|
+
[ContainerConfig::Provider::RailsCredential.new]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|