foreman/app/models/lookup_key.rb @ f8d94608
0265427b | Ohad Levy | class LookupKey < ActiveRecord::Base
|
|
f8d94608 | Amos Benari | include Authorization
|
|
9afa092e | Ohad Levy | ||
f8d94608 | Amos Benari | KEY_TYPES = %w( string boolean integer real array hash yaml json )
|
|
VALIDATOR_TYPES = %w( regexp list )
|
|||
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON', 'yes', 'YES', 'y', 'Y'].to_set
|
|||
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF', 'no', 'NO', 'n', 'N'].to_set
|
|||
9afa092e | Ohad Levy | ||
KEY_DELM = ","
|
|||
EQ_DELM = "="
|
|||
f8d94608 | Amos Benari | serialize :default_value
|
|
9afa092e | Ohad Levy | belongs_to :puppetclass
|
|
f8d94608 | Amos Benari | has_many :environment_classes, :dependent => :destroy
|
|
has_many :environments, :through => :environment_classes, :uniq => true
|
|||
has_one :param_class, :through => :environment_classes, :class_name => 'Puppetclass', :source => :puppetclass
|
|||
9afa092e | Ohad Levy | has_many :lookup_values, :dependent => :destroy, :inverse_of => :lookup_key
|
|
08bf6aba | Ohad Levy | accepts_nested_attributes_for :lookup_values, :reject_if => lambda { |a| a[:value].blank? }, :allow_destroy => true
|
|
f8d94608 | Amos Benari | ||
before_validation :validate_and_cast_default_value
|
|||
validates_uniqueness_of :key, :unless => Proc.new{|p| p.is_param?}
|
|||
validates_presence_of :key
|
|||
validates_presence_of :puppetclass_id, :unless => Proc.new {|k| k.is_param?}
|
|||
validates_inclusion_of :validator_type, :in => VALIDATOR_TYPES, :message => "invalid", :allow_blank => true, :allow_nil => true
|
|||
validates_inclusion_of :key_type, :in => KEY_TYPES, :message => "invalid", :allow_blank => true, :allow_nil => true
|
|||
validate :validate_list, :validate_regexp
|
|||
0265427b | Ohad Levy | validates_associated :lookup_values
|
|
f8d94608 | Amos Benari | validate :ensure_type
|
|
0265427b | Ohad Levy | ||
9afa092e | Ohad Levy | before_save :sanitize_path
|
|
scoped_search :on => :key, :complete_value => true, :default_order => true
|
|||
f8d94608 | Amos Benari | scoped_search :on => :override, :complete_value => {:true => true, :false => false}
|
|
scoped_search :in => :param_class, :on => :name, :rename => :puppetclass, :complete_value => true
|
|||
9afa092e | Ohad Levy | scoped_search :in => :lookup_values, :on => :value, :rename => :value, :complete_value => true
|
|
default_scope :order => 'LOWER(lookup_keys.key)'
|
|||
def to_param
|
|||
f8d94608 | Amos Benari | "#{id}-#{key}"
|
|
0265427b | Ohad Levy | end
|
|
b28fdce4 | Ohad Levy | def to_s
|
|
key
|
|||
end
|
|||
9afa092e | Ohad Levy | def value_for host
|
|
path2matches(host).each do |match|
|
|||
67799065 | Ohad Levy | if (v = lookup_values.find_by_match(match))
|
|
9afa092e | Ohad Levy | return v.value
|
|
end
|
|||
f8d94608 | Amos Benari | end if lookup_values.any?
|
|
9afa092e | Ohad Levy | default_value
|
|
end
|
|||
def path
|
|||
f8d94608 | Amos Benari | path = read_attribute(:path)
|
|
path.blank? ? array2path(Setting["Default_variables_Lookup_Path"]) : path
|
|||
9afa092e | Ohad Levy | end
|
|
def path=(v)
|
|||
f8d94608 | Amos Benari | using_default = v.tr("\r","") == array2path(Setting["Default_variables_Lookup_Path"])
|
|
write_attribute(:path, using_default ? nil : v)
|
|||
end
|
|||
def default_value_before_type_cast
|
|||
value_before_type_cast default_value
|
|||
end
|
|||
def value_before_type_cast val
|
|||
case validator_type.to_sym
|
|||
when :json
|
|||
val = JSON.dump val
|
|||
when :yaml, :hash
|
|||
val = YAML.dump val
|
|||
val.sub! /\A---\s*$\n/, ''
|
|||
when :array
|
|||
val = val.inspect
|
|||
end unless validator_type.blank?
|
|||
val
|
|||
end
|
|||
# Returns the casted value, or raises a TypeError
|
|||
def cast_validate_value value
|
|||
method = "cast_value_#{validator_type}".to_sym
|
|||
return value unless self.respond_to? method, true
|
|||
self.send(method, value) rescue raise TypeError
|
|||
9afa092e | Ohad Levy | end
|
|
b05278e3 | Ohad Levy | def as_json(options={})
|
|
f8d94608 | Amos Benari | super({:only => [:key, :is_param, :required, :override, :description, :default_value, :id]}.merge(options))
|
|
b05278e3 | Ohad Levy | end
|
|
9afa092e | Ohad Levy | private
|
|
# Generate possible lookup values type matches to a given host
|
|||
def path2matches host
|
|||
raise "Invalid Host" unless host.is_a?(Host)
|
|||
matches = []
|
|||
path_elements.each do |rule|
|
|||
match = []
|
|||
rule.each do |element|
|
|||
match << "#{element}#{EQ_DELM}#{attr_to_value(host,element)}"
|
|||
end
|
|||
matches << match.join(KEY_DELM)
|
|||
end
|
|||
matches
|
|||
end
|
|||
# translates an element such as domain to its real value per host
|
|||
8ea536e3 | Ohad Levy | # tries to find the host attribute first, parameters and then fallback to a puppet fact.
|
|
9afa092e | Ohad Levy | def attr_to_value host, element
|
|
# direct host attribute
|
|||
return host.send(element) if host.respond_to?(element)
|
|||
8ea536e3 | Ohad Levy | # host parameter
|
|
return host.host_params[element] if host.host_params.include?(element)
|
|||
9afa092e | Ohad Levy | # fact attribute
|
|
67799065 | Ohad Levy | if (fn = host.fact_names.first(:conditions => { :name => element }))
|
|
017e1049 | Ohad Levy | return FactValue.where(:host_id => host.id, :fact_name_id => fn.id).first.value
|
|
9afa092e | Ohad Levy | end
|
|
end
|
|||
def path_elements
|
|||
path.split.map do |paths|
|
|||
paths.split(KEY_DELM).map do |element|
|
|||
element
|
|||
end
|
|||
end
|
|||
end
|
|||
def sanitize_path
|
|||
self.path = path.tr("\s","").downcase unless path.blank?
|
|||
end
|
|||
def array2path array
|
|||
raise "invalid path" unless array.is_a?(Array)
|
|||
array.map do |sub_array|
|
|||
sub_array.is_a?(Array) ? sub_array.join(KEY_DELM) : sub_array
|
|||
end.join("\n")
|
|||
end
|
|||
f8d94608 | Amos Benari | ||
def validate_and_cast_default_value
|
|||
return true if default_value.nil?
|
|||
begin
|
|||
self.default_value = cast_validate_value self.default_value
|
|||
true
|
|||
rescue
|
|||
errors.add(:default_value, "is invalid")
|
|||
false
|
|||
end
|
|||
end
|
|||
def cast_value_boolean value
|
|||
return true if TRUE_VALUES.include? value
|
|||
return false if FALSE_VALUES.include? value
|
|||
raise TypeError
|
|||
end
|
|||
def cast_value_integer value
|
|||
return value.to_i if value.is_a?(Numeric)
|
|||
if value.is_a?(String)
|
|||
if value =~ /^0x[0-9a-f]+$/i
|
|||
value.to_i(16)
|
|||
elsif value =~ /^0[0-7]+$/
|
|||
value.to_i(8)
|
|||
elsif value =~ /^-?\d+$/
|
|||
value.to_i
|
|||
else
|
|||
raise TypeError
|
|||
end
|
|||
end
|
|||
end
|
|||
def cast_value_real value
|
|||
return value if value.is_a? Numeric
|
|||
if value.is_a?(String)
|
|||
if value =~ /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?$/
|
|||
value.to_f
|
|||
else
|
|||
cast_value_integer value
|
|||
end
|
|||
end
|
|||
end
|
|||
def load_yaml_or_json value
|
|||
return value unless value.is_a? String
|
|||
begin
|
|||
JSON.load value
|
|||
rescue
|
|||
YAML.load value
|
|||
end
|
|||
end
|
|||
def cast_value_array value
|
|||
return value if value.is_a? Array
|
|||
return value.to_a if not value.is_a? String and value.is_a? Enumerable
|
|||
value = load_yaml_or_json value
|
|||
raise TypeError unless value.is_a? Array
|
|||
value
|
|||
end
|
|||
def cast_value_hash value
|
|||
return value if value.is_a? Hash
|
|||
value = load_yaml_or_json value
|
|||
raise TypeError unless value.is_a? Hash
|
|||
value
|
|||
end
|
|||
def cast_value_yaml value
|
|||
value = YAML.load value
|
|||
end
|
|||
def cast_value_json value
|
|||
value = JSON.load value
|
|||
end
|
|||
def ensure_type
|
|||
if puppetclass_id.present? and is_param?
|
|||
self.errors.add(:base, 'Global variable or class Parameter, not both')
|
|||
end
|
|||
end
|
|||
9afa092e | Ohad Levy | def validate_regexp
|
|
return true unless (validator_type == 'regexp')
|
|||
errors.add(:default_value, "is invalid") and return false unless (default_value =~ /#{validator_rule}/)
|
|||
end
|
|||
def validate_list
|
|||
return true unless (validator_type == 'list')
|
|||
f8d94608 | Amos Benari | errors.add(:default_value, "#{default_value} is not one of #{validator_rule}") and return false unless validator_rule.split(KEY_DELM).map(&:strip).include?(default_value)
|
|
9afa092e | Ohad Levy | end
|
|
0265427b | Ohad Levy | end
|