Class: Hako::EnvExpander

Inherits:
Object
  • Object
show all
Defined in:
lib/hako/env_expander.rb

Defined Under Namespace

Classes: ExpansionError, Literal, Variable

Instance Method Summary collapse

Constructor Details

#initialize(providers) ⇒ EnvExpander

Returns a new instance of EnvExpander.

Parameters:



17
18
19
# File 'lib/hako/env_expander.rb', line 17

def initialize(providers)
  @providers = providers
end

Instance Method Details

#expand(env) ⇒ Hash<String, String>

Parameters:

  • env (Hash<String, String>)

Returns:

  • (Hash<String, String>)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/hako/env_expander.rb', line 23

def expand(env)
  parsed_env = parse_env(env)
  variables = Set.new
  parsed_env.each_value do |tokens|
    tokens.each do |t|
      if t.is_a?(Variable)
        variables << t.name
      end
    end
  end

  values = {}
  @providers.each do |provider|
    if variables.empty?
      break
    end

    provider.ask(variables.to_a).each do |var, val|
      values[var] = val
      variables.delete(var)
    end
  end
  unless variables.empty?
    raise ExpansionError.new("Could not resolve embedded variables from $providers=#{@providers}: #{variables.to_a}")
  end

  expanded_env = {}
  parsed_env.each do |key, tokens|
    expanded_env[key] = tokens.map { |t| expand_value(values, t) }.join('')
  end
  expanded_env
end

#expand_value(values, token) ⇒ Object (private)



132
133
134
135
136
137
138
139
140
141
# File 'lib/hako/env_expander.rb', line 132

def expand_value(values, token)
  case token
  when Literal
    token.literal
  when Variable
    values.fetch(token.name)
  else
    raise ExpansionError.new("Unknown token type: #{token.class}")
  end
end

#parse(value) ⇒ Array (private)

Parameters:

  • value (String)

Returns:

  • (Array)


108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/hako/env_expander.rb', line 108

def parse(value)
  s = StringScanner.new(value)
  tokens = []
  pos = 0
  while s.scan_until(/#\{(.*?)\}/)
    pre = s.string.byteslice(pos...(s.pos - s.matched.size))
    var = s[1]
    unless pre.empty?
      tokens << Literal.new(pre)
    end
    if var.empty?
      raise ExpansionError.new('Empty interpolation is not allowed')
    else
      tokens << Variable.new(var)
    end

    pos = s.pos
  end
  unless s.rest.empty?
    tokens << Literal.new(s.rest)
  end
  tokens
end

#parse_env(env) ⇒ Hash<String, Array<Literal, Variable>> (private)

Parameters:

  • env (Hash<String, String>)

Returns:



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/hako/env_expander.rb', line 94

def parse_env(env)
  parsed_env = {}
  env.each do |key, val|
    unless val.is_a?(String)
      raise ExpansionError.new("#{key} must be a String but got #{val.class}: #{val.inspect}")
    end

    parsed_env[key] = parse(val)
  end
  parsed_env
end

#validate!(env) ⇒ Boolean

Parameters:

  • env (Hash<String, String>)

Returns:

  • (Boolean)


58
59
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
86
87
88
# File 'lib/hako/env_expander.rb', line 58

def validate!(env)
  parsed_env = parse_env(env)
  variables = Set.new
  parsed_env.each_value do |tokens|
    tokens.each do |t|
      if t.is_a?(Variable)
        variables << t.name
      end
    end
  end

  @providers.each do |provider|
    if variables.empty?
      break
    end

    if provider.can_ask_keys?
      provider.ask_keys(variables.to_a).each do |var|
        variables.delete(var)
      end
    else
      Hako.logger.warn("EnvProvider#validate! is skipped because #{provider.class} doesn't support ask_keys method")
      return false
    end
  end
  unless variables.empty?
    raise ExpansionError.new("Could not find embedded variables from $providers=#{@providers}: #{variables.to_a}")
  end

  true
end