Project

General

Profile

« Previous | Next » 

Revision 6895854c

Added by Stephen Benjamin about 10 years ago

fixes #4256 - makes columns sortable in the UI

View differences:

app/controllers/domains_controller.rb
def index
@domains = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
@host_counter = Host.group(:domain_id).where(:domain_id => @domains.select(&:id)).count
end
def new
app/controllers/environments_controller.rb
def index
@environments = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
@host_counter = Host.group(:environment_id).where(:environment_id => @environments.select(&:id)).count
end
def new
app/controllers/models_controller.rb
def index
@models = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
@host_counter = Host.group(:model_id).where(:model_id => @models.select(&:id)).count
end
def new
app/controllers/operatingsystems_controller.rb
def index
@operatingsystems = resource_base.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
@host_counter = Host.group(:operatingsystem_id).where(:operatingsystem_id => @operatingsystems.collect(&:id)).count
end
def new
app/controllers/puppetclasses_controller.rb
def index
@puppetclasses = resource_base.search_for(params[:search], :order => params[:order]).includes(:environments, :hostgroups).paginate(:page => params[:page])
@host_counter = Host.group(:puppetclass_id).joins(:puppetclasses).where(:puppetclasses => {:id => @puppetclasses.collect(&:id)}).count
@keys_counter = Puppetclass.joins(:class_params).select('distinct environment_classes.lookup_key_id').group(:name).count
@hostgroups_authorizer = Authorizer.new(User.current, :collection => HostgroupClass.find_all_by_puppetclass_id(@puppetclasses.map(&:id)).compact.uniq.map(&:hostgroup_id))
end
app/helpers/puppetclasses_helper.rb
klass = name.gsub('::', '/')
"puppet/rdoc/#{environment}/classes/#{klass}.html"
end
def host_counter klass
# workaround for sqlite bug
# https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/4544-rails3-activerecord-sqlite3-lost-column-type-when-using-views#ticket-4544-2
@host_counter[klass.id.to_s] || @host_counter[klass.id.to_i] || 0
rescue
_("N/A")
end
end
app/models/architecture.rb
audited :allow_mass_assignment => true
scoped_search :on => :name, :complete_value => :true
scoped_search :on => :hosts_count
def to_param
"#{id}-#{name.parameterize}"
app/models/concerns/host_common.rb
extend ActiveSupport::Concern
included do
belongs_to :architecture
belongs_to :environment
belongs_to :operatingsystem
counter_cache = "#{model_name.split(":").first.pluralize.downcase}_count".to_sym # e.g. :hosts_count
belongs_to :architecture, :counter_cache => counter_cache
belongs_to :environment, :counter_cache => counter_cache
belongs_to :operatingsystem, :counter_cache => counter_cache
belongs_to :medium
belongs_to :ptable
belongs_to :puppet_proxy, :class_name => "SmartProxy"
belongs_to :puppet_ca_proxy, :class_name => "SmartProxy"
belongs_to :domain
belongs_to :domain, :counter_cache => counter_cache
belongs_to :subnet
belongs_to :compute_profile
app/models/domain.rb
validates :fullname, :uniqueness => true, :allow_blank => true, :allow_nil => true
scoped_search :on => [:name, :fullname], :complete_value => true
scoped_search :on => :hosts_count
scoped_search :on => :hostgroups_count
scoped_search :in => :domain_parameters, :on => :value, :on_key=> :name, :complete_value => true, :only_explicit => true, :rename => :params
# with proc support, default_scope can no longer be chained
app/models/environment.rb
}
scoped_search :on => :name, :complete_value => :true
scoped_search :on => :hosts_count
scoped_search :on => :hostgroups_count
def to_param
name
app/models/environment_class.rb
scope :parameters_for_class, lambda {|puppetclasses_ids, environment_id|
all_parameters_for_class(puppetclasses_ids, environment_id).where(:lookup_keys => {:override => true})
}
scope :all_parameters_for_class, lambda {|puppetclasses_ids, environment_id|
where(:puppetclass_id => puppetclasses_ids, :environment_id => environment_id).
where('lookup_key_id is NOT NULL').
includes(:lookup_key)
}
scope :used_by_other_environment_classes, lambda{|lookup_key_id, this_environment_class_id|
where(:lookup_key_id => lookup_key_id).
where("id != #{this_environment_class_id}")
}
# These counters key track of unique puppet class keys (parameters) across environments
after_create { |record|
Puppetclass.increment_counter(:lookup_keys_count, self.puppetclass.id) unless self.lookup_key.blank? ||
EnvironmentClass.used_by_other_environment_classes(self.lookup_key, self.id).count > 0
}
after_destroy { |record|
Puppetclass.decrement_counter(:lookup_keys_count, self.puppetclass.id) unless self.lookup_key.blank? ||
EnvironmentClass.used_by_other_environment_classes(self.lookup_key, self.id).count > 0
}
#TODO move these into scopes?
def self.is_in_any_environment(puppetclass, lookup_key)
EnvironmentClass.where(:puppetclass_id => puppetclass, :lookup_key_id => lookup_key ).count > 0
app/models/host/base.rb
self.table_name = :hosts
OWNER_TYPES = %w(User Usergroup)
belongs_to :model
belongs_to :model, :counter_cache => :hosts_count
has_many :fact_values, :dependent => :destroy, :foreign_key => :host_id
has_many :fact_names, :through => :fact_values
app/models/host_class.rb
include Authorizable
audited :associated_with => :host, :allow_mass_assignment => true
belongs_to_host :foreign_key => :host_id
belongs_to :puppetclass
belongs_to :puppetclass, :counter_cache => :hosts_count
validates :host_id, :presence => true
validates :puppetclass_id, :presence => true, :uniqueness => {:scope => :host_id}
app/models/hostgroup_class.rb
include Authorizable
audited :associated_with => :hostgroup, :allow_mass_assignment => true
belongs_to :hostgroup
belongs_to :puppetclass
belongs_to :puppetclass, :counter_cache => :hostgroups_count
attr_accessible :hostgroup_id, :hostgroup, :puppetclass_id, :puppetclass
app/models/lookup_key.rb
attr_name :key
scoped_search :on => :key, :complete_value => true, :default_order => true
scoped_search :on => :lookup_values_count, :rename => :values_count
scoped_search :on => :override, :complete_value => {:true => true, :false => false}
scoped_search :in => :param_classes, :on => :name, :rename => :puppetclass, :complete_value => true
scoped_search :in => :lookup_values, :on => :value, :rename => :value, :complete_value => true
app/models/model.rb
scoped_search :on => :name, :complete_value => :true, :default_order => true
scoped_search :on => :info
scoped_search :on => :hosts_count
scoped_search :on => :vendor_class, :complete_value => :true
scoped_search :on => :hardware_model, :complete_value => :true
end
app/models/operatingsystem.rb
scoped_search :on => :minor, :complete_value => :true
scoped_search :on => :description, :complete_value => :true
scoped_search :on => :type, :complete_value => :true, :rename => "family"
scoped_search :on => :hosts_count
scoped_search :on => :hostgroups_count
scoped_search :in => :architectures, :on => :name, :complete_value => :true, :rename => "architecture"
scoped_search :in => :media, :on => :name, :complete_value => :true, :rename => "medium"
app/models/puppetclass.rb
default_scope lambda { order('puppetclasses.name') }
scoped_search :on => :name, :complete_value => :true
scoped_search :on => :hosts_count
scoped_search :on => :lookup_keys_count, :rename => :keys_count
scoped_search :in => :environments, :on => :name, :complete_value => :true, :rename => "environment"
scoped_search :in => :hostgroups, :on => :name, :complete_value => :true, :rename => "hostgroup"
scoped_search :in => :hosts, :on => :name, :complete_value => :true, :rename => "host", :ext_method => :search_by_host, :only_explicit => true
app/services/puppet_class_importer.rb
def remove_classes_from_foreman env_name, klasses
env = find_or_create_env(env_name)
classes = find_existing_foreman_classes(klasses)
env.puppetclasses.delete classes
env.puppetclasses.destroy classes
# remove all old classes from hosts
HostClass.joins(:host).where(:hosts => { :environment_id => env.id }, :puppetclass_id => classes).destroy_all
if klasses.include? '_destroy_'
app/views/architectures/index.html.erb
<tr>
<th><%= sort :name, :as => s_("Architecture|Name") %></th>
<th><%= _("Operating Systems") %></th>
<th><%= sort :hosts_count, :as => _("Hosts") %></th>
<th></th>
</tr>
<% for architecture in @architectures %>
......
<td class='col-md-3'><%= link_to_if_authorized(h(architecture.name),
hash_for_edit_architecture_path(:id => architecture).merge(:auth_object => architecture, :authorizer => authorizer)) %></td>
<td><%=h architecture.operatingsystems.map(&:to_label).to_sentence %></td>
<td><%= link_to architecture.hosts_count, hosts_path(:search => "architecture = #{architecture}") %>
<td align="right">
<%= display_delete_if_authorized hash_for_architecture_path(:id => architecture.name).merge(:auth_object => architecture, :authorizer => authorizer),
:confirm => "Delete #{architecture.name}?" %>
app/views/domains/index.html.erb
<table class="table table-bordered table-striped table-two-pane">
<tr>
<th><%= sort :name, :as => s_("Domain|Fullname") %></th>
<th><%= _("Hosts") %></th>
<th><%= sort :hosts_count, :as => _("Hosts") %></th>
<th></th>
</tr>
<% for domain in @domains %>
<tr>
<td><%= link_to_if_authorized h(domain.fullname.empty? ? domain.name : domain.fullname), hash_for_edit_domain_path(:id => domain).merge(:auth_object => domain, :authorizer => authorizer) %></td>
<td><%= link_to @host_counter[domain.id] || 0, hosts_path(:search => "domain = #{domain}") %>
<td><%= link_to domain.hosts_count, hosts_path(:search => "domain = #{domain}") %>
<td><%= display_delete_if_authorized hash_for_domain_path(:id => domain).merge(:auth_object => domain, :authorizer => authorizer), :confirm => _("Delete %s?") % domain.name %></td>
</tr>
<% end %>
app/views/environments/index.html.erb
<table class="table table-bordered table-striped table-two-pane">
<tr>
<th><%= sort :name, :as => s_('Environment|Name') %></th>
<th><%= _('Hosts') %></th>
<th><%= sort :hosts_count, :as => _('Hosts') %></th>
<th></th>
</tr>
......
<td>
<%= link_to_if_authorized environment.name, hash_for_edit_environment_path(:id => environment.name).merge(:auth_object => environment, :authorizer => authorizer) %>
</td>
<td><%= link_to @host_counter[environment.id] || 0, hosts_path(:search => "environment = #{environment}") %>
<td><%= link_to environment.hosts_count, hosts_path(:search => "environment = #{environment}") %>
<td>
<%= action_buttons(link_to(_('Classes'), puppetclasses_path(:search => "environment = #{environment}")),
import_proxy_links(hash_for_import_environments_environments_path(:env => environment.name)),
app/views/lookup_keys/index.html.erb
<tr>
<th><%= sort :key, :as => _("Variable") %></th>
<th><%= sort :puppetclass, :as => _("Puppetclass") %></th>
<th><%= _('Number of values') %></th>
<th><%= sort :values_count, :as => _('Number of values') %></th>
<th></th>
</tr>
......
<td><%= link_to_if_authorized h(lookup_key.key), hash_for_edit_lookup_key_path(:id => lookup_key).merge(:auth_object => lookup_key, :permission => 'edit_external_variables', :authorizer => authorizer) %></td>
<% puppet_class = lookup_key.param_class %>
<td><%= link_to_if_authorized h(puppet_class), hash_for_edit_puppetclass_path(:id => puppet_class).merge(:auth_object => puppet_class, :authorizer => @puppetclass_authorizer) if puppet_class %></td>
<td><%=h lookup_key.lookup_values.count %></td>
<td><%=h lookup_key.lookup_values_count %></td>
<td><%= display_delete_if_authorized hash_for_lookup_key_path(:id => lookup_key).merge(:auth_object => lookup_key, :permission => 'destroy_external_variables', :authorizer => authorizer),
:confirm => _("Delete %s?") % lookup_key.key %></td>
</tr>
app/views/media/index.html.erb
<tr>
<th><%= sort :name, :as => s_("Medium|Name") %></th>
<th><%= sort :path, :as => s_("Medium|Path") %></th>
<th><%= s_("Medium|Os family") %></th>
<th><%= sort :family, :as => s_("Medium|Os family") %></th>
<th><%= _("Operating Systems") %></th>
<th></th>
</tr>
app/views/models/index.html.erb
<table class="table table-bordered table-striped table-two-pane">
<tr>
<th><%= sort :name, :as => s_("Model|Name") %></th>
<th><%= _("Vendor class") %></th>
<th><%= s_("Model|Hardware model") %></th>
<th><%= _("Hosts") %></th>
<th><%= sort :vendor_class, :as => _("Vendor class") %></th>
<th><%= sort :hardware_model, :as => s_("Model|Hardware model") %></th>
<th><%= sort :hosts_count, :as => _("Hosts") %></th>
<th></th>
</tr>
<% for model in @models %>
......
<td><%=link_to_if_authorized h(model.name), hash_for_edit_model_path(:id => model).merge(:auth_object => model, :authorizer => authorizer) %></td>
<td><%=h(model.vendor_class)%></td>
<td><%=h(model.hardware_model)%></td>
<td class="ra"><%= link_to @host_counter[model.id] || 0, hosts_path(:search => "model = \"#{model}\"") %></td>
<td class="ra"><%= link_to model.hosts_count, hosts_path(:search => "model = \"#{model}\"") %></td>
<td class="ra">
<%= display_delete_if_authorized hash_for_model_path(:id => model).merge(:auth_object => model, :authorizer => authorizer),
:confirm => _("Delete %s?") % model.name %>
app/views/operatingsystems/index.html.erb
<table class="table table-bordered table-striped table-two-pane">
<tr>
<th><%= sort :name, :as => s_("Operatingsystem|Name") %></th>
<th><%= _("Hosts") %></th>
<th><%= sort :hosts_count, :as => _("Hosts") %></th>
<th></th>
</tr>
<% for operatingsystem in @operatingsystems %>
<tr>
<td><%= link_to_if_authorized(os_name(operatingsystem), hash_for_edit_operatingsystem_path(:id => operatingsystem.id).merge(:auth_object => operatingsystem, :authorizer => authorizer)) %></td>
<td class="ra"><%= link_to @host_counter[operatingsystem.id] || 0, hosts_path(:search => "os = #{operatingsystem.name}") %></td>
<td class="ra"><%= link_to operatingsystem.hosts_count, hosts_path(:search => "os = #{operatingsystem.name}") %></td>
<td class="ra">
<%= display_delete_if_authorized hash_for_operatingsystem_path(:id => operatingsystem).merge(:auth_object => operatingsystem, :authorizer => authorizer),
:confirm => _("Delete %s?") % operatingsystem.fullname %>
app/views/ptables/index.html.erb
<table class="table table-bordered table-striped table-two-pane">
<tr>
<th><%= sort :name, :as => s_("Ptable|Name") %></th>
<th><%= s_("Ptable|Os family") %></th>
<th><%= sort :family, :as => s_("Ptable|Os family") %></th>
<th><%= _("Operating systems") %></th>
<th></th>
</tr>
app/views/puppetclasses/index.html.erb
<th><%= sort :name, :as => s_("Puppetclass|Name") %></th>
<th><%= sort :environment, :as => _("Environments and documentation") %></th>
<th><%= _('Host group') %></th>
<th><%= _('Hosts') %></th>
<th><%= _('Keys') %></th>
<th><%= sort :hosts_count, :as => _('Hosts') %></th>
<th><%= sort :keys_count, :as => _('Keys') %></th>
<th></th>
</tr>
<% for puppetclass in @puppetclasses %>
......
<% end %>
</td>
<td><%= puppetclass.hostgroups.map {|hg| link_to_if_authorized hg, hash_for_edit_hostgroup_path(:id=>hg).merge(:auth_object => hg, :authorizer => @hostgroups_authorizer)}.to_sentence.html_safe %></td>
<td> <%= link_to host_counter(puppetclass), hosts_path(:search => "class = #{puppetclass.name}")%></td>
<td><%= @keys_counter[puppetclass.name] || 0 %> </td>
<td> <%= link_to puppetclass.hosts_count, hosts_path(:search => "class = #{puppetclass.name}")%></td>
<td><%= puppetclass.lookup_keys_count %> </td>
<td>
<%= display_delete_if_authorized hash_for_puppetclass_path(:id => puppetclass).merge(:auth_object => puppetclass, :authorizer => authorizer),
:confirm => _("Delete %s?") % puppetclass.name %>
db/migrate/20140314004243_add_counter_caches.rb
class AddCounterCaches < ActiveRecord::Migration
def up
# Architectures
add_column :architectures, :hosts_count, :integer, :default => 0
add_column :architectures, :hostgroups_count, :integer, :default => 0
Architecture.all.each do |a|
Architecture.reset_counters(a.id, :hosts)
Architecture.reset_counters(a.id, :hostgroups)
end
# Domains
add_column :domains, :hosts_count, :integer, :default => 0
add_column :domains, :hostgroups_count, :integer, :default => 0
Domain.all.each do |d|
Domain.reset_counters(d.id, :hosts)
Domain.reset_counters(d.id, :hostgroups)
end
# Environments
add_column :environments, :hosts_count, :integer, :default => 0
add_column :environments, :hostgroups_count, :integer, :default => 0
Environment.all.each do |e|
Environment.reset_counters(e.id, :hosts)
Environment.reset_counters(e.id, :hostgroups)
end
# Hardware Models
add_column :models, :hosts_count, :integer, :default => 0
Model.all.each do |m|
Model.reset_counters(m.id, :hosts)
end
# Operating Systems
add_column :operatingsystems, :hosts_count, :integer, :default => 0
add_column :operatingsystems, :hostgroups_count, :integer, :default => 0
Operatingsystem.all.each do |o|
Operatingsystem.reset_counters(o.id, :hosts)
Operatingsystem.reset_counters(o.id, :hostgroups)
end
# Puppetclasses
add_column :puppetclasses, :hosts_count, :integer, :default => 0
add_column :puppetclasses, :hostgroups_count, :integer, :default => 0
Puppetclass.all.each do |p|
Puppetclass.reset_counters(p.id, :hosts)
Puppetclass.reset_counters(p.id, :hostgroups)
end
add_column :puppetclasses, :lookup_keys_count, :integer, :default => 0
EnvironmentClass.all.each do |e|
Puppetclass.increment_counter(:lookup_keys_count, e.puppetclass_id) unless EnvironmentClass.used_by_other_environment_classes(e.lookup_key_id, e.id).count > 0
end
end
def down
remove_column :architectures, :hosts_count
remove_column :architectures, :hostgroups_count
remove_column :domains, :hosts_count
remove_column :domains, :hostgroups_count
remove_column :environments, :hosts_count
remove_column :environments, :hostgroups_count
remove_column :models, :hosts_count
remove_column :operatingsystems, :hosts_count
remove_column :operatingsystems, :hostgroups_count
remove_column :puppetclasses, :hosts_count
remove_column :puppetclasses, :hostgroups_count
remove_column :puppetclasses, :lookup_keys_count
end
end
test/unit/architecture_test.rb
assert architecture.to_s == architecture.name
end
test "should update hosts_count" do
arch = architectures(:sparc)
assert_difference "arch.hosts_count" do
hosts(:one).update_attribute(:architecture, arch)
arch.reload
end
end
test "should update hostgroups_count" do
arch = architectures(:sparc)
assert_difference "arch.hostgroups_count" do
hostgroups(:common).update_attribute(:architecture, arch)
arch.reload
end
end
test "should not destroy while using" do
architecture = Architecture.new :name => "i386"
assert architecture.save
test/unit/domain_test.rb
assert domain.save!
end
test "should update hosts_count" do
domain = domains(:yourdomain)
assert_difference "domain.hosts_count" do
hosts(:one).update_attribute(:domain, domain)
domain.reload
end
end
test "should update hostgroups_count" do
domain = domains(:yourdomain)
assert_difference "domain.hostgroups_count" do
hostgroups(:common).update_attribute(:domain, domain)
domain.reload
end
end
#I must find out how to create a fact_name inside of fact_value
# test "should counts how many times a fact value exists in this domain" do
test/unit/environment_test.rb
assert_equal env.to_s, env.name
end
test "should update hosts_count" do
environment = environments(:testing)
assert_difference "environment.hosts_count" do
hosts(:one).update_attribute(:environment, environment)
environment.reload
end
end
test "should update hostgroups_count" do
environment = environments(:testing)
assert_difference "environment.hostgroups_count" do
hostgroups(:common).update_attribute(:environment, environment)
environment.reload
end
end
end
test/unit/host_class_test.rb
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 => hosts(:one).id)
pc.reload
end
end
end
test/unit/host_mailer_test.rb
@options = {}
@options[:env] = @env
# HostMailer relies on .size, and Rails looks to the counter_caches
# if they exist. Since fixtures don't populate the counter_caches,
# we do it here:
Environment.reset_counters(@env, :hosts)
@env.reload
end
test "mail should have the specified recipient" do
test/unit/hostgroup_class_test.rb
end
end
end
test "should update hostgroups_count" do
pc = puppetclasses(:two)
assert_difference "pc.hostgroups_count" do
hc = HostgroupClass.create(:puppetclass_id => pc.id, :hostgroup_id => hostgroups(:common).id)
pc.reload
end
end
end
test/unit/model_test.rb
m.hosts << host
assert !m.destroy
end
test "should update hosts_count" do
model = Model.create :name => "newmodel"
assert_difference "model.hosts_count" do
hosts(:one).update_attribute(:model, model)
model.reload
end
end
end
test/unit/operatingsystem_test.rb
end
end
test "should update hosts_count" do
os = operatingsystems(:ubuntu1010)
assert_difference "os.hosts_count" do
hosts(:one).update_attribute(:operatingsystem, os)
os.reload
end
end
test "should update hostgroups_count" do
os = operatingsystems(:ubuntu1010)
assert_difference "os.hostgroups_count" do
hostgroups(:common).update_attribute(:operatingsystem, os)
os.reload
end
end
end
test/unit/puppetclass_test.rb
assert_equal "Puppetclass", "puppetclass".classify
assert_equal "Puppetclass", "puppetclasses".classify
end
end

Also available in: Unified diff