Module: DopCommon::HashParser

Included in:
AffinityGroup, Command, Credential, DNS, DataDisk, Hooks, Infrastructure, InfrastructureProperties, Interface, Network, Node, Plan
Defined in:
lib/dop_common/hash_parser.rb

Class Method Summary collapse

Class Method Details

.deep_symbolize_keys(hash, stack = []) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/dop_common/hash_parser.rb', line 40

def deep_symbolize_keys(hash, stack = [])
  # prevent loops in recursive function
  return if stack.include?(hash.object_id)
  stack << hash.object_id

  if hash.kind_of?(Hash)
    Hash[
      hash.map do |k, v|
        [k.respond_to?(:to_sym) ? k.to_sym : k, deep_symbolize_keys(v, stack)]
      end
    ]
  elsif hash.kind_of?(Array)
    hash.map { |v| deep_symbolize_keys(v, stack) }
  else
    hash
  end
end

.hash_of_pattern_lists_valid?(hash, key, optional = true) ⇒ Boolean

This method takes a hash where all the values are pattern lists and checks if they are valid.

Example:

hash = {

:key => {
  'list_1' => [ 'my_node', '/my_node/' ],
  'list_2' => '/my_node'/
}

}

Returns:

  • (Boolean)


122
123
124
125
126
127
128
129
130
131
132
# File 'lib/dop_common/hash_parser.rb', line 122

def hash_of_pattern_lists_valid?(hash, key, optional = true )
  return false if hash[key].nil? && optional
  hash[key].kind_of?(Hash) or
    raise PlanParsingError, "The value for '#{key}' has to be a Hash"
  hash[key].each_key do |list_name|
    list_name.kind_of?(String) or
      raise PlanParsingError, "The key '#{list_name.to_s}' in '#{key}' has to be a String"
    HashParser.pattern_list_valid?(hash[key], list_name)
  end
  true
end

.is_valid_regexp?(value) ⇒ Boolean

This method will return true if the string in ‘value’ represents a regex and if it is possible to create a regexp object

Returns:

  • (Boolean)


72
73
74
75
76
77
78
79
# File 'lib/dop_common/hash_parser.rb', line 72

def is_valid_regexp?(value)
  return false unless represents_regexp?(value)
  regexp = value[/^\/(.*)\/$/, 1]
  Regexp.new(regexp)
  true
rescue
  false
end

.key_aliases(hash, key, key_aliases) ⇒ Object

This method will set the key from a list of defined aliases or raise an error if multiple values are found



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/dop_common/hash_parser.rb', line 12

def key_aliases(hash, key, key_aliases)
  value = hash[key]
  key_aliases.each do |key_alias|
    next if hash[key_alias].nil?
    unless value.nil?
      keys_with_values = key_aliases.select{|a| !hash[a].nil?}
      keys_with_values << key if hash[key]
      key_list = keys_with_values.map{|k| k.kind_of?(Symbol) ? ':' + k.to_s : k}.join(', ')
      raise DopCommon::PlanParsingError,
        "Two or more values found for the same thing. There can only be one of: #{key_list}"
    else
      value = hash[key] = hash.delete(key_alias)
      key_s = key.kind_of?(Symbol) ? ':' + key.to_s : key
      DopCommon.log.debug("Key alias found '#{key_alias}', mapping for key #{key_s}")
    end
  end
end

.load_content(value) ⇒ Object

Load string content from different sources

the content can be directly a string in which case it will immediatly return. load_content(‘hello world’)

it may also be a hash with the following content: load_content({ file => ‘/path/to/some/file’ }) This will check if the file exists and load it

you can also specify a script it will execute to get the content load_content({ exec => ‘/path/to/some/executable_file’ })



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/dop_common/hash_parser.rb', line 171

def load_content(value)
  if value.kind_of?(Hash)
    method, params = symbolize_keys(value).first
    file = case params
    when Array  then params.join(' ')
    when String then params
    end
    case method
    when :file then File.read(file).chomp
    when :exec
      prog = params.first
      args = params[1, params.length].join(' ')
      o, e, s = Open3.capture3(Utils::sanitize_env, "#{prog} #{args}", :unsetenv_others => true)

      unless s.success?
        DopCommon.log.error("Standard error output of '#{prog} #{args}':\n#{e.chomp}")
        DopCommon.log.error("Standard output of '#{prog} #{args}':\n#{o.chomp}")
        raise PlanParsingError, "Program '#{prog}' returned non-zero exit status #{s.exitstatus}"
      end

      o.chomp
    end
  else
    value
  end
end

.load_content_valid?(value) ⇒ Boolean

This is the validation method for the load_content method and will check if the value is a correctly specified content source

Returns:

  • (Boolean)


202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/dop_common/hash_parser.rb', line 202

def load_content_valid?(value)
  case value
  when String then true
  when Hash
    value.count == 1 or
      raise PlanParsingError, "You can only specify one content type"
    method, params = symbolize_keys(value).first
    [:file, :exec].include?(method) or
      raise PlanParsingError, "#{method} is not a valid content method. valid methods are :exec and :file"
    file = case params
    when Array
      params.count >= 1 or
        raise PlanParsingError, "The array for method #{method} has to have at least one entry"
      params.all?{|e| e.kind_of?(String)} or
        raise PlanParsingError, "The array for method #{method} can only contain strings"
      method != :file or
        raise PlanParsingError, "The method :file does not support arrays as an argument"
      params.first
    when String
      params
    else
      raise PlanParsingError, "The value for method #{method} has to be an array or string"
    end
    File.exists?(file) or
      raise PlanParsingError, "The file #{file} does not exist."
    File.readable?(file) or
      raise PlanParsingError, "The file #{file} is not readable."
    if method == :exec
      File.executable?(file) or
        raise PlanParsingError, "The file #{file} is not executable."
    end
  else
    raise PlanParsingError, 'The content source has to be a string or a hash with a content lookup method'
  end
  true
end

.parse_hash_of_pattern_lists(hash, key) ⇒ Object

This method will parse a hash of pattern lists and replace the regexp strings with Regexp objects



151
152
153
154
155
# File 'lib/dop_common/hash_parser.rb', line 151

def parse_hash_of_pattern_lists(hash, key)
  Hash[hash[key].map do |list_name, pattern_list|
    [list_name, parse_pattern_list(hash[key], list_name)]
  end]
end

.parse_pattern_list(hash, key) ⇒ Object

This method will parse a valid pattern list and replace regexp strings with Regexp objects.



137
138
139
140
141
142
143
144
145
146
# File 'lib/dop_common/hash_parser.rb', line 137

def parse_pattern_list(hash, key)
  case hash[key]
  when 'all', 'All', 'ALL', :all then :all
  else
    patterns = [hash[key]].flatten.compact
    patterns.map do |pattern|
      HashParser.represents_regexp?(pattern) ? Regexp.new(pattern[/^\/(.*)\/$/, 1]) : pattern
    end
  end
end

.pattern_list_valid?(hash, key, optional = true) ⇒ Boolean

This method takes a hash and a key. It will then validate the pattern list in the value of that key.

Examples (Simple String/Regexp):

hash = { :key => ‘my_node’} hash = { :key => ‘/my_node/’}

Examples (Array of Strings, Regexps):

hash = { :key => [ ‘my_node’, ‘/my_node/’ ] }

Returns:

  • (Boolean)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/dop_common/hash_parser.rb', line 94

def pattern_list_valid?(hash, key, optional = true)
  return false if hash[key].nil? && optional
  [Array, String, Symbol].include? hash[key].class or
    raise PlanParsingError, "The value for '#{key}' has to be a string, an array or a symbol."
  [hash[key]].flatten.each do |pattern|
    [String, Symbol].include? pattern.class or
      raise PlanParsingError, "The pattern #{pattern} in '#{key}' is not a symbol or string."
    if HashParser.represents_regexp?(pattern)
      HashParser.is_valid_regexp?(pattern) or
        raise PlanParsingError, "The pattern #{pattern} in '#{key}' is not a valid regular expression."
    end
  end
  true
end

.represents_regexp?(value) ⇒ Boolean

This method will retrun true if the String in ‘value’ starts and ends with /, which means it represents a regexp

Returns:

  • (Boolean)


61
62
63
64
65
66
67
# File 'lib/dop_common/hash_parser.rb', line 61

def represents_regexp?(value)
  if value.kind_of?(String)
    value[/^\/(.*)\/$/, 1] ? true : false
  else
    false
  end
end

.symbolize_keys(hash) ⇒ Object



31
32
33
34
35
36
37
# File 'lib/dop_common/hash_parser.rb', line 31

def symbolize_keys(hash)
  if hash.kind_of?(Hash)
    Hash[hash.map { |k, v| [k.to_sym, v] }] if hash.kind_of?(Hash)
  else
    hash
  end
end