Revision 4d4b84f6
Added by Ohad Levy almost 13 years ago
- ID 4d4b84f6b722874504f508fa92802f6ddee37c11
.gitmodules | ||
---|---|---|
[submodule "vendor/plugins/scoped_search"]
|
||
path = vendor/plugins/scoped_search
|
||
url = git://github.com/wvanbergen/scoped_search.git
|
||
[submodule "vendor/plugins/ancestry"]
|
||
path = vendor/plugins/ancestry
|
||
url = git://github.com/stefankroes/ancestry.git
|
app/controllers/hostgroups_controller.rb | ||
---|---|---|
def index
|
||
begin
|
||
values = Hostgroup.search_for(params[:search],:order => params[:order])
|
||
flash.clear
|
||
rescue => e
|
||
error e.to_s
|
||
values = Hostgroup.search_for ""
|
||
... | ... | |
@hostgroup = Hostgroup.new
|
||
end
|
||
|
||
def nest
|
||
@hostgroup = Hostgroup.new(:parent_id => params[:id])
|
||
render :action => :new
|
||
end
|
||
|
||
# Clone the hostgroup
|
||
def clone
|
||
new = @hostgroup.clone
|
app/helpers/hostgroups_helper.rb | ||
---|---|---|
module HostgroupsHelper
|
||
include CommonParametersHelper
|
||
include HostsAndHostgroupsHelper
|
||
|
||
def warning_message group
|
||
msg = ["Are you sure?"]
|
||
if group.has_children?
|
||
msg << "This group has nested groups!\n"
|
||
msg << "Deleting this group will unlink its nested groups and any associated puppet classes and / or parameters"
|
||
end
|
||
msg.join("\n")
|
||
end
|
||
|
||
end
|
app/helpers/hosts_and_hostgroups_helper.rb | ||
---|---|---|
end
|
||
end
|
||
|
||
def hostgroup_name group
|
||
return if group.blank?
|
||
content_tag(:span, group.to_s.gsub(group.name, ""), :class => "grey") +
|
||
link_to_if_authorized(h(group.name), hash_for_edit_hostgroup_path(:id => group))
|
||
end
|
||
|
||
def accessible_hostgroups
|
||
hg = (User.current.hostgroups.any? and !User.current.admin?) ? User.current.hostgroups : Hostgroup.all
|
||
hg.sort
|
||
end
|
||
|
||
def image_file_entry item
|
||
# If the host has an explicit image_path then use that
|
||
# Else use the default based upon the host's medium and operatingsystem
|
app/helpers/hosts_helper.rb | ||
---|---|---|
(User.current.domains.any? and !User.current.admin?) ? User.current.domains : Domain.all
|
||
end
|
||
|
||
def accessible_hostgroups
|
||
(User.current.hostgroups.any? and !User.current.admin?) ? User.current.hostgroups : Hostgroup.all
|
||
end
|
||
|
||
def update_details_from_hostgroup
|
||
return nil unless @host.new_record?
|
||
remote_function(:url => { :action => "process_hostgroup" },
|
app/models/host.rb | ||
---|---|---|
end
|
||
|
||
def all_puppetclasses
|
||
return hostgroup.nil? ? puppetclasses : (hostgroup.puppetclasses + puppetclasses).uniq
|
||
return hostgroup.nil? ? puppetclasses : (hostgroup.classes + puppetclasses).uniq
|
||
end
|
||
|
||
# provide information about each node, mainly used for puppet external nodes
|
||
... | ... | |
# read OS parameters
|
||
operatingsystem.os_parameters.each {|p| parameters.update Hash[p.name => p.value] } unless operatingsystem.nil?
|
||
# read group parameters only if a host belongs to a group
|
||
hostgroup.group_parameters.each {|p| parameters.update Hash[p.name => p.value] } unless hostgroup.nil?
|
||
parameters.update hostgroup.parameters unless hostgroup.nil?
|
||
# and now read host parameters, override if required
|
||
host_parameters.each {|p| parameters.update Hash[p.name => p.value] }
|
||
return parameters
|
app/models/hostgroup.rb | ||
---|---|---|
class Hostgroup < ActiveRecord::Base
|
||
has_ancestry :orphan_strategy => :rootify
|
||
include Authorization
|
||
include HostCommon
|
||
has_and_belongs_to_many :puppetclasses
|
||
has_and_belongs_to_many :users, :join_table => "user_hostgroups"
|
||
validates_uniqueness_of :name
|
||
validates_uniqueness_of :name, :scope => :ancestry
|
||
validates_format_of :name, :with => /\A(\S+\s?)+\Z/, :message => "can't be blank or contain trailing white spaces."
|
||
has_many :group_parameters, :dependent => :destroy, :foreign_key => :reference_id
|
||
accepts_nested_attributes_for :group_parameters, :reject_if => lambda { |a| a[:value].blank? }, :allow_destroy => true
|
||
... | ... | |
#TODO: add a method that returns the valid os for a hostgroup
|
||
|
||
def all_puppetclasses
|
||
puppetclasses
|
||
classes
|
||
end
|
||
|
||
alias_method :to_label, :to_s
|
||
|
||
def to_label
|
||
"/" + ancestors.map{|a| a.name + "/"}.join + name
|
||
end
|
||
|
||
def as_json(options={})
|
||
super({:only => [:name, :id, :value], :include => [:puppetclasses, :group_parameters, :environment]}.merge(options))
|
||
super({:only => [:name, :id], :methods => [:classes, :parameters], :include => [:puppetclasses, :group_parameters, :environment]}.merge(options))
|
||
end
|
||
|
||
def hostgroup
|
||
... | ... | |
ptable.layout
|
||
end
|
||
|
||
def classes
|
||
klasses = []
|
||
ids = ancestor_ids
|
||
ids << id unless new_record? or self.frozen?
|
||
Hostgroup.sort_by_ancestry(Hostgroup.find(ids, :include => :puppetclasses)).each do |hg|
|
||
klasses << hg.puppetclasses
|
||
end
|
||
klasses.flatten
|
||
end
|
||
|
||
# returns self and parent parameters as a hash
|
||
def parameters
|
||
hash = {}
|
||
ids = ancestor_ids
|
||
ids << id unless new_record? or self.frozen?
|
||
Hostgroup.sort_by_ancestry(Hostgroup.find(ids, :include => :group_parameters)).each do |hg|
|
||
hg.group_parameters.each {|p| hash[p.name] = p.value }
|
||
end
|
||
hash
|
||
end
|
||
|
||
def params
|
||
parameters = {}
|
||
# read common parameters
|
||
... | ... | |
# read OS parameters
|
||
operatingsystem.os_parameters.each {|p| parameters.update Hash[p.name => p.value] } unless operatingsystem.nil?
|
||
# read group parameters only if a host belongs to a group
|
||
hostgroup.group_parameters.each {|p| parameters.update Hash[p.name => p.value] } unless hostgroup.nil?
|
||
parameters.update self.parameters unless hostgroup.nil?
|
||
parameters
|
||
end
|
||
|
app/views/hostgroups/_form.html.erb | ||
---|---|---|
<% form_for @hostgroup do |f| %>
|
||
<%= f.error_messages %>
|
||
<p>
|
||
<%= f.label :parent_id, "Parent", :class => "span-3" %>
|
||
<%= f.collection_select(:parent_id, accessible_hostgroups, :id, :to_label, { :include_blank => true },
|
||
{ :class => "span-3" }) %>
|
||
|
||
<%= f.label :name, nil, :class => "span-3" %>
|
||
<%= f.text_field :name, :class => "last" %>
|
||
<%= f.text_field :name, :class => "span-3" %>
|
||
</p>
|
||
|
||
<br>
|
||
|
||
<% field_set_tag 'Host Defaults' do -%>
|
||
|
||
<% field_set_tag 'Primary Settings' do %>
|
app/views/hostgroups/index.html.erb | ||
---|---|---|
<th>Name</th>
|
||
<th></th>
|
||
</tr>
|
||
<% for hostgroup in @hostgroups %>
|
||
<% Hostgroup.sort_by_ancestry(@hostgroups).each do |hostgroup| %>
|
||
<tr class="<%= cycle("even", "odd") -%>">
|
||
<td><%=link_to_if_authorized h(hostgroup.name), hash_for_edit_hostgroup_path(:id => hostgroup) %></td>
|
||
<td> <%= hostgroup_name hostgroup %> </td>
|
||
<td class="ra">
|
||
<%= display_link_if_authorized 'Nest', hash_for_nest_hostgroup_path(:id => hostgroup) %>
|
||
<%= display_link_if_authorized 'Clone', hash_for_clone_hostgroup_path(:id => hostgroup) %>
|
||
<%= display_link_if_authorized "Destroy", hash_for_hostgroup_path(:id => hostgroup, :auth_action => :destroy), :confirm => 'Are you sure?', :method => :delete %>
|
||
<%= display_link_if_authorized "Destroy", hash_for_hostgroup_path(:id => hostgroup, :auth_action => :destroy), :confirm => warning_message(hostgroup), :method => :delete %>
|
||
</td>
|
||
</tr>
|
||
<% end %>
|
app/views/hosts/_form.html.erb | ||
---|---|---|
<%= f.label :name %>
|
||
<%= f.text_field :name, :value => @host.shortname, :title => @host.to_s, :size => 12 %>
|
||
</div>
|
||
<div class="span-6">
|
||
<div class="span-3">
|
||
<%= f.label :hostgroup_id, "Host group" %>
|
||
<%= image_tag "spinner.gif", :id => "indicator1", :style => "display:none;" %>
|
||
<%= f.collection_select(:hostgroup_id, accessible_hostgroups, :id, :name, { :include_blank => true },
|
||
{ :onchange => update_details_from_hostgroup }) %>
|
||
</div>
|
||
<%= f.collection_select(:hostgroup_id, accessible_hostgroups, :id, :to_label, { :include_blank => true },
|
||
{ :onchange => update_details_from_hostgroup, :class => "span-3" }) %>
|
||
<div class="span-6">
|
||
<%= f.label :environment_id %>
|
||
<%= f.collection_select :environment_id, Environment.all, :id, :to_label, { :include_blank => true } %>
|
app/views/hosts/_list.html.erb | ||
---|---|---|
<td><%= icon(host.os, :size => "18x18", :title => host.os.to_s) + " " + host.os.to_s if host.os %></td>
|
||
<td><%= h host.try(:environment) %></td>
|
||
<td><%= h host.try(:model) %></td>
|
||
<td><%= h host.try(:hostgroup) %></td>
|
||
<td><%= hostgroup_name host.hostgroup %></td>
|
||
<td><%= last_report_column(host) %></td>
|
||
<td>
|
||
<%= display_link_if_authorized 'Edit', hash_for_edit_host_path(:id => host) %>
|
app/views/puppetclasses/_class_selection.html.erb | ||
---|---|---|
:collection => obj.puppetclasses ,:as => :klass,
|
||
:locals => { :type => obj.class.to_s.downcase } %>
|
||
</div>
|
||
<% if (klasses = obj.hostgroup.try(:puppetclasses)).is_a?(Array) and obj.is_a?(Host) -%>
|
||
<% if (klasses = obj.hostgroup.try(:classes)).is_a?(Array) and obj.is_a?(Host) -%>
|
||
<% for klass in klasses -%>
|
||
<li title="included already from host group"><%= h klass.name %></li>
|
||
<% end -%>
|
config/routes.rb | ||
---|---|---|
map.resources :puppetclasses, :member => { :assign => :post }, :collection => {:import_environments => :get, :auto_complete_search => :get} do |pc|
|
||
pc.resources :hosts, :requirements => {:id => /[^\/]+/}
|
||
end
|
||
map.resources :hostgroups, :member => { :clone => :get }, :collection => { :auto_complete_search => :get }
|
||
map.resources :hostgroups, :member => { :nest => :get, :clone => :get }, :collection => { :auto_complete_search => :get }
|
||
map.resources :common_parameters
|
||
map.resources :environments, :collection => {:import_environments => :get, :obsolete_and_new => :post}
|
||
map.resources :fact_values, :only => [:create, :index], :collection => { :auto_complete_search => :get }
|
db/migrate/20110619130336_add_ancestry_to_hostgroup.rb | ||
---|---|---|
class AddAncestryToHostgroup < ActiveRecord::Migration
|
||
def self.up
|
||
add_column :hostgroups, :ancestry, :string
|
||
add_index :hostgroups, :ancestry
|
||
end
|
||
|
||
def self.down
|
||
remove_index :hostgroups, :ancestry
|
||
remove_column :hostgroups, :ancestry
|
||
end
|
||
end
|
public/stylesheets/style.css | ||
---|---|---|
height: 25px;
|
||
}
|
||
.menu-dropdown {text-transform: capitalize;}
|
||
|
||
.grey {
|
||
color:#aaa;
|
||
}
|
test/functional/hostgroups_controller_test.rb | ||
---|---|---|
assert_template 'new'
|
||
end
|
||
|
||
def test_nest
|
||
get :nest, {:id => Hostgroup.first.id}, set_session_user
|
||
assert_template 'new'
|
||
end
|
||
|
||
|
||
def test_create_invalid
|
||
Hostgroup.any_instance.stubs(:valid?).returns(false)
|
||
post :create, {}, set_session_user
|
||
... | ... | |
end
|
||
|
||
def test_destroy
|
||
hostgroup = Hostgroup.first
|
||
delete :destroy, {:id => hostgroup}, set_session_user
|
||
hostgroup = hostgroups(:unusual)
|
||
delete :destroy, {:id => hostgroup.id}, set_session_user
|
||
assert_redirected_to hostgroups_url
|
||
assert !Hostgroup.exists?(hostgroup.id)
|
||
end
|
||
|
||
def test_destroy_json
|
||
hostgroup = Hostgroup.first
|
||
delete :destroy, {:format => "json", :id => hostgroup}, set_session_user
|
||
hostgroup = hostgroups(:common)
|
||
delete :destroy, {:format => "json", :id => hostgroup.id}, set_session_user
|
||
template = ActiveSupport::JSON.decode(@response.body)
|
||
assert_response :ok
|
||
assert !Hostgroup.exists?(hostgroup.id)
|
test/unit/hostgroup_test.rb | ||
---|---|---|
assert record.valid?
|
||
end
|
||
|
||
test "should be able to nest a group parameters" do
|
||
# creates a 3 level hirecy, each one with his own parameters
|
||
# and overrides.
|
||
pid = Time.now.to_i
|
||
assert (top = Hostgroup.create(:name => "topA", :group_parameters_attributes => {
|
||
pid += 1=>{"name"=>"topA", "value"=>"1", :nested => ""},
|
||
pid += 1=>{"name"=>"topB", "value"=>"1", :nested => ""},
|
||
pid += 1=>{"name"=>"topC", "value"=>"1", :nested => ""},
|
||
}))
|
||
assert (second = Hostgroup.create(:name => "SecondA", :parent_id => top.id, :group_parameters_attributes => {
|
||
pid += 1 =>{"name"=>"topA", "value"=>"2", :nested => ""},
|
||
pid += 1 =>{"name"=>"secondA", "value"=>"2", :nested => ""}}))
|
||
|
||
assert second.parameters.include? "topA"
|
||
assert_equal "2", second.parameters["topA"]
|
||
assert second.parameters.include? "topB"
|
||
assert_equal "1", second.parameters["topB"]
|
||
assert second.parameters.include? "topC"
|
||
assert_equal "1", second.parameters["topC"]
|
||
assert second.parameters.include? "secondA"
|
||
assert_equal "2", second.parameters["secondA"]
|
||
|
||
assert (third = Hostgroup.create(:name => "ThirdA", :parent_id => second.id, :group_parameters_attributes => {
|
||
pid += 1 =>{"name"=>"topB", "value"=>"3", :nested => ""},
|
||
pid += 1 =>{"name"=>"topA", "value"=>"3", :nested => ""}}))
|
||
|
||
assert third.parameters.include? "topA"
|
||
assert_equal "3", third.parameters["topA"]
|
||
assert third.parameters.include? "topB"
|
||
assert_equal "3", third.parameters["topB"]
|
||
assert third.parameters.include? "topC"
|
||
assert_equal "1", third.parameters["topC"]
|
||
assert third.parameters.include? "secondA"
|
||
assert_equal "2", third.parameters["secondA"]
|
||
end
|
||
|
||
test "should inheirt parent classes" do
|
||
assert (top = Hostgroup.create(:name => "topA", "puppetclass_ids"=>[Puppetclass.first.id]))
|
||
assert (second = Hostgroup.create(:name => "secondB", :parent_id => top.id, "puppetclass_ids"=>[Puppetclass.last.id]))
|
||
|
||
assert_equal [Puppetclass.first, Puppetclass.last].sort, second.classes.sort
|
||
end
|
||
|
||
test "should remove relationships if deleting a parent hostgroup" do
|
||
assert (top = Hostgroup.create(:name => "topA"))
|
||
assert (second = Hostgroup.create(:name => "secondB", :parent_id => top.id))
|
||
|
||
assert top.has_children?
|
||
assert !second.is_root?
|
||
assert top.destroy
|
||
assert Hostgroup.find(second.id).is_root?
|
||
end
|
||
|
||
end
|
vendor/plugins/ancestry | ||
---|---|---|
Subproject commit 770f2e36eb8b9865ee0ea1f81f5ca21068bebe3e
|
Also available in: Unified diff
fixes #35 - Allow hostgroup nesting for puppet classes and parameters