module Kucodiff

Constants

VERSION

Public Class Methods

diff(files, ignore: false, indent_pod: false, expected: {}) click to toggle source
# File lib/kucodiff.rb, line 5
def diff(files, ignore: false, indent_pod: false, expected: {})
  raise ArgumentError, "Need 2+ files" if files.size < 2

  base = files.shift
  base_template = read(base)

  diff = files.each_with_object({}) do |other, all|
    other_template = read(other)
    result =
      if indent_pod
        different_keys_pod_indented(base_template, other_template)
      else
        different_keys(base_template, other_template)
      end
    result.reject! { |k| k =~ ignore } if ignore
    all["#{base}-#{other}"] = result.sort
  end

  expected.each do |k, v|
    result = xor(diff[k] || [], v)
    result.empty? ? diff.delete(k) : diff[k] = result
  end

  diff
end

Private Class Methods

different_keys(a, b) click to toggle source
# File lib/kucodiff.rb, line 87
def different_keys(a, b)
  (a.keys + b.keys).uniq.select { |k| a[k] != b[k] }
end
different_keys_pod_indented(*templates) click to toggle source
# File lib/kucodiff.rb, line 69
def different_keys_pod_indented(*templates)
  ignore_unindented = false
  prefix = "spec.template."

  templates.map! do |template|
    if template["kind"] == "Pod"
      ignore_unindented = true
      Hash[template.map { |k,v| [prefix + k, v] }]
    else
      template
    end
  end

  diff = different_keys(*templates)
  diff.select! { |k| k.start_with?(prefix) } if ignore_unindented
  diff
end
flat_hash(input, base = nil, all = {}) click to toggle source

stackoverflow.com/questions/9647997/converting-a-nested-hash-into-a-flat-hash

# File lib/kucodiff.rb, line 100
def flat_hash(input, base = nil, all = {})
  if input.is_a?(Array)
    input = input.each_with_index.to_a.each(&:reverse!)
  end

  if input.is_a?(Hash) || input.is_a?(Array)
    input.each do |k, v|
      flat_hash(v, base ? "#{base}.#{k}" : k, all)
    end
  else
    all[base] = input
  end

  all
end
hashify_container_env!(content) click to toggle source

make env comparable

# File lib/kucodiff.rb, line 52
def hashify_container_env!(content)
  containers = template(content).fetch('spec', {}).fetch('containers', [])
  containers.each do |container|
    next unless container['env']
    container['env'] = container['env'].each_with_object({}) do |v, h|
      value_key = (v.keys - ['name']).first
      h[v.fetch('name')] = v.fetch(value_key)
    end
  end
end
hashify_required_env!(content) click to toggle source
# File lib/kucodiff.rb, line 63
def hashify_required_env!(content)
  key = 'samson/required_env'
  annotations = template(content).fetch('metadata', {}).fetch('annotations', {})
  annotations[key] = Hash[annotations[key].strip.split(/[\s,]/).map { |k| [k, true] }] if annotations[key]
end
read(file) click to toggle source
# File lib/kucodiff.rb, line 33
def read(file)
  content =
    if file.end_with?('.yml', '.yaml')
      if RUBY_VERSION >= "2.6.0"
        YAML.load_stream(File.read(file), filename: file) # uncovered
      else
        YAML.load_stream(File.read(file), file) # uncovered
      end
    else
      raise ArgumentError, "unknown file format in #{file}"
    end.first

  hashify_container_env!(content)
  hashify_required_env!(content)

  flat_hash(content)
end
template(content) click to toggle source
# File lib/kucodiff.rb, line 95
def template(content)
  content['kind'] == "Pod" ? content : content.fetch('spec', {}).fetch('template', {})
end
xor(a, b) click to toggle source
# File lib/kucodiff.rb, line 91
def xor(a, b)
  a + b - (a & b)
end