katello 3.9.1 → 3.10.0.rc1

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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/hosts/host_and_hostgroup_edit.js +28 -12
  3. data/app/controllers/katello/api/rhsm/candlepin_dynflow_proxy_controller.rb +12 -3
  4. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +4 -13
  5. data/app/controllers/katello/api/v2/content_credentials_controller.rb +1 -1
  6. data/app/controllers/katello/api/v2/content_view_filter_rules_controller.rb +1 -1
  7. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +6 -4
  8. data/app/controllers/katello/api/v2/content_views_controller.rb +8 -3
  9. data/app/controllers/katello/api/v2/gpg_keys_controller.rb +2 -1
  10. data/app/controllers/katello/api/v2/host_module_streams_controller.rb +39 -0
  11. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +20 -11
  12. data/app/controllers/katello/api/v2/module_streams_controller.rb +2 -1
  13. data/app/controllers/katello/api/v2/repository_sets_controller.rb +17 -8
  14. data/app/controllers/katello/application_controller.rb +0 -2
  15. data/app/controllers/katello/concerns/hosts_controller_extensions.rb +5 -2
  16. data/app/lib/actions/candlepin/consumer/attach_subscription.rb +0 -2
  17. data/app/lib/actions/candlepin/consumer/remove_subscription.rb +0 -2
  18. data/app/lib/actions/katello/capsule_content/create_repos.rb +1 -25
  19. data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
  20. data/app/lib/actions/katello/content_view/promote.rb +2 -5
  21. data/app/lib/actions/katello/content_view/promote_to_environment.rb +2 -5
  22. data/app/lib/actions/katello/content_view/publish.rb +1 -4
  23. data/app/lib/actions/katello/content_view_puppet_environment/create.rb +6 -10
  24. data/app/lib/actions/katello/content_view_version/export.rb +0 -2
  25. data/app/lib/actions/katello/content_view_version/incremental_update.rb +19 -1
  26. data/app/lib/actions/katello/environment/publish_repositories.rb +2 -1
  27. data/app/lib/actions/katello/gpg_key/update.rb +17 -0
  28. data/app/lib/actions/katello/host/attach_subscriptions.rb +0 -2
  29. data/app/lib/actions/katello/host/erratum/install.rb +6 -0
  30. data/app/lib/actions/katello/host/generate_applicability.rb +0 -2
  31. data/app/lib/actions/katello/host/hypervisors_update.rb +11 -6
  32. data/app/lib/actions/katello/host/package/install.rb +6 -0
  33. data/app/lib/actions/katello/host/package/remove.rb +6 -0
  34. data/app/lib/actions/katello/host/package/update.rb +7 -1
  35. data/app/lib/actions/katello/host/package_group/install.rb +6 -0
  36. data/app/lib/actions/katello/host/package_group/remove.rb +6 -0
  37. data/app/lib/actions/katello/host/recalculate_errata_status.rb +0 -2
  38. data/app/lib/actions/katello/host/remove_subscriptions.rb +0 -2
  39. data/app/lib/actions/katello/host/update.rb +1 -0
  40. data/app/lib/actions/katello/host/update_content_overrides.rb +0 -2
  41. data/app/lib/actions/katello/host/upload_package_profile.rb +13 -12
  42. data/app/lib/actions/katello/host/upload_profiles.rb +70 -0
  43. data/app/lib/actions/katello/product/reindex_subscriptions.rb +0 -2
  44. data/app/lib/actions/katello/product/repositories_certs_reset.rb +4 -4
  45. data/app/lib/actions/katello/product/repositories_gpg_reset.rb +2 -2
  46. data/app/lib/actions/katello/repository/check_matching_content.rb +18 -6
  47. data/app/lib/actions/katello/repository/clone_deb_content.rb +1 -1
  48. data/app/lib/actions/katello/repository/clone_to_environment.rb +3 -5
  49. data/app/lib/actions/katello/repository/clone_to_version.rb +2 -3
  50. data/app/lib/actions/katello/repository/clone_yum_content.rb +1 -2
  51. data/app/lib/actions/katello/repository/clone_yum_metadata.rb +2 -2
  52. data/app/lib/actions/katello/repository/create.rb +1 -31
  53. data/app/lib/actions/katello/repository/destroy.rb +1 -2
  54. data/app/lib/actions/katello/repository/export.rb +0 -2
  55. data/app/lib/actions/katello/repository/fetch_pxe_files.rb +0 -2
  56. data/app/lib/actions/katello/repository/filtered_index_content.rb +0 -2
  57. data/app/lib/actions/katello/repository/finish_upload.rb +0 -2
  58. data/app/lib/actions/katello/repository/import_upload.rb +0 -2
  59. data/app/lib/actions/katello/repository/index_content.rb +0 -1
  60. data/app/lib/actions/katello/repository/index_package_groups.rb +0 -2
  61. data/app/lib/actions/katello/repository/instance_update.rb +21 -0
  62. data/app/lib/actions/katello/repository/remove_content.rb +0 -2
  63. data/app/lib/actions/katello/repository/sync.rb +0 -1
  64. data/app/lib/actions/katello/repository/update.rb +0 -2
  65. data/app/lib/actions/katello/upstream_subscriptions/bind_entitlement.rb +0 -2
  66. data/app/lib/actions/katello/upstream_subscriptions/bind_entitlements.rb +0 -2
  67. data/app/lib/actions/katello/upstream_subscriptions/remove_entitlement.rb +0 -1
  68. data/app/lib/actions/katello/upstream_subscriptions/remove_entitlements.rb +0 -2
  69. data/app/lib/actions/katello/upstream_subscriptions/update_entitlement.rb +0 -1
  70. data/app/lib/actions/katello/upstream_subscriptions/update_entitlements.rb +0 -2
  71. data/app/lib/actions/pulp/abstract.rb +13 -14
  72. data/app/lib/actions/pulp/repository/create.rb +13 -211
  73. data/app/lib/actions/pulp/repository/create_in_plan.rb +4 -18
  74. data/app/lib/actions/pulp/repository/refresh.rb +7 -70
  75. data/app/lib/actions/pulp/repository/sync.rb +1 -2
  76. data/app/lib/katello/capsule_content.rb +3 -3
  77. data/app/lib/katello/resources/candlepin/consumer.rb +1 -1
  78. data/app/lib/katello/resources/candlepin/product.rb +1 -1
  79. data/app/lib/katello/validators/hostgroup_kickstart_repository_validator.rb +1 -1
  80. data/app/models/katello/available_module_stream.rb +11 -0
  81. data/app/models/katello/concerns/content_facet_host_extensions.rb +1 -0
  82. data/app/models/katello/concerns/host_managed_extensions.rb +56 -0
  83. data/app/models/katello/concerns/hostgroup_extensions.rb +17 -0
  84. data/app/models/katello/concerns/redhat_extensions.rb +20 -6
  85. data/app/models/katello/concerns/search_by_repository_name.rb +0 -1
  86. data/app/models/katello/concerns/smart_proxy_extensions.rb +26 -12
  87. data/app/models/katello/content_facet_applicable_module_stream.rb +7 -0
  88. data/app/models/katello/content_view_puppet_environment.rb +14 -35
  89. data/app/models/katello/erratum.rb +54 -24
  90. data/app/models/katello/erratum_package.rb +6 -0
  91. data/app/models/katello/glue/pulp/repo.rb +5 -228
  92. data/app/models/katello/gpg_key.rb +1 -0
  93. data/app/models/katello/host/content_facet.rb +38 -83
  94. data/app/models/katello/host_available_module_stream.rb +47 -0
  95. data/app/models/katello/module_stream.rb +18 -0
  96. data/app/models/katello/module_stream_erratum_package.rb +6 -0
  97. data/app/models/katello/product.rb +0 -2
  98. data/app/models/katello/product_content.rb +1 -0
  99. data/app/models/katello/repository.rb +15 -6
  100. data/app/models/katello/root_repository.rb +1 -1
  101. data/app/models/katello/rpm.rb +5 -17
  102. data/app/services/katello/applicable_content_helper.rb +111 -0
  103. data/app/services/katello/managed_content_medium_provider.rb +7 -0
  104. data/app/services/katello/pulp/consumer.rb +13 -7
  105. data/app/services/katello/pulp/repository.rb +157 -4
  106. data/app/services/katello/pulp/repository/deb.rb +47 -0
  107. data/app/services/katello/pulp/repository/docker.rb +43 -0
  108. data/app/services/katello/pulp/repository/file.rb +31 -0
  109. data/app/services/katello/pulp/repository/ostree.rb +40 -0
  110. data/app/services/katello/pulp/repository/puppet.rb +43 -0
  111. data/app/services/katello/pulp/repository/yum.rb +61 -0
  112. data/app/services/katello/repository_type.rb +1 -1
  113. data/app/views/katello/api/v2/content_facet/base.json.rabl +1 -0
  114. data/app/views/katello/api/v2/content_view_versions/base.json.rabl +0 -1
  115. data/app/views/katello/api/v2/errata/_counts.json.rabl +0 -1
  116. data/app/views/katello/api/v2/errata/show.json.rabl +9 -3
  117. data/app/views/katello/api/v2/host_collections/delta_activation_keys.rabl +0 -1
  118. data/app/views/katello/api/v2/host_module_streams/base.json.rabl +8 -0
  119. data/app/views/katello/api/v2/host_module_streams/index.json.rabl +7 -0
  120. data/app/views/katello/api/v2/packages/backend.json.rabl +0 -1
  121. data/app/views/katello/api/v2/repositories/show.json.rabl +6 -6
  122. data/app/views/katello/layouts/react.html.erb +2 -2
  123. data/app/views/overrides/activation_keys/_host_synced_content_select.html.erb +0 -1
  124. data/config/routes/api/rhsm.rb +1 -0
  125. data/config/routes/overrides.rb +4 -0
  126. data/db/migrate/20181008201422_add_modules_to_errata_packages.rb +29 -0
  127. data/db/migrate/20181017181806_available_module_streams.rb +34 -0
  128. data/db/migrate/20181027014323_add_applicable_modules.rb +24 -0
  129. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/common/module-stream-actions.service.js +2 -1
  130. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/details/views/content-credential-info.html +1 -1
  131. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/new/views/new-content-credential.html +1 -0
  132. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-host-bulk-module-streams-modal.html +2 -2
  133. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-errata-modal.html +37 -22
  134. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.controller.js +4 -1
  135. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-module-streams.controller.js +27 -7
  136. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-module-streams.html +29 -0
  137. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/errata-details.html +15 -1
  138. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +1 -1
  139. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-promotion.controller.js +0 -1
  140. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-publish.controller.js +1 -2
  141. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-versions.controller.js +3 -1
  142. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/histories/content-view-history.controller.js +1 -1
  143. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-promotion.html +0 -15
  144. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-publish.html +0 -14
  145. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/erratum.controller.js +19 -0
  146. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/views/erratum-info.html +0 -12
  147. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/views/erratum-packages.html +36 -0
  148. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/views/erratum.html +7 -0
  149. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/errata.routes.js +9 -0
  150. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/hosts/host-module-streams.factory.js +18 -0
  151. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +4 -2
  152. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +2 -2
  153. data/engines/bastion_katello/app/assets/stylesheets/bastion_katello/bastion_katello.scss +13 -0
  154. data/lib/katello/permissions/host_permissions.rb +3 -0
  155. data/lib/katello/repository_types/deb.rb +3 -1
  156. data/lib/katello/repository_types/docker.rb +3 -1
  157. data/lib/katello/repository_types/file.rb +1 -0
  158. data/lib/katello/repository_types/ostree.rb +3 -1
  159. data/lib/katello/repository_types/puppet.rb +3 -1
  160. data/lib/katello/repository_types/yum.rb +3 -1
  161. data/lib/katello/tasks/delete_orphaned_content.rake +1 -1
  162. data/lib/katello/tasks/reset.rake +1 -0
  163. data/lib/katello/tasks/test.rake +14 -0
  164. data/lib/katello/tasks/unify_hosts.rake +2 -0
  165. data/lib/katello/tasks/virt_who_report.rake +2 -1
  166. data/lib/katello/version.rb +1 -1
  167. data/locale/Makefile +52 -17
  168. data/locale/update-i18n +22 -0
  169. data/package.json +11 -1
  170. data/webpack/__mocks__/foremanReact/components/common/EmptyState.js +8 -0
  171. data/webpack/move_to_foreman/components/common/table/components/Table.js +2 -1
  172. data/webpack/move_to_pf/react-bootstrap-select/index.js +4 -2
  173. data/webpack/move_to_pf/test-utils/testHelpers.js +9 -0
  174. data/webpack/redux/OrganizationProducts/OrganizationProductsActions.js +24 -0
  175. data/webpack/redux/OrganizationProducts/OrganizationProductsConstants.js +5 -0
  176. data/webpack/redux/OrganizationProducts/OrganizationProductsReducer.js +38 -0
  177. data/webpack/redux/OrganizationProducts/OrganizationProductsSelectors.js +7 -0
  178. data/webpack/redux/OrganizationProducts/__tests__/OrganizationProductsActions.test.js +47 -0
  179. data/webpack/redux/OrganizationProducts/__tests__/OrganizationProductsReducer.test.js +33 -0
  180. data/webpack/redux/OrganizationProducts/__tests__/OrganizationProductsSelectors.test.js +19 -0
  181. data/webpack/redux/OrganizationProducts/__tests__/__snapshots__/OrganizationProductsActions.test.js.snap +49 -0
  182. data/webpack/redux/OrganizationProducts/__tests__/__snapshots__/OrganizationProductsReducer.test.js.snap +36 -0
  183. data/webpack/redux/OrganizationProducts/__tests__/__snapshots__/OrganizationProductsSelectors.test.js.snap +9 -0
  184. data/webpack/redux/OrganizationProducts/index.js +13 -0
  185. data/webpack/redux/actions/RedHatRepositories/enabled.js +7 -1
  186. data/webpack/redux/actions/RedHatRepositories/helpers.js +4 -0
  187. data/webpack/redux/actions/RedHatRepositories/sets.js +2 -0
  188. data/webpack/redux/reducers/RedHatRepositories/enabled.fixtures.js +8 -2
  189. data/webpack/redux/reducers/RedHatRepositories/enabled.js +1 -1
  190. data/webpack/redux/reducers/RedHatRepositories/sets.fixtures.js +12 -3
  191. data/webpack/redux/reducers/index.js +2 -0
  192. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +68 -33
  193. data/webpack/scenes/RedHatRepositories/index.js +13 -2
  194. data/webpack/scenes/RedHatRepositories/index.scss +26 -0
  195. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +1 -1
  196. data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +1 -1
  197. data/webpack/scenes/Subscriptions/SubscriptionActions.js +18 -2
  198. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +8 -0
  199. data/webpack/scenes/Subscriptions/SubscriptionHelpers.js +15 -0
  200. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +22 -14
  201. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +39 -90
  202. data/webpack/scenes/Subscriptions/SubscriptionsSelectors.js +14 -0
  203. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +1 -3
  204. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +0 -1
  205. data/webpack/scenes/Subscriptions/__tests__/SubscriptionHelpers.test.js +84 -0
  206. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsActions.test.js +26 -1
  207. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +5 -0
  208. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsReducer.test.js +177 -75
  209. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsSelectors.test.js +29 -0
  210. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionHelpers.test.js.snap +31 -0
  211. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsActions.test.js.snap +32 -0
  212. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +18 -96
  213. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsReducer.test.js.snap +511 -0
  214. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsSelectors.test.js.snap +26 -0
  215. data/webpack/scenes/Subscriptions/__tests__/subscriptions.fixtures.js +6 -1
  216. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +3 -21
  217. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +113 -0
  218. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.test.js +47 -0
  219. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/__snapshots__/SubscriptionsToolbar.test.js.snap +504 -0
  220. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/index.js +1 -0
  221. data/webpack/scenes/Subscriptions/index.js +15 -4
  222. metadata +59 -14
  223. data/app/lib/actions/pulp/repository/associate_distributor.rb +0 -20
  224. data/app/lib/actions/pulp/repository/associate_importer.rb +0 -23
  225. data/app/lib/actions/pulp/repository/delete_distributor.rb +0 -18
  226. data/app/lib/actions/pulp/repository/refresh_distributor.rb +0 -19
  227. data/app/lib/actions/pulp/repository/update_importer.rb +0 -33
  228. data/app/lib/katello/bulk_actions.rb +0 -63
  229. data/webpack/move_to_foreman/components/common/EmptyState/index.js +0 -68
@@ -0,0 +1,47 @@
1
+ module Katello
2
+ class HostAvailableModuleStream < Katello::Model
3
+ belongs_to :host, :inverse_of => :host_available_module_streams, :class_name => '::Host::Managed'
4
+ belongs_to :available_module_stream, :inverse_of => :host_available_module_streams, :class_name => 'Katello::AvailableModuleStream'
5
+ serialize :installed_profiles
6
+
7
+ scope :installed, -> { enabled.where.not(installed_profiles: []) }
8
+ scope :enabled, -> { where(status: ENABLED) }
9
+ scope :disabled, -> { where(status: DISABLED) }
10
+ scope :unknown, -> { where(status: UNKNOWN) }
11
+
12
+ ENABLED = "enabled".freeze
13
+ DISABLED = "disabled".freeze
14
+ UNKNOWN = "unknown".freeze
15
+ INSTALLED = "installed".freeze
16
+ UPGRADABLE = "upgradable".freeze
17
+
18
+ STATUS = [ENABLED, DISABLED, UNKNOWN].freeze
19
+
20
+ API_STATES = {
21
+ ENABLED => :enabled,
22
+ DISABLED => :disabled,
23
+ UNKNOWN => :unknown,
24
+ INSTALLED => :installed,
25
+ UPGRADABLE => :upgradable
26
+ }.with_indifferent_access
27
+
28
+ scoped_search :on => :name, :relation => :available_module_stream, :complete_value => true
29
+ scoped_search :on => :stream, :relation => :available_module_stream, :complete_value => false
30
+ scoped_search :on => :status, :complete_value => STATUS
31
+
32
+ def upgradable?
33
+ return false if status != ENABLED
34
+
35
+ ApplicableContentHelper.new(ModuleStream).installable_for_hosts([host_id]).
36
+ where(ModuleStream.table_name => {:name => available_module_stream.name,
37
+ :stream => available_module_stream.stream}).exists?
38
+ end
39
+
40
+ def self.upgradable(host)
41
+ upgradable_module_name_streams = ApplicableContentHelper.new(ModuleStream).installable_for_hosts([host]).select(:name, :stream)
42
+
43
+ enabled.joins(:available_module_stream).where(:host_id => host).
44
+ where("(#{AvailableModuleStream.table_name}.name, #{AvailableModuleStream.table_name}.stream) in (#{upgradable_module_name_streams.to_sql})")
45
+ end
46
+ end
47
+ end
@@ -7,6 +7,12 @@ module Katello
7
7
  has_many :repositories, through: :repository_module_streams, class_name: "Katello::Repository"
8
8
  has_many :profiles, class_name: "Katello::ModuleProfile", dependent: :destroy, inverse_of: :module_stream
9
9
  has_many :artifacts, class_name: "Katello::ModuleStreamArtifact", dependent: :destroy, inverse_of: :module_stream
10
+ has_many :module_stream_errata_packages, class_name: "Katello::ModuleStreamErratumPackage", dependent: :destroy, inverse_of: :module_stream
11
+ has_many :erratum_packages, class_name: "Katello::ErratumPackage", :through => :module_stream_errata_packages
12
+
13
+ has_many :content_facet_applicable_module_streams, :class_name => "Katello::ContentFacetApplicableModuleStream",
14
+ :dependent => :destroy, :inverse_of => :module_stream
15
+ has_many :content_facets, :through => :content_facet_applicable_module_streams, :class_name => "Katello::Host::ContentFacet"
10
16
 
11
17
  scoped_search on: :name, complete_value: true
12
18
  scoped_search on: :uuid, complete_value: true
@@ -36,6 +42,14 @@ module Katello
36
42
  RepositoryModuleStream
37
43
  end
38
44
 
45
+ def self.content_facet_association_class
46
+ ContentFacetApplicableModuleStream
47
+ end
48
+
49
+ def self.installable_for_hosts(hosts = nil)
50
+ ApplicableContentHelper.new(ModuleStream).installable_for_hosts(hosts)
51
+ end
52
+
39
53
  def update_from_json(json)
40
54
  shared_attributes = json.keys & self.class.column_names
41
55
  shared_json = json.select { |key, _v| shared_attributes.include?(key) }
@@ -83,6 +97,10 @@ module Katello
83
97
  items.join(":")
84
98
  end
85
99
 
100
+ def module_spec_hash
101
+ {:name => name, :stream => stream, :version => version, :context => context, :arch => arch, :id => id}.compact
102
+ end
103
+
86
104
  def self.parse_module_spec(module_spec)
87
105
  # NAME:STREAM:VERSION:CONTEXT:ARCH/PROFILE
88
106
  spec = module_spec.split("/").first
@@ -0,0 +1,6 @@
1
+ module Katello
2
+ class ModuleStreamErratumPackage < Katello::Model
3
+ belongs_to :module_stream, class_name: "Katello::ModuleStream", inverse_of: :module_stream_errata_packages
4
+ belongs_to :erratum_package, class_name: "Katello::ErratumPackage", inverse_of: :module_stream_errata_packages
5
+ end
6
+ end
@@ -127,8 +127,6 @@ module Katello
127
127
  !self.provider.redhat_provider? || self.repositories.present?
128
128
  end
129
129
 
130
- delegate :organization, to: :provider
131
-
132
130
  delegate :library, to: :organization
133
131
 
134
132
  def plan_name
@@ -22,6 +22,7 @@ module Katello
22
22
  scoped_search :on => :content_type, :relation => :content
23
23
  scoped_search :on => :label, :relation => :content
24
24
  scoped_search :on => :name, :relation => :product, :rename => :product_name
25
+ scoped_search :on => :id, :relation => :product, :rename => :product_id, :only_explicit => true
25
26
 
26
27
  def self.content_table_name
27
28
  Katello::Content.table_name
@@ -96,7 +96,10 @@ module Katello
96
96
 
97
97
  validates_with Validators::ContainerImageNameValidator, :attributes => :container_repository_name, :allow_blank => false, :if => :docker?
98
98
  validates :pulp_id, :presence => true, :uniqueness => true, :if => proc { |r| r.name.present? }
99
- validates :container_repository_name, :uniqueness => true, :if => :docker?
99
+ validates :container_repository_name, :if => :docker?, :uniqueness => {message: ->(object, _data) do
100
+ _("for repository '%{name}' is not unique and cannot be created in '%{env}'. Its Container Repository Name (%{container_name}) conflicts with an existing repository. Consider changing the Lifecycle Environment's Registry Name Pattern to something more specific.") %
101
+ {name: object.name, container_name: object.container_repository_name, :env => object.environment.name}
102
+ end}
100
103
 
101
104
  before_validation :set_pulp_id
102
105
  before_validation :set_container_repository_name, :if => :docker?
@@ -134,12 +137,14 @@ module Katello
134
137
  scoped_search :on => :redhat, :complete_value => { :true => true, :false => false }, :ext_method => :search_by_redhat
135
138
  scoped_search :on => :container_repository_name, :complete_value => true
136
139
  scoped_search :on => :description, :relation => :root, :only_explicit => true
140
+ scoped_search :on => :name, :relation => :product, :rename => :product_name
141
+ scoped_search :on => :id, :relation => :product, :rename => :product_id, :only_explicit => true
137
142
 
138
143
  delegate :product, :redhat?, :custom?, :to => :root
139
144
  delegate :yum?, :docker?, :puppet?, :deb?, :file?, :ostree?, :to => :root
140
145
  delegate :name, :label, :docker_upstream_name, :url, :to => :root
141
146
 
142
- delegate :name, :created_at, :updated_at, :major, :minor, :gpg_key_id, :content_id, :arch, :label, :url, :unprotected,
147
+ delegate :name, :created_at, :updated_at, :major, :minor, :gpg_key_id, :gpg_key, :content_id, :arch, :label, :url, :unprotected,
143
148
  :content_type, :product_id, :checksum_type, :docker_upstream_name, :mirror_on_sync, :"mirror_on_sync?",
144
149
  :download_policy, :verify_ssl_on_sync, :"verify_ssl_on_sync?", :upstream_username, :upstream_password,
145
150
  :ostree_upstream_sync_policy, :ostree_upstream_sync_depth, :deb_releases, :deb_components, :deb_architectures,
@@ -150,6 +155,10 @@ module Katello
150
155
  joins(:root).where("#{RootRepository.table_name}.content_type" => content_type)
151
156
  end
152
157
 
158
+ def backend_service(smart_proxy)
159
+ @service ||= Katello::Pulp::Repository.instance_for_type(self, smart_proxy)
160
+ end
161
+
153
162
  def organization
154
163
  if self.environment
155
164
  self.environment.organization
@@ -278,6 +287,10 @@ module Katello
278
287
  all_instances
279
288
  end
280
289
 
290
+ def to_hash(content_source = nil)
291
+ {id: id, name: label, url: full_path(content_source)}
292
+ end
293
+
281
294
  #is the repo cloned in the specified environment
282
295
  def cloned_in?(env)
283
296
  !get_clone(env).nil?
@@ -481,10 +494,6 @@ module Katello
481
494
  self.ostree_branches.map(&:name)
482
495
  end
483
496
 
484
- def ostree_capsule_sync_depth
485
- -1
486
- end
487
-
488
497
  def units_for_removal(ids)
489
498
  table_name = removable_unit_association.table_name
490
499
  is_integer = Integer(ids.first) rescue false #assume all ids are either integers or not
@@ -235,7 +235,7 @@ module Katello
235
235
  changeable_attributes = %w(url unprotected checksum_type docker_upstream_name download_policy mirror_on_sync verify_ssl_on_sync
236
236
  upstream_username upstream_password ostree_upstream_sync_policy ostree_upstream_sync_depth ignore_global_proxy ignorable_content)
237
237
  changeable_attributes += %w(name container_repository_name) if docker?
238
- changeable_attributes += %w(deb_releases deb_components deb_architectures) if deb?
238
+ changeable_attributes += %w(deb_releases deb_components deb_architectures gpg_key_id) if deb?
239
239
  changeable_attributes.any? { |key| previous_changes.key?(key) }
240
240
  end
241
241
 
@@ -31,6 +31,10 @@ module Katello
31
31
  RepositoryRpm
32
32
  end
33
33
 
34
+ def self.content_facet_association_class
35
+ ContentFacetApplicableRpm
36
+ end
37
+
34
38
  def self.scoped_search_version(_key, operator, value)
35
39
  self.scoped_search_sortable('version', operator, value)
36
40
  end
@@ -222,23 +226,7 @@ module Katello
222
226
  end
223
227
 
224
228
  def self.installable_for_hosts(hosts = nil)
225
- hosts = ::Host.where(:id => hosts) if hosts && hosts.is_a?(Array)
226
-
227
- query = Katello::Rpm.joins(:content_facet_applicable_rpms).
228
- joins("INNER JOIN #{Katello::ContentFacetRepository.table_name} on \
229
- #{Katello::ContentFacetRepository.table_name}.content_facet_id = #{Katello::ContentFacetApplicableRpm.table_name}.content_facet_id").
230
- joins("INNER JOIN #{Katello::RepositoryRpm.table_name} AS host_repo_rpm ON \
231
- host_repo_rpm.rpm_id = #{Katello::Rpm.table_name}.id AND \
232
- #{Katello::ContentFacetRepository.table_name}.repository_id = host_repo_rpm.repository_id")
233
-
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
229
+ ApplicableContentHelper.new(Rpm).installable_for_hosts(hosts)
242
230
  end
243
231
 
244
232
  def self.applicable_to_hosts(hosts)
@@ -0,0 +1,111 @@
1
+ module Katello
2
+ class ApplicableContentHelper
3
+ attr_accessor :content_facet, :content_unit_class
4
+
5
+ def initialize(content_unit_class, content_facet = nil)
6
+ self.content_facet = content_facet
7
+ self.content_unit_class = content_unit_class
8
+ end
9
+
10
+ def import(partial)
11
+ to_add, to_remove = applicable_differences(partial)
12
+ content_facet_association_class.where(:content_facet_id => content_facet.id).delete_all unless partial
13
+ ActiveRecord::Base.transaction do
14
+ insert(to_add) unless to_add.blank?
15
+ remove(to_remove) unless to_remove.blank?
16
+ end
17
+ end
18
+
19
+ def installable(env = nil, content_view = nil)
20
+ repos = if env && content_view
21
+ Katello::Repository.in_environment(env).in_content_views([content_view])
22
+ else
23
+ content_facet.bound_repositories.pluck(:id)
24
+ end
25
+ content_facet.send(applicable_units).in_repositories(repos)
26
+ end
27
+
28
+ def installable_for_hosts(hosts = nil)
29
+ # Main goal of this query
30
+ # 1) Get me the applicable content units for these set of hosts
31
+ # 2) Now further prune this list. Only include units from repos that have been "enabled" on those hosts.
32
+ # In other words, prune the list to only include the units in the "bound" repositories signified by
33
+ # the inner join between ContentFacetRepository and Repository<Unit>
34
+
35
+ facet_repos = Katello::ContentFacetRepository.joins(:content_facet => :host).select(:repository_id)
36
+ facet_content_units = content_facet_association_class.joins(:content_facet => :host).select(content_unit_association_id)
37
+
38
+ if hosts
39
+ hosts = ::Host.where(id: hosts) if hosts.is_a?(Array)
40
+ facet_repos = facet_repos.merge(hosts).reorder(nil)
41
+ facet_content_units = facet_content_units.merge(hosts).reorder(nil)
42
+ end
43
+
44
+ content_unit_class.joins(repository_association_units).
45
+ where(repository_association_class.table_name => {:repository_id => facet_repos,
46
+ content_unit_association_id => facet_content_units}).distinct
47
+ end
48
+
49
+ private
50
+
51
+ def content_units
52
+ content_unit_class.name.demodulize.pluralize.underscore.to_sym
53
+ end
54
+
55
+ def applicable_units
56
+ "applicable_#{content_units}".to_sym
57
+ end
58
+
59
+ def content_unit_association_id
60
+ "#{content_unit_class.name.demodulize.underscore}_id".to_sym
61
+ end
62
+
63
+ def content_type
64
+ content_unit_class.const_get(:CONTENT_TYPE)
65
+ end
66
+
67
+ def content_facet_association_class
68
+ # Example: ContentFacetErratum
69
+ self.content_unit_class.content_facet_association_class
70
+ end
71
+
72
+ def content_facet_association_units
73
+ content_facet_association_class.name.demodulize.pluralize.underscore.to_sym
74
+ end
75
+
76
+ def repository_association_class
77
+ content_unit_class.repository_association_class
78
+ end
79
+
80
+ def repository_association_units
81
+ repository_association_class.name.demodulize.pluralize.underscore.to_sym
82
+ end
83
+
84
+ def applicable_differences(partial)
85
+ content_uuids = ::Katello::Pulp::Consumer.new(content_facet.uuid).applicable_ids(content_type)
86
+ if partial
87
+ consumer_uuids = content_facet.send(applicable_units).pluck("#{content_unit_class.table_name}.uuid")
88
+ to_remove = consumer_uuids - content_uuids
89
+ to_add = content_uuids - consumer_uuids
90
+ else
91
+ to_add = content_uuids
92
+ to_remove = nil
93
+ end
94
+ [to_add, to_remove]
95
+ end
96
+
97
+ def insert(uuids)
98
+ applicable_ids = content_unit_class.where(:uuid => uuids).pluck(:id)
99
+ unless applicable_ids.empty?
100
+ inserts = applicable_ids.map { |applicable_id| "(#{applicable_id.to_i}, #{content_facet.id.to_i})" }
101
+ sql = "INSERT INTO #{content_facet_association_class.table_name} (#{content_unit_association_id}, content_facet_id) VALUES #{inserts.join(', ')}"
102
+ ActiveRecord::Base.connection.execute(sql)
103
+ end
104
+ end
105
+
106
+ def remove(uuids)
107
+ applicable_ids = content_unit_class.where(:uuid => uuids).pluck(:id)
108
+ content_facet_association_class.where(:content_facet_id => content_facet.id, content_unit_association_id => applicable_ids).delete_all
109
+ end
110
+ end
111
+ end
@@ -14,6 +14,13 @@ module Katello
14
14
  URI.parse(url)
15
15
  end
16
16
 
17
+ # If there is an 'AppStream' variant, we need to make it
18
+ # available to Anaconda
19
+ def additional_media
20
+ appstream = entity.operatingsystem.variant_repo(entity, 'AppStream')
21
+ super + (appstream ? [appstream] : [])
22
+ end
23
+
17
24
  def unique_id
18
25
  @unique_id ||= begin
19
26
  "#{kickstart_repo.name.parameterize}-#{kickstart_repo.id}"
@@ -20,16 +20,22 @@ module Katello
20
20
  Katello.pulp_server.extensions.consumer.upload_profile(self.uuid, 'rpm', profile)
21
21
  end
22
22
 
23
- def applicable_errata_ids
24
- response = Katello.pulp_server.extensions.consumer.applicable_errata([self.uuid])
25
- return [] if response.empty?
26
- response[0]['applicability']['erratum'] || []
23
+ def upload_module_stream_profile(profile)
24
+ Katello.pulp_server.extensions.consumer.upload_profile(self.uuid, 'modulemd', profile)
27
25
  end
28
26
 
29
- def applicable_rpm_ids
30
- response = Katello.pulp_server.extensions.consumer.applicable_rpms([self.uuid])
27
+ def applicable_ids(content_unit_type)
28
+ consumer_method = case content_unit_type
29
+ when ::Katello::Erratum::CONTENT_TYPE
30
+ :applicable_errata
31
+ when ::Katello::ModuleStream::CONTENT_TYPE
32
+ :applicable_module_streams
33
+ else
34
+ :applicable_rpms
35
+ end
36
+ response = Katello.pulp_server.extensions.consumer.send(consumer_method, [self.uuid])
31
37
  return [] if response.empty?
32
- response[0]['applicability']['rpm'] || []
38
+ response[0]['applicability'][content_unit_type] || []
33
39
  end
34
40
 
35
41
  def bind_yum_repositories(ids)
@@ -1,21 +1,174 @@
1
1
  module Katello
2
2
  module Pulp
3
3
  class Repository < ::Actions::Pulp::Abstract
4
- attr_accessor :repo
4
+ attr_accessor :repo, :input, :pulp_api
5
+ attr_accessor :smart_proxy
6
+ delegate :root, to: :repo
5
7
 
6
- def initialize(repo, smart_proxy = nil)
8
+ def initialize(repo, smart_proxy)
7
9
  @repo = repo
8
10
  @smart_proxy = smart_proxy
9
11
  end
10
12
 
13
+ def backend_data(force = false)
14
+ return smart_proxy.pulp_api.extensions.repository.retrieve_with_details(repo.pulp_id) if (repo.pulp_id && force)
15
+ @backend_data ||= smart_proxy.pulp_api.extensions.repository.retrieve_with_details(repo.pulp_id) if repo.pulp_id
16
+ rescue RestClient::ResourceNotFound
17
+ nil
18
+ end
19
+
20
+ def self.instance_for_type(repo, smart_proxy)
21
+ Katello::RepositoryTypeManager.repository_types[repo.root.content_type].service_class.new(repo, smart_proxy)
22
+ end
23
+
24
+ def partial_repo_path
25
+ fail NotImplementedError
26
+ end
27
+
28
+ def importer_class
29
+ fail NotImplementedError
30
+ end
31
+
32
+ def master_importer_configuration
33
+ fail NotImplementedError
34
+ end
35
+
36
+ def mirror_importer_configuration
37
+ fail NotImplementedError
38
+ end
39
+
40
+ def generate_mirror_importer
41
+ fail NotImplementedError
42
+ end
43
+
44
+ def generate_master_importer
45
+ fail NotImplementedError
46
+ end
47
+
48
+ def generate_distributors
49
+ fail NotImplementedError
50
+ end
51
+
11
52
  def sync(overrides = {})
12
53
  sync_options = {}
13
54
  sync_options[:max_speed] = SETTINGS.dig(:katello, :pulp, :sync_KBlimit)
14
55
  sync_options[:num_threads] = SETTINGS.dig(:katello, :pulp, :sync_threads)
15
- sync_options[:feed] = overrides[:source_url] if overrides[:source_url]
56
+ sync_options[:feed] = overrides[:feed] if overrides[:feed]
16
57
  sync_options[:validate] = !SETTINGS.dig(:katello, :pulp, :skip_checksum_validation)
17
58
  sync_options.merge!(overrides[:options]) if overrides[:options]
18
- [::Katello::CapsuleContent.new(@smart_proxy).pulp_server.resources.repository.sync(@repo.pulp_id, override_config: sync_options.compact!)]
59
+ [smart_proxy.pulp_api.resources.repository.sync(@repo.pulp_id, override_config: sync_options.compact!)]
60
+ end
61
+
62
+ def create
63
+ smart_proxy.pulp_api.extensions.repository.create_with_importer_and_distributors(repo.pulp_id, generate_importer,
64
+ generate_distributors, display_name: root.name)
65
+ end
66
+
67
+ def external_url(force_https = false)
68
+ uri = URI.parse(::SmartProxy.pulp_master.pulp_url)
69
+ uri.scheme = (root.unprotected && !force_https) ? 'http' : 'https'
70
+ uri.path = partial_repo_path
71
+ uri.to_s
72
+ end
73
+
74
+ def generate_importer
75
+ if smart_proxy.pulp_mirror?
76
+ generate_mirror_importer
77
+ elsif repo.in_default_view?
78
+ generate_master_importer
79
+ else #content view repositories don't need any importer configuration
80
+ importer_class.new
81
+ end
82
+ end
83
+
84
+ def master_importer_connection_options
85
+ options = {
86
+ proxy_host: self.proxy_host_importer_value,
87
+ basic_auth_username: root.upstream_username,
88
+ basic_auth_password: root.upstream_password,
89
+ ssl_validation: root.verify_ssl_on_sync?
90
+ }
91
+ options.merge(master_importer_ssl_options)
92
+ end
93
+
94
+ def master_importer_ssl_options
95
+ if root.redhat? && Katello::Resources::CDN::CdnResource.redhat_cdn?(root.url)
96
+ {
97
+ ssl_client_cert: root.product.certificate,
98
+ ssl_client_key: root.product.key,
99
+ ssl_ca_cert: Katello::Repository.feed_ca_cert(root.url)
100
+ }
101
+ elsif root.custom?
102
+ {
103
+ ssl_client_cert: root.ssl_client_cert&.content,
104
+ ssl_client_key: root.ssl_client_key&.content,
105
+ ssl_ca_cert: root.ssl_ca_cert&.content
106
+ }
107
+ else
108
+ {}
109
+ end
110
+ end
111
+
112
+ def mirror_importer_connection_options
113
+ ueber_cert = ::Cert::Certs.ueber_cert(root.organization)
114
+ {
115
+ ssl_client_cert: ueber_cert[:cert],
116
+ ssl_client_key: ueber_cert[:key],
117
+ ssl_ca_cert: ::Cert::Certs.ca_cert
118
+ }
119
+ end
120
+
121
+ def proxy_host_importer_value
122
+ root.ignore_global_proxy ? "" : nil
123
+ end
124
+
125
+ def refresh
126
+ update_or_associate_importer
127
+ update_or_associate_distributors
128
+ remove_unnecessary_distributors
129
+ end
130
+
131
+ def update_or_associate_importer
132
+ existing_importers = backend_data["importers"]
133
+ importer = generate_importer
134
+ found = existing_importers.find { |i| i['importer_type_id'] == importer.id }
135
+
136
+ if found
137
+ ssl_ca_cert = importer.config.delete('ssl_ca_cert')
138
+ ssl_client_cert = importer.config.delete('ssl_client_cert')
139
+ ssl_client_key = importer.config.delete('ssl_client_key')
140
+ importer.config['basic_auth_username'] = nil if importer.config['basic_auth_username'].blank?
141
+ importer.config['basic_auth_password'] = nil if importer.config['basic_auth_password'].blank?
142
+ # Update ssl options by themselves workaround for https://pulp.plan.io/issues/2727
143
+ smart_proxy.pulp_api.resources.repository.update_importer(repo.pulp_id, found['id'], :ssl_client_cert => ssl_client_cert,
144
+ :ssl_client_key => ssl_client_key, :ssl_ca_cert => ssl_ca_cert)
145
+ smart_proxy.pulp_api.resources.repository.update_importer(repo.pulp_id, found['id'], importer.config)
146
+ else
147
+ smart_proxy.pulp_api.resources.repository.associate_importer(repo.pulp_id, repo.importers.first['importer_type_id'], importer.config)
148
+ end
149
+ end
150
+
151
+ def update_or_associate_distributors
152
+ existing_distributors = backend_data["distributors"]
153
+ generate_distributors.each do |distributor|
154
+ found = existing_distributors.find { |i| i['distributor_type_id'] == distributor.type_id }
155
+ if found
156
+ smart_proxy.pulp_api.resources.repository.
157
+ update_distributor(repo.pulp_id, found['id'], distributor.config)
158
+ else
159
+ smart_proxy.pulp_api.resources.repository.
160
+ associate_distributor(repo.pulp_id, distributor.type_id, distributor.config, :distributor_id => distributor.id)
161
+ end
162
+ end
163
+ end
164
+
165
+ def remove_unnecessary_distributors
166
+ existing_distributors = backend_data["distributors"]
167
+ generated_distributors = generate_distributors
168
+ existing_distributors.each do |distributor|
169
+ found = generated_distributors.find { |dist| dist.type_id == distributor['distributor_type_id'] }
170
+ smart_proxy.pulp_api.resources.repository.delete_distributor(repo.pulp_id, distributor['id']) unless found
171
+ end
19
172
  end
20
173
  end
21
174
  end