module BjnInventory class ByKey < Hash def escape_name(value) value.gsub(/[^a-zA-Z0-9_-]+/, '_') end def _field_groups(fields, device, sep='__') fields = [fields] unless fields.respond_to? :inject value_map = fields.map do |field| values = device[field] values = [values] unless values.respond_to? :map values.map { |val| escape_name(val) } end # # So now we have an array of arrays, eg.: # fields='region' => # [['dc2']] # # fields=['roles', 'region'] => # [['web', ['dc2']] # 'db'], # groups = if fields.length == 1 value_map.first else driving_array, *rest = value_map driving_array.product(*rest).map { |compound_value| compound_value.join(sep) } end groups end # This basically builds an ansible inventory given a hash of hostvars def to_groups(kwargs) group_by = kwargs[:group_by] if group_by.empty? raise ArgumentError, "Expected group_by either as keyword or as argument list" end logger = kwargs[:logger] || BjnInventory::DefaultLogger.new # We need at least one field to create groups separator = kwargs[:separator] || '__' groups = { } self.each do |name, device_hash| group_by.each do |group_field_spec| group_field_spec = [group_field_spec] unless group_field_spec.respond_to? :all? if group_field_spec.all? { |field| !device_hash[field].nil? && !device_hash[field].empty? } field_groups = _field_groups(group_field_spec, device_hash, separator) field_groups.each do |group_name| groups[group_name] = [ ] unless groups.has_key? group_name groups[group_name] << name end end end end # I can't really do children, they need to be generators and I'm not # about that right now. Save it for ansible. groups end end end