On 07/13/2012 09:14 PM, Dan Radez wrote:
On 07/13/2012 02:22 PM, Jan Provazník wrote:
On 07/04/2012 06:03 PM, jzigmund@redhat.com wrote:
From: Jozef Zigmund jzigmund@redhat.com
src/Gemfile.in | 1 + src/app/controllers/deployables_controller.rb | 13 +++++++ src/app/models/deployable.rb | 1 + src/app/util/deployable_xml.rb | 35 ++++++++++++++++++++ .../deployables/service_dependencies.html.haml | 11 ++++++ src/app/views/deployables/show.html.haml | 1 + src/config/initializers/mime_types.rb | 1 + src/config/locales/en.yml | 1 + src/config/routes.rb | 1 + 9 files changed, 65 insertions(+), 0 deletions(-) create mode 100644 src/app/views/deployables/service_dependencies.html.haml
diff --git a/src/Gemfile.in b/src/Gemfile.in index 1d90a91..7bb3704 100644 --- a/src/Gemfile.in +++ b/src/Gemfile.in @@ -23,6 +23,7 @@ gem 'compass' gem 'compass-960-plugin', :require=> 'ninesixty' gem 'delayed_job', '~> 2.1.4' gem 'paranoia' +gem 'graphviz'
platforms :ruby_18 do gem 'fastercsv' diff --git a/src/app/controllers/deployables_controller.rb b/src/app/controllers/deployables_controller.rb index 3e3b76a..e4d3f91 100644 --- a/src/app/controllers/deployables_controller.rb +++ b/src/app/controllers/deployables_controller.rb @@ -283,6 +283,19 @@ class DeployablesController < ApplicationController redirect_to_original({"deployables_preset_filter" => params[:deployables_preset_filter], "deployables_search" => params[:deployables_search]}) end
def service_dependencies
deployable = Deployable.find(params[:id])
deployable_xml = DeployableXML.new(deployable.xml)
respond_to do |format|
format.html do
render :locals => {:deployable => deployable}
end
format.png do
render :text => deployable_xml.display_digraph
end
end
end
private
def set_header
diff --git a/src/app/models/deployable.rb b/src/app/models/deployable.rb index 9c6aff9..b052b44 100644 --- a/src/app/models/deployable.rb +++ b/src/app/models/deployable.rb @@ -15,6 +15,7 @@ #
require 'util/conductor' +require 'util/deployable_xml'
class Deployable < ActiveRecord::Base class << self diff --git a/src/app/util/deployable_xml.rb b/src/app/util/deployable_xml.rb index cdbbc39..ab46251 100644 --- a/src/app/util/deployable_xml.rb +++ b/src/app/util/deployable_xml.rb @@ -17,6 +17,7 @@ =begin XML Wrapper objects for the deployable XML format =end +require "graphviz"
class ValidationError < RuntimeError; end
@@ -100,6 +101,8 @@ end
class AssemblyXML
- attr_accessor :root
- def initialize(xmlstr_or_node = "") if xmlstr_or_node.is_a? Nokogiri::XML::Node @root = xmlstr_or_node
@@ -202,6 +205,38 @@ class DeployableXML @relax_file = "#{File.dirname(File.expand_path(__FILE__))}/deployable-rng.xml" end
- def display_digraph
- graph = GraphViz.new(:G, :type => :digraph)
- if has_reference?
draw_nodes(graph)
draw_edges(graph)
- else
draw_nodes(graph)
- end
- graph.output :png => String
- end
- def draw_nodes(graph)
- assemblies.each do |assembly|
graph.add_node(assembly.name)
- end
- end
- def draw_edges(graph)
- assemblies.each do |assembly|
references = assembly.root.xpath(".//reference")
unless references.empty?
references.each do |reference|
graph.add_edge(assembly.name,
reference.attributes['assembly'].value)
end
end
- end
- end
- def has_reference?
not @root.xpath("//reference").empty?
- end
- def name @root["name"] if @root end
diff --git a/src/app/views/deployables/service_dependencies.html.haml b/src/app/views/deployables/service_dependencies.html.haml new file mode 100644 index 0000000..075de04 --- /dev/null +++ b/src/app/views/deployables/service_dependencies.html.haml @@ -0,0 +1,11 @@ += render :partial => 'layouts/admin_nav' +%header.page-header
- .obj_actions
- .button-group
- if check_privilege(Privilege::MODIFY, deployable)
= link_to t('deployables.show.edit'),
edit_polymorphic_path([@catalog, deployable]), :class => 'button', :id => 'edit_button'
= link_to t('deployables.show.edit_xml'),
edit_polymorphic_path([@catalog, deployable], :edit_xml => true), :class => 'button', :id => 'edit_xml_button'
= button_to t('delete'), polymorphic_path([@catalog,
deployable]), :method => 'delete', :confirm => "#{t'catalog_entries.show.confirm_delete'}", :class => 'button danger', :id => 'delete'
- %h1.catalog_entries= deployable.name
+%p
- = image_tag(service_dependencies_deployable_path(deployable,
:format => :png)) \ No newline at end of file diff --git a/src/app/views/deployables/show.html.haml b/src/app/views/deployables/show.html.haml index a7ee021..d28db60 100644 --- a/src/app/views/deployables/show.html.haml +++ b/src/app/views/deployables/show.html.haml @@ -3,6 +3,7 @@ .obj_actions .button-group - if check_privilege(Privilege::MODIFY, @deployable)
= link_to t(".dependencies_diagram"),
service_dependencies_deployable_path(@deployable, :catalog_id => @catalog, :pushed_count => @pushed_count), :class => 'button' = link_to t('.edit'), edit_polymorphic_path([@catalog, @deployable]), :class => 'button', :id => 'edit_button' = link_to t('.edit_xml'), edit_polymorphic_path([@catalog, @deployable], :edit_xml => true), :class => 'button', :id => 'edit_xml_button' = button_to t('.delete'), polymorphic_path([@catalog, @deployable]), :method => 'delete', :confirm => "#{t'catalog_entries.show.confirm_delete'}", :class => 'button danger', :id => 'delete' diff --git a/src/config/initializers/mime_types.rb b/src/config/initializers/mime_types.rb index 18ecf33..bd77cce 100644 --- a/src/config/initializers/mime_types.rb +++ b/src/config/initializers/mime_types.rb @@ -20,3 +20,4 @@ # Mime::Type.register "text/richtext", :rtf # Mime::Type.register_alias "text/html", :iphone Mime::Type.register "image/svg+xml", :svg +Mime::Type.register "image/png", :png diff --git a/src/config/locales/en.yml b/src/config/locales/en.yml index 9295373..1684721 100644 --- a/src/config/locales/en.yml +++ b/src/config/locales/en.yml @@ -1036,6 +1036,7 @@ en: n_a: "N/A" uuids: "UUIDs" show_hide_uuids: "Show/Hide"
dependencies_diagram: Dependencies Diagram form: choose_xml: Choose Deployable XML file catalog: Catalog
diff --git a/src/config/routes.rb b/src/config/routes.rb index e7f26c5..18ed7f2 100644 --- a/src/config/routes.rb +++ b/src/config/routes.rb @@ -237,6 +237,7 @@ Conductor::Application.routes.draw do end member do get :definition
endget :service_dependencies end
Hi Jozef, I didn't have time to do a proper review yet, but have a few findings about this so far:
- graphviz has many pkg dependencies (it added 41 new pkgs). Maybe it
could be optional - if graphviz is not installed, one some warning about missing graphviz would be displayed.
- there is also already packaged graphviz-ruby gem - couldn't this be
used? I didn't check this, maybe it's not sufficient, but it could save us some packaging
- it seems that this code generates dependencies between assemblies,
what we need are dependencies between services: so nodes would be services, edges would represent param references, assembly would be represented by a frame around services belonging to this assembly.
I checked deployable xml schema and what confuses me is that it seems that a service param can reference a service _or_ an assembly (according to param definition in app/util/deployable-rng.xml). If a param references assembly, then we can't resolve dependencies between services. Dan, you are most familiar with this - what do you think about it? As I understand it, referencing whole assemblies should be disabled.
Jan
Services can depend on other services with in the same assembly. We don't have code that allows cross assembly references. If you are going to represent relationships do it service to service within an assembly.
There was talk to allow cross assembly relationships, but I doubt it will ever come to fruition.
Hm, from what I know, Audrey now waits with launching services of an assembly until all params for all services of the assembly are gathered. So if assembly1 references assembly2, assembly2 can't reference (directly or indirectly) assembly1 because of deadlock. Isn't it too big limitation?
Anyway, in current situation, conductor should make sure that: - there is no deadlock between services in an assembly - there is no deadlock between whole assemblies Right?
Visual representation of the relationships is a cool idea.
Dan