katello 3.4.0.rc2 → 3.4.0

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.

Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/rhsm/candlepin_dynflow_proxy_controller.rb +43 -0
  3. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +20 -14
  4. data/app/controllers/katello/api/v2/content_views_controller.rb +2 -2
  5. data/app/controllers/katello/api/v2/errata_controller.rb +1 -0
  6. data/app/controllers/katello/api/v2/packages_controller.rb +6 -2
  7. data/app/lib/actions/candlepin/async_hypervisors.rb +22 -0
  8. data/app/lib/actions/candlepin/import_pool_handler.rb +19 -23
  9. data/app/lib/actions/katello/capsule_content/sync.rb +1 -0
  10. data/app/lib/actions/katello/host/hypervisors.rb +16 -4
  11. data/app/lib/actions/katello/host/hypervisors_update.rb +2 -2
  12. data/app/lib/actions/katello/host/upload_package_profile.rb +13 -6
  13. data/app/lib/actions/katello/repository/remove_content.rb +8 -8
  14. data/app/lib/actions/middleware/backend_services_check.rb +2 -2
  15. data/app/lib/katello/capsule_content.rb +6 -0
  16. data/app/lib/katello/resources/candlepin.rb +12 -7
  17. data/app/models/katello/concerns/organization_extensions.rb +4 -0
  18. data/app/models/katello/events/import_pool.rb +17 -0
  19. data/app/models/katello/glue/candlepin/owner.rb +4 -0
  20. data/app/models/katello/host/subscription_facet.rb +9 -2
  21. data/app/models/katello/ping.rb +4 -4
  22. data/app/models/katello/subscription_status.rb +5 -2
  23. data/app/services/cert/certs.rb +7 -0
  24. data/config/routes/api/rhsm.rb +4 -2
  25. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/views/activation-key-details.html +2 -1
  26. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/views/activation-key-host-collections-table.html +4 -6
  27. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/views/activation-key-info.html +2 -2
  28. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/new/views/activation-key-new.html +1 -1
  29. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-details.html +1 -0
  30. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-info.html +1 -1
  31. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/filters/views/filter-repositories.html +0 -1
  32. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/new/views/content-view-new.html +1 -1
  33. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/docker-tags/details/views/docker-tag-environments.html +4 -11
  34. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/gpg-keys/new/views/new-gpg-key.html +1 -1
  35. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/new/views/new-host-collection.html +1 -1
  36. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +1 -1
  37. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/views/product-details.html +1 -1
  38. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/new/new-sync-plan-modal.controller.js +46 -0
  39. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/new/product-form.controller.js +15 -2
  40. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/new/views/new-sync-plan-modal.html +18 -0
  41. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/new/views/product-new-form.html +40 -38
  42. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/products.routes.js +0 -19
  43. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/content-access-mode-banner.directive.js +22 -0
  44. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/details/views/subscription-details.html +2 -1
  45. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/manifest/views/manifest-import.html +1 -1
  46. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/manifest/views/manifest.html +2 -0
  47. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/views/content-access-mode-banner.html +5 -0
  48. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/details/views/sync-plan-info.html +0 -3
  49. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/new/new-sync-plan.controller.js +16 -24
  50. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/new/views/new-sync-plan-form.html +52 -48
  51. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/new/views/new-sync-plan.html +3 -1
  52. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/sync-plan-helper.service.js +66 -0
  53. data/lib/katello/engine.rb +10 -0
  54. data/lib/katello/params_parser_wrapper.rb +16 -0
  55. data/lib/katello/permissions/host_permissions.rb +7 -3
  56. data/lib/katello/plugin.rb +4 -4
  57. data/lib/katello/tasks/regenerate_ueber_certs.rake +1 -1
  58. data/lib/katello/tasks/repository.rake +23 -0
  59. data/lib/katello/version.rb +1 -1
  60. metadata +13 -5
  61. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/views/product-new-sync-plan.html +0 -2
@@ -40,15 +40,6 @@ angular.module('Bastion.products').config(['$stateProvider', function ($statePro
40
40
  ncyBreadcrumb: {
41
41
  label: "{{ 'New Product' | translate }}"
42
42
  }
43
- })
44
- .state('products.new.sync-plan', {
45
- url: '/new/sync-plan',
46
- permission: 'create_sync_plans',
47
- controller: 'NewSyncPlanController',
48
- templateUrl: 'sync-plans/new/views/new-sync-plan-form.html',
49
- ncyBreadcrumb: {
50
- label: "{{ 'New Sync Plan' | translate }}"
51
- }
52
43
  });
53
44
 
54
45
  $stateProvider.state("product-discovery", {
@@ -93,16 +84,6 @@ angular.module('Bastion.products').config(['$stateProvider', function ($statePro
93
84
  label: "{{ product.name }}",
94
85
  parent: 'products'
95
86
  }
96
- })
97
- .state('product.new-sync-plan', {
98
- url: '/sync-plan/new',
99
- permission: 'create_sync_plans',
100
- controller: 'NewSyncPlanController',
101
- templateUrl: 'products/details/views/product-new-sync-plan.html',
102
- ncyBreadcrumb: {
103
- label: "{{ 'New Sync Plan' | translate}}",
104
- parent: 'product.info'
105
- }
106
87
  });
107
88
 
108
89
  $stateProvider.state('product.tasks', {
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @ngdoc directive
3
+ * @name Bastion.subscriptions:contentAccessModeBanner
4
+ *
5
+ * @requires contentAccessMode
6
+ *
7
+ * @description
8
+ * Component for showing information about content access mode (whether content is
9
+ * allowed with or without a subscription)
10
+ */
11
+ angular.module('Bastion.subscriptions').directive('contentAccessModeBanner',
12
+ ['contentAccessMode',
13
+ function (contentAccessMode) {
14
+ return {
15
+ restrict: 'AE',
16
+ controller: ['$scope', function ($scope) {
17
+ $scope.contentAccessMode = contentAccessMode;
18
+ }],
19
+ templateUrl: 'subscriptions/views/content-access-mode-banner.html'
20
+ };
21
+ }
22
+ ]);
@@ -6,6 +6,7 @@
6
6
  </header>
7
7
 
8
8
  <nav data-block="navigation">
9
+ <div content-access-mode-banner></div>
9
10
  <ul class="nav nav-tabs details-nav">
10
11
  <li ng-class="{active: isState('subscription.info')}">
11
12
  <a translate ui-sref="subscription.info({subscriptionId: subscription.id})">
@@ -42,4 +43,4 @@
42
43
  <div data-block="content">
43
44
  <section ui-view></section>
44
45
  </div>
45
- </div>
46
+ </div>
@@ -73,7 +73,7 @@
73
73
  </div>
74
74
 
75
75
  </form>
76
-
76
+
77
77
  <div bst-alert="info" ng-if="details.virt_who">
78
78
  <span translate>
79
79
  The uploaded manifest contains subscriptions that require the use of virt-who. Learn how to configure and use this tool in the <a href="https://access.redhat.com/documentation/en/red-hat-satellite/6.2/single/virtual-instances-guide/">Virtual Instances Guide</a>.
@@ -4,6 +4,8 @@
4
4
  </header>
5
5
 
6
6
  <nav data-block="navigation">
7
+ <div content-access-mode-banner></div>
8
+
7
9
  <ul class="nav nav-tabs details-nav" role="menu">
8
10
  <li role="menuitem" ui-sref-active="active">
9
11
  <a ui-sref="subscriptions-manifest.details">
@@ -0,0 +1,5 @@
1
+ <div bst-alert="info" ng-show="contentAccessMode === 'org_environment'">
2
+ <span translate>
3
+ Access to repositories is unrestricted in this organization. Hosts can consume all repositories available in the Content View they are registered to, regardless of subscription status.
4
+ </span>
5
+ </div>
@@ -63,9 +63,6 @@
63
63
  on-save="save(syncPlan)">
64
64
  </dd>
65
65
 
66
- <dt translate>Interval</dt>
67
- <dd>{{ syncPlan.interval }}</dd>
68
-
69
66
  <dt translate>Products</dt>
70
67
  <dd>
71
68
  <a ui-sref="sync-plan.products.list">
@@ -5,51 +5,43 @@
5
5
  * @requires $scope
6
6
  * @requires translate
7
7
  * @requires SyncPlan
8
+ * @requires SyncPlanHelper
9
+ * @requires GlobalNotification
8
10
  *
9
11
  * @description
10
12
  * Controls the creation of an empty SyncPlan object for use by sub-controllers.
11
13
  */
12
14
  angular.module('Bastion.sync-plans').controller('NewSyncPlanController',
13
- ['$scope', 'translate', 'SyncPlan', 'GlobalNotification',
14
- function ($scope, translate, SyncPlan, GlobalNotification) {
15
- $scope.intervals = [
16
- {id: 'hourly', value: translate('hourly')},
17
- {id: 'daily', value: translate('daily')},
18
- {id: 'weekly', value: translate('weekly')}
19
- ];
15
+ ['$scope', '$rootScope', 'translate', 'SyncPlan', 'SyncPlanHelper', 'GlobalNotification',
16
+ function ($scope, $rootScope, translate, SyncPlan, SyncPlanHelper, GlobalNotification) {
17
+ $scope.intervals = SyncPlanHelper.getIntervals();
20
18
 
21
19
  $scope.syncPlan = new SyncPlan();
22
20
  $scope.syncPlan.interval = $scope.intervals[0].id;
23
21
 
24
22
  function success(syncPlan) {
25
23
  $scope.working = false;
24
+ $scope.$state.go('sync-plan.info', {syncPlanId: syncPlan.id});
26
25
  GlobalNotification.setSuccessMessage(translate('New sync plan successfully created.'));
27
- if ($scope.product) {
28
- $scope.product['sync_plan_id'] = syncPlan.id;
29
- $scope.$state.go('product.info', {productId: $scope.product.id});
30
- } else {
31
- $scope.$state.go('sync-plan.info', {syncPlanId: syncPlan.id});
32
- }
33
26
  }
34
27
 
35
28
  function error(response) {
36
- $scope.working = false;
29
+ var form = SyncPlanHelper.getForm();
30
+
37
31
  angular.forEach(response.data.errors, function (errors, field) {
38
- $scope.syncPlanForm[field].$setValidity('server', false);
39
- $scope.syncPlanForm[field].$error.messages = errors;
32
+ form[field].$setValidity('server', false);
33
+ form[field].$error.messages = errors;
40
34
  });
35
+
36
+ $scope.working = false;
41
37
  }
42
38
 
43
39
  $scope.createSyncPlan = function (syncPlan) {
44
- var GMT_OFFSET_MILLISECONDS = syncPlan.startDate.getTimezoneOffset() * 60000,
45
- syncDate = new Date(syncPlan.startDate.getTime() + GMT_OFFSET_MILLISECONDS),
46
- syncTime = new Date(syncPlan.startTime || new Date());
47
- syncDate.setHours(syncTime.getHours());
48
- syncDate.setMinutes(syncTime.getMinutes());
49
- syncDate.setSeconds(0);
40
+ SyncPlanHelper.createSyncPlan(syncPlan, success, error);
41
+ };
50
42
 
51
- syncPlan['sync_date'] = syncDate.toString();
52
- syncPlan.$save(success, error);
43
+ $scope.setForm = function (form) {
44
+ SyncPlanHelper.setForm(form);
53
45
  };
54
46
  }]
55
47
  );
@@ -1,65 +1,69 @@
1
- <form ng-controller="NewSyncPlanController" name="syncPlanForm" class="col-sm-5" novalidate role="form">
2
- <div bst-form-group label="{{ 'Name' | translate }}">
3
- <input id="name"
4
- name="name"
5
- ng-model="syncPlan.name"
6
- type="text"
7
- tabindex="1"
8
- autofocus
9
- required/>
10
- </div>
1
+ <div ng-form name="syncPlanForm" novalidate role="form">
2
+ <div bst-form-group label="{{ 'Name' | translate }}">
3
+ <input id="name"
4
+ name="name"
5
+ ng-model="syncPlan.name"
6
+ type="text"
7
+ tabindex="1"
8
+ autofocus
9
+ required/>
10
+ </div>
11
11
 
12
- <div bst-form-group label="{{ 'Description' | translate }}">
12
+ <div bst-form-group label="{{ 'Description' | translate }}">
13
13
  <textarea id="description"
14
14
  name="description"
15
15
  ng-model="syncPlan.description"
16
16
  tabindex="2">
17
17
  </textarea>
18
- </div>
18
+ </div>
19
19
 
20
- <div bst-form-group label="{{ 'Interval' | translate }}">
21
- <select id="interval"
22
- name="interval"
23
- ng-model="syncPlan.interval"
24
- ng-options="interval.id as interval.value for interval in intervals"
25
- tabindex="3"
26
- required>
20
+ <div bst-form-group label="{{ 'Interval' | translate }}">
21
+ <select id="interval"
22
+ name="interval"
23
+ ng-model="syncPlan.interval"
24
+ ng-options="interval.id as interval.value for interval in intervals"
25
+ tabindex="3"
26
+ required>
27
27
  <option value="" translate>-- select an interval --</option>
28
- </select>
29
- </div>
28
+ </select>
29
+ </div>
30
30
 
31
- <div bst-form-group label="{{ 'Start Date' | translate }}">
32
- <div class="input-group">
33
- <input type="text" uib-datepicker-popup
34
- id="startDate"
35
- name="startDate"
36
- is-open="isOpen"
37
- ng-model="syncPlan.startDate"
38
- show-weeks="false"
39
- tabindex="4"
40
- required/>
31
+ <div bst-form-group label="{{ 'Start Date' | translate }}">
32
+ <div class="input-group">
33
+ <input type="text" uib-datepicker-popup
34
+ id="startDate"
35
+ name="startDate"
36
+ is-open="isOpen"
37
+ ng-model="syncPlan.startDate"
38
+ show-weeks="false"
39
+ tabindex="4"
40
+ required/>
41
41
 
42
42
  <span class="input-group-btn">
43
43
  <button type="button" class="btn btn-default" ng-click="isOpen = !isOpen">
44
44
  <i class="fa fa-calendar"></i>
45
45
  </button>
46
46
  </span>
47
- </div>
48
- </div>
47
+ </div>
48
+ </div>
49
49
 
50
- <div bst-form-group label="{{ 'Start Time' | translate }}">
51
- <div uib-timepicker show-meridian="false"
52
- id="startTime"
53
- name="startTime"
54
- ng-model="syncPlan.startTime"
55
- tabindex="5">
56
- </div>
57
- <p class="help-block" translate>The time the sync should happen in your current time zone.</p>
58
- </div>
50
+ <div bst-form-group label="{{ 'Start Time' | translate }}">
51
+ <div uib-timepicker show-meridian="false"
52
+ id="startTime"
53
+ name="startTime"
54
+ ng-model="syncPlan.startTime"
55
+ tabindex="5">
56
+ </div>
57
+ <p class="help-block" translate>The time the sync should happen in your current time zone.</p>
58
+ </div>
59
59
 
60
- <div bst-form-buttons
61
- on-cancel="transitionBack()"
62
- on-save="createSyncPlan(syncPlan)"
63
- working="working">
64
- </div>
65
- </form>
60
+ <div ng-init="setForm(syncPlanForm);"></div>
61
+
62
+ <div ng-show="isState('sync-plans.new')">
63
+ <div bst-form-buttons
64
+ on-cancel="transitionBack()"
65
+ on-save="createSyncPlan(syncPlan)"
66
+ working="working">
67
+ </div>
68
+ </div>
69
+ </div>
@@ -6,6 +6,8 @@
6
6
  </header>
7
7
 
8
8
  <div data-block="content">
9
- <div ng-include="'sync-plans/new/views/new-sync-plan-form.html'"></div>
9
+ <div class="row">
10
+ <div class="col-sm-5" ng-include="'sync-plans/new/views/new-sync-plan-form.html'"></div>
11
+ </div>
10
12
  </div>
11
13
  </div>
@@ -0,0 +1,66 @@
1
+ (function () {
2
+
3
+ /**
4
+ * @ngdoc service
5
+ * @name Bastion.sync-plans.service:SyncPlanHelper
6
+ *
7
+ * @description
8
+ * Provides a helper service for Sync Plans
9
+ *
10
+ */
11
+ function SyncPlanHelper(translate) {
12
+
13
+ /**
14
+ * Get the set form. Allows the sharing of form data across controllers
15
+ *
16
+ * @param form the form to set
17
+ */
18
+ this.setForm = function (form) {
19
+ this.form = form;
20
+ };
21
+
22
+ /**
23
+ * Set the form. Allows the sharing of form data across controllers
24
+ *
25
+ * @returns {form|*} the stored form
26
+ */
27
+ this.getForm = function () {
28
+ return this.form;
29
+ };
30
+
31
+ /**
32
+ * Returns the valid sync plan intervals.
33
+ *
34
+ * @returns {{id: string, value: *}[]}
35
+ */
36
+ this.getIntervals = function () {
37
+ return [
38
+ {id: 'hourly', value: translate('hourly')},
39
+ {id: 'daily', value: translate('daily')},
40
+ {id: 'weekly', value: translate('weekly')}
41
+ ];
42
+
43
+ };
44
+
45
+ /**
46
+ * Create a sync plan, including setting the dates correctly.
47
+ *
48
+ * @returns $resource sync plan
49
+ */
50
+ this.createSyncPlan = function (syncPlan, success, error) {
51
+ var GMT_OFFSET_MILLISECONDS = syncPlan.startDate.getTimezoneOffset() * 60000,
52
+ syncDate = new Date(syncPlan.startDate.getTime() + GMT_OFFSET_MILLISECONDS),
53
+ syncTime = new Date(syncPlan.startTime || new Date());
54
+ syncDate.setHours(syncTime.getHours());
55
+ syncDate.setMinutes(syncTime.getMinutes());
56
+ syncDate.setSeconds(0);
57
+
58
+ syncPlan['sync_date'] = syncDate.toString();
59
+ syncPlan.$save(success, error);
60
+ return syncPlan;
61
+ };
62
+ }
63
+
64
+ angular.module('Bastion.sync-plans').service('SyncPlanHelper', SyncPlanHelper);
65
+ SyncPlanHelper.$inject = ['translate'];
66
+ })();
@@ -2,6 +2,15 @@ module Katello
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Katello
4
4
 
5
+ initializer 'katello.selective_params_parser', :before => :build_middleware_stack do |app|
6
+ require 'katello/params_parser_wrapper'
7
+ app.middleware.swap(
8
+ ActionDispatch::ParamsParser,
9
+ Katello::ParamsParserWrapper,
10
+ ->(env) { env['PATH_INFO'] =~ /consumers/ && env['PATH_INFO'] =~ /profile|packages/ }
11
+ )
12
+ end
13
+
5
14
  initializer 'katello.mount_engine', :after => :build_middleware_stack do |app|
6
15
  app.routes_reloader.paths << "#{Katello::Engine.root}/config/routes/mount_engine.rb"
7
16
  end
@@ -241,6 +250,7 @@ module Katello
241
250
  end
242
251
 
243
252
  Katello::EventQueue.register_event(Katello::Events::ImportHostApplicability::EVENT_TYPE, Katello::Events::ImportHostApplicability)
253
+ Katello::EventQueue.register_event(Katello::Events::ImportPool::EVENT_TYPE, Katello::Events::ImportPool)
244
254
 
245
255
  ::HostsController.class_eval do
246
256
  helper Katello::Concerns::HostsAndHostgroupsHelperExtensions
@@ -0,0 +1,16 @@
1
+ module Katello
2
+ class ParamsParserWrapper < ActionDispatch::ParamsParser
3
+ def initialize(app, excludes)
4
+ @exclude = excludes
5
+ super(app)
6
+ end
7
+
8
+ def call(env)
9
+ if @exclude && @exclude.call(env)
10
+ @app.call(env)
11
+ else
12
+ super(env)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -24,10 +24,13 @@ Foreman::AccessControl.permission(:edit_hosts).actions.concat [
24
24
  'katello/api/v2/hosts_bulk_actions/auto_attach',
25
25
  'katello/api/v2/hosts_bulk_actions/content_overrides',
26
26
  'katello/api/v2/hosts_bulk_actions/environment_content_view',
27
- 'katello/api/rhsm/candlepin_proxies/upload_package_profile',
27
+ 'katello/api/rhsm/candlepin_dynflow_proxy/upload_package_profile',
28
28
  'katello/api/rhsm/candlepin_proxies/regenerate_identity_certificates',
29
29
  'katello/api/rhsm/candlepin_proxies/hypervisors_update',
30
- 'katello/api/rhsm/candlepin_proxies/upload_tracer_profile'
30
+ 'katello/api/rhsm/candlepin_proxies/async_hypervisors_update',
31
+ 'katello/api/rhsm/candlepin_proxies/upload_tracer_profile',
32
+ 'katello/remote_execution/new',
33
+ 'katello/remote_execution/create'
31
34
  ]
32
35
 
33
36
  Foreman::AccessControl.permission(:view_hosts).actions.concat [
@@ -54,5 +57,6 @@ Foreman::AccessControl.permission(:create_hosts).actions.concat [
54
57
  'katello/api/v2/host_subscriptions/create',
55
58
  'katello/api/rhsm/candlepin_proxies/consumer_create',
56
59
  'katello/api/rhsm/candlepin_proxies/consumer_show',
57
- 'katello/api/rhsm/candlepin_proxies/hypervisors_update'
60
+ 'katello/api/rhsm/candlepin_proxies/hypervisors_update',
61
+ 'katello/api/rhsm/candlepin_proxies/async_hypervisors_update'
58
62
  ]
@@ -244,13 +244,13 @@ Foreman::Plugin.register :katello do
244
244
 
245
245
  add_controller_action_scope(HostsController, :index) do |base_scope|
246
246
  base_scope
247
- .includes(:content_view, :lifecycle_environment, :subscription_facet, :applicable_errata)
248
- .includes(content_facet: [:bound_repositories, :applicable_errata, :content_view, :lifecycle_environment])
247
+ .preload(:content_view, :lifecycle_environment, :subscription_facet, :applicable_errata)
248
+ .preload(content_facet: [:bound_repositories, :applicable_errata, :content_view, :lifecycle_environment])
249
249
  end
250
250
 
251
251
  add_controller_action_scope(Api::V2::HostsController, :index) do |base_scope|
252
252
  base_scope
253
- .includes(:content_view, :lifecycle_environment, :subscription_facet, :applicable_errata)
254
- .includes(content_facet: [:bound_repositories, :applicable_errata, :content_view, :lifecycle_environment])
253
+ .preload(:content_view, :lifecycle_environment, :subscription_facet, :applicable_errata)
254
+ .preload(content_facet: [:bound_repositories, :applicable_errata, :content_view, :lifecycle_environment])
255
255
  end
256
256
  end