Module: LocalVault::EnvProjection
- Defined in:
- lib/localvault/env_projection.rb
Defined Under Namespace
Classes: Entry, InvalidMapping, UnknownProfile
Constant Summary collapse
- ENV_NAME_PATTERN =
/\A[A-Za-z_][A-Za-z0-9_]*\z/- PROFILES =
{ "aws" => { only: ["AWS_IAM.*"], map: { "AWS_IAM.access_key_id" => "AWS_ACCESS_KEY_ID", "AWS_IAM.secret_access_key" => "AWS_SECRET_ACCESS_KEY", "AWS_IAM.session_token" => "AWS_SESSION_TOKEN" } } }.freeze
Class Method Summary collapse
- .apply_mapping(entry, mappings, on_skip:) ⇒ Object
- .entries(secrets, project: nil, only: nil, except: nil, map: nil, profile: nil, on_skip: nil) ⇒ Object
- .flatten(secrets, project:, on_skip:) ⇒ Object
- .flatten_group(group, pairs, on_skip:) ⇒ Object
- .include_entry?(key, selectors) ⇒ Boolean
- .parse_map(value) ⇒ Object
- .parse_selectors(value) ⇒ Object
- .profile_config(profile) ⇒ Object
- .safe_env_name?(name) ⇒ Boolean
- .selector_match?(key, selectors) ⇒ Boolean
Class Method Details
.apply_mapping(entry, mappings, on_skip:) ⇒ Object
117 118 119 120 121 122 123 124 125 |
# File 'lib/localvault/env_projection.rb', line 117 def self.apply_mapping(entry, mappings, on_skip:) mapped_name = mappings.fetch(entry.key, entry.env_name) unless safe_env_name?(mapped_name) on_skip&.call(entry.key) return nil end Entry.new(key: entry.key, env_name: mapped_name, value: entry.value) end |
.entries(secrets, project: nil, only: nil, except: nil, map: nil, profile: nil, on_skip: nil) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/localvault/env_projection.rb', line 21 def self.entries(secrets, project: nil, only: nil, except: nil, map: nil, profile: nil, on_skip: nil) profile_config = profile_config(profile) selectors = parse_selectors(only) || profile_config[:only] exclusions = parse_selectors(except) || [] mappings = profile_config[:map].merge(parse_map(map)) flatten(secrets, project: project, on_skip: on_skip) .select { |entry| include_entry?(entry.key, selectors) } .reject { |entry| selector_match?(entry.key, exclusions) } .map { |entry| apply_mapping(entry, mappings, on_skip: on_skip) } .compact end |
.flatten(secrets, project:, on_skip:) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/localvault/env_projection.rb', line 60 def self.flatten(secrets, project:, on_skip:) if project group = secrets[project] return [] unless group.is_a?(Hash) group.filter_map do |key, value| if safe_env_name?(key) Entry.new(key: key, env_name: key, value: value.to_s) else on_skip&.call(key) nil end end else secrets.flat_map do |key, value| if value.is_a?(Hash) flatten_group(key, value, on_skip: on_skip) elsif safe_env_name?(key) [Entry.new(key: key, env_name: key, value: value.to_s)] else on_skip&.call(key) [] end end end end |
.flatten_group(group, pairs, on_skip:) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/localvault/env_projection.rb', line 87 def self.flatten_group(group, pairs, on_skip:) unless safe_env_name?(group) on_skip&.call(group) return [] end pairs.filter_map do |key, value| if safe_env_name?(key) Entry.new(key: "#{group}.#{key}", env_name: "#{group.upcase}__#{key}", value: value.to_s) else on_skip&.call("#{group}.#{key}") nil end end end |
.include_entry?(key, selectors) ⇒ Boolean
103 104 105 |
# File 'lib/localvault/env_projection.rb', line 103 def self.include_entry?(key, selectors) selectors.nil? || selector_match?(key, selectors) end |
.parse_map(value) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/localvault/env_projection.rb', line 40 def self.parse_map(value) Array(value).compact.flat_map { |v| v.to_s.split(",") }.each_with_object({}) do |pair, hash| next if pair.strip.empty? key, env_name = pair.split("=", 2).map(&:strip) raise InvalidMapping, "Invalid map '#{pair}'. Use KEY=ENV_NAME" if key.to_s.empty? || env_name.to_s.empty? raise InvalidMapping, "Invalid environment variable name '#{env_name}'" unless safe_env_name?(env_name) hash[key] = env_name end end |
.parse_selectors(value) ⇒ Object
34 35 36 37 38 |
# File 'lib/localvault/env_projection.rb', line 34 def self.parse_selectors(value) values = Array(value).compact.flat_map { |v| v.to_s.split(",") } selectors = values.map(&:strip).reject(&:empty?) selectors.empty? ? nil : selectors end |
.profile_config(profile) ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/localvault/env_projection.rb', line 52 def self.profile_config(profile) return { only: nil, map: {} } if profile.nil? || profile.to_s.empty? PROFILES.fetch(profile.to_s) do raise UnknownProfile, "Unknown env profile '#{profile}'" end end |
.safe_env_name?(name) ⇒ Boolean
127 128 129 |
# File 'lib/localvault/env_projection.rb', line 127 def self.safe_env_name?(name) name.is_a?(String) && name.match?(ENV_NAME_PATTERN) end |
.selector_match?(key, selectors) ⇒ Boolean
107 108 109 110 111 112 113 114 115 |
# File 'lib/localvault/env_projection.rb', line 107 def self.selector_match?(key, selectors) selectors.any? do |selector| if selector.end_with?(".*") key.start_with?("#{selector.delete_suffix(".*")}.") else key == selector end end end |