Project

General

Profile

« Previous | Next » 

Revision e76ac9ca

Added by Ohad Levy over 11 years ago

  • ID e76ac9ca4690f34791d726ccac41373e43616df6

fixes #2003 - Improve Parameterized classes values retrieval time

This patch adds a new classification class which
tries to fetch all values at once

The initial implementation cared about a name / value at a time
however getting all at once (e.g. during a puppet ENC call) is much more
common.

This patch creates in memory tree of all possible values and process
them in memory instead of asking the database for each possible match.

View differences:

app/models/classification.rb
class Classification
delegate :hostgroup, :environment_id,
:to => :host
def initialize args = { }
@host = args[:host]
end
def enc
klasses = { }
key_hash = hashed_class_parameters
values = values_hash
classes.each do |klass|
klasses[klass.name] ||= { }
if key_hash[klass.id]
key_hash[klass.id].each do |param|
klasses[klass.name][param.to_s] = values[param.to_s] ? values[param.to_s][:value] : param.default_value
end
else
klasses[klass.name] = nil
end
end
klasses
end
private
attr_reader :host
def puppetclass_ids
return @puppetclass_ids if @puppetclass_ids
@puppetclass_ids = host.host_classes.pluck(:puppetclass_id)
@puppetclass_ids += HostgroupClass.where(:hostgroup_id => hostgroup.path_ids).pluck(:puppetclass_id) if hostgroup
@puppetclass_ids
end
def classes
Puppetclass.where(:id => puppetclass_ids)
end
def class_parameters
@keys ||= LookupKey.includes(:environment_classes).parameters_for_class(puppetclass_ids, environment_id)
end
def possible_value_orders
class_parameters.select do |key|
# take only keys with actual values
key.lookup_values_count > 0 # we use counter cache, so its safe to make that query
end.map(&:path_elements).flatten.uniq
end
def values_hash
values = {}
path2matches.each do |match|
LookupValue.where(:match => match).where(:lookup_key_id => class_parameters.map(&:id)).each do |value|
key = @keys.detect{|k| k.id == value.lookup_key_id }
name = key.to_s
element = match.split(LookupKey::EQ_DELM).first
if values[name].nil?
values[name] = {:value => value.value, :element => element}
else
if key.path.index(element) < key.path.index(values[name][:element])
values[name] = {:value => value.value, :element => element}
end
end
end
end
values
end
def hashed_class_parameters
h = {}
class_parameters.each do |key|
klass_id = key.environment_classes.first.puppetclass_id
h[klass_id] ||= []
h[klass_id] << key
end
h
end
# Generate possible lookup values type matches to a given host
def path2matches
matches = []
possible_value_orders.each do |rule|
match = []
rule.each do |element|
match << "#{element}#{LookupKey::EQ_DELM}#{attr_to_value(element)}"
end
matches << match.join(LookupKey::KEY_DELM)
end
matches
end
# translates an element such as domain to its real value per host
# tries to find the host attribute first, parameters and then fallback to a puppet fact.
def attr_to_value element
# direct host attribute
return host.send(element) if host.respond_to?(element)
# host parameter
return host.host_params[element] if host.host_params.include?(element)
# fact attribute
if (fn = host.fact_names.first(:conditions => { :name => element }))
return FactValue.where(:host_id => host.id, :fact_name_id => fn.id).first.value
end
end
def path_elements path = nil
path.split.map do |paths|
paths.split(LookupKey::KEY_DELM).map do |element|
element
end
end
end
end
app/models/host.rb
end
def lookup_keys_class_params
p={}
classes = all_puppetclasses
keys = EnvironmentClass.parameters_for_class(classes.map(&:id), environment_id).includes(:lookup_key).group_by(&:puppetclass_id)
classes.each do |klass|
p[klass.name] = nil
keys[klass.id].map(&:lookup_key).each do |lookup_key|
p[klass.name] ||= {}
value = lookup_key.value_for(self)
p[klass.name].merge!({lookup_key.key => value})
end if keys[klass.id]
end
p
Classification.new(:host => self).enc
end
# align common mac and ip address input
app/models/lookup_key.rb
default_scope :order => 'lookup_keys.key'
scope :override, where(:override => true)
scope :parameters_for_class, lambda {|puppetclass_ids, environment_id|
override.joins(:environment_classes).where(:environment_classes => {:puppetclass_id => puppetclass_ids, :environment_id => environment_id})
}
def to_param
"#{id}-#{key}"
end

Also available in: Unified diff