This includes models and model rspec tests for Assemblies, Deployments, and Deployables. Associated role/privilege additions needed for these types are also included.
Signed-off-by: Scott Seago sseago@redhat.com --- src/app/models/assembly.rb | 67 ++++++++++++++++ src/app/models/deployable.rb | 61 ++++++++++++++ src/app/models/deployment.rb | 84 ++++++++++++++++++++ src/app/models/image_warehouse_object.rb | 42 ++++++++++ src/app/models/instance.rb | 24 +++++- src/app/models/permission.rb | 6 ++ src/app/models/permissioned_object.rb | 2 +- src/app/models/privilege.rb | 9 ++ src/app/models/template.rb | 23 +----- src/db/migrate/20110207100700_create_assemblies.rb | 24 ++++++ .../migrate/20110207100800_update_deployables.rb | 24 ++++++ .../migrate/20110207100900_create_deployments.rb | 17 ++++ src/db/migrate/20110207101000_update_instances.rb | 21 +++++ src/db/migrate/20110207101100_deployment_roles.rb | 65 +++++++++++++++ src/db/seeds.rb | 17 +++- src/spec/factories/assembly.rb | 5 + src/spec/factories/deployable.rb | 4 + src/spec/factories/deployment.rb | 6 ++ src/spec/models/assembly_spec.rb | 25 ++++++ src/spec/models/deployable_spec.rb | 25 ++++++ src/spec/models/deployment_spec.rb | 59 ++++++++++++++ src/spec/models/instance_spec.rb | 13 +++- 22 files changed, 591 insertions(+), 32 deletions(-) create mode 100644 src/app/models/assembly.rb create mode 100644 src/app/models/deployment.rb create mode 100644 src/app/models/image_warehouse_object.rb create mode 100644 src/db/migrate/20110207100700_create_assemblies.rb create mode 100644 src/db/migrate/20110207100800_update_deployables.rb create mode 100644 src/db/migrate/20110207100900_create_deployments.rb create mode 100644 src/db/migrate/20110207101000_update_instances.rb create mode 100644 src/db/migrate/20110207101100_deployment_roles.rb create mode 100644 src/spec/factories/assembly.rb create mode 100644 src/spec/factories/deployable.rb create mode 100644 src/spec/factories/deployment.rb create mode 100644 src/spec/models/assembly_spec.rb create mode 100644 src/spec/models/deployable_spec.rb create mode 100644 src/spec/models/deployment_spec.rb
diff --git a/src/app/models/assembly.rb b/src/app/models/assembly.rb new file mode 100644 index 0000000..5a47525 --- /dev/null +++ b/src/app/models/assembly.rb @@ -0,0 +1,67 @@ +# +# Copyright (C) 2011 Red Hat, Inc. +# Written by Scott Seago sseago@redhat.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. A copy of the GNU General Public License is +# also available at http://www.gnu.org/copyleft/gpl.html. + +require 'sunspot_rails' +class Assembly < ActiveRecord::Base + include PermissionedObject + include ImageWarehouseObject + searchable do + text :name, :as => :code_substring + text :architecture, :as => :code_substring + text :summary, :as => :code_substring + end + + has_and_belongs_to_many :templates + has_and_belongs_to_many :deployables + has_many :instances + + has_many :permissions, :as => :permission_object, :dependent => :destroy, + :include => [:role], + :order => "permissions.id ASC" + + before_validation :generate_uuid + before_save :update_xml + + has_many :permissions, :as => :permission_object, :dependent => :destroy, + :include => [:role], + :order => "permissions.id ASC" + + validates_presence_of :uuid + validates_uniqueness_of :uuid + validates_presence_of :name + validates_uniqueness_of :name + validates_length_of :name, :maximum => 255 + validates_presence_of :architecture + + def self.default_privilege_target_type + Template + end + + def update_xml + xml.name = self.name + xml.description = self.summary + xml.architecture = self.architecture + write_attribute(:xml, xml.to_xml) + end + + def self.find_or_create(id) + id ? Assembly.find(id) : Assembly.new + end + +end diff --git a/src/app/models/deployable.rb b/src/app/models/deployable.rb index f4891d8..9ed15ef 100644 --- a/src/app/models/deployable.rb +++ b/src/app/models/deployable.rb @@ -1,2 +1,63 @@ +# +# Copyright (C) 2011 Red Hat, Inc. +# Written by Scott Seago sseago@redhat.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. A copy of the GNU General Public License is +# also available at http://www.gnu.org/copyleft/gpl.html. + +require 'sunspot_rails' class Deployable < ActiveRecord::Base + include PermissionedObject + include ImageWarehouseObject + searchable do + text :name, :as => :code_substring + text :summary, :as => :code_substring + end + + has_and_belongs_to_many :assemblies + has_many :deployments + + has_many :permissions, :as => :permission_object, :dependent => :destroy, + :include => [:role], + :order => "permissions.id ASC" + + before_validation :generate_uuid + before_save :update_xml + + has_many :permissions, :as => :permission_object, :dependent => :destroy, + :include => [:role], + :order => "permissions.id ASC" + + validates_presence_of :uuid + validates_uniqueness_of :uuid + validates_presence_of :name + validates_uniqueness_of :name + validates_length_of :name, :maximum => 255 + + def self.default_privilege_target_type + Template + end + + def update_xml + xml.name = self.name + xml.description = self.summary + write_attribute(:xml, xml.to_xml) + end + + def self.find_or_create(id) + id ? Deployable.find(id) : Deployable.new + end + end diff --git a/src/app/models/deployment.rb b/src/app/models/deployment.rb new file mode 100644 index 0000000..1b41871 --- /dev/null +++ b/src/app/models/deployment.rb @@ -0,0 +1,84 @@ +# +# Copyright (C) 2011 Red Hat, Inc. +# Written by Scott Seago sseago@redhat.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. A copy of the GNU General Public License is +# also available at http://www.gnu.org/copyleft/gpl.html. + +require 'sunspot_rails' +class Deployment < ActiveRecord::Base + include SearchFilter + include PermissionedObject + + searchable do + text :name, :as => :code_substring + end + + belongs_to :pool + + belongs_to :deployable + has_many :instances + + belongs_to :realm + belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" + + has_many :permissions, :as => :permission_object, :dependent => :destroy, + :include => [:role], + :order => "permissions.id ASC" + + validates_presence_of :pool_id + validates_presence_of :deployable_id + + validates_presence_of :name + validates_uniqueness_of :name, :scope => :pool_id + validates_length_of :name, :maximum => 1024 + + SEARCHABLE_COLUMNS = %w(name) + + def object_list + super << pool + end + class << self + alias orig_list_for_user_include list_for_user_include + alias orig_list_for_user_conditions list_for_user_conditions + end + + def self.list_for_user_include + includes = orig_list_for_user_include + includes << { :pool => {:permissions => {:role => :privileges}}} + includes + end + + def self.list_for_user_conditions + "(#{orig_list_for_user_conditions}) or + (permissions_pools.user_id=:user and + privileges_roles.target_type=:target_type and + privileges_roles.action=:action)" + end + + def get_action_list(user=nil) + # FIXME: how do actions and states interact for deployments? + # For instances the list comes from the provider based on current state. + # Deployments don't currently have an explicit state field, but + # something could be calculated from associated instances. + ["start", "stop", "reboot"] + end + + def valid_action?(action) + return get_action_list.include?(action) ? true : false + end + + +end diff --git a/src/app/models/image_warehouse_object.rb b/src/app/models/image_warehouse_object.rb new file mode 100644 index 0000000..48dd04f --- /dev/null +++ b/src/app/models/image_warehouse_object.rb @@ -0,0 +1,42 @@ +# +# Copyright (C) 2010 Red Hat, Inc. +# Written by Scott Seago sseago@redhat.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. A copy of the GNU General Public License is +# also available at http://www.gnu.org/copyleft/gpl.html. +module ImageWarehouseObject + + WAREHOUSE_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/image_warehouse.yml") + + def xml + @xml ||= ImageDescriptorXML.new(self[:xml].to_s) + end + + def upload + self.uri = File.join(WAREHOUSE_CONFIG['baseurl'], "#{uuid}") + response = Typhoeus::Request.put(self.uri, :body => xml.to_xml, :timeout => 30000) + if response.code == 200 + update_attribute(:uploaded, true) + else + raise "failed to upload template (code #{response.code}): #{response.body}" + end + end + + def generate_uuid + # TODO: generate real uuid here, e.g. with some ruby uuid generator + self.uuid ||= "#{self.name}-#{Time.now.to_f.to_s}" + end + +end diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index b84a596..68c7174 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -37,9 +37,11 @@ class Instance < ActiveRecord::Base
belongs_to :pool belongs_to :cloud_account + belongs_to :deployment
belongs_to :hardware_profile belongs_to :template + belongs_to :assembly belongs_to :realm belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" belongs_to :instance_hwp @@ -51,7 +53,8 @@ class Instance < ActiveRecord::Base
validates_presence_of :pool_id validates_presence_of :hardware_profile_id - validates_presence_of :template_id + validates_presence_of :template_id, :unless => :deployment_id + validates_presence_of :assembly_id, :if => :deployment_id
#validates_presence_of :external_key # TODO: can we do uniqueness validation on indirect association @@ -79,8 +82,15 @@ class Instance < ActiveRecord::Base validates_inclusion_of :state, :in => STATES
+ def validate + if assembly and template + errors.add(:assembly, "Please specify either template or assembly, but not both") + errors.add(:template, "Please specify either template or assembly, but not both") + end + end + def object_list - super << pool + super + [pool, deployment] end class << self alias orig_list_for_user_include list_for_user_include @@ -89,15 +99,19 @@ class Instance < ActiveRecord::Base
def self.list_for_user_include includes = orig_list_for_user_include - includes << { :pool => {:permissions => {:role => :privileges}}} + includes << { :pool => {:permissions => {:role => :privileges}}, + :deployment => {:permissions => {:role => :privileges}}} includes end
def self.list_for_user_conditions "(#{orig_list_for_user_conditions}) or - (permissions_pools.user_id=:user and + (permissions_deployments.user_id=:user and privileges_roles.target_type=:target_type and - privileges_roles.action=:action)" + privileges_roles.action=:action) or + (permissions_pools.user_id=:user and + privileges_roles_2.target_type=:target_type and + privileges_roles_2.action=:action)" end
def get_action_list(user=nil) diff --git a/src/app/models/permission.rb b/src/app/models/permission.rb index 22b228a..03f75b7 100644 --- a/src/app/models/permission.rb +++ b/src/app/models/permission.rb @@ -35,12 +35,18 @@ class Permission < ActiveRecord::Base :foreign_key => "permission_object_id" belongs_to :instance, :class_name => "Instance", :foreign_key => "permission_object_id" + belongs_to :deployment, :class_name => "Deployment", + :foreign_key => "permission_object_id" belongs_to :provider, :class_name => "Provider", :foreign_key => "permission_object_id" belongs_to :cloud_account, :class_name => "CloudAccount", :foreign_key => "permission_object_id" belongs_to :template, :class_name => "Template", :foreign_key => "permission_object_id" + belongs_to :assembly, :class_name => "Assembly", + :foreign_key => "permission_object_id" + belongs_to :deployable, :class_name => "Deployable", + :foreign_key => "permission_object_id" belongs_to :base_permission_object, :class_name => "BasePermissionObject", :foreign_key => "permission_object_id"
diff --git a/src/app/models/permissioned_object.rb b/src/app/models/permissioned_object.rb index d46ed8f..d2a5878 100644 --- a/src/app/models/permissioned_object.rb +++ b/src/app/models/permissioned_object.rb @@ -22,7 +22,7 @@ module PermissionedObject return false if user.nil? or action.nil? target_type = self.class.default_privilege_target_type if target_type.nil? object_list.each do |obj| - return true if obj.permissions.find(:first, + return true if obj and obj.permissions.find(:first, :include => [:role => :privileges], :conditions => ["permissions.user_id=:user and diff --git a/src/app/models/privilege.rb b/src/app/models/privilege.rb index f7a61ef..f5a5887 100644 --- a/src/app/models/privilege.rb +++ b/src/app/models/privilege.rb @@ -43,6 +43,7 @@ class Privilege < ActiveRecord::Base Pool => ACTIONS - [USE], PoolFamily => ACTIONS - [USE], Instance => ACTIONS, + Deployment => ACTIONS, Quota => [VIEW, MODIFY], HardwareProfile => ACTIONS - [USE, VIEW], Realm => ACTIONS - [VIEW], @@ -99,6 +100,14 @@ class Privilege < ActiveRecord::Base # view_perms Can view permissions # set_perms Can set permissions (or can set instance permissions on this pool) # + # Instance This Deployment or deployments within this Pool + # view Can view + # use Can perform lifecycle actions on and/or view console + # modify Can modify + # create Can create (within this Pool) + # view_perms Can view permissions + # set_perms Can set permissions (or can set instance permissions on this pool) + # # Quota The Pool/CloudAccount/PoolFamily/User assigned the quota # view Can view quota on this obj # modify Can edit quota on this obj diff --git a/src/app/models/template.rb b/src/app/models/template.rb index 4e8ad27..d930294 100644 --- a/src/app/models/template.rb +++ b/src/app/models/template.rb @@ -3,6 +3,7 @@ require 'typhoeus'
class Template < ActiveRecord::Base include PermissionedObject + include ImageWarehouseObject searchable do text :name, :as => :code_substring text :platform, :as => :code_substring @@ -13,6 +14,7 @@ class Template < ActiveRecord::Base
has_many :images, :dependent => :destroy has_many :instances + has_and_belongs_to_many :assemblies before_validation :generate_uuid before_save :update_xml before_destroy :no_instances? @@ -21,8 +23,6 @@ class Template < ActiveRecord::Base :include => [:role], :order => "permissions.id ASC"
- WAREHOUSE_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/image_warehouse.yml") - validates_presence_of :uuid validates_uniqueness_of :uuid validates_presence_of :name @@ -41,25 +41,6 @@ class Template < ActiveRecord::Base true end
- def xml - @xml ||= ImageDescriptorXML.new(self[:xml].to_s) - end - - def upload - self.uri = File.join(WAREHOUSE_CONFIG['baseurl'], "#{uuid}") - response = Typhoeus::Request.put(self.uri, :body => xml.to_xml, :timeout => 30000) - if response.code == 200 - update_attribute(:uploaded, true) - else - raise "failed to upload template (code #{response.code}): #{response.body}" - end - end - - def generate_uuid - # TODO: generate real uuid here, e.g. with some ruby uuid generator - self.uuid ||= "#{self.name}-#{Time.now.to_f.to_s}" - end - def update_xml xml.name = self.name xml.description = self.summary diff --git a/src/db/migrate/20110207100700_create_assemblies.rb b/src/db/migrate/20110207100700_create_assemblies.rb new file mode 100644 index 0000000..7e4be57 --- /dev/null +++ b/src/db/migrate/20110207100700_create_assemblies.rb @@ -0,0 +1,24 @@ +class CreateAssemblies < ActiveRecord::Migration + def self.up + create_table :assemblies do |t| + t.string :uuid, :null => false + t.binary :xml, :null => false + t.string :uri + t.string :name + t.string :architecture + t.text :summary + t.boolean :uploaded, :default => false + t.integer :lock_version, :default => 0 + t.timestamps + end + create_table :assemblies_templates, :id => false do |t| + t.integer :assembly_id, :null => false + t.integer :template_id, :null => false + end + end + + def self.down + drop_table :assemblies_templates + drop_table :assemblies + end +end diff --git a/src/db/migrate/20110207100800_update_deployables.rb b/src/db/migrate/20110207100800_update_deployables.rb new file mode 100644 index 0000000..4414560 --- /dev/null +++ b/src/db/migrate/20110207100800_update_deployables.rb @@ -0,0 +1,24 @@ +class UpdateDeployables < ActiveRecord::Migration + def self.up + change_table :deployables do |t| + t.integer :lock_version, :default => 0 + t.string :uuid, :null => false + t.binary :xml, :null => false + t.string :uri + t.text :summary + t.boolean :uploaded, :default => false + end + + create_table :assemblies_deployables, :id => false do |t| + t.integer :assembly_id, :null => false + t.integer :deployable_id, :null => false + end + end + + def self.down + drop_table :assemblies_deployables + change_table :deployables do |t| + t.remove :lock_version, :uuid, :xml, :uri, :summary, :uploaded + end + end +end diff --git a/src/db/migrate/20110207100900_create_deployments.rb b/src/db/migrate/20110207100900_create_deployments.rb new file mode 100644 index 0000000..d026f7b --- /dev/null +++ b/src/db/migrate/20110207100900_create_deployments.rb @@ -0,0 +1,17 @@ +class CreateDeployments < ActiveRecord::Migration + def self.up + create_table :deployments do |t| + t.string :name, :null => false, :limit => 1024 + t.integer :realm_id + t.integer :owner_id + t.integer :pool_id, :null => false + t.integer :deployable_id, :null => false + t.integer :lock_version, :default => 0 + t.timestamps + end + end + + def self.down + drop_table :deployments + end +end diff --git a/src/db/migrate/20110207101000_update_instances.rb b/src/db/migrate/20110207101000_update_instances.rb new file mode 100644 index 0000000..4b758f7 --- /dev/null +++ b/src/db/migrate/20110207101000_update_instances.rb @@ -0,0 +1,21 @@ +class UpdateInstances < ActiveRecord::Migration + def self.up + change_table :instances do |t| + t.integer :assembly_id + t.integer :deployment_id + t.change :template_id, :integer, :null => true + end + + create_table :assemblies_instances, :id => false do |t| + t.integer :assembly_id, :null => false + t.integer :deployable_id, :null => false + end + end + + def self.down + change_table :instances do |t| + t.remove :assembly_id, :deployment_id + t.change :template_id, :integer, :null => false + end + end +end diff --git a/src/db/migrate/20110207101100_deployment_roles.rb b/src/db/migrate/20110207101100_deployment_roles.rb new file mode 100644 index 0000000..b63413a --- /dev/null +++ b/src/db/migrate/20110207101100_deployment_roles.rb @@ -0,0 +1,65 @@ +class DeploymentRoles < ActiveRecord::Migration + VIEW = "view" + USE = "use" + MOD = "modify" + CRE = "create" + VPRM = "view_perms" + GPRM = "set_perms" + NEW_ROLES = { + Deployment => + {"Deployment Controller" => [false, {Deployment => [VIEW,USE], + Instance => [VIEW]}], + "Deployment Owner" => [true, {Deployment => [VIEW,USE,MOD, VPRM,GPRM], + Instance => [VIEW,USE,MOD]}]}, + Pool => + {"Pool User" => [false, {Pool => [VIEW], + Instance => [ CRE], + Deployment => [ CRE], + Quota => [VIEW]}], + "Pool Owner" => [true, {Pool => [VIEW, MOD, VPRM,GPRM], + Instance => [VIEW,USE,MOD,CRE], + Deployment => [VIEW,USE,MOD,CRE], + Quota => [VIEW]}]}, + BasePermissionObject => + {"Pool Administrator" => [false, {Pool => [VIEW, MOD,CRE,VPRM,GPRM], + Instance => [VIEW,USE,MOD,CRE,VPRM,GPRM], + Deployment => [VIEW,USE,MOD,CRE,VPRM,GPRM], + Quota => [VIEW, MOD], + PoolFamily => [VIEW, MOD,CRE,VPRM,GPRM]}], + "Administrator" => [false, {Provider => [VIEW, MOD,CRE,VPRM,GPRM], + CloudAccount => [VIEW,USE,MOD,CRE,VPRM,GPRM], + HardwareProfile => [ MOD,CRE,VPRM,GPRM], + Realm => [ USE,MOD,CRE,VPRM,GPRM], + User => [VIEW, MOD,CRE], + Pool => [VIEW, MOD,CRE,VPRM,GPRM], + Instance => [VIEW,USE,MOD,CRE,VPRM,GPRM], + Deployment => [VIEW,USE,MOD,CRE,VPRM,GPRM], + Quota => [VIEW, MOD], + PoolFamily => [VIEW, MOD,CRE,VPRM,GPRM], + Template => [VIEW,USE,MOD,CRE,VPRM,GPRM], + BasePermissionObject => [ MOD, VPRM,GPRM]}]}} + def self.up + unless Role.all.size == 0 + Role.transaction do + NEW_ROLES.each do |role_scope, scoped_hash| + scoped_hash.each do |role_name, role_def| + role = Role.find_or_initialize_by_name(role_name) + role.update_attributes({:name => role_name, :scope => role_scope.name, + :assign_to_owner => role_def[0]}) + role.privileges = {} + role.save! + role_def[1].each do |priv_type, priv_actions| + priv_actions.each do |action| + Privilege.create!(:role => role, :target_type => priv_type.name, + :action => action) + end + end + end + end + end + end + end + + def self.down + end +end diff --git a/src/db/seeds.rb b/src/db/seeds.rb index 71726bf..d0b6477 100644 --- a/src/db/seeds.rb +++ b/src/db/seeds.rb @@ -17,6 +17,11 @@ roles = {Instance => {"Instance Controller" => [false, {Instance => [VIEW,USE]}], "Instance Owner" => [true, {Instance => [VIEW,USE,MOD, VPRM,GPRM]}]}, + Deployment => + {"Deployment Controller" => [false, {Deployment => [VIEW,USE], + Instance => [VIEW]}], + "Deployment Owner" => [true, {Deployment => [VIEW,USE,MOD, VPRM,GPRM], + Instance => [VIEW,USE,MOD]}]}, PoolFamily => {"Pool Family User" => [false, {Pool => [VIEW]}], "Pool Family Owner" => [true, {PoolFamily => [VIEW, MOD, VPRM,GPRM], @@ -24,9 +29,11 @@ roles = Pool => {"Pool User" => [false, {Pool => [VIEW], Instance => [ CRE], + Deployment => [ CRE], Quota => [VIEW]}], "Pool Owner" => [true, {Pool => [VIEW, MOD, VPRM,GPRM], Instance => [VIEW,USE,MOD,CRE], + Deployment => [VIEW,USE,MOD,CRE], Quota => [VIEW]}]}, Provider => {"Provider Owner" => [true, {Provider => [VIEW, MOD, VPRM,GPRM], @@ -46,6 +53,7 @@ roles = "Pool Creator" => [false, {Pool => [ CRE]}], "Pool Administrator" => [false, {Pool => [VIEW, MOD,CRE,VPRM,GPRM], Instance => [VIEW,USE,MOD,CRE,VPRM,GPRM], + Deployment => [VIEW,USE,MOD,CRE,VPRM,GPRM], Quota => [VIEW, MOD], PoolFamily => [VIEW, MOD,CRE,VPRM,GPRM]}], "Template Administrator" => [false, {Template => [VIEW,USE,MOD,CRE,VPRM,GPRM]}], @@ -56,6 +64,7 @@ roles = User => [VIEW, MOD,CRE], Pool => [VIEW, MOD,CRE,VPRM,GPRM], Instance => [VIEW,USE,MOD,CRE,VPRM,GPRM], + Deployment => [VIEW,USE,MOD,CRE,VPRM,GPRM], Quota => [VIEW, MOD], PoolFamily => [VIEW, MOD,CRE,VPRM,GPRM], Template => [VIEW,USE,MOD,CRE,VPRM,GPRM], @@ -63,11 +72,11 @@ roles = Role.transaction do roles.each do |role_scope, scoped_hash| scoped_hash.each do |role_name, role_def| + role = Role.find_or_initialize_by_name(role_name) + role.update_attributes({:name => role_name, :scope => role_scope.name, + :assign_to_owner => role_def[0]}) + role.save! role_def[1].each do |priv_type, priv_actions| - role = Role.find_or_initialize_by_name(role_name) - role.update_attributes({:name => role_name, :scope => role_scope.name, - :assign_to_owner => role_def[0]}) - role.save! priv_actions.each do |action| Privilege.create!(:role => role, :target_type => priv_type.name, :action => action) diff --git a/src/spec/factories/assembly.rb b/src/spec/factories/assembly.rb new file mode 100644 index 0000000..af290dc --- /dev/null +++ b/src/spec/factories/assembly.rb @@ -0,0 +1,5 @@ +Factory.define :assembly do |a| + a.sequence(:name) { |n| "assembly#{n}" } + a.architecture 'x86_64' + a.templates { |t| [t.association(:template)] } +end diff --git a/src/spec/factories/deployable.rb b/src/spec/factories/deployable.rb new file mode 100644 index 0000000..60b160b --- /dev/null +++ b/src/spec/factories/deployable.rb @@ -0,0 +1,4 @@ +Factory.define :deployable do |a| + a.sequence(:name) { |n| "deployable#{n}" } + a.assemblies { |t| [t.association(:assembly)] } +end diff --git a/src/spec/factories/deployment.rb b/src/spec/factories/deployment.rb new file mode 100644 index 0000000..f3c0522 --- /dev/null +++ b/src/spec/factories/deployment.rb @@ -0,0 +1,6 @@ +Factory.define :deployment do |d| + d.sequence(:name) { |n| "deployment#{n}" } + d.association :deployable, :factory => :deployable + d.association :pool, :factory => :pool + d.association :owner, :factory => :user +end diff --git a/src/spec/models/assembly_spec.rb b/src/spec/models/assembly_spec.rb new file mode 100644 index 0000000..2693116 --- /dev/null +++ b/src/spec/models/assembly_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe Assembly do + + it "should have automatically generated uuid after validation" do + a = Factory.build(:assembly) + a.uuid = nil + a.save + a.uuid.should_not be_nil + end + + it "should not be valid if assembly name is too long" do + a = Factory.build(:assembly) + a.name = ('a' * 256) + a.valid?.should be_false + a.errors[:name].should_not be_nil + a.errors[:name].should =~ /^is too long.*/ + end + + it "should have associated template" do + a = Factory.build(:assembly) + a.templates.size.should eql(1) + end + +end diff --git a/src/spec/models/deployable_spec.rb b/src/spec/models/deployable_spec.rb new file mode 100644 index 0000000..af1fc9f --- /dev/null +++ b/src/spec/models/deployable_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe Deployable do + + it "should have automatically generated uuid after validation" do + d = Factory.build(:deployable) + d.uuid = nil + d.save + d.uuid.should_not be_nil + end + + it "should not be valid if deployable name is too long" do + d = Factory.build(:deployable) + d.name = ('a' * 256) + d.valid?.should be_false + d.errors[:name].should_not be_nil + d.errors[:name].should =~ /^is too long.*/ + end + + it "should have associated assembly" do + d = Factory.build(:deployable) + d.assemblies.size.should eql(1) + end + +end diff --git a/src/spec/models/deployment_spec.rb b/src/spec/models/deployment_spec.rb new file mode 100644 index 0000000..c8eda13 --- /dev/null +++ b/src/spec/models/deployment_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' + +describe Deployment do + before(:each) do + @quota = Factory :quota + @pool = Factory(:pool, :quota_id => @quota.id) + @deployment = Factory.build(:deployment, :pool_id => @pool.id) + @actions = ['start', 'stop'] + end + + it "should require pool to be set" do + @deployment.pool_id = nil + @deployment.should_not be_valid + + @deployment.pool_id = 1 + @deployment.should be_valid + end + + it "should require deployable to be set" do + @deployment.deployable_id = nil + @deployment.should_not be_valid + + @deployment.deployable_id = 1 + @deployment.should be_valid + end + + it "should have a name of reasonable length" do + [nil, '', 'x'*1025].each do |invalid_name| + @deployment.name = invalid_name + @deployment.should_not be_valid + end + @deployment.name = 'x'*1024 + @deployment.should be_valid + + end + + it "should have unique name" do + @deployment.save! + second_deployment = Factory.build(:deployment, + :pool_id => @deployment.pool_id, + :name => @deployment.name) + second_deployment.should_not be_valid + + second_deployment.name = 'unique name' + second_deployment.should be_valid + end + + it "should tell apart valid and invalid actions" do + @deployment.stub!(:get_action_list).and_return(@actions) + @deployment.valid_action?('invalid action').should == false + @deployment.valid_action?('start').should == true + end + + it "should return action list" do + @deployment.get_action_list.should eql(["start", "stop", "reboot"]) + end + + +end diff --git a/src/spec/models/instance_spec.rb b/src/spec/models/instance_spec.rb index 625718d..787c0c5 100644 --- a/src/spec/models/instance_spec.rb +++ b/src/spec/models/instance_spec.rb @@ -24,14 +24,25 @@ describe Instance do @instance.should be_valid end
- it "should require template to be set" do + it "should require template to be set if there no deployment" do @instance.template_id = nil + @instance.deployment_id = nil @instance.should_not be_valid
@instance.template_id = 1 @instance.should be_valid end
+ it "should not allow template to be set if there's a deployment" do + @instance.deployment_id = 1 + @instance.template_id = 1 + @instance.should_not be_valid + + @instance.template_id = nil + @instance.assembly_id = 1 + @instance.should be_valid + end + it "should have a name of reasonable length" do [nil, '', 'x'*1025].each do |invalid_name| @instance.name = invalid_name
ACK
On 02/10/2011 04:20 PM, Scott Seago wrote:
This includes models and model rspec tests for Assemblies, Deployments, and Deployables. Associated role/privilege additions needed for these types are also included.
Signed-off-by: Scott Seagosseago@redhat.com
src/app/models/assembly.rb | 67 ++++++++++++++++ src/app/models/deployable.rb | 61 ++++++++++++++ src/app/models/deployment.rb | 84 ++++++++++++++++++++ src/app/models/image_warehouse_object.rb | 42 ++++++++++ src/app/models/instance.rb | 24 +++++- src/app/models/permission.rb | 6 ++ src/app/models/permissioned_object.rb | 2 +- src/app/models/privilege.rb | 9 ++ src/app/models/template.rb | 23 +----- src/db/migrate/20110207100700_create_assemblies.rb | 24 ++++++ .../migrate/20110207100800_update_deployables.rb | 24 ++++++ .../migrate/20110207100900_create_deployments.rb | 17 ++++ src/db/migrate/20110207101000_update_instances.rb | 21 +++++ src/db/migrate/20110207101100_deployment_roles.rb | 65 +++++++++++++++ src/db/seeds.rb | 17 +++- src/spec/factories/assembly.rb | 5 + src/spec/factories/deployable.rb | 4 + src/spec/factories/deployment.rb | 6 ++ src/spec/models/assembly_spec.rb | 25 ++++++ src/spec/models/deployable_spec.rb | 25 ++++++ src/spec/models/deployment_spec.rb | 59 ++++++++++++++ src/spec/models/instance_spec.rb | 13 +++- 22 files changed, 591 insertions(+), 32 deletions(-) create mode 100644 src/app/models/assembly.rb create mode 100644 src/app/models/deployment.rb create mode 100644 src/app/models/image_warehouse_object.rb create mode 100644 src/db/migrate/20110207100700_create_assemblies.rb create mode 100644 src/db/migrate/20110207100800_update_deployables.rb create mode 100644 src/db/migrate/20110207100900_create_deployments.rb create mode 100644 src/db/migrate/20110207101000_update_instances.rb create mode 100644 src/db/migrate/20110207101100_deployment_roles.rb create mode 100644 src/spec/factories/assembly.rb create mode 100644 src/spec/factories/deployable.rb create mode 100644 src/spec/factories/deployment.rb create mode 100644 src/spec/models/assembly_spec.rb create mode 100644 src/spec/models/deployable_spec.rb create mode 100644 src/spec/models/deployment_spec.rb
diff --git a/src/app/models/assembly.rb b/src/app/models/assembly.rb new file mode 100644 index 0000000..5a47525 --- /dev/null +++ b/src/app/models/assembly.rb @@ -0,0 +1,67 @@ +# +# Copyright (C) 2011 Red Hat, Inc. +# Written by Scott Seagosseago@redhat.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. A copy of the GNU General Public License is +# also available at http://www.gnu.org/copyleft/gpl.html.
+require 'sunspot_rails' +class Assembly< ActiveRecord::Base
- include PermissionedObject
- include ImageWarehouseObject
- searchable do
- text :name, :as => :code_substring
- text :architecture, :as => :code_substring
- text :summary, :as => :code_substring
- end
- has_and_belongs_to_many :templates
- has_and_belongs_to_many :deployables
- has_many :instances
- has_many :permissions, :as => :permission_object, :dependent => :destroy,
:include => [:role],
:order => "permissions.id ASC"
- before_validation :generate_uuid
- before_save :update_xml
- has_many :permissions, :as => :permission_object, :dependent => :destroy,
:include => [:role],
:order => "permissions.id ASC"
- validates_presence_of :uuid
- validates_uniqueness_of :uuid
- validates_presence_of :name
- validates_uniqueness_of :name
- validates_length_of :name, :maximum => 255
- validates_presence_of :architecture
- def self.default_privilege_target_type
- Template
- end
- def update_xml
- xml.name = self.name
- xml.description = self.summary
- xml.architecture = self.architecture
- write_attribute(:xml, xml.to_xml)
- end
- def self.find_or_create(id)
- id ? Assembly.find(id) : Assembly.new
- end
+end diff --git a/src/app/models/deployable.rb b/src/app/models/deployable.rb index f4891d8..9ed15ef 100644 --- a/src/app/models/deployable.rb +++ b/src/app/models/deployable.rb @@ -1,2 +1,63 @@ +# +# Copyright (C) 2011 Red Hat, Inc. +# Written by Scott Seagosseago@redhat.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. A copy of the GNU General Public License is +# also available at http://www.gnu.org/copyleft/gpl.html.
+require 'sunspot_rails' class Deployable< ActiveRecord::Base
- include PermissionedObject
- include ImageWarehouseObject
- searchable do
- text :name, :as => :code_substring
- text :summary, :as => :code_substring
- end
- has_and_belongs_to_many :assemblies
- has_many :deployments
- has_many :permissions, :as => :permission_object, :dependent => :destroy,
:include => [:role],
:order => "permissions.id ASC"
- before_validation :generate_uuid
- before_save :update_xml
- has_many :permissions, :as => :permission_object, :dependent => :destroy,
:include => [:role],
:order => "permissions.id ASC"
- validates_presence_of :uuid
- validates_uniqueness_of :uuid
- validates_presence_of :name
- validates_uniqueness_of :name
- validates_length_of :name, :maximum => 255
- def self.default_privilege_target_type
- Template
- end
- def update_xml
- xml.name = self.name
- xml.description = self.summary
- write_attribute(:xml, xml.to_xml)
- end
- def self.find_or_create(id)
- id ? Deployable.find(id) : Deployable.new
- end
- end
diff --git a/src/app/models/deployment.rb b/src/app/models/deployment.rb new file mode 100644 index 0000000..1b41871 --- /dev/null +++ b/src/app/models/deployment.rb @@ -0,0 +1,84 @@ +# +# Copyright (C) 2011 Red Hat, Inc. +# Written by Scott Seagosseago@redhat.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. A copy of the GNU General Public License is +# also available at http://www.gnu.org/copyleft/gpl.html.
+require 'sunspot_rails' +class Deployment< ActiveRecord::Base
- include SearchFilter
- include PermissionedObject
- searchable do
- text :name, :as => :code_substring
- end
- belongs_to :pool
- belongs_to :deployable
- has_many :instances
- belongs_to :realm
- belongs_to :owner, :class_name => "User", :foreign_key => "owner_id"
- has_many :permissions, :as => :permission_object, :dependent => :destroy,
:include => [:role],
:order => "permissions.id ASC"
- validates_presence_of :pool_id
- validates_presence_of :deployable_id
- validates_presence_of :name
- validates_uniqueness_of :name, :scope => :pool_id
- validates_length_of :name, :maximum => 1024
- SEARCHABLE_COLUMNS = %w(name)
- def object_list
- super<< pool
- end
- class<< self
- alias orig_list_for_user_include list_for_user_include
- alias orig_list_for_user_conditions list_for_user_conditions
- end
- def self.list_for_user_include
- includes = orig_list_for_user_include
- includes<< { :pool => {:permissions => {:role => :privileges}}}
- includes
- end
- def self.list_for_user_conditions
- "(#{orig_list_for_user_conditions}) or
(permissions_pools.user_id=:user and
privileges_roles.target_type=:target_type and
privileges_roles.action=:action)"
- end
- def get_action_list(user=nil)
- # FIXME: how do actions and states interact for deployments?
- # For instances the list comes from the provider based on current state.
- # Deployments don't currently have an explicit state field, but
- # something could be calculated from associated instances.
- ["start", "stop", "reboot"]
- end
- def valid_action?(action)
- return get_action_list.include?(action) ? true : false
- end
+end diff --git a/src/app/models/image_warehouse_object.rb b/src/app/models/image_warehouse_object.rb new file mode 100644 index 0000000..48dd04f --- /dev/null +++ b/src/app/models/image_warehouse_object.rb @@ -0,0 +1,42 @@ +# +# Copyright (C) 2010 Red Hat, Inc. +# Written by Scott Seagosseago@redhat.com +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. A copy of the GNU General Public License is +# also available at http://www.gnu.org/copyleft/gpl.html. +module ImageWarehouseObject
- WAREHOUSE_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/image_warehouse.yml")
- def xml
- @xml ||= ImageDescriptorXML.new(self[:xml].to_s)
- end
- def upload
- self.uri = File.join(WAREHOUSE_CONFIG['baseurl'], "#{uuid}")
- response = Typhoeus::Request.put(self.uri, :body => xml.to_xml, :timeout => 30000)
- if response.code == 200
update_attribute(:uploaded, true)
- else
raise "failed to upload template (code #{response.code}): #{response.body}"
- end
- end
- def generate_uuid
- # TODO: generate real uuid here, e.g. with some ruby uuid generator
- self.uuid ||= "#{self.name}-#{Time.now.to_f.to_s}"
- end
+end diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb index b84a596..68c7174 100644 --- a/src/app/models/instance.rb +++ b/src/app/models/instance.rb @@ -37,9 +37,11 @@ class Instance< ActiveRecord::Base
belongs_to :pool belongs_to :cloud_account
belongs_to :deployment
belongs_to :hardware_profile belongs_to :template
belongs_to :assembly belongs_to :realm belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" belongs_to :instance_hwp
@@ -51,7 +53,8 @@ class Instance< ActiveRecord::Base
validates_presence_of :pool_id validates_presence_of :hardware_profile_id
- validates_presence_of :template_id
validates_presence_of :template_id, :unless => :deployment_id
validates_presence_of :assembly_id, :if => :deployment_id
#validates_presence_of :external_key # TODO: can we do uniqueness validation on indirect association
@@ -79,8 +82,15 @@ class Instance< ActiveRecord::Base validates_inclusion_of :state, :in => STATES
- def validate
- if assembly and template
errors.add(:assembly, "Please specify either template or assembly, but not both")
errors.add(:template, "Please specify either template or assembly, but not both")
- end
- end
- def object_list
- super<< pool
- super + [pool, deployment] end class<< self alias orig_list_for_user_include list_for_user_include
@@ -89,15 +99,19 @@ class Instance< ActiveRecord::Base
def self.list_for_user_include includes = orig_list_for_user_include
- includes<< { :pool => {:permissions => {:role => :privileges}}}
includes<< { :pool => {:permissions => {:role => :privileges}},
:deployment => {:permissions => {:role => :privileges}}} includes
end
def self.list_for_user_conditions "(#{orig_list_for_user_conditions}) or
(permissions_pools.user_id=:user and
(permissions_deployments.user_id=:user and privileges_roles.target_type=:target_type and
privileges_roles.action=:action)"
privileges_roles.action=:action) or
(permissions_pools.user_id=:user and
privileges_roles_2.target_type=:target_type and
privileges_roles_2.action=:action)"
end
def get_action_list(user=nil)
diff --git a/src/app/models/permission.rb b/src/app/models/permission.rb index 22b228a..03f75b7 100644 --- a/src/app/models/permission.rb +++ b/src/app/models/permission.rb @@ -35,12 +35,18 @@ class Permission< ActiveRecord::Base :foreign_key => "permission_object_id" belongs_to :instance, :class_name => "Instance", :foreign_key => "permission_object_id"
- belongs_to :deployment, :class_name => "Deployment",
belongs_to :provider, :class_name => "Provider", :foreign_key => "permission_object_id" belongs_to :cloud_account, :class_name => "CloudAccount", :foreign_key => "permission_object_id" belongs_to :template, :class_name => "Template", :foreign_key => "permission_object_id":foreign_key => "permission_object_id"
- belongs_to :assembly, :class_name => "Assembly",
:foreign_key => "permission_object_id"
- belongs_to :deployable, :class_name => "Deployable",
belongs_to :base_permission_object, :class_name => "BasePermissionObject", :foreign_key => "permission_object_id":foreign_key => "permission_object_id"
diff --git a/src/app/models/permissioned_object.rb b/src/app/models/permissioned_object.rb index d46ed8f..d2a5878 100644 --- a/src/app/models/permissioned_object.rb +++ b/src/app/models/permissioned_object.rb @@ -22,7 +22,7 @@ module PermissionedObject return false if user.nil? or action.nil? target_type = self.class.default_privilege_target_type if target_type.nil? object_list.each do |obj|
return true if obj.permissions.find(:first,
return true if obj and obj.permissions.find(:first, :include => [:role => :privileges], :conditions => ["permissions.user_id=:user and
diff --git a/src/app/models/privilege.rb b/src/app/models/privilege.rb index f7a61ef..f5a5887 100644 --- a/src/app/models/privilege.rb +++ b/src/app/models/privilege.rb @@ -43,6 +43,7 @@ class Privilege< ActiveRecord::Base Pool => ACTIONS - [USE], PoolFamily => ACTIONS - [USE], Instance => ACTIONS,
Deployment => ACTIONS, Quota => [VIEW, MODIFY], HardwareProfile => ACTIONS - [USE, VIEW], Realm => ACTIONS - [VIEW],
@@ -99,6 +100,14 @@ class Privilege< ActiveRecord::Base # view_perms Can view permissions # set_perms Can set permissions (or can set instance permissions on this pool) #
- # Instance This Deployment or deployments within this Pool
- # view Can view
- # use Can perform lifecycle actions on and/or view console
- # modify Can modify
- # create Can create (within this Pool)
- # view_perms Can view permissions
- # set_perms Can set permissions (or can set instance permissions on this pool)
- # # Quota The Pool/CloudAccount/PoolFamily/User assigned the quota # view Can view quota on this obj # modify Can edit quota on this obj
diff --git a/src/app/models/template.rb b/src/app/models/template.rb index 4e8ad27..d930294 100644 --- a/src/app/models/template.rb +++ b/src/app/models/template.rb @@ -3,6 +3,7 @@ require 'typhoeus'
class Template< ActiveRecord::Base include PermissionedObject
- include ImageWarehouseObject searchable do text :name, :as => :code_substring text :platform, :as => :code_substring
@@ -13,6 +14,7 @@ class Template< ActiveRecord::Base
has_many :images, :dependent => :destroy has_many :instances
- has_and_belongs_to_many :assemblies before_validation :generate_uuid before_save :update_xml before_destroy :no_instances?
@@ -21,8 +23,6 @@ class Template< ActiveRecord::Base :include => [:role], :order => "permissions.id ASC"
- WAREHOUSE_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/image_warehouse.yml")
- validates_presence_of :uuid validates_uniqueness_of :uuid validates_presence_of :name
@@ -41,25 +41,6 @@ class Template< ActiveRecord::Base true end
- def xml
- @xml ||= ImageDescriptorXML.new(self[:xml].to_s)
- end
- def upload
- self.uri = File.join(WAREHOUSE_CONFIG['baseurl'], "#{uuid}")
- response = Typhoeus::Request.put(self.uri, :body => xml.to_xml, :timeout => 30000)
- if response.code == 200
update_attribute(:uploaded, true)
- else
raise "failed to upload template (code #{response.code}): #{response.body}"
- end
- end
- def generate_uuid
- # TODO: generate real uuid here, e.g. with some ruby uuid generator
- self.uuid ||= "#{self.name}-#{Time.now.to_f.to_s}"
- end
- def update_xml xml.name = self.name xml.description = self.summary
diff --git a/src/db/migrate/20110207100700_create_assemblies.rb b/src/db/migrate/20110207100700_create_assemblies.rb new file mode 100644 index 0000000..7e4be57 --- /dev/null +++ b/src/db/migrate/20110207100700_create_assemblies.rb @@ -0,0 +1,24 @@ +class CreateAssemblies< ActiveRecord::Migration
- def self.up
- create_table :assemblies do |t|
t.string :uuid, :null => false
t.binary :xml, :null => false
t.string :uri
t.string :name
t.string :architecture
t.text :summary
t.boolean :uploaded, :default => false
t.integer :lock_version, :default => 0
t.timestamps
- end
- create_table :assemblies_templates, :id => false do |t|
t.integer :assembly_id, :null => false
t.integer :template_id, :null => false
- end
- end
- def self.down
- drop_table :assemblies_templates
- drop_table :assemblies
- end
+end diff --git a/src/db/migrate/20110207100800_update_deployables.rb b/src/db/migrate/20110207100800_update_deployables.rb new file mode 100644 index 0000000..4414560 --- /dev/null +++ b/src/db/migrate/20110207100800_update_deployables.rb @@ -0,0 +1,24 @@ +class UpdateDeployables< ActiveRecord::Migration
- def self.up
- change_table :deployables do |t|
t.integer :lock_version, :default => 0
t.string :uuid, :null => false
t.binary :xml, :null => false
t.string :uri
t.text :summary
t.boolean :uploaded, :default => false
- end
- create_table :assemblies_deployables, :id => false do |t|
t.integer :assembly_id, :null => false
t.integer :deployable_id, :null => false
- end
- end
- def self.down
- drop_table :assemblies_deployables
- change_table :deployables do |t|
t.remove :lock_version, :uuid, :xml, :uri, :summary, :uploaded
- end
- end
+end diff --git a/src/db/migrate/20110207100900_create_deployments.rb b/src/db/migrate/20110207100900_create_deployments.rb new file mode 100644 index 0000000..d026f7b --- /dev/null +++ b/src/db/migrate/20110207100900_create_deployments.rb @@ -0,0 +1,17 @@ +class CreateDeployments< ActiveRecord::Migration
- def self.up
- create_table :deployments do |t|
t.string :name, :null => false, :limit => 1024
t.integer :realm_id
t.integer :owner_id
t.integer :pool_id, :null => false
t.integer :deployable_id, :null => false
t.integer :lock_version, :default => 0
t.timestamps
- end
- end
- def self.down
- drop_table :deployments
- end
+end diff --git a/src/db/migrate/20110207101000_update_instances.rb b/src/db/migrate/20110207101000_update_instances.rb new file mode 100644 index 0000000..4b758f7 --- /dev/null +++ b/src/db/migrate/20110207101000_update_instances.rb @@ -0,0 +1,21 @@ +class UpdateInstances< ActiveRecord::Migration
- def self.up
- change_table :instances do |t|
t.integer :assembly_id
t.integer :deployment_id
t.change :template_id, :integer, :null => true
- end
- create_table :assemblies_instances, :id => false do |t|
t.integer :assembly_id, :null => false
t.integer :deployable_id, :null => false
- end
- end
- def self.down
- change_table :instances do |t|
t.remove :assembly_id, :deployment_id
t.change :template_id, :integer, :null => false
- end
- end
+end diff --git a/src/db/migrate/20110207101100_deployment_roles.rb b/src/db/migrate/20110207101100_deployment_roles.rb new file mode 100644 index 0000000..b63413a --- /dev/null +++ b/src/db/migrate/20110207101100_deployment_roles.rb @@ -0,0 +1,65 @@ +class DeploymentRoles< ActiveRecord::Migration
- VIEW = "view"
- USE = "use"
- MOD = "modify"
- CRE = "create"
- VPRM = "view_perms"
- GPRM = "set_perms"
- NEW_ROLES = {
- Deployment =>
{"Deployment Controller" => [false, {Deployment => [VIEW,USE],
Instance => [VIEW]}],
"Deployment Owner" => [true, {Deployment => [VIEW,USE,MOD, VPRM,GPRM],
Instance => [VIEW,USE,MOD]}]},
- Pool =>
{"Pool User" => [false, {Pool => [VIEW],
Instance => [ CRE],
Deployment => [ CRE],
Quota => [VIEW]}],
"Pool Owner" => [true, {Pool => [VIEW, MOD, VPRM,GPRM],
Instance => [VIEW,USE,MOD,CRE],
Deployment => [VIEW,USE,MOD,CRE],
Quota => [VIEW]}]},
- BasePermissionObject =>
- {"Pool Administrator" => [false, {Pool => [VIEW, MOD,CRE,VPRM,GPRM],
Instance => [VIEW,USE,MOD,CRE,VPRM,GPRM],
Deployment => [VIEW,USE,MOD,CRE,VPRM,GPRM],
Quota => [VIEW, MOD],
PoolFamily => [VIEW, MOD,CRE,VPRM,GPRM]}],
"Administrator" => [false, {Provider => [VIEW, MOD,CRE,VPRM,GPRM],
CloudAccount => [VIEW,USE,MOD,CRE,VPRM,GPRM],
HardwareProfile => [ MOD,CRE,VPRM,GPRM],
Realm => [ USE,MOD,CRE,VPRM,GPRM],
User => [VIEW, MOD,CRE],
Pool => [VIEW, MOD,CRE,VPRM,GPRM],
Instance => [VIEW,USE,MOD,CRE,VPRM,GPRM],
Deployment => [VIEW,USE,MOD,CRE,VPRM,GPRM],
Quota => [VIEW, MOD],
PoolFamily => [VIEW, MOD,CRE,VPRM,GPRM],
Template => [VIEW,USE,MOD,CRE,VPRM,GPRM],
BasePermissionObject => [ MOD, VPRM,GPRM]}]}}
- def self.up
- unless Role.all.size == 0
Role.transaction do
NEW_ROLES.each do |role_scope, scoped_hash|
scoped_hash.each do |role_name, role_def|
role = Role.find_or_initialize_by_name(role_name)
role.update_attributes({:name => role_name, :scope => role_scope.name,
:assign_to_owner => role_def[0]})
role.privileges = {}
role.save!
role_def[1].each do |priv_type, priv_actions|
priv_actions.each do |action|
Privilege.create!(:role => role, :target_type => priv_type.name,
:action => action)
end
end
end
end
end
- end
- end
- def self.down
- end
+end diff --git a/src/db/seeds.rb b/src/db/seeds.rb index 71726bf..d0b6477 100644 --- a/src/db/seeds.rb +++ b/src/db/seeds.rb @@ -17,6 +17,11 @@ roles = {Instance => {"Instance Controller" => [false, {Instance => [VIEW,USE]}], "Instance Owner" => [true, {Instance => [VIEW,USE,MOD, VPRM,GPRM]}]},
- Deployment =>
{"Deployment Controller" => [false, {Deployment => [VIEW,USE],
Instance => [VIEW]}],
"Deployment Owner" => [true, {Deployment => [VIEW,USE,MOD, VPRM,GPRM],
PoolFamily => {"Pool Family User" => [false, {Pool => [VIEW]}], "Pool Family Owner" => [true, {PoolFamily => [VIEW, MOD, VPRM,GPRM],Instance => [VIEW,USE,MOD]}]},
@@ -24,9 +29,11 @@ roles = Pool => {"Pool User" => [false, {Pool => [VIEW], Instance => [ CRE],
Deployment => [ CRE], Quota => [VIEW]}], "Pool Owner" => [true, {Pool => [VIEW, MOD, VPRM,GPRM], Instance => [VIEW,USE,MOD,CRE],
Provider => {"Provider Owner" => [true, {Provider => [VIEW, MOD, VPRM,GPRM],Deployment => [VIEW,USE,MOD,CRE], Quota => [VIEW]}]},
@@ -46,6 +53,7 @@ roles = "Pool Creator" => [false, {Pool => [ CRE]}], "Pool Administrator" => [false, {Pool => [VIEW, MOD,CRE,VPRM,GPRM], Instance => [VIEW,USE,MOD,CRE,VPRM,GPRM],
Deployment => [VIEW,USE,MOD,CRE,VPRM,GPRM], Quota => [VIEW, MOD], PoolFamily => [VIEW, MOD,CRE,VPRM,GPRM]}], "Template Administrator" => [false, {Template => [VIEW,USE,MOD,CRE,VPRM,GPRM]}],
@@ -56,6 +64,7 @@ roles = User => [VIEW, MOD,CRE], Pool => [VIEW, MOD,CRE,VPRM,GPRM], Instance => [VIEW,USE,MOD,CRE,VPRM,GPRM],
Deployment => [VIEW,USE,MOD,CRE,VPRM,GPRM], Quota => [VIEW, MOD], PoolFamily => [VIEW, MOD,CRE,VPRM,GPRM], Template => [VIEW,USE,MOD,CRE,VPRM,GPRM],
@@ -63,11 +72,11 @@ roles = Role.transaction do roles.each do |role_scope, scoped_hash| scoped_hash.each do |role_name, role_def|
role = Role.find_or_initialize_by_name(role_name)
role.update_attributes({:name => role_name, :scope => role_scope.name,
:assign_to_owner => role_def[0]})
role.save! role_def[1].each do |priv_type, priv_actions|
role = Role.find_or_initialize_by_name(role_name)
role.update_attributes({:name => role_name, :scope => role_scope.name,
:assign_to_owner => role_def[0]})
role.save! priv_actions.each do |action| Privilege.create!(:role => role, :target_type => priv_type.name, :action => action)
diff --git a/src/spec/factories/assembly.rb b/src/spec/factories/assembly.rb new file mode 100644 index 0000000..af290dc --- /dev/null +++ b/src/spec/factories/assembly.rb @@ -0,0 +1,5 @@ +Factory.define :assembly do |a|
- a.sequence(:name) { |n| "assembly#{n}" }
- a.architecture 'x86_64'
- a.templates { |t| [t.association(:template)] }
+end diff --git a/src/spec/factories/deployable.rb b/src/spec/factories/deployable.rb new file mode 100644 index 0000000..60b160b --- /dev/null +++ b/src/spec/factories/deployable.rb @@ -0,0 +1,4 @@ +Factory.define :deployable do |a|
- a.sequence(:name) { |n| "deployable#{n}" }
- a.assemblies { |t| [t.association(:assembly)] }
+end diff --git a/src/spec/factories/deployment.rb b/src/spec/factories/deployment.rb new file mode 100644 index 0000000..f3c0522 --- /dev/null +++ b/src/spec/factories/deployment.rb @@ -0,0 +1,6 @@ +Factory.define :deployment do |d|
- d.sequence(:name) { |n| "deployment#{n}" }
- d.association :deployable, :factory => :deployable
- d.association :pool, :factory => :pool
- d.association :owner, :factory => :user
+end diff --git a/src/spec/models/assembly_spec.rb b/src/spec/models/assembly_spec.rb new file mode 100644 index 0000000..2693116 --- /dev/null +++ b/src/spec/models/assembly_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper'
+describe Assembly do
- it "should have automatically generated uuid after validation" do
- a = Factory.build(:assembly)
- a.uuid = nil
- a.save
- a.uuid.should_not be_nil
- end
- it "should not be valid if assembly name is too long" do
- a = Factory.build(:assembly)
- a.name = ('a' * 256)
- a.valid?.should be_false
- a.errors[:name].should_not be_nil
- a.errors[:name].should =~ /^is too long.*/
- end
- it "should have associated template" do
- a = Factory.build(:assembly)
- a.templates.size.should eql(1)
- end
+end diff --git a/src/spec/models/deployable_spec.rb b/src/spec/models/deployable_spec.rb new file mode 100644 index 0000000..af1fc9f --- /dev/null +++ b/src/spec/models/deployable_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper'
+describe Deployable do
- it "should have automatically generated uuid after validation" do
- d = Factory.build(:deployable)
- d.uuid = nil
- d.save
- d.uuid.should_not be_nil
- end
- it "should not be valid if deployable name is too long" do
- d = Factory.build(:deployable)
- d.name = ('a' * 256)
- d.valid?.should be_false
- d.errors[:name].should_not be_nil
- d.errors[:name].should =~ /^is too long.*/
- end
- it "should have associated assembly" do
- d = Factory.build(:deployable)
- d.assemblies.size.should eql(1)
- end
+end diff --git a/src/spec/models/deployment_spec.rb b/src/spec/models/deployment_spec.rb new file mode 100644 index 0000000..c8eda13 --- /dev/null +++ b/src/spec/models/deployment_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper'
+describe Deployment do
- before(:each) do
- @quota = Factory :quota
- @pool = Factory(:pool, :quota_id => @quota.id)
- @deployment = Factory.build(:deployment, :pool_id => @pool.id)
- @actions = ['start', 'stop']
- end
- it "should require pool to be set" do
- @deployment.pool_id = nil
- @deployment.should_not be_valid
- @deployment.pool_id = 1
- @deployment.should be_valid
- end
- it "should require deployable to be set" do
- @deployment.deployable_id = nil
- @deployment.should_not be_valid
- @deployment.deployable_id = 1
- @deployment.should be_valid
- end
- it "should have a name of reasonable length" do
- [nil, '', 'x'*1025].each do |invalid_name|
@deployment.name = invalid_name
@deployment.should_not be_valid
- end
- @deployment.name = 'x'*1024
- @deployment.should be_valid
- end
- it "should have unique name" do
- @deployment.save!
- second_deployment = Factory.build(:deployment,
:pool_id => @deployment.pool_id,
:name => @deployment.name)
- second_deployment.should_not be_valid
- second_deployment.name = 'unique name'
- second_deployment.should be_valid
- end
- it "should tell apart valid and invalid actions" do
- @deployment.stub!(:get_action_list).and_return(@actions)
- @deployment.valid_action?('invalid action').should == false
- @deployment.valid_action?('start').should == true
- end
- it "should return action list" do
- @deployment.get_action_list.should eql(["start", "stop", "reboot"])
- end
+end diff --git a/src/spec/models/instance_spec.rb b/src/spec/models/instance_spec.rb index 625718d..787c0c5 100644 --- a/src/spec/models/instance_spec.rb +++ b/src/spec/models/instance_spec.rb @@ -24,14 +24,25 @@ describe Instance do @instance.should be_valid end
- it "should require template to be set" do
it "should require template to be set if there no deployment" do @instance.template_id = nil
@instance.deployment_id = nil @instance.should_not be_valid
@instance.template_id = 1 @instance.should be_valid end
it "should not allow template to be set if there's a deployment" do
@instance.deployment_id = 1
@instance.template_id = 1
@instance.should_not be_valid
@instance.template_id = nil
@instance.assembly_id = 1
@instance.should be_valid
end
it "should have a name of reasonable length" do [nil, '', 'x'*1025].each do |invalid_name| @instance.name = invalid_name
aeolus-devel@lists.fedorahosted.org