katello 3.17.0 → 3.18.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 (272) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +38 -21
  3. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +3 -1
  4. data/app/controllers/katello/api/v2/activation_keys_controller.rb +10 -15
  5. data/app/controllers/katello/api/v2/capsule_content_controller.rb +2 -2
  6. data/app/controllers/katello/api/v2/content_credentials_controller.rb +1 -8
  7. data/app/controllers/katello/api/v2/content_export_incrementals_controller.rb +98 -0
  8. data/app/controllers/katello/api/v2/content_exports_controller.rb +84 -0
  9. data/app/controllers/katello/api/v2/content_imports_controller.rb +59 -0
  10. data/app/controllers/katello/api/v2/content_view_components_controller.rb +31 -14
  11. data/app/controllers/katello/api/v2/content_view_filters_controller.rb +17 -8
  12. data/app/controllers/katello/api/v2/content_view_repositories_controller.rb +1 -0
  13. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +65 -71
  14. data/app/controllers/katello/api/v2/content_views_controller.rb +37 -26
  15. data/app/controllers/katello/api/v2/environments_controller.rb +8 -8
  16. data/app/controllers/katello/api/v2/gpg_keys_controller.rb +5 -5
  17. data/app/controllers/katello/api/v2/host_collections_controller.rb +19 -16
  18. data/app/controllers/katello/api/v2/host_debs_controller.rb +1 -0
  19. data/app/controllers/katello/api/v2/host_errata_controller.rb +2 -2
  20. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +35 -6
  21. data/app/controllers/katello/api/v2/products_bulk_actions_controller.rb +1 -1
  22. data/app/controllers/katello/api/v2/products_controller.rb +9 -9
  23. data/app/controllers/katello/api/v2/repositories_bulk_actions_controller.rb +1 -1
  24. data/app/controllers/katello/api/v2/repositories_controller.rb +10 -5
  25. data/app/controllers/katello/api/v2/repository_sets_controller.rb +24 -14
  26. data/app/controllers/katello/api/v2/subscriptions_controller.rb +1 -1
  27. data/app/controllers/katello/api/v2/sync_plans_controller.rb +8 -9
  28. data/app/controllers/katello/api/v2/upstream_subscriptions_controller.rb +9 -2
  29. data/app/controllers/katello/concerns/api/v2/authorization.rb +19 -5
  30. data/app/controllers/katello/concerns/api/v2/bulk_hosts_extensions.rb +22 -18
  31. data/app/controllers/katello/concerns/api/v2/registration_controller_extensions.rb +21 -0
  32. data/app/controllers/katello/concerns/api/v2/repository_content_controller.rb +1 -1
  33. data/app/controllers/katello/concerns/organizations_controller_extensions.rb +2 -1
  34. data/app/controllers/katello/concerns/registration_controller_extensions.rb +16 -0
  35. data/app/helpers/katello/katello_urls_helper.rb +5 -2
  36. data/app/lib/actions/candlepin/product/content_create.rb +2 -0
  37. data/app/lib/actions/candlepin/product/content_update.rb +2 -0
  38. data/app/lib/actions/helpers/smart_proxy_sync_history_helper.rb +24 -0
  39. data/app/lib/actions/katello/applicability/hosts/bulk_generate.rb +6 -2
  40. data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
  41. data/app/lib/actions/katello/capsule_content/sync_capsule.rb +16 -7
  42. data/app/lib/actions/katello/content_view/promote_to_environment.rb +1 -1
  43. data/app/lib/actions/katello/content_view/publish.rb +9 -9
  44. data/app/lib/actions/katello/content_view_version/import.rb +8 -13
  45. data/app/lib/actions/katello/content_view_version/import_library.rb +17 -0
  46. data/app/lib/actions/katello/content_view_version/incremental_update.rb +18 -3
  47. data/app/lib/actions/katello/host/hypervisors_update.rb +18 -0
  48. data/app/lib/actions/katello/host/update_system_purpose.rb +31 -0
  49. data/app/lib/actions/katello/host/upload_package_profile.rb +3 -1
  50. data/app/lib/actions/katello/host/upload_profiles.rb +8 -6
  51. data/app/lib/actions/katello/organization/manifest_delete.rb +0 -1
  52. data/app/lib/actions/katello/organization/manifest_import.rb +0 -1
  53. data/app/lib/actions/katello/organization/manifest_refresh.rb +0 -1
  54. data/app/lib/actions/katello/product/content_create.rb +7 -6
  55. data/app/lib/actions/katello/repository/filtered_index_content.rb +10 -1
  56. data/app/lib/actions/katello/repository/import_upload.rb +4 -1
  57. data/app/lib/actions/katello/repository/remove_content.rb +1 -1
  58. data/app/lib/actions/katello/repository/sync.rb +3 -1
  59. data/app/lib/actions/katello/repository/update.rb +5 -1
  60. data/app/lib/actions/katello/repository/upload_files.rb +1 -0
  61. data/app/lib/actions/middleware/record_smart_proxy_sync_history.rb +15 -0
  62. data/app/lib/actions/pulp/consumer/sync_capsule.rb +4 -2
  63. data/app/lib/actions/pulp/repository/distributor_publish.rb +1 -1
  64. data/app/lib/actions/pulp3/capsule_content/sync.rb +1 -0
  65. data/app/lib/actions/pulp3/content_migration.rb +10 -0
  66. data/app/lib/actions/pulp3/content_migration_presenter.rb +59 -0
  67. data/app/lib/actions/pulp3/content_view/delete_repository_references.rb +1 -1
  68. data/app/lib/actions/pulp3/content_view_version/create_importer.rb +7 -3
  69. data/app/lib/actions/pulp3/content_view_version/export.rb +7 -1
  70. data/app/lib/actions/pulp3/content_view_version/import.rb +7 -3
  71. data/app/lib/actions/pulp3/import_migration.rb +6 -1
  72. data/app/lib/actions/pulp3/orchestration/content_view_version/copy_version_units_to_library.rb +2 -1
  73. data/app/lib/actions/pulp3/orchestration/content_view_version/export.rb +38 -14
  74. data/app/lib/actions/pulp3/orchestration/content_view_version/export_library.rb +60 -0
  75. data/app/lib/actions/pulp3/orchestration/content_view_version/import.rb +16 -10
  76. data/app/lib/actions/pulp3/orchestration/repository/generate_metadata.rb +4 -1
  77. data/app/lib/actions/pulp3/orchestration/repository/import_upload.rb +16 -3
  78. data/app/lib/actions/pulp3/repository/commit_upload.rb +2 -1
  79. data/app/lib/actions/pulp3/repository/copy_content.rb +1 -1
  80. data/app/lib/actions/pulp3/repository/delete.rb +1 -1
  81. data/app/lib/actions/pulp3/repository/save_artifact.rb +1 -1
  82. data/app/lib/actions/pulp3/repository/save_version.rb +1 -1
  83. data/app/lib/actions/pulp3/repository/upload_tag.rb +18 -0
  84. data/app/lib/katello/resources/candlepin/consumer.rb +2 -2
  85. data/app/lib/katello/resources/candlepin/owner.rb +5 -0
  86. data/app/lib/katello/resources/candlepin/upstream_consumer.rb +6 -0
  87. data/app/lib/katello/resources/registry.rb +3 -3
  88. data/app/models/katello/authorization/activation_key.rb +4 -0
  89. data/app/models/katello/authorization/content_view.rb +13 -0
  90. data/app/models/katello/authorization/content_view_component.rb +15 -0
  91. data/app/models/katello/authorization/content_view_filter.rb +15 -0
  92. data/app/models/katello/authorization/content_view_version.rb +25 -2
  93. data/app/models/katello/authorization/content_view_version_export_history.rb +1 -1
  94. data/app/models/katello/authorization/gpg_key.rb +12 -4
  95. data/app/models/katello/authorization/lifecycle_environment.rb +8 -0
  96. data/app/models/katello/authorization/organization.rb +8 -0
  97. data/app/models/katello/authorization/sync_plan.rb +16 -0
  98. data/app/models/katello/concerns/operatingsystem_extensions.rb +2 -0
  99. data/app/models/katello/concerns/organization_extensions.rb +4 -5
  100. data/app/models/katello/concerns/smart_proxy_extensions.rb +6 -4
  101. data/app/models/katello/content_migration_progress.rb +4 -0
  102. data/app/models/katello/content_view.rb +30 -4
  103. data/app/models/katello/content_view_component.rb +2 -0
  104. data/app/models/katello/content_view_filter.rb +5 -0
  105. data/app/models/katello/content_view_history.rb +2 -1
  106. data/app/models/katello/content_view_package_filter.rb +1 -1
  107. data/app/models/katello/content_view_puppet_module.rb +8 -0
  108. data/app/models/katello/content_view_repository.rb +13 -1
  109. data/app/models/katello/content_view_version_export_history.rb +8 -1
  110. data/app/models/katello/glue/candlepin/pool.rb +9 -14
  111. data/app/models/katello/glue/pulp/repo.rb +8 -0
  112. data/app/models/katello/gpg_key.rb +1 -1
  113. data/app/models/katello/ping.rb +8 -3
  114. data/app/models/katello/repository.rb +33 -0
  115. data/app/models/katello/root_repository.rb +26 -1
  116. data/app/models/katello/smart_proxy_sync_history.rb +8 -0
  117. data/app/services/katello/candlepin/event_handler.rb +2 -0
  118. data/app/services/katello/candlepin/message_handler.rb +34 -0
  119. data/app/services/katello/candlepin/upstream_consumer.rb +28 -0
  120. data/app/services/katello/host_status_manager.rb +9 -0
  121. data/app/services/katello/pulp3/api/apt.rb +57 -0
  122. data/app/services/katello/pulp3/api/core.rb +8 -0
  123. data/app/services/katello/pulp3/api/docker.rb +4 -0
  124. data/app/services/katello/pulp3/content_view_version/export.rb +125 -8
  125. data/app/services/katello/pulp3/content_view_version/import.rb +39 -34
  126. data/app/services/katello/pulp3/content_view_version/import_export_common.rb +6 -16
  127. data/app/services/katello/pulp3/content_view_version/import_validator.rb +114 -0
  128. data/app/services/katello/pulp3/deb.rb +38 -0
  129. data/app/services/katello/pulp3/docker_manifest.rb +1 -0
  130. data/app/services/katello/pulp3/docker_tag.rb +1 -0
  131. data/app/services/katello/pulp3/migration.rb +51 -10
  132. data/app/services/katello/pulp3/pulp_content_unit.rb +5 -0
  133. data/app/services/katello/pulp3/repository.rb +10 -4
  134. data/app/services/katello/pulp3/repository/ansible_collection.rb +9 -0
  135. data/app/services/katello/pulp3/repository/apt.rb +63 -0
  136. data/app/services/katello/pulp3/repository/docker.rb +9 -0
  137. data/app/services/katello/pulp3/repository/yum.rb +14 -9
  138. data/app/services/katello/pulp3/repository_mirror.rb +9 -4
  139. data/app/services/katello/pulp3/task.rb +4 -0
  140. data/app/services/katello/pulp3/task_group.rb +4 -0
  141. data/app/services/katello/repository_type.rb +2 -1
  142. data/app/services/katello/smart_proxy_helper.rb +9 -0
  143. data/app/views/dashboard/_subscription_widget.html.erb +0 -5
  144. data/app/views/foreman/hosts/_registration.html.erb +12 -0
  145. data/app/views/katello/api/v2/content_view_version_export_histories/show.json.rabl +1 -1
  146. data/app/views/katello/api/v2/content_views/base.json.rabl +1 -0
  147. data/app/views/katello/api/v2/repositories/base.json.rabl +1 -1
  148. data/app/views/katello/layouts/react.html.erb +3 -2
  149. data/app/views/overrides/activation_keys/_host_tab_pane.html.erb +1 -5
  150. data/app/views/overrides/organizations/_index_row_override.html.erb +1 -1
  151. data/config/routes/api/v2.rb +24 -2
  152. data/config/routes/overrides.rb +1 -0
  153. data/db/migrate/20200929200357_create_katello_smart_proxy_sync_history.rb +13 -0
  154. data/db/migrate/20201008204114_add_os_versions_to_katello_root_repositories.rb +5 -0
  155. data/db/migrate/20201012172713_remove_gpg_key_perms.rb +23 -0
  156. data/db/migrate/20201012192035_add_metadata_to_katello_content_view_version_export_history.rb +5 -0
  157. data/db/migrate/20201021150008_add_import_only_to_katello_content_view.rb +5 -0
  158. data/db/migrate/20201119211133_pulp3_migration_progress.rb +9 -0
  159. data/db/seeds.d/111-upgrade_tasks.rb +2 -1
  160. data/engines/bastion/app/assets/javascripts/bastion/components/notification.service.js +1 -1
  161. data/engines/bastion/app/assets/javascripts/bastion/components/nutupane.factory.js +8 -13
  162. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-system-purpose-modal.controller.js +112 -0
  163. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-system-purpose-modal.html +78 -0
  164. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-host-modal-helper.service.js +11 -0
  165. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.controller.js +5 -0
  166. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-debs-installed.controller.js +2 -42
  167. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +4 -0
  168. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/content-views.controller.js +6 -2
  169. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-details.controller.js +12 -0
  170. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-details.html +7 -7
  171. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-info.html +7 -1
  172. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/new/content-view-new.controller.js +17 -3
  173. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/new/views/content-view-new.html +16 -2
  174. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/views/content-views.html +5 -0
  175. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/details/host-collection-details.controller.js +4 -0
  176. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/host-collections/details/views/host-collection-info.html +6 -0
  177. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/hosts/host-bulk-action.factory.js +2 -1
  178. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +92 -19
  179. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/de.po +17 -20
  180. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/es.po +17 -24
  181. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/fr.po +1292 -1170
  182. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/it.po +17 -20
  183. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ja.po +858 -807
  184. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ko.po +18 -19
  185. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/pt_BR.po +17 -24
  186. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/ru.po +17 -18
  187. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_CN.po +986 -971
  188. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/locale/zh_TW.po +19 -20
  189. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/translations.js +9 -9
  190. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/bulk/products-bulk-advanced-sync-modal.controller.js +6 -7
  191. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +168 -155
  192. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +17 -2
  193. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +125 -113
  194. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +15 -3
  195. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/os-versions.service.js +46 -0
  196. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repository-types.service.js +8 -1
  197. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/views/content-access-mode-banner.html +1 -1
  198. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/details/views/sync-plan-details.html +1 -1
  199. data/lib/katello/engine.rb +2 -0
  200. data/lib/katello/permission_creator.rb +98 -69
  201. data/lib/katello/permissions/host_permissions.rb +1 -0
  202. data/lib/katello/plugin.rb +10 -2
  203. data/lib/katello/repository_types/deb.rb +9 -1
  204. data/lib/katello/tasks/pulp3_migration.rake +17 -3
  205. data/lib/katello/tasks/pulp3_migration_abort.rake +22 -0
  206. data/lib/katello/tasks/pulp3_migration_stats.rake +41 -0
  207. data/lib/katello/tasks/receptor/extract_orgs.rake +1 -1
  208. data/lib/katello/tasks/reset.rake +2 -1
  209. data/lib/katello/tasks/upgrades/3.18/add_cvv_export_history_metadata.rb +18 -0
  210. data/lib/katello/version.rb +1 -1
  211. data/locale/action_names.rb +51 -44
  212. data/locale/bn/katello.po +279 -55
  213. data/locale/cs/katello.po +278 -51
  214. data/locale/de/katello.po +279 -52
  215. data/locale/en/katello.po +278 -49
  216. data/locale/es/katello.po +279 -51
  217. data/locale/fr/katello.po +279 -51
  218. data/locale/gu/katello.po +279 -55
  219. data/locale/hi/katello.po +279 -55
  220. data/locale/it/katello.po +279 -51
  221. data/locale/ja/katello.po +279 -52
  222. data/locale/katello.pot +1379 -971
  223. data/locale/kn/katello.po +279 -55
  224. data/locale/ko/katello.po +279 -51
  225. data/locale/mr/katello.po +279 -55
  226. data/locale/or/katello.po +279 -55
  227. data/locale/pa/katello.po +279 -55
  228. data/locale/pt/katello.po +278 -52
  229. data/locale/pt_BR/katello.po +279 -51
  230. data/locale/ru/katello.po +279 -51
  231. data/locale/ta/katello.po +279 -55
  232. data/locale/te/katello.po +279 -55
  233. data/locale/zh_CN/katello.po +279 -51
  234. data/locale/zh_TW/katello.po +279 -52
  235. data/webpack/components/ActionableDetail.js +2 -1
  236. data/webpack/components/Search/Search.js +1 -1
  237. data/webpack/components/Table/MainTable.js +6 -2
  238. data/webpack/components/Table/TableWrapper.js +46 -9
  239. data/webpack/scenes/ContentViews/ContentViewSelectors.js +7 -3
  240. data/webpack/scenes/ContentViews/ContentViewsConstants.js +8 -0
  241. data/webpack/scenes/ContentViews/ContentViewsPage.js +2 -9
  242. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +25 -3
  243. data/webpack/scenes/ContentViews/Details/ContentViewDetailSelectors.js +14 -4
  244. data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +2 -1
  245. data/webpack/scenes/ContentViews/Details/Repositories/ContentCounts.js +56 -0
  246. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +169 -0
  247. data/webpack/scenes/ContentViews/Details/Repositories/LastSync.js +47 -0
  248. data/webpack/scenes/ContentViews/Details/Repositories/RepoAddedStatus.js +17 -0
  249. data/webpack/scenes/ContentViews/Details/Repositories/RepoIcon.js +23 -0
  250. data/webpack/scenes/ContentViews/Details/Repositories/SelectableDropdown.js +49 -0
  251. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewDetailRepos.fixtures.json +154 -0
  252. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewDetailRepos.test.js +131 -0
  253. data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetail.test.js +3 -0
  254. data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +4 -1
  255. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +2 -2
  256. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +29 -19
  257. data/webpack/scenes/Subscriptions/Manifest/ManifestActions.js +17 -0
  258. data/webpack/scenes/Subscriptions/Manifest/ManifestConstants.js +4 -0
  259. data/webpack/scenes/Subscriptions/Manifest/SimpleContentAccess.js +19 -2
  260. data/webpack/scenes/Subscriptions/Manifest/__tests__/SimpleContentAccess.test.js +9 -1
  261. data/webpack/scenes/Subscriptions/Manifest/index.js +2 -1
  262. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +1 -1
  263. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +3 -0
  264. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +8 -2
  265. data/webpack/scenes/Subscriptions/SubscriptionsSelectors.js +3 -0
  266. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +3 -0
  267. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsSelectors.test.js +6 -0
  268. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsSelectors.test.js.snap +6 -0
  269. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +1 -13
  270. data/webpack/test-utils/react-testing-lib-wrapper.js +3 -0
  271. metadata +74 -13
  272. data/webpack/__mocks__/foremanReact/components/common/Fill/GlobalFill.js +0 -3
@@ -86,6 +86,14 @@ module Katello
86
86
  PulpcoreClient::UploadsApi.new(core_api_client)
87
87
  end
88
88
 
89
+ def upload_commit_class
90
+ PulpcoreClient::UploadCommit
91
+ end
92
+
93
+ def signing_services_api
94
+ PulpcoreClient::SigningServicesApi.new(core_api_client)
95
+ end
96
+
89
97
  def tasks_api
90
98
  PulpcoreClient::TasksApi.new(core_api_client)
91
99
  end
@@ -32,6 +32,10 @@ module Katello
32
32
  PulpContainerClient::RecursiveManage
33
33
  end
34
34
 
35
+ def self.tag_image_class
36
+ PulpContainerClient::TagImage
37
+ end
38
+
35
39
  def api_client
36
40
  PulpContainerClient::ApiClient.new(smart_proxy.pulp3_configuration(PulpContainerClient::Configuration))
37
41
  end
@@ -3,12 +3,36 @@ module Katello
3
3
  module ContentViewVersion
4
4
  class Export
5
5
  include ImportExportCommon
6
- METADATA_FILE = "metadata.json".freeze
7
6
 
8
- def initialize(smart_proxy:, content_view_version: nil, destination_server: nil)
7
+ def initialize(smart_proxy:,
8
+ content_view_version: nil,
9
+ destination_server: nil,
10
+ from_content_view_version: nil)
9
11
  @smart_proxy = smart_proxy
10
12
  @content_view_version = content_view_version
11
13
  @destination_server = destination_server
14
+ @from_content_view_version = from_content_view_version
15
+ end
16
+
17
+ def repository_hrefs
18
+ version_hrefs.map { |href| version_href_to_repository_href(href) }.uniq
19
+ end
20
+
21
+ def version_hrefs
22
+ repositories.pluck(:version_href).compact
23
+ end
24
+
25
+ def repositories(fetch_all: false)
26
+ repos = if @content_view_version.default?
27
+ @content_view_version.repositories.yum_type
28
+ else
29
+ @content_view_version.archived_repos.yum_type
30
+ end
31
+ if fetch_all
32
+ repos
33
+ else
34
+ repos.immediate
35
+ end
12
36
  end
13
37
 
14
38
  def generate_exporter_path
@@ -26,8 +50,33 @@ module Katello
26
50
  repositories: repository_hrefs)
27
51
  end
28
52
 
29
- def create_export(exporter_href)
30
- [api.export_api.create(exporter_href, { versions: version_hrefs })]
53
+ def create_export(exporter_href, chunk_size: nil)
54
+ options = { versions: version_hrefs }
55
+ options[:chunk_size] = "#{chunk_size}MB" if chunk_size
56
+ if @from_content_view_version
57
+ from_exporter = Export.new(smart_proxy: @smart_proxy, content_view_version: @from_content_view_version)
58
+ start_versions = from_exporter.version_hrefs
59
+
60
+ # current_cvv - cvv_from , i.e. repos in current cvv that are not in from
61
+ # implying something got added to the current cvv
62
+ # make sure you set the start_versions as 0
63
+ added_repo_hrefs = repository_hrefs - from_exporter.repository_hrefs
64
+ added_repo_hrefs.each do |added_repo_href|
65
+ start_versions << zero_version_href(added_repo_href)
66
+ end
67
+
68
+ # cvv_from - current_cvv , i.e. repos in from cvv that are not in current
69
+ # implying something got removed the current cvv
70
+ # make sure the start_versions doesn't contain those
71
+ deleted_repo_hrefs = from_exporter.repository_hrefs - repository_hrefs
72
+ start_versions.select! do |href|
73
+ !deleted_repo_hrefs.include?(version_href_to_repository_href(href))
74
+ end
75
+
76
+ options[:start_versions] = start_versions
77
+ options[:full] = 'false'
78
+ end
79
+ [api.export_api.create(exporter_href, options)]
31
80
  end
32
81
 
33
82
  def fetch_export(exporter_href)
@@ -41,15 +90,67 @@ module Katello
41
90
  api.exporter_api.delete(exporter_href)
42
91
  end
43
92
 
93
+ def validate!(fail_on_missing_content: true, validate_incremental: true)
94
+ validate_repositories_immediate! if fail_on_missing_content
95
+ validate_incremental_export! if validate_incremental && !@from_content_view_version.blank?
96
+ end
97
+
98
+ def validate_repositories_immediate!
99
+ non_immediate_repos = repositories(fetch_all: true).non_immediate
100
+ if non_immediate_repos.any?
101
+ fail _("NOTE: Unable to fully export Content View Version '%{content_view} %{current}'"\
102
+ " it contains repositories without the 'immediate' download policy."\
103
+ " Update the download policy and sync affected repositories. Once synced republish the content view"\
104
+ " and export the generated version. \n %{repos}" %
105
+ { content_view: @content_view_version.content_view.name,
106
+ current: @content_view_version.version,
107
+ repos: self.class.generate_product_repo_strings(repositories: non_immediate_repos)})
108
+ end
109
+ end
110
+
111
+ def validate_incremental_export!
112
+ from_exporter = Export.new(smart_proxy: @smart_proxy, content_view_version: @from_content_view_version)
113
+
114
+ from_exporter_repos = generate_repo_mapping(from_exporter.repositories(fetch_all: true))
115
+ to_exporter_repos = generate_repo_mapping(repositories(fetch_all: true))
116
+
117
+ invalid_repos_exist = (from_exporter_repos.keys & to_exporter_repos.keys).any? do |repo_id|
118
+ from_exporter_repos[repo_id] != to_exporter_repos[repo_id]
119
+ end
120
+
121
+ if invalid_repos_exist
122
+ fail _("The exported Content View Version '%{content_view} %{current}' cannot be incrementally updated from version '%{from}'."\
123
+ " Please do a full export." % { content_view: @content_view_version.content_view.name,
124
+ current: @content_view_version.version,
125
+ from: @from_content_view_version.version})
126
+ end
127
+ end
128
+
129
+ def generate_repo_mapping(repositories)
130
+ # return a repo mapping with key being the library_instance_id and value being the repostiory_href
131
+ # used by validate_incremental_export
132
+ repo_map = {}
133
+ repositories.each do |repo|
134
+ repo_map[repo.library_instance_id] = version_href_to_repository_href(repo.version_href)
135
+ end
136
+ repo_map
137
+ end
138
+
44
139
  def generate_metadata
45
140
  ret = { organization: @content_view_version.organization.name,
46
141
  repository_mapping: {},
47
142
  content_view: @content_view_version.content_view.name,
48
- content_view_version: {
49
- major: @content_view_version.major,
50
- minor: @content_view_version.minor
51
- }
143
+ content_view_version: @content_view_version.slice(:major, :minor),
144
+ incremental: @from_content_view_version.present?
52
145
  }
146
+
147
+ unless @from_content_view_version.blank?
148
+ ret[:from_content_view_version] = {
149
+ major: @from_content_view_version.major,
150
+ minor: @from_content_view_version.minor
151
+ }
152
+ end
153
+
53
154
  repositories.each do |repo|
54
155
  next if repo.version_href.blank?
55
156
  pulp3_repo = fetch_repository_info(repo.version_href).name
@@ -61,6 +162,22 @@ module Katello
61
162
  end
62
163
  ret
63
164
  end
165
+
166
+ def self.find_library_export_view(create_by_default: false,
167
+ destination_server:,
168
+ organization:)
169
+ name = "Export-Library"
170
+ name += "-#{destination_server}" unless destination_server.blank?
171
+ select_method = create_by_default ? :first_or_create : :first
172
+ ::Katello::ContentView.where(name: name, organization: organization).send(select_method)
173
+ end
174
+
175
+ def self.generate_product_repo_strings(repositories:)
176
+ repositories.map do |repo|
177
+ _("Product: '%{product}', Repository: '%{repository}'" % { product: repo.product.name,
178
+ repository: repo.name})
179
+ end
180
+ end
64
181
  end
65
182
  end
66
183
  end
@@ -3,17 +3,17 @@ module Katello
3
3
  module ContentViewVersion
4
4
  class Import
5
5
  include ImportExportCommon
6
- BASEDIR = '/var/lib/pulp'.freeze
7
6
 
8
- def initialize(smart_proxy:, content_view_version: nil, path: nil)
7
+ def initialize(smart_proxy:, content_view_version: nil, path: nil, metadata: nil)
9
8
  @smart_proxy = smart_proxy
10
9
  @content_view_version = content_view_version
11
10
  @path = path
11
+ @metadata = metadata
12
12
  end
13
13
 
14
14
  def repository_mapping
15
15
  mapping = {}
16
- metadata[:repository_mapping].each do |key, value|
16
+ @metadata[:repository_mapping].each do |key, value|
17
17
  repo = @content_view_version.importable_repositories.joins(:root, :product).
18
18
  where("#{::Katello::Product.table_name}" => {:name => value[:product]},
19
19
  "#{::Katello::RootRepository.table_name}" => {:name => value[:repository]}).first
@@ -30,7 +30,7 @@ module Katello
30
30
  end
31
31
 
32
32
  def create_import(importer_href)
33
- [api.import_api.create(importer_href, toc: "#{@path}/#{metadata[:toc]}")]
33
+ [api.import_api.create(importer_href, toc: "#{@path}/#{@metadata[:toc]}")]
34
34
  end
35
35
 
36
36
  def fetch_import(importer_href)
@@ -43,43 +43,48 @@ module Katello
43
43
  api.importer_api.delete(importer_href)
44
44
  end
45
45
 
46
- def metadata
47
- @metadata ||= self.class.metadata(@path)
46
+ def self.check!(content_view:, metadata:, path:)
47
+ ImportValidator.new(content_view: content_view, metadata: metadata, path: path).check!
48
48
  end
49
49
 
50
- class << self
51
- def metadata(path)
52
- JSON.parse(File.read("#{path}/#{Export::METADATA_FILE}")).with_indifferent_access
53
- end
50
+ def self.reset_content_view_repositories_from_metadata!(content_view:, metadata:)
51
+ # Given metadata from the dump and a content view
52
+ # this method
53
+ # 1) Fetches ids of the library repos whose product name, repo name amd redhat?
54
+ # => match values provided in the metadata's repository mapping
55
+ # 2) Removes all the repositories associated to this content view
56
+ # 3) Adds the repositories matched from the dump
57
+ # The main intent of this method is to assume that the user intends for the
58
+ # content view to exaclty look like what is specified in metadata
54
59
 
55
- def check_permissions!(path)
56
- fail _("Invalid path specified.") if path.blank? || !File.directory?(path)
57
- fail _("The import path must be in a subdirectory under '%s'." % BASEDIR) unless path.starts_with?(BASEDIR)
58
- metadata_file = "#{path}/#{::Katello::Pulp3::ContentViewVersion::Export::METADATA_FILE}"
59
- fail _("Could not find metadata.json at '%s'." % metadata_file) unless File.exist?(metadata_file)
60
- fail _("Unable to read the metadata.json at '%s'." % metadata_file) unless File.readable?(metadata_file)
61
- fail _("Pulp user or group unable to read content in '%s'." % path) unless pulp_user_accessible?(path)
62
- Dir.glob("#{path}/*").each do |file|
63
- next if file == metadata_file
64
- fail _("Pulp user or group unable to read '%s'." % file) unless pulp_user_accessible?(file)
65
- end
60
+ repos_in_library = Katello::Repository.
61
+ in_default_view.
62
+ yum_type.
63
+ joins(:product => :provider, :content_view_version => :content_view).
64
+ joins(:root).
65
+ where("#{::Katello::ContentView.table_name}.organization_id" => content_view.organization_id).
66
+ pluck("#{::Katello::Repository.table_name}.id",
67
+ "#{::Katello::RootRepository.table_name}.name",
68
+ "#{::Katello::Product.table_name}.name",
69
+ "#{::Katello::Provider.table_name}.provider_type"
70
+ )
71
+ repos_in_library_map = {}
72
+ # repos_in_library_map is going to look like {['repo1', 'product1', false] => 100, ['repo1', 'product1', true] => 200 }
73
+ repos_in_library.each do |id, repo, product, provider_type|
74
+ repos_in_library_map[[repo, product, provider_type == Katello::Provider::REDHAT]] = id
66
75
  end
67
76
 
68
- def pulp_user_accessible?(path)
69
- pulp_info = fetch_pulp_user_info
70
- return false if pulp_info.blank?
71
-
72
- stat = File.stat(path)
73
- stat.gid.to_s == pulp_info.gid ||
74
- stat.uid.to_s == pulp_info.uid ||
75
- stat.mode.to_s(8)[-1].to_i >= 4
77
+ repo_ids = metadata[:repository_mapping].values.map do |repo|
78
+ repos_in_library_map[[repo[:repository], repo[:product], repo[:redhat]]]
76
79
  end
80
+ content_view.update!(repository_ids: repo_ids)
81
+ end
77
82
 
78
- def fetch_pulp_user_info
79
- pulp_user = nil
80
- Etc.passwd { |u| pulp_user = u if u.name == 'pulp' }
81
- pulp_user
82
- end
83
+ def self.find_or_create_library_import_view(organization)
84
+ name = ::Katello::ContentView::IMPORT_LIBRARY
85
+ ::Katello::ContentView.where(name: name,
86
+ organization: organization,
87
+ import_only: true).first_or_create
83
88
  end
84
89
  end
85
90
  end
@@ -19,25 +19,15 @@ module Katello
19
19
  repo_api.read(version_href_to_repository_href(version_href))
20
20
  end
21
21
 
22
- def repository_hrefs
23
- version_hrefs.map { |href| version_href_to_repository_href(href) }.uniq
24
- end
25
-
26
- def version_hrefs
27
- repositories.pluck(:version_href).compact
28
- end
29
-
30
- def repositories
31
- if @content_view_version.default?
32
- @content_view_version.repositories.yum_type
33
- else
34
- @content_view_version.archived_repos.yum_type
35
- end
36
- end
37
-
38
22
  def version_href_to_repository_href(version_href)
39
23
  version_href.split("/")[0..-3].join("/") + "/"
40
24
  end
25
+
26
+ def zero_version_href(repository_href)
27
+ # /pulp/api/v3/repositories/rpm/rpm/e59c4334-81d2-4d6b-a1a1-b61fa55ed664/versions/0/
28
+ repository_href += "/" unless repository_href.ends_with?('/')
29
+ "#{repository_href}versions/0/"
30
+ end
41
31
  end
42
32
  end
43
33
  end
@@ -0,0 +1,114 @@
1
+ module Katello
2
+ module Pulp3
3
+ module ContentViewVersion
4
+ class ImportValidator
5
+ BASEDIR = '/var/lib/pulp'.freeze
6
+ attr_accessor :metadata, :path, :content_view
7
+ def initialize(content_view:, path:, metadata:)
8
+ self.content_view = content_view
9
+ self.path = path
10
+ self.metadata = metadata
11
+ end
12
+
13
+ def check!
14
+ check_permissions!
15
+ unless content_view.default?
16
+ ensure_importing_cvv_does_not_exist!
17
+ ensure_from_cvv_exists!
18
+ end
19
+ ensure_repositories_metadata_are_in_the_library!
20
+ end
21
+
22
+ def ensure_importing_cvv_does_not_exist!
23
+ major = metadata[:content_view_version][:major]
24
+ minor = metadata[:content_view_version][:minor]
25
+
26
+ if ::Katello::ContentViewVersion.where(major: major, minor: minor, content_view: content_view).exists?
27
+ fail _("Content View Version specified in the metadata - '%{name}' already exists. "\
28
+ "If you wish to replace the existing version, delete %{name} and try again. " % { name: "#{content_view.name} #{major}.#{minor}" })
29
+ end
30
+ end
31
+
32
+ def ensure_from_cvv_exists!
33
+ major = metadata[:content_view_version][:major]
34
+ minor = metadata[:content_view_version][:minor]
35
+
36
+ if metadata[:from_content_view_version].present?
37
+ from_major = metadata[:from_content_view_version][:major]
38
+ from_minor = metadata[:from_content_view_version][:minor]
39
+
40
+ unless ::Katello::ContentViewVersion.where(major: from_major, minor: from_minor, content_view: content_view).exists?
41
+ fail _("Prior Content View Version specified in the metadata - '%{name}' does not exist. "\
42
+ "Please import the metadata for '%{name}' before importing '%{current}' " % { name: "#{content_view.name} #{from_major}.#{from_minor}",
43
+ current: "#{content_view.name} #{major}.#{minor}"})
44
+ end
45
+ end
46
+ end
47
+
48
+ def ensure_repositories_metadata_are_in_the_library!
49
+ repos_in_library = Katello::Repository.
50
+ in_default_view.
51
+ yum_type.
52
+ joins(:product => :provider, :content_view_version => :content_view).
53
+ joins(:root).
54
+ where("#{::Katello::ContentView.table_name}.organization_id" => content_view.organization_id).
55
+ pluck("#{::Katello::Product.table_name}.name",
56
+ "#{::Katello::RootRepository.table_name}.name",
57
+ "#{::Katello::Provider.table_name}.provider_type"
58
+ )
59
+
60
+ # repos_in_library look like [["prod1", "repo1", "Anonymous"], ["prod2", "repo2", "Red Hat"]]
61
+ product_repos_in_library = repos_in_library.map { |product, repo, provider| [product, repo, provider == ::Katello::Provider::REDHAT] }
62
+ product_repos_in_metadata = metadata[:repository_mapping].values.map { |repo| [repo[:product], repo[:repository], repo[:redhat]] }
63
+ # product_repos_in_library & product_repos_in_metadata look like [["prod1", "repo1", false], ["prod2", "repo2", false]]
64
+ product_repos_not_in_library = product_repos_in_metadata - product_repos_in_library
65
+ unless product_repos_not_in_library.blank?
66
+ repos_in_import = generate_product_repo_i18n_string(product_repos_not_in_library)
67
+ fail _("The following repositories provided in the import metadata are either not available in the Library or are of incorrect Respository Type. "\
68
+ "Please add or enable the repositories before importing\n "\
69
+ "%{repos}" % { content_view: content_view.name, repos: repos_in_import.join("")}
70
+ )
71
+ end
72
+ end
73
+
74
+ def check_permissions!
75
+ fail _("Invalid path specified.") if path.blank? || !File.directory?(path)
76
+ fail _("The import path must be in a subdirectory under '%s'." % BASEDIR) unless path.starts_with?(BASEDIR)
77
+ fail _("Pulp user or group unable to read content in '%s'." % path) unless pulp_user_accessible?(path)
78
+
79
+ Dir.glob("#{path}/*").each do |file|
80
+ fail _("Pulp user or group unable to read '%s'." % file) unless pulp_user_accessible?(file)
81
+ end
82
+ toc_path = "#{path}/#{metadata[:toc]}"
83
+ fail _("The TOC file specified in the metadata does not exist. %s " % toc_path) unless File.exist?(toc_path)
84
+ end
85
+
86
+ def pulp_user_accessible?(path)
87
+ pulp_info = fetch_pulp_user_info
88
+ return false if pulp_info.blank?
89
+
90
+ stat = File.stat(path)
91
+ stat.gid.to_s == pulp_info.gid ||
92
+ stat.uid.to_s == pulp_info.uid ||
93
+ stat.mode.to_s(8)[-1].to_i >= 4
94
+ end
95
+
96
+ def fetch_pulp_user_info
97
+ pulp_user = nil
98
+ Etc.passwd { |u| pulp_user = u if u.name == 'pulp' }
99
+ pulp_user
100
+ end
101
+
102
+ def generate_product_repo_i18n_string(product_repos)
103
+ # product_repos look like [["prod1", "repo1", false], ["prod2", "repo2", false]]
104
+ product_repos.map do |product, repo, redhat|
105
+ repo_type = redhat ? _("Red Hat") : _("Custom")
106
+ _("\n* Product = '%{product}', Repository = '%{repository}', Repository Type = '%{repo_type}'" % { product: product,
107
+ repository: repo,
108
+ repo_type: repo_type})
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end