katello 3.12.0 → 3.12.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/app/lib/actions/candlepin/product/content_update.rb +1 -1
  3. data/app/lib/actions/katello/host/update.rb +5 -1
  4. data/app/lib/actions/katello/product/content_destroy.rb +1 -1
  5. data/app/lib/katello/resources/candlepin/content.rb +3 -2
  6. data/app/models/katello/concerns/smart_proxy_extensions.rb +3 -4
  7. data/app/models/katello/glue/candlepin/pool.rb +1 -1
  8. data/app/models/katello/host/info_provider.rb +2 -2
  9. data/app/models/katello/host/subscription_facet.rb +3 -1
  10. data/app/models/katello/subscription.rb +4 -0
  11. data/app/models/setting/content.rb +2 -0
  12. data/app/views/katello/api/v2/errata/_counts.json.rabl +2 -2
  13. data/app/views/katello/api/v2/subscriptions/base.json.rabl +2 -1
  14. data/app/views/katello/api/v2/subscriptions/show.json.rabl +1 -0
  15. data/app/views/overrides/smart_proxies/_environment_tab.html.erb +1 -1
  16. data/app/views/overrides/smart_proxies/_environment_tab_pane.html.erb +1 -1
  17. data/db/migrate/20190205142619_add_content_constraints.rb +6 -2
  18. data/db/seeds.d/111-upgrade_tasks.rb +1 -0
  19. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-errata.html +2 -2
  20. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-info.html +2 -2
  21. data/lib/katello/tasks/upgrades/3.10/update_gpg_key_urls.rake +32 -0
  22. data/lib/katello/version.rb +1 -1
  23. data/webpack/components/SelectOrg/SetOrganization.js +3 -1
  24. data/webpack/components/WithOrganization/withOrganization.js +4 -1
  25. data/webpack/move_to_foreman/components/common/ModalProgressBar/ModalProgressBar.js +6 -1
  26. data/webpack/redux/actions/RedHatRepositories/repositorySetRepositories.js +9 -0
  27. data/webpack/scenes/ModuleStreams/Details/ModuleStreamDetails.js +8 -1
  28. data/webpack/scenes/ModuleStreams/ModuleStreamsTable.js +6 -1
  29. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepositories.js +3 -0
  30. data/webpack/scenes/RedHatRepositories/index.js +9 -2
  31. data/webpack/scenes/Subscriptions/Details/SubscriptionAttributes.js +1 -2
  32. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailAssociations.js +5 -1
  33. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailInfo.js +12 -1
  34. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProduct.js +9 -1
  35. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProductContent.js +3 -1
  36. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProducts.js +3 -1
  37. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +6 -1
  38. data/webpack/scenes/Subscriptions/Details/SubscriptionPurposeAttributes.js +8 -0
  39. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailInfo.test.js +2 -1
  40. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailInfo.test.js.snap +50 -11
  41. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +9 -0
  42. data/webpack/scenes/Subscriptions/Details/__tests__/subscriptionDetails.fixtures.js +3 -0
  43. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +15 -2
  44. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +6 -1
  45. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +7 -1
  46. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js +2 -0
  47. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Table.js +7 -1
  48. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1014f15535a58f5e1728c5a9bb6c564a9b9a095b1efa80efa6a9f4249d56824c
4
- data.tar.gz: f655e1161eb1767cc87b8e9de5883befe95968202ade0a29eae5912c2436e9d4
3
+ metadata.gz: 45cc83708ed5880a23368a5f1b29b58e0c442475b96036d324f6e92c4d5aa308
4
+ data.tar.gz: e23464e83cf613250d03c4b980482716a5f5cee3640784669f5a8b7c0a09cc4f
5
5
  SHA512:
6
- metadata.gz: 9295f9e67103e6913e61ed365389c705113ca12638a413d21020f7d596fc0ffd0063652fcd7435fa496facc62122d1f948cb713bc7f375c0b96e642002d8e204
7
- data.tar.gz: 84f9ad06abe7182a733551da25fecfdea1857927f77b98670fc54fbe832c2455e3d5701912bb6b15e9d3d9889d675d460e159a18ea73f277d2cb4f1f8702a2bc
6
+ metadata.gz: 75174382112a3331e2917fb949f30c66987b9a7b5b0f71363de706ca8f4b85094f662c25310b3cc37500e49c07f4b2c9d5011030926a5dc7e5dfcffa026e840c
7
+ data.tar.gz: 5ce0ed0ad5fd4f2666730c73d5ece96452132b5a6e26702d0c36eb14422392dc6b6852ce30189a167a2f47b382b9884102fb742c91262b74527210e47e4a7967
@@ -19,7 +19,7 @@ module Actions
19
19
  id: input[:content_id],
20
20
  name: input[:name],
21
21
  contentUrl: input[:content_url],
22
- gpgUrl: input[:gpg_key_url],
22
+ gpgUrl: input[:gpg_key_url] || '', #candlepin ignores nil
23
23
  type: input[:type],
24
24
  arches: input[:arches],
25
25
  label: input[:label],
@@ -45,7 +45,11 @@ module Actions
45
45
  end
46
46
 
47
47
  def resource_locks
48
- :update
48
+ if Setting[:host_update_lock]
49
+ :link
50
+ else
51
+ :update
52
+ end
49
53
  end
50
54
 
51
55
  def rescue_strategy
@@ -19,7 +19,7 @@ module Actions
19
19
  owner: root_repository.product.organization.label,
20
20
  content_id: root_repository.content_id)
21
21
 
22
- ::Katello::Content.find(katello_content_id)&.destroy!
22
+ ::Katello::Content.find_by_id(katello_content_id)&.destroy!
23
23
  end
24
24
  end
25
25
  end
@@ -12,8 +12,9 @@ module Katello
12
12
  JSON.parse(content_json).with_indifferent_access
13
13
  end
14
14
 
15
- def all(owner_label)
16
- content_json = Candlepin::CandlepinResource.get(path(owner_label), self.default_headers).body
15
+ def all(owner_label, include_only: nil)
16
+ includes = include_only ? "?#{included_list(include_only)}" : ""
17
+ content_json = Candlepin::CandlepinResource.get(path(owner_label) + includes, self.default_headers).body
17
18
  JSON.parse(content_json)
18
19
  end
19
20
 
@@ -145,12 +145,11 @@ module Katello
145
145
  end
146
146
 
147
147
  def pulp_mirror?
148
- self.features.map(&:name).include?(PULP_NODE_FEATURE)
148
+ self.has_feature? PULP_NODE_FEATURE
149
149
  end
150
150
 
151
151
  def pulp_master?
152
- # use map instead of pluck in case the features aren't saved yet during create
153
- self.features.map(&:name).include?(PULP_FEATURE)
152
+ self.has_feature? PULP_FEATURE
154
153
  end
155
154
 
156
155
  #deprecated methods
@@ -162,7 +161,7 @@ module Katello
162
161
  end
163
162
 
164
163
  def associate_default_locations
165
- return unless pulp_master?
164
+ return unless self.pulp_master?
166
165
  ['puppet_content', 'subscribed_hosts'].each do |type|
167
166
  default_location = ::Location.unscoped.find_by_title(
168
167
  ::Setting[:"default_location_#{type}"])
@@ -10,7 +10,7 @@ module Katello
10
10
  lazy_accessor :subscription_facts, :initializer => lambda { |_s| self.subscription ? self.subscription.attributes : {} }
11
11
 
12
12
  lazy_accessor :pool_derived, :owner, :source_pool_id, :virt_limit, :arch, :description, :product_family,
13
- :variant, :suggested_quantity, :support_type, :product_id, :type, :upstream_entitlement_id,
13
+ :variant, :suggested_quantity, :support_type, :product_id, :type, :upstream_entitlement_id, :role, :usage, :addons,
14
14
  :initializer => :pool_facts
15
15
 
16
16
  lazy_accessor :name, :support_level, :org, :sockets, :cores, :instance_multiplier,
@@ -28,7 +28,7 @@ module Katello
28
28
  'label' => host.content_view.try(:label),
29
29
  'latest-version' => host.content_view.try(:latest_version),
30
30
  'version' => content_version.try(:version),
31
- 'published' => content_version.try(:created_at).try(:time),
31
+ 'published' => content_version.try(:created_at).try(:time).to_s,
32
32
  'components' => content_view_components
33
33
  }
34
34
 
@@ -43,7 +43,7 @@ module Katello
43
43
  cv_label = cv.component_version.content_view.label
44
44
  components[cv_label] = {}
45
45
  components[cv_label]['version'] = cv.component_version.try(:version)
46
- components[cv_label]['published'] = cv.component_version.try(:created_at).try(:time)
46
+ components[cv_label]['published'] = cv.component_version.try(:created_at).try(:time).to_s
47
47
  end
48
48
  components
49
49
  end
@@ -29,6 +29,8 @@ module Katello
29
29
 
30
30
  attr_accessor :facts
31
31
 
32
+ DMI_UUID_ALLOWED_DUPS = ['', 'Not Settable', 'Not Present'].freeze
33
+
32
34
  def host_type
33
35
  host_facts = self.host.facts
34
36
  host_facts["virt::host_type"] || host_facts["hypervisor::type"]
@@ -249,7 +251,7 @@ module Katello
249
251
 
250
252
  hosts = ::Host.unscoped.distinct.left_outer_joins(:fact_values)
251
253
  .where("#{::Host.table_name}.name = ? OR (#{FactValue.table_name}.fact_name_id = ?
252
- AND #{FactValue.table_name}.value = ?)", host_name, uuid_fact_id, host_uuid)
254
+ AND #{FactValue.table_name}.value = ? AND #{FactValue.table_name}.value NOT IN (?))", host_name, uuid_fact_id, host_uuid, DMI_UUID_ALLOWED_DUPS)
253
255
 
254
256
  return if hosts.empty?
255
257
 
@@ -42,6 +42,10 @@ module Katello
42
42
  pools.any?(&:recently_expired?)
43
43
  end
44
44
 
45
+ def multi_entitlement?
46
+ pools.where("#{Katello::Pool.table_name}.multi_entitlement" => true).any?
47
+ end
48
+
45
49
  def virt_who_pools
46
50
  pools.where("#{Katello::Pool.table_name}.virt_who" => true)
47
51
  end
@@ -106,6 +106,8 @@ class Setting::Content < Setting
106
106
  N_('Default Location where new Puppet content will be put upon Content View publish'),
107
107
  nil, N_('Default Location Puppet content'), nil,
108
108
  :collection => proc { Hash[Location.unscoped.all.map { |loc| [loc[:title], loc[:title]] }] }),
109
+ self.set('host_update_lock', N_("Allow multiple concurrent Actions::Katello::Host::Update calls for one host to be processed at the same time."),
110
+ false, N_('Concurrent Actions::Katello::Host::Update allowed')),
109
111
  self.set('expire_soon_days', N_('The number of days remaining in a subscription before you will be reminded about renewing it.'),
110
112
  120, N_('Expire soon days')),
111
113
  self.set('content_view_solve_dependencies',
@@ -5,11 +5,11 @@ node :security do |_presenter|
5
5
  end
6
6
 
7
7
  node :bugfix do |_presenter|
8
- totals[:bugfix]
8
+ totals[:bugfix].to_i + totals[:recommended].to_i
9
9
  end
10
10
 
11
11
  node :enhancement do |_presenter|
12
- totals[:enhancement]
12
+ totals[:enhancement].to_i + totals[:optional].to_i
13
13
  end
14
14
 
15
15
  node :total do |_presenter|
@@ -10,7 +10,8 @@ attributes :account_number, :contract_number
10
10
  attributes :support_level
11
11
  attributes :product_id
12
12
  attributes :sockets, :cores, :ram
13
- attributes :instance_multiplier, :stacking_id, :multi_entitlement
13
+ attributes :instance_multiplier, :stacking_id
14
+ attributes :multi_entitlement? => :multi_entitlement
14
15
  attributes :type
15
16
  attributes :name => :product_name
16
17
  attributes :unmapped_guest
@@ -5,6 +5,7 @@ extends "katello/api/v2/subscriptions/base"
5
5
  attributes :arch
6
6
  attributes :description
7
7
  attributes :support_type
8
+ attributes :role, :usage, :addons
8
9
 
9
10
  node(:host_count) do |subscription|
10
11
  subscription.hosts.count
@@ -1,4 +1,4 @@
1
- <% if !@smart_proxy.new_record? && @smart_proxy.features.pluck(:name).include?(SmartProxy::PULP_NODE_FEATURE) -%>
1
+ <% if !@smart_proxy.new_record? && @smart_proxy.has_feature?(SmartProxy::PULP_NODE_FEATURE) -%>
2
2
  <li id="kt_environments_tab">
3
3
  <a href="#kt_environments" data-toggle="tab"><%= _('Lifecycle Environments') %></a>
4
4
  </li>
@@ -1,4 +1,4 @@
1
- <% if !@smart_proxy.new_record? && @smart_proxy.features.pluck(:name).include?(SmartProxy::PULP_NODE_FEATURE) -%>
1
+ <% if !@smart_proxy.new_record? && @smart_proxy.has_feature?(SmartProxy::PULP_NODE_FEATURE) -%>
2
2
  <div class="tab-pane" id="kt_environments">
3
3
  <%= multiple_selects f, :lifecycle_environments, Katello::KTEnvironment.completer_scope(:organization_id => ::Organization.current.try(:id)), @smart_proxy.lifecycle_environment_ids, {:label => _('Lifecycle Environments')}, @smart_proxy.default_capsule? ? {:disabled => :disabled } : {} %>
4
4
 
@@ -13,15 +13,19 @@ class AddContentConstraints < ActiveRecord::Migration[5.2]
13
13
  duplicates.each do |dup|
14
14
  contents = Katello::Content.where(organization_id: dup.organization_id, cp_content_id: dup.cp_content_id).to_a
15
15
  first = contents.pop
16
+ content_to_delete = []
16
17
  contents.each do |content|
17
18
  content.product_contents.each do |pc|
18
- unless first.products.include?(pc.product)
19
+ if !first.products.include?(pc.product)
19
20
  pc.content = first
20
21
  pc.save!
22
+ else
23
+ pc.delete
21
24
  end
22
25
  end
23
- content.delete
26
+ content_to_delete << content.id
24
27
  end
28
+ ::Katello::Content.where(id: content_to_delete).delete_all
25
29
  end
26
30
 
27
31
  add_index :katello_contents, [:cp_content_id, :organization_id], :unique => true, :name => :katello_contents_cpcid_orgid_uniq
@@ -5,6 +5,7 @@ UpgradeTask.define_tasks(:katello) do
5
5
  {:name => 'katello:clean_backend_objects', :long_running => true, :skip_failure => true, :always_run => true},
6
6
  {:name => 'katello:upgrades:3.8:clear_checksum_type'},
7
7
  {:name => 'katello:upgrades:3.10:clear_invalid_repo_credentials'},
8
+ {:name => 'katello:upgrades:3.10:update_gpg_key_urls'},
8
9
  {:name => 'katello:upgrades:3.11:import_yum_metadata'},
9
10
  {:name => 'katello:upgrades:3.11:update_puppet_repos'},
10
11
  {:name => 'katello:upgrades:3.11:clear_checksum_type', :task_name => 'katello:upgrades:3.8:clear_checksum_type'},
@@ -121,11 +121,11 @@
121
121
  <i class="fa fa-warning inline-icon" title="{{ 'Security' | translate }}"></i>
122
122
  </span>
123
123
 
124
- <span ng-show="erratum.type == 'bugfix'">
124
+ <span ng-show="erratum.type == 'bugfix' || erratum.type == 'recommended'">
125
125
  <i class="fa fa-bug inline-icon" title="{{ 'Bug Fix' | translate }}"></i>
126
126
  </span>
127
127
 
128
- <span ng-show="erratum.type == 'enhancement'">
128
+ <span ng-show="erratum.type == 'enhancement' || erratum.type == 'optional'">
129
129
  <i class="fa fa-plus-square inline-icon" title="{{ 'Enhancement' | translate }}"></i>
130
130
  </span>
131
131
 
@@ -208,7 +208,7 @@
208
208
 
209
209
  <dt translate>Bug Fix</dt>
210
210
  <dd>
211
- <a ui-sref="content-host.errata.index({getSearch: 'type=bugfix'})" ng-class="{black: !host.content_facet_attributes.errata_counts.bugfix, yellow: host.content_facet_attributes.errata_counts.bugfix > 0}">
211
+ <a ui-sref="content-host.errata.index({getSearch: 'type=bugfix or type=recommended'})" ng-class="{black: !host.content_facet_attributes.errata_counts.bugfix, yellow: host.content_facet_attributes.errata_counts.bugfix > 0}">
212
212
  <i class="fa fa-bug inline-icon" title="{{ 'Bug Fix' | translate }}"></i>
213
213
  {{ host.content_facet_attributes.errata_counts.bugfix || 0 }}
214
214
  </a>
@@ -216,7 +216,7 @@
216
216
 
217
217
  <dt translate>Enhancement</dt>
218
218
  <dd>
219
- <a ui-sref="content-host.errata.index({getSearch: 'type=enhancement'})" ng-class="{black: !host.content_facet_attributes.errata_counts.enhancement, yellow: host.content_facet_attributes.errata_counts.enhancement > 0}">
219
+ <a ui-sref="content-host.errata.index({getSearch: 'type=enhancement or type=optional'})" ng-class="{black: !host.content_facet_attributes.errata_counts.enhancement, yellow: host.content_facet_attributes.errata_counts.enhancement > 0}">
220
220
  <i class="fa fa-plus-square inline-icon" title="{{ 'Enhancement' | translate }}"></i>
221
221
  {{ host.content_facet_attributes.errata_counts.enhancement || 0 }}
222
222
  </a>
@@ -0,0 +1,32 @@
1
+ namespace :katello do
2
+ namespace :upgrades do
3
+ namespace '3.10' do
4
+ desc "Update repositories with API V1 GPG URLs"
5
+ task :update_gpg_key_urls => ["environment", "katello:check_ping"] do
6
+ User.current = User.anonymous_admin
7
+
8
+ ::Organization.all.each do |org|
9
+ org_contents = Katello::Resources::Candlepin::Content.all(org.label, include_only: [:id, :gpgUrl])
10
+
11
+ org_contents.each do |cp_content|
12
+ gpg_url = cp_content['gpgUrl']
13
+ if gpg_url && gpg_url.match(/katello\/api\/repositories/)
14
+ content = Katello::Content.where(cp_content_id: cp_content['id'], organization: org).first
15
+
16
+ if content.nil?
17
+ Rails.logger.warn("Candlepin Content id=#{cp_content['id']} isn't in our DB. Try running 'rake katello:reimport' first.")
18
+ else
19
+ root_repo = Katello::RootRepository.in_organization(org).where(content_id: content.cp_content_id).first
20
+ new_gpg_url = root_repo.library_instance.yum_gpg_key_url
21
+ cp_content['gpgUrl'] = new_gpg_url
22
+ Katello::Resources::Candlepin::Content.update(org.label, cp_content)
23
+ content.gpg_url = new_gpg_url
24
+ content.save!
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "3.12.0".freeze
2
+ VERSION = "3.12.1".freeze
3
3
  end
@@ -96,7 +96,9 @@ SetOrganization.propTypes = {
96
96
  list: PropTypes.arrayOf(PropTypes.object),
97
97
  loading: PropTypes.bool.isRequired,
98
98
  changeCurrentOrganization: PropTypes.func.isRequired,
99
- history: PropTypes.shape({}).isRequired,
99
+ history: PropTypes.shape({
100
+ push: PropTypes.func,
101
+ }).isRequired,
100
102
  redirectPath: PropTypes.string.isRequired,
101
103
  getOrganiztionsList: PropTypes.func.isRequired,
102
104
  };
@@ -62,7 +62,10 @@ function withOrganization(WrappedComponent, redirectPath) {
62
62
  CheckOrg.propTypes = {
63
63
  location: PropTypes.shape({}),
64
64
  loadOrganization: PropTypes.func.isRequired,
65
- organization: PropTypes.shape({}).isRequired,
65
+ organization: PropTypes.shape({
66
+ label: PropTypes.string,
67
+ loading: PropTypes.bool,
68
+ }).isRequired,
66
69
  };
67
70
 
68
71
  CheckOrg.defaultProps = {
@@ -32,7 +32,12 @@ const ModalProgressBar = (props) => {
32
32
  ModalProgressBar.propTypes = {
33
33
  show: PropTypes.bool.isRequired,
34
34
  container: PropTypes.shape({}),
35
- task: PropTypes.shape({}),
35
+ task: PropTypes.shape({
36
+ progress: PropTypes.number,
37
+ humanized: PropTypes.shape({
38
+ action: PropTypes.string,
39
+ }),
40
+ }),
36
41
  };
37
42
 
38
43
  ModalProgressBar.defaultProps = {
@@ -1,3 +1,4 @@
1
+ import PropTypes from 'prop-types';
1
2
  import api from '../../../services/api';
2
3
  import { apiError, apiSuccess } from '../../../move_to_foreman/common/helpers.js';
3
4
  import { getArchFromPath } from './helpers.js';
@@ -76,4 +77,12 @@ const loadRepositorySetRepos = (contentId, productId) => (dispatch) => {
76
77
  });
77
78
  };
78
79
 
80
+ loadRepositorySetRepos.propTypes = {
81
+ data: PropTypes.shape({
82
+ error: PropTypes.shape({
83
+ displayMessage: PropTypes.string,
84
+ }),
85
+ }),
86
+ };
87
+
79
88
  export default loadRepositorySetRepos;
@@ -141,7 +141,14 @@ ModuleStreamDetails.propTypes = {
141
141
  id: PropTypes.string.isRequired,
142
142
  }).isRequired,
143
143
  }).isRequired,
144
- moduleStreamDetails: PropTypes.shape({}).isRequired,
144
+ moduleStreamDetails: PropTypes.shape({
145
+ loading: PropTypes.bool,
146
+ name: PropTypes.string,
147
+ profiles: PropTypes.array,
148
+ repositories: PropTypes.array,
149
+ artifacts: PropTypes.array,
150
+ stream: PropTypes.string,
151
+ }).isRequired,
145
152
  };
146
153
 
147
154
  export default ModuleStreamDetails;
@@ -31,7 +31,12 @@ const ModuleStreamsTable = ({ moduleStreams, onPaginationChange }) => {
31
31
  };
32
32
 
33
33
  ModuleStreamsTable.propTypes = {
34
- moduleStreams: PropTypes.shape({}).isRequired,
34
+ moduleStreams: PropTypes.shape({
35
+ loading: PropTypes.bool,
36
+ results: PropTypes.array,
37
+ pagination: PropTypes.shape({}),
38
+ itemCount: PropTypes.number,
39
+ }).isRequired,
35
40
  onPaginationChange: PropTypes.func.isRequired,
36
41
  };
37
42
 
@@ -81,6 +81,9 @@ RepositorySetRepositories.propTypes = {
81
81
  data: PropTypes.shape({
82
82
  loading: PropTypes.bool.isRequired,
83
83
  repositories: PropTypes.arrayOf(PropTypes.object),
84
+ error: PropTypes.shape({
85
+ displayMessage: PropTypes.string,
86
+ }),
84
87
  }).isRequired,
85
88
  };
86
89
 
@@ -94,8 +94,15 @@ RedHatRepositoriesPage.propTypes = {
94
94
  loadEnabledRepos: PropTypes.func.isRequired,
95
95
  loadRepositorySets: PropTypes.func.isRequired,
96
96
  updateRecommendedRepositorySets: PropTypes.func.isRequired,
97
- enabledRepositories: PropTypes.shape({}).isRequired,
98
- repositorySets: PropTypes.shape({}).isRequired,
97
+ enabledRepositories: PropTypes.shape({
98
+ loading: PropTypes.bool,
99
+ search: PropTypes.string,
100
+ }).isRequired,
101
+ repositorySets: PropTypes.shape({
102
+ recommended: PropTypes.array,
103
+ loading: PropTypes.bool,
104
+ search: PropTypes.string,
105
+ }).isRequired,
99
106
  };
100
107
 
101
108
  const mapStateToProps = ({
@@ -10,10 +10,9 @@ export default {
10
10
  product_id: __('Product ID'),
11
11
  contract_number: __('Contract Number'),
12
12
  account_number: __('Account Number'),
13
- support_level: __('Support Level'),
14
13
  support_type: __('Support Type'),
15
14
  arch: __('Architecture(s)'),
16
15
  type: __('Type'),
17
- mutli_entitlement: __('Multi-entitlement'),
16
+ multi_entitlement: __('Multi-entitlement'),
18
17
  stacking_id: __('Stacking ID'),
19
18
  };
@@ -42,7 +42,11 @@ const SubscriptionDetailAssociations = ({ subscriptionDetails }) => {
42
42
  };
43
43
 
44
44
  SubscriptionDetailAssociations.propTypes = {
45
- subscriptionDetails: PropTypes.shape({}).isRequired,
45
+ subscriptionDetails: PropTypes.shape({
46
+ id: PropTypes.number,
47
+ host_count: PropTypes.number,
48
+ activation_keys: PropTypes.array,
49
+ }).isRequired,
46
50
  };
47
51
 
48
52
  export default SubscriptionDetailAssociations;
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import { Table } from 'react-bootstrap';
4
4
  import { translate as __ } from 'foremanReact/common/I18n';
5
5
  import subscriptionAttributes from './SubscriptionAttributes';
6
+ import subscriptionPurposeAttributes from './SubscriptionPurposeAttributes';
6
7
 
7
8
  const SubscriptionDetailInfo = ({ subscriptionDetails }) => {
8
9
  const subscriptionLimits = (subDetails) => {
@@ -54,7 +55,17 @@ const SubscriptionDetailInfo = ({ subscriptionDetails }) => {
54
55
  </tr>
55
56
  </tbody>
56
57
  </Table>
57
-
58
+ <h2>{__('System Purpose')}</h2>
59
+ <Table>
60
+ <tbody>
61
+ {Object.keys(subscriptionPurposeAttributes).map(key => (
62
+ <tr key={key}>
63
+ <td><b>{__(subscriptionPurposeAttributes[key])}</b></td>
64
+ <td>{subscriptionDetailValue(subscriptionDetails, key)}</td>
65
+ </tr>
66
+ ))}
67
+ </tbody>
68
+ </Table>
58
69
  </div>
59
70
  );
60
71
  };
@@ -30,7 +30,15 @@ const SubscriptionDetailProduct = ({ content }) => (
30
30
  );
31
31
 
32
32
  SubscriptionDetailProduct.propTypes = {
33
- content: PropTypes.shape({}).isRequired,
33
+ content: PropTypes.shape({
34
+ id: PropTypes.string,
35
+ name: PropTypes.string,
36
+ enabled: PropTypes.bool,
37
+ content_url: PropTypes.string,
38
+ gpg_url: PropTypes.string,
39
+ type: PropTypes.string,
40
+ enable: PropTypes.bool,
41
+ }).isRequired,
34
42
  };
35
43
 
36
44
  export default SubscriptionDetailProduct;
@@ -48,7 +48,9 @@ const SubscriptionDetailProductContent = ({ productContent }) => {
48
48
  };
49
49
 
50
50
  SubscriptionDetailProductContent.propTypes = {
51
- productContent: PropTypes.shape({}).isRequired,
51
+ productContent: PropTypes.shape({
52
+ results: PropTypes.array,
53
+ }).isRequired,
52
54
  };
53
55
 
54
56
  export default SubscriptionDetailProductContent;
@@ -16,7 +16,9 @@ const SubscriptionDetailProducts = ({ subscriptionDetails }) => (
16
16
  );
17
17
 
18
18
  SubscriptionDetailProducts.propTypes = {
19
- subscriptionDetails: PropTypes.shape({}).isRequired,
19
+ subscriptionDetails: PropTypes.shape({
20
+ provided_products: PropTypes.array,
21
+ }).isRequired,
20
22
  };
21
23
 
22
24
  export default SubscriptionDetailProducts;
@@ -135,7 +135,12 @@ class SubscriptionDetails extends Component {
135
135
  SubscriptionDetails.propTypes = {
136
136
  loadSubscriptionDetails: PropTypes.func.isRequired,
137
137
  loadProducts: PropTypes.func.isRequired,
138
- subscriptionDetails: PropTypes.shape({}).isRequired,
138
+ subscriptionDetails: PropTypes.shape({
139
+ error: PropTypes.shape({}),
140
+ loading: PropTypes.bool,
141
+ name: PropTypes.string,
142
+ productContent: PropTypes.shape({}),
143
+ }).isRequired,
139
144
  history: PropTypes.shape({ push: PropTypes.func.isRequired }).isRequired,
140
145
  match: PropTypes.shape({
141
146
  params: PropTypes.shape({
@@ -0,0 +1,8 @@
1
+ import { translate as __ } from 'foremanReact/common/I18n';
2
+
3
+ export default {
4
+ support_level: __('Service Level (SLA)'),
5
+ usage: __('Usage Type'),
6
+ role: __('Role'),
7
+ addons: __('Add ons'),
8
+ };
@@ -10,6 +10,7 @@ describe('subscriptions detail associations page', () => {
10
10
  const testInstance = testRenderer.root;
11
11
 
12
12
  expect(testRenderer.toJSON()).toMatchSnapshot();
13
- expect(testInstance.findByType('h2').children[0]).toBe('Subscription Info');
13
+ expect(testInstance.findAllByType('h2')[0].children[0]).toBe('Subscription Info');
14
+ expect(testInstance.findAllByType('h2')[1].children[0]).toBe('System Purpose');
14
15
  });
15
16
  });
@@ -99,16 +99,6 @@ exports[`subscriptions detail associations page renders correctly 1`] = `
99
99
  1212729
100
100
  </td>
101
101
  </tr>
102
- <tr>
103
- <td>
104
- <b>
105
- Support Level
106
- </b>
107
- </td>
108
- <td>
109
- Self-Support
110
- </td>
111
- </tr>
112
102
  <tr>
113
103
  <td>
114
104
  <b>
@@ -146,7 +136,7 @@ exports[`subscriptions detail associations page renders correctly 1`] = `
146
136
  </b>
147
137
  </td>
148
138
  <td>
149
-
139
+ true
150
140
  </td>
151
141
  </tr>
152
142
  <tr>
@@ -181,5 +171,54 @@ exports[`subscriptions detail associations page renders correctly 1`] = `
181
171
  </tr>
182
172
  </tbody>
183
173
  </table>
174
+ <h2>
175
+ System Purpose
176
+ </h2>
177
+ <table
178
+ className="table"
179
+ >
180
+ <tbody>
181
+ <tr>
182
+ <td>
183
+ <b>
184
+ Service Level (SLA)
185
+ </b>
186
+ </td>
187
+ <td>
188
+ Self-Support
189
+ </td>
190
+ </tr>
191
+ <tr>
192
+ <td>
193
+ <b>
194
+ Usage Type
195
+ </b>
196
+ </td>
197
+ <td>
198
+ Development
199
+ </td>
200
+ </tr>
201
+ <tr>
202
+ <td>
203
+ <b>
204
+ Role
205
+ </b>
206
+ </td>
207
+ <td>
208
+ Test Role
209
+ </td>
210
+ </tr>
211
+ <tr>
212
+ <td>
213
+ <b>
214
+ Add ons
215
+ </b>
216
+ </td>
217
+ <td>
218
+ Addon1, Addon2
219
+ </td>
220
+ </tr>
221
+ </tbody>
222
+ </table>
184
223
  </div>
185
224
  `;
@@ -91,6 +91,7 @@ exports[`subscriptions details page should render and contain appropiate compone
91
91
  Object {
92
92
  "account_number": 1212729,
93
93
  "activation_keys": Array [],
94
+ "addons": "Addon1, Addon2",
94
95
  "arch": "ia64,ppc,ppc64,ppc64le,s390,s390x,x86,x86_64",
95
96
  "available": 1,
96
97
  "consumed": 0,
@@ -204,6 +205,7 @@ exports[`subscriptions details page should render and contain appropiate compone
204
205
  ],
205
206
  "quantity": 1,
206
207
  "ram": null,
208
+ "role": "Test Role",
207
209
  "sockets": null,
208
210
  "stacking_id": "SER0421",
209
211
  "start_date": "2013-03-01 00:00:00 -0500",
@@ -213,6 +215,7 @@ exports[`subscriptions details page should render and contain appropiate compone
213
215
  "type": "NORMAL",
214
216
  "unmapped_guest": false,
215
217
  "upstream": true,
218
+ "usage": " Development",
216
219
  "virt_only": false,
217
220
  "virt_who": false,
218
221
  }
@@ -229,6 +232,7 @@ exports[`subscriptions details page should render and contain appropiate compone
229
232
  Object {
230
233
  "account_number": 1212729,
231
234
  "activation_keys": Array [],
235
+ "addons": "Addon1, Addon2",
232
236
  "arch": "ia64,ppc,ppc64,ppc64le,s390,s390x,x86,x86_64",
233
237
  "available": 1,
234
238
  "consumed": 0,
@@ -342,6 +346,7 @@ exports[`subscriptions details page should render and contain appropiate compone
342
346
  ],
343
347
  "quantity": 1,
344
348
  "ram": null,
349
+ "role": "Test Role",
345
350
  "sockets": null,
346
351
  "stacking_id": "SER0421",
347
352
  "start_date": "2013-03-01 00:00:00 -0500",
@@ -351,6 +356,7 @@ exports[`subscriptions details page should render and contain appropiate compone
351
356
  "type": "NORMAL",
352
357
  "unmapped_guest": false,
353
358
  "upstream": true,
359
+ "usage": " Development",
354
360
  "virt_only": false,
355
361
  "virt_who": false,
356
362
  }
@@ -361,6 +367,7 @@ exports[`subscriptions details page should render and contain appropiate compone
361
367
  Object {
362
368
  "account_number": 1212729,
363
369
  "activation_keys": Array [],
370
+ "addons": "Addon1, Addon2",
364
371
  "arch": "ia64,ppc,ppc64,ppc64le,s390,s390x,x86,x86_64",
365
372
  "available": 1,
366
373
  "consumed": 0,
@@ -474,6 +481,7 @@ exports[`subscriptions details page should render and contain appropiate compone
474
481
  ],
475
482
  "quantity": 1,
476
483
  "ram": null,
484
+ "role": "Test Role",
477
485
  "sockets": null,
478
486
  "stacking_id": "SER0421",
479
487
  "start_date": "2013-03-01 00:00:00 -0500",
@@ -483,6 +491,7 @@ exports[`subscriptions details page should render and contain appropiate compone
483
491
  "type": "NORMAL",
484
492
  "unmapped_guest": false,
485
493
  "upstream": true,
494
+ "usage": " Development",
486
495
  "virt_only": false,
487
496
  "virt_who": false,
488
497
  }
@@ -25,6 +25,9 @@ export const subDetails = Immutable({
25
25
  arch: 'ia64,ppc,ppc64,ppc64le,s390,s390x,x86,x86_64',
26
26
  description: 'OpenShift Enterprise',
27
27
  support_type: 'L1-L3',
28
+ role: 'Test Role',
29
+ usage: ' Development',
30
+ addons: 'Addon1, Addon2',
28
31
  id: 48,
29
32
  cp_id: '4028f92a6317cfbd0163b419377f3bee',
30
33
  subscription_id: 3,
@@ -295,13 +295,26 @@ ManageManifestModal.propTypes = {
295
295
  refresh: PropTypes.func.isRequired,
296
296
  delete: PropTypes.func.isRequired,
297
297
  loadManifestHistory: PropTypes.func.isRequired,
298
- organization: PropTypes.shape({}).isRequired,
298
+ organization: PropTypes.shape({
299
+ loading: PropTypes.bool,
300
+ redhat_repository_url: PropTypes.string,
301
+ owner_details: PropTypes.shape({
302
+ upstreamConsumer: PropTypes.shape({
303
+ uuid: PropTypes.string,
304
+ name: PropTypes.string,
305
+ webUrl: PropTypes.string,
306
+ }),
307
+ }),
308
+ }).isRequired,
299
309
  disableManifestActions: PropTypes.bool,
300
310
  disabledReason: PropTypes.string,
301
311
  loadOrganization: PropTypes.func.isRequired,
302
312
  saveOrganization: PropTypes.func.isRequired,
303
313
  taskInProgress: PropTypes.bool.isRequired,
304
- manifestHistory: PropTypes.shape({}).isRequired,
314
+ manifestHistory: PropTypes.shape({
315
+ loading: PropTypes.bool,
316
+ results: PropTypes.array,
317
+ }).isRequired,
305
318
  showModal: PropTypes.bool.isRequired,
306
319
  onClose: PropTypes.func,
307
320
  };
@@ -308,8 +308,13 @@ SubscriptionsPage.propTypes = {
308
308
  updateQuantity: PropTypes.func.isRequired,
309
309
  loadTableColumns: PropTypes.func.isRequired,
310
310
  taskDetails: PropTypes.shape({}),
311
- subscriptions: PropTypes.shape({}).isRequired,
311
+ subscriptions: PropTypes.shape({
312
+ disconnected: PropTypes.bool,
313
+ tableColumns: PropTypes.array,
314
+ selectedTableColumns: PropTypes.array,
315
+ }).isRequired,
312
316
  organization: PropTypes.shape({
317
+ id: PropTypes.number,
313
318
  owner_details: PropTypes.shape({
314
319
  displayName: PropTypes.string,
315
320
  }),
@@ -261,7 +261,13 @@ UpstreamSubscriptionsPage.propTypes = {
261
261
  loadUpstreamSubscriptions: PropTypes.func.isRequired,
262
262
  saveUpstreamSubscriptions: PropTypes.func.isRequired,
263
263
  upstreamSubscriptions: PropTypes.shape({
264
- task: PropTypes.shape({}),
264
+ loading: PropTypes.bool,
265
+ itemCount: PropTypes.number,
266
+ results: PropTypes.array,
267
+ pagination: PropTypes.shape({}),
268
+ task: PropTypes.shape({
269
+ id: PropTypes.number,
270
+ }),
265
271
  }).isRequired,
266
272
  history: PropTypes.shape({ push: PropTypes.func.isRequired }).isRequired,
267
273
  };
@@ -288,6 +288,8 @@ SubscriptionsTable.propTypes = {
288
288
  updateQuantity: PropTypes.func.isRequired,
289
289
  emptyState: PropTypes.shape({}).isRequired,
290
290
  subscriptions: PropTypes.shape({
291
+ loading: PropTypes.bool,
292
+ availableQuantities: PropTypes.shape({}),
291
293
  results: PropTypes.array,
292
294
  }).isRequired,
293
295
  subscriptionDeleteModalOpen: PropTypes.bool.isRequired,
@@ -89,11 +89,17 @@ Table.propTypes = {
89
89
  emptyState: PropTypes.shape({}).isRequired,
90
90
  tableColumns: PropTypes.arrayOf(PropTypes.string).isRequired,
91
91
  subscriptions: PropTypes.shape({
92
+ searchIsActive: PropTypes.bool,
93
+ itemCount: PropTypes.number,
94
+ pagination: PropTypes.shape({}),
92
95
  results: PropTypes.array,
93
96
  }).isRequired,
94
97
  loadSubscriptions: PropTypes.func.isRequired,
95
98
  selectionController: PropTypes.shape({}).isRequired,
96
- inlineEditController: PropTypes.shape({}).isRequired,
99
+ inlineEditController: PropTypes.shape({
100
+ onCancel: PropTypes.func,
101
+ onConfirm: PropTypes.func,
102
+ }).isRequired,
97
103
  groupedSubscriptions: PropTypes.shape({}).isRequired,
98
104
  editing: PropTypes.bool.isRequired,
99
105
  rows: PropTypes.arrayOf(PropTypes.object).isRequired,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katello
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.12.0
4
+ version: 3.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - N/A
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-05 00:00:00.000000000 Z
11
+ date: 2019-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -3919,6 +3919,7 @@ files:
3919
3919
  - lib/katello/tasks/update_subscription_facet_backend_data.rake
3920
3920
  - lib/katello/tasks/upgrade_check.rake
3921
3921
  - lib/katello/tasks/upgrades/3.10/clear_invalid_repo_credentials.rake
3922
+ - lib/katello/tasks/upgrades/3.10/update_gpg_key_urls.rake
3922
3923
  - lib/katello/tasks/upgrades/3.11/import_yum_metadata_file.rake
3923
3924
  - lib/katello/tasks/upgrades/3.11/update_puppet_repos.rake
3924
3925
  - lib/katello/tasks/upgrades/3.12/remove_pulp2_notifier.rake
@@ -4244,6 +4245,7 @@ files:
4244
4245
  - webpack/scenes/Subscriptions/Details/SubscriptionDetailReducer.js
4245
4246
  - webpack/scenes/Subscriptions/Details/SubscriptionDetails.js
4246
4247
  - webpack/scenes/Subscriptions/Details/SubscriptionDetails.scss
4248
+ - webpack/scenes/Subscriptions/Details/SubscriptionPurposeAttributes.js
4247
4249
  - webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailActions.test.js
4248
4250
  - webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailAssociations.test.js
4249
4251
  - webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailInfo.test.js