katello 3.7.0 → 3.7.1

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/common/index.js +1 -0
  3. data/app/assets/javascripts/katello/sync_management/index.js +1 -0
  4. data/app/controllers/katello/api/v2/host_packages_controller.rb +1 -5
  5. data/app/controllers/katello/remote_execution_controller.rb +6 -6
  6. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +37 -9
  7. data/app/lib/actions/katello/host/hypervisors_update.rb +82 -22
  8. data/app/lib/actions/pulp/consumer/abstract_content_action.rb +12 -0
  9. data/app/lib/actions/pulp/consumer/content_install.rb +1 -1
  10. data/app/lib/actions/pulp/consumer/content_uninstall.rb +1 -1
  11. data/app/lib/actions/pulp/consumer/content_update.rb +1 -1
  12. data/app/models/katello/concerns/subscription_facet_host_extensions.rb +1 -1
  13. data/app/models/katello/content_view.rb +12 -4
  14. data/app/models/katello/glue/candlepin/pool.rb +11 -11
  15. data/app/models/katello/host/content_facet.rb +2 -1
  16. data/app/models/katello/rpm.rb +14 -6
  17. data/app/models/katello/subscription_status.rb +1 -1
  18. data/app/services/katello/candlepin/consumer.rb +8 -0
  19. data/app/views/overrides/activation_keys/_host_environment_select.html.erb +2 -3
  20. data/config/routes.rb +1 -0
  21. data/db/migrate/20180612163403_add_foreign_key_to_hypervisor_id.rb +3 -0
  22. data/db/seeds.d/75-job_templates.rb +5 -2
  23. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-repository-sets-modal.controller.js +4 -3
  24. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-subscriptions-modal.controller.js +4 -1
  25. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-installed.controller.js +1 -1
  26. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/views/discovery-create.html +1 -1
  27. data/engines/bastion_katello/app/assets/stylesheets/bastion_katello/bastion_katello.scss +5 -0
  28. data/lib/katello/tasks/clean_backend_objects.rake +12 -3
  29. data/lib/katello/version.rb +1 -1
  30. data/package.json +10 -7
  31. data/webpack/__mocks__/foremanReact/redux.js +3 -0
  32. data/webpack/__mocks__/foremanReact/redux/actions/toasts.js +2 -0
  33. data/webpack/components/Search/Search.test.js +3 -1
  34. data/webpack/components/SelectOrg/SelectOrg.scss +3 -0
  35. data/webpack/components/SelectOrg/SelectOrgAction.js +41 -0
  36. data/webpack/components/SelectOrg/SelectOrgReducer.js +33 -0
  37. data/webpack/components/SelectOrg/SetOrganization.js +116 -0
  38. data/webpack/components/WithOrganization/withOrganization.js +28 -0
  39. data/webpack/containers/Application/config.js +9 -2
  40. data/webpack/containers/Application/index.js +4 -2
  41. data/webpack/global_test_setup.js +6 -0
  42. data/webpack/helpers/caret.js +6 -0
  43. data/webpack/move_to_foreman/components/common/{emptyState → EmptyState}/index.js +16 -3
  44. data/webpack/move_to_foreman/components/common/table/components/Table.js +1 -1
  45. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/CollapseSubscriptionGroupButton.test.js.snap +2 -2
  46. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionCell.test.js.snap +1 -1
  47. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionHeaderCell.test.js.snap +1 -1
  48. data/webpack/move_to_pf/LoadingState/LoadingState.js +27 -14
  49. data/webpack/move_to_pf/LoadingState/LoadingState.test.js +8 -4
  50. data/webpack/move_to_pf/Select/Select.js +40 -0
  51. data/webpack/move_to_pf/react-bootstrap-select/index.js +12 -1
  52. data/webpack/redux/actions/RedHatRepositories/enabled.js +0 -1
  53. data/webpack/redux/actions/RedHatRepositories/helpers.js +5 -5
  54. data/webpack/redux/consts.js +6 -0
  55. data/webpack/redux/reducers/index.js +2 -0
  56. data/webpack/scenes/Products/ProductActions.js +24 -0
  57. data/webpack/scenes/Products/ProductConstants.js +3 -0
  58. data/webpack/scenes/Products/__tests__/ProductActions.test.js +40 -0
  59. data/webpack/scenes/Products/__tests__/products.fixtures.js +90 -0
  60. data/webpack/scenes/RedHatRepositories/components/EnabledRepository.js +14 -23
  61. data/webpack/scenes/RedHatRepositories/components/EnabledRepositoryContent.js +34 -0
  62. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepository.js +1 -1
  63. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +1 -0
  64. data/webpack/scenes/RedHatRepositories/components/__tests__/EnabledRepository.test.js +36 -0
  65. data/webpack/scenes/RedHatRepositories/components/__tests__/EnabledRepositoryContent.test.js +27 -0
  66. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/EnabledRepository.test.js.snap +25 -0
  67. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/EnabledRepositoryContent.test.js.snap +47 -0
  68. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/RecommendedRepositorySetsToggler.test.js.snap +3 -1
  69. data/webpack/scenes/RedHatRepositories/index.js +7 -3
  70. data/webpack/scenes/RedHatRepositories/index.scss +1 -0
  71. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailActions.js +1 -1
  72. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailEnabledProducts.js +54 -0
  73. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProduct.js +29 -0
  74. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailReducer.js +29 -0
  75. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +67 -22
  76. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.scss +9 -0
  77. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailEnabledProducts.test.js +18 -0
  78. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailProduct.test.js +13 -0
  79. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetails.test.js +6 -0
  80. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailEnabledProducts.test.js.snap +45 -0
  81. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailProduct.test.js.snap +67 -0
  82. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +497 -410
  83. data/webpack/scenes/Subscriptions/Details/__tests__/subscriptionDetails.fixtures.js +4 -0
  84. data/webpack/scenes/Subscriptions/Details/index.js +3 -1
  85. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +78 -34
  86. data/webpack/scenes/Subscriptions/Manifest/ManifestHistoryReducer.js +8 -0
  87. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManageManifestModal.test.js +3 -0
  88. data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +34 -7
  89. data/webpack/scenes/Subscriptions/Manifest/index.js +1 -0
  90. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +1 -0
  91. data/webpack/scenes/Subscriptions/SubscriptionHelpers.js +3 -0
  92. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +6 -2
  93. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +31 -36
  94. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +2 -7
  95. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsPage.test.js +1 -1
  96. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +3 -6
  97. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +2 -0
  98. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +14 -2
  99. data/webpack/scenes/Subscriptions/__tests__/subscriptions.fixtures.js +4 -3
  100. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/EntitlementsInlineEditFormatter.js +8 -5
  101. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js +29 -19
  102. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableHelpers.js +9 -2
  103. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableSchema.js +2 -2
  104. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/EntitlementsInlineEditFormatter.test.js +110 -0
  105. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/SubscriptionsTable.test.js +15 -3
  106. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/EntitlementsInlineEditFormatter.test.js.snap +228 -0
  107. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +54 -21
  108. data/webpack/scenes/Subscriptions/index.js +1 -0
  109. data/webpack/scenes/Tasks/helpers.js +52 -0
  110. data/webpack/services/api/index.js +17 -1
  111. data/webpack/test_setup.js +2 -0
  112. metadata +31 -4
  113. data/config/katello.yaml +0 -89
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8fac07da0f8761539cf0d1277ef31e4afd4252e7
4
- data.tar.gz: 0c327b63c0b1ea5296657f5551e80e61c98f84fd
3
+ metadata.gz: d88404b2afad190e4d14c345ac95118fbf2f8f44
4
+ data.tar.gz: 2f5cb4dfb3a91dd1733bc84866d303131ce96546
5
5
  SHA512:
6
- metadata.gz: 0fa3348cfe3b738493a89038154f305bf1ba9ecb142c89e23851049f4d548e50bcdaeb564ed6bc7132e227cb54975df908f1b0114efc521b8c73e55e131c2924
7
- data.tar.gz: '0941f97d419cea37695d53344727dfd59c8bae0104fa27ffe42bfcbb031dbdba8d029ab6b428383f5d494a1f74a426911685d39c3816bddc100787c786f17e43'
6
+ metadata.gz: af4305e274f7c50eff1aa319b28d0e9f5a678ac4a09436e1a6ad8fe629749e486758b19ff50b624f6283767717d717003e89bbc471e91fadc6674b7b1738c791
7
+ data.tar.gz: 23365d77760637b47a6f4ca0a5234702f254f979a464d5f115e778551553958f73e22e79ffa49a5ca19d0d0c9fe17767147ef716ba78a17e937c61c32ac31b6a
@@ -1,3 +1,4 @@
1
+ //= require bastion/lodash/lodash
1
2
  //= require "katello/common/katello.global"
2
3
  //= require "katello/common/katello.common.js"
3
4
  //= require "katello/common/katello"
@@ -1,2 +1,3 @@
1
1
  //= require "katello/jquery.treeTable"
2
+ //= require "katello/common/katello.common.js"
2
3
  //= require "katello/sync_management/sync_management"
@@ -102,13 +102,9 @@ module Katello
102
102
  @host = resource_finder(::Host::Managed.authorized(:view_hosts, ::Host::Managed), params[:host_id])
103
103
  end
104
104
 
105
- def valid_package_name?(package_name)
106
- package_name =~ /^[a-zA-Z0-9\-\.\_\+\,]+$/
107
- end
108
-
109
105
  def validate_package_list_format(packages)
110
106
  packages.each do |package|
111
- if !valid_package_name?(package) && !package.is_a?(Hash)
107
+ unless package.is_a?(String) && ::Katello::Util::Package.valid_package_name_format(package).nil?
112
108
  fail HttpErrors::BadRequest, _("%s is not a valid package name") % package
113
109
  end
114
110
  end
@@ -15,6 +15,12 @@ module Katello
15
15
  end
16
16
  end
17
17
 
18
+ # to overcome the isolated namespace engine difficulties with paths
19
+ helper Rails.application.routes.url_helpers
20
+ def _routes
21
+ Rails.application.routes
22
+ end
23
+
18
24
  private
19
25
 
20
26
  def prepare_composer
@@ -43,12 +49,6 @@ module Katello
43
49
  # getting packageInstall from UI, translating to 'katello_package_install' feature
44
50
  "katello_#{params[:remote_action].underscore}"
45
51
  end
46
-
47
- # to overcome the isolated namespace engine difficulties with paths
48
- helper Rails.application.routes.url_helpers
49
- def _routes
50
- Rails.application.routes
51
- end
52
52
  end
53
53
  else
54
54
  class RemoteExecutionController < ApplicationController
@@ -72,6 +72,12 @@ module Katello
72
72
  return selected_host_group.content_view if selected_host_group.present?
73
73
  end
74
74
 
75
+ def fetch_content_source(host, options = {})
76
+ return host.content_source if host.content_source.present?
77
+ selected_host_group = options.fetch(:selected_host_group, nil)
78
+ return selected_host_group.content_source if selected_host_group.present?
79
+ end
80
+
75
81
  def accessible_lifecycle_environments(org, host)
76
82
  selected = host.lifecycle_environment
77
83
  envs = org.kt_environments.readable
@@ -97,24 +103,28 @@ module Katello
97
103
  end
98
104
  end
99
105
 
100
- def lifecycle_environment_options(host, options = {})
106
+ # Generic method to provide a list of options in the UI
107
+ def content_options(host, selected_id, object_type, options = {})
101
108
  include_blank = options.fetch(:include_blank, nil)
102
109
  include_blank = '<option></option>' if include_blank == true #check for true specifically
103
-
104
- selected_id = fetch_lifecycle_environment(host, options).try(:id)
105
110
  orgs = relevant_organizations(host)
106
111
  all_options = []
107
112
  orgs.each do |org|
108
- env_options = ""
109
- accessible_lifecycle_environments(org, host).each do |env|
110
- selected = selected_id == env.id ? 'selected' : ''
111
- env_options << %(<option value="#{env.id}" class="kt-env" #{selected}>#{h(env.name)}</option>)
113
+ content_object_options = ""
114
+ accessible_content_objects = if object_type == :lifecycle_environment
115
+ accessible_lifecycle_environments(org, host)
116
+ elsif object_type == :content_source
117
+ accessible_content_proxies(host)
118
+ end
119
+ accessible_content_objects.each do |content_object|
120
+ selected = selected_id == content_object.id ? 'selected' : ''
121
+ content_object_options << %(<option value="#{content_object.id}" class="kt-env" #{selected}>#{h(content_object.name)}</option>)
112
122
  end
113
123
 
114
124
  if orgs.count > 1
115
- all_options << %(<optgroup label="#{org.name}">#{env_options}</optgroup>)
125
+ all_options << %(<optgroup label="#{org.name}">#{content_object_options}</optgroup>)
116
126
  else
117
- all_options << env_options
127
+ all_options << content_object_options
118
128
  end
119
129
  end
120
130
 
@@ -123,6 +133,24 @@ module Katello
123
133
  all_options.html_safe
124
134
  end
125
135
 
136
+ def lifecycle_environment_options(host, options = {})
137
+ content_options(
138
+ host,
139
+ fetch_lifecycle_environment(host, options).try(:id),
140
+ :lifecycle_environment,
141
+ options
142
+ )
143
+ end
144
+
145
+ def content_source_options(host, options = {})
146
+ content_options(
147
+ host,
148
+ fetch_content_source(host, options).try(:id),
149
+ :content_source,
150
+ options
151
+ )
152
+ end
153
+
126
154
  def content_views_for_host(host, options)
127
155
  include_blank = options.fetch(:include_blank, nil)
128
156
  if include_blank == true #check for true specifically
@@ -13,37 +13,86 @@ module Actions
13
13
  end
14
14
 
15
15
  def finalize
16
- hypervisors = input[:hypervisors]
16
+ @hypervisors = input[:hypervisors]
17
+ return unless @hypervisors
17
18
 
18
- if hypervisors
19
- User.as_anonymous_admin do
20
- hypervisors.each { |hypervisor| update_or_create_hypervisor(hypervisor) }
19
+ User.as_anonymous_admin do
20
+ load_resources
21
+
22
+ @hosts.each do |uuid, host|
23
+ update_subscription_facet(uuid, host)
21
24
  end
22
25
  end
23
26
  end
24
27
 
25
- def update_or_create_hypervisor(hypervisor_json)
26
- organization = ::Organization.find_by(:label => hypervisor_json[:organization_label])
28
+ # Loads all resources needed for refreshing subscription facet
29
+ def load_resources
30
+ @organizations = ::Organization.where(label: hypervisors_field(:organization_label)).map { |org| [org.label, org] }.to_h
31
+ @hosts = {}
32
+
33
+ load_hosts_by_uuid
34
+ load_hosts_by_duplicate_name
35
+ create_missing_hosts
36
+
37
+ candlepin_data = ::Katello::Resources::Candlepin::Consumer.get(uuid: @hosts.keys)
38
+ @candlepin_attributes = candlepin_data.map { |consumer| [consumer[:uuid], consumer] }.to_h
39
+ end
40
+
41
+ def load_hosts_by_uuid
42
+ hosts_by_uuid = ::Host.eager_load(:subscription_facet).where(katello_subscription_facets: { uuid: hypervisors_field(:uuid) })
43
+ @hosts.merge(hosts_by_uuid.map { |host| [host.subscription_facet.uuid, host] }.to_h)
44
+ end
45
+
46
+ def load_hosts_by_duplicate_name
47
+ duplicate_names, duplicate_name_orgs = generate_duplicates_list
48
+
49
+ hosts_by_dup_name = ::Host.preload(:subscription_facet).where(name: duplicate_names.keys)
50
+
51
+ hosts_by_dup_name.each do |host|
52
+ validate_host_organization(host, duplicate_name_orgs[host.name].try(:id))
53
+ end
54
+
55
+ @hosts.merge!(hosts_by_dup_name.map { |host| [duplicate_names[host.name], host] }.to_h)
56
+ end
57
+
58
+ def create_missing_hosts
59
+ # remaining hypervisors
60
+ @hypervisors.each do |hypervisor|
61
+ next if @hosts.key?(hypervisor[:uuid])
62
+ duplicate_name, org = duplicate_name(hypervisor)
63
+ @hosts[hypervisor[:uuid]] = create_host_for_hypervisor(duplicate_name, org)
64
+ end
65
+ end
66
+
67
+ def generate_duplicates_list
68
+ duplicate_names = {}
69
+ duplicate_name_orgs = {}
70
+ @hypervisors.each do |hypervisor|
71
+ next if @hosts.key?(hypervisor[:uuid])
72
+
73
+ duplicate_name, org = duplicate_name(hypervisor)
74
+ duplicate_names[duplicate_name] = hypervisor[:uuid]
75
+ duplicate_name_orgs[duplicate_name] = org
76
+ end
27
77
 
28
- # Since host names must be unique yet hypervisors may have unique subscription
29
- # facets in different orgs
30
- sanitized_name = ::Katello::Host::SubscriptionFacet.sanitize_name(hypervisor_json[:name])
31
- duplicate_name = "virt-who-#{sanitized_name}-#{organization.id}"
32
- host = ::Katello::Host::SubscriptionFacet.find_by(:uuid => hypervisor_json[:uuid]).try(:host)
33
- host ||= ::Host.find_by(:name => duplicate_name)
34
- if host && host.organization.try(:id) != organization.id
78
+ [duplicate_names, duplicate_name_orgs]
79
+ end
80
+
81
+ def validate_host_organization(host, organization)
82
+ if host.organization_id.nil? || host.organization_id != organization
35
83
  fail _("Host '%{name}' does not belong to an organization") % {:name => host.name} unless host.organization
36
- host = nil
37
84
  end
85
+ end
38
86
 
39
- host ||= create_host_for_hypervisor(duplicate_name, organization)
40
- host.subscription_facet ||= ::Katello::Host::SubscriptionFacet.new
41
- host.subscription_facet.host_id = host.id
42
- host.subscription_facet.uuid = hypervisor_json[:uuid]
43
- host.subscription_facet.import_database_attributes(host.subscription_facet.candlepin_consumer.consumer_attributes)
44
- host.subscription_facet.save!
45
- host.subscription_facet.update_subscription_status
46
- host.save!
87
+ # extracts a single field from a given list og hypervisors data.
88
+ def hypervisors_field(field, hypervisors = @hypervisors)
89
+ hypervisors.map { |h| h[field] }.uniq
90
+ end
91
+
92
+ def duplicate_name(hypervisor)
93
+ organization = @organizations[hypervisor[:organization_label]]
94
+ sanitized_name = ::Katello::Host::SubscriptionFacet.sanitize_name(hypervisor[:name])
95
+ ["virt-who-#{sanitized_name}-#{organization.id}", organization]
47
96
  end
48
97
 
49
98
  def create_host_for_hypervisor(name, organization, location = nil)
@@ -54,6 +103,17 @@ module Actions
54
103
  host
55
104
  end
56
105
 
106
+ def update_subscription_facet(uuid, host)
107
+ host.subscription_facet ||= host.build_subscription_facet(uuid: uuid)
108
+ if @candlepin_attributes.key?(uuid)
109
+ host.subscription_facet.candlepin_consumer.consumer_attributes = @candlepin_attributes[uuid]
110
+ host.subscription_facet.import_database_attributes
111
+ host.subscription_facet.save!
112
+ host.subscription_facet.update_subscription_status(@candlepin_attributes[uuid].try(:[], :entitlementStatus))
113
+ end
114
+ host.save!
115
+ end
116
+
57
117
  def rescue_strategy
58
118
  Dynflow::Action::Rescue::Skip
59
119
  end
@@ -44,6 +44,18 @@ module Actions
44
44
  messages
45
45
  end
46
46
 
47
+ # by default runcible puts whatever we pass into a hash under the 'name' key
48
+ # here we can make the unit hash more precise
49
+ def parse_units_for_type
50
+ if input[:type] == 'rpm'
51
+ input[:args].collect do |unit|
52
+ ::Katello::Util::Package.parse_nvrea_nvre(unit) || unit
53
+ end
54
+ else
55
+ input[:args]
56
+ end
57
+ end
58
+
47
59
  def presenter
48
60
  Consumer::ContentPresenter.new(self)
49
61
  end
@@ -14,7 +14,7 @@ module Actions
14
14
  def invoke_external_task
15
15
  task = pulp_extensions.consumer.install_content(input[:consumer_uuid],
16
16
  input[:type],
17
- input[:args],
17
+ parse_units_for_type,
18
18
  "importkeys" => true)
19
19
  schedule_timeout(Setting['content_action_accept_timeout'])
20
20
  task
@@ -14,7 +14,7 @@ module Actions
14
14
  def invoke_external_task
15
15
  pulp_extensions.consumer.uninstall_content(input[:consumer_uuid],
16
16
  input[:type],
17
- input[:args])
17
+ parse_units_for_type)
18
18
  end
19
19
 
20
20
  def presenter
@@ -17,7 +17,7 @@ module Actions
17
17
 
18
18
  pulp_extensions.consumer.update_content(input[:consumer_uuid],
19
19
  input[:type],
20
- input[:args],
20
+ parse_units_for_type,
21
21
  options)
22
22
  end
23
23
 
@@ -50,7 +50,7 @@ module Katello
50
50
  scoped_search :on => :hypervisor, :relation => :subscription_facet, :complete_value => true
51
51
  scoped_search :on => :name, :relation => :hypervisor_host, :complete_value => true, :rename => :hypervisor_host, :ext_method => :find_by_hypervisor_host
52
52
  scoped_search :on => :name, :relation => :subscriptions, :rename => :subscription_name, :complete_value => true, :ext_method => :find_by_subscription_name
53
- scoped_search :on => :id, :relation => :pools, :rename => :subscription_id, :complete_value => true, :ext_method => :find_by_subscription_id
53
+ scoped_search :on => :id, :relation => :pools, :rename => :subscription_id, :complete_value => true, :ext_method => :find_by_subscription_id, :only_explicit => true
54
54
  end
55
55
 
56
56
  module ClassMethods
@@ -579,14 +579,22 @@ module Katello
579
579
 
580
580
  def check_composite_action_allowed!(env)
581
581
  if composite? && Setting['restrict_composite_view']
582
- # verify that the composite's component view versions exist in the target environment.
582
+ if components.size != content_view_components.size
583
+ fail _("Make sure all the component content views are published before publishing/promoting the composite content view. "\
584
+ "This restriction is optional and can be modified in the Administrator -> Settings -> Content "\
585
+ "page using the restrict_composite_view flag.")
586
+ end
587
+
588
+ env_ids = env.try(:pluck, 'id') || []
589
+ env_ids << env.id unless env_ids.size > 0
583
590
  components.each do |component|
584
- unless component.environments.include?(env)
591
+ component_environment_ids = component.environments.pluck('id')
592
+ unless (env_ids - component_environment_ids).empty?
585
593
  fail _("The action requested on this composite view cannot be performed until all of the "\
586
594
  "component content view versions have been promoted to the target environment: %{env}. "\
587
- "This restriction is optional and can be modified in the Administrator -> Settings "\
595
+ "This restriction is optional and can be modified in the Administrator -> Settings -> Content "\
588
596
  "page using the restrict_composite_view flag.") %
589
- { :env => env.name }
597
+ { :env => env.try(:pluck, 'name') || env.name }
590
598
  end
591
599
  end
592
600
  end
@@ -40,6 +40,16 @@ module Katello
40
40
  end
41
41
  pool.import_data(index_hosts)
42
42
  end
43
+
44
+ def stacking_subscription(org_label, stacking_id)
45
+ org = Organization.find_by(:label => org_label)
46
+ subscription = ::Katello::Subscription.find_by(:organization_id => org.id, :cp_id => stacking_id)
47
+ if subscription.nil?
48
+ found_product = ::Katello::Resources::Candlepin::Product.find_for_stacking_id(org_label, stacking_id)
49
+ subscription = ::Katello::Subscription.find_by(:organization_id => org.id, :cp_id => found_product['id']) if found_product
50
+ end
51
+ subscription
52
+ end
43
53
  end
44
54
 
45
55
  module InstanceMethods
@@ -80,16 +90,6 @@ module Katello
80
90
  providers.any?
81
91
  end
82
92
 
83
- def stacking_subscription(org_label, stacking_id)
84
- org = Organization.find_by(:label => org_label)
85
- subscription = ::Katello::Subscription.find_by(:organization_id => org.id, :product_id => stacking_id)
86
- if subscription.nil?
87
- found_product = ::Katello::Resources::Candlepin::Product.find_for_stacking_id(org_label, stacking_id)
88
- subscription = ::Katello::Subscription.find_by(:organization_id => org.id, :cp_id => found_product['id']) if found_product
89
- end
90
- subscription
91
- end
92
-
93
93
  # rubocop:disable MethodLength,Metrics/AbcSize
94
94
  def import_data(index_hosts_and_activation_keys = false)
95
95
  pool_attributes = {}.with_indifferent_access
@@ -101,7 +101,7 @@ module Katello
101
101
  product_attributes.map { |attr| pool_attributes[attr["name"].underscore.to_sym] = attr["value"] }
102
102
 
103
103
  if pool_json["sourceStackId"]
104
- subscription = stacking_subscription(pool_json['owner']['key'], pool_json["sourceStackId"])
104
+ subscription = Pool.stacking_subscription(pool_json['owner']['key'], pool_json["sourceStackId"])
105
105
  else
106
106
  subscription = ::Katello::Subscription.find_by(:cp_id => pool_json["productId"])
107
107
  end
@@ -83,13 +83,14 @@ module Katello
83
83
  end
84
84
 
85
85
  def update_applicability_counts
86
- self.update_attributes!(
86
+ self.assign_attributes(
87
87
  :installable_security_errata_count => self.installable_errata.security.count,
88
88
  :installable_bugfix_errata_count => self.installable_errata.bugfix.count,
89
89
  :installable_enhancement_errata_count => self.installable_errata.enhancement.count,
90
90
  :applicable_rpm_count => self.content_facet_applicable_rpms.count,
91
91
  :upgradable_rpm_count => self.installable_rpms.count
92
92
  )
93
+ self.save!(:validate => false)
93
94
  end
94
95
 
95
96
  def import_rpm_applicability(partial)
@@ -16,7 +16,7 @@ module Katello
16
16
  scoped_search :on => :release, :complete_value => true, :ext_method => :scoped_search_release
17
17
  scoped_search :on => :arch, :complete_value => true
18
18
  scoped_search :on => :epoch, :complete_value => true
19
- scoped_search :on => :evr, :ext_method => :scoped_search_evr
19
+ scoped_search :on => :evr, :ext_method => :scoped_search_evr, :only_explicit => true
20
20
  scoped_search :on => :filename, :complete_value => true
21
21
  scoped_search :on => :sourcerpm, :complete_value => true
22
22
  scoped_search :on => :checksum
@@ -222,15 +222,23 @@ module Katello
222
222
  end
223
223
 
224
224
  def self.installable_for_hosts(hosts = nil)
225
- query = Katello::Rpm.joins(:content_facet_applicable_rpms).joins(:repository_rpms).
225
+ hosts = ::Host.where(:id => hosts) if hosts && hosts.is_a?(Array)
226
+
227
+ query = Katello::Rpm.joins(:content_facet_applicable_rpms).
226
228
  joins("INNER JOIN #{Katello::ContentFacetRepository.table_name} on \
227
229
  #{Katello::ContentFacetRepository.table_name}.content_facet_id = #{Katello::ContentFacetApplicableRpm.table_name}.content_facet_id").
228
230
  joins("INNER JOIN #{Katello::RepositoryRpm.table_name} AS host_repo_rpm ON \
229
- host_repo_rpm.rpm_id = #{Katello::Rpm.table_name}.id").
230
- where("#{Katello::ContentFacetRepository.table_name}.repository_id = host_repo_rpm.repository_id")
231
+ host_repo_rpm.rpm_id = #{Katello::Rpm.table_name}.id AND \
232
+ #{Katello::ContentFacetRepository.table_name}.repository_id = host_repo_rpm.repository_id")
231
233
 
232
- query = query.joins(:content_facets).where("#{Katello::Host::ContentFacet.table_name}.host_id" => hosts.map(&:id)) if hosts
233
- query.distinct
234
+ if hosts
235
+ query = query.where("#{Katello::ContentFacetRepository.table_name}.content_facet_id" => hosts.joins(:content_facet)
236
+ .select("#{Katello::Host::ContentFacet.table_name}.id"))
237
+ else
238
+ query = query.joins(:content_facet_applicable_rpms)
239
+ end
240
+
241
+ query
234
242
  end
235
243
 
236
244
  def self.applicable_to_hosts(hosts)