katello 3.15.0.rc1.1 → 3.15.0.rc1.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of katello might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/app/assets/javascripts/katello/hosts/activation_key_edit.js +32 -54
- data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +1 -1
- data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +11 -4
- data/app/controllers/katello/api/v2/repositories_controller.rb +7 -3
- data/app/controllers/katello/api/v2/subscriptions_controller.rb +2 -3
- data/app/lib/actions/katello/content_view/incremental_updates.rb +1 -1
- data/app/lib/actions/katello/host/erratum/applicable_errata_install.rb +6 -2
- data/app/lib/actions/pulp3/content_migration.rb +5 -5
- data/app/lib/actions/pulp3/import_migration.rb +3 -3
- data/app/lib/actions/pulp3/orchestration/repository/import_upload.rb +1 -1
- data/app/lib/katello/concerns/base_template_scope_extensions.rb +1 -1
- data/app/models/katello/authorization/pool.rb +5 -1
- data/app/models/katello/authorization/subscription.rb +3 -1
- data/app/models/katello/candlepin/repository_mapper.rb +5 -1
- data/app/models/katello/concerns/host_managed_extensions.rb +17 -8
- data/app/models/katello/concerns/pulp_database_unit.rb +1 -1
- data/app/models/katello/content_view.rb +4 -0
- data/app/models/katello/glue/candlepin/candlepin_object.rb +0 -6
- data/app/models/katello/glue/candlepin/owner.rb +1 -1
- data/app/models/katello/glue/candlepin/repository.rb +0 -8
- data/app/models/katello/glue/pulp/repos.rb +41 -1
- data/app/models/katello/installed_package.rb +5 -4
- data/app/models/katello/pool.rb +1 -1
- data/app/services/katello/pulp/repository/docker.rb +12 -2
- data/app/services/katello/pulp/simple_package.rb +6 -2
- data/app/services/katello/pulp3/erratum.rb +4 -0
- data/app/services/katello/pulp3/migration.rb +61 -8
- data/app/services/katello/pulp3/migration_plan.rb +79 -5
- data/app/views/dashboard/_subscription_widget.html.erb +1 -1
- data/app/views/katello/api/v2/organizations/show.json.rabl +3 -0
- data/app/views/katello/api/v2/packages/backend.json.rabl +4 -0
- data/app/views/katello/api/v2/products/show.json.rabl +2 -0
- data/app/views/overrides/activation_keys/_host_tab_pane.html.erb +10 -2
- data/app/views/smart_proxies/plugins/{_pulp3.html.erb → _pulpcore.html.erb} +0 -0
- data/config/katello.yaml.example +0 -6
- data/db/migrate/20200121213430_katello_repository_rpms_id_big_int.rb +5 -0
- data/db/migrate/20200129172534_add_epoch_version_release_arch_to_katello_installed_packages.rb +40 -0
- data/engines/bastion/app/views/bastion/layouts/assets.html.erb +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-errata-modal.controller.js +9 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-subscriptions-modal.controller.js +4 -4
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-errata-modal.html +2 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-subscriptions-modal.html +3 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-host-modal-helper.service.js +1 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-details.controller.js +4 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-subscriptions.controller.js +4 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-info.html +2 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-subscriptions.html +15 -10
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/packages/details/views/package-info.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/content-access-mode-banner.directive.js +4 -4
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/views/content-access-mode-banner.html +1 -1
- data/lib/katello/tasks/pulp3_migration.rake +1 -1
- data/lib/katello/tasks/pulp3_post_migration_check.rake +32 -0
- data/lib/katello/tasks/repository.rake +10 -7
- data/lib/katello/version.rb +1 -1
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalActions.js +2 -0
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalSelectors.js +2 -0
- data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +4 -0
- data/webpack/scenes/Organizations/OrganizationSelectors.js +4 -0
- data/webpack/scenes/Subscriptions/Manifest/DeleteManifestModalText.js +14 -9
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +183 -169
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.scss +12 -0
- data/webpack/scenes/Subscriptions/Manifest/ManifestConstants.js +4 -0
- data/webpack/scenes/Subscriptions/Manifest/__tests__/ManageManifestModal.test.js +5 -3
- data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +130 -181
- data/webpack/scenes/Subscriptions/Manifest/index.js +10 -1
- data/webpack/scenes/Subscriptions/SubscriptionActions.js +4 -9
- data/webpack/scenes/Subscriptions/SubscriptionConstants.js +0 -3
- data/webpack/scenes/Subscriptions/SubscriptionReducer.js +3 -11
- data/webpack/scenes/Subscriptions/SubscriptionsPage.js +33 -13
- data/webpack/scenes/Subscriptions/SubscriptionsSelectors.js +2 -5
- data/webpack/scenes/Subscriptions/__tests__/SubscriptionsActions.test.js +0 -7
- data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +5 -0
- data/webpack/scenes/Subscriptions/__tests__/SubscriptionsReducer.test.js +0 -12
- data/webpack/scenes/Subscriptions/__tests__/SubscriptionsSelectors.test.js +0 -3
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsActions.test.js.snap +0 -12
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +2 -3
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsReducer.test.js.snap +0 -73
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsSelectors.test.js.snap +0 -3
- data/webpack/scenes/Subscriptions/__tests__/subscriptions.fixtures.js +0 -4
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js +13 -22
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/SubscriptionsTable.test.js +10 -0
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +2 -1
- data/webpack/scenes/Subscriptions/index.js +4 -3
- data/webpack/scenes/Tasks/TaskConstants.js +1 -0
- metadata +41 -18
- data/app/assets/javascripts/katello/widgets/auto_complete.js +0 -183
- data/db/seeds.d/115-http_proxy.rb +0 -25
- data/vendor/assets/stylesheets/katello/jquery.jnotify.css +0 -98
data/db/migrate/20200129172534_add_epoch_version_release_arch_to_katello_installed_packages.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
class AddEpochVersionReleaseArchToKatelloInstalledPackages < ActiveRecord::Migration[5.2]
|
2
|
+
def up
|
3
|
+
add_column :katello_installed_packages, :nvrea, :string
|
4
|
+
add_column :katello_installed_packages, :epoch, :string
|
5
|
+
add_column :katello_installed_packages, :version, :string
|
6
|
+
add_column :katello_installed_packages, :release, :string
|
7
|
+
add_column :katello_installed_packages, :arch, :string
|
8
|
+
|
9
|
+
epoch_non_0 = ::Katello::Rpm.where.not(epoch: [0, nil]).pluck(:nvra, :epoch).to_h
|
10
|
+
installed_packages = []
|
11
|
+
|
12
|
+
::Katello::InstalledPackage.reset_column_information
|
13
|
+
::Katello::InstalledPackage.find_each do |pkg|
|
14
|
+
epoch = epoch_non_0[pkg.nvra] || "0"
|
15
|
+
|
16
|
+
attributes_hash = ::Katello::Util::Package.parse_nvrea(pkg.nvra)
|
17
|
+
attributes_hash[:epoch] = epoch
|
18
|
+
attributes_hash[:nvra] = pkg.nvra
|
19
|
+
if epoch == "0"
|
20
|
+
attributes_hash[:nvrea] = pkg.nvra
|
21
|
+
else
|
22
|
+
attributes_hash[:nvrea] = "#{pkg.name}-#{epoch}:#{attributes_hash[:version]}-"\
|
23
|
+
"#{attributes_hash[:release]}.#{attributes_hash[:arch]}"
|
24
|
+
end
|
25
|
+
|
26
|
+
installed_packages << ::Katello::InstalledPackage.new(attributes_hash)
|
27
|
+
end
|
28
|
+
::Katello::InstalledPackage.import(installed_packages, validate: false, batch_size: 50_000,
|
29
|
+
on_duplicate_key_update: {conflict_target: [:nvra],
|
30
|
+
columns: [:nvrea, :epoch, :version, :release, :arch]})
|
31
|
+
end
|
32
|
+
|
33
|
+
def down
|
34
|
+
remove_column :katello_installed_packages, :nvrea, :string
|
35
|
+
remove_column :katello_installed_packages, :epoch, :string
|
36
|
+
remove_column :katello_installed_packages, :version, :string
|
37
|
+
remove_column :katello_installed_packages, :release, :string
|
38
|
+
remove_column :katello_installed_packages, :arch, :string
|
39
|
+
end
|
40
|
+
end
|
@@ -18,7 +18,7 @@
|
|
18
18
|
angular.module('Bastion.features').value('FeatureSettings', angular.fromJson(<%= SETTINGS[:features].nil? ? {} : SETTINGS[:features].to_json.html_safe %>));
|
19
19
|
angular.module('Bastion').value('currentLocale', '<%= I18n.locale %>');
|
20
20
|
angular.module('Bastion').value('CurrentOrganization', "<%= Organization.current.id if Organization.current %>");
|
21
|
-
angular.module('Bastion').value('
|
21
|
+
angular.module('Bastion').value('simpleContentAccessEnabled', <%= Organization.current.simple_content_access? if Organization.current %>);
|
22
22
|
angular.module('Bastion').value('foreman', tfm);
|
23
23
|
angular.module('Bastion').value('repositoryTypes', angular.fromJson('<%= Katello::RepositoryTypeManager.repository_types.values.to_json.html_safe %>'));
|
24
24
|
angular.module('Bastion').value('deleteHostOnUnregister', angular.fromJson('<%= Setting[:unregister_delete_host] %>'));
|
@@ -29,6 +29,13 @@ angular.module('Bastion.content-hosts').controller('ContentHostsBulkErrataModalC
|
|
29
29
|
var params = hostIds;
|
30
30
|
params['content_type'] = 'errata';
|
31
31
|
params.content = _.map($scope.table.getSelected(), 'errata_id');
|
32
|
+
|
33
|
+
if (nutupane.table.allResultsSelected) {
|
34
|
+
params['install_all'] = true;
|
35
|
+
} else {
|
36
|
+
params['install_all'] = false;
|
37
|
+
}
|
38
|
+
|
32
39
|
params['organization_id'] = CurrentOrganization;
|
33
40
|
return params;
|
34
41
|
}
|
@@ -38,6 +45,8 @@ angular.module('Bastion.content-hosts').controller('ContentHostsBulkErrataModalC
|
|
38
45
|
}
|
39
46
|
|
40
47
|
nutupane = new Nutupane(HostBulkAction, hostIds, 'installableErrata');
|
48
|
+
nutupane.enableSelectAllResults();
|
49
|
+
|
41
50
|
$scope.controllerName = 'katello_errata';
|
42
51
|
nutupane.masterOnly = true;
|
43
52
|
$scope.showErrata = false;
|
@@ -12,13 +12,14 @@
|
|
12
12
|
* @requires SubscriptionsHelper
|
13
13
|
* @requires Notification
|
14
14
|
* @requires hostIds
|
15
|
+
* @requires simpleContentAccessEnabled
|
15
16
|
*
|
16
17
|
* @description
|
17
18
|
* A controller for providing bulk action functionality to the content hosts page.
|
18
19
|
*/
|
19
20
|
angular.module('Bastion.content-hosts').controller('ContentHostsBulkSubscriptionsModalController',
|
20
|
-
['$scope', '$location', '$uibModalInstance', 'Nutupane', 'CurrentOrganization', 'HostBulkAction', 'Subscription', 'SubscriptionsHelper', 'Notification', 'hostIds', '
|
21
|
-
function ($scope, $location, $uibModalInstance, Nutupane, CurrentOrganization, HostBulkAction, Subscription, SubscriptionsHelper, Notification, hostIds,
|
21
|
+
['$scope', '$location', '$uibModalInstance', 'Nutupane', 'CurrentOrganization', 'HostBulkAction', 'Subscription', 'SubscriptionsHelper', 'Notification', 'hostIds', 'simpleContentAccessEnabled',
|
22
|
+
function ($scope, $location, $uibModalInstance, Nutupane, CurrentOrganization, HostBulkAction, Subscription, SubscriptionsHelper, Notification, hostIds, simpleContentAccessEnabled) {
|
22
23
|
var success, error, params = {
|
23
24
|
'organization_id': CurrentOrganization,
|
24
25
|
'sort_order': 'ASC',
|
@@ -44,7 +45,6 @@ angular.module('Bastion.content-hosts').controller('ContentHostsBulkSubscription
|
|
44
45
|
});
|
45
46
|
};
|
46
47
|
|
47
|
-
|
48
48
|
$scope.contentNutupane = new Nutupane(Subscription, params,
|
49
49
|
'queryPaged', {disableAutoLoad: true});
|
50
50
|
$scope.controllerName = 'katello_subscriptions';
|
@@ -53,7 +53,7 @@ angular.module('Bastion.content-hosts').controller('ContentHostsBulkSubscription
|
|
53
53
|
$scope.contentNutupane.masterOnly = true;
|
54
54
|
$scope.contentNutupane.load();
|
55
55
|
$scope.groupedSubscriptions = {};
|
56
|
-
$scope.
|
56
|
+
$scope.simpleContentAccessEnabled = simpleContentAccessEnabled;
|
57
57
|
|
58
58
|
$scope.$watch('table.rows', function (rows) {
|
59
59
|
$scope.groupedSubscriptions = SubscriptionsHelper.groupByProductName(rows);
|
@@ -7,11 +7,11 @@
|
|
7
7
|
|
8
8
|
<div class="row">
|
9
9
|
<div class="col-sm-12">
|
10
|
-
<button type="button" class="btn btn-default" ng-click="autoAttach()" ng-disabled="table.numSelected > 0 ||
|
10
|
+
<button type="button" class="btn btn-default" ng-click="autoAttach()" ng-disabled="table.numSelected > 0 || simpleContentAccessEnabled">
|
11
11
|
<span translate>Auto-Attach</span>
|
12
12
|
</button>
|
13
13
|
|
14
|
-
<p class="help-text" ng-show="table.numSelected === 0 &&
|
14
|
+
<p class="help-text" ng-show="table.numSelected === 0 && !simpleContentAccessEnabled">
|
15
15
|
Auto-attach available subscriptions to all selected hosts.
|
16
16
|
</p>
|
17
17
|
|
@@ -19,7 +19,7 @@
|
|
19
19
|
<div content-access-mode-banner/>
|
20
20
|
</p>
|
21
21
|
|
22
|
-
<p class="help-text" ng-show="table.numSelected > 0 &&
|
22
|
+
<p class="help-text" ng-show="table.numSelected > 0 && !simpleContentAccessEnabled">
|
23
23
|
Auto-attach uses all available subscriptions, not a selected subset.
|
24
24
|
</p>
|
25
25
|
</div>
|
@@ -39,6 +39,7 @@ angular.module('Bastion.content-hosts').service('ContentHostsModalHelper', ['$ui
|
|
39
39
|
$uibModal.open({
|
40
40
|
templateUrl: 'content-hosts/bulk/views/content-hosts-bulk-errata-modal.html',
|
41
41
|
controller: 'ContentHostsBulkErrataModalController',
|
42
|
+
openedClass: 'bastion',
|
42
43
|
size: 'lg',
|
43
44
|
resolve: {
|
44
45
|
hostIds: this.resolveFunc()
|
@@ -141,6 +141,10 @@ angular.module('Bastion.content-hosts').controller('ContentHostDetailsController
|
|
141
141
|
return false;
|
142
142
|
};
|
143
143
|
|
144
|
+
$scope.autoHealOptions = function () {
|
145
|
+
return [{value: true, name: translate("Yes")}, {value: true, name: translate("No")}];
|
146
|
+
};
|
147
|
+
|
144
148
|
$scope.serviceLevels = function () {
|
145
149
|
return $scope.organization.$promise.then(function(org) {
|
146
150
|
return _.union(org.service_levels, $scope.defaultServiceLevels);
|
@@ -8,13 +8,14 @@
|
|
8
8
|
* @requires Subscription
|
9
9
|
* @requires SubscriptionsHelper
|
10
10
|
* @requires Notification
|
11
|
+
* @requires simpleContentAccessEnabled
|
11
12
|
*
|
12
13
|
* @description
|
13
14
|
* Provides the functionality for the content host details action pane.
|
14
15
|
*/
|
15
16
|
angular.module('Bastion.content-hosts').controller('ContentHostSubscriptionsController',
|
16
|
-
['$scope', '$location', 'translate', 'Nutupane', 'CurrentOrganization', 'Subscription', 'Host', 'HostSubscription', 'SubscriptionsHelper', 'Notification',
|
17
|
-
function ($scope, $location, translate, Nutupane, CurrentOrganization, Subscription, Host, HostSubscription, SubscriptionsHelper, Notification) {
|
17
|
+
['$scope', '$location', 'translate', 'Nutupane', 'CurrentOrganization', 'Subscription', 'Host', 'HostSubscription', 'SubscriptionsHelper', 'Notification', 'simpleContentAccessEnabled',
|
18
|
+
function ($scope, $location, translate, Nutupane, CurrentOrganization, Subscription, Host, HostSubscription, SubscriptionsHelper, Notification, simpleContentAccessEnabled) {
|
18
19
|
|
19
20
|
var params = {
|
20
21
|
'organization_id': CurrentOrganization,
|
@@ -30,6 +31,7 @@ angular.module('Bastion.content-hosts').controller('ContentHostSubscriptionsCont
|
|
30
31
|
$scope.nutupane.masterOnly = true;
|
31
32
|
$scope.isRemoving = false;
|
32
33
|
$scope.contextAdd = false;
|
34
|
+
$scope.simpleContentAccessEnabled = simpleContentAccessEnabled;
|
33
35
|
$scope.groupedSubscriptions = {};
|
34
36
|
$scope.$watch('table.rows', function (rows) {
|
35
37
|
$scope.groupedSubscriptions = SubscriptionsHelper.groupByProductName(rows);
|
@@ -82,12 +82,12 @@
|
|
82
82
|
</dd>
|
83
83
|
|
84
84
|
<dt translate>Auto-Attach</dt>
|
85
|
-
<dd
|
85
|
+
<dd ng-if= "simpleContentAccessEnabled" translate> Not Applicable </dd>
|
86
|
+
<dd ng-if= "!simpleContentAccessEnabled" bst-edit-select="host.subscription_facet_attributes.autoheal"
|
86
87
|
readonly="denied('edit_hosts', host)"
|
87
88
|
formatter="booleanToYesNo"
|
88
89
|
on-save="saveSubscriptionFacet(host)">
|
89
90
|
</dd>
|
90
|
-
|
91
91
|
</dl>
|
92
92
|
|
93
93
|
<div class="divider"></div>
|
@@ -25,22 +25,27 @@
|
|
25
25
|
|
26
26
|
<dt translate>Auto-Attach</dt>
|
27
27
|
<dd>
|
28
|
+
<span ng-if="simpleContentAccessEnabled" translate>
|
29
|
+
Not Applicable
|
30
|
+
</span>
|
31
|
+
<div ng-if="!simpleContentAccessEnabled">
|
28
32
|
<div bst-edit-checkbox="host.subscription_facet_attributes.autoheal"
|
29
33
|
formatter="booleanToYesNo"
|
30
34
|
readonly="denied('edit_hosts', host)"
|
31
35
|
on-save="saveSubscriptionFacet(host)">
|
32
36
|
</div>
|
37
|
+
<a ng-hide="denied('edit_hosts', host)"
|
38
|
+
ng-click="autoAttachSubscriptions()"
|
39
|
+
class="btn btn-default"
|
40
|
+
ng-disabled="subscription.workingMode">
|
41
|
+
<span translate>Run Auto-Attach</span>
|
42
|
+
</a>
|
33
43
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
</
|
39
|
-
|
40
|
-
<span ng-show="subscription.workingMode">
|
41
|
-
<i class="fa fa-spinner inline-icon fa-spin"></i>
|
42
|
-
<span translate>Working</span>
|
43
|
-
</span>
|
44
|
+
<span ng-show="subscription.workingMode">
|
45
|
+
<i class="fa fa-spinner inline-icon fa-spin"></i>
|
46
|
+
<span translate>Working</span>
|
47
|
+
</span>
|
48
|
+
</div>
|
44
49
|
</dd>
|
45
50
|
|
46
51
|
<dt translate>Service Level</dt>
|
@@ -2,19 +2,19 @@
|
|
2
2
|
* @ngdoc directive
|
3
3
|
* @name Bastion.subscriptions:contentAccessModeBanner
|
4
4
|
*
|
5
|
-
* @requires
|
5
|
+
* @requires simpleContentAccessEnabled
|
6
6
|
*
|
7
7
|
* @description
|
8
8
|
* Component for showing information about content access mode (whether content is
|
9
9
|
* allowed with or without a subscription)
|
10
10
|
*/
|
11
11
|
angular.module('Bastion.subscriptions').directive('contentAccessModeBanner',
|
12
|
-
['
|
13
|
-
function (
|
12
|
+
['simpleContentAccessEnabled',
|
13
|
+
function (simpleContentAccessEnabled) {
|
14
14
|
return {
|
15
15
|
restrict: 'AE',
|
16
16
|
controller: ['$scope', function ($scope) {
|
17
|
-
$scope.
|
17
|
+
$scope.simpleContentAccessEnabled = simpleContentAccessEnabled;
|
18
18
|
}],
|
19
19
|
templateUrl: 'subscriptions/views/content-access-mode-banner.html'
|
20
20
|
};
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div bst-alert="info" ng-show="
|
1
|
+
<div bst-alert="info" ng-show="simpleContentAccessEnabled">
|
2
2
|
<span translate>
|
3
3
|
This organization has Simple Content Access enabled. Hosts can consume from all repositories in their Content View regardless of subscription status.
|
4
4
|
</span>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
namespace :katello do
|
2
2
|
desc "Runs a Pulp 2 to 3 Content Migration for supported types. May be run multiple times. Use wait=false to immediately return with a task url."
|
3
3
|
task :pulp3_migration => ["environment", "disable_dynflow", "check_ping"] do
|
4
|
-
task = ForemanTasks.async_task(Actions::Pulp3::ContentMigration
|
4
|
+
task = ForemanTasks.async_task(Actions::Pulp3::ContentMigration)
|
5
5
|
|
6
6
|
if ENV['wait'].nil? || ::Foreman::Cast.to_bool(ENV['wait'])
|
7
7
|
until !task.pending? || task.paused?
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.expand_path("../engine", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
namespace :katello do
|
4
|
+
desc "Runs a post Pulp3 migration check for supported content types."
|
5
|
+
task :pulp3_post_migration_check => :environment do
|
6
|
+
repository_types = Katello::Pulp3::Migration::REPOSITORY_TYPES
|
7
|
+
|
8
|
+
repository_types.each do |type|
|
9
|
+
filter = 'version_href is NULL OR remote_href is NULL'
|
10
|
+
|
11
|
+
unless type == Katello::Repository::DOCKER_TYPE
|
12
|
+
filter += ' OR publication_href is NULL'
|
13
|
+
end
|
14
|
+
repositories = Katello::Repository.with_type(type).where(filter)
|
15
|
+
|
16
|
+
if repositories.any?
|
17
|
+
$stderr.print("ERROR: #{type} repository #{repositories.first.id} has a NULL value for remote_href, version_href, publication_href\n")
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
non_archived_repositories = Katello::Repository.with_type(type).non_archived
|
22
|
+
with_no_distribution_references = non_archived_repositories
|
23
|
+
.left_outer_joins(:distribution_references)
|
24
|
+
.where(katello_distribution_references: { id: nil })
|
25
|
+
|
26
|
+
if with_no_distribution_references.any?
|
27
|
+
$stderr.print("ERROR: A non-archive #{type} repository #{with_no_distribution_references.first.id} did not have a distribution reference\n")
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -11,14 +11,17 @@ namespace :katello do
|
|
11
11
|
task :publish_unpublished_repositories => ["environment", "disable_dynflow", "check_ping"] do
|
12
12
|
needing_publish = []
|
13
13
|
Organization.find_each do |org|
|
14
|
-
org.default_content_view.versions.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
if org.default_content_view && !org.default_content_view.versions.empty?
|
15
|
+
org.default_content_view.versions.first.repositories.joins(:root)
|
16
|
+
.where.not(katello_root_repositories: { url: nil }).find_each do |repo|
|
17
|
+
begin
|
18
|
+
if repo.needs_metadata_publish?
|
19
|
+
Rails.logger.error("Repository metadata for #{repo.name} (#{repo.id}) is out of date, regenerating.")
|
20
|
+
needing_publish << repo.id
|
21
|
+
end
|
22
|
+
rescue => e
|
23
|
+
puts "Failed to check repository #{repo.id}: #{e}"
|
19
24
|
end
|
20
|
-
rescue => e
|
21
|
-
puts "Failed to check repository #{repo.id}: #{e}"
|
22
25
|
end
|
23
26
|
end
|
24
27
|
end
|
data/lib/katello/version.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import React from 'react';
|
1
2
|
import { translate as __ } from 'foremanReact/common/I18n';
|
2
3
|
|
3
4
|
const question = __('Are you sure you want to delete the manifest?');
|
@@ -11,14 +12,18 @@ const l4 = __(`Require you to upload the subscription-manifest and re-attach
|
|
11
12
|
const debug = __(`This action should only be taken in extreme circumstances or
|
12
13
|
for debugging purposes.`);
|
13
14
|
|
14
|
-
const DeleteManifestModalText =
|
15
|
-
<
|
16
|
-
<
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
</
|
22
|
-
<
|
15
|
+
const DeleteManifestModalText = () => (
|
16
|
+
<React.Fragment>
|
17
|
+
<p>{question}</p>
|
18
|
+
<p>{note}</p>
|
19
|
+
<ul className="list-aligned">
|
20
|
+
<li>{l1}</li>
|
21
|
+
<li>{l2}</li>
|
22
|
+
<li>{l3}</li>
|
23
|
+
<li>{l4}</li>
|
24
|
+
</ul>
|
25
|
+
<p>{debug}</p>
|
26
|
+
</React.Fragment>
|
27
|
+
);
|
23
28
|
|
24
29
|
export default DeleteManifestModalText;
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import React, { Component } from 'react';
|
2
2
|
import PropTypes from 'prop-types';
|
3
|
-
import { Col, Tabs, Tab, Form, FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
|
4
|
-
import { Button,
|
3
|
+
import { Grid, Col, Row, Tabs, Tab, Form, FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
|
4
|
+
import { Button, Spinner, OverlayTrigger, Tooltip, Icon } from 'patternfly-react';
|
5
|
+
import ForemanModal from 'foremanReact/components/ForemanModal';
|
5
6
|
import { isEqual } from 'lodash';
|
6
7
|
import { translate as __ } from 'foremanReact/common/I18n';
|
7
8
|
import TooltipButton from '../../../move_to_pf/TooltipButton';
|
@@ -10,25 +11,24 @@ import { Table } from '../../../move_to_foreman/components/common/table';
|
|
10
11
|
import { manifestExists } from '../SubscriptionHelpers';
|
11
12
|
import { columns } from './ManifestHistoryTableSchema';
|
12
13
|
import DeleteManifestModalText from './DeleteManifestModalText';
|
14
|
+
import { MANAGE_MANIFEST_MODAL_ID, DELETE_MANIFEST_MODAL_ID } from './ManifestConstants';
|
15
|
+
|
16
|
+
import './ManageManifestModal.scss';
|
13
17
|
|
14
18
|
class ManageManifestModal extends Component {
|
15
19
|
constructor(props) {
|
16
20
|
super(props);
|
17
21
|
|
18
22
|
this.state = {
|
19
|
-
showModal: props.showModal,
|
20
23
|
actionInProgress: props.taskInProgress,
|
21
|
-
showDeleteManifestModalDialog: false,
|
22
24
|
};
|
23
25
|
}
|
24
26
|
|
25
27
|
static getDerivedStateFromProps(newProps, prevState) {
|
26
28
|
if (
|
27
|
-
!isEqual(newProps.showModal, prevState.showModal) ||
|
28
29
|
!isEqual(newProps.taskInProgress, prevState.actionInProgress)
|
29
30
|
) {
|
30
31
|
return {
|
31
|
-
showModal: newProps.showModal,
|
32
32
|
actionInProgress: newProps.taskInProgress,
|
33
33
|
};
|
34
34
|
}
|
@@ -52,10 +52,16 @@ class ManageManifestModal extends Component {
|
|
52
52
|
}
|
53
53
|
|
54
54
|
hideModal = () => {
|
55
|
-
this.
|
56
|
-
this.props.
|
55
|
+
if (this.props.deleteManifestModalIsOpen) this.hideDeleteManifestModal();
|
56
|
+
this.props.setModalClosed({ id: MANAGE_MANIFEST_MODAL_ID });
|
57
57
|
};
|
58
58
|
|
59
|
+
showDeleteManifestModal = () =>
|
60
|
+
this.props.setModalOpen({ id: DELETE_MANIFEST_MODAL_ID });
|
61
|
+
|
62
|
+
hideDeleteManifestModal = () =>
|
63
|
+
this.props.setModalClosed({ id: DELETE_MANIFEST_MODAL_ID });
|
64
|
+
|
59
65
|
updateRepositoryUrl = (event) => {
|
60
66
|
this.setState({ redhat_repository_url: event.target.value });
|
61
67
|
};
|
@@ -82,13 +88,6 @@ class ManageManifestModal extends Component {
|
|
82
88
|
this.hideModal();
|
83
89
|
this.setState({ actionInProgress: true });
|
84
90
|
this.props.delete();
|
85
|
-
this.showDeleteManifestModal(false);
|
86
|
-
};
|
87
|
-
|
88
|
-
showDeleteManifestModal = (show) => {
|
89
|
-
this.setState({
|
90
|
-
showDeleteManifestModalDialog: show,
|
91
|
-
});
|
92
91
|
};
|
93
92
|
|
94
93
|
disabledTooltipText = () => {
|
@@ -107,6 +106,7 @@ class ManageManifestModal extends Component {
|
|
107
106
|
canImportManifest,
|
108
107
|
canDeleteManifest,
|
109
108
|
canEditOrganizations,
|
109
|
+
simpleContentAccess,
|
110
110
|
} = this.props;
|
111
111
|
|
112
112
|
const showRedHatProviderDetails = canEditOrganizations;
|
@@ -150,166 +150,177 @@ class ManageManifestModal extends Component {
|
|
150
150
|
};
|
151
151
|
|
152
152
|
return (
|
153
|
-
<
|
154
|
-
<
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
<h5>{__('Red Hat Provider Details')}</h5>
|
172
|
-
<hr />
|
173
|
-
<FormGroup>
|
174
|
-
<Col sm={3}>
|
175
|
-
<ControlLabel htmlFor="cdnUrl">
|
176
|
-
{__('Red Hat CDN URL')}
|
177
|
-
</ControlLabel>
|
178
|
-
</Col>
|
179
|
-
<Col sm={9}>
|
180
|
-
<FormControl
|
181
|
-
id="cdnUrl"
|
182
|
-
type="text"
|
183
|
-
defaultValue={this.state.redhat_repository_url || organization.redhat_repository_url || ''}
|
184
|
-
onBlur={this.updateRepositoryUrl}
|
185
|
-
/>
|
186
|
-
</Col>
|
187
|
-
</FormGroup>
|
188
|
-
<FormGroup>
|
189
|
-
<Col smOffset={3} sm={3}>
|
190
|
-
<Button onClick={this.saveOrganization} disabled={organization.loading}>
|
191
|
-
{organization.loading ? buttonLoading : __('Update')}
|
192
|
-
</Button>
|
193
|
-
</Col>
|
194
|
-
</FormGroup>
|
195
|
-
<br />
|
196
|
-
</React.Fragment>
|
197
|
-
}
|
198
|
-
{showSubscriptionManifest &&
|
199
|
-
<React.Fragment>
|
200
|
-
<h5>{__('Subscription Manifest')}</h5>
|
201
|
-
<hr />
|
202
|
-
|
203
|
-
<FormGroup>
|
204
|
-
<ControlLabel
|
205
|
-
className="col-sm-3 control-label"
|
206
|
-
htmlFor="usmaFile"
|
207
|
-
style={{ paddingTop: '0' }}
|
208
|
-
>
|
209
|
-
<OverlayTrigger
|
210
|
-
overlay={
|
211
|
-
<Tooltip id="usma-tooltip">
|
212
|
-
{__('Upstream Subscription Management Application')}
|
213
|
-
</Tooltip>
|
214
|
-
}
|
215
|
-
placement="bottom"
|
216
|
-
trigger={['hover', 'focus']}
|
217
|
-
rootClose={false}
|
218
|
-
>
|
219
|
-
<span>{__('USMA')}</span>
|
220
|
-
</OverlayTrigger>
|
221
|
-
</ControlLabel>
|
222
|
-
|
223
|
-
<Col sm={9} className="manifest-actions">
|
224
|
-
<Spinner loading={actionInProgress} inline />
|
225
|
-
|
226
|
-
{getManifestName()}
|
227
|
-
{canImportManifest &&
|
153
|
+
<ForemanModal id={MANAGE_MANIFEST_MODAL_ID} title={__('Manage Manifest')}>
|
154
|
+
<Tabs id="manifest-history-tabs">
|
155
|
+
{showManifestTab &&
|
156
|
+
<Tab eventKey={1} title={__('Manifest')}>
|
157
|
+
<Form className="form-horizontal">
|
158
|
+
{showRedHatProviderDetails &&
|
159
|
+
<React.Fragment>
|
160
|
+
<h5>{__('Red Hat Provider Details')}</h5>
|
161
|
+
<hr />
|
162
|
+
<FormGroup>
|
163
|
+
<Grid>
|
164
|
+
<Row>
|
165
|
+
<Col sm={4}>
|
166
|
+
<ControlLabel htmlFor="cdnUrl">
|
167
|
+
{__('Red Hat CDN URL')}
|
168
|
+
</ControlLabel>
|
169
|
+
</Col>
|
170
|
+
<Col sm={8}>
|
228
171
|
<FormControl
|
229
|
-
id="
|
230
|
-
type="
|
231
|
-
|
232
|
-
|
233
|
-
onChange={e => this.uploadManifest(e.target.files)}
|
172
|
+
id="cdnUrl"
|
173
|
+
type="text"
|
174
|
+
defaultValue={this.state.redhat_repository_url || organization.redhat_repository_url || ''}
|
175
|
+
onBlur={this.updateRepositoryUrl}
|
234
176
|
/>
|
235
|
-
|
236
|
-
|
177
|
+
</Col>
|
178
|
+
</Row>
|
179
|
+
</Grid>
|
180
|
+
</FormGroup>
|
181
|
+
<FormGroup>
|
182
|
+
<Grid>
|
183
|
+
<Row>
|
184
|
+
<Col smOffset={4} sm={4}>
|
185
|
+
<Button onClick={this.saveOrganization} disabled={organization.loading}>
|
186
|
+
{organization.loading ? buttonLoading : __('Update')}
|
187
|
+
</Button>
|
188
|
+
</Col>
|
189
|
+
</Row>
|
190
|
+
</Grid>
|
191
|
+
</FormGroup>
|
192
|
+
<br />
|
193
|
+
</React.Fragment>
|
194
|
+
}
|
195
|
+
{showSubscriptionManifest &&
|
196
|
+
<React.Fragment>
|
197
|
+
|
198
|
+
<FormGroup>
|
199
|
+
<Grid>
|
200
|
+
<h5>{__('Subscription Manifest')}</h5>
|
201
|
+
<hr />
|
202
|
+
<Row>
|
203
|
+
<Col sm={4}>
|
204
|
+
<ControlLabel
|
205
|
+
className="control-label"
|
206
|
+
htmlFor="usmaFile"
|
207
|
+
style={{ paddingTop: '0' }}
|
208
|
+
>
|
209
|
+
<OverlayTrigger
|
210
|
+
overlay={
|
211
|
+
<Tooltip id="usma-tooltip">
|
212
|
+
{__('Upstream Subscription Management Application')}
|
213
|
+
</Tooltip>
|
214
|
+
}
|
215
|
+
placement="bottom"
|
216
|
+
trigger={['hover', 'focus']}
|
217
|
+
rootClose={false}
|
218
|
+
>
|
219
|
+
<div>{__('USMA')}</div>
|
220
|
+
</OverlayTrigger>
|
221
|
+
</ControlLabel>
|
222
|
+
</Col>
|
223
|
+
<Col sm={8}>
|
224
|
+
{getManifestName()}
|
225
|
+
</Col>
|
226
|
+
</Row>
|
227
|
+
<Row>
|
228
|
+
<Col sm={4}>
|
229
|
+
<div>{__('Simple Content Access')}</div>
|
230
|
+
</Col>
|
231
|
+
<Col sm={8} className="manifest-actions">
|
232
|
+
<Spinner loading={actionInProgress} inline />
|
233
|
+
{simpleContentAccess ? __('Yes') : __('No')}
|
234
|
+
<OverlayTrigger
|
235
|
+
overlay={
|
236
|
+
<Tooltip id="sca-tooltip">
|
237
|
+
{__('When Simple Content Access is enabled, hosts can consume from all repositories in their Content View regardless of subscription status.')}
|
238
|
+
</Tooltip>
|
239
|
+
}
|
240
|
+
placement="bottom"
|
241
|
+
trigger={['hover', 'focus']}
|
242
|
+
rootClose={false}
|
243
|
+
>
|
244
|
+
<Icon type="pf" name="info" />
|
245
|
+
</OverlayTrigger>
|
237
246
|
{canImportManifest &&
|
238
|
-
<
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
disabled={!manifestExists(organization) ||
|
245
|
-
actionInProgress || disableManifestActions}
|
246
|
-
/>
|
247
|
-
}
|
248
|
-
{canDeleteManifest &&
|
249
|
-
<React.Fragment>
|
250
|
-
<TooltipButton
|
251
|
-
renderedButton={(
|
252
|
-
<Button
|
253
|
-
disabled={!manifestExists(organization) || actionInProgress}
|
254
|
-
bsStyle="danger"
|
255
|
-
onClick={() => this.showDeleteManifestModal(true)}
|
256
|
-
>
|
257
|
-
{__('Delete')}
|
258
|
-
</Button>
|
259
|
-
)}
|
260
|
-
|
261
|
-
tooltipId="delete-manifest-button-tooltip"
|
262
|
-
tooltipText={this.disabledTooltipText()}
|
263
|
-
tooltipPlacement="top"
|
264
|
-
|
265
|
-
/>
|
266
|
-
</React.Fragment>
|
267
|
-
}
|
268
|
-
</div>
|
269
|
-
|
270
|
-
<MessageDialog
|
271
|
-
show={this.state.showDeleteManifestModalDialog}
|
272
|
-
title={__('Confirm delete manifest')}
|
273
|
-
secondaryContent={
|
274
|
-
// eslint-disable-next-line react/no-danger
|
275
|
-
<p dangerouslySetInnerHTML={{
|
276
|
-
__html: DeleteManifestModalText,
|
277
|
-
}}
|
247
|
+
<FormControl
|
248
|
+
id="usmaFile"
|
249
|
+
type="file"
|
250
|
+
accept=".zip"
|
251
|
+
disabled={actionInProgress}
|
252
|
+
onChange={e => this.uploadManifest(e.target.files)}
|
278
253
|
/>
|
279
254
|
}
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
255
|
+
<div id="manifest-actions-row">
|
256
|
+
{canImportManifest &&
|
257
|
+
<TooltipButton
|
258
|
+
onClick={this.refreshManifest}
|
259
|
+
tooltipId="refresh-manifest-button-tooltip"
|
260
|
+
tooltipText={disabledReason}
|
261
|
+
tooltipPlacement="top"
|
262
|
+
title={__('Refresh')}
|
263
|
+
disabled={!manifestExists(organization) ||
|
264
|
+
actionInProgress || disableManifestActions}
|
265
|
+
/>
|
266
|
+
}
|
267
|
+
{canDeleteManifest &&
|
268
|
+
<React.Fragment>
|
269
|
+
<TooltipButton
|
270
|
+
renderedButton={(
|
271
|
+
<Button
|
272
|
+
disabled={!manifestExists(organization) || actionInProgress}
|
273
|
+
bsStyle="danger"
|
274
|
+
onClick={this.showDeleteManifestModal}
|
275
|
+
>
|
276
|
+
{__('Delete')}
|
277
|
+
</Button>
|
278
|
+
)}
|
279
|
+
|
280
|
+
tooltipId="delete-manifest-button-tooltip"
|
281
|
+
tooltipText={this.disabledTooltipText()}
|
282
|
+
tooltipPlacement="top"
|
283
|
+
|
284
|
+
/>
|
285
|
+
</React.Fragment>
|
286
|
+
}
|
287
|
+
</div>
|
288
|
+
<ForemanModal title={__('Confirm delete manifest')} id={DELETE_MANIFEST_MODAL_ID}>
|
289
|
+
<DeleteManifestModalText />
|
290
|
+
<ForemanModal.Footer>
|
291
|
+
<Button bsStyle="default" onClick={this.hideDeleteManifestModal}>
|
292
|
+
{__('Cancel')}
|
293
|
+
</Button>
|
294
|
+
<Button bsStyle="danger" onClick={this.deleteManifest}>
|
295
|
+
{__('Delete')}
|
296
|
+
</Button>
|
297
|
+
</ForemanModal.Footer>
|
298
|
+
</ForemanModal>
|
299
|
+
</Col>
|
300
|
+
</Row>
|
301
|
+
</Grid>
|
302
|
+
</FormGroup>
|
303
|
+
</React.Fragment>
|
304
|
+
}
|
305
|
+
</Form>
|
304
306
|
</Tab>
|
305
|
-
|
306
|
-
|
307
|
-
|
307
|
+
}
|
308
|
+
<Tab eventKey={2} title={__('Manifest History')}>
|
309
|
+
<LoadingState loading={manifestHistory.loading} loadingText={__('Loading')}>
|
310
|
+
<Table
|
311
|
+
rows={manifestHistory.results}
|
312
|
+
columns={columns}
|
313
|
+
emptyState={emptyStateData()}
|
314
|
+
/>
|
315
|
+
</LoadingState>
|
316
|
+
</Tab>
|
317
|
+
</Tabs>
|
318
|
+
<ForemanModal.Footer>
|
308
319
|
<Button bsStyle="primary" onClick={this.hideModal}>
|
309
320
|
{__('Close')}
|
310
321
|
</Button>
|
311
|
-
</
|
312
|
-
</
|
322
|
+
</ForemanModal.Footer>
|
323
|
+
</ForemanModal>
|
313
324
|
);
|
314
325
|
}
|
315
326
|
}
|
@@ -338,12 +349,14 @@ ManageManifestModal.propTypes = {
|
|
338
349
|
loadOrganization: PropTypes.func.isRequired,
|
339
350
|
saveOrganization: PropTypes.func.isRequired,
|
340
351
|
taskInProgress: PropTypes.bool.isRequired,
|
352
|
+
simpleContentAccess: PropTypes.bool,
|
341
353
|
manifestHistory: PropTypes.shape({
|
342
354
|
loading: PropTypes.bool,
|
343
355
|
results: PropTypes.array,
|
344
356
|
}).isRequired,
|
345
|
-
|
346
|
-
|
357
|
+
setModalClosed: PropTypes.func.isRequired,
|
358
|
+
setModalOpen: PropTypes.func.isRequired,
|
359
|
+
deleteManifestModalIsOpen: PropTypes.bool,
|
347
360
|
};
|
348
361
|
|
349
362
|
ManageManifestModal.defaultProps = {
|
@@ -352,7 +365,8 @@ ManageManifestModal.defaultProps = {
|
|
352
365
|
canImportManifest: false,
|
353
366
|
canDeleteManifest: false,
|
354
367
|
canEditOrganizations: false,
|
355
|
-
|
368
|
+
deleteManifestModalIsOpen: false,
|
369
|
+
simpleContentAccess: false,
|
356
370
|
};
|
357
371
|
|
358
372
|
export default ManageManifestModal;
|