Skip to content

Commit

Permalink
Fixes #36577 - Filter gets applied to all the repository upon removal…
Browse files Browse the repository at this point in the history
… of repository for which the filter was created.
  • Loading branch information
sjha4 committed Jul 12, 2023
1 parent 05f9de2 commit 5c99a80
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 12 deletions.
5 changes: 4 additions & 1 deletion app/controllers/katello/api/v2/repositories_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -416,9 +416,12 @@ def update
api :DELETE, "/repositories/:id", N_("Destroy a custom repository")
param :id, :number, :required => true
param :remove_from_content_view_versions, :bool, :required => false, :desc => N_("Force delete the repository by removing it from all content view versions")
param :delete_empty_repo_filters, :bool, :required => false, :desc => N_("Delete content view filters that have this repository as the last associated repository. Defaults to true. If false, such filters will now apply to all repositories in the content view.")
def destroy
sync_task(::Actions::Katello::Repository::Destroy, @repository,
remove_from_content_view_versions: ::Foreman::Cast.to_bool(params.fetch(:remove_from_content_view_versions, false)))
remove_from_content_view_versions: ::Foreman::Cast.to_bool(params.fetch(:remove_from_content_view_versions, false)),
delete_empty_repo_filters: ::Foreman::Cast.to_bool(params.fetch(:delete_empty_repo_filters, true))
)
respond_for_destroy
end

Expand Down
7 changes: 7 additions & 0 deletions app/lib/actions/katello/repository/destroy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def plan(repository, options = {})
options.fetch(:organization_destroy, false)
destroy_content = options.fetch(:destroy_content, true)
remove_from_content_view_versions = options.fetch(:remove_from_content_view_versions, false)
delete_empty_repo_filters = options.fetch(:delete_empty_repo_filters, true)
action_subject(repository)
check_destroyable!(repository, remove_from_content_view_versions)
remove_generated_content_views(repository)
Expand All @@ -29,6 +30,7 @@ def plan(repository, options = {})

handle_acs_product_removal(repository)
handle_alternate_content_sources(repository)
delete_empty_repo_filters(repository) if delete_empty_repo_filters

plan_self(:user_id => ::User.current.id, :affected_cvv_ids => affected_cvv_ids)
sequence do
Expand Down Expand Up @@ -81,6 +83,11 @@ def handle_acs_product_removal(repository)
end
end

def delete_empty_repo_filters(repository)
filters_to_delete = repository.filters.select { |filter| filter.repositories.size == 1 }
::Katello::ContentViewFilter.where(id: filters_to_delete).destroy_all
end

def handle_custom_content(repository, remove_from_content_view_versions)
#if this is the last instance of a custom repo, destroy the content
if remove_from_content_view_versions || repository.root.repositories.where.not(id: repository.id).empty?
Expand Down
18 changes: 18 additions & 0 deletions app/views/katello/api/v2/repositories/base.json.rabl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,24 @@ child :published_in_versions => :content_view_versions do |_version|
end
end

child :repository_content_view_filters => :filters do |_filters|
node :content_view_filter_id do |object|
object.filter.id
end
node :content_view_filter_name do |object|
object.filter.name
end
node :content_view_id do |object|
object.filter.content_view_id
end
node :content_view_name do |object|
object.filter.content_view_name
end
node :last_affected_repo do |object|
object.filter&.repositories&.size == 1
end
end

child :latest_dynflow_sync => :last_sync do |_object|
attributes :id, :username, :started_at, :ended_at, :state, :result, :progress
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,25 @@
});
};

$scope.repositoryFiltersToDelete = function () {
return _.groupBy($scope.repository.filters && $scope.repository.filters.filter(function(filter) {
return filter.last_affected_repo === true;
}), function(filter) {
return filter.content_view_id;
});
};

$scope.repositoryWrapper = {
repository: $scope.repository,
repositoryVersions: {},
forceDelete: false
repositoryFiltersToDelete: {},
forceDeleteCV: false,
filterAction: 'delete',
showLastFilterDeletion: false
};

$scope.updateForceDelete = function () {
$scope.repositoryWrapper.forceDelete = !($scope.repositoryWrapper.forceDelete);
$scope.updateForceDeleteCV = function () {
$scope.repositoryWrapper.forceDeleteCV = !($scope.repositoryWrapper.forceDeleteCV);
};

$scope.product = Product.get({id: $scope.$stateParams.productId}, function () {
Expand All @@ -71,6 +82,8 @@
$scope.page.loading = false;
$scope.repositoryWrapper.repository = $scope.repository;
$scope.repositoryWrapper.repositoryVersions = $scope.repositoryVersions();
$scope.repositoryWrapper.repositoryFiltersToDelete = $scope.repositoryFiltersToDelete();
$scope.repositoryWrapper.showLastFilterDeletion = Object.keys($scope.repositoryWrapper.repositoryFiltersToDelete).length !== 0;
}, function (response) {
$scope.page.loading = false;
ApiErrorHandler.handleGETRequestErrors(response, $scope);
Expand Down Expand Up @@ -152,7 +165,7 @@
Notification.setSuccessMessage(translate('Repository "%s" successfully deleted').replace('%s', repositoryName));
};

Repository.remove({id: repository.id}, success, errorHandler);
Repository.remove({id: repository.id, 'delete_orphaned_filters': ($scope.repositoryWrapper.filterAction === 'delete')}, success, errorHandler);
};

$scope.canRemove = function (repo, product) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ <h2 translate>{{ repository.name }}</h2>
</li>
</ul>

<div bst-modal="removeRepository(repository)" model="repositoryWrapper">
<div bst-modal="removeRepository(repository, filterAction)" model="repositoryWrapper">
<div data-block="modal-header" translate>Remove Repository {{ repositoryWrapper.repository.name }}?</div>
<div data-block="modal-body">
<div ng-show="repositoryWrapper.repository.content_view_versions.length !== 0" style="margin-bottom: 1em">
<span translate>Repository will also be removed from the following published content view versions!</span>
<b><span translate>Repository will also be removed from the following published content view versions!</span></b>
<table class="table table-striped table-bordered" style="margin-top: 1em">
<thead>
<tr>
Expand Down Expand Up @@ -127,13 +127,62 @@ <h2 translate>{{ repository.name }}</h2>
</div>
<input type="checkbox"
ng-show="repositoryWrapper.repository.content_view_versions.length !== 0"
ng-model="repositoryWrapper.forceDelete"
ng-change="updateForceDelete()"/>
<span translate> Are you sure you want to remove repository {{ repositoryWrapper.repository.name }} from all content views?</span>
ng-model="repositoryWrapper.forceDeleteCV"
ng-change="updateForceDeleteCV()"/>
<span translate
ng-show="repositoryWrapper.repository.content_view_versions.length !== 0"
style="margin-bottom: 2em"
>
Are you sure you want to remove repository {{ repositoryWrapper.repository.name }} from all content views?
</span>
<div ng-show="repositoryWrapper.showLastFilterDeletion" style="margin-top: 1em; margin-bottom: 1em">
<b><span translate> The filters below have this repository as the last affected repository!</span></b>
<table class="table table-striped table-bordered" style="margin-top: 1em">
<thead>
<tr>
<th translate>Content View</th>
<th translate>Filters</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="filters in repositoryWrapper.repositoryFiltersToDelete">
<td class="align-center">
<a href="/content_views/{{filters[0]['content_view_id']}}/" target="_blank">
{{filters[0]['content_view_name']}}
</a>
</td>
<td class="align-center">
<div ng-repeat="filter in filters">
<a href="/content_views/{{filter['content_view_id']}}#/filters/{{filter['content_view_filter_id']}}" target="_blank">
{{filter['content_view_filter_name']}}
</a>
</div>
</td>
</tr>
</tbody>
</table>
<div class="radio">
<label>
<input type="radio" ng-model="repositoryWrapper.filterAction" value="delete" />
<span translate>
Delete filters
</span>
</label>
</div>
<div class="radio">
<label>
<input type="radio" ng-model="repositoryWrapper.filterAction" value="applyAll" />
<span translate>
Make filters apply to all repositories in the content view
</span>
</label>
</div>
</div>
</div>
<div data-block="modal-footer">
<span data-block="modal-confirm-button">
<button class="btn btn-danger" ng-disabled="repositoryWrapper.repository.content_view_versions.length !== 0 && !repositoryWrapper.forceDelete" ng-click="ok()">
<button class="btn btn-danger" ng-disabled="(repositoryWrapper.repository.content_view_versions.length !== 0 &&
!repositoryWrapper.forceDeleteCV)" ng-click="ok()">
<span translate>Delete</span>
</button>
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,15 @@ describe('Controller: RepositoryDetailsController', function() {

it('should provide a way to remove a repository', function() {
repository.id = 1;

repository.filters = [
{
"content_view_filter_id": 1,
"content_view_filter_name": "test",
"content_view_id": 38,
"content_view_name": "test",
"last_affected_repo": true
}
];
spyOn($scope, 'transitionTo');

$scope.removeRepository(repository);
Expand Down Expand Up @@ -202,4 +210,63 @@ describe('Controller: RepositoryDetailsController', function() {
}]
});
});

it('should provide a way to view orphaned filters on a repository', function() {
repository.id = 1;
repository.filters = [
{
"content_view_filter_id": 1,
"content_view_filter_name": "test",
"content_view_id": 38,
"content_view_name": "test",
"last_affected_repo": true
},
{
"content_view_filter_id": 2,
"content_view_filter_name": "test2",
"content_view_id": 38,
"content_view_name": "test",
"last_affected_repo": false
},
{
"content_view_filter_id": 3,
"content_view_filter_name": "test3",
"content_view_id": 38,
"content_view_name": "test",
"last_affected_repo": true
},
{
"content_view_filter_id": 4,
"content_view_filter_name": "test4",
"content_view_id": 39,
"content_view_name": "test",
"last_affected_repo": true
}
];
expect($scope.repositoryFiltersToDelete()).toEqual(
{
38: [{
content_view_filter_id: 1,
content_view_filter_name: 'test',
content_view_id: 38,
content_view_name: 'test',
last_affected_repo: true
},
{
content_view_filter_id: 3,
content_view_filter_name: 'test3',
content_view_id: 38,
content_view_name: 'test',
last_affected_repo: true
}
],
39: [{
content_view_filter_id: 4,
content_view_filter_name: 'test4',
content_view_id: 39,
content_view_name: 'test',
last_affected_repo: true
}]
});
});
});

0 comments on commit 5c99a80

Please sign in to comment.