On 07/13/2012 02:22 PM, Jan Provazník wrote:
On 07/04/2012 06:03 PM, jzigmund(a)redhat.com wrote:
> From: Jozef Zigmund <jzigmund(a)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
> + get :service_dependencies
> end
> 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.
Visual representation of the relationships is a cool idea.
Dan