Revision 83683ed0
Added by Tomer Brisker over 9 years ago
app/models/concerns/host_common.rb | ||
---|---|---|
def update_config_group_counters(record)
|
||
record.update_attribute(:hostgroups_count, cnt_hostgroups(record))
|
||
record.update_attribute(:hosts_count, cnt_hosts(record))
|
||
|
||
record.update_puppetclasses_total_hosts
|
||
end
|
||
|
||
end
|
app/models/concerns/puppetclass_total_hosts.rb | ||
---|---|---|
module PuppetclassTotalHosts
|
||
|
||
module Indirect
|
||
extend ActiveSupport::Concern
|
||
|
||
included do
|
||
#updates counters for all puppetclasses affected indirectly
|
||
def update_puppetclasses_total_hosts(relation = nil)
|
||
if self.is_a?(Hostgroup)
|
||
config_groups.each(&:update_puppetclasses_total_hosts) if config_groups.present?
|
||
parent.update_puppetclasses_total_hosts unless is_root?
|
||
end
|
||
puppetclasses.each(&:update_total_hosts) if puppetclasses.present?
|
||
end
|
||
|
||
end
|
||
end
|
||
|
||
module JoinTable
|
||
extend ActiveSupport::Concern
|
||
|
||
included do
|
||
after_save :update_total_hosts
|
||
after_destroy :update_total_hosts
|
||
|
||
def update_total_hosts
|
||
puppetclass.update_total_hosts
|
||
end
|
||
end
|
||
end
|
||
|
||
end
|
app/models/config_group.rb | ||
---|---|---|
audited :allow_mass_assignment => true
|
||
include Authorizable
|
||
include Parameterizable::ByIdName
|
||
include PuppetclassTotalHosts::Indirect
|
||
|
||
validates_lengths_from_database
|
||
|
||
attr_accessible :name, :puppetclass_ids
|
||
|
||
has_many :config_group_classes
|
||
has_many :puppetclasses, :through => :config_group_classes
|
||
has_many :puppetclasses, :through => :config_group_classes, :dependent => :destroy
|
||
has_many :host_config_groups
|
||
has_many_hosts :through => :host_config_groups
|
||
|
app/models/config_group_class.rb | ||
---|---|---|
class ConfigGroupClass < ActiveRecord::Base
|
||
include Authorizable
|
||
include CounterCacheFix
|
||
include PuppetclassTotalHosts::JoinTable
|
||
|
||
audited :associated_with => :config_group, :allow_mass_assignment => true
|
||
attr_accessible :config_group_id, :puppetclass_id
|
app/models/host/managed.rb | ||
---|---|---|
class Host::Managed < Host::Base
|
||
include ReportCommon
|
||
include Hostext::Search
|
||
|
||
PROVISION_METHODS = %w[build image]
|
||
|
||
has_many :host_classes, :dependent => :destroy, :foreign_key => :host_id
|
||
has_many :puppetclasses, :through => :host_classes
|
||
has_many :host_classes, :foreign_key => :host_id
|
||
has_many :puppetclasses, :through => :host_classes, :dependent => :destroy
|
||
belongs_to :hostgroup
|
||
has_many :reports, :dependent => :destroy, :foreign_key => :host_id
|
||
has_many :host_parameters, :dependent => :destroy, :foreign_key => :reference_id, :inverse_of => :host
|
||
... | ... | |
# Custom hooks will be executed after_commit
|
||
after_commit :build_hooks
|
||
before_save :clear_data_on_build
|
||
after_save :update_hostgroups_puppetclasses, :if => :hostgroup_id_changed?
|
||
|
||
def build_hooks
|
||
return unless respond_to?(:old) && old && (build? != old.build?)
|
||
... | ... | |
LookupValue.where(:match => "fqdn=#{fqdn_was}").update_all(:match => lookup_value_match)
|
||
end
|
||
|
||
def update_hostgroups_puppetclasses
|
||
Hostgroup.find(hostgroup_id_was).update_puppetclasses_total_hosts if hostgroup_id_was.present?
|
||
Hostgroup.find(hostgroup_id).update_puppetclasses_total_hosts if hostgroup_id.present?
|
||
end
|
||
|
||
end
|
app/models/host_class.rb | ||
---|---|---|
class HostClass < ActiveRecord::Base
|
||
include Authorizable
|
||
include CounterCacheFix
|
||
include PuppetclassTotalHosts::JoinTable
|
||
|
||
validates_lengths_from_database
|
||
audited :associated_with => :host, :allow_mass_assignment => true
|
||
belongs_to_host :foreign_key => :host_id
|
||
belongs_to :puppetclass, :counter_cache => :hosts_count
|
||
belongs_to_host
|
||
belongs_to :puppetclass
|
||
|
||
validates :host_id, :presence => true
|
||
validates :puppetclass_id, :presence => true, :uniqueness => {:scope => :host_id}
|
app/models/hostgroup.rb | ||
---|---|---|
include HostCommon
|
||
include NestedAncestryCommon
|
||
include ScopedSearchExtensions
|
||
include PuppetclassTotalHosts::Indirect
|
||
|
||
validates_lengths_from_database :except => [:name]
|
||
before_destroy EnsureNotUsedBy.new(:hosts)
|
||
has_many :hostgroup_classes, :dependent => :destroy
|
||
has_many :puppetclasses, :through => :hostgroup_classes
|
||
has_many :hostgroup_classes
|
||
has_many :puppetclasses, :through => :hostgroup_classes, :dependent => :destroy
|
||
validates :name, :format => { :with => /\A(\S+\s?)+\Z/, :message => N_("can't contain trailing white spaces.")}
|
||
validates :root_pass, :allow_blank => true, :length => {:minimum => 8, :message => _('should be 8 characters or more')}
|
||
has_many :group_parameters, :dependent => :destroy, :foreign_key => :reference_id, :inverse_of => :hostgroup
|
||
accepts_nested_attributes_for :group_parameters, :allow_destroy => true
|
||
include ParameterValidators
|
||
has_many_hosts
|
||
has_many_hosts :after_add => :update_puppetclasses_total_hosts,
|
||
:after_remove => :update_puppetclasses_total_hosts
|
||
has_many :template_combinations, :dependent => :destroy
|
||
has_many :config_templates, :through => :template_combinations
|
||
before_save :remove_duplicated_nested_class
|
||
after_save :update_ancestry_puppetclasses, :if => :ancestry_changed?
|
||
|
||
alias_attribute :arch, :architecture
|
||
alias_attribute :os, :operatingsystem
|
||
... | ... | |
new
|
||
end
|
||
|
||
def update_ancestry_puppetclasses
|
||
unscoped_find(ancestry_was.to_s.split('/').last.to_i).update_puppetclasses_total_hosts if ancestry_was.present?
|
||
unscoped_find(ancestry.to_s.split('/').last.to_i).update_puppetclasses_total_hosts if ancestry.present?
|
||
end
|
||
|
||
private
|
||
|
||
def lookup_value_match
|
app/models/hostgroup_class.rb | ||
---|---|---|
class HostgroupClass < ActiveRecord::Base
|
||
include Authorizable
|
||
include CounterCacheFix
|
||
include PuppetclassTotalHosts::JoinTable
|
||
|
||
audited :associated_with => :hostgroup, :allow_mass_assignment => true
|
||
belongs_to :hostgroup
|
app/models/puppetclass.rb | ||
---|---|---|
has_many :environment_classes, :dependent => :destroy
|
||
has_many :environments, :through => :environment_classes, :uniq => true
|
||
has_and_belongs_to_many :operatingsystems
|
||
has_many :hostgroup_classes, :dependent => :destroy
|
||
has_many :hostgroups, :through => :hostgroup_classes
|
||
has_many :host_classes, :dependent => :destroy
|
||
has_many_hosts :through => :host_classes
|
||
has_many :hostgroup_classes
|
||
has_many :hostgroups, :through => :hostgroup_classes, :dependent => :destroy
|
||
has_many :host_classes
|
||
has_many_hosts :through => :host_classes, :dependent => :destroy
|
||
has_many :config_group_classes
|
||
has_many :config_groups, :through => :config_group_classes
|
||
has_many :config_groups, :through => :config_group_classes, :dependent => :destroy
|
||
|
||
has_many :lookup_keys, :inverse_of => :puppetclass, :dependent => :destroy
|
||
accepts_nested_attributes_for :lookup_keys, :reject_if => lambda { |a| a[:key].blank? }, :allow_destroy => true
|
||
... | ... | |
default_scope lambda { order('puppetclasses.name') }
|
||
|
||
scoped_search :on => :name, :complete_value => :true
|
||
scoped_search :on => :hosts_count
|
||
scoped_search :on => :total_hosts
|
||
scoped_search :on => :global_class_params_count, :rename => :params_count # Smart Parameters
|
||
scoped_search :on => :lookup_keys_count, :rename => :variables_count # Smart Variables
|
||
scoped_search :in => :environments, :on => :name, :complete_value => :true, :rename => "environment"
|
||
... | ... | |
name.gsub(module_name+"::","")
|
||
end
|
||
|
||
# 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)
|
||
hgs.flat_map(&:subtree).uniq if with_descendants
|
||
end
|
||
|
||
def all_hosts
|
||
ids = host_ids
|
||
ids += all_hostgroups.flat_map(&:host_ids)
|
||
ids += host_ids_from_config_groups('Host::Base')
|
||
Host::Managed.unscoped.where(:id => ids.uniq)
|
||
end
|
||
|
||
def update_total_hosts
|
||
update_attribute(:total_hosts, all_hosts.count)
|
||
end
|
||
|
||
# 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
|
app/views/puppetclasses/index.html.erb | ||
---|---|---|
<tr>
|
||
<th><%= sort :name, :as => s_("Puppetclass|Name") %></th>
|
||
<th><%= sort :environment, :as => _("Environments and documentation") %></th>
|
||
<th><%= _('Host group') %></th>
|
||
<th><%= sort :hosts_count, :as => _('Hosts'), :default => "DESC" %></th>
|
||
<th><%= _('Host groups') %></th>
|
||
<th><%= sort :total_hosts, :as => _('Hosts'), :default => "DESC" %></th>
|
||
<th><%= sort :params_count, :as => _('Parameters'), :default => "DESC" %></th>
|
||
<th><%= sort :variables_count, :as => _('Variables'), :default => "DESC" %></th>
|
||
<th></th>
|
||
... | ... | |
<% end %>
|
||
</td>
|
||
<td><%= puppetclass.hostgroups.map {|hg| link_to_if_authorized trunc(hg), hash_for_edit_hostgroup_path(:id=>hg).merge(:auth_object => hg, :authorizer => @hostgroups_authorizer)}.to_sentence.html_safe %></td>
|
||
<td> <%= link_to puppetclass.hosts_count, hosts_path(:search => "class = #{puppetclass.name}")%></td>
|
||
<td> <%= link_to puppetclass.total_hosts, hosts_path(:search => "class = #{puppetclass.name}")%></td>
|
||
<td><%= puppetclass.global_class_params_count %> </td>
|
||
<td><%= puppetclass.lookup_keys_count %> </td>
|
||
<td>
|
db/migrate/20141109131448_rename_hosts_count_column.rb | ||
---|---|---|
class RenameHostsCountColumn < ActiveRecord::Migration
|
||
#prevent wierdness with rails treating hosts_count as cached counter in some cases
|
||
def up
|
||
rename_column :puppetclasses, :hosts_count, :total_hosts
|
||
end
|
||
|
||
def down
|
||
rename_column :puppetclasses, :total_hosts, :hosts_count
|
||
end
|
||
end
|
db/migrate/20141110084848_fix_puppetclass_total_hosts.rb | ||
---|---|---|
class FixPuppetclassTotalHosts < ActiveRecord::Migration
|
||
def up
|
||
Rake::Task['puppet:fix_total_hosts'].invoke
|
||
end
|
||
|
||
def down
|
||
end
|
||
end
|
lib/tasks/fix_cached_counters.rake | ||
---|---|---|
cl.all.each{|el| cl.reset_counters(el.id, :hosts, :hostgroups)}
|
||
puts "#{cl} corrected"
|
||
end
|
||
Puppetclass.all.each{|el| Puppetclass.reset_counters(el.id, :host_classes, :hostgroup_classes, :lookup_keys)}
|
||
Puppetclass.all.each{|el| Puppetclass.reset_counters(el.id, :hostgroup_classes, :lookup_keys)}
|
||
puts "Puppetclass corrected"
|
||
Model.all.each{|el| Model.reset_counters(el.id, :hosts)}
|
||
puts "Model corrected"
|
lib/tasks/puppet.rake | ||
---|---|---|
end
|
||
end
|
||
|
||
desc "Correct hosts counts for all classes in case they are wrong"
|
||
task :fix_total_hosts => :environment do
|
||
if Puppetclass.count > 0
|
||
User.current = User.anonymous_admin
|
||
Puppetclass.all.each(&:update_total_hosts)
|
||
end
|
||
end
|
||
|
||
end
|
test/unit/host_class_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
class HostClassTest < ActiveSupport::TestCase
|
||
|
||
setup do
|
||
disable_orchestration
|
||
User.current = User.find_by_login "one"
|
||
# puppetclasses(:two) needs to be in production environment
|
||
EnvironmentClass.create(:puppetclass_id => puppetclasses(:two).id, :environment_id => environments(:production).id )
|
||
end
|
||
|
||
test "should update hosts_count" do
|
||
pc = puppetclasses(:two)
|
||
assert_difference "pc.hosts_count" do
|
||
hc = HostClass.create(:puppetclass_id => pc.id, :host_id => FactoryGirl.create(:host).id)
|
||
pc.reload
|
||
end
|
||
end
|
||
end
|
test/unit/puppetclass_test.rb | ||
---|---|---|
assert_equal "Puppetclass", "puppetclass".classify
|
||
assert_equal "Puppetclass", "puppetclasses".classify
|
||
end
|
||
|
||
context 'host counter updates on all possible class inheritance' do
|
||
setup do
|
||
@class = FactoryGirl.create(:puppetclass)
|
||
@host = FactoryGirl.create(:host)
|
||
@hostgroup = FactoryGirl.create(:hostgroup)
|
||
@another_hostgroup = FactoryGirl.create(:hostgroup)
|
||
@config_group = FactoryGirl.create(:config_group)
|
||
end
|
||
|
||
def check_host_hostgroup
|
||
assert_difference('@class.total_hosts') do
|
||
@host.update_attribute(:hostgroup, @hostgroup)
|
||
@class.reload
|
||
end
|
||
assert_difference('@class.total_hosts', -1) do
|
||
@host.update_attribute(:hostgroup, nil)
|
||
@class.reload
|
||
end
|
||
assert_difference('@class.total_hosts') do
|
||
@hostgroup.hosts << @host
|
||
@class.reload
|
||
end
|
||
assert_difference('@class.total_hosts', -1) do
|
||
@hostgroup.hosts.delete(@host)
|
||
@class.reload
|
||
end
|
||
end
|
||
|
||
def check_object_class(obj)
|
||
assert_difference('@class.total_hosts') do
|
||
obj.puppetclasses << @class
|
||
@class.reload
|
||
end
|
||
assert_difference('@class.total_hosts', -1) do
|
||
obj.puppetclasses.delete(@class)
|
||
@class.reload
|
||
end
|
||
assert_difference('@class.total_hosts') do
|
||
@class.send("#{obj.class.table_name}") << obj
|
||
@class.reload
|
||
end
|
||
assert_difference('@class.total_hosts', -1) do
|
||
@class.send("#{obj.class.table_name}").delete(obj)
|
||
@class.reload
|
||
end
|
||
end
|
||
|
||
def check_object_config_group(obj)
|
||
assert_difference('@class.total_hosts') do
|
||
obj.config_groups << @config_group
|
||
@class.reload
|
||
end
|
||
assert_difference('@class.total_hosts', -1) do
|
||
obj.config_groups.delete(@config_group)
|
||
@class.reload
|
||
end
|
||
end
|
||
|
||
it 'on direct assignment to host' do
|
||
check_object_class(@host)
|
||
end
|
||
|
||
# hostgroup-related
|
||
|
||
it 'class on hostgroup, adding host to hostgroup' do
|
||
@hostgroup.puppetclasses << @class
|
||
check_host_hostgroup
|
||
end
|
||
|
||
it 'host in hostgroup, adding class to hostgroup' do
|
||
@host.update_attribute(:hostgroup, @hostgroup)
|
||
check_object_class(@hostgroup)
|
||
end
|
||
|
||
it 'class on hostgroup parent, adding host to hostgroup' do
|
||
@another_hostgroup.puppetclasses << @class
|
||
@hostgroup.update_attribute(:parent, @another_hostgroup)
|
||
check_host_hostgroup
|
||
end
|
||
|
||
it 'hostgroup ancestry change' do
|
||
@another_hostgroup.puppetclasses << @class
|
||
@host.update_attribute(:hostgroup, @hostgroup)
|
||
assert_difference('@class.total_hosts') do
|
||
@hostgroup.update_attribute(:parent, @another_hostgroup)
|
||
@class.reload
|
||
end
|
||
assert_difference('@class.total_hosts', -1) do
|
||
@hostgroup.update_attribute(:parent, nil)
|
||
@class.reload
|
||
end
|
||
end
|
||
|
||
it 'host in hostgroup, adding class to hostgroup parent' do
|
||
@hostgroup.update_attribute(:parent, @another_hostgroup)
|
||
@host.update_attribute(:hostgroup, @hostgroup)
|
||
check_object_class(@another_hostgroup)
|
||
end
|
||
|
||
# config_group related
|
||
it 'class on config_group, adding host to config_group' do
|
||
@config_group.puppetclasses << @class
|
||
check_object_config_group(@host)
|
||
end
|
||
|
||
it 'host in config_group, adding class to config_group' do
|
||
@host.config_groups << @config_group
|
||
check_object_class(@config_group)
|
||
end
|
||
|
||
it 'class on config_group, hostgroup in config_group, adding host to hostgroup' do
|
||
@config_group.puppetclasses << @class
|
||
@hostgroup.config_groups << @config_group
|
||
check_host_hostgroup
|
||
end
|
||
|
||
it 'host in hostgroup, hostgroup in config_group, adding class to config_group' do
|
||
@hostgroup.config_groups << @config_group
|
||
@host.update_attribute(:hostgroup, @hostgroup)
|
||
check_object_class(@config_group)
|
||
end
|
||
|
||
it 'class on config_group, host in hostgroup, adding hostgroup to config_group' do
|
||
@config_group.puppetclasses << @class
|
||
@host.update_attribute(:hostgroup, @hostgroup)
|
||
check_object_config_group(@hostgroup)
|
||
end
|
||
end
|
||
|
||
end
|
Also available in: Unified diff
Fixes #844 #5725 - correct hosts count in puppetclass