foreman/app/models/puppetclass.rb @ 88275be4
c6eee281 | Ohad Levy | class Puppetclass < ActiveRecord::Base
|
|
acfbc458 | Marek Hulan | include Authorizable
|
|
e44f5c1c | Daniel Lobato | include ScopedSearchExtensions
|
|
8b737c9c | Joseph Magen | extend FriendlyId
|
|
friendly_id :name
|
|||
e768c976 | Tomas Strachota | include Parameterizable::ByIdName
|
|
e44f5c1c | Daniel Lobato | ||
3034e8e2 | Ori Rabin | validates_lengths_from_database
|
|
ff8cc704 | Joseph Mitchell Magen | before_destroy EnsureNotUsedBy.new(:hosts, :hostgroups)
|
|
f8d94608 | Amos Benari | has_many :environment_classes, :dependent => :destroy
|
|
has_many :environments, :through => :environment_classes, :uniq => true
|
|||
c6eee281 | Ohad Levy | has_and_belongs_to_many :operatingsystems
|
|
83683ed0 | Tomer Brisker | has_many :hostgroup_classes
|
|
has_many :hostgroups, :through => :hostgroup_classes, :dependent => :destroy
|
|||
has_many :host_classes
|
|||
has_many_hosts :through => :host_classes, :dependent => :destroy
|
|||
111cde57 | Joseph Magen | has_many :config_group_classes
|
|
83683ed0 | Tomer Brisker | has_many :config_groups, :through => :config_group_classes, :dependent => :destroy
|
|
6b4b489f | Ori Rabin | has_many :lookup_keys, :inverse_of => :puppetclass, :dependent => :destroy, :class_name => 'VariableLookupKey'
|
|
bb3572ff | Daniel Lobato | accepts_nested_attributes_for :lookup_keys, :reject_if => ->(a) { a[:key].blank? }, :allow_destroy => true
|
|
f8d94608 | Amos Benari | # param classes
|
|
has_many :class_params, :through => :environment_classes, :uniq => true,
|
|||
6b4b489f | Ori Rabin | :source => :puppetclass_lookup_key, :conditions => 'environment_classes.puppetclass_lookup_key_id is NOT NULL'
|
|
bb3572ff | Daniel Lobato | accepts_nested_attributes_for :class_params, :reject_if => ->(a) { a[:key].blank? }, :allow_destroy => true
|
|
6b4b489f | Ori Rabin | ||
dff926cb | Tomer Brisker | validates :name, :uniqueness => true, :presence => true, :no_whitespace => true
|
|
6b4b489f | Ori Rabin | audited :allow_mass_assignment => true, :except => [:total_hosts, :variable_lookup_keys_count, :global_class_params_count]
|
|
f8e711fe | Ohad Levy | ||
bbf64d99 | Joseph Magen | alias_attribute :smart_variables, :lookup_keys
|
|
alias_attribute :smart_variable_ids, :lookup_key_ids
|
|||
alias_attribute :smart_class_parameters, :class_params
|
|||
alias_attribute :smart_class_parameter_ids, :class_param_ids
|
|||
bb3572ff | Daniel Lobato | default_scope -> { order('puppetclasses.name') }
|
|
af6e2624 | Ohad Levy | ||
ac7fe332 | Ohad Levy | scoped_search :on => :name, :complete_value => :true
|
|
83683ed0 | Tomer Brisker | scoped_search :on => :total_hosts
|
|
df471c78 | Stephen Benjamin | scoped_search :on => :global_class_params_count, :rename => :params_count # Smart Parameters
|
|
6b4b489f | Ori Rabin | scoped_search :on => :variable_lookup_keys_count, :rename => :variables_count # Smart Variables
|
|
ac7fe332 | Ohad Levy | scoped_search :in => :environments, :on => :name, :complete_value => :true, :rename => "environment"
|
|
scoped_search :in => :hostgroups, :on => :name, :complete_value => :true, :rename => "hostgroup"
|
|||
d20aba2b | Joseph Magen | scoped_search :in => :config_groups, :on => :name, :complete_value => :true, :rename => "config_group"
|
|
7d46a25e | Ohad Levy | scoped_search :in => :hosts, :on => :name, :complete_value => :true, :rename => "host", :ext_method => :search_by_host, :only_explicit => true
|
|
0126385b | Lukas Zapletal | scoped_search :in => :class_params, :on => :key, :complete_value => :true, :only_explicit => true
|
|
31207a31 | Ohad Levy | ||
bb3572ff | Daniel Lobato | scope :not_in_any_environment, -> { includes(:environment_classes).where(:environment_classes => {:environment_id => nil}) }
|
|
31207a31 | Ohad Levy | ||
bd46fa41 | Ohad Levy | # returns a hash containing modules and associated classes
|
|
5f029ed6 | Daniel Lobato | def self.classes2hash(classes)
|
|
bd46fa41 | Ohad Levy | hash = {}
|
|
for klass in classes
|
|||
67799065 | Ohad Levy | if (mod = klass.module_name)
|
|
bd46fa41 | Ohad Levy | hash[mod] ||= []
|
|
hash[mod] << klass
|
|||
else
|
|||
next
|
|||
end
|
|||
92b7b44d | Joseph Magen | end
|
|
96144a47 | Daniel Lobato | hash
|
|
92b7b44d | Joseph Magen | end
|
|
# For API v2 - eliminate node :puppetclass for each object. returns a hash containing modules and associated classes
|
|||
5f029ed6 | Daniel Lobato | def self.classes2hash_v2(classes)
|
|
92b7b44d | Joseph Magen | hash = {}
|
|
classes.each do |klass|
|
|||
if (mod = klass.module_name)
|
|||
hash[mod] ||= []
|
|||
hash[mod] << {:id => klass.id, :name => klass.name, :created_at => klass.created_at, :updated_at => klass.updated_at}
|
|||
end
|
|||
bd46fa41 | Ohad Levy | end
|
|
96144a47 | Daniel Lobato | hash
|
|
bd46fa41 | Ohad Levy | end
|
|
# returns module name (excluding of the class name)
|
|||
4ebe38c7 | Ohad Levy | # if class separator does not exists (the "::" chars), then returns the whole class name
|
|
bd46fa41 | Ohad Levy | def module_name
|
|
67799065 | Ohad Levy | (i = name.index("::")) ? name[0..i-1] : name
|
|
bd46fa41 | Ohad Levy | end
|
|
# returns class name (excluding of the module name)
|
|||
def klass
|
|||
67799065 | Ohad Levy | name.gsub(module_name+"::","")
|
|
163711af | Ohad Levy | end
|
|
83683ed0 | Tomer Brisker | # return host ids from config groups by type
|
|
def host_ids_from_config_groups(host_type)
|
|||
ids = config_groups.joins(:host_config_groups)
|
|||
.where("host_config_groups.host_type='#{host_type}'")
|
|||
.pluck('host_config_groups.host_id') unless config_group_classes.empty?
|
|||
ids || []
|
|||
end
|
|||
def all_hostgroups(with_descendants = true)
|
|||
ids = hostgroup_ids
|
|||
ids += host_ids_from_config_groups('Hostgroup')
|
|||
hgs = Hostgroup.unscoped.where(:id => ids.uniq)
|
|||
eb8c02e1 | Tomer Brisker | hgs = hgs.flat_map(&:subtree).uniq if with_descendants
|
|
hgs
|
|||
83683ed0 | Tomer Brisker | end
|
|
88275be4 | Tom Caspy | def all_host_ids
|
|
83683ed0 | Tomer Brisker | ids = host_ids
|
|
88275be4 | Tom Caspy | ids += Host::Managed.unscoped.where(:hostgroup_id => all_hostgroups.map(&:id)).pluck(:id)
|
|
83683ed0 | Tomer Brisker | ids += host_ids_from_config_groups('Host::Base')
|
|
88275be4 | Tom Caspy | ids.uniq
|
|
83683ed0 | Tomer Brisker | end
|
|
def update_total_hosts
|
|||
88275be4 | Tom Caspy | update_attribute(:total_hosts, all_host_ids.size)
|
|
83683ed0 | Tomer Brisker | end
|
|
a67b0923 | Paul Kelly | # Populates the rdoc tree with information about all the classes in your modules.
|
|
# Firstly, we prepare the modules tree
|
|||
# Secondly we run puppetdoc over the modulespath and manifestdir for all environments
|
|||
# The results are written into document_root/puppet/rdoc/<env>/<class>"
|
|||
5f029ed6 | Daniel Lobato | def self.rdoc(root)
|
|
a67b0923 | Paul Kelly | debug, verbose = false, false
|
|
relocated = root != "/" # This is true if the prepare phase copied the modules tree
|
|||
# Retrieve an optional http server's DocumentRoot from the settings.yaml file, and prepare it for writing
|
|||
76607ed5 | Ohad Levy | doc_root = Pathname.new(Setting[:document_root])
|
|
a67b0923 | Paul Kelly | doc_root.mkpath
|
|
unless doc_root.directory? and doc_root.writable?
|
|||
puts "Unable to write html to #{doc_root}"
|
|||
return false
|
|||
end
|
|||
aa6430ed | Paul Kelly | validator = '<div id="validator-badges">'
|
|
a67b0923 | Paul Kelly | # For each environment we write a puppetdoc tree
|
|
for env, path in Environment.puppetEnvs
|
|||
# We may need to rewrite the modulepaths because they have been changed by the prepare step
|
|||
modulepaths = relocated ? path.split(":").map{|p| root + p}.join(":") : path
|
|||
# Identify and prepare the output directory
|
|||
b04622a4 | Lee Lowder | out = doc_root + env
|
|
a67b0923 | Paul Kelly | out.rmtree if out.directory?
|
|
aa6430ed | Paul Kelly | replacement = "<div id=\\\"validator-badges\\\"><small><a href=\\\"/puppet/rdoc/#{env}/\\\">[Browser]</a></small>"
|
|
a67b0923 | Paul Kelly | # Create the documentation
|
|
aa6430ed | Paul Kelly | ||
815923d0 | Paul Kelly | puts "*********Proccessing environment #{env} *************"
|
|
aa6430ed | Paul Kelly | cmd = "puppetdoc --output #{out} --modulepath #{modulepaths} -m rdoc"
|
|
e4fde4e3 | Ivan Nečas | puts cmd if Foreman.in_rake?
|
|
aa6430ed | Paul Kelly | sh cmd do |ok, res|
|
|
815923d0 | Paul Kelly | if ok
|
|
# Add a link to the class browser
|
|||
96144a47 | Daniel Lobato | files = `find #{out} -exec grep -l 'validator-badges' {} \\; 2>/dev/null`.gsub(/\n/, " ")
|
|
815923d0 | Paul Kelly | if files.empty?
|
|
warn "No files to update with the browser link in #{out}. This is probably due to a previous error."
|
|||
else
|
|||
cmd = "ruby -p -i -e '$_.gsub!(/#{validator}/,\"#{replacement}\")' #{files}"
|
|||
puts cmd if debug
|
|||
afe02d30 | Daniel Lobato | sh cmd
|
|
815923d0 | Paul Kelly | end
|
|
# Relocate the paths for files and references if the manifests were relocated and sanitized
|
|||
96144a47 | Daniel Lobato | if relocated and (files = `find #{out} -exec grep -l '#{root}' {} \\;`.gsub(/\n/, " ")) != ""
|
|
815923d0 | Paul Kelly | puts "Rewriting..." if verbose
|
|
cmd = "ruby -p -i -e 'rex=%r{#{root}};$_.gsub!(rex,\"\")' #{files}"
|
|||
puts cmd if debug
|
|||
sh cmd
|
|||
# Now relocate the files/* files to match the rewritten url
|
|||
mv Dir.glob("#{out}/files/#{root}/*"), "#{out}/files", :verbose => verbose
|
|||
end
|
|||
a67b0923 | Paul Kelly | else
|
|
815923d0 | Paul Kelly | logger.warn "Failed to process puppetdocs for #{out} while executing #{cmd}"
|
|
puts "Failed to process puppetdocs for #{out} while executing #{cmd}"
|
|||
a67b0923 | Paul Kelly | end
|
|
end
|
|||
815923d0 | Paul Kelly | puts
|
|
a67b0923 | Paul Kelly | end
|
|
end
|
|||
# Optionally creates a copy of the current puppet modules and sanitizes it.
|
|||
# If your 'live' manifests and modules can be parsed by puppetdoc
|
|||
4ebe38c7 | Ohad Levy | # then you do not need to do this step. (Unfortunately some sites have circular
|
|
a67b0923 | Paul Kelly | # symlinks which have to be removed.)
|
|
017e1049 | Ohad Levy | # If the executable Rails,root/script/rdoc_prepare_script exists then it is run
|
|
a67b0923 | Paul Kelly | # and passed a list of all directory paths in all environments.
|
|
# It should return the directory into which it has copied the cleaned modules"
|
|||
5f029ed6 | Daniel Lobato | def self.prepare_rdoc(root)
|
|
a67b0923 | Paul Kelly | debug, verbose = false, false
|
|
017e1049 | Ohad Levy | prepare_script = Pathname.new(Rails.root) + "script/rdoc_prepare_script.rb"
|
|
a67b0923 | Paul Kelly | if prepare_script.executable?
|
|
dirs = Environment.puppetEnvs.values.join(":").split(":").uniq.sort.join(" ")
|
|||
puts "Running #{prepare_script} #{dirs}" if debug
|
|||
96144a47 | Daniel Lobato | location = `#{prepare_script} #{dirs}`
|
|
4f7a4d0b | David Davis | if $CHILD_STATUS == 0
|
|
a67b0923 | Paul Kelly | root = location.chomp
|
|
puts "Relocated modules to #{root}" if verbose
|
|||
end
|
|||
else
|
|||
puts "No executable #{prepare_script} found so using the uncopied module sources" if verbose
|
|||
end
|
|||
root
|
|||
end
|
|||
3aa6ea3f | Ohad Levy | ||
31207a31 | Ohad Levy | def self.search_by_host(key, operator, value)
|
|
387b764b | Amos Benari | conditions = sanitize_sql_for_conditions(["hosts.name #{operator} ?", value_to_sql(operator, value)])
|
|
0e1c5371 | Tomer Brisker | direct = Puppetclass.joins(:hosts).where(conditions).uniq.pluck('puppetclasses.id')
|
|
aca6fd3a | Joseph Mitchell Magen | hostgroup = Hostgroup.joins(:hosts).where(conditions).first
|
|
0e1c5371 | Tomer Brisker | indirect = hostgroup.blank? ? [] : HostgroupClass.where(:hostgroup_id => hostgroup.path_ids).uniq.pluck('puppetclass_id')
|
|
aca6fd3a | Joseph Mitchell Magen | return { :conditions => "1=0" } if direct.blank? && indirect.blank?
|
|
puppet_classes = (direct + indirect).uniq
|
|||
{ :conditions => "puppetclasses.id IN(#{puppet_classes.join(',')})" }
|
|||
31207a31 | Ohad Levy | end
|
|
6e50fa1d | Ohad Levy | end
|