module SousChef::Config

Public Instance Methods

_normalize(hash) click to toggle source
# File lib/souschef/config.rb, line 126
def _normalize(hash)
  hash[:__default__] = hash.delete '__default__' if hash.key? '__default__'
  hash[:__items__] = hash.delete '__items__' if hash.key? '__items__'
end
compile_attribute(value, context, key_stack) click to toggle source
# File lib/souschef/config.rb, line 7
def compile_attribute(value, context, key_stack)
  if value.is_a? Hash
    if value.key? :__items__
      value[:__root__] = context[:__root__]
      context = value
    end
    return compile_attribute_hash(value, context, key_stack)
  elsif value.is_a? String
    return value.gsub(/\{([\w\.0-9]+)\}/) {|m|
      res = context.access $1

      if not res
        puts "Couldn\'t read attribute #{$1} from.."
        ap context
        raise "Couldn\'t read attribute #{$1}"
      end

      if res[/\{([\w\.0-9]+)\}/]
        next compile_attribute(res, context, key_stack)
      end

      res
    }
  end

  value
end
compile_attribute_hash(hash, context=nil, key_stack=[]) click to toggle source

Attribute hash “compiler”

Parses a hash replacing {prop.subprop.subsub} tokens by it's values

Usage:

  • Reference other properties using dot-notation {site.certs.root}

  • Use a :__default__ key to define default values

  • Use an :__items__ key to define the items to create using the default values

  • :__key__ and :__item__ keys only exist inside __default__

  • Overwrite defaults by adding a key with the same name of the item

Example: default = {

name: 'myapp',
user: 'appuser',
certs: {
  root: '/etc/ssl/certs/{name}',
  cert: '{certs.root}/cert.pem'
},
envs: {
  __default__: {
    name: '{__key__}',
    debug: true
  },
  __items__: ['dev', 'staging', 'prod'],
  prod: {
    debug: false
  }
}

}

# File lib/souschef/config.rb, line 66
def compile_attribute_hash(hash, context=nil, key_stack=[])
  context ||= hash
  context[:__key__] = ''

  _normalize(hash)
  _normalize(context)

  if not context.key? :__root__
    context[:__root__] = context
  end

  attr_hash = Hash.new

  hash.each do |key, val|
    if not key.to_s.start_with? '__'
      key_stack.push key
      begin
        attr_hash[key] = compile_attribute(val, context, key_stack)
      rescue Exception => e
        puts "Error compiling value for #{key_stack.join('.')} in..."
        ap context[:__item__]
        raise e
      end
      key_stack.pop
    end
  end

  if hash.key? :__items__

    hash[:__items__].each do |item|
      context[:__key__] = item

      if hash.key? item
        attr_hash[item] = hash[item]
      else
        attr_hash[item] = {}
      end

      if hash.key? :__default__
        attr_hash[item] = hash[:__default__].deep_merge(attr_hash[item])
      end

      context[:__item__] = attr_hash[item]

      attr_hash[item].each do |key, val|
        key_stack.push key
        attr_hash[item][key] = compile_attribute(val, context, key_stack)
        key_stack.pop
      end

    end

  end

  attr_hash.delete :__key__
  attr_hash.delete :__root__
  attr_hash
end