katello 4.9.0.rc2 → 4.9.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +1 -4
  3. data/app/controllers/katello/api/v2/organizations_controller.rb +7 -4
  4. data/app/controllers/katello/api/v2/repositories_controller.rb +4 -4
  5. data/app/lib/actions/katello/content_view/promote_to_environment.rb +1 -1
  6. data/app/lib/actions/katello/content_view_version/republish_repositories.rb +1 -1
  7. data/app/lib/actions/katello/repository/clone_to_version.rb +1 -1
  8. data/app/lib/actions/katello/repository/multi_clone_to_version.rb +1 -1
  9. data/app/lib/katello/resources/cdn/katello_cdn.rb +8 -4
  10. data/app/services/katello/pulp3/repository.rb +1 -0
  11. data/app/services/katello/pulp3/smart_proxy_mirror_repository.rb +12 -11
  12. data/app/views/katello/api/v2/content_facet/base.json.rabl +9 -10
  13. data/app/views/katello/hosts/_errata_counts.html.erb +13 -0
  14. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repository.factory.js +1 -1
  15. data/lib/katello/plugin.rb +1 -1
  16. data/lib/katello/version.rb +1 -1
  17. data/webpack/components/RoutedTabs/index.js +1 -0
  18. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/index.js +1 -0
  19. data/webpack/components/extensions/RegistrationCommands/__tests__/__snapshots__/ActivationKeys.test.js.snap +3 -3
  20. data/webpack/components/extensions/RegistrationCommands/fields/ActivationKeys.js +3 -3
  21. data/webpack/redux/actions/RedHatRepositories/helpers.js +3 -5
  22. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +1 -14
  23. data/webpack/scenes/ContentViews/Create/__tests__/createContentView.test.js +0 -4
  24. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +1 -1
  25. data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +39 -31
  26. data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +32 -26
  27. data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +10 -2
  28. data/webpack/scenes/ContentViews/Details/Filters/CVDebFilterContent.js +10 -2
  29. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +10 -2
  30. data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +10 -2
  31. data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +10 -2
  32. data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +10 -2
  33. data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +10 -2
  34. data/webpack/scenes/ContentViews/Details/Repositories/ContentCounts.js +3 -3
  35. data/webpack/scenes/ContentViews/Details/Versions/Compare/CVVersionCompare.js +1 -0
  36. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetails.js +1 -0
  37. data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetail.test.js +28 -4
  38. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +0 -2
  39. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +15 -3
  40. metadata +5 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d870b3e8317aae2cc5675bdebddc2541257c470714209df06d79135ebc751643
4
- data.tar.gz: e19a405204719de4c723e6b7a0c4612e40983698df33562f74e28e0eb2fb83f6
3
+ metadata.gz: 41a12235a03808c77522d0fbc1c0fe8394ee1bfd6735b4a9671909ccc341bd3d
4
+ data.tar.gz: 4b6514b149494a537a41b1b944c1133328591aa9c950bf9ff343679a76532100
5
5
  SHA512:
6
- metadata.gz: ee637b366b689e48fdbde217e2255b683c35095ffcbc3ad1234b9446ba7757be992a5b33a61650dc1fc5ac25ff4474185e2e58772991475c0f6a78627bbd70c4
7
- data.tar.gz: 6eac40d9467c4365c19c82ecdce5d53f42418f511c7e35e12f987c5e58b432c3919f0ff0a2c1d581084e14e8f1ca29147f298a505331ec1d6907a6f132b4e209
6
+ metadata.gz: c7f886b06454dafcf674d3ba7694d8bf7ef79799d3e1ebc21523edb59b1139d4ca3e8ad0733ea2cd2880dcb4eebe1b52c2e675da46935192906c95ce8281f4dc
7
+ data.tar.gz: e00320f2a9a0273fd850feda7946c9fa6f2e068358fc7177e406334fa0400cd240fa36c8ed216c46e118ce64302081c9331f8101c63cee78774482836144023e
@@ -78,11 +78,8 @@ module Katello
78
78
 
79
79
  api :PUT, "/content_view_versions/:id/republish_repositories", N_("Forces a republish of the version's repositories' metadata")
80
80
  param :id, :number, :desc => N_("Content view version identifier"), :required => true
81
- param :force, :bool, :desc => N_("Force metadata regeneration to proceed. Dangerous when repositories use the 'Complete Mirroring' mirroring policy"), :required => true
81
+ param :force, :bool, :desc => N_("Force metadata regeneration to proceed. (Deprecated)"), deprecated: true
82
82
  def republish_repositories
83
- unless ::Foreman::Cast.to_bool(params[:force])
84
- fail HttpErrors::BadRequest, _("Metadata republishing must be forced because it is a dangerous operation.")
85
- end
86
83
  task = async_task(::Actions::Katello::ContentViewVersion::RepublishRepositories, @content_view_version)
87
84
  respond_for_async :resource => task
88
85
  end
@@ -180,11 +180,14 @@ module Katello
180
180
  protected
181
181
 
182
182
  def action_permission
183
- if %w(download_debug_certificate redhat_provider repo_discover cdn_configuration
184
- cancel_repo_discover).include?(params[:action])
185
- :edit
186
- elsif params[:action] == "releases"
183
+ if params[:action] == "releases"
184
+ :view
185
+ elsif params[:action] == "download_debug_certificate" &&
186
+ Organization.find(params[:id]).authorized?(:export_content)
187
187
  :view
188
+ elsif %w(download_debug_certificate redhat_provider repo_discover cdn_configuration
189
+ cancel_repo_discover).include?(params[:action])
190
+ :edit
188
191
  else
189
192
  super
190
193
  end
@@ -323,12 +323,12 @@ module Katello
323
323
  render :json => repo_types.values
324
324
  end
325
325
 
326
- api :PUT, "/repositories/:id/republish", N_("Forces a republish of the specified repository, regenerating metadata and symlinks on the filesystem.")
326
+ api :PUT, "/repositories/:id/republish", N_("Forces a republish of the specified repository, regenerating metadata and symlinks on the filesystem. Not allowed for repositories with the 'Complete Mirroring' mirroring policy.")
327
327
  param :id, :number, :desc => N_("Repository identifier"), :required => true
328
- param :force, :bool, :desc => N_("Force metadata regeneration to proceed. Dangerous when repositories use the 'Complete Mirroring' mirroring policy."), :required => true
328
+ param :force, :bool, :desc => N_("Force metadata regeneration to proceed. (Deprecated)"), deprecated: true
329
329
  def republish
330
- unless ::Foreman::Cast.to_bool(params[:force])
331
- fail HttpErrors::BadRequest, _('Metadata republishing must be forced because it is a dangerous operation.')
330
+ if @repository.mirroring_policy == Katello::RootRepository::MIRRORING_POLICY_COMPLETE
331
+ fail HttpErrors::BadRequest, _("Metadata republishing is not allowed on repositories with the 'Complete Mirroring' mirroring policy.")
332
332
  end
333
333
  task = async_task(::Actions::Katello::Repository::MetadataGenerate, @repository)
334
334
  respond_for_async :resource => task
@@ -55,7 +55,7 @@ module Actions
55
55
 
56
56
  def trigger_capsule_sync(_execution_plan)
57
57
  environment = ::Katello::KTEnvironment.find(input[:environment_id])
58
- if !input[:incremental_update] && sync_proxies?(environment)
58
+ if !input[:incremental_update] && sync_proxies?(environment) && Setting[:foreman_proxy_content_auto_sync]
59
59
  ForemanTasks.async_task(ContentView::CapsuleSync,
60
60
  ::Katello::ContentView.find(input[:content_view_id]),
61
61
  environment)
@@ -5,7 +5,7 @@ module Actions
5
5
  def plan(content_view_version)
6
6
  action_subject(content_view_version.content_view)
7
7
  plan_self(:version_id => content_view_version.id)
8
- plan_action(::Actions::Katello::Repository::BulkMetadataGenerate, content_view_version.repositories)
8
+ plan_action(::Actions::Katello::Repository::BulkMetadataGenerate, content_view_version.repositories.joins(:root).where.not(root: { mirroring_policy: ::Katello::RootRepository::MIRRORING_POLICY_COMPLETE }))
9
9
  end
10
10
 
11
11
  def run
@@ -23,7 +23,7 @@ module Actions
23
23
  rpm_filenames: rpm_filenames,
24
24
  copy_contents: copy_contents,
25
25
  solve_dependencies: content_view.solve_dependencies,
26
- metadata_generate: !incremental)
26
+ generate_metadata: true)
27
27
  end
28
28
  end
29
29
 
@@ -10,7 +10,7 @@ module Actions
10
10
  plan_action(::Actions::Katello::Repository::MultiCloneContents, extended_repo_map,
11
11
  copy_contents: true,
12
12
  solve_dependencies: true,
13
- metadata_generate: !incremental)
13
+ generate_metadata: true)
14
14
  end
15
15
  end
16
16
 
@@ -11,10 +11,14 @@ module Katello
11
11
  super
12
12
  end
13
13
 
14
- def fetch_paths(content_path)
14
+ def fetch_repo_set(content_path)
15
15
  url = "/katello/api/v2/repository_sets?organization_id=#{organization['id']}&search=#{CGI.escape("path = #{content_path}")}"
16
16
  response = get(url)
17
- repo_set = JSON.parse(response)['results'].first
17
+ JSON.parse(response)['results'].first
18
+ end
19
+
20
+ def fetch_paths(content_path)
21
+ repo_set = fetch_repo_set(content_path)
18
22
 
19
23
  fail _("Upstream organization %s does not provide this content path") % @organization_label if repo_set.nil?
20
24
 
@@ -33,8 +37,8 @@ module Katello
33
37
  results = json_body['results']
34
38
 
35
39
  results.map do |repo|
36
- Katello::Content.substitute_content_path(arch: repo[:arch],
37
- releasever: repo[:minor],
40
+ Katello::Content.substitute_content_path(arch: repo['arch'],
41
+ releasever: repo['minor'],
38
42
  content_path: content_path)
39
43
  end
40
44
  end
@@ -39,6 +39,7 @@ module Katello
39
39
 
40
40
  def self.api(smart_proxy, repository_type_label)
41
41
  repo_type = RepositoryTypeManager.enabled_repository_types[repository_type_label]
42
+ fail _("%s content type is not enabled." % repository_type_label) unless repo_type
42
43
  repo_type.pulp3_api(smart_proxy)
43
44
  end
44
45
 
@@ -79,18 +79,19 @@ module Katello
79
79
  known_acss = smart_proxy.smart_proxy_alternate_content_sources
80
80
  known_acs_hrefs = known_acss.pluck(:alternate_content_source_href) if known_acss.present?
81
81
 
82
- file_acs_api = ::Katello::Pulp3::Repository.api(smart_proxy, 'file').alternate_content_source_api
83
- yum_acs_api = ::Katello::Pulp3::Repository.api(smart_proxy, 'yum').alternate_content_source_api
84
-
85
- orphan_file_acs_hrefs = file_acs_api.list.results.map(&:pulp_href) - known_acs_hrefs
86
- orphan_yum_acs_hrefs = yum_acs_api.list.results.map(&:pulp_href) - known_acs_hrefs
87
-
88
- orphan_file_acs_hrefs.each do |orphan_file_acs_href|
89
- tasks << file_acs_api.delete(orphan_file_acs_href)
82
+ if RepositoryTypeManager.enabled_repository_types['file']
83
+ file_acs_api = ::Katello::Pulp3::Repository.api(smart_proxy, 'file').alternate_content_source_api
84
+ orphan_file_acs_hrefs = file_acs_api.list.results.map(&:pulp_href) - known_acs_hrefs
85
+ orphan_file_acs_hrefs.each do |orphan_file_acs_href|
86
+ tasks << file_acs_api.delete(orphan_file_acs_href)
87
+ end
90
88
  end
91
-
92
- orphan_yum_acs_hrefs.each do |orphan_yum_acs_href|
93
- tasks << yum_acs_api.delete(orphan_yum_acs_href)
89
+ if RepositoryTypeManager.enabled_repository_types['yum']
90
+ yum_acs_api = ::Katello::Pulp3::Repository.api(smart_proxy, 'yum').alternate_content_source_api
91
+ orphan_yum_acs_hrefs = yum_acs_api.list.results.map(&:pulp_href) - known_acs_hrefs
92
+ orphan_yum_acs_hrefs.each do |orphan_yum_acs_href|
93
+ tasks << yum_acs_api.delete(orphan_yum_acs_href)
94
+ end
94
95
  end
95
96
  end
96
97
 
@@ -1,6 +1,4 @@
1
1
  attributes :id, :uuid
2
- attributes :content_view_id, :content_view_name
3
- attributes :lifecycle_environment_id, :lifecycle_environment_name
4
2
  attributes :content_source_id, :content_source_name
5
3
  attributes :kickstart_repository_id, :kickstart_repository_name
6
4
  attributes :errata_counts
@@ -10,6 +8,15 @@ attributes :applicable_rpm_count => :applicable_package_count
10
8
  attributes :upgradable_rpm_count => :upgradable_package_count
11
9
  attributes :applicable_module_stream_count, :upgradable_module_stream_count
12
10
 
11
+ child :content_view_environments => :content_view_environments do
12
+ node :content_view do |cve|
13
+ { id: cve.content_view.id, name: cve.content_view.name, composite: cve.content_view.composite }
14
+ end
15
+ node :lifecycle_environment do |cve|
16
+ { id: cve.lifecycle_environment.id, name: cve.lifecycle_environment.name }
17
+ end
18
+ end
19
+
13
20
  node :content_view do |content_facet|
14
21
  content_view = content_facet.single_content_view
15
22
  if content_view.present?
@@ -31,14 +38,6 @@ node :lifecycle_environment do |content_facet|
31
38
  end
32
39
  end
33
40
 
34
- child :content_views => :content_views do
35
- attributes :id, :name, :composite
36
- end
37
-
38
- child :lifecycle_environments => :lifecycle_environments do
39
- attributes :id, :name
40
- end
41
-
42
41
  child :content_source => :content_source do
43
42
  attributes :id, :name, :url
44
43
  end
@@ -1,4 +1,8 @@
1
+ <% if Setting["host_details_ui"] %>
2
+ <a href="/new/hosts/<%= host.name %>#/Content/errata">
3
+ <% else %>
1
4
  <a href="/content_hosts/<%= host.id %>/errata">
5
+ <% end %>
2
6
  <span class="aligned-errata-count">
3
7
  <span class="errata-count <%= counts[:security].to_i.positive? ? 'red' : 'black' %>">
4
8
  <span>
@@ -20,8 +24,13 @@
20
24
  </span>
21
25
  </span>
22
26
  </a>
27
+
23
28
  <% if !host.operatingsystem_name&.match(/Debian|Ubuntu/) %>
29
+ <% if Setting["host_details_ui"] %>
30
+ <a href="/new/hosts/<%= host.name %>#/Content/packages">
31
+ <% else %>
24
32
  <a href="/content_hosts/<%= host.id %>/packages/applicable">
33
+ <% end %>
25
34
  <span class="aligned-errata-count">
26
35
  <span class="errata-count <%= host.content_facet_attributes&.upgradable_rpm_count&.positive? ? 'green' : 'black' %>"
27
36
  <span>
@@ -33,7 +42,11 @@
33
42
  </a>
34
43
  <% end %>
35
44
  <% if host.operatingsystem_name&.match(/Debian|Ubuntu/) %>
45
+ <% if Setting["host_details_ui"] %>
46
+ <a href="/new/hosts/<%= host.name %>#/Content/packages">
47
+ <% else %>
36
48
  <a href="/content_hosts/<%= host.id %>/debs/applicable">
49
+ <% end %>
37
50
  <span class="aligned-errata-count">
38
51
  <span class="errata-count <%= host.content_facet_attributes&.upgradable_deb_count&.positive? ? 'green' : 'black' %>"
39
52
  <span>
@@ -18,7 +18,7 @@ angular.module('Bastion.repositories').factory('Repository',
18
18
  update: { method: 'PUT' },
19
19
  sync: { method: 'POST', params: { action: 'sync' } },
20
20
  verifyChecksum: { method: 'POST', params: { action: 'verify_checksum' }},
21
- republishMetadata: { method: 'PUT', params: { action: 'republish', force: true }},
21
+ republishMetadata: { method: 'PUT', params: { action: 'republish'}},
22
22
  reclaimSpace: { method: 'POST', params: { action: 'reclaim_space' }},
23
23
  removePackages: { method: 'PUT', params: { action: 'remove_packages'}},
24
24
  removeContent: { method: 'PUT', params: { action: 'remove_content'}},
@@ -748,7 +748,7 @@ Foreman::Plugin.register :katello do
748
748
  :attach_subscriptions, :view_host_collections,
749
749
  :view_organizations, :view_lifecycle_environments, :view_products,
750
750
  :view_locations, :view_domains, :view_architectures,
751
- :view_operatingsystems, :view_smart_proxies
751
+ :view_operatingsystems, :view_smart_proxies, :view_params
752
752
  ]
753
753
 
754
754
  role 'Content Importer', [
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "4.9.0.rc2".freeze
2
+ VERSION = "4.9.0".freeze
3
3
  end
@@ -23,6 +23,7 @@ const RoutedTabs = ({
23
23
  >
24
24
  {tabs.map(({ key, title }) => (
25
25
  <Tab
26
+ ouiaId={`routed-tabs-tab-${key}`}
26
27
  href={`#/${key}`}
27
28
  key={key}
28
29
  eventKey={key}
@@ -24,6 +24,7 @@ const ContentTab = ({ location: { pathname } }) => {
24
24
  >
25
25
  {filteredTabs.map(({ key, title }) => (
26
26
  <Tab
27
+ ouiaId={`host-content-tabs-tab-${key}`}
27
28
  key={key}
28
29
  eventKey={key}
29
30
  title={<TabTitleText>{title}</TabTitleText>}
@@ -2,7 +2,7 @@
2
2
 
3
3
  exports[`ActivationKeys renders 1`] = `
4
4
  <FormGroup
5
- fieldId="reg_katello_ak"
5
+ fieldId="activation_keys_field"
6
6
  helperText="From host group: "
7
7
  helperTextInvalid={
8
8
  <a
@@ -36,7 +36,7 @@ exports[`ActivationKeys renders 1`] = `
36
36
  favoritesLabel="Favorites"
37
37
  hasInlineFilter={false}
38
38
  hasPlaceholderStyle={false}
39
- id="reg_katello_ak"
39
+ id="activation_keys_field"
40
40
  inlineFilterPlaceholderText={null}
41
41
  inputAutoComplete="off"
42
42
  inputIdPrefix=""
@@ -58,7 +58,7 @@ exports[`ActivationKeys renders 1`] = `
58
58
  onSelect={[Function]}
59
59
  onToggle={[Function]}
60
60
  onTypeaheadInputChanged={null}
61
- ouiaId="reg-katello-ak"
61
+ ouiaId="activation-keys-field"
62
62
  ouiaSafe={true}
63
63
  placeholderText="No Activation keys to select"
64
64
  position="left"
@@ -45,7 +45,7 @@ const ActivationKeys = ({
45
45
  return (
46
46
  <FormGroup
47
47
  label={__('Activation Keys')}
48
- fieldId="reg_katello_ak"
48
+ fieldId="activation_keys_field"
49
49
  helperText={hostGroupActivationKeys && sprintf('From host group: %s', hostGroupActivationKeys)}
50
50
  helperTextInvalid={activationKeys?.length === 0 ? <a href="/activation_keys/new">{__('Create new activation key')}</a> : __('No Activation Keys selected')}
51
51
  validated={validateAKField(hostGroupId, pluginValues?.activationKeys, hostGroupActivationKeys)}
@@ -53,14 +53,14 @@ const ActivationKeys = ({
53
53
  isRequired
54
54
  >
55
55
  <Select
56
- ouiaId="reg-katello-ak"
56
+ ouiaId="activation-keys-field"
57
57
  selections={selectedKeys}
58
58
  variant={SelectVariant.typeaheadMulti}
59
59
  onToggle={() => setIsOpen(!isOpen)}
60
60
  onSelect={onSelect}
61
61
  onClear={() => updatePluginValues([])}
62
62
  isOpen={isOpen}
63
- id="reg_katello_ak"
63
+ id="activation_keys_field"
64
64
  className="without_select2"
65
65
  isDisabled={isLoading || activationKeys?.length === 0}
66
66
  placeholderText={activationKeys?.length === 0 ? __('No Activation keys to select') : ''}
@@ -24,7 +24,6 @@ const recommendedRepositoriesRHEL = [
24
24
  'rhel-7-server-optional-rpms',
25
25
  'rhel-7-server-extras-rpms',
26
26
  'rhel-7-server-kickstart',
27
- 'rhel-6-server-els-rpms',
28
27
  ];
29
28
 
30
29
  const recommendedRepositoriesSatTools = [
@@ -35,10 +34,9 @@ const recommendedRepositoriesSatTools = [
35
34
  ];
36
35
 
37
36
  const recommendedRepositoriesMisc = [
38
- 'satellite-capsule-6.13-for-rhel-8-x86_64-rpms',
39
- 'ansible-2-for-rhel-8-x86_64-rpms',
40
- 'satellite-maintenance-6.13-for-rhel-8-x86_64-rpms',
41
- 'satellite-utils-6.13-for-rhel-8-x86_64-rpms',
37
+ 'satellite-capsule-6.14-for-rhel-8-x86_64-rpms',
38
+ 'satellite-maintenance-6.14-for-rhel-8-x86_64-rpms',
39
+ 'satellite-utils-6.14-for-rhel-8-x86_64-rpms',
42
40
  ];
43
41
 
44
42
  const recommendedRepositorySetLables = recommendedRepositoriesRHEL
@@ -7,7 +7,7 @@ import { useDispatch, useSelector } from 'react-redux';
7
7
  import { Form, FormGroup, TextInput, TextArea, Checkbox, ActionGroup, Button, Tile, Grid, GridItem } from '@patternfly/react-core';
8
8
  import { createContentView } from '../ContentViewsActions';
9
9
  import { selectCreateContentViews, selectCreateContentViewStatus, selectCreateContentViewError } from './ContentViewCreateSelectors';
10
- import { LabelDependencies, LabelAutoPublish, LabelImportOnly } from './ContentViewFormComponents';
10
+ import { LabelDependencies, LabelAutoPublish } from './ContentViewFormComponents';
11
11
  import ContentViewIcon from '../components/ContentViewIcon';
12
12
  import './CreateContentViewForm.scss';
13
13
 
@@ -19,7 +19,6 @@ const CreateContentViewForm = ({ setModalOpen }) => {
19
19
  const [composite, setComposite] = useState(false);
20
20
  const [component, setComponent] = useState(true);
21
21
  const [autoPublish, setAutoPublish] = useState(false);
22
- const [importOnly, setImportOnly] = useState(false);
23
22
  const [dependencies, setDependencies] = useState(false);
24
23
  const [redirect, setRedirect] = useState(false);
25
24
  const [saving, setSaving] = useState(false);
@@ -59,7 +58,6 @@ const CreateContentViewForm = ({ setModalOpen }) => {
59
58
  composite,
60
59
  solve_dependencies: dependencies,
61
60
  auto_publish: (autoPublish && composite),
62
- import_only: importOnly,
63
61
  }));
64
62
  };
65
63
 
@@ -168,17 +166,6 @@ const CreateContentViewForm = ({ setModalOpen }) => {
168
166
  onChange={checked => setDependencies(checked)}
169
167
  />
170
168
  </FormGroup>}
171
- {!composite &&
172
- <FormGroup isInline fieldId="importOnly">
173
- <Checkbox
174
- id="importOnly"
175
- ouiaId="importOnly"
176
- name="importOnly"
177
- label={LabelImportOnly()}
178
- isChecked={importOnly}
179
- onChange={checked => setImportOnly(checked)}
180
- />
181
- </FormGroup>}
182
169
  {composite &&
183
170
  <FormGroup isInline fieldId="autoPublish">
184
171
  <Checkbox
@@ -24,7 +24,6 @@ const createDetails = {
24
24
  composite: false,
25
25
  solve_dependencies: false,
26
26
  auto_publish: false,
27
- import_only: false,
28
27
  };
29
28
 
30
29
  const createdCVDetails = { ...cvCreateData };
@@ -78,7 +77,6 @@ test('Displays dependent fields correctly', () => {
78
77
  expect(getByText('Content view')).toBeInTheDocument();
79
78
  expect(getByText('Solve dependencies')).toBeInTheDocument();
80
79
  expect(queryByText('Auto publish')).not.toBeInTheDocument();
81
- expect(getByText('Import only')).toBeInTheDocument();
82
80
 
83
81
  // label auto_set
84
82
  fireEvent.change(getByLabelText('input_name'), { target: { value: '123 2123' } });
@@ -88,13 +86,11 @@ test('Displays dependent fields correctly', () => {
88
86
  fireEvent.click(getByLabelText('composite_tile'));
89
87
  expect(queryByText('Solve dependencies')).not.toBeInTheDocument();
90
88
  expect(getByText('Auto publish')).toBeInTheDocument();
91
- expect(queryByText('Import only')).not.toBeInTheDocument();
92
89
 
93
90
  // display Solve Dependencies when Component CV
94
91
  fireEvent.click(getByLabelText('component_tile'));
95
92
  expect(getByText('Solve dependencies')).toBeInTheDocument();
96
93
  expect(queryByText('Auto publish')).not.toBeInTheDocument();
97
- expect(getByText('Import only')).toBeInTheDocument();
98
94
  });
99
95
 
100
96
  test('Validates label field', () => {
@@ -592,7 +592,7 @@ export const republishCVVRepoMetadata = (params, handleSuccess) => put({
592
592
  type: API_OPERATIONS.PUT,
593
593
  key: cvVersionRepublishRepoMetadataKey(params.cvId, params.id),
594
594
  url: api.getApiUrl(`/content_view_versions/${params.id}/republish_repositories`),
595
- params: { ...params, force: true },
595
+ params,
596
596
  handleSuccess: (response) => {
597
597
  if (handleSuccess) return handleSuccess();
598
598
  return renderTaskStartedToast(response.data);
@@ -105,39 +105,47 @@ export default () => {
105
105
  generated_for: generatedFor, import_only: importOnly,
106
106
  } = details;
107
107
  const generatedContentView = generatedFor !== 'none';
108
+ const detailsTab = {
109
+ key: 'details',
110
+ title: __('Details'),
111
+ content: <ContentViewInfo {...{ cvId, details }} />,
112
+ };
113
+ const versionsTab = {
114
+ key: 'versions',
115
+ title: __('Versions'),
116
+ content: <ContentViewVersionsRoutes {...{ cvId, details }} />,
117
+ };
118
+ const contentViewsTab = {
119
+ key: 'contentviews',
120
+ title: __('Content views'),
121
+ content: <ContentViewComponents {...{ cvId, details }} />,
122
+ };
123
+ const repositoriesTab = {
124
+ key: 'repositories',
125
+ title: __('Repositories'),
126
+ content: <ContentViewRepositories {...{ cvId, details }} />,
127
+ };
128
+ const filtersTab = {
129
+ key: 'filters',
130
+ title: __('Filters'),
131
+ content: <ContentViewFilterRoutes {...{ cvId, details }} />,
132
+ };
133
+ const historyTab = {
134
+ key: 'history',
135
+ title: __('History'),
136
+ content: <ContentViewHistories cvId={cvId} />,
137
+ };
138
+
139
+ /* eslint-disable no-nested-ternary */
108
140
  const tabs = [
109
- {
110
- key: 'details',
111
- title: __('Details'),
112
- content: <ContentViewInfo {...{ cvId, details }} />,
113
- },
114
- {
115
- key: 'versions',
116
- title: __('Versions'),
117
- content: <ContentViewVersionsRoutes {...{ cvId, details }} />,
118
- },
119
- ...composite ? [{
120
- key: 'contentviews',
121
- title: __('Content views'),
122
- content: <ContentViewComponents {...{ cvId, details }} />,
123
- }] : [{
124
- key: 'repositories',
125
- title: __('Repositories'),
126
- content: <ContentViewRepositories {...{ cvId, details }} />,
127
- },
128
- !(importOnly || generatedContentView) &&
129
- {
130
- key: 'filters',
131
- title: __('Filters'),
132
- content: <ContentViewFilterRoutes {...{ cvId, details }} />,
133
- }],
134
- {
135
- key: 'history',
136
- title: __('History'),
137
- content: <ContentViewHistories cvId={cvId} />,
138
- },
141
+ detailsTab,
142
+ versionsTab,
143
+ ...(composite ? [contentViewsTab] :
144
+ ((importOnly || generatedContentView) ?
145
+ [repositoriesTab] : [repositoriesTab, filtersTab])),
146
+ historyTab,
139
147
  ];
140
-
148
+ /* eslint-enable no-nested-ternary */
141
149
 
142
150
  return (
143
151
  <>
@@ -111,32 +111,38 @@ const ContentViewInfo = ({ cvId, details }) => {
111
111
  boolean
112
112
  {...{ currentAttribute, setCurrentAttribute }}
113
113
  />)}
114
- <TextListItem component={TextListItemVariants.dt}>
115
- {LabelImportOnly()}
116
- </TextListItem>
117
- <TextListItem component={TextListItemVariants.dd} className="foreman-spaced-list">
118
- <Switch
119
- id="import_only_switch"
120
- ouiaId="import_only_switch"
121
- aria-label="import_only_switch"
122
- isChecked={importOnly}
123
- className="foreman-spaced-list"
124
- disabled
125
- />
126
- </TextListItem>
127
- <TextListItem component={TextListItemVariants.dt}>
128
- {LabelGenerated()}
129
- </TextListItem>
130
- <TextListItem component={TextListItemVariants.dd} className="foreman-spaced-list">
131
- <Switch
132
- id="generated_by_export_switch"
133
- ouiaId="generated_by_export_switch"
134
- aria-label="generated_by_export_switch"
135
- isChecked={generatedContentView}
136
- className="foreman-spaced-list"
137
- disabled
138
- />
139
- </TextListItem>
114
+ {importOnly &&
115
+ <>
116
+ <TextListItem component={TextListItemVariants.dt}>
117
+ {LabelImportOnly()}
118
+ </TextListItem>
119
+ <TextListItem component={TextListItemVariants.dd} className="foreman-spaced-list">
120
+ <Switch
121
+ id="import_only_switch"
122
+ ouiaId="import_only_switch"
123
+ aria-label="import_only_switch"
124
+ isChecked={importOnly}
125
+ className="foreman-spaced-list"
126
+ disabled
127
+ />
128
+ </TextListItem>
129
+ </>}
130
+ {generatedContentView &&
131
+ <>
132
+ <TextListItem component={TextListItemVariants.dt}>
133
+ {LabelGenerated()}
134
+ </TextListItem>
135
+ <TextListItem component={TextListItemVariants.dd} className="foreman-spaced-list">
136
+ <Switch
137
+ id="generated_by_export_switch"
138
+ ouiaId="generated_by_export_switch"
139
+ aria-label="generated_by_export_switch"
140
+ isChecked={generatedContentView}
141
+ className="foreman-spaced-list"
142
+ disabled
143
+ />
144
+ </TextListItem>
145
+ </>}
140
146
  </TextList>
141
147
  </TextContent>
142
148
  );
@@ -135,7 +135,11 @@ const CVContainerImageFilterContent = ({
135
135
  ouiaId="cv-container-image-filter-tabs"
136
136
  onSelect={(_event, eventKey) => setActiveTabKey(eventKey)}
137
137
  >
138
- <Tab eventKey={0} title={<TabTitleText>{__('Tags')}</TabTitleText>}>
138
+ <Tab
139
+ ouiaId="cv-container-image-filter-tags-tab"
140
+ eventKey={0}
141
+ title={<TabTitleText>{__('Tags')}</TabTitleText>}
142
+ >
139
143
  <div className="margin-24-0">
140
144
  <TableWrapper
141
145
  {...{
@@ -200,7 +204,11 @@ const CVContainerImageFilterContent = ({
200
204
  </div>
201
205
  </Tab>
202
206
  {(repositories.length || showAffectedRepos) &&
203
- <Tab eventKey={1} title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}>
207
+ <Tab
208
+ ouiaId="cv-container-image-affected-repos-tab"
209
+ eventKey={1}
210
+ title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}
211
+ >
204
212
  <div className="margin-24-0">
205
213
  <AffectedRepositoryTable cvId={cvId} filterId={filterId} repoType="docker" setShowAffectedRepos={setShowAffectedRepos} details={details} />
206
214
  </div>
@@ -150,7 +150,11 @@ const CVDebFilterContent = ({
150
150
  activeKey={activeTabKey}
151
151
  onSelect={(_event, eventKey) => setActiveTabKey(eventKey)}
152
152
  >
153
- <Tab eventKey={0} title={<TabTitleText>{tabTitle}</TabTitleText>}>
153
+ <Tab
154
+ ouiaId="cv-deb-filter-content-table-tab"
155
+ eventKey={0}
156
+ title={<TabTitleText>{tabTitle}</TabTitleText>}
157
+ >
154
158
  <div className="tab-body-with-spacing">
155
159
  <TableWrapper
156
160
  {...{
@@ -225,7 +229,11 @@ const CVDebFilterContent = ({
225
229
  </div>
226
230
  </Tab>
227
231
  {(repositories.length || showAffectedRepos) &&
228
- <Tab eventKey={1} title={<TabTitleText>{__('Affected Repositories')}</TabTitleText>}>
232
+ <Tab
233
+ ouiaId="cv-deb-filter-content-affected-repos-tab"
234
+ eventKey={1}
235
+ title={<TabTitleText>{__('Affected Repositories')}</TabTitleText>}
236
+ >
229
237
  <div className="tab-body-with-spacing">
230
238
  <AffectedRepositoryTable cvId={cvId} filterId={filterId} repoType="deb" setShowAffectedRepos={setShowAffectedRepos} details={details} />
231
239
  </div>
@@ -119,7 +119,11 @@ const CVErrataDateFilterContent = ({
119
119
  activeKey={activeTabKey}
120
120
  onSelect={(_event, eventKey) => setActiveTabKey(eventKey)}
121
121
  >
122
- <Tab eventKey={0} title={<TabTitleText>{tabTitle}</TabTitleText>}>
122
+ <Tab
123
+ ouiaId="errata-date-filter-form-tab"
124
+ eventKey={0}
125
+ title={<TabTitleText>{tabTitle}</TabTitleText>}
126
+ >
123
127
  <div className="margin-24">
124
128
  <Form onSubmit={(e) => {
125
129
  e.preventDefault();
@@ -309,7 +313,11 @@ const CVErrataDateFilterContent = ({
309
313
  </div>
310
314
  </Tab>
311
315
  {(repositories.length || showAffectedRepos) &&
312
- <Tab eventKey={1} title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}>
316
+ <Tab
317
+ ouiaId="affected-repositories-tab"
318
+ eventKey={1}
319
+ title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}
320
+ >
313
321
  <div className="margin-24-0">
314
322
  <AffectedRepositoryTable cvId={cvId} filterId={filterId} repoType="yum" setShowAffectedRepos={setShowAffectedRepos} details={details} />
315
323
  </div>
@@ -251,7 +251,11 @@ const CVErrataIDFilterContent = ({
251
251
  activeKey={activeTabKey}
252
252
  onSelect={(_event, eventKey) => setActiveTabKey(eventKey)}
253
253
  >
254
- <Tab eventKey={0} title={<TabTitleText>{__('Errata')}</TabTitleText>}>
254
+ <Tab
255
+ ouiaId="errata-filter-table-tab"
256
+ eventKey={0}
257
+ title={<TabTitleText>{__('Errata')}</TabTitleText>}
258
+ >
255
259
  <div className="margin-24-0">
256
260
  <TableWrapper
257
261
  {...{
@@ -452,7 +456,11 @@ const CVErrataIDFilterContent = ({
452
456
  </div>
453
457
  </Tab>
454
458
  {(repositories.length || showAffectedRepos) &&
455
- <Tab eventKey={1} title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}>
459
+ <Tab
460
+ ouiaId="affected-repos-tab"
461
+ eventKey={1}
462
+ title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}
463
+ >
456
464
  <div className="margin-24-0">
457
465
  <AffectedRepositoryTable cvId={cvId} filterId={filterId} repoType="yum" setShowAffectedRepos={setShowAffectedRepos} details={details} />
458
466
  </div>
@@ -207,7 +207,11 @@ const CVModuleStreamFilterContent = ({
207
207
  activeKey={activeTabKey}
208
208
  onSelect={(_event, eventKey) => setActiveTabKey(eventKey)}
209
209
  >
210
- <Tab eventKey={0} title={<TabTitleText>{__('Module Streams')}</TabTitleText>}>
210
+ <Tab
211
+ ouiaId="module-stream-filter-content-table-tab"
212
+ eventKey={0}
213
+ title={<TabTitleText>{__('Module Streams')}</TabTitleText>}
214
+ >
211
215
  <div className="margin-24-0">
212
216
  <TableWrapper
213
217
  {...{
@@ -285,7 +289,11 @@ const CVModuleStreamFilterContent = ({
285
289
  </div>
286
290
  </Tab>
287
291
  {(repositories.length || showAffectedRepos) &&
288
- <Tab eventKey={1} title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}>
292
+ <Tab
293
+ ouiaId="affected-repos-tab"
294
+ eventKey={1}
295
+ title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}
296
+ >
289
297
  <div className="margin-24-0">
290
298
  <AffectedRepositoryTable cvId={cvId} filterId={filterId} repoType="yum" setShowAffectedRepos={setShowAffectedRepos} details={details} />
291
299
  </div>
@@ -197,7 +197,11 @@ const CVPackageGroupFilterContent = ({
197
197
  activeKey={activeTabKey}
198
198
  onSelect={(_event, eventKey) => setActiveTabKey(eventKey)}
199
199
  >
200
- <Tab eventKey={0} title={<TabTitleText>{__('Package groups')}</TabTitleText>}>
200
+ <Tab
201
+ ouiaId="cv-package-group-filter-content-table-tab"
202
+ eventKey={0}
203
+ title={<TabTitleText>{__('Package groups')}</TabTitleText>}
204
+ >
201
205
  <div className="margin-24-0">
202
206
  <TableWrapper
203
207
  {...{
@@ -275,7 +279,11 @@ const CVPackageGroupFilterContent = ({
275
279
  </div>
276
280
  </Tab>
277
281
  {(repositories.length || showAffectedRepos) &&
278
- <Tab eventKey={1} title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}>
282
+ <Tab
283
+ ouiaId="affected-repos-tab"
284
+ eventKey={1}
285
+ title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}
286
+ >
279
287
  <div className="margin-24-0">
280
288
  <AffectedRepositoryTable cvId={cvId} filterId={filterId} repoType="yum" setShowAffectedRepos={setShowAffectedRepos} details={details} />
281
289
  </div>
@@ -167,7 +167,11 @@ const CVRpmFilterContent = ({
167
167
  activeKey={activeTabKey}
168
168
  onSelect={(_event, eventKey) => setActiveTabKey(eventKey)}
169
169
  >
170
- <Tab eventKey={0} title={<TabTitleText>{tabTitle}</TabTitleText>}>
170
+ <Tab
171
+ ouiaId="cv-rpm-filter-content-table-tab"
172
+ eventKey={0}
173
+ title={<TabTitleText>{tabTitle}</TabTitleText>}
174
+ >
171
175
  <div className="margin-24-0">
172
176
  <TableWrapper
173
177
  {...{
@@ -239,7 +243,11 @@ const CVRpmFilterContent = ({
239
243
  </div>
240
244
  </Tab>
241
245
  {(repositories.length || showAffectedRepos) &&
242
- <Tab eventKey={1} title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}>
246
+ <Tab
247
+ ouiaId="cv-rpm-filter-content-affected-repos-tab"
248
+ eventKey={1}
249
+ title={<TabTitleText>{__('Affected repositories')}</TabTitleText>}
250
+ >
243
251
  <div className="margin-24-0">
244
252
  <AffectedRepositoryTable cvId={cvId} filterId={filterId} repoType="yum" setShowAffectedRepos={setShowAffectedRepos} details={details} />
245
253
  </div>
@@ -12,9 +12,9 @@ const repoLabels = {
12
12
  erratum: ['errata', 'erratum', 'errata'], // need to handle link, its $URL/errata?repositoryId=107
13
13
  deb: ['deb packages', 'deb package', 'debs'],
14
14
  ansible_collection: ['Ansible collections', 'Ansible collection', 'ansible_collections'],
15
- docker_manifest: ['container manifests', 'container manifest', 'content/docker_manifests'],
16
- docker_manifest_list: ['container manifest lists', 'container manifest list', 'content/docker_manifest_lists'],
17
- docker_tag: ['container tags', 'container tag', 'content/docker_tags'],
15
+ docker_manifest: ['container manifests', 'container manifest', 'docker_manifests'],
16
+ docker_manifest_list: ['container manifest lists', 'container manifest list', 'docker_manifest_lists'],
17
+ docker_tag: ['container tags', 'container tag', 'docker_tags'],
18
18
  file: ['files', 'file', 'content/files'],
19
19
  package_group: ['package groups', 'package group', 'package_groups'],
20
20
  srpm: ['source RPMs', 'source RPM', 'source_rpms'], // no link?
@@ -106,6 +106,7 @@ const CVVersionCompare = ({
106
106
  const { name } = config;
107
107
  return (
108
108
  <Tab
109
+ ouiaId={`cv-version-compare-tab-${name}`}
109
110
  key={name}
110
111
  eventKey={name}
111
112
  title={
@@ -76,6 +76,7 @@ const ContentViewVersionDetails = ({ cvId, details }) => {
76
76
  >
77
77
  {filteredTableConfigs.map(({ route, name, getCountKey }) => (
78
78
  <Tab
79
+ ouiaId={`cv-version-details-tabs-tab-${route}`}
79
80
  key={route}
80
81
  eventKey={route}
81
82
  title={
@@ -28,7 +28,7 @@ test('Can call API and show details on page load', async (done) => {
28
28
  .query(true)
29
29
  .reply(200, cvDetailData);
30
30
 
31
- const { getByLabelText } = renderWithRedux(
31
+ const { getByLabelText, queryByLabelText } = renderWithRedux(
32
32
  withCVRoute(<ContentViewDetails />),
33
33
  renderOptions,
34
34
  );
@@ -40,6 +40,8 @@ test('Can call API and show details on page load', async (done) => {
40
40
  expect(getByLabelText('a_cv_index')).toBeInTheDocument();
41
41
  expect(getByLabelText(`b_${name}`)).toBeInTheDocument();
42
42
  expect(getByLabelText('c_details')).toBeInTheDocument();
43
+ expect(queryByLabelText('Import only')).not.toBeInTheDocument();
44
+ expect(queryByLabelText('Generated')).not.toBeInTheDocument();
43
45
  });
44
46
 
45
47
  assertNockRequest(scope, done);
@@ -98,7 +100,7 @@ test('Can edit boolean details such as solve dependencies', async (done) => {
98
100
  .query(true)
99
101
  .reply(200, updatedCVDetails);
100
102
 
101
- const { getByLabelText } = renderWithRedux(
103
+ const { getByLabelText, queryByLabelText } = renderWithRedux(
102
104
  withCVRoute(<ContentViewDetails />),
103
105
  renderOptions,
104
106
  );
@@ -110,8 +112,7 @@ test('Can edit boolean details such as solve dependencies', async (done) => {
110
112
  await patientlyWaitFor(() => expect(getByLabelText(checkboxLabel).checked).toBeTruthy());
111
113
 
112
114
  const disabledImportLabel = /import_only_switch/;
113
- expect(getByLabelText(disabledImportLabel)).toBeInTheDocument();
114
- expect(getByLabelText(disabledImportLabel)).toHaveAttribute('disabled');
115
+ expect(queryByLabelText(disabledImportLabel)).not.toBeInTheDocument();
115
116
 
116
117
  assertNockRequest(getscope);
117
118
  assertNockRequest(updatescope);
@@ -137,3 +138,26 @@ test('Can link to view tasks', async () => {
137
138
 
138
139
  assertNockRequest(scope);
139
140
  });
141
+
142
+ test('Can show import_only and generated when true', async (done) => {
143
+ const updatedCVDetails = { ...cvDetailData };
144
+ updatedCVDetails.generated_for = 'Library';
145
+ updatedCVDetails.import_only = true;
146
+
147
+ const scope = nockInstance
148
+ .get(cvDetailsPath)
149
+ .query(true)
150
+ .reply(200, updatedCVDetails);
151
+
152
+ const { getByLabelText } = renderWithRedux(
153
+ withCVRoute(<ContentViewDetails />),
154
+ renderOptions,
155
+ );
156
+
157
+ await patientlyWaitFor(() => {
158
+ expect(getByLabelText('import_only_switch')).toBeInTheDocument();
159
+ expect(getByLabelText('generated_by_export_switch')).toBeInTheDocument();
160
+ });
161
+
162
+ assertNockRequest(scope, done);
163
+ });
@@ -351,7 +351,6 @@ test('Displays Create Content View and opens modal with Form', async () => {
351
351
  expect(queryByText('Content view')).not.toBeInTheDocument();
352
352
  expect(queryByText('Solve dependencies')).not.toBeInTheDocument();
353
353
  expect(queryByText('Auto publish')).not.toBeInTheDocument();
354
- expect(queryByText('Import only')).not.toBeInTheDocument();
355
354
 
356
355
  getByLabelText('create_content_view').click();
357
356
 
@@ -362,7 +361,6 @@ test('Displays Create Content View and opens modal with Form', async () => {
362
361
  expect(getByText('Content view')).toBeInTheDocument();
363
362
  expect(getByText('Solve dependencies')).toBeInTheDocument();
364
363
  expect(queryByText('Auto publish')).not.toBeInTheDocument();
365
- expect(getByText('Import only')).toBeInTheDocument();
366
364
  });
367
365
 
368
366
  /* eslint-enable no-useless-escape */
@@ -130,7 +130,11 @@ class ManageManifestModal extends Component {
130
130
  <ForemanModal id={MANAGE_MANIFEST_MODAL_ID} title={__('Manage Manifest')}>
131
131
  <Tabs id="manifest-history-tabs" ouiaId="manifest-history-tabs">
132
132
  {showManifestTab &&
133
- <Tab eventKey={1} title={__('Manifest')}>
133
+ <Tab
134
+ ouiaId="subscription-manifest-tab"
135
+ eventKey={1}
136
+ title={__('Manifest')}
137
+ >
134
138
  {showSubscriptionManifest &&
135
139
  <React.Fragment>
136
140
  <Grid>
@@ -210,7 +214,11 @@ class ManageManifestModal extends Component {
210
214
  <Slot id="katello-manage-manifest-form" multi />
211
215
  </Tab>
212
216
  }
213
- <Tab eventKey={2} title={__('Manifest History')}>
217
+ <Tab
218
+ ouiaId="manifest-history-tab"
219
+ eventKey={2}
220
+ title={__('Manifest History')}
221
+ >
214
222
  <LoadingState loading={manifestHistory.loading} loadingText={__('Loading')}>
215
223
  <Table
216
224
  ouiaId="manifest-history-table"
@@ -221,7 +229,11 @@ class ManageManifestModal extends Component {
221
229
  </LoadingState>
222
230
  </Tab>
223
231
  {showCdnConfigurationTab &&
224
- <Tab eventKey={3} title={__('CDN Configuration')}>
232
+ <Tab
233
+ ouiaId="cdn-configuration-tab"
234
+ eventKey={3}
235
+ title={__('CDN Configuration')}
236
+ >
225
237
  <Grid>
226
238
  <h3>{__('CDN Configuration for Red Hat Content')}</h3>
227
239
  <hr />
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: 4.9.0.rc2
4
+ version: 4.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - N/A
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-07 00:00:00.000000000 Z
11
+ date: 2023-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -5514,11 +5514,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
5514
5514
  version: '2.5'
5515
5515
  required_rubygems_version: !ruby/object:Gem::Requirement
5516
5516
  requirements:
5517
- - - ">"
5517
+ - - ">="
5518
5518
  - !ruby/object:Gem::Version
5519
- version: 1.3.1
5519
+ version: '0'
5520
5520
  requirements: []
5521
- rubygems_version: 3.3.26
5521
+ rubygems_version: 3.4.10
5522
5522
  signing_key:
5523
5523
  specification_version: 4
5524
5524
  summary: Content and Subscription Management plugin for Foreman