From: Nick Lewis <[email protected]>

Added methods to list nodes/groups/classes, along with the groups
via which they were inherited.

Signed-off-by: Nick Lewis <[email protected]>
---
 app/models/node.rb                    |    2 +-
 app/models/node_class.rb              |   15 +++++++++
 app/models/node_group.rb              |   34 +++++++++++++++++++-
 app/views/node_classes/show.html.haml |    2 +-
 app/views/node_groups/show.html.haml  |   38 +++++++++++-----------
 lib/node_group_graph.rb               |   54 ++++++++++++++++++++++++++++++--
 spec/models/node_spec.rb              |   17 ++++++++--
 7 files changed, 131 insertions(+), 31 deletions(-)

diff --git a/app/models/node.rb b/app/models/node.rb
index be6dae9..dc6de11 100644
--- a/app/models/node.rb
+++ b/app/models/node.rb
@@ -99,7 +99,7 @@ class Node < ActiveRecord::Base
   end
 
   def inherited_classes
-    (node_group_list - [self]).map(&:node_classes).flatten.uniq
+    (node_group_list.keys - [self]).map(&:node_classes).flatten.uniq
   end
 
   def all_classes
diff --git a/app/models/node_class.rb b/app/models/node_class.rb
index ca7ed48..f048599 100644
--- a/app/models/node_class.rb
+++ b/app/models/node_class.rb
@@ -1,6 +1,8 @@
 class NodeClass < ActiveRecord::Base
   def self.per_page; 50 end # Pagination
 
+  include NodeGroupGraph
+
   has_many :node_group_class_memberships, :dependent => :destroy
   has_many :node_class_memberships, :dependent => :destroy
 
@@ -30,4 +32,17 @@ class NodeClass < ActiveRecord::Base
   def self.find_from_form_ids(*ids)
     ids.map{|entry| entry.to_s.split(/[ 
,]/)}.flatten.reject(&:blank?).uniq.map{|id| self.find(id)}
   end
+
+  def node_list
+    return @node_list if @node_list
+    all = {}
+    self.walk_groups do |group,_|
+      group.nodes.each do |node|
+        all[node] ||= Set.new
+        all[node] << group
+      end
+      group
+    end
+    @node_list = all
+  end
 end
diff --git a/app/models/node_group.rb b/app/models/node_group.rb
index 036b033..933ae88 100644
--- a/app/models/node_group.rb
+++ b/app/models/node_group.rb
@@ -12,8 +12,12 @@ class NodeGroup < ActiveRecord::Base
   has_many :node_group_edges_out, :class_name => "NodeGroupEdge", :foreign_key 
=> 'from_id', :dependent => :destroy
   has_many :node_group_edges_in, :class_name => "NodeGroupEdge", :foreign_key 
=> 'to_id', :dependent => :destroy
 
-  # TODO Want to add a list of groups have edges into us, may want to rename 
node_groups
-  has_many :node_groups, :through => :node_group_edges_out, :source => :to
+  has_many :node_group_children, :class_name => "NodeGroup", :through => 
:node_group_edges_in, :source => :from
+  has_many :node_group_parents, :class_name => "NodeGroup", :through => 
:node_group_edges_out, :source => :to
+
+  # Alias for compatibility with Node
+  alias :node_groups :node_group_parents
+  alias :node_groups= :node_group_parents=
 
   has_parameters
 
@@ -70,4 +74,30 @@ class NodeGroup < ActiveRecord::Base
   def self.find_from_form_ids(*ids)
     ids.map{|entry| entry.to_s.split(/[ 
,]/)}.flatten.reject(&:blank?).uniq.map{|id| self.find(id)}
   end
+
+  def node_group_child_list
+    return @node_group_child_list if @node_group_child_list
+    all = {}
+    self.walk_child_groups do |group,children|
+      children.each do |child|
+        all[child] ||= Set.new
+        all[child] << group
+      end
+      group
+    end
+    @node_group_child_list = all
+  end
+
+  def node_list
+    return @node_list if @node_list
+    all = {}
+    self.walk_child_groups do |group,_|
+      group.nodes.each do |node|
+        all[node] ||= Set.new
+        all[node] << group
+      end
+      group
+    end
+    @node_list = all
+  end
 end
diff --git a/app/views/node_classes/show.html.haml 
b/app/views/node_classes/show.html.haml
index b6a035c..c792214 100644
--- a/app/views/node_classes/show.html.haml
+++ b/app/views/node_classes/show.html.haml
@@ -15,6 +15,6 @@
     .section
       %h3 Nodes in this class
       - if @node_class.nodes.present?
-        = render 'nodes/nodes', :nodes => @node_class.nodes
+        = render 'nodes/nodes', :nodes => @node_class.node_list.map(&:first), 
:container => @node_class
       - else
         = describe_no_matches_for :nodes, :class
diff --git a/app/views/node_groups/show.html.haml 
b/app/views/node_groups/show.html.haml
index 9b7f084..3a9743d 100644
--- a/app/views/node_groups/show.html.haml
+++ b/app/views/node_groups/show.html.haml
@@ -9,27 +9,27 @@
       %li= link_to 'Destroy', @node_group, :confirm => 'Are you sure?', 
:method => :delete, :class => "delete button"
 
   .item
-    .section
-      %h3 Parameters
-      - unless @node_group.parameters.blank?
-        = inspector_table @node_group.parameters.to_hash
-      - else
-        = describe_no_matches_as 'No parameters'
-
-    .section.half
-      %h3 Inherited groups
-      - unless @node_group.node_groups.blank?
-        = inspector_table @node_group.node_groups, :name, false, :link => true
-      - else
-        = describe_no_matches_as 'No groups'
+    = render 'shared/parameters', :resource => @node_group
+    = render 'shared/groups', :resource => @node_group
+    = render 'shared/classes', :resource => @node_group
 
     .section.half
-      %h3 Classes
-      - unless @node_group.node_classes.blank?
-        = inspector_table @node_group.node_classes, :name, false, :link => true
+      %h3 Derived groups
+      - unless @node_group.node_group_child_list.empty?
+        %table.inspector
+          %thead
+            %tr
+              %th Group
+              %th Source groups
+          %tbody
+            - @node_group.node_group_child_list.each do |group,parents|
+              %tr
+                %td
+                  %strong= link_to(group.name,group)
+                %td
+                  = parents.map{|p| link_to(p.name,p)}.join(", ") unless 
parents.include?(@node_group)
       - else
-        = describe_no_matches_as 'No classes'
-
+        = describe_no_matches_as 'No child groups'
   .item
     - if @node_group.nodes.present?
       .section
@@ -37,6 +37,6 @@
     .section
       %h3 Nodes for this group
       - if @node_group.nodes.present?
-        = render 'nodes/nodes', :nodes => @node_group.nodes
+        = render 'nodes/nodes', :nodes => @node_group.node_list.map(&:first), 
:container => @node_group
       - else
         = describe_no_matches_for :nodes, :group
diff --git a/lib/node_group_graph.rb b/lib/node_group_graph.rb
index 7f00514..88fbc48 100644
--- a/lib/node_group_graph.rb
+++ b/lib/node_group_graph.rb
@@ -1,10 +1,45 @@
 module NodeGroupGraph
-  def node_group_graph
-    @node_group_graph ||= compile_node_group_graph.last
+  # Returns a hash of all the groups for this group/node, direct or inherited.
+  # Each key is a group, and each value is the Set of groups from which we 
inherit
+  # that group.
+  def node_group_list
+    return @node_group_list if @node_group_list
+    all = {}
+    self.walk_groups do |group,parents|
+      parents.each do |parent|
+        all[parent] ||= Set.new
+        all[parent] << group
+      end
+      group
+    end
+    @node_group_list = all
   end
 
-  def node_group_list
-    @node_group_list ||= compile_node_group_graph.first
+  # Returns a hash of all the classes for this group/node, direct or inherited.
+  # Each key is a class, and each value is the Set of groups from which we 
inherit
+  # that class.
+  def node_class_list
+    return @node_class_list if @node_class_list
+    all = {}
+    self.walk_groups do |group,_|
+      group.node_classes.each do |node_class|
+        all[node_class] ||= Set.new
+        all[node_class] << group
+      end
+    end
+    @node_class_list = all
+  end
+
+  def walk_groups(&block)
+    walk(:node_groups,&block)
+  end
+
+  def walk_child_groups(&block)
+    walk(:node_group_children,&block)
+  end
+
+  def node_group_graph
+    @node_group_graph ||= compile_node_group_graph.last
   end
 
   private
@@ -14,4 +49,15 @@ module NodeGroupGraph
     graph = group.node_groups.map {|grp| {grp => compile_node_group_graph(grp, 
seen + [group], all).last}}.inject({},&:merge)
     [all.uniq, graph]
   end
+
+  def walk(method,&block)
+    def yield_children(seen,method,&block)
+      return nil if seen.include?(self)
+      children_results = self.send(method).map{|group| 
group.yield_children(seen+[self],method,&block)}.compact
+      yield self,children_results
+    end
+    return unless block
+    seen = []
+    yield_children(seen,method,&block)
+  end
 end
diff --git a/spec/models/node_spec.rb b/spec/models/node_spec.rb
index 8ee87db..99283e0 100644
--- a/spec/models/node_spec.rb
+++ b/spec/models/node_spec.rb
@@ -256,7 +256,7 @@ describe Node do
 
   describe "handling the node group graph" do
     before :each do
-      @node = Node.generate!
+      @node = Node.generate! :name => "Sample"
 
       @node_group_a = NodeGroup.generate! :name => "A"
       @node_group_b = NodeGroup.generate! :name => "B"
@@ -273,17 +273,26 @@ describe Node do
 
     describe "when a group is included twice" do
       before :each do
-        @node_group_c = NodeGroup.generate!
+        @node_group_c = NodeGroup.generate! :name => "C"
+        @node_group_d = NodeGroup.generate! :name => "D"
+        @node_group_c.node_groups << @node_group_d
         @node_group_a.node_groups << @node_group_c
         @node_group_b.node_groups << @node_group_c
       end
 
       it "should return the correct graph" do
-        @node.node_group_graph.should == {...@node_group_a => 
{...@node_group_c => {}}, @node_group_b => {...@node_group_c => {}}}
+        @node.node_group_graph.should == {
+          @node_group_a => {
+            @node_group_c => {...@node_group_d => {}}
+          },
+          @node_group_b => {
+            @node_group_c => {...@node_group_d => {}}
+          }
+        }
       end
 
       it "should return the correct list" do
-        @node.node_group_list.should == [...@node, @node_group_a, 
@node_group_c, @node_group_b]
+        @node.node_group_list.should == {...@node_group_a => s...@node], 
@node_group_c => s...@node_group_a,@node_group_b], @node_group_b => s...@node], 
@node_group_d => s...@node_group_c]}
       end
     end
 
-- 
1.7.3.1

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to