Module: Kerbi::Utils::Mixing

Defined in:
lib/utils/mixing.rb

Class Method Summary collapse

Class Method Details

.clean_and_filter_dicts(dicts, opts = {}) ⇒ Array<Hash>

Turns hashes into symbol-keyed hashes, and applies white/blacklisting based on filters supplied

Parameters:

  • dicts (Array<Hash>)

    list of inflated hashes

  • white_rules (Array<String>)

    list/single k8s res ID to whitelist

  • black_rules (Array<String>)

    list/single k8s res ID to blacklist

Returns:

  • (Array<Hash>)

    list of clean and filtered hashes



75
76
77
78
79
80
81
82
83
# File 'lib/utils/mixing.rb', line 75

def self.clean_and_filter_dicts(dicts, opts={})
  white_rules = opts[:white_rules] || opts[:only]
  black_rules = opts[:black_rules] || opts[:except]
  _dicts = self.hash_to_cloned_hashes(dicts)
  _dicts = _dicts.compact.map(&:deep_symbolize_keys).to_a
  _dicts = self.select_res_dicts_whitelist(_dicts, white_rules)
  _dicts = self.select_res_dicts_blacklist(_dicts, black_rules)
  self.sanitize_res_dict_list(_dicts)
end

.hash_to_cloned_hashes(hashes) ⇒ Array<Hash>

Returns list of clean and filtered hashes.

Returns:

  • (Array<Hash>)

    list of clean and filtered hashes



105
106
107
108
109
110
111
# File 'lib/utils/mixing.rb', line 105

def self.hash_to_cloned_hashes(hashes)
  if !hashes.is_a?(Array)
    [hashes]
  else
    hashes
  end
end

.interpolate_erb_string(yaml_str, opts = {}) ⇒ String

Performs ERB interpolation on an ERB string, and returns the interpolated string.

Parameters:

  • yaml_str (String)

    contents of a yaml or yaml.erb

  • opts (Hash) (defaults to: {})

    an additional hash available to ERB

Returns:

  • (String)

    the interpolated string



39
40
41
42
43
# File 'lib/utils/mixing.rb', line 39

def self.interpolate_erb_string(yaml_str, opts={})
  final_binding = opts[:src_binding] || binding
  final_binding.local_variable_set(:extras, opts[:extras] || {})
  ERB.new(yaml_str).result(final_binding)
end

.res_dict_matches_rule?(res_dict, rule_dict) ⇒ TrueClass, FalseClass

Checks whether a dict, assumed to be a Kubernetes resource, matches a kerbi resource selection rule.

Parameters:

  • res_dict (Hash)

    the Kubernetes-style resource dict

  • rule_dict (Hash)

    the kerbi resource selector dict

Returns:

  • (TrueClass, FalseClass)

    true if the selector selects the resource



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/utils/mixing.rb', line 149

def self.res_dict_matches_rule?(res_dict, rule_dict)
  return false unless res_dict.is_a?(Hash)
  return false unless res_dict.present?

  return false unless rule_dict.is_a?(Hash)
  return false unless rule_dict.present?

  target_kind = rule_dict[:kind].presence
  target_name = rule_dict[:name].presence
  if !target_kind || self.str_cmp(target_kind, res_dict[:kind])
    wild = !target_name || target_name == "*"
    res_name = res_dict[:metadata]&.[](:name)
    wild || self.str_cmp(target_name, res_name)
  end
end

.sanitize_res_dict_list(res_dicts) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/utils/mixing.rb', line 85

def self.sanitize_res_dict_list(res_dicts)
  pushable_list = nil
  if res_dicts.is_a?(Array)
    pushable_list = res_dicts
  elsif res_dicts.is_a?(Hash)
    pushable_list = [res_dicts]
  end

  if pushable_list.present?
    #noinspection RubyNilAnalysis
    pushable_list.select do |item|
      item.present? && item.is_a?(Hash)
    end.map(&:deep_symbolize_keys).compact
  else
    []
  end
end

.select_res_dicts_blacklist(res_dicts, rule_dicts) ⇒ Array<Hash>

Returns res dicts that match zero rules

Parameters:

  • res_dicts (Array<Hash>)

    k8s res-hashes

  • rule_dicts (Array<String>)

    list of simple k8s res-ids by which to filter

Returns:

  • (Array<Hash>)

    list of clean and filtered hashes



133
134
135
136
137
138
139
140
141
# File 'lib/utils/mixing.rb', line 133

def self.select_res_dicts_blacklist(res_dicts, rule_dicts)
  _res_dicts = res_dicts.compact.map(&:deep_symbolize_keys).to_a
  return _res_dicts if (rule_dicts || []).compact.empty?
  _res_dicts.reject do |res_dict|
    rule_dicts.any? do |rule_dict|
      self.res_dict_matches_rule?(res_dict, rule_dict)
    end
  end
end

.select_res_dicts_whitelist(res_dicts, rule_dicts) ⇒ Array<Hash>

Returns res dicts that match one or more rules

Parameters:

  • res_dicts (Array<Hash>)

    k8s res-hashes

  • rule_dicts (Array<String>)

    list of simple k8s res-ids by which to filter

Returns:

  • (Array<Hash>)

    list of clean and filtered hashes



118
119
120
121
122
123
124
125
126
# File 'lib/utils/mixing.rb', line 118

def self.select_res_dicts_whitelist(res_dicts, rule_dicts)
  _res_dicts = res_dicts.compact.map(&:deep_symbolize_keys).to_a
  return _res_dicts if (rule_dicts || []).compact.empty?
  _res_dicts.select do |res_dict|
    rule_dicts.any? do |rule_dict|
      self.res_dict_matches_rule?(res_dict, rule_dict)
    end
  end
end

.str_cmp(rule_str, actual_str) ⇒ TrueClass, FalseClass

Checks whether the value matching string given in a kerbi resource selector dict matches the value of the attribute in the Kubernetes-style resource dict. Works by performing a regex check on the two values with a full stop e.g ^$.

Parameters:

  • rule_str (String)

    the regex to test the candidate string

  • actual_str (String)

    the candidate string being tested

Returns:

  • (TrueClass, FalseClass)

    true if the rule matches the input



173
174
175
176
177
# File 'lib/utils/mixing.rb', line 173

def self.str_cmp(rule_str, actual_str)
  final_regex = Regexp.new("^#{rule_str}$")
  match_result = actual_str =~ final_regex
  !match_result.nil?
end

.yaml_file_to_dicts(fname, opts = {}) ⇒ Array<Hash>

Loads a YAML/JSON/ERB file, parses it, interpolates it, and returns the resulting dicts.

Parameters:

  • fname (String)

    simplified or absolute path of file

  • extras (Hash)

    additional hash passed to ERB

Returns:

  • (Array<Hash>)

    list of res-hashes



23
24
25
26
27
28
29
30
31
# File 'lib/utils/mixing.rb', line 23

def self.yaml_file_to_dicts(fname, opts={})
  contents = File.read(fname)
  begin
    self.yaml_str_to_dicts(contents, **opts)
  rescue Error => e
    STDERR.puts "Exception below from file #{fname}"
    raise e
  end
end

.yaml_str_to_dicts(yaml_str, opts = {}) ⇒ Array<Hash>

Parses and interpolates YAML or JSON dicts and outputs their symbol-keyed Hash forms.

Parameters:

  • yaml_str (String)

    plain yaml, json, or erb string

  • extras (Hash)

    additional hash passed to ERB

Returns:

  • (Array<Hash>)

    list of inflated dicts



11
12
13
14
15
# File 'lib/utils/mixing.rb', line 11

def self.yaml_str_to_dicts(yaml_str, opts={})
  interpolated_yaml = self.interpolate_erb_string(yaml_str, **opts)
  hashes = YAML.load_stream(interpolated_yaml)
  self.clean_and_filter_dicts(hashes, **opts)
end

.yamls_in_dir_to_dicts(pwd, dir, opts = {}) ⇒ Array<Hash>

Loads, interpolates, and parses all dicts found in all YAML/JSON/ERB files in a given directory.

Parameters:

  • dir (String)

    relative or absolute path of the directory

  • file_blacklist (Array<String>)

    list of filenames to avoid

Returns:

  • (Array<Hash>)

    array of processed dicts



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/utils/mixing.rb', line 51

def self.yamls_in_dir_to_dicts(pwd, dir, opts={})
  file_blacklist = opts.delete(:file_blacklist)
  blacklist = file_blacklist || []

  dir ||= pwd
  dir = "#{pwd}/#{dir}" if dir && pwd && dir.start_with?(".")
  yaml_files = Dir["#{dir}/*.yaml"]
  erb_files = Dir["#{dir}/*.yaml.erb"]

  (yaml_files + erb_files).map do |fname|
    is_blacklisted = blacklist.include?(File.basename(fname))
    unless is_blacklisted
      self.yaml_file_to_dicts(fname, **opts)
    end
  end.compact.flatten
end