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.
@@ -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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+
5
+ module ContainerConfig
6
+ # ContainerConfig Logging class
7
+ class Logger < ::Logger
8
+ end
9
+ 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