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(a)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(a)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(a)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(a)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(a)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
--
1.7.3.4