Revision c7bfc159
Added by Partha Aji almost 10 years ago
app/controllers/katello/api/v2/environments_controller.rb | ||
---|---|---|
param :organization_id, :number, :desc => N_("organization identifier")
|
||
def destroy
|
||
if @environment.is_deletable?
|
||
@environment.destroy
|
||
sync_task(::Actions::Katello::Environment::Destroy, @environment)
|
||
respond_for_destroy
|
||
else
|
||
fail HttpErrors::BadRequest, @environment.errors.full_messages.join(" ")
|
app/lib/actions/katello/environment/destroy.rb | ||
---|---|---|
#
|
||
# Copyright 2014 Red Hat, Inc.
|
||
#
|
||
# This software is licensed to you under the GNU General Public
|
||
# License as published by the Free Software Foundation; either version
|
||
# 2 of the License (GPLv2) or (at your option) any later version.
|
||
# There is NO WARRANTY for this software, express or implied,
|
||
# including the implied warranties of MERCHANTABILITY,
|
||
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
|
||
# have received a copy of GPLv2 along with this software; if not, see
|
||
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||
|
||
module Actions
|
||
module Katello
|
||
module Environment
|
||
class Destroy < Actions::EntryAction
|
||
def plan(env)
|
||
sequence do
|
||
env.disable_auto_reindex!
|
||
action_subject(env)
|
||
|
||
concurrence do
|
||
env.content_view_environments.each do |cve|
|
||
plan_action(ContentView::Remove, cve.content_view, :content_view_environments => [cve])
|
||
end
|
||
end
|
||
|
||
env.reload.destroy!
|
||
plan_action(ElasticSearch::Reindex, env)
|
||
end
|
||
end
|
||
|
||
def humanized_name
|
||
_("Delete Lifecycle Environment")
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
app/lib/actions/katello/organization/destroy.rb | ||
---|---|---|
remove_content_views(organization)
|
||
remove_products(organization)
|
||
remove_default_content_view(organization)
|
||
remove_environments(organization)
|
||
organization.reload
|
||
organization.destroy!
|
||
end
|
||
... | ... | |
end
|
||
end
|
||
|
||
def remove_environments(organization)
|
||
organization.promotion_paths.each do |path|
|
||
path.reverse.each do |env|
|
||
plan_action(Katello::Environment::Destroy, env)
|
||
end
|
||
end
|
||
plan_action(Katello::Environment::Destroy, organization.library)
|
||
end
|
||
|
||
def remove_content_view_environments(organization)
|
||
organization.content_view_environments.non_default.each do |cv_env|
|
||
remove_content_view_environment(cv_env)
|
app/models/katello/concerns/organization_extensions.rb | ||
---|---|---|
include Glue::ElasticSearch::Organization if Katello.config.use_elasticsearch
|
||
include Ext::LabelFromName
|
||
|
||
before_destroy :remove_environments # must be before has_many :kt_environments
|
||
|
||
has_many :activation_keys, :class_name => "Katello::ActivationKey", :dependent => :destroy
|
||
has_many :providers, :class_name => "Katello::Provider", :dependent => :destroy
|
||
has_many :products, :class_name => "Katello::Product", :dependent => :destroy, :inverse_of => :organization
|
||
# has_many :environments is already defined in Foreman taxonomy.rb
|
||
has_many :kt_environments, :class_name => "Katello::KTEnvironment", :dependent => :destroy, :inverse_of => :organization
|
||
has_many :kt_environments, :class_name => "Katello::KTEnvironment", :dependent => :restrict, :inverse_of => :organization
|
||
has_one :library, :class_name => "Katello::KTEnvironment", :conditions => {:library => true}, :dependent => :destroy
|
||
has_many :gpg_keys, :class_name => "Katello::GpgKey", :dependent => :destroy, :inverse_of => :organization
|
||
has_many :sync_plans, :class_name => "Katello::SyncPlan", :dependent => :destroy, :inverse_of => :organization
|
||
... | ... | |
fail ::Foreman::Exception.new(N_("You cannot set an organization's parent_id. This feature is disabled."))
|
||
end
|
||
|
||
def remove_environments
|
||
# start at the end of each promotion path
|
||
promotion_paths.each do |path|
|
||
path.reverse.each { |env| env.destroy! }
|
||
end
|
||
library.destroy!
|
||
end
|
||
|
||
private
|
||
|
||
def start_discovery_task(url, notify = false)
|
app/models/katello/glue/elastic_search/environment.rb | ||
---|---|---|
base.class_eval do
|
||
include Ext::IndexedModel
|
||
after_save :update_related_index
|
||
after_destroy :delete_related_index
|
||
|
||
index_options :extended_json => :extended_index_attrs,
|
||
:json => {:only => [:id, :name, :description, :organization_id]},
|
||
... | ... | |
end
|
||
end
|
||
|
||
def delete_related_index
|
||
self.organization.update_index if self.organization
|
||
end
|
||
|
||
end
|
||
end
|
app/models/katello/glue/elastic_search/organization.rb | ||
---|---|---|
base.class_eval do
|
||
index_options :extended_json => :extended_index_attrs,
|
||
:json => {:except => [:debug_cert, :events]},
|
||
:display_attrs => [:name, :description, :environment]
|
||
:display_attrs => [:name, :description]
|
||
|
||
mapping do
|
||
indexes :name, :type => 'string', :analyzer => :kt_name_analyzer
|
||
... | ... | |
end
|
||
|
||
def extended_index_attrs
|
||
{:name_sort => name.downcase, :environment => self.kt_environments.collect{|e| e.name}}
|
||
{:name_sort => name.downcase}
|
||
end
|
||
end
|
||
end
|
app/models/katello/kt_environment.rb | ||
---|---|---|
module Katello
|
||
class KTEnvironment < Katello::Model
|
||
self.include_root_in_json = false
|
||
|
||
include ForemanTasks::Concerns::ActionSubject
|
||
include Authorization::LifecycleEnvironment
|
||
include Glue::ElasticSearch::Environment if Katello.config.use_elasticsearch
|
||
|
||
self.table_name = "katello_environments"
|
||
include Ext::LabelFromName
|
||
|
||
# RAILS3458: before_destroys before associations. see http://tinyurl.com/rails3458
|
||
before_destroy :is_deletable?
|
||
|
||
belongs_to :organization, :class_name => "Organization", :inverse_of => :environments
|
||
has_many :activation_keys, :class_name => "Katello::ActivationKey",
|
||
:dependent => :destroy, :foreign_key => :environment_id
|
||
:dependent => :restrict, :foreign_key => :environment_id
|
||
# rubocop:disable HasAndBelongsToMany
|
||
# TODO: change these into has_many associations
|
||
has_and_belongs_to_many :priors, { :class_name => "Katello::KTEnvironment", :foreign_key => :environment_id,
|
||
... | ... | |
|
||
has_many :repositories, :class_name => "Katello::Repository", dependent: :destroy, foreign_key: :environment_id
|
||
has_many :systems, :class_name => "Katello::System", :inverse_of => :environment,
|
||
:dependent => :destroy, :foreign_key => :environment_id
|
||
:dependent => :restrict, :foreign_key => :environment_id
|
||
has_many :distributors, :class_name => "Katello::Distributor", :inverse_of => :environment,
|
||
:dependent => :destroy, :foreign_key => :environment_id
|
||
has_many :content_view_environments, :class_name => "Katello::ContentViewEnvironment",
|
||
:foreign_key => :environment_id, :inverse_of => :environment, :dependent => :destroy
|
||
:foreign_key => :environment_id, :inverse_of => :environment, :dependent => :restrict
|
||
has_many :content_view_puppet_environments, :class_name => "Katello::ContentViewPuppetEnvironment",
|
||
:foreign_key => :environment_id, :inverse_of => :environment, :dependent => :destroy
|
||
:foreign_key => :environment_id, :inverse_of => :environment, :dependent => :restrict
|
||
has_many :content_view_versions, :through => :content_view_environments, :inverse_of => :environments
|
||
has_many :content_views, :through => :content_view_environments, :inverse_of => :environments
|
||
has_many :content_view_histories, :class_name => "Katello::ContentViewHistory", :dependent => :destroy,
|
||
... | ... | |
has_many :capsule_lifecycle_environments, :foreign_key => :lifecycle_environment_id,
|
||
:dependent => :destroy, :inverse_of => :lifecycle_environment
|
||
|
||
# RAILS3458: before_destroys before associations. see http://tinyurl.com/rails3458
|
||
before_destroy :is_deletable?, :prepend => true
|
||
|
||
scope(:not_in_capsule,
|
||
lambda do |capsule|
|
||
select("DISTINCT #{KTEnvironment.table_name}.*").
|
||
... | ... | |
return true if self.organization.nil? || self.organization.being_deleted?
|
||
|
||
if library?
|
||
errors.add :base, _("Library environments may not be deleted.")
|
||
return false
|
||
errors.add :base, _("Library lifecycle environments may not be deleted.")
|
||
elsif !successor.nil?
|
||
errors.add :base, _("Environment %s has a successor. Only the last environment on a path can be deleted") % self.name
|
||
return false
|
||
errors.add :base, _("Lifecycle Environment %s has a successor. Only the last lifecycle environment on a path can be deleted") % self.name
|
||
end
|
||
|
||
if systems.any?
|
||
errors.add(:base,
|
||
_("Lifecycle Environment %s has associated Content Hosts." +
|
||
" Please unregister or move the associated Content Hosts before trying to delete this lifecycle environment.") % self.name)
|
||
end
|
||
|
||
if activation_keys.any?
|
||
errors.add(:base,
|
||
_("Lifecycle Environment %s has associated Activation Keys." +
|
||
" Please change or remove the associated Activation Keys before trying to delete this lifecycle environment.") % self.name)
|
||
end
|
||
|
||
return true
|
||
return errors.empty?
|
||
end
|
||
|
||
#Unlike path which only gives the path from this environment going forward
|
spec/models/environment_spec.rb | ||
---|---|---|
end
|
||
|
||
describe "delete an environment" do
|
||
|
||
it "should delete the environment" do
|
||
id = @environment.id
|
||
@environment.destroy
|
||
User.current.remote_id = User.current.login
|
||
env = KTEnvironment.create!(:name=>"Boooo1224",
|
||
:organization => @organization,
|
||
:prior => @organization.library)
|
||
id = env.id
|
||
env.destroy!
|
||
lambda { KTEnvironment.find(id)}.must_raise(ActiveRecord::RecordNotFound)
|
||
end
|
||
end
|
spec/models/organization_spec.rb | ||
---|---|---|
end
|
||
end
|
||
|
||
describe "delete an organization" do
|
||
it "can delete the org" do
|
||
id = @organization.id
|
||
Organization.any_instance.stubs(:being_deleted?).returns(true)
|
||
@organization.destroy
|
||
|
||
@organization.must_be :destroyed?
|
||
lambda{Organization.find(id)}.must_raise(ActiveRecord::RecordNotFound)
|
||
end
|
||
|
||
it "can delete the org and envs are deleted" do
|
||
org_id = @organization.id
|
||
|
||
env_name = "prod"
|
||
@env = KTEnvironment.new(:name=>env_name, :label=> env_name, :library => false, :prior => @organization.library)
|
||
@organization.kt_environments << @env
|
||
@env.save!
|
||
|
||
Organization.any_instance.stubs(:being_deleted?).returns(true)
|
||
@organization.reload.destroy
|
||
|
||
lambda{Organization.find(org_id)}.must_raise(ActiveRecord::RecordNotFound)
|
||
KTEnvironment.where(:name => env_name).all.must_be_empty
|
||
end
|
||
|
||
it "can delete the org and env of a different org exist" do
|
||
env_name = "prod"
|
||
|
||
@org2 = Organization.create!(:name=>"foobar", :label=> "foobar")
|
||
|
||
@env1 = KTEnvironment.new(:name=>env_name, :label=> env_name, :organization => @organization, :prior => @organization.library)
|
||
@organization.kt_environments << @env1
|
||
@env1.save!
|
||
|
||
@env2 = KTEnvironment.new(:name=>env_name, :label=> env_name, :organization => @org2, :prior => @organization.library)
|
||
@org2.kt_environments << @env2
|
||
@env2.save!
|
||
|
||
id1 = @organization.id
|
||
Organization.any_instance.stubs(:being_deleted?).returns(true)
|
||
@organization.reload.destroy
|
||
lambda{Organization.find(id1)}.must_raise(ActiveRecord::RecordNotFound)
|
||
|
||
KTEnvironment.where(:name => env_name).first.must_equal(@env2)
|
||
KTEnvironment.where(:name => env_name).size.must_equal(1)
|
||
end
|
||
|
||
it "can delete an org where there is a full environment path" do
|
||
dev = create_environment(:name=>"Dev-34343", :label=> "Dev", :organization => @organization, :prior => @organization.library)
|
||
qa = create_environment(:name=>"QA", :label=> "QA", :organization => @organization, :prior => dev)
|
||
prod = create_environment(:name=>"prod", :label=> "prod", :organization => @organization, :prior => qa)
|
||
Organization.any_instance.stubs(:being_deleted?).returns(true)
|
||
|
||
@organization = @organization.reload
|
||
@organization.destroy
|
||
lambda{Organization.find(@organization.id)}.must_raise(ActiveRecord::RecordNotFound)
|
||
KTEnvironment.where(:name =>'Dev-34343').size.must_equal(0)
|
||
end
|
||
end
|
||
|
||
describe "it can retrieve manifest history" do
|
||
test 'test manifest history should be successful' do
|
||
@organization = @organization.reload
|
test/actions/katello/environment_test.rb | ||
---|---|---|
library, content_view)
|
||
end
|
||
end
|
||
|
||
class DestroyTest < TestBase
|
||
let(:action_class) { ::Actions::Katello::Environment::Destroy }
|
||
let(:action) { create_action action_class }
|
||
|
||
let(:environment) { stub }
|
||
|
||
it 'plans' do
|
||
content_view = stub
|
||
cve = mock(:content_view => content_view)
|
||
action.stubs(:action_subject).with(environment)
|
||
environment.expects(:reload).returns(environment)
|
||
environment.expects(:destroy!).returns(true)
|
||
environment.expects(:disable_auto_reindex!)
|
||
environment.expects(:content_view_environments).returns([cve])
|
||
plan_action(action, environment)
|
||
assert_action_planed_with(action, ::Actions::ElasticSearch::Reindex, environment)
|
||
assert_action_planed_with(action, ::Actions::Katello::ContentView::Remove, content_view, :content_view_environments => [cve])
|
||
end
|
||
end
|
||
|
||
end
|
test/actions/katello/organization_test.rb | ||
---|---|---|
let(:organization) { stub }
|
||
|
||
it 'plans' do
|
||
env = stub
|
||
library = stub
|
||
|
||
action.stubs(:action_subject).with(organization)
|
||
default_view = stub(:content_view_environments => [])
|
||
library = stub(:destroy! => true)
|
||
... | ... | |
organization.expects(:content_view_environments).returns(stub(:non_default => []))
|
||
organization.expects(:reload)
|
||
organization.expects(:destroy!).returns(true)
|
||
organization.expects(:promotion_paths).returns([[env]])
|
||
organization.expects(:library).returns(library)
|
||
|
||
plan_action(action, organization)
|
||
|
||
... | ... | |
::Actions::Candlepin::Owner::Destroy,
|
||
label: "ACME_Corporation")
|
||
assert_action_planed_with(action, ::Actions::Katello::ContentView::Destroy, default_view)
|
||
assert_action_planed_with(action, ::Actions::Katello::Environment::Destroy, env)
|
||
end
|
||
end
|
||
end
|
test/controllers/api/v2/environments_controller_test.rb | ||
---|---|---|
|
||
module Katello
|
||
class Api::V2::EnvironmentsControllerTest < ActionController::TestCase
|
||
|
||
include Support::ForemanTasks::Task
|
||
def self.before_suite
|
||
models = ["KTEnvironment", "ContentViewEnvironment", "Organization"]
|
||
disable_glue_layers(["Candlepin", "Pulp", "ElasticSearch"], models)
|
||
... | ... | |
end
|
||
|
||
def test_destroy
|
||
destroyable_env = KTEnvironment.create!(:name => "DestroyAble",
|
||
:organization => @staging.organization,
|
||
:prior => @staging)
|
||
assert_sync_task(::Actions::Katello::Environment::Destroy, destroyable_env)
|
||
delete :destroy, :organization_id => @organization.id,
|
||
:id => @staging.id
|
||
:id => destroyable_env.id
|
||
|
||
assert_response :success
|
||
end
|
test/models/content_view_test.rb | ||
---|---|---|
assert_includes @library.content_views, @library_view
|
||
end
|
||
|
||
def test_environment_content_view_env_destroy
|
||
def test_environment_content_view_env_destroy_should_fail
|
||
User.current = User.find(users(:admin))
|
||
ContentViewPuppetEnvironment.any_instance.stubs(:clear_content_indices)
|
||
env = @dev
|
||
cve = env.content_views.first.content_view_environments.where(:environment_id=>env.id).first
|
||
env.destroy
|
||
assert_nil ContentViewEnvironment.find_by_id(cve.id)
|
||
assert_raises(RuntimeError) do
|
||
env.destroy!
|
||
end
|
||
refute_nil ContentViewEnvironment.find_by_id(cve.id)
|
||
end
|
||
|
||
def test_promote
|
test/models/kt_environment_test.rb | ||
---|---|---|
assert_nil env.default_content_view_version
|
||
end
|
||
|
||
def test_destroy_content_view_environment
|
||
env = @staging
|
||
cve = env.content_views.first.content_view_environments.where(:environment_id=>env.id).first
|
||
cve_cp_id = cve.cp_id
|
||
env.destroy
|
||
assert_empty ContentViewEnvironment.where(:cp_id=>cve_cp_id)
|
||
def test_destroy_env_with_systems_should_fail
|
||
env = KTEnvironment.create!(:name => "batman", :organization => @acme_corporation, :prior => @library)
|
||
env.expects(:systems).returns([stub])
|
||
assert_raises(RuntimeError) do
|
||
env.destroy!
|
||
end
|
||
end
|
||
|
||
def test_destroy_env_with_activation_keys_should_fail
|
||
env = KTEnvironment.create!(:name => "batman", :organization => @acme_corporation, :prior => @library)
|
||
env.stubs(:activation_keys).returns([stub])
|
||
assert_raises(RuntimeError) do
|
||
env.destroy!
|
||
end
|
||
end
|
||
|
||
def test_destroy_library
|
test/models/organization_test.rb | ||
---|---|---|
refute_empty org.default_content_view.content_view_environments
|
||
end
|
||
|
||
def test_org_being_deleted
|
||
Organization.any_instance.stubs(:being_deleted?).returns(true)
|
||
User.current = User.find(users(:admin))
|
||
org = Organization.create!(:name=>"TestOrg", :label=>'test_org')
|
||
org.content_view_environments.first.destroy!
|
||
org.reload.library.destroy!
|
||
id = org.id
|
||
org.destroy!
|
||
assert_nil Organization.find_by_id(id)
|
||
end
|
||
|
||
end
|
||
end
|
Also available in: Unified diff
Fixes #6815,#6187/bz1125398,1125358 - Environment Destroy Dynflow
This commit adds code to orchestrate lifecycle env destroy via dynflow.
In addition to that it adds code to prevent environment deletion if any
of the lifecycle env associations like content hosts and activation keys