katello 3.8.0.rc1 → 3.8.0.rc2

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 (123) 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/registry/registry_proxies_controller.rb +1 -1
  5. data/app/controllers/katello/api/v2/environments_controller.rb +0 -1
  6. data/app/controllers/katello/api/v2/ostree_branches_controller.rb +1 -1
  7. data/app/controllers/katello/api/v2/repository_sets_controller.rb +10 -1
  8. data/app/controllers/katello/remote_execution_controller.rb +6 -6
  9. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +37 -9
  10. data/app/lib/katello/resources/registry.rb +4 -4
  11. data/app/models/katello/authorization/repository.rb +2 -1
  12. data/app/models/katello/content_view.rb +12 -4
  13. data/app/models/katello/glue/candlepin/owner.rb +0 -8
  14. data/app/models/katello/glue/candlepin/pool.rb +11 -11
  15. data/app/models/katello/kt_environment.rb +0 -6
  16. data/app/models/katello/product_content.rb +4 -1
  17. data/app/models/katello/rpm.rb +13 -5
  18. data/app/services/katello/ui_notifications/pulp/proxy_disk_space.rb +3 -1
  19. data/app/views/overrides/activation_keys/_host_environment_select.html.erb +2 -3
  20. data/config/katello.yaml.example +5 -0
  21. data/config/routes.rb +1 -0
  22. data/db/seeds.d/75-job_templates.rb +5 -2
  23. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment-details.html +43 -8
  24. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/discovery.controller.js +17 -2
  25. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/views/discovery-create.html +1 -1
  26. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/views/discovery.html +1 -1
  27. data/engines/bastion_katello/app/assets/stylesheets/bastion_katello/bastion_katello.scss +5 -0
  28. data/lib/katello/version.rb +1 -1
  29. data/package.json +11 -7
  30. data/webpack/__mocks__/foremanReact/components/BreadcrumbBar.js +3 -0
  31. data/webpack/__mocks__/foremanReact/redux/actions/toasts.js +8 -0
  32. data/webpack/__mocks__/foremanReact/redux.js +3 -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/mockRequest.js +3 -3
  44. data/webpack/move_to_foreman/common/helpers.js +45 -8
  45. data/webpack/move_to_foreman/components/common/{emptyState → EmptyState}/index.js +16 -3
  46. data/webpack/move_to_foreman/components/common/table/components/Table.js +1 -1
  47. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/CollapseSubscriptionGroupButton.test.js.snap +2 -2
  48. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionCell.test.js.snap +1 -1
  49. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionHeaderCell.test.js.snap +1 -1
  50. data/webpack/move_to_pf/LoadingState/LoadingState.js +27 -14
  51. data/webpack/move_to_pf/LoadingState/LoadingState.test.js +8 -4
  52. data/webpack/move_to_pf/Select/Select.js +40 -0
  53. data/webpack/move_to_pf/react-bootstrap-select/index.js +12 -1
  54. data/webpack/redux/actions/RedHatRepositories/enabled.js +0 -1
  55. data/webpack/redux/actions/RedHatRepositories/helpers.js +5 -5
  56. data/webpack/redux/actions/RedHatRepositories/sets.js +1 -1
  57. data/webpack/redux/consts.js +6 -0
  58. data/webpack/redux/reducers/index.js +2 -0
  59. data/webpack/scenes/RedHatRepositories/components/EnabledRepository.js +14 -23
  60. data/webpack/scenes/RedHatRepositories/components/EnabledRepositoryContent.js +34 -0
  61. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepository.js +1 -1
  62. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +1 -0
  63. data/webpack/scenes/RedHatRepositories/components/__tests__/EnabledRepository.test.js +36 -0
  64. data/webpack/scenes/RedHatRepositories/components/__tests__/EnabledRepositoryContent.test.js +27 -0
  65. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/EnabledRepository.test.js.snap +25 -0
  66. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/EnabledRepositoryContent.test.js.snap +47 -0
  67. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/RecommendedRepositorySetsToggler.test.js.snap +3 -1
  68. data/webpack/scenes/RedHatRepositories/index.js +7 -3
  69. data/webpack/scenes/RedHatRepositories/index.scss +1 -0
  70. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailActions.js +3 -8
  71. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProducts.js +5 -3
  72. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailReducer.js +1 -1
  73. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +44 -6
  74. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.scss +4 -0
  75. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailReducer.test.js +3 -1
  76. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetails.test.js +2 -1
  77. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailProducts.test.js.snap +113 -23
  78. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +23 -14
  79. data/webpack/scenes/Subscriptions/Details/__tests__/subscriptionDetails.fixtures.js +3 -4
  80. data/webpack/scenes/Subscriptions/Details/index.js +2 -2
  81. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +78 -34
  82. data/webpack/scenes/Subscriptions/Manifest/ManifestActions.js +5 -24
  83. data/webpack/scenes/Subscriptions/Manifest/ManifestHistoryReducer.js +9 -1
  84. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManageManifestModal.test.js +3 -0
  85. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManifestActions.test.js +20 -8
  86. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManifestHistoryReducer.test.js +3 -1
  87. data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +34 -7
  88. data/webpack/scenes/Subscriptions/Manifest/__tests__/manifest.fixtures.js +9 -16
  89. data/webpack/scenes/Subscriptions/Manifest/index.js +1 -0
  90. data/webpack/scenes/Subscriptions/SubscriptionActions.js +5 -26
  91. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +1 -0
  92. data/webpack/scenes/Subscriptions/SubscriptionHelpers.js +3 -0
  93. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +11 -4
  94. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +31 -36
  95. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsActions.js +3 -12
  96. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +57 -27
  97. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsReducer.js +2 -3
  98. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsTableSchema.js +10 -5
  99. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsActions.test.js +10 -5
  100. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsPage.test.js +50 -5
  101. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsReducer.test.js +8 -3
  102. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +21 -11
  103. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/upstreamSubscriptions.fixtures.js +5 -8
  104. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +2 -0
  105. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsReducer.test.js +9 -3
  106. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +14 -2
  107. data/webpack/scenes/Subscriptions/__tests__/subscriptions.fixtures.js +11 -17
  108. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/EntitlementsInlineEditFormatter.js +8 -5
  109. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js +45 -58
  110. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableHelpers.js +11 -4
  111. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableSchema.js +2 -2
  112. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/EntitlementsInlineEditFormatter.test.js +110 -0
  113. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/SubscriptionsTable.test.js +16 -3
  114. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/EntitlementsInlineEditFormatter.test.js.snap +228 -0
  115. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +392 -365
  116. data/webpack/scenes/Subscriptions/index.js +1 -0
  117. data/webpack/scenes/Tasks/helpers.js +52 -0
  118. data/webpack/services/api/index.js +17 -1
  119. data/webpack/services/api/testHelpers.js +28 -0
  120. data/webpack/test_setup.js +2 -0
  121. metadata +24 -5
  122. data/config/katello.yaml +0 -89
  123. data/webpack/services/api/fixtures.js +0 -353
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9b618c5ea8ea521a3bc6e5c240bb41675162b2a7
4
- data.tar.gz: 7ee6a2bc9a14c84fb699d749cc05b5956a72ef0b
3
+ metadata.gz: a29f4138e7efc30092c57d2d41cba2daa63d8f96
4
+ data.tar.gz: 2d6286442b855654c1baaa52db2c96946b153c39
5
5
  SHA512:
6
- metadata.gz: 03e1ed24d9276d21a18323c34be085e1970eff16c2b999e252733b1da420170d54c2689bbb993cc7b68fb75322fb3994089615ecaac7c29efb10a4085637b8f3
7
- data.tar.gz: 6f5ebc555ebcaadc3b6653979195e0959cc63259327c8dff05c33df1d635081ec97a80a33d0dcc359fdf9156680d0fc14e981c610979fe2590b6a1426aea816f
6
+ metadata.gz: 98f1753327006589d1804417424b7b5252bbe60ba35cef2cac87a8b2f5088548dbfeedc5212f88d70240b97f7b80c12fad55e87c9d1985fae771120baff2bb39
7
+ data.tar.gz: d7fed987e7d06d564e141b5675c08be8dc960f8b0f2e87531f3ef2268bf72250b228c518d4f6cc04ca261d4be69e166b88556ce760e5d0d6c3bf9b57fc0aef46
@@ -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"
@@ -449,7 +449,7 @@ module Katello
449
449
  end
450
450
 
451
451
  def confirm_settings
452
- return true if SETTINGS[:katello][:registry]
452
+ return true if SETTINGS[:katello][:container_image_registry]
453
453
  render_error('custom_error', :status => :not_found,
454
454
  :locals => { :message => "Registry not configured" })
455
455
  false
@@ -104,7 +104,6 @@ module Katello
104
104
  fail HttpErrors::BadRequest, _("Can't update the '%s' environment") % "Library" if @environment.library? && update_params.empty?
105
105
  update_params[:name] = params[:environment][:new_name] if params[:environment][:new_name]
106
106
  @environment.update_attributes!(update_params)
107
- @environment.update_container_repositories(update_params[:registry_unauthenticated_pull]) if update_params.key? :registry_unauthenticated_pull
108
107
  if update_params[:registry_name_pattern]
109
108
  task = send(async ? :async_task : :sync_task, ::Actions::Katello::Environment::PublishRepositories,
110
109
  @environment, content_type: Katello::Repository::DOCKER_TYPE)
@@ -4,7 +4,7 @@ module Katello
4
4
  include Katello::Concerns::Api::V2::RepositoryContentController
5
5
 
6
6
  def default_sort
7
- %w(version_date desc)
7
+ %w(version desc)
8
8
  end
9
9
 
10
10
  private
@@ -17,6 +17,7 @@ module Katello
17
17
  param :product_id, :number, :required => true, :desc => N_("ID of a product to list repository sets from")
18
18
  param :name, String, :required => false, :desc => N_("Repository set name to search on")
19
19
  param :enabled, :bool, :required => false, :desc => N_("If true, only return repository sets that have been enabled. Defaults to false")
20
+ param :with_active_subscription, :bool, :required => false, :desc => N_("If true, only return repository sets that are associated with an active subscriptions")
20
21
  param_group :search, Api::V2::ApiController
21
22
  def index
22
23
  respond(:collection => scoped_search(index_relation, nil, nil, :custom_sort => default_sort,
@@ -92,7 +93,15 @@ module Katello
92
93
  relation = @product.displayable_product_contents
93
94
  end
94
95
 
95
- relation = relation.enabled(@organization) if ::Foreman::Cast.to_bool(params[:enabled])
96
+ if ::Foreman::Cast.to_bool(params[:enabled])
97
+ relation = relation.enabled(@organization)
98
+ elsif ::Foreman::Cast.to_bool(params[:with_active_subscription])
99
+ relation = relation.with_valid_subscription(@organization)
100
+ else
101
+ relation = relation.where(:id => Katello::ProductContent.with_valid_subscription(@organization)).or(
102
+ relation.where(:id => Katello::ProductContent.enabled(@organization)))
103
+ end
104
+
96
105
  relation = relation.where(Katello::Content.table_name => {:name => params[:name]}) if params[:name].present?
97
106
  relation.redhat
98
107
  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
@@ -18,13 +18,13 @@ module Katello
18
18
  end
19
19
 
20
20
  class RegistryResource < HttpResource
21
- if SETTINGS[:katello][:registry]
22
- cfg = SETTINGS[:katello][:registry]
23
- url = cfg[:url]
21
+ if SETTINGS[:katello][:container_image_registry]
22
+ cfg = SETTINGS[:katello][:container_image_registry]
23
+ url = cfg[:crane_url]
24
24
  uri = URI.parse(url)
25
25
  self.prefix = uri.path
26
26
  self.site = "#{uri.scheme}://#{uri.host}:#{uri.port}"
27
- self.ca_cert_file = cfg[:ca_cert_file]
27
+ self.ca_cert_file = cfg[:crane_ca_cert_file]
28
28
  end
29
29
 
30
30
  class << self
@@ -21,9 +21,10 @@ module Katello
21
21
  module ClassMethods
22
22
  def readable
23
23
  in_products = Repository.where(:product_id => Katello::Product.authorized(:view_products)).select(:id)
24
+ in_environments = Repository.where(:environment_id => Katello::KTEnvironment.authorized(:view_lifecycle_environments)).select(:id)
24
25
  in_content_views = Repository.joins(:content_view_repositories).where("#{ContentViewRepository.table_name}.content_view_id" => Katello::ContentView.readable).select(:id)
25
26
  in_versions = Repository.joins(:content_view_version).where("#{Katello::ContentViewVersion.table_name}.content_view_id" => Katello::ContentView.readable).select(:id)
26
- where("#{self.table_name}.id in (?) or #{self.table_name}.id in (?) or #{self.table_name}.id in (?)", in_products, in_content_views, in_versions)
27
+ where("#{self.table_name}.id in (?) or #{self.table_name}.id in (?) or #{self.table_name}.id in (?) or #{self.table_name}.id in (?)", in_products, in_content_views, in_versions, in_environments)
27
28
  end
28
29
 
29
30
  def deletable
@@ -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
@@ -39,14 +39,6 @@ module Katello
39
39
  self.owner_details['contentAccessMode']
40
40
  end
41
41
 
42
- def pools(consumer_uuid = nil)
43
- if consumer_uuid
44
- Resources::Candlepin::Owner.pools self.label, :consumer => consumer_uuid
45
- else
46
- Resources::Candlepin::Owner.pools self.label
47
- end
48
- end
49
-
50
42
  def generate_debug_cert
51
43
  Resources::Candlepin::Owner.generate_ueber_cert(label)
52
44
  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
@@ -221,12 +221,6 @@ module Katello
221
221
  self.repositories.readable.where(:content_type => Katello::Repository::PUPPET_TYPE)
222
222
  end
223
223
 
224
- def update_container_repositories(registry_unauthenticated_pull)
225
- self.repositories.readable.where(:content_type => Katello::Repository::DOCKER_TYPE).each do |repository|
226
- repository.update_attributes!(registry_unauthenticated_pull: registry_unauthenticated_pull)
227
- end
228
- end
229
-
230
224
  def as_json(_options = {})
231
225
  to_ret = self.attributes
232
226
  to_ret['prior'] = self.prior && self.prior.name
@@ -12,7 +12,6 @@ module Katello
12
12
 
13
13
  scope :displayable, -> {
14
14
  joins(:content).where.not("#{content_table_name}.content_type IN (?)", Katello::Repository.undisplayable_types)
15
- .order("LOWER(#{content_table_name}.name) ASC")
16
15
  }
17
16
 
18
17
  scope :redhat, -> {
@@ -32,6 +31,10 @@ module Katello
32
31
  joins(:content).where("#{self.content_table_name}.cp_content_id" => Katello::Repository.in_organization(organization).select(:content_id))
33
32
  end
34
33
 
34
+ def self.with_valid_subscription(organization)
35
+ where(:product_id => Katello::PoolProduct.where(:pool_id => organization.pools).select(:product_id))
36
+ end
37
+
35
38
  # used by Katello::Api::V2::RepositorySetsController#index
36
39
  def repositories
37
40
  product.repositories.in_default_view.has_url.where(:content_id => content.cp_content_id)
@@ -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)
@@ -5,7 +5,9 @@ module Katello
5
5
  class << self
6
6
  def deliver!
7
7
  SmartProxy.unscoped.with_content.each do |proxy|
8
- percentage = proxy.statuses[:pulp].storage['pulp_dir']['percent']
8
+ status = proxy.statuses[:pulp] || proxy.statuses[:pulpnode]
9
+ next unless (percentage = status&.storage&.dig('pulp_dir', 'percent'))
10
+
9
11
  if percentage[0..2].to_i < 90 && notification_already_exists?(proxy)
10
12
  blueprint.notifications.where(subject: proxy).destroy_all
11
13
  elsif update_notifications(proxy).empty? && percentage[0..2].to_i > 90
@@ -35,12 +35,11 @@ end %>
35
35
  <% cs_select_name = using_hostgroups_page? ? 'hostgroup[content_source_id]' : 'host[content_facet_attributes][content_source_id]' %>
36
36
  <% cs_select_attr = using_hostgroups_page? ? 'content_source' : 'content_facet.content_source' %>
37
37
 
38
- <% proxies = accessible_content_proxies(@host || @hostgroup) %>
39
38
  <%= field(f, cs_select_attr, {:label => _("Content Source")}) do
40
39
  if using_hostgroups_page?
41
- select_tag cs_select_id, options_from_collection_for_select(proxies, :id, :name, @hostgroup.content_source_id), :data => {"spinner_path" => spinner_path},
40
+ select_tag cs_select_id, content_source_options(@hostgroup, :selected_host_group => @hostgroup.hostgroup, :include_blank => blank_or_inherit_with_id(f, :content_source)), :data => {"spinner_path" => spinner_path},
42
41
  :class => 'form-control', :name => cs_select_name, include_blank: true
43
42
  else
44
- select_tag cs_select_id, options_from_collection_for_select(proxies, :id, :name, (@hostgroup || @host).content_source_id), :data => {"spinner_path" => spinner_path}, :class => 'form-control', :name => cs_select_name, include_blank: true
43
+ select_tag cs_select_id, content_source_options(@host, :selected_host_group => @host.hostgroup, :include_blank => blank_or_inherit_with_id(f, :content_source)), :data => {"spinner_path" => spinner_path}, :class => 'form-control', :name => cs_select_name, include_blank: true
45
44
  end
46
45
  end %>
@@ -71,6 +71,11 @@
71
71
  # :user: login
72
72
  # :password: password
73
73
 
74
+ # Internal configuration for communication from server to pulp crane service.
75
+ :container_image_registry:
76
+ :crane_url: https://localhost:5000
77
+ :crane_ca_cert_file: /etc/pki/katello/certs/katello-server-ca.crt
78
+
74
79
  # Logging configuration can be changed by uncommenting the loggers
75
80
  # section and the logger configuration desired.
76
81
  #
data/config/routes.rb CHANGED
@@ -23,4 +23,5 @@ Katello::Engine.routes.draw do
23
23
 
24
24
  match '/xui' => 'react#index', :via => [:get]
25
25
  match '/xui/*page' => 'react#index', :via => [:get]
26
+ match '/organization_select' => 'react#index', :via => [:get]
26
27
  end
@@ -7,10 +7,13 @@ if Katello.with_remote_execution?
7
7
  sync = !Rails.env.test? && Setting[:remote_execution_sync_templates]
8
8
  # import! was renamed to import_raw! around 1.3.1
9
9
  if JobTemplate.respond_to?('import_raw!')
10
- JobTemplate.import_raw!(File.read(template), :default => true, :locked => true, :update => sync)
10
+ template = JobTemplate.import_raw!(File.read(template), :default => true, :locked => true, :update => sync)
11
11
  else
12
- JobTemplate.import!(File.read(template), :default => true, :locked => true, :update => sync)
12
+ template = JobTemplate.import!(File.read(template), :default => true, :locked => true, :update => sync)
13
13
  end
14
+
15
+ template.organizations << Organization.unscoped.all if template && template.organizations.empty?
16
+ template.locations << Location.unscoped.all if template && template.locations.empty?
14
17
  end
15
18
  end
16
19
  end
@@ -24,16 +24,51 @@
24
24
 
25
25
  <dl class="dl-horizontal dl-horizontal-left">
26
26
  <dt translate>Unauthenticated Pull</dt>
27
- <dd bst-edit-checkbox="environment.registry_unauthenticated_pull"
28
- formatter="booleanToYesNo"
29
- on-save="save(environment)"
30
- readonly="denied('edit_lifecycle_environments', environment)">
27
+ <dd>
28
+ <div bst-edit-checkbox="environment.registry_unauthenticated_pull"
29
+ formatter="booleanToYesNo"
30
+ on-save="save(environment)"
31
+ readonly="denied('edit_lifecycle_environments', environment)">
32
+ </div>
33
+ <div bst-alert='info'>
34
+ <span translate>
35
+ Determines whether to require login to pull container images in this lifecycle environment.
36
+ </span>
37
+ </div>
31
38
  </dd>
32
39
  <dt translate>Registry Name Pattern</dt>
33
- <dd bst-edit-textarea="environment.registry_name_pattern"
34
- on-save="save(environment)"
35
- readonly="denied('edit_lifecycle_environments', environment)">
40
+ <dd>
41
+ <div bst-edit-textarea="environment.registry_name_pattern"
42
+ on-save="save(environment)"
43
+ readonly="denied('edit_lifecycle_environments', environment)">
44
+ </div>
45
+ <div bst-alert='info'>
46
+ <span translate>
47
+ The <i>Registry Name Pattern</i> overrides the default name by which container images may be pulled from the server. (By default this name is a combination of Organization, Lifecycle Environment, Content View, Product, and Repository labels.)
48
+
49
+ <br/><br/>The name may be constructed using ERB syntax. Variables available for use are:
50
+
51
+ <pre>
52
+ organization.name
53
+ organization.label
54
+ repository.name
55
+ repository.label
56
+ repository.docker_upstream_name
57
+ repository.url
58
+ content_view.label
59
+ content_view.name
60
+ content_view.version
61
+ product.name
62
+ product.label
63
+ lifecycle_environment.name
64
+ lifecycle_environment.label</pre>
65
+
66
+ Examples:
67
+ <pre>
68
+ &lt;%= organization.label %&gt;-&lt;%= lifecycle_environment.label %&gt;-&lt;%= content_view.label %&gt;-&lt;%= product.label %&gt;-&lt;%= repository.label %&gt;
69
+ &lt;%= organization.label %&gt;/&lt;%= repository.docker_upstream_name %&gt;</pre>
70
+ </span>
71
+ </div>
36
72
  </dd>
37
73
  </dl>
38
-
39
74
  </div>
@@ -17,8 +17,8 @@
17
17
  * Provides the functionality for the repo discovery action pane.
18
18
  */
19
19
  angular.module('Bastion.products').controller('DiscoveryController',
20
- ['$scope', '$q', '$timeout', '$http', 'Notification', 'Task', 'Organization', 'CurrentOrganization', 'DiscoveryRepositories', 'translate',
21
- function ($scope, $q, $timeout, $http, Notification, Task, Organization, CurrentOrganization, DiscoveryRepositories, translate) {
20
+ ['$scope', '$q', '$timeout', '$http', '$filter', 'Notification', 'Task', 'Organization', 'CurrentOrganization', 'DiscoveryRepositories', 'translate',
21
+ function ($scope, $q, $timeout, $http, $filter, Notification, Task, Organization, CurrentOrganization, DiscoveryRepositories, translate) {
22
22
  var transformRows, setDiscoveryDetails;
23
23
 
24
24
  $scope.discovery = {
@@ -50,6 +50,21 @@ angular.module('Bastion.products').controller('DiscoveryController',
50
50
  $scope.table.resource.subtotal = $scope.table.resource.total;
51
51
  };
52
52
 
53
+ $scope.filteredRows = function (filter) {
54
+ var rows, idx;
55
+ angular.forEach($scope.table.rows, function (row) {
56
+ row.unselectable = true;
57
+ });
58
+ rows = $filter('filter')($scope.table.rows.slice(), filter);
59
+ angular.forEach(rows, function (row) {
60
+ idx = $scope.table.rows.indexOf(row);
61
+ $scope.table.rows[idx].unselectable = false;
62
+ });
63
+ $scope.table.getSelected();
64
+
65
+ return (rows);
66
+ };
67
+
53
68
  $scope.setupSelected = function () {
54
69
  var url;
55
70
 
@@ -44,7 +44,7 @@
44
44
 
45
45
  <div bst-form-group ng-show="createRepoChoices.newProduct === 'true' && contentCredentials.length !== 0"
46
46
  label="{{ 'GPG Key' | translate }}">
47
- <select class="form-control" ng-model="createRepoChoices.product.content_credential_id"
47
+ <select class="form-control" ng-model="createRepoChoices.product.gpg_key_id"
48
48
  ng-options="content_credential.id as content_credential.name for content_credential in contentCredentials"/>
49
49
  </div>
50
50
 
@@ -101,7 +101,7 @@
101
101
  </thead>
102
102
 
103
103
  <tbody>
104
- <tr bst-table-row ng-repeat="urlRow in table.rows | filter:tableFilter" row-select="urlRow">
104
+ <tr bst-table-row ng-repeat="urlRow in filteredRows(tableFilter)" row-select="urlRow">
105
105
  <td bst-table-cell style="white-space:nowrap">{{ urlRow.path }}</td>
106
106
  </tr>
107
107
  </tbody>
@@ -38,3 +38,8 @@
38
38
  .bottom-padded-content {
39
39
  padding-bottom: 10%;
40
40
  }
41
+
42
+ .modal-body .uib-time input {
43
+ width: 100%;
44
+ padding-right: 6px;
45
+ }
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "3.8.0.rc1".freeze
2
+ VERSION = "3.8.0.rc2".freeze
3
3
  end
data/package.json CHANGED
@@ -9,7 +9,9 @@
9
9
  "test:current": "jest webpack --watch",
10
10
  "format": "prettier --single-quote --trailing-comma es5 --write 'webpack/**/*.js'",
11
11
  "build": "npm run format && npm run lint",
12
- "lint": "eslint --fix webpack/ || exit 0"
12
+ "lint": "eslint webpack/ || exit 0",
13
+ "lint:fix": "eslint --fix webpack/ || exit 0",
14
+ "lint:test": "npm run lint && npm test"
13
15
  },
14
16
  "repository": {
15
17
  "type": "git",
@@ -22,11 +24,11 @@
22
24
  "@storybook/react": "^3.2.17",
23
25
  "@storybook/storybook-deployer": "^2.0.0",
24
26
  "babel-core": "^6.26.3",
25
- "babel-jest": "^21.2.0",
27
+ "babel-jest": "^23.4.0",
26
28
  "babel-plugin-transform-class-properties": "^6.24.1",
27
29
  "babel-plugin-transform-object-rest-spread": "^6.26.0",
28
- "babel-preset-env": "^1.6.0",
29
30
  "babel-polyfill": "^6.26.0",
31
+ "babel-preset-env": "^1.6.0",
30
32
  "babel-preset-react": "^6.24.1",
31
33
  "enzyme": "^3.2.0",
32
34
  "enzyme-adapter-react-16": "^1.1.0",
@@ -34,11 +36,11 @@
34
36
  "eslint": "^4.8.0",
35
37
  "eslint-config-airbnb": "^16.0.0",
36
38
  "eslint-plugin-import": "^2.7.0",
37
- "eslint-plugin-jest": "^21.2.0",
39
+ "eslint-plugin-jest": "^21.18.0",
38
40
  "eslint-plugin-jsx-a11y": "^6.0.2",
39
41
  "eslint-plugin-react": "^7.4.0",
40
42
  "identity-obj-proxy": "^3.0.0",
41
- "jest": "^21.2.1",
43
+ "jest": "^23.4.1",
42
44
  "prettier": "^1.7.4",
43
45
  "react-test-renderer": "^16.0.0",
44
46
  "redux-mock-store": "^1.3.0",
@@ -53,10 +55,10 @@
53
55
  "jed": "^1.1.1",
54
56
  "lodash": "^4.17.5",
55
57
  "patternfly": "^3.41.1",
56
- "patternfly-react": "2.5.1",
58
+ "patternfly-react": "^2.5.1",
57
59
  "prop-types": "^15.6.0",
58
60
  "react": "^16.3.1",
59
- "react-bootstrap": "^0.31.5",
61
+ "react-bootstrap": "^0.32.1",
60
62
  "react-bootstrap-tooltip-button": "^1.0.6",
61
63
  "react-dom": "^16.3.1",
62
64
  "react-ellipsis-with-tooltip": "^1.0.7",
@@ -68,10 +70,12 @@
68
70
  "seamless-immutable": "^7.1.2"
69
71
  },
70
72
  "jest": {
73
+ "testURL": "http://localhost/",
71
74
  "setupFiles": [
72
75
  "raf/polyfill",
73
76
  "./webpack/test_setup.js"
74
77
  ],
78
+ "setupTestFrameworkScriptFile": "./webpack/global_test_setup.js",
75
79
  "testPathIgnorePatterns": [
76
80
  "/node_modules/",
77
81
  "<rootDir>/foreman/",
@@ -0,0 +1,3 @@
1
+
2
+ const BreadcrumbsBar = () => jest.fn();
3
+ export default BreadcrumbsBar;
@@ -0,0 +1,8 @@
1
+ export const addToast = toast => ({
2
+ type: 'TOASTS_ADD',
3
+ payload: {
4
+ message: toast,
5
+ },
6
+ });
7
+
8
+ export default addToast;