From: Jan Provaznik <jprovazn(a)redhat.com>
This patch significantly cleanups template UI backend. Drops most of hacks made
for package selction in beta1, though there is still metagroup support (will be
removed with new UI design).
I think this is a good base for future rework of views (while we get it from
design team). I also moved build actions into separate controller (BuildsController).
Note that you should run 'rake dc:prepare_repos' if you don't use pulp.
---
src/app/controllers/builds_controller.rb | 90 ++++++
src/app/controllers/templates_controller.rb | 298 +++++++------------
src/app/models/template.rb | 72 ++++--
src/app/util/image_descriptor_xml.rb | 41 ++--
src/app/util/repository_manager.rb | 149 +++-------
.../util/repository_manager/abstract_repository.rb | 4 +
.../util/repository_manager/comps_repository.rb | 78 +++---
src/app/util/repository_manager/pulp_repository.rb | 23 +-
src/app/views/builds/index.haml | 89 ++++++
src/app/views/builds/new.haml | 55 ++++
src/app/views/templates/_collections.haml | 11 +-
src/app/views/templates/_form.haml | 122 ++++++++
src/app/views/templates/_hidden_fields.haml | 4 +-
.../views/templates/_local_content_to_bundle.haml | 21 ++
src/app/views/templates/_managed_content.haml | 15 +-
src/app/views/templates/_metagroup_packages.haml | 14 +-
src/app/views/templates/_metagroups.haml | 13 +
.../views/templates/_preboot_configuration.haml | 11 +
src/app/views/templates/_search_packages.haml | 45 +++
src/app/views/templates/_searched_packages.haml | 43 ---
src/app/views/templates/_software_selection.haml | 39 +++
src/app/views/templates/build_form.haml | 55 ----
src/app/views/templates/builds.haml | 89 ------
src/app/views/templates/collections.haml | 1 +
src/app/views/templates/content_selection.haml | 56 ----
src/app/views/templates/edit.haml | 6 +
src/app/views/templates/index.haml | 2 +-
src/app/views/templates/metagroup_packages.haml | 1 +
src/app/views/templates/new.haml | 162 +-----------
src/app/views/templates/search_packages.haml | 1 +
src/config/navigation.rb | 6 +-
src/config/routes.rb | 10 +-
src/features/step_definitions/general_steps.rb | 3 +
src/features/step_definitions/template_steps.rb | 13 +-
src/features/support/paths.rb | 6 +-
src/features/template.feature | 67 +++--
src/spec/controllers/builds_controller_spec.rb | 37 +++
src/spec/controllers/templates_controller_spec.rb | 27 +--
src/spec/factories/template.rb | 25 +--
src/spec/models/template_spec.rb | 2 +-
src/spec/utils/repository_manager_spec.rb | 20 ++-
41 files changed, 917 insertions(+), 909 deletions(-)
create mode 100644 src/app/controllers/builds_controller.rb
create mode 100644 src/app/views/builds/index.haml
create mode 100644 src/app/views/builds/new.haml
create mode 100644 src/app/views/templates/_form.haml
create mode 100644 src/app/views/templates/_local_content_to_bundle.haml
create mode 100644 src/app/views/templates/_metagroups.haml
create mode 100644 src/app/views/templates/_preboot_configuration.haml
create mode 100644 src/app/views/templates/_search_packages.haml
delete mode 100644 src/app/views/templates/_searched_packages.haml
create mode 100644 src/app/views/templates/_software_selection.haml
delete mode 100644 src/app/views/templates/build_form.haml
delete mode 100644 src/app/views/templates/builds.haml
create mode 100644 src/app/views/templates/collections.haml
delete mode 100644 src/app/views/templates/content_selection.haml
create mode 100644 src/app/views/templates/edit.haml
create mode 100644 src/app/views/templates/metagroup_packages.haml
create mode 100644 src/app/views/templates/search_packages.haml
create mode 100644 src/features/step_definitions/general_steps.rb
create mode 100644 src/spec/controllers/builds_controller_spec.rb
diff --git a/src/app/controllers/builds_controller.rb
b/src/app/controllers/builds_controller.rb
new file mode 100644
index 0000000..820f28b
--- /dev/null
+++ b/src/app/controllers/builds_controller.rb
@@ -0,0 +1,90 @@
+class BuildsController < ApplicationController
+ before_filter :require_user
+
+ def section_id
+ 'build'
+ end
+
+ def index
+ require_privilege(Privilege::IMAGE_VIEW)
+ order = get_order('templates.name')
+ @running_images = Image.all(:include => :template, :conditions => ['status
IN (?)', Image::ACTIVE_STATES], :order => order)
+ @completed_images = Image.all(:include => :template, :conditions => {:status
=> Image::STATE_COMPLETE}, :order => order)
+ @failed_images = Image.all(:include => :template, :conditions => {:status =>
Image::STATE_FAILED}, :order => order)
+ end
+
+ def new
+ raise "select template to build" unless id = params[:template_id]
+ @tpl = Template.find(id)
+ @all_targets = Image.available_targets
+ end
+
+ def create
+ if params[:cancel]
+ redirect_to templates_path
+ return
+ end
+
+ @tpl = Template.find(params[:template_id])
+ @all_targets = Image.available_targets
+
+ if params[:targets].blank?
+ flash.now[:warning] = 'You need to check at least one provider format'
+ render :action => 'new'
+ return
+ end
+
+ @tpl.upload_template unless @tpl.uploaded
+ errors = {}
+ params[:targets].each do |target|
+ # FIXME: for beta release we check explicitly that provider and provider
+ # account exists
+ unless provider = Provider.find_by_cloud_type(target)
+ flash_error('Error while trying to build image',
+ 'no provider account' => "There is no provider of
'#{target}' type, \
+you can add provider on <a href=\"#{url_for :controller =>
'provider'}\">the providers page.</a>")
+ render :action => 'new' and return
+ end
+ if provider.cloud_accounts.empty?
+ flash_error('Error while trying to build image',
+ 'no provider account' => "There is no provider
account for '#{target}' \
+provider, you can add account on <a href=\"#{url_for :controller =>
'provider', \
+:action => 'accounts', :id => provider.id}\">the provider accounts
page</a>")
+ render :action => 'new' and return
+ end
+ begin
+ Image.build(@tpl, target)
+ rescue
+ errors[target] = $!.message
+ end
+ end
+ if errors.empty?
+ redirect_to builds_path
+ else
+ flash_error('Error while trying to build image', errors)
+ render :action => 'new'
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ end
+
+ private
+
+ # TODO: DRY this, is used in templates controller too
+ def get_order(default)
+ @order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc'
+ @order_field = params[:order_field] || default
+ "#{@order_field} #{@order_dir}"
+ end
+
+ def flash_error(summary, errs)
+ flash.now[:error] ||= {}
+ flash.now[:error][:summary] = summary
+ flash.now[:error][:failures] ||= {}
+ flash.now[:error][:failures].merge!(errs)
+ end
+end
diff --git a/src/app/controllers/templates_controller.rb
b/src/app/controllers/templates_controller.rb
index 12df295..403e6c3 100644
--- a/src/app/controllers/templates_controller.rb
+++ b/src/app/controllers/templates_controller.rb
@@ -2,7 +2,12 @@ require 'util/repository_manager'
class TemplatesController < ApplicationController
before_filter :require_user
- before_filter :check_permission, :except => [:index, :builds]
+ before_filter :check_permission, :except => :index
+ layout :layout
+
+ def layout
+ return "aggregator" unless request.xhr?
+ end
def section_id
'build'
@@ -18,31 +23,29 @@ class TemplatesController < ApplicationController
)
end
- def action
+ def index_action
if params[:new_template]
- redirect_to :action => 'new'
+ redirect_to new_template_path
elsif params[:assembly]
- redirect_to :action => 'assembly'
+ redirect_to assembly_template_path(:id => params[:ids].to_a.first)
elsif params[:deployment_definition]
- redirect_to :action => 'deployment_definition'
+ redirect_to deployment_definition_template_path(:id => params[:ids].to_a.first)
elsif params[:delete]
- redirect_to :action => 'delete', :ids => params[:ids].to_a
+ redirect_to destroy_multiple_templates_path(:ids => params[:ids].to_a)
elsif params[:edit]
- begin
- redirect_to :action => 'new', :id => get_selected_id
- rescue
- flash[:notice] = "No template selected"
- redirect_to :action => 'index'
+ if id = get_selected_id
+ redirect_to edit_template_path(:id => id)
+ else
+ redirect_to templates_path
end
elsif params[:build]
- begin
- redirect_to :action => 'build_form', 'template_id' =>
get_selected_id
- rescue
- flash[:notice] = "No template selected"
- redirect_to :action => 'index'
+ if id = get_selected_id
+ redirect_to new_build_path(:template_id => id)
+ else
+ redirect_to templates_path
end
else
- raise "Unknown action"
+ raise 'Unknown action'
end
end
@@ -51,183 +54,122 @@ class TemplatesController < ApplicationController
def dispatch
if params[:save]
create
-
elsif params[:cancel]
- redirect_to :action => 'index'
-
+ redirect_to templates_path
elsif params[:add_software_form]
- content_selection
-
+ collections
+ elsif params[:collections]
+ collections
elsif pkg = params.keys.find { |k| k =~ /^remove_package_(.*)$/ }
# actually remove the package from list
params[:packages].delete($1) if params[:packages]
new
-
elsif params[:add_selected]
new
-
elsif params[:cancel_add_software]
- params[:packages] = params[:selected_packages]
+ params[:selected_packages] = params[:packages]
+ params[:selected_groups] = params[:groups]
+ params[:cached_packages] = []
new
-
- elsif params.include?('show_metagroup')
- @metagroup = params['show_metagroup']
- content_selection
-
- elsif not params[:package_search].blank?
- content_selection
-
+ elsif params.include?('metagroup_packages')
+ metagroup_packages
+ elsif params[:package_search]
+ search_packages
+ else
+ raise "unknown action"
end
end
- # FIXME at some point split edit/update out from new/create
- # to conform to web standards
def new
# can't use @template variable - is used by compass (or something other)
- @id = params[:id]
- @tpl = @id.blank? ? Template.new : Template.find(@id)
- @tpl.attributes = params[:tpl] unless params[:tpl].nil?
- get_selected_packages(@tpl)
+ @tpl = Template.new(params[:tpl])
+ @repository_manager = RepositoryManager.new(:repositories => params[:repository]
|| @tpl.platform)
+ @tpl.add_software(params[:packages].to_a + params[:selected_packages].to_a +
params[:cached_packages].to_a,
+ params[:groups].to_a + params[:selected_groups].to_a)
render :action => :new
end
- def create
- @id = params[:tpl][:id]
- @tpl = @id.blank? || @id == "" ? Template.new(params[:tpl]) :
Template.find(@id)
-
- @tpl.xml.clear_packages
-
- params[:groups].to_a.each { |group| @tpl.xml.add_group(group) }
- params[:packages].to_a.each { |pkg| @tpl.xml.add_package(pkg) }
-
- # this is crazy, but we have most attrs in xml and also in model,
- # synchronize it at first to xml
- @tpl.update_xml_attributes(params[:tpl])
+ def edit
+ @tpl = Template.find(params[:id])
+ @tpl.attributes = params[:tpl] unless params[:tpl].blank?
+ @repository_manager = RepositoryManager.new(:repositories => params[:repository]
|| @tpl.platform)
+ render :action => :edit
+ end
+ def create
+ @tpl = Template.new(params[:tpl])
+ @tpl.packages = params[:packages]
if @tpl.save
flash[:notice] = "Template saved."
@tpl.set_complete
- redirect_to :action => 'index'
+ redirect_to templates_path
else
- get_selected_packages(@tpl)
+ @repository_manager = RepositoryManager.new(:repositories => params[:repository]
|| @tpl.platform)
render :action => 'new'
end
end
- def content_selection
- @repository_manager = RepositoryManager.new
- @id = params[:id]
- @tpl = @id.blank? ? Template.new : Template.find(@id)
- @tpl.attributes = params[:tpl] unless params[:tpl].nil?
- @packages = []
- @packages += params[:packages].collect{ |p| { :name => p } } unless
params[:packages].blank?
- @packages += params[:selected_packages].collect{ |p| { :name => p } } unless
params[:selected_packages].blank?
- @groups = @repository_manager.all_groups_with_tagged_selected_packages(@packages,
params[:repository] || @tpl.platform)
- @embed = params[:embed]
- @categories = @repository_manager.categories(params[:tpl] ? params[:tpl][:platform] :
nil)
- @metagroups = @repository_manager.metagroups
+ def update
+ @tpl = Template.find(params[:id])
+ @tpl.packages = []
- if not params[:package_search].blank?
- @page = get_page
- @cached_packages = params[:cached_packages].to_a
- @searched_packages = @repository_manager.search_package(params[:package_search],
- params[:repository] ||
@tpl.platform).paginate(:page => @page,
-
:per_page => 60)
- elsif not @metagroup.blank?
- if @metagroup == 'Collections'
- # TODO: if we remember selected groups, this could be done much more simply
- @collections =
@repository_manager.all_groups_with_tagged_selected_packages(@packages,
params[:repository] || @tpl.platform)
- else
- @metagroup_packages =
@repository_manager.metagroup_packages_with_tagged_selected_packages(@metagroup,
@packages, params[:repository] || @tpl.platform)
- end
+ if @tpl.update_attributes(params[:tpl])
+ @tpl.set_complete
+ flash[:notice] = "Template updated."
+ redirect_to templates_path
else
- @collections =
@repository_manager.all_groups_with_tagged_selected_packages(@packages,
params[:repository] || @tpl.platform)
- end
- if request.xhr?
- if @metagroup_packages
- render :partial => 'metagroup_packages' and return
- end
- if @searched_packages
- render :partial => 'searched_packages' and return
- end
- if @collections and @metagroup
- render :partial => 'collections' and return
- end
+ @repository_manager = RepositoryManager.new(:repositories => params[:repository]
|| @tpl.platform)
+ render :action => 'edit'
end
+ end
- if @embed
- render :layout => false
+ def search_packages
+ set_package_vars
+ @page = get_page
+ @cached_packages = params[:cached_packages].to_a + params[:selected_packages].to_a
+ @searched_packages = params[:package_search].empty? ? [] :
@repository_manager.search_package(
+ params[:package_search]).paginate(:page => @page, :per_page => 60)
+ if request.xhr?
+ render :partial => 'search_packages'
else
- render :action => :content_selection
+ render :search_packages
end
end
- def managed_content
- get_selected_packages
- render :layout => false
- end
-
- def build_form
- raise "select template to build" unless id = params[:template_id]
- @tpl = Template.find(id)
- @all_targets = Image.available_targets
- end
-
- def build
- if params[:cancel]
- redirect_to :action => 'index'
- return
- end
-
- @tpl = Template.find(params[:template_id])
- @all_targets = Image.available_targets
-
- if params[:targets].blank?
- flash.now[:warning] = 'You need to check at least one provider format'
- render :action => 'build_form'
- return
+ def metagroup_packages
+ set_package_vars
+ @metagroup_packages =
@repository_manager.metagroup_packages(params[:metagroup_packages])
+ if request.xhr?
+ render :partial => 'metagroup_packages'
+ else
+ render :metagroup_packages
end
+ end
- @tpl.upload_template unless @tpl.uploaded
- params[:targets].each do |target|
- # FIXME: for beta release we check explicitly that provider and provider
- # account exists
- unless provider = Provider.find_by_cloud_type(target)
- flash_error("There is no provider of '#{target}' type, you can add
provider \
-on <a href=\"#{url_for :controller => 'providers'}\">the
providers page.</a>")
- render :action => 'build_form' and return
- end
- if provider.cloud_accounts.empty?
- flash_error("There is no provider account for '#{target}' provider,
you can \
-add account on <a href=\"#{url_for :controller => 'providers', \
-:action => 'accounts', :id => provider.id}\">the provider accounts
page</a>")
- render :action => 'build_form' and return
- end
- begin
- Image.build(@tpl, target)
- rescue
- flash.now[:error] ||= {}
- flash.now[:error][:failures] ||= {}
- flash.now[:error][:failures][target] = $!.message
- end
- end
- if flash[:error] and not flash[:error][:failures].blank?
- flash[:error][:summary] = 'Error while trying to build image'
- render :action => 'build_form'
+ def collections
+ set_package_vars
+ @collections = @repository_manager.groups
+ if request.xhr?
+ render :partial => 'collections'
else
- redirect_to :action => 'builds'
+ render :collections
end
end
- def builds
- order = get_order('templates.name')
- @running_images = Image.all(:include => :template, :conditions => ['status
IN (?)', Image::ACTIVE_STATES], :order => order)
- @completed_images = Image.all(:include => :template, :conditions => {:status
=> Image::STATE_COMPLETE}, :order => order)
- @failed_images = Image.all(:include => :template, :conditions => {:status =>
Image::STATE_FAILED}, :order => order)
- require_privilege(Privilege::IMAGE_VIEW)
+ def content_selection
+ set_package_vars(true)
+ @collections = @repository_manager.groups
+ render :collections
end
- def delete
+ def managed_content
+ @tpl = params[:template_id].blank? ? Template.new :
Template.find(params[:template_id])
+ @tpl.add_software(params[:packages].to_a + params[:selected_packages].to_a,
+ params[:groups].to_a + params[:selected_groups].to_a)
+ render :layout => false
+ end
+
+ def destroy_multiple
ids = params[:ids].to_a
if ids.empty?
flash[:notice] = "No Template Selected"
@@ -242,12 +184,10 @@ add account on <a href=\"#{url_for :controller =>
'providers', \
if errs.empty?
flash[:notice] = 'Template deleted'
else
- flash[:error] ||= {}
- flash[:error][:summary] = 'Error while deleting template'
- (flash[:error][:failures] ||= {}).merge!(errs)
+ flash_error('Error while deleting template', errs)
end
end
- redirect_to :action => 'index'
+ redirect_to templates_path
end
def assembly
@@ -259,17 +199,27 @@ add account on <a href=\"#{url_for :controller =>
'providers', \
private
+ def set_package_vars(set_all = false)
+ @tpl = params[:id].blank? ? Template.new : Template.find(params[:id])
+ @tpl.attributes = params[:tpl] unless params[:tpl].nil?
+ @repository_manager = RepositoryManager.new(:repositories => params[:repository]
|| @tpl.platform)
+ @groups = @repository_manager.groups
+ @categories = @repository_manager.categories if not request.xhr? or set_all
+ @metagroups = @repository_manager.metagroups if not request.xhr? or set_all
+ @tpl.add_software(params[:packages].to_a, params[:groups].to_a)
+ end
+
def get_order(default)
@order_dir = params[:order_dir] == 'desc' ? 'desc' : 'asc'
@order_field = params[:order_field] || default
"#{@order_field} #{@order_dir}"
end
- def flash_error(msg)
+ def flash_error(summary, errs)
flash.now[:error] ||= {}
- flash.now[:error][:summary] = 'Error while trying to build image'
+ flash.now[:error][:summary] = summary
flash.now[:error][:failures] ||= {}
- flash.now[:error][:failures]['no provider account'] = msg
+ flash.now[:error][:failures].merge!(errs)
end
def check_permission
@@ -279,40 +229,12 @@ add account on <a href=\"#{url_for :controller =>
'providers', \
def get_selected_id
ids = params[:ids].to_a
if ids.size != 1
- raise "No Template Selected" if ids.empty?
- raise "You can select only one template" if ids.size > 1
+ flash[:warning] = ids.empty? ? 'No Template Selected' : 'You can select
only one template'
+ return
end
return ids.first
end
- def get_selected_packages(tpl=nil)
- @repository_manager = RepositoryManager.new
- @groups = @repository_manager.all_groups(params[:repository])
-
- if not params[:packages].blank? or not params[:selected_packages].blank? or not
params[:cached_packages].blank?
- @selected_packages = params[:packages].to_a + params[:selected_packages].to_a
- elsif !tpl.nil?
- @selected_packages = tpl.xml.packages.collect { |p| p[:name] }
- else
- @selected_packages = []
- end
-
- if params[:collections].to_s == 'true' or not request.xhr?
- [:selected_groups, :groups].each do |pg|
- if params[pg]
- params[pg].each { |grp|
- fg = @groups.find { |gk, gv| gk == grp }
- fg[1][:packages].each { |pk, pv|
- @selected_packages << pk
- } unless fg.nil?
- }
- end
- end
- end
-
- @selected_packages.uniq!
- end
-
def get_page
if params[:page] == 'Previous'
return params[:old_page].to_i - 1
diff --git a/src/app/models/template.rb b/src/app/models/template.rb
index e1e9df2..74bf208 100644
--- a/src/app/models/template.rb
+++ b/src/app/models/template.rb
@@ -4,7 +4,8 @@ require 'typhoeus'
class Template < ActiveRecord::Base
has_many :images, :dependent => :destroy
has_many :instances
- before_validation :update_attrs
+ before_validation :generate_uuid
+ before_save :update_xml
before_destroy :no_instances?
WAREHOUSE_CONFIG =
YAML.load_file("#{RAILS_ROOT}/config/image_warehouse.yml")
@@ -27,19 +28,6 @@ class Template < ActiveRecord::Base
true
end
- def update_xml_attributes(opts = {})
- xml.name = opts[:name] if opts[:name]
- xml.description = opts[:summary] if opts[:summary]
- if plat = opts[:platform]
- xml.platform = plat
- xml.platform_version = platforms[plat]['version'].to_s
- xml.architecture = platforms[plat]['architecture']
- end
- self[:xml] = xml.to_xml
- @xml = nil
- update_attrs
- end
-
def xml
@xml ||= ImageDescriptorXML.new(self[:xml].to_s)
end
@@ -54,14 +42,18 @@ class Template < ActiveRecord::Base
end
end
- def update_attrs
+ def generate_uuid
# TODO: generate real uuid here, e.g. with some ruby uuid generator
- self.uuid ||= "#{xml.name}-#{Time.now.to_f.to_s}"
- self.name = xml.name
- self.summary = xml.description
- self.platform = xml.platform
- self.platform_version = xml.platform_version
- self.architecture = xml.architecture
+ self.uuid ||= "#{self.name}-#{Time.now.to_f.to_s}"
+ end
+
+ def update_xml
+ xml.name = self.name
+ xml.description = self.summary
+ xml.platform = self.platform
+ xml.platform_version = self.platform_version
+ xml.architecture = self.architecture
+ write_attribute(:xml, xml.to_s)
end
def providers
@@ -83,4 +75,42 @@ class Template < ActiveRecord::Base
def platforms
@platforms ||=
YAML.load_file("#{RAILS_ROOT}/config/image_descriptor_platform_repositories.yml")
end
+
+ def add_packages(packages)
+ packages.to_a.each {|pkg| xml.add_package(pkg)}
+ end
+
+ def add_groups(groups)
+ groups.to_a.each {|pkg| xml.add_group(pkg)}
+ end
+
+ def add_software(packages, groups)
+ add_packages(packages)
+ add_groups(groups)
+ end
+
+ def platform=(plat)
+ write_attribute(:platform, plat)
+ self.platform_version = platforms[plat]['version'].to_s
+ self.architecture = platforms[plat]['architecture']
+ end
+
+ # packages and groups are virtual attributes
+ def packages
+ xml.packages
+ end
+
+ def packages=(packages)
+ xml.clear_packages
+ packages.to_a.each {|pkg| xml.add_package(pkg)}
+ end
+
+ def groups
+ xml.groups
+ end
+
+ def groups=(groups)
+ xml.clear_groups
+ groups.to_a.each {|group| xml.add_group(group)}
+ end
end
diff --git a/src/app/util/image_descriptor_xml.rb b/src/app/util/image_descriptor_xml.rb
index 034d943..e9f71d9 100644
--- a/src/app/util/image_descriptor_xml.rb
+++ b/src/app/util/image_descriptor_xml.rb
@@ -52,7 +52,7 @@ class ImageDescriptorXML
# platform
# update: we don't add platform repo, image builder chooses right one from OS
# name, but we add all other repos
- recreate_repo_nodes
+ #recreate_repo_nodes
get_or_create_node('os')['name'] = str
end
@@ -109,28 +109,28 @@ class ImageDescriptorXML
end
def packages
- packages = []
- @root.xpath('/image/packages/package').each do |s|
- packages << {:name => s.at_xpath('.//name').text}
+ @root.xpath('/image/packages/package').map do |s|
+ s.at_xpath('.//name').text
+ end
+ end
+
+ def groups
+ @root.xpath('/image/groups/group').map do |s|
+ s.at_xpath('.//name').text
end
- return packages
end
def add_package(pkg)
pkgs_node = get_or_create_node('packages')
- unless older = packages.find {|p| p[:name] == pkg}
- add_package_node(pkgs_node, pkg)
- end
+ add_package_node(pkgs_node, pkg) unless packages.include?(pkg)
end
def add_group(gname)
- unless group = repository_manager.all_groups[gname]
- raise "group #{gname} not found in repositories"
- end
- group[:packages].each do |p, info|
- next if info[:type] == 'optional'
- add_package(p)
- end
+ #unless group = repository_manager.groups.find(gname)
+ # raise "group #{gname} not found in repositories"
+ #end
+ node = get_or_create_node('groups')
+ add_group_node(node, gname) unless groups.include?(gname)
end
def remove_package(package)
@@ -145,12 +145,17 @@ class ImageDescriptorXML
@root.xpath('/image/packages').each { |s| s.remove }
end
+ def clear_groups
+ @root.xpath('/image/groups').each { |s| s.remove }
+ end
+
private
def add_group_node(parent, group)
- n = Nokogiri::XML::Node.new('group', @doc)
- n.content = group
- parent << n
+ pnode = get_or_create_node('group', parent)
+ n = Nokogiri::XML::Node.new('name', @doc)
+ n.content = name
+ pnode << n
end
def recreate_repo_nodes
diff --git a/src/app/util/repository_manager.rb b/src/app/util/repository_manager.rb
index 382f48d..8ada489 100644
--- a/src/app/util/repository_manager.rb
+++ b/src/app/util/repository_manager.rb
@@ -28,141 +28,63 @@ class RepositoryManager
@config = opts[:config] || load_config
@config = [ @config ] if Hash === @config
@repositories = get_repositories
+ @selected_repositories = get_selected_repositories(opts[:repositories])
end
- def all_groups(repository = nil)
- unless @all_groups
- @all_groups = {}
- repositories.each do |r|
- next if repository and repository != 'all' and repository != r.id
- r.groups.each do |group, data|
- if @all_groups[group]
- @all_groups[group][:packages].merge!(data[:packages])
- else
- @all_groups[group] = data
- end
- end
- end
- end
- return @all_groups
+ def groups
+ @groups ||= @selected_repositories.map {|repo| repo.groups}.flatten
end
- def packages(repository = nil)
+ def packages
+ @packages ||= @selected_repositories.map {|repo| repo.packages}.flatten
end
- def categories(repository = nil)
- unless @all_categories
- @all_categories = {}
- repositories.each do |r|
- next if repository and repository != 'all' and repository != r.id
- r.categories.each do |id, data|
- if @all_categories[id]
- @all_categories[id][:groups] += data[:groups]
- else
- @all_categories[id] = data
- end
- end
- end
+ def categories
+ @categories ||= @selected_repositories.map {|repo| repo.categories}.flatten
+ end
+
+ def repositories_hash
+ res = {}
+ @repositories.each do |r|
+ res[r.id] = r
end
- return @all_categories
+ res
end
- def packages(repository = nil)
- unless @packages
- @packages = []
- repositories.each do |r|
- next if repository and repository != 'all' and repository != r.id
- @packages += r.packages
- end
+ def search_package(str)
+ @selected_repositories.map {|repo| repo.search_package(str)}.flatten
+ end
+
+ # TODO (remove): this is temporary solution for categorizing packages
+ def metagroup_packages(category)
+ res = []
+ grps = groups
+ metagroups[category].to_a.each do |entry|
+ gname = entry[1]
+ cat = categories.find{|t| t[:id] == entry[0]}
+ group = grps.find{|g| g[:id] == gname}
+ next unless cat and cat[:groups].include?(gname) and group
+ next if res.find{|g| g[:name] == gname}
+ res << {:name => gname, :packages => group[:packages].keys}
end
- return @packages
+ res
end
- # TODO: this is temporary solution for categorizing packages
+ # TODO (remove): this is temporary solution for categorizing packages
def metagroups
unless @metagroups
@metagroups = {}
File.readlines('config/image_descriptor_package_metagroups.conf').each do
|line|
group, entries_str = line.chomp.split('=')
next unless group and entries_str
- @metagroups[group] = entries_str.split(',')
+ @metagroups[group] = entries_str.split(',').map {|entry|
entry.split(';')}
end
end
@metagroups
end
- def metagroup_packages(category, repository = nil)
- res = {}
- groups = all_groups(repository)
- metagroups[category].to_a.each do |entry|
- cat, group = entry.split(';')
- next unless c = categories[cat] and c[:groups].include?(group) and groups[group]
- res[group] = {:packages => groups[group][:packages].keys}
- end
- res
- end
-
- def metagroup_packages_with_tagged_selected_packages(category, pkgs, repository = nil)
- mgroups = metagroup_packages(category, repository)
- mgroups.each_value do |group|
- missing = false
- group[:packages].each do |pkg|
- unless pkgs.find {|p| p[:name] == pkg}
- missing = true
- break
- end
- end
- next if missing
- group[:selected] = true
- end
- mgroups
- end
-
- def all_groups_with_tagged_selected_packages(pkgs, repository = nil)
- groups = all_groups(repository)
- groups.each_value do |group|
- pkgs.each do |pkg|
- next unless p = group[:packages][pkg[:name]]
- p[:selected] = true
- end
- group[:selected] = is_group_selected(group)
- end
- return groups
- end
-
- def repositories_hash
- res = {}
- @repositories.each do |r|
- res[r.id] = r
- end
- res
- end
-
- def search_package(str, repository = nil)
- packages(repository).select {|p| p =~ /#{Regexp.escape(str)}/i}
- end
-
private
- # returns true if all non-optional packages are selected
- # (if there are only non-optional packages in the group,
- # all packages must be selected)
- def is_group_selected(group)
- all = true
- all_nonopt = true
- only_opt = true
- group[:packages].each_value do |pkg|
- all = false unless pkg[:selected]
- if pkg[:type] != 'optional'
- only_opt = false
- if !pkg[:selected]
- all_nonopt = false
- end
- end
- end
- return only_opt ? all : all_nonopt
- end
-
def load_config
YAML.load_file("#{RAILS_ROOT}/config/image_descriptor_package_repositories.yml")
end
@@ -178,4 +100,11 @@ class RepositoryManager
end
return repositories
end
+
+ def get_selected_repositories(repos)
+ return @repositories if repos.blank?
+ repos.map do |repo|
+ @repositories.find {|r| r.id == repo} or raise "repository '#{repo}'
not found"
+ end
+ end
end
diff --git a/src/app/util/repository_manager/abstract_repository.rb
b/src/app/util/repository_manager/abstract_repository.rb
index 5400ae1..7b73926 100644
--- a/src/app/util/repository_manager/abstract_repository.rb
+++ b/src/app/util/repository_manager/abstract_repository.rb
@@ -8,4 +8,8 @@ class AbstractRepository
@yumurl = conf['yumurl'] || conf['baseurl']
@type = conf['type']
end
+
+ def search_package(what)
+ packages.select {|p| p[:name] =~ /#{Regexp.escape(what)}/i}
+ end
end
diff --git a/src/app/util/repository_manager/comps_repository.rb
b/src/app/util/repository_manager/comps_repository.rb
index 6a90f14..494fbac 100644
--- a/src/app/util/repository_manager/comps_repository.rb
+++ b/src/app/util/repository_manager/comps_repository.rb
@@ -19,58 +19,55 @@ class CompsRepository < AbstractRepository
end
def packages
- pkgs = []
- groups.each_value do |g|
- pkgs += g[:packages].keys
- end
- pkgs.uniq
+ @packages ||= load_data[:packages]
end
def prepare_repo
- grps = {}
- @all_pkgs = pkg_names
- group_nodes.each do |g|
- pkgs = group_packages(g)
- next if pkgs.empty?
- name = g.at_xpath('name').text
- id = g.at_xpath('id').text
- grps[id] = {
- :name => name,
+ Dir.mkdir(@cache_dir) unless File.directory?(@cache_dir)
+ File.open(@cache_file, 'w') do |f|
+ Marshal.dump({
+ :packages => get_packages,
+ :groups => get_groups,
+ :categories => get_categories
+ }, f)
+ end
+ end
+
+ private
+
+ def get_packages
+ packages = package_nodes.map do |node|
+ {
+ #:id => node.at_xpath('./xmlns:id/child::text()').text,
+ :name => node.at_xpath('./xmlns:name/child::text()').text,
:repository_id => @id,
- :packages => pkgs
}
end
+ end
- other = {}
- @all_pkgs.each do |pkg, val|
- other[pkg] = {:type => 'optional'} if val != :listed
- end
- if other.size > 0
- name = 'unsorted'
- grps[name] = {
- :name => name,
+ def get_groups
+ group_nodes.map do |g|
+ pkgs = group_packages(g)
+ next if pkgs.empty?
+ {
+ :id => g.at_xpath('id').text,
+ :name => g.at_xpath('name').text,
:repository_id => @id,
- :packages => other
+ :packages => pkgs
}
end
+ end
- categories = {}
- category_nodes.each do |cat|
- id = cat.at_xpath('id').text
- categories[id] = {
+ def get_categories
+ category_nodes.map do |cat|
+ {
+ :id => cat.at_xpath('id').text,
:name => cat.at_xpath('name').text,
:groups => cat.xpath('./grouplist/groupid').map {|g| g.text}
}
end
-
- Dir.mkdir(@cache_dir) unless File.directory?(@cache_dir)
- File.open(@cache_file, 'w') do |f|
- Marshal.dump({:groups => grps, :categories => categories}, f)
- end
end
- private
-
def load_data
unless @load_data
begin
@@ -100,14 +97,9 @@ class CompsRepository < AbstractRepository
xml.xpath('/comps/category')
end
- def pkg_names
- pkgs = {}
+ def package_nodes
xml = Nokogiri::XML(primary_xml)
- xml.xpath('/xmlns:metadata/xmlns:package').each do |node|
- next unless name = node.at_xpath('./xmlns:name/child::text()')
- pkgs[name.text] = true
- end
- return pkgs
+ xml.xpath('/xmlns:metadata/xmlns:package')
end
def download_xml(url)
@@ -146,8 +138,6 @@ class CompsRepository < AbstractRepository
pkgs = {}
group_node.xpath('packagelist/packagereq').each do |p|
pkg_name = p.text
- next unless val = @all_pkgs[pkg_name]
- val = :listed
(pkgs[pkg_name] ||= {})[:type] = p.attr('type')
end
return pkgs
diff --git a/src/app/util/repository_manager/pulp_repository.rb
b/src/app/util/repository_manager/pulp_repository.rb
index 051bc47..b232d7f 100644
--- a/src/app/util/repository_manager/pulp_repository.rb
+++ b/src/app/util/repository_manager/pulp_repository.rb
@@ -35,41 +35,36 @@ class PulpRepository < AbstractRepository
end
def groups
- groups = {}
- WrappedRestClient.get(@groups_url, HTTP_OPTS).each do |id, info|
+ WrappedRestClient.get(@groups_url, HTTP_OPTS).map do |id, info|
pkgs = {}
info['default_package_names'].each {|p| pkgs[p] = {:type =>
'default'}}
info['optional_package_names'].each {|p| pkgs[p] = {:type =>
'optional'}}
info['mandatory_package_names'].each {|p| pkgs[p] = {:type =>
'mandatory'}}
next if pkgs.empty?
- name = info['name']
- groups[info['id']] = {
+ {
+ :id => id,
:name => info['name'],
:description => info['description'].to_s,
:repository_id => @id,
:packages => pkgs,
}
- end
- return groups
+ end.compact
end
def categories
- categories = {}
- WrappedRestClient.get(@categories_url, HTTP_OPTS).each do |id, info|
- categories[info['id']] = {
+ WrappedRestClient.get(@categories_url, HTTP_OPTS).map do |id, info|
+ {
+ :id => id,
:name => info['name'],
:groups => info['packagegroupids'],
}
end
- return categories
end
def packages
- packages = []
- WrappedRestClient.get(@packages_url, HTTP_OPTS).each do |info|
- packages << info['name']
+ WrappedRestClient.get(@packages_url, HTTP_OPTS).map do |info|
+ {:name => info['name']}
end
- return packages
end
private
diff --git a/src/app/views/builds/index.haml b/src/app/views/builds/index.haml
new file mode 100644
index 0000000..0d2d5ce
--- /dev/null
+++ b/src/app/views/builds/index.haml
@@ -0,0 +1,89 @@
+- columns = [ |
+ {:name => 'NAME', :sort_attr => 'templates.name'},
|
+ {:name => 'OS', :sort_attr => 'templates.platform'},
|
+ {:name => 'VERSION', :sort_attr => 'templates.platform_version'},
|
+ {:name => 'ARCH', :sort_attr => 'templates.architecture'},
|
+ {:name => 'STATUS', :sort_attr => 'status'},
|
+] |
+
+- form_tag :action => "" do
+ .actionsidebar.grid_3
+ %dl
+ %dt Build Job Actions
+ %dd
+ %h5 JOB QUEUE
+ %ul
+ %li.delete
+ %span
+ = submit_tag "Cancel Job", :name => "job_details",
:disabled => true, :class => "icon"
+ %li.show
+ %span
+ = submit_tag "Show Job Details", :name =>
"job_details", :disabled => true, :class => "icon"
+ %li.show
+ %span
+ = submit_tag "Show Job Log", :name => "job_log",
:disabled => true, :class => "icon"
+ %li.clear
+ %span
+ = submit_tag "Clear Job History", :name =>
"job_history", :disabled => true, :class => "icon"
+
+ .grid_13
+ %h1 Status
+ %section.wrap.status
+ %label.grid_4.alpha Image Warehouse Status:
+ .grid_3.suffix_6.omega
+ %span.good
+ Green
+
+ %label.grid_4.alpha Total Builds in Queue:
+ .grid_3.suffix_6.omega
+ = @running_images.size
+
+ %label.grid_4.alpha Number of VM's Building:
+ .grid_3.suffix_6.omega
+ = @running_images.select {|i| i.status == Image::STATE_BUILDING}.size
+
+ %h1 Running
+
+ %table
+ = sortable_table_header(columns)
+ %tbody
+ - if @running_images.empty?
+ %tr
+ %td{:colspan => 5} No Images
+ - else
+ - @running_images.each do |img|
+ %tr
+ %td= img.template.name
+ %td= img.template.platform
+ %td= img.template.platform_version
+ %td= img.template.architecture
+ %td= img.status
+
+ - unless @failed_images.empty?
+ %h1 Failed
+ %table
+ = sortable_table_header(columns)
+ %tbody
+ - @failed_images.each do |img|
+ %tr
+ %td= img.template.name
+ %td= img.template.platform
+ %td= img.template.platform_version
+ %td= img.template.architecture
+ %td= img.status
+
+ %h1 Completed
+ %table
+ = sortable_table_header(columns)
+ %tbody
+ - if @completed_images.empty?
+ %tr
+ %td{:colspan => 5} No Images
+ - else
+ - @completed_images.each do |img|
+ %tr
+ %td= img.template.name
+ %td= img.template.platform
+ %td= img.template.platform_version
+ %td= img.template.architecture
+ %td OK
diff --git a/src/app/views/builds/new.haml b/src/app/views/builds/new.haml
new file mode 100644
index 0000000..4cddb6f
--- /dev/null
+++ b/src/app/views/builds/new.haml
@@ -0,0 +1,55 @@
+%h2 BUILD REQUEST
+- form_tag :action => 'create' do
+ = hidden_field_tag :template_id, @tpl.id
+ %h3 Deployment Definition
+ %fieldset.clearfix
+ = label_tag :deploy_name, 'Deployment Definition Name:', :class =>
'grid_4'
+ = text_field_tag 'deploy_name', 'Deployment Name', :disabled =>
true, :class => 'grid_3'
+ = text_field_tag 'deploy_description', 'Deployment Description',
:disabled => true, :class => 'grid_3'
+ %fieldset.clearfix
+ .prefix_4.grid_6
+ = check_box_tag 'use_for_machine', 1, true, :disabled => true
+ = label_tag 'use_for_machine', 'Use for Machine Definition Name and
Description'
+ %fieldset.clearfix
+ .grid_7
+ = file_field :templates, :choose_logo, :value => 'Choose Logo',
:disabled => true
+ = text_field :templates, :logo_text, :value => 'Logo Text (5 characters)',
:disabled => true, :class => "grid_3"
+
+ %fieldset.clearfix
+ %label.grid_4{:for => :template_group}
+ Template Category:
+ .grid_3
+ = select_tag(:template_group, options_for_select([['User Private', 1]]))
+
+ %h3 Deployment Options
+ %fieldset.clearfix
+ .grid_6
+ %label OS:
+ = @tpl.platform
+ .grid_3
+ Hardware Profile
+ .grid_3.suffix_3
+ Locale
+ %fieldset.clearfix
+ .grid_3
+ %label OS Version:
+ = @tpl.platform_version
+ .grid_3.ra
+ %label Global Settings:
+ .grid_3
+ Small
+ .grid_3
+ Any
+ .grid_3
+ = submit_tag "Config", :name => "config", :disabled =>
true
+ %h3 Build Options
+ %label Choose Provider Format:
+ %section.clearfix.gap
+ %ul.block
+ - @all_targets.each do |target_id, target|
+ %li
+ = check_box_tag 'targets[]', target_id, false
+ = label_tag 'targets[]', target['name']
+
+ = submit_tag "Submit to Build", :name => "build"
+ = submit_tag "Cancel", :name => "cancel"
diff --git a/src/app/views/templates/_collections.haml
b/src/app/views/templates/_collections.haml
index 4623f6f..98ce959 100644
--- a/src/app/views/templates/_collections.haml
+++ b/src/app/views/templates/_collections.haml
@@ -1,9 +1,8 @@
-= hidden_field_tag :collections, true
-
%ul.collections
- - @collections.keys.sort.each do |id|
+ - @collections.each do |c|
%li
- - selected = @collections[id][:selected] ? true : false
- = check_box_tag 'groups[]', id, selected, {:disabled => selected, :id
=> "group_#{id}", :class => "#{selected ? 'selected' :
''}"}
- = label_tag "group_#{id}", @collections[id][:name]
+ /- selected = c[:selected] ? true : false
+ - selected = false
+ = check_box_tag 'groups[]', c[:id], selected, {:disabled => selected,
:id => "group_#{c[:id]}", :class => "#{selected ? 'selected'
: ''}"}
+ = label_tag "group_#{c[:id]}", c[:name]
= render :partial => 'addbuttons'
diff --git a/src/app/views/templates/_form.haml b/src/app/views/templates/_form.haml
new file mode 100644
index 0000000..dff9811
--- /dev/null
+++ b/src/app/views/templates/_form.haml
@@ -0,0 +1,122 @@
+:javascript
+ $(document).ready(function() {
+ var $content_container = $('#managed_content');
+ var $sel_pkg_container = $('#package_selection_list');
+ var $submit = $('#add_software_button');
+ $submit.click(function(e) {
+ e.preventDefault();
+ $submit.hide();
+ var data = {
+ 'packages[]':
$("input[name='packages[]']").map(function() {return
$(this).val()}).get(),
+ 'repository': $("select[name='tpl[platform]']").val()
|| ''
+ }
+ var url = '#{url_for :action => 'content_selection', :id =>
@id}';
+ //$content_container.empty().show();
+ $sel_pkg_container.empty().show().addClass('loading');
+ $sel_pkg_container.load(url, data, function(){
+ $sel_pkg_container.removeClass('loading');
+ var $groups = $('.softwaregroups .disclosure', this);
+ //search
+ $("input[name='package_search']").keypress(function(event) {
+ if (event.keyCode == '13') {
+ event.preventDefault();
+ $("input[name=package_search] ~ button").click();
+ }
+ });
+ $("input[name=package_search] ~ button").click(function(event) {
+ event.preventDefault();
+ var data = {
+ 'packages[]':
$("input:text[name='packages[]']").map(function() {return
$(this).val()}).get(),
+ 'package_search':
$("input[name='package_search']").val(),
+ 'repository':
$("select[name='tpl[platform]']").val()
+ };
+ var url = '#{url_for :action => 'search_packages', :id =>
@id}';
+ $('#metagrouppackages').empty().addClass('loading');
+ $('#metagrouppackages').load(url, data, function() {
+ $('#metagrouppackages').removeClass('loading');
+ });
+ });
+ });
+ });
+ //removing packages from the list
+ $('.remove_package').live('click', function (e) {
+ e.preventDefault();
+ $(this).parent().hide(300, function () {
+ $(this).remove();
+ });
+ });
+ //displaying extended package info and actions
+ $('.dropdown').hide();
+ $('.packagename').live('click', function () {
+ var dropdowncontent = $(this).siblings('.dropdown').html(),
+ $dropdown = $("#dropdown");
+ $('.packagewrap').removeClass('selected');
+ $(this).parent().addClass('selected');
+ $dropdown.empty().html(dropdowncontent).css({
+ 'top': $(this).positionAncestor('#content').top + 17,
+ 'left': $(this).positionAncestor('#content').left - 4
+ }).show();
+ });
+ //catch #content clicks and hide the #dropdown if it's not within it
+ $("#content").click(function (e) {
+ if(!e.target.id === 'dropdown' ||
!$(e.target).closest("#dropdown").length) {
+ $("#dropdown").hide();
+ $('.packagewrap').removeClass('selected');
+ }
+ });
+ // select correct package repo when we change platform
+ $("select[name='tpl[platform]']").change(function() {
+ if ($submit.is(':hidden')) {
+ $submit.trigger('click');
+ }
+ });
+ // add selected pkgs/groups
+ $('#do_add_software').live('click', function(e) {
+ e.preventDefault();
+ var $button = $(this).clone();
+ var label = "<span id='do_add_software' class='loading
fl'>Adding Packages</span>";
+ var url = '#{url_for :action => 'managed_content'}';
+ var new_pkgs =
$("input:checked[name='selected_packages[]']").map(function() {return
$(this).val()}).get();
+ var old_pkgs =
$("input:hidden[name='packages[]']").map(function() {return
$(this).val()}).get()
+ var cached_pkgs =
$("input:hidden[name='cached_packages[]']").map(function() {return
$(this).val()}).get()
+ var data = {
+ 'selected_packages[]': old_pkgs.concat(new_pkgs.concat(cached_pkgs)),
+ 'selected_groups[]':
$("input:checked[name='groups[]']").map(function() {return
$(this).val()}).get(),
+ 'collections': $("input:hidden[name=collections]").val(),
+ 'template_id' : '#{(a)id.nil? ? nil : @id}'
+ };
+ $(this).replaceWith(label);
+ $('#managed_content').load(url, data, function(){
+ $("input:checked[name='groups[]']").attr('disabled',
'disabled');
+ $("input:checked[name='packages[]']").attr('disabled',
'disabled');
+ // $('#add_software_button').show();
+ $('.dropdown').hide();
+ $('#do_add_software').replaceWith($button);
+ });
+ });
+ // hide sw selection panel
+ $('#cancel_add_software').live('click', function(e) {
+ e.preventDefault();
+ $('#package_selection_list').hide();
+ $('#add_software_button').show();
+ $('.dropdown').hide();
+ });
+ });
+
+= error_messages_for :tpl, :object_name => 'template'
+= render :partial => 'basics'
+= render :partial => 'local_content_to_bundle'
+
+#managed_content
+ = render :partial => 'managed_content'
+
+.clearfix
+ .grid_16.alpha.omega
+ = submit_tag "Add Software", :name => "add_software_form", :id
=> "add_software_button", :class => "iconbutton"
+
+#package_selection_list{:style => 'display: none'}
+
+= render :partial => 'preboot_configuration'
+
+= submit_tag "Save", :name => "save", :class =>
"formbutton"
+= submit_tag "Cancel", :name => "cancel", :class =>
"formbutton"
diff --git a/src/app/views/templates/_hidden_fields.haml
b/src/app/views/templates/_hidden_fields.haml
index 3fcab65..5709087 100644
--- a/src/app/views/templates/_hidden_fields.haml
+++ b/src/app/views/templates/_hidden_fields.haml
@@ -1,8 +1,8 @@
-- # the template fields as hidden form inputs
-<input type="hidden" id="id" name="id"
value="#{@id}" />
= hidden_field :tpl, :id
= hidden_field :tpl, :name
= hidden_field :tpl, :summary
= hidden_field :tpl, :platform
= hidden_field :tpl, :platform_version
= hidden_field :tpl, :architecture
+- @tpl.packages.each do |p|
+ = hidden_field_tag "packages[]", p, :id => "package_#{p}"
diff --git a/src/app/views/templates/_local_content_to_bundle.haml
b/src/app/views/templates/_local_content_to_bundle.haml
new file mode 100644
index 0000000..109ce20
--- /dev/null
+++ b/src/app/views/templates/_local_content_to_bundle.haml
@@ -0,0 +1,21 @@
+%h3.disabled.gap Local Content to Bundle
+%fieldset.clearfix
+ = label_tag :local_bundle_name, 'Local:', :class => "disabled grid_2
alpha"
+ = text_field_tag 'local_bundle_name[]', 'Bundle Name', :disabled =>
true, :class => "grid_8"
+ .grid_6.omega
+ %button{:type => 'button', :disabled => 'disabled'} Browse
+ %button{:type => 'button', :disabled => 'disabled'} Config
+ %button{:type => 'button', :disabled => 'disabled'} Metadata
+ (
+ %a{:href => '#'} Remove
+ )
+ .grid_2.alpha
+
+ = text_field_tag 'local_bundle_name[]', 'Bundle Name', :disabled =>
true, :class => "grid_8"
+ .grid_6.omega
+ %button{:type => 'button', :disabled => 'disabled'} Browse
+ %button{:type => 'button', :disabled => 'disabled'} Config
+ %button{:type => 'button', :disabled => 'disabled'} Metadata
+ (
+ %a{:href => '#'} Remove
+ )
diff --git a/src/app/views/templates/_managed_content.haml
b/src/app/views/templates/_managed_content.haml
index 86b076f..5b9f13a 100644
--- a/src/app/views/templates/_managed_content.haml
+++ b/src/app/views/templates/_managed_content.haml
@@ -1,20 +1,21 @@
#selected_packages
%h3.gap Managed Content to Bundle
.grid_16.alpha.omega
- - if @selected_packages.empty?
+ - if @tpl.packages.empty?
No selected packages
- else
- - repos = @repository_manager.repositories_hash
- - @selected_packages.sort.each do |pkg|
- - pkg_group = @groups.keys.find {|g| @groups[g][:packages][pkg]}
+ /- repos = @repository_manager.repositories_hash
+ - @tpl.packages.sort.each do |pkg|
+ /- pkg_group = @groups.keys.find {|g| @groups[g][:packages][pkg]}
.packagewrap
%a.packagename{:id => "package_#{pkg}"}=pkg
= hidden_field_tag 'packages[]', pkg, :id =>
"package_#{pkg}"
= submit_tag "Remove", :name => "remove_package_#{pkg}",
:id => "remove_package_#{pkg}", :class => 'remove_package'
.dropdown
- %section
- Repository:
- %label= (pkg_group and repo = repos[@groups[pkg_group][:repository_id]]) ?
repo.name.to_s : ' '
+ / we don't display repository for now, it's pretty difficult with
current design
+ /%section
+ / Repository:
+ / %label= (pkg_group and repo = repos[@groups[pkg_group][:repository_id]]) ?
repo.name.to_s : ' '
%fieldset.nomargin
%button{:disabled => true} Browse
%button{:disabled => true} Config
diff --git a/src/app/views/templates/_metagroup_packages.haml
b/src/app/views/templates/_metagroup_packages.haml
index c709f97..3e83d34 100644
--- a/src/app/views/templates/_metagroup_packages.haml
+++ b/src/app/views/templates/_metagroup_packages.haml
@@ -4,16 +4,16 @@
%h4
= "#{@metagroup} Packages"
%ul.metagrouppackages
- - @metagroup_packages.keys.sort.each do |group|
+ - @metagroup_packages.sort {|a, b| a[:name] <=> b[:name]}.each do |group|
%li
- - selected = !@metagroup_packages[group][:selected].nil?
+ - selected = false
%h5
- = check_box_tag 'groups[]', group, selected, {:disabled => selected,
:id => "group_#{group}", :class => "softwaregroups #{selected ?
'selected' : ''}"}
- = label_tag "group_#{group}", group
+ = check_box_tag 'selected_groups[]', group[:id], selected, {:disabled
=> selected, :id => "group_#{group[:id]}", :class =>
"softwaregroups #{selected ? 'selected' : ''}"}
+ = label_tag "group_#{group[:id]}", group[:name]
%ul
- - @metagroup_packages[group][:packages].each do |pkg|
+ - group[:packages].each do |pkg|
%li
- selected = @packages.to_a.find {|p| p[:name] == pkg}
- = check_box_tag 'packages[]', pkg, selected, {:disabled =>
selected, :id => "pkg_#{group}_#{pkg}"}
- = label_tag "pkg_#{group}_#{pkg}", pkg
+ = check_box_tag 'selected_packages[]', pkg, selected, {:disabled
=> selected, :id => "pkg_#{group[:name]}_#{pkg}"}
+ = label_tag "pkg_#{group[:name]}_#{pkg}", pkg
= render :partial => 'addbuttons'
diff --git a/src/app/views/templates/_metagroups.haml
b/src/app/views/templates/_metagroups.haml
new file mode 100644
index 0000000..b4fcf3f
--- /dev/null
+++ b/src/app/views/templates/_metagroups.haml
@@ -0,0 +1,13 @@
+%fieldset.clearfix
+ .search.grid_4.alpha
+ %input{:type => "search", :placeholder => "Search for
package", :name => 'package_search', :value => params[:package_search],
:id => 'package_search'}
+ %button.action{:id => 'package_search_button'}
+ .grid_8
+ %a.grid_4.omega Advanced Search
+
+%ul.metagroups{:class => 'packagegroupsidebar grid_4 alpha'}
+ %li
+ = submit_tag 'Collections', :name => 'collections', :id =>
'collections', :class => 'icon'
+ - @metagroups.keys.sort.each do |cat|
+ %li
+ = submit_tag cat, :name => "metagroup_packages", :class =>
'icon'
diff --git a/src/app/views/templates/_preboot_configuration.haml
b/src/app/views/templates/_preboot_configuration.haml
new file mode 100644
index 0000000..79ae839
--- /dev/null
+++ b/src/app/views/templates/_preboot_configuration.haml
@@ -0,0 +1,11 @@
+%h3.clear.gap Preboot Configuration
+%fieldset.clearfix
+ .grid_4.alpha
+ = radio_button_tag :configure_via_script, 'no', :disabled => true
+ = label_tag :configure_via_script, 'Configure Via Script'
+ = file_field_tag 'script_file', :disabled => true, :class => 'grid_12
omega'
+%fieldset.clearfix
+ .grid_4.alpha
+ = radio_button_tag :configure_via_script, 'no', :disabled => true
+ = label_tag :configure_via_script, 'Configure Via Script'
+ = file_field_tag 'script_file', :disabled => true, :class => 'grid_12
omega'
diff --git a/src/app/views/templates/_search_packages.haml
b/src/app/views/templates/_search_packages.haml
new file mode 100644
index 0000000..873f2ab
--- /dev/null
+++ b/src/app/views/templates/_search_packages.haml
@@ -0,0 +1,45 @@
+:javascript
+ $(document).ready(function() {
+ $('.pagination input[type=submit]').click(function(e) {
+ e.preventDefault();
+ var url = '#{url_for :action => 'dispatch', :id => @id}';
+ var old_pkgs =
$("input:hidden[name='cached_packages[]']").map(function() {return
$(this).val()}).get();
+ var new_pkgs =
$("input:checked[name='selected_packages[]']").map(function() {return
$(this).val()}).get();
+ var data = {
+ 'selected_packages[]':
$("input:hidden[name='packages[]']").map(function() {return
$(this).val()}).get(),
+ 'cached_packages[]': old_pkgs.concat(new_pkgs),
+ 'selected_groups[]':
$("input:checked[name='groups[]']").map(function() {return
$(this).val()}).get(),
+ 'package_search':
$("input[name='package_search']").val(),
+ 'old_page': '#{@page}',
+ 'template_id' : '#{(a)id.nil? ? nil : @id}',
+ 'page': $(this).val(),
+ 'repository': $("select[name='tpl[platform]']").val()
+ };
+ $('#metagrouppackages').empty().addClass('loading');
+ $('#metagrouppackages').load(url, data, function() {
+ $('#metagrouppackages').removeClass('loading');
+ })
+ });
+ });
+
+- @cached_packages.uniq.each do |pkg|
+ = hidden_field_tag 'cached_packages[]', pkg
+
+- if params[:package_search].empty?
+ Search string is empty.
+-else
+ %h4
+ = "Search Results for '#{params[:package_search]}'"
+ %ul.searchedpackages
+ - @searched_packages.sort {|a, b| a [:name] <=> b[:name]}.each do |pkg|
+ %li
+ - selected = (@packages.to_a.find {|p| p[:name] == pkg[:name]} or
@cached_packages.include?(pkg[:name]))
+ - disabled = @tpl.packages.include?(pkg[:name])
+ = check_box_tag 'selected_packages[]', pkg[:name], selected, {:disabled
=> disabled, :id => "pkg_#{pkg[:name]}"}
+ = label_tag "pkg_#{pkg[:name]}", pkg[:name]
+ .pageinfo
+ = page_entries_info @searched_packages, :entry_name => 'package'
+ = will_paginate @searched_packages, :params => {:package_search =>
params[:package_search]}, :renderer => TemplatesHelper::ButtonPaginationRenderer.new,
:previous_label => 'Previous', :next_label => 'Next'
+
+
+ = render :partial => 'addbuttons'
diff --git a/src/app/views/templates/_searched_packages.haml
b/src/app/views/templates/_searched_packages.haml
deleted file mode 100644
index 6533f1a..0000000
--- a/src/app/views/templates/_searched_packages.haml
+++ /dev/null
@@ -1,43 +0,0 @@
-:javascript
- $(document).ready(function() {
- $('.pagination input[type=submit]').click(function(e) {
- e.preventDefault();
- var url = '#{url_for :action => 'dispatch', :id => @id}';
- var old_pkgs =
$("input:hidden[name='cached_packages[]']").map(function() {return
$(this).val()}).get();
- var new_pkgs =
$("input:checked[name='packages[]']").map(function() {return
$(this).val()}).get();
- var data = {
- 'selected_packages[]':
$("input:hidden[name='packages[]']").map(function() {return
$(this).val()}).get(),
- 'cached_packages[]': old_pkgs.concat(new_pkgs),
- 'selected_groups[]':
$("input:checked[name='groups[]']").map(function() {return
$(this).val()}).get(),
- 'package_search':
$("input[name='package_search']").val(),
- 'old_page': '#{@page}',
- 'template_id' : '#{(a)id.nil? ? nil : @id}',
- 'page': $(this).val(),
- 'repository': $("select[name='tpl[platform]']").val()
- };
- $('#metagrouppackages').empty().addClass('loading');
- $('#metagrouppackages').load(url, data, function() {
- $('#metagrouppackages').removeClass('loading');
- Aggregator.hook_selected_packages();
- })
- });
- });
-
-- @cached_packages.uniq.each do |pkg|
- = hidden_field_tag 'cached_packages[]', pkg
-
-%h4
- = "Search Results for '#{params[:package_search]}'"
-%ul.searchedpackages
- - @searched_packages.sort.each do |pkg|
- %li
- - selected = (@packages.to_a.find {|p| p[:name] == pkg} or
@cached_packages.include?(pkg))
- - disabled = params[:selected_packages].to_a.include?(pkg)
- = check_box_tag 'packages[]', pkg, selected, {:disabled => disabled, :id
=> "pkg_#{pkg}"}
- = label_tag "pkg_#{pkg}", pkg
-.pageinfo
- = page_entries_info @searched_packages, :entry_name => 'package'
-= will_paginate @searched_packages, :params => {:package_search =>
params[:package_search]}, :renderer => TemplatesHelper::ButtonPaginationRenderer.new,
:previous_label => 'Previous', :next_label => 'Next'
-
-
-= render :partial => 'addbuttons'
diff --git a/src/app/views/templates/_software_selection.haml
b/src/app/views/templates/_software_selection.haml
new file mode 100644
index 0000000..79bbe1e
--- /dev/null
+++ b/src/app/views/templates/_software_selection.haml
@@ -0,0 +1,39 @@
+:javascript
+ $(document).ready(function() {
+ var $metagrouppackages = $('#metagrouppackages');
+ $('.metagroups input').click(function(e) {
+ e.preventDefault();
+ var data = {
+ 'repository': $("select[name='tpl[platform]']").val(),
+ 'packages[]':
$("input:hidden[name='packages[]']").map(function() {return
$(this).val()}).get()
+ };
+ if ($(this).attr('name') == 'collections') {
+ var url = '#{url_for :action => 'collections', :id =>
@id}';
+ } else {
+ var url = '#{url_for :action => 'metagroup_packages', :id =>
@id}';
+ data.metagroup_packages = e.currentTarget.value;
+ }
+ $metagrouppackages.empty().addClass('loading');
+ $metagrouppackages.load(url, data, function() {
+ $metagrouppackages.removeClass('loading');
+ //select all packages in collection
+ $(".softwaregroups").click(function() {
+ if ($(this).attr("checked") === true) {
+
$(this).parent().siblings("ul").find("input[type='checkbox']").attr("checked","checked");
+ } else {
+
$(this).parent().siblings("ul").find("input[type='checkbox']").removeAttr("checked");
+ }
+ });
+ });
+ });
+ });
+
+.grid_16
+ %h4 Managed Content Selection
+
+ - form_tag :action => 'dispatch' do
+ - unless request.xhr?
+ = render :partial => 'hidden_fields'
+ = render :partial => 'metagroups'
+ #metagrouppackages.grid_12.omega.gap
+ = render :partial => view
diff --git a/src/app/views/templates/build_form.haml
b/src/app/views/templates/build_form.haml
deleted file mode 100644
index 7084f39..0000000
--- a/src/app/views/templates/build_form.haml
+++ /dev/null
@@ -1,55 +0,0 @@
-%h2 BUILD REQUEST
-- form_tag :action => 'build' do
- = hidden_field_tag :template_id, @tpl.id
- %h3 Deployment Definition
- %fieldset.clearfix
- = label_tag :deploy_name, 'Deployment Definition Name:', :class =>
'grid_4'
- = text_field_tag 'deploy_name', 'Deployment Name', :disabled =>
true, :class => 'grid_3'
- = text_field_tag 'deploy_description', 'Deployment Description',
:disabled => true, :class => 'grid_3'
- %fieldset.clearfix
- .prefix_4.grid_6
- = check_box_tag 'use_for_machine', 1, true, :disabled => true
- = label_tag 'use_for_machine', 'Use for Machine Definition Name and
Description'
- %fieldset.clearfix
- .grid_7
- = file_field :templates, :choose_logo, :value => 'Choose Logo',
:disabled => true
- = text_field :templates, :logo_text, :value => 'Logo Text (5 characters)',
:disabled => true, :class => "grid_3"
-
- %fieldset.clearfix
- %label.grid_4{:for => :template_group}
- Template Category:
- .grid_3
- = select_tag(:template_group, options_for_select([['User Private', 1]]))
-
- %h3 Deployment Options
- %fieldset.clearfix
- .grid_6
- %label OS:
- = @tpl.platform
- .grid_3
- Hardware Profile
- .grid_3.suffix_3
- Locale
- %fieldset.clearfix
- .grid_3
- %label OS Version:
- = @tpl.platform_version
- .grid_3.ra
- %label Global Settings:
- .grid_3
- Small
- .grid_3
- Any
- .grid_3
- = submit_tag "Config", :name => "config", :disabled =>
true
- %h3 Build Options
- %label Choose Provider Format:
- %section.clearfix.gap
- %ul.block
- - @all_targets.each do |target_id, target|
- %li
- = check_box_tag 'targets[]', target_id, false
- = label_tag 'targets[]', target['name']
-
- = submit_tag "Submit to Build", :name => "build"
- = submit_tag "Cancel", :name => "cancel"
diff --git a/src/app/views/templates/builds.haml b/src/app/views/templates/builds.haml
deleted file mode 100644
index 0d2d5ce..0000000
--- a/src/app/views/templates/builds.haml
+++ /dev/null
@@ -1,89 +0,0 @@
-- columns = [ |
- {:name => 'NAME', :sort_attr => 'templates.name'},
|
- {:name => 'OS', :sort_attr => 'templates.platform'},
|
- {:name => 'VERSION', :sort_attr => 'templates.platform_version'},
|
- {:name => 'ARCH', :sort_attr => 'templates.architecture'},
|
- {:name => 'STATUS', :sort_attr => 'status'},
|
-] |
-
-- form_tag :action => "" do
- .actionsidebar.grid_3
- %dl
- %dt Build Job Actions
- %dd
- %h5 JOB QUEUE
- %ul
- %li.delete
- %span
- = submit_tag "Cancel Job", :name => "job_details",
:disabled => true, :class => "icon"
- %li.show
- %span
- = submit_tag "Show Job Details", :name =>
"job_details", :disabled => true, :class => "icon"
- %li.show
- %span
- = submit_tag "Show Job Log", :name => "job_log",
:disabled => true, :class => "icon"
- %li.clear
- %span
- = submit_tag "Clear Job History", :name =>
"job_history", :disabled => true, :class => "icon"
-
- .grid_13
- %h1 Status
- %section.wrap.status
- %label.grid_4.alpha Image Warehouse Status:
- .grid_3.suffix_6.omega
- %span.good
- Green
-
- %label.grid_4.alpha Total Builds in Queue:
- .grid_3.suffix_6.omega
- = @running_images.size
-
- %label.grid_4.alpha Number of VM's Building:
- .grid_3.suffix_6.omega
- = @running_images.select {|i| i.status == Image::STATE_BUILDING}.size
-
- %h1 Running
-
- %table
- = sortable_table_header(columns)
- %tbody
- - if @running_images.empty?
- %tr
- %td{:colspan => 5} No Images
- - else
- - @running_images.each do |img|
- %tr
- %td= img.template.name
- %td= img.template.platform
- %td= img.template.platform_version
- %td= img.template.architecture
- %td= img.status
-
- - unless @failed_images.empty?
- %h1 Failed
- %table
- = sortable_table_header(columns)
- %tbody
- - @failed_images.each do |img|
- %tr
- %td= img.template.name
- %td= img.template.platform
- %td= img.template.platform_version
- %td= img.template.architecture
- %td= img.status
-
- %h1 Completed
- %table
- = sortable_table_header(columns)
- %tbody
- - if @completed_images.empty?
- %tr
- %td{:colspan => 5} No Images
- - else
- - @completed_images.each do |img|
- %tr
- %td= img.template.name
- %td= img.template.platform
- %td= img.template.platform_version
- %td= img.template.architecture
- %td OK
diff --git a/src/app/views/templates/collections.haml
b/src/app/views/templates/collections.haml
new file mode 100644
index 0000000..a899c85
--- /dev/null
+++ b/src/app/views/templates/collections.haml
@@ -0,0 +1 @@
+= render :partial => 'software_selection', :locals => {:view =>
'collections'}
diff --git a/src/app/views/templates/content_selection.haml
b/src/app/views/templates/content_selection.haml
deleted file mode 100644
index 689c33d..0000000
--- a/src/app/views/templates/content_selection.haml
+++ /dev/null
@@ -1,56 +0,0 @@
-:javascript
- $(document).ready(function() {
- var $metagrouppackages = $('#metagrouppackages');
- $('.metagroups input[name="show_metagroup"]').click(function(e) {
- e.preventDefault();
- var data = {
- 'show_metagroup': e.currentTarget.value,
- 'repository': $("select[name='tpl[platform]']").val(),
- 'packages[]':
$("input:hidden[name='packages[]']").map(function() {return
$(this).val()}).get()
- };
- var url = '#{url_for :action => 'dispatch', :id => @id}';
- $metagrouppackages.empty().addClass('loading');
- $metagrouppackages.load(url, data, function() {
- $metagrouppackages.removeClass('loading');
- Aggregator.hook_selected_packages();
- //select all packages in collection
- $(".softwaregroups").click(function() {
- if ($(this).attr("checked") === true) {
-
$(this).parent().siblings("ul").find("input[type='checkbox']").attr("checked","checked");
- } else {
-
$(this).parent().siblings("ul").find("input[type='checkbox']").removeAttr("checked");
- }
- });
- });
- });
- Aggregator.hook_selected_packages();
- });
-
-.grid_16
- %h4 Managed Content Selection
-
- - form_tag :action => "dispatch" do
- - unless @embed
- = render :partial => 'hidden_fields'
- - @packages.each do |p|
- <input type="hidden" id="selected_package_#{p[:name]}"
name="selected_packages[]" value="#{p[:name]}" />
- %fieldset.clearfix
- .search.grid_4.alpha
- %input{:type => "search", :placeholder => "Search for
package", :name => 'package_search', :value =>
params[:package_search]}
- %button.action
- .grid_8
- %a.grid_4.omega Advanced Search
-
- %ul.metagroups{:class => 'packagegroupsidebar grid_4 alpha'}
- %li
- = submit_tag 'Collections', :name => 'show_metagroup', :id
=> 'collections', :class => 'icon'
- - @metagroups.keys.sort.each do |cat|
- %li
- = submit_tag cat, :name => "show_metagroup", :class =>
'icon'
- #metagrouppackages.grid_12.omega.gap
- - if @collections
- = render :partial => 'collections'
- - elsif @searched_packages
- = render :partial => 'searched_packages'
- - else
- = render :partial => 'metagroup_packages'
diff --git a/src/app/views/templates/edit.haml b/src/app/views/templates/edit.haml
new file mode 100644
index 0000000..a2fece4
--- /dev/null
+++ b/src/app/views/templates/edit.haml
@@ -0,0 +1,6 @@
+#dropdown
+.grid_16
+ %h2 Edit Template
+ - form_for @tpl, :url => {:action => 'dispatch'} do
+ = hidden_field_tag :id, @tpl.id
+ = render :partial => 'form'
diff --git a/src/app/views/templates/index.haml b/src/app/views/templates/index.haml
index 0d4c515..38b32de 100644
--- a/src/app/views/templates/index.haml
+++ b/src/app/views/templates/index.haml
@@ -1,4 +1,4 @@
-- form_tag(:action => 'action') do
+- form_tag(:action => 'index_action') do
.actionsidebar.grid_3
%dl
%dt Actions
diff --git a/src/app/views/templates/metagroup_packages.haml
b/src/app/views/templates/metagroup_packages.haml
new file mode 100644
index 0000000..9703663
--- /dev/null
+++ b/src/app/views/templates/metagroup_packages.haml
@@ -0,0 +1 @@
+= render :partial => 'software_selection', :locals => {:view =>
'metagroup_packages'}
diff --git a/src/app/views/templates/new.haml b/src/app/views/templates/new.haml
index 669babb..9ae8525 100644
--- a/src/app/views/templates/new.haml
+++ b/src/app/views/templates/new.haml
@@ -1,161 +1,5 @@
-:javascript
- $(document).ready(function() {
- var $content_container = $('#managed_content');
- var $sel_pkg_container = $('#package_selection_list');
- var $submit = $('#add_software_button');
- $submit.click(function(e) {
- e.preventDefault();
- $submit.hide();
- var data = {
- 'packages[]':
$("input[name='packages[]']").map(function() {return
$(this).val()}).get(),
- 'repository': $("select[name='tpl[platform]']").val()
|| ''
- }
- var url = '#{url_for :action => 'content_selection', :embed =>
true, :id => @id}';
- //$content_container.empty().show();
- $sel_pkg_container.empty().show().addClass('loading');
- $sel_pkg_container.load(url, data, function(){
- $sel_pkg_container.removeClass('loading');
- var $groups = $('.softwaregroups .disclosure', this);
- //search
- $("input[name='package_search']").keypress(function(event) {
- if (event.keyCode == '13') {
- event.preventDefault();
- $("input[name=package_search] ~ button").click();
- }
- });
- $("input[name=package_search] ~ button").click(function(event) {
- event.preventDefault();
- var data = {
- 'packages[]':
$("input:text[name='packages[]']").map(function() {return
$(this).val()}).get(),
- 'package_search':
$("input[name='package_search']").val(),
- 'repository':
$("select[name='tpl[platform]']").val()
- };
- var url = '#{url_for :action => 'dispatch', :id =>
@id}';
- $('#metagrouppackages').empty().addClass('loading');
- $('#metagrouppackages').load(url, data, function() {
- $('#metagrouppackages').removeClass('loading');
- Aggregator.hook_selected_packages();
- });
- });
- });
- });
- //removing packages from the list
- $('.remove_package').live('click', function (e) {
- e.preventDefault();
- $(this).parent().hide(300, function () {
- $(this).remove();
- });
- });
- //displaying extended package info and actions
- $('.dropdown').hide();
- $('.packagename').live('click', function () {
- var dropdowncontent = $(this).siblings('.dropdown').html(),
- $dropdown = $("#dropdown");
- $('.packagewrap').removeClass('selected');
- $(this).parent().addClass('selected');
- $dropdown.empty().html(dropdowncontent).css({
- 'top': $(this).positionAncestor('#content').top + 17,
- 'left': $(this).positionAncestor('#content').left - 4
- }).show();
- });
- //catch #content clicks and hide the #dropdown if it's not within it
- $("#content").click(function (e) {
- if(!e.target.id === 'dropdown' ||
!$(e.target).closest("#dropdown").length) {
- $("#dropdown").hide();
- $('.packagewrap').removeClass('selected');
- }
- });
- // select correct package repo when we change platform
- $("select[name='tpl[platform]']").change(function() {
- if ($submit.is(':hidden')) {
- $submit.trigger('click');
- }
- });
- Aggregator.hook_selected_packages = function() {
- $('#do_add_software').live('click', function(e) {
- e.preventDefault();
- var $button = $(this).clone();
- var label = "<span id='do_add_software' class='loading
fl'>Adding Packages</span>";
- var url = '#{url_for :action => 'managed_content'}';
- var new_pkgs =
$("input:checked[name='packages[]']").map(function() {return
$(this).val()}).get();
- var old_pkgs =
$("input:hidden[name='packages[]']").map(function() {return
$(this).val()}).get()
- var cached_pkgs =
$("input:hidden[name='cached_packages[]']").map(function() {return
$(this).val()}).get()
- var data = {
- 'selected_packages[]': old_pkgs.concat(new_pkgs.concat(cached_pkgs)),
- 'selected_groups[]':
$("input:checked[name='groups[]']").map(function() {return
$(this).val()}).get(),
- 'cached_packages[]':
$("input:text[name='cached[]']").map(function() {return
$(this).val()}).get(),
- 'collections': $("input:hidden[name=collections]").val(),
- 'template_id' : '#{(a)id.nil? ? nil : @id}'
- };
- $(this).replaceWith(label);
- $('#managed_content').load(url, data, function(){
- $("input:checked[name='groups[]']").attr('disabled',
'disabled');
-
$("input:checked[name='packages[]']").attr('disabled',
'disabled');
- $('#add_software_button').show();
- $('.dropdown').hide();
- $('#do_add_software').replaceWith($button);
- });
- });
- $('#cancel_add_software').click(function(e) {
- e.preventDefault();
- $('#package_selection_list').hide();
- $('#add_software_button').show();
- $('.dropdown').hide();
- });
- }
- });
-
#dropdown
.grid_16
- %h2 Template
- - form_for @tpl, :url => { :action => "dispatch" } do
- <input type="hidden" id="id" name="id"
value="#{@id}" />
- = hidden_field :tpl, :id
- = error_messages_for :tpl, :object_name => 'template'
- = render :partial => 'basics'
-
- %h3.disabled.gap Local Content to Bundle
- %fieldset.clearfix
- = label_tag :local_bundle_name, 'Local:', :class => "disabled
grid_2 alpha"
- = text_field_tag 'local_bundle_name[]', 'Bundle Name', :disabled
=> true, :class => "grid_8"
- .grid_6.omega
- %button{:type => 'button', :disabled => 'disabled'} Browse
- %button{:type => 'button', :disabled => 'disabled'} Config
- %button{:type => 'button', :disabled => 'disabled'}
Metadata
- (
- %a{:href => '#'} Remove
- )
- .grid_2.alpha
-
- = text_field_tag 'local_bundle_name[]', 'Bundle Name', :disabled
=> true, :class => "grid_8"
- .grid_6.omega
- %button{:type => 'button', :disabled => 'disabled'} Browse
- %button{:type => 'button', :disabled => 'disabled'} Config
- %button{:type => 'button', :disabled => 'disabled'}
Metadata
- (
- %a{:href => '#'} Remove
- )
-
- #managed_content
- = render :partial => 'managed_content'
-
- .clearfix
- .grid_16.alpha.omega
- = submit_tag "Add Software", :name => "add_software_form",
:id => "add_software_button", :class => "iconbutton"
-
- #package_selection_list{:style => 'display: none'}
-
- %h3.clear.gap Preboot Configuration
- %fieldset.clearfix
- .grid_4.alpha
- = radio_button_tag :configure_via_script, 'no', :disabled => true
- = label_tag :configure_via_script, 'Configure Via Script'
- = file_field_tag 'script_file', :disabled => true, :class =>
'grid_12 omega'
- %fieldset.clearfix
- .grid_4.alpha
- = radio_button_tag :configure_via_script, 'no', :disabled => true
- = label_tag :configure_via_script, 'Configure Via Script'
- = file_field_tag 'script_file', :disabled => true, :class =>
'grid_12 omega'
-
- = submit_tag "Save", :name => "save", :class =>
"formbutton"
- = submit_tag "Cancel", :name => "cancel", :class =>
"formbutton"
+ %h2 New Template
+ - form_for @tpl, :url => {:action => 'dispatch'} do
+ = render :partial => 'form'
diff --git a/src/app/views/templates/search_packages.haml
b/src/app/views/templates/search_packages.haml
new file mode 100644
index 0000000..94e30f5
--- /dev/null
+++ b/src/app/views/templates/search_packages.haml
@@ -0,0 +1 @@
+= render :partial => 'software_selection', :locals => {:view =>
'search_packages'}
diff --git a/src/config/navigation.rb b/src/config/navigation.rb
index 3b63df1..9f5c8eb 100644
--- a/src/config/navigation.rb
+++ b/src/config/navigation.rb
@@ -30,10 +30,8 @@ SimpleNavigation::Configuration.run do |navigation|
second_level.item :assistance_requests, t(:assistance_requests), '#',
:class => 'disabled'
end
first_level.item :define, t(:define), '#', :class => 'build' do
|second_level|
- # TODO: currently we exclude /templates/builds (next tab), but
- # we could have special controller for builds in future
- second_level.item :deployables, t(:deployables), {:controller =>
'templates'}, :highlights_on => /(\/templates$|\/templates\/(?!builds))/
- second_level.item :builds, t(:builds), :controller => 'templates',
:action => 'builds'
+ second_level.item :deployables, t(:deployables), {:controller =>
'templates'}, :highlights_on => /\/templates/
+ second_level.item :builds, t(:builds), :controller => 'builds', :action
=> 'index'
second_level.item :images, t(:images), '#', :class =>
'disabled'
end
first_level.item :runtime, t(:runtime), '#', :class => 'runtime'
do |second_level|
diff --git a/src/config/routes.rb b/src/config/routes.rb
index f59a2aa..e0672ef 100644
--- a/src/config/routes.rb
+++ b/src/config/routes.rb
@@ -46,7 +46,7 @@ ActionController::Routing::Routes.draw do |map|
map.dashboard '/dashboard', :controller => 'dashboard'
map.instance '/instances', :controller => 'instances'
- map.templates '/templates', :controller => 'templates'
+ # map.templates '/templates', :controller => 'templates'
map.settings '/settings', :controller => 'settings'
map.root :dashboard
@@ -54,6 +54,14 @@ ActionController::Routing::Routes.draw do |map|
# Will be re-enabled in upcoming patch
map.resources :providers
+ map.resources :templates, :collection => { :destroy_multiple => :get },
+ :member => {
+ :assembly => :get,
+ :deployment_definition => :get,
+ :action => :get,
+ }
+ map.resources :builds
+
# Allow downloading Web Service WSDL as a file with an extension
# instead of a file named 'wsdl'
map.connect ':controller/service.wsdl', :action => 'wsdl'
diff --git a/src/features/step_definitions/general_steps.rb
b/src/features/step_definitions/general_steps.rb
new file mode 100644
index 0000000..df1f588
--- /dev/null
+++ b/src/features/step_definitions/general_steps.rb
@@ -0,0 +1,3 @@
+Then /^I should see an input "([^\"]*)"$/ do |value|
+ response.should have_selector("form input[value=#{value}]")
+end
diff --git a/src/features/step_definitions/template_steps.rb
b/src/features/step_definitions/template_steps.rb
index 65b89c1..894bf0a 100644
--- a/src/features/step_definitions/template_steps.rb
+++ b/src/features/step_definitions/template_steps.rb
@@ -17,8 +17,7 @@ Given /^There is a mock pulp repository$/ do
end
Given /^there is a "([^"]*)" template$/ do |name|
- @template = Factory.build :template
- @template.xml.name = name
+ @template = Factory.build :template, :name => name
@template.save!
end
@@ -27,14 +26,13 @@ Given /^there is a package group$/ do
end
Given /^no package is selected$/ do
- @template.xml.packages = []
+ @template.packages = []
end
Given /^there is one selected package$/ do
pkg = RepositoryManager.new.all_packages.first
- @template.xml.packages = []
- @template.xml.add_package(pkg['name'], nil)
- @template.save_xml!
+ @template.packages = [pkg['name']]
+ @template.save!
end
# "I jump" is used instead of "I am" because "I am" is
already defined in
@@ -72,8 +70,7 @@ Then /^I should see "([^"]*)" followed by
"([^"]*)"$/ do |arg1, arg2|
end
Given /^there is a "([^"]*)" build$/ do |arg1|
- template = Factory.build :template
- template.xml.name = arg1
+ template = Factory.build :template, :name => arg1
template.save!
image = Factory.build(:image, :template => template)
image.save!
diff --git a/src/features/support/paths.rb b/src/features/support/paths.rb
index e948161..1c73ffa 100644
--- a/src/features/support/paths.rb
+++ b/src/features/support/paths.rb
@@ -66,16 +66,16 @@ module NavigationHelpers
url_for :action => 'new', :controller => 'permissions',
:only_path => true
when /the new template page/
- url_for :action => 'new', :controller => 'templates',
:only_path => true
+ url_for new_template_path
when /the template builds page/
- url_for :action => 'builds', :controller => 'templates',
:only_path => true
+ url_for builds_path
when /the templates page/
templates_path
when /the create template page/
- url_for :action => 'create', :controller => 'templates',
:only_path => true
+ url_for create_template_path
when /the self service settings page/
url_for :action => 'self_service', :controller => 'settings',
:only_path => true
diff --git a/src/features/template.feature b/src/features/template.feature
index 3404638..4ce0151 100644
--- a/src/features/template.feature
+++ b/src/features/template.feature
@@ -21,27 +21,38 @@ Feature: Manage Templates
And I should see "Template saved"
And I should see "mocktemplate"
- Scenario: Add group and remove package to/from the template
- Given I am on the templates page
- When I press "Template"
- Then I should be on the new template page
- When I fill in the following:
- | tpl_name | mocktemplate |
- And I press "Add Software"
- Then I should see "Managed Content Selection"
- When I press "Collections"
- And I check "group_deltacloud"
+ Scenario: Add a searched package to a new template
+ Given I am on the new template page
+ When I press "Add Software"
+ And I fill in "package_search" with "libdeltacloud"
+ And I press "package_search_button"
+ Then I should see "libdeltacloud"
+ When I check "libdeltacloud"
And I press "Add Selected"
- Then I should see "Managed Content to Bundle"
- And the "tpl[name]" field by name should contain "mocktemplate"
- And the page should contain "#package_libdeltacloud" selector
- When I press "remove_package_libdeltacloud"
- Then I should see "Managed Content to Bundle"
- And the page should not contain "#package_libdeltacloud" selector
- When I press "Save"
- Then I should be on the templates page
- And I should see "Template saved"
- And I should see "mocktemplate"
+ Then I should see "New Template"
+ And I should see "libdeltacloud"
+
+ #Scenario: Add group and remove package to/from the template
+ # Given I am on the templates page
+ # When I press "Template"
+ # Then I should be on the new template page
+ # When I fill in the following:
+ # | tpl_name | mocktemplate |
+ # And I press "Add Software"
+ # Then I should see "Managed Content Selection"
+ # When I press "Collections"
+ # And I check "group_deltacloud"
+ # And I press "Add Selected"
+ # Then I should see "Managed Content to Bundle"
+ # And the "tpl[name]" field by name should contain "mocktemplate"
+ # And the page should contain "#package_libdeltacloud" selector
+ # When I press "remove_package_libdeltacloud"
+ # Then I should see "Managed Content to Bundle"
+ # And the page should not contain "#package_libdeltacloud" selector
+ # When I press "Save"
+ # Then I should be on the templates page
+ # And I should see "Template saved"
+ # And I should see "mocktemplate"
Scenario: Sorting templates
Given there is a "mock1" template
@@ -60,3 +71,19 @@ Feature: Manage Templates
Then I should see "mock1" followed by "mock2"
When I follow "Name"
Then I should see "mock2" followed by "mock1"
+
+ Scenario: Search software with empty string
+ Given I am on the new template page
+ When I press "Add Software"
+ And I fill in "package_search" with ""
+ And I press "package_search_button"
+ Then I should see "Search string is empty"
+
+ Scenario: Show software selection
+ Given I am on the new template page
+ And I press "Add Software"
+ Then I should see an input "Collections"
+ # test that we see a metagroup
+ Then I should see an input "admin-tools"
+ # test that we see a collection (collections are loaded by default)
+ And I should see an input "deltacloud"
diff --git a/src/spec/controllers/builds_controller_spec.rb
b/src/spec/controllers/builds_controller_spec.rb
new file mode 100644
index 0000000..ef4f3d4
--- /dev/null
+++ b/src/spec/controllers/builds_controller_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe BuildsController do
+ fixtures :all
+ before(:each) do
+ @admin_permission = Factory :admin_permission
+ @admin = @admin_permission.user
+ @tuser = Factory :tuser
+ activate_authlogic
+ end
+
+ context "when a user has permission to build templates" do
+ #FIXME: The following functionality needs to come out of the controller
+
+ before(:each) do
+ UserSession.create(@admin)
+ @template = Factory.create(:template)
+ hydra = Typhoeus::Hydra.hydra
+ hydra.stub(:put, %r{http://localhost:9090/templates/.*}).and_return(
+ Typhoeus::Response.new(:code => 200))
+ Factory.create(:mock_cloud_account)
+ Factory.create(:mock_provider)
+ end
+
+ it "should create a new Image" do
+ lambda do
+ post :create, :template_id => @template.id, :targets => ["mock"]
+ end.should change(Image, :count).by(1)
+ end
+
+ it "should create a new ReplicatedImage" do
+ lambda do
+ post :create, :template_id => @template.id, :targets => ["mock"]
+ end.should change(ReplicatedImage, :count).by(1)
+ end
+ end
+end
diff --git a/src/spec/controllers/templates_controller_spec.rb
b/src/spec/controllers/templates_controller_spec.rb
index 6e23609..0ead1b0 100644
--- a/src/spec/controllers/templates_controller_spec.rb
+++ b/src/spec/controllers/templates_controller_spec.rb
@@ -13,7 +13,7 @@ describe TemplatesController do
it "should allow a user with image_modify permission to create new template"
do
UserSession.create(@admin)
lambda do
- post :create, :tpl => { :name => 'template', :platform =>
'fedora', :platform_version => '11', :architecture =>
'64-bit' }
+ post :create, :tpl => { :name => 'template', :platform =>
'fedora' }
end.should change(Template, :count).by(1)
response.should redirect_to(templates_path)
end
@@ -23,29 +23,4 @@ describe TemplatesController do
get :new
response.should_not render_template("new")
end
-
- context "when a user has permission to build templates" do
- #FIXME: The following functionality needs to come out of the controller
-
- before(:each) do
- UserSession.create(@admin)
- @template = Factory.create(:template)
- hydra = Typhoeus::Hydra.hydra
- hydra.stub(:put, %r{http://localhost:9090/templates/.*}).and_return(
- Typhoeus::Response.new(:code => 200))
- Factory.create(:mock_cloud_account)
- end
-
- it "should create a new Image" do
- lambda do
- post :build, :template_id => @template.id, :targets => ["mock"]
- end.should change(Image, :count).by(1)
- end
-
- it "should create a new ReplicatedImage" do
- lambda do
- post :build, :template_id => @template.id, :targets => ["mock"]
- end.should change(ReplicatedImage, :count).by(1)
- end
- end
end
diff --git a/src/spec/factories/template.rb b/src/spec/factories/template.rb
index 7130370..0305147 100644
--- a/src/spec/factories/template.rb
+++ b/src/spec/factories/template.rb
@@ -1,25 +1,4 @@
-Factory.sequence :template_name do |n|
- "template#{n}"
-end
-
Factory.define :template do |i|
- i.xml { %Q{
-<image>
- <name>#{Factory.next :template_name}</name>
- <repos>
- <repo>https://localhost/pulp/repos/jboss2</repo>
- </repos>
- <os name="Fedora" version="13"
architecture="64-bit"/>
- <description/>
- <services/>
- <groups>
- <group>JBoss Core Packages</group>
- </groups>
- <packages>
- <package><name>jboss-as5</name><group>JBoss Core
Packages</group></package>
- <package><name>jboss-jgroups</name><group>JBoss Core
Packages</group></package>
- </packages>
-</image>
- }
-}
+ i.sequence(:name) { |n| "template#{n}" }
+ i.platform 'fedora'
end
diff --git a/src/spec/models/template_spec.rb b/src/spec/models/template_spec.rb
index 407657f..406febd 100644
--- a/src/spec/models/template_spec.rb
+++ b/src/spec/models/template_spec.rb
@@ -19,7 +19,7 @@ describe Template do
it "should not be valid if template name is too long" do
t = Factory.build(:template)
- t.xml.name = ('a' * 256)
+ t.name = ('a' * 256)
t.valid?.should be_false
t.errors[:name].should_not be_nil
t.errors[:name].should =~ /^is too long.*/
diff --git a/src/spec/utils/repository_manager_spec.rb
b/src/spec/utils/repository_manager_spec.rb
index c2da511..98ff157 100644
--- a/src/spec/utils/repository_manager_spec.rb
+++ b/src/spec/utils/repository_manager_spec.rb
@@ -8,6 +8,8 @@ describe RepositoryManager do
'../fixtures/packagegroups.json'))
@packages_json = File.read(File.join(File.dirname(__FILE__),
'../fixtures/packages.json'))
+ @packagegroupcategories_json = File.read(File.join(File.dirname(__FILE__),
+
'../fixtures/packagegroupcategories.json'))
end
before(:each) do
@@ -18,6 +20,8 @@ describe RepositoryManager do
Typhoeus::Response.new(:code => 200, :body => @packagegroups_json))
hydra.stub(:get,
"http://pulptest/repositories/fedora/packages/").and_return(
Typhoeus::Response.new(:code => 200, :body => @packages_json))
+ hydra.stub(:get,
"http://pulptest/repositories/fedora/packagegroupcategories/").and_return(
+ Typhoeus::Response.new(:code => 200, :body => @packagegroupcategories_json))
@rmanager = RepositoryManager.new(:config => [{
'baseurl' => 'http://pulptest',
@@ -26,13 +30,23 @@ describe RepositoryManager do
}])
end
- it "should return a list of repositories" do
+ it 'should return a list of repositories' do
@rmanager.repositories.should have(1).items
@rmanager.repositories.first.id.should eql('fedora')
end
- it "should return a list of packagegroups" do
+ it 'should return a list of packagegroups' do
rep = @rmanager.repositories.first
- rep.groups.keys.sort.should == ["deltacloud"]
+ rep.groups.first[:id].should == 'deltacloud'
+ end
+
+ it 'should return a list of categories' do
+ @rmanager.categories.should have(1).items
+ @rmanager.categories.first[:id].should eql('base-system')
+ end
+
+ it "should return a list of packages" do
+ @rmanager.packages.should have(2).items
+ @rmanager.packages.first[:name].should eql('libdeltacloud')
end
end
--
1.7.2.3