katello 4.12.1 → 4.13.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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/katello/locale/bn/katello.js +3365 -3350
- data/app/assets/javascripts/katello/locale/bn_IN/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/ca/katello.js +3588 -3576
- data/app/assets/javascripts/katello/locale/cs/katello.js +3499 -3487
- data/app/assets/javascripts/katello/locale/cs_CZ/katello.js +4186 -4186
- data/app/assets/javascripts/katello/locale/de/katello.js +5553 -5562
- data/app/assets/javascripts/katello/locale/de_AT/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/de_DE/katello.js +3066 -3051
- data/app/assets/javascripts/katello/locale/el/katello.js +3376 -3370
- data/app/assets/javascripts/katello/locale/en/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/en_GB/katello.js +3076 -3073
- data/app/assets/javascripts/katello/locale/en_US/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/es/katello.js +5366 -5372
- data/app/assets/javascripts/katello/locale/et_EE/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/fr/katello.js +5975 -5984
- data/app/assets/javascripts/katello/locale/gl/katello.js +3125 -3113
- data/app/assets/javascripts/katello/locale/gu/katello.js +3119 -3104
- data/app/assets/javascripts/katello/locale/he_IL/katello.js +3020 -3005
- data/app/assets/javascripts/katello/locale/hi/katello.js +3137 -3122
- data/app/assets/javascripts/katello/locale/id/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/it/katello.js +4469 -4466
- data/app/assets/javascripts/katello/locale/ja/katello.js +5969 -5978
- data/app/assets/javascripts/katello/locale/ka/katello.js +5649 -5652
- data/app/assets/javascripts/katello/locale/kn/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/ko/katello.js +4717 -4720
- data/app/assets/javascripts/katello/locale/locale/katello.js +1050 -1084
- data/app/assets/javascripts/katello/locale/ml_IN/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/mr/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/nl_NL/katello.js +3116 -3101
- data/app/assets/javascripts/katello/locale/or/katello.js +3137 -3122
- data/app/assets/javascripts/katello/locale/pa/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/pl/katello.js +3210 -3195
- data/app/assets/javascripts/katello/locale/pl_PL/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/pt/katello.js +3009 -2994
- data/app/assets/javascripts/katello/locale/pt_BR/katello.js +5362 -5368
- data/app/assets/javascripts/katello/locale/ro/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/ro_RO/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/ru/katello.js +4638 -4641
- data/app/assets/javascripts/katello/locale/sl/katello.js +3051 -3036
- data/app/assets/javascripts/katello/locale/sv_SE/katello.js +3156 -3144
- data/app/assets/javascripts/katello/locale/ta/katello.js +3365 -3350
- data/app/assets/javascripts/katello/locale/ta_IN/katello.js +3121 -3106
- data/app/assets/javascripts/katello/locale/te/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/tr/katello.js +3025 -3010
- data/app/assets/javascripts/katello/locale/vi/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/vi_VN/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/zh/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/zh_CN/katello.js +5968 -5977
- data/app/assets/javascripts/katello/locale/zh_TW/katello.js +4694 -4697
- data/app/controllers/katello/api/registry/registry_proxies_controller.rb +370 -132
- data/app/controllers/katello/api/rhsm/candlepin_dynflow_proxy_controller.rb +12 -20
- data/app/controllers/katello/api/v2/activation_keys_controller.rb +10 -4
- data/app/controllers/katello/api/v2/capsule_content_controller.rb +24 -0
- data/app/controllers/katello/api/v2/content_view_versions_controller.rb +9 -2
- data/app/controllers/katello/api/v2/debs_controller.rb +1 -1
- data/app/controllers/katello/api/v2/errata_controller.rb +1 -1
- data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +12 -4
- data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +3 -3
- data/app/controllers/katello/api/v2/organizations_controller.rb +0 -11
- data/app/controllers/katello/api/v2/packages_controller.rb +1 -1
- data/app/controllers/katello/api/v2/repositories_controller.rb +19 -13
- data/app/controllers/katello/api/v2/repository_sets_controller.rb +2 -1
- data/app/controllers/katello/api/v2/simple_content_access_controller.rb +9 -22
- data/app/controllers/katello/concerns/api/v2/authorization.rb +1 -1
- data/app/helpers/katello/subscription_mailer_helper.rb +1 -1
- data/app/jobs/create_manifest_expire_soon_warning_notifications.rb +11 -0
- data/app/lib/actions/candlepin/owner/regenerate_upstream_identity_cert.rb +21 -0
- data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
- data/app/lib/actions/katello/capsule_content/sync_capsule.rb +7 -2
- data/app/lib/actions/katello/capsule_content/verify_checksum.rb +75 -0
- data/app/lib/actions/katello/content_view/promote.rb +1 -1
- data/app/lib/actions/katello/content_view/publish.rb +1 -1
- data/app/lib/actions/katello/content_view_version/verify_checksum.rb +29 -0
- data/app/lib/actions/katello/host/hypervisors_update.rb +1 -0
- data/app/lib/actions/katello/host/update_content_view.rb +2 -2
- data/app/lib/actions/katello/organization/manifest_delete.rb +6 -1
- data/app/lib/actions/katello/organization/manifest_import.rb +5 -0
- data/app/lib/actions/katello/organization/manifest_refresh.rb +3 -0
- data/app/lib/actions/katello/repository/create.rb +17 -11
- data/app/lib/actions/katello/repository/create_root.rb +4 -2
- data/app/lib/actions/katello/repository/metadata_generate.rb +7 -1
- data/app/lib/actions/katello/repository/remove_content.rb +1 -0
- data/app/lib/actions/katello/repository/sync.rb +2 -1
- data/app/lib/actions/katello/repository/upload_files.rb +1 -0
- data/app/lib/actions/katello/upstream_subscriptions/bind_entitlement.rb +1 -1
- data/app/lib/actions/pulp3/capsule_content/verify_checksum.rb +27 -0
- data/app/lib/actions/pulp3/orchestration/content_view_version/export_repository.rb +7 -9
- data/app/lib/actions/pulp3/orchestration/content_view_version/syncable_export.rb +5 -4
- data/app/lib/actions/pulp3/orchestration/orphan_cleanup/remove_orphans.rb +1 -0
- data/app/lib/actions/pulp3/orphan_cleanup/purge_completed_tasks.rb +15 -0
- data/app/lib/katello/concerns/base_template_scope_extensions.rb +7 -2
- data/app/lib/katello/http_resource.rb +6 -1
- data/app/lib/katello/resources/candlepin/consumer.rb +1 -1
- data/app/lib/katello/resources/candlepin/upstream_consumer.rb +18 -6
- data/app/lib/katello/resources/candlepin/upstream_job.rb +1 -1
- data/app/lib/katello/resources/registry.rb +25 -0
- data/app/mailers/katello/subscription_mailer.rb +3 -6
- data/app/models/katello/concerns/organization_extensions.rb +42 -3
- data/app/models/katello/content_view.rb +30 -0
- data/app/models/katello/content_view_environment_content_facet.rb +4 -2
- data/app/models/katello/glue/provider.rb +19 -12
- data/app/models/katello/glue/pulp/repos.rb +11 -3
- data/app/models/katello/host/content_facet.rb +1 -1
- data/app/models/katello/host/subscription_facet.rb +1 -1
- data/app/models/katello/ping.rb +1 -1
- data/app/models/katello/repository.rb +32 -1
- data/app/models/katello/root_repository.rb +4 -6
- data/app/models/katello/trace_status.rb +1 -1
- data/app/services/katello/content_unit_indexer.rb +9 -0
- data/app/services/katello/pulp3/alternate_content_source.rb +4 -6
- data/app/services/katello/pulp3/api/core.rb +21 -0
- data/app/services/katello/pulp3/api/docker.rb +4 -0
- data/app/services/katello/pulp3/api/yum.rb +11 -0
- data/app/services/katello/pulp3/docker_manifest.rb +5 -1
- data/app/services/katello/pulp3/repository/generic.rb +1 -1
- data/app/services/katello/pulp3/repository/yum.rb +1 -6
- data/app/services/katello/pulp3/repository.rb +26 -6
- data/app/services/katello/pulp3/repository_mirror.rb +13 -12
- data/app/services/katello/pulp3/service_common.rb +2 -10
- data/app/services/katello/pulp3/smart_proxy_repository.rb +0 -2
- data/app/services/katello/ui_notifications/subscriptions/manifest_expire_soon_warning.rb +75 -0
- data/app/views/foreman/job_templates/update_package_-_katello_ansible_default.erb +5 -1
- data/app/views/foreman/job_templates/update_packages_by_search_query_-_katello_ansible_default.erb +2 -2
- data/app/views/foreman/job_templates/upload_profile.erb +16 -0
- data/app/views/foreman/smart_proxies/_content_tab.html.erb +3 -1
- data/app/views/katello/api/v2/content_view_filter_rules/show.json.rabl +9 -0
- data/app/views/katello/api/v2/docker_manifests/show.json.rabl +1 -0
- data/app/views/katello/api/v2/organizations/show.json.rabl +9 -1
- data/app/views/overrides/activation_keys/_host_environment_select.html.erb +1 -1
- data/app/views/overrides/activation_keys/_host_media_type_select.html.erb +15 -5
- data/config/routes/api/registry.rb +4 -8
- data/config/routes/api/v2.rb +2 -0
- data/db/migrate/20240423112842_add_fields_to_katello_docker_manifest.rb +8 -0
- data/db/migrate/20240502192021_change_katello_repository_rpms_id_seq_to_big_int.rb +9 -0
- data/db/migrate/20240520142245_add_container_push_props_to_repo.rb +7 -0
- data/db/migrate/20240531193030_remove_sha1_repository_checksum_type.rb +10 -0
- data/db/seeds.d/109-katello-notification-blueprints.rb +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-repository-sets.controller.js +3 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/new/views/new-content-credential.html +2 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-repository-sets.controller.js +3 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +0 -15
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/checksum.service.js +6 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +8 -6
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +12 -13
- data/lib/katello/permission_creator.rb +3 -3
- data/lib/katello/permissions/registry_permissions.rb +4 -7
- data/lib/katello/plugin.rb +21 -8
- data/lib/katello/repository_types/ostree.rb +7 -0
- data/lib/katello/scheduled_jobs.rb +7 -1
- data/lib/katello/tasks/clean_backend_objects.rake +1 -1
- data/lib/katello/tasks/repository.rake +22 -0
- data/lib/katello/version.rb +1 -1
- data/locale/action_names.rb +4 -3
- data/locale/bn/katello.po +166 -151
- data/locale/bn_IN/katello.po +166 -151
- data/locale/ca/katello.po +166 -151
- data/locale/cs/katello.po +166 -151
- data/locale/cs_CZ/LC_MESSAGES/katello.mo +0 -0
- data/locale/cs_CZ/katello.po +172 -157
- data/locale/de/LC_MESSAGES/katello.mo +0 -0
- data/locale/de/katello.po +178 -163
- data/locale/de_AT/katello.po +166 -151
- data/locale/de_DE/katello.po +166 -151
- data/locale/el/katello.po +166 -151
- data/locale/en/katello.po +166 -151
- data/locale/en_GB/katello.po +166 -151
- data/locale/en_US/katello.po +166 -151
- data/locale/es/LC_MESSAGES/katello.mo +0 -0
- data/locale/es/katello.po +178 -163
- data/locale/et_EE/katello.po +166 -151
- data/locale/fr/LC_MESSAGES/katello.mo +0 -0
- data/locale/fr/katello.po +179 -164
- data/locale/gl/katello.po +166 -151
- data/locale/gu/katello.po +166 -151
- data/locale/he_IL/katello.po +166 -151
- data/locale/hi/katello.po +166 -151
- data/locale/id/katello.po +166 -151
- data/locale/it/LC_MESSAGES/katello.mo +0 -0
- data/locale/it/katello.po +169 -154
- data/locale/ja/LC_MESSAGES/katello.mo +0 -0
- data/locale/ja/katello.po +179 -164
- data/locale/ka/LC_MESSAGES/katello.mo +0 -0
- data/locale/ka/katello.po +177 -162
- data/locale/katello.pot +1119 -1062
- data/locale/kn/katello.po +166 -151
- data/locale/ko/LC_MESSAGES/katello.mo +0 -0
- data/locale/ko/katello.po +174 -159
- data/locale/ml_IN/katello.po +166 -151
- data/locale/mr/katello.po +166 -151
- data/locale/nl_NL/katello.po +166 -151
- data/locale/or/katello.po +166 -151
- data/locale/pa/katello.po +166 -151
- data/locale/pl/katello.po +166 -151
- data/locale/pl_PL/katello.po +166 -151
- data/locale/pt/katello.po +166 -151
- data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
- data/locale/pt_BR/katello.po +178 -163
- data/locale/ro/katello.po +166 -151
- data/locale/ro_RO/katello.po +166 -151
- data/locale/ru/LC_MESSAGES/katello.mo +0 -0
- data/locale/ru/katello.po +171 -156
- data/locale/sl/katello.po +166 -151
- data/locale/sv_SE/katello.po +166 -151
- data/locale/ta/katello.po +166 -151
- data/locale/ta_IN/katello.po +166 -151
- data/locale/te/katello.po +166 -151
- data/locale/tr/katello.po +166 -151
- data/locale/vi/katello.po +166 -151
- data/locale/vi_VN/katello.po +166 -151
- data/locale/zh/katello.po +166 -151
- data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
- data/locale/zh_CN/katello.po +179 -164
- data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
- data/locale/zh_TW/katello.po +171 -156
- data/package.json +0 -1
- data/webpack/ForemanColumnExtensions/index.js +129 -0
- data/webpack/components/Content/ContentTable.js +0 -1
- data/webpack/components/Content/__tests__/__snapshots__/ContentTable.test.js.snap +0 -1
- data/webpack/components/Table/TableWrapper.js +14 -0
- data/webpack/components/extensions/HostDetails/ActionsBar/index.js +1 -1
- data/webpack/components/extensions/Hosts/ActionsBar/index.js +20 -1
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/BulkChangeHostCVModal.js +220 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/actions.js +23 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/index.js +25 -0
- data/webpack/components/extensions/Hosts/BulkActions/__tests__/bulkChangeHostCVModal.test.js +133 -0
- data/webpack/global_index.js +9 -0
- data/webpack/scenes/Hosts/ChangeContentSource/actions.js +3 -1
- data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +62 -24
- data/webpack/scenes/Hosts/ChangeContentSource/index.js +24 -16
- data/webpack/scenes/ModuleStreams/ModuleStreamsPage.js +33 -39
- data/webpack/scenes/ModuleStreams/__tests__/ModuleStreamPage.test.js +4 -2
- data/webpack/scenes/ModuleStreams/__tests__/__snapshots__/ModuleStreamsTable.test.js.snap +0 -1
- data/webpack/scenes/RedHatRepositories/__tests__/__snapshots__/RedHatRepositoriesPage.test.js.snap +1 -0
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +66 -5
- data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +16 -13
- data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +14 -8
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +1 -0
- data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +1 -1
- metadata +60 -42
- data/app/lib/actions/katello/host/upload_package_profile.rb +0 -45
- data/app/lib/actions/katello/host/upload_profiles.rb +0 -47
- data/webpack/utils/__tests__/useParamsWithHash.test.js +0 -22
- data/webpack/utils/paramsFromHash.js +0 -16
- data/webpack/utils/useUrlParams.js +0 -14
@@ -3,15 +3,16 @@ module Katello
|
|
3
3
|
class Api::Registry::RegistryProxiesController < Api::V2::ApiController
|
4
4
|
before_action :disable_strong_params
|
5
5
|
before_action :confirm_settings
|
6
|
-
before_action :confirm_push_settings, only: [:start_upload_blob, :upload_blob, :finish_upload_blob,
|
7
|
-
:chunk_upload_blob, :push_manifest]
|
8
6
|
skip_before_action :authorize
|
9
7
|
before_action :optional_authorize, only: [:token, :catalog]
|
10
8
|
before_action :registry_authorize, except: [:token, :v1_search, :catalog]
|
11
9
|
before_action :authorize_repository_read, only: [:pull_manifest, :tags_list]
|
12
|
-
|
10
|
+
# TODO: authorize_repository_write commented out due to container push changes. Additional task needed to fix.
|
11
|
+
# before_action :authorize_repository_write, only: [:start_upload_blob, :upload_blob, :finish_upload_blob, :push_manifest]
|
12
|
+
before_action :container_push_prop_validation, only: [:start_upload_blob, :upload_blob, :finish_upload_blob, :push_manifest]
|
13
|
+
before_action :create_container_repo_if_needed, only: [:start_upload_blob, :upload_blob, :finish_upload_blob, :push_manifest]
|
13
14
|
skip_before_action :check_media_type, only: [:start_upload_blob, :upload_blob, :finish_upload_blob,
|
14
|
-
:
|
15
|
+
:push_manifest]
|
15
16
|
|
16
17
|
wrap_parameters false
|
17
18
|
|
@@ -83,6 +84,301 @@ module Katello
|
|
83
84
|
return false
|
84
85
|
end
|
85
86
|
|
87
|
+
def container_push_prop_validation(props = nil)
|
88
|
+
# Handle validation and repo creation for container pushes before talking to pulp
|
89
|
+
return false unless confirm_push_settings
|
90
|
+
props = parse_blob_push_props if props.nil?
|
91
|
+
return false unless check_blob_push_field_syntax(props)
|
92
|
+
|
93
|
+
# validate input and find the org and product either using downcase label or id
|
94
|
+
if props[:schema] == "label"
|
95
|
+
return false unless check_blob_push_org_label(props)
|
96
|
+
return false unless check_blob_push_product_label(props)
|
97
|
+
else
|
98
|
+
return false unless check_blob_push_org_id(props)
|
99
|
+
return false unless check_blob_push_product_id(props)
|
100
|
+
end
|
101
|
+
|
102
|
+
return false unless check_blob_push_container(props)
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
def parse_blob_push_props(path_string = nil)
|
107
|
+
# path string should follow one of these formats:
|
108
|
+
# - /v2/{org_label}/{product_label}/{name}/blobs/uploads...
|
109
|
+
# - /v2/id/{org_id}/{product_id}/{name}/blobs/uploads...
|
110
|
+
# - /v2/{org_label}/{product_label}/{name}/manifests/...
|
111
|
+
# - /v2/id/{org_id}/{product_id}/{name}/manifests/...
|
112
|
+
# inputs not matching format will return {valid_format: false}
|
113
|
+
path_string = @_request.fullpath if path_string.nil?
|
114
|
+
segments = path_string.split('/')
|
115
|
+
|
116
|
+
if segments.length >= 7 && segments[0] == "" && segments[1] == "v2" &&
|
117
|
+
segments[2] != "id" && (segments[5] == "blobs" || segments[5] == "manifests")
|
118
|
+
|
119
|
+
return {
|
120
|
+
valid_format: true,
|
121
|
+
schema: "label",
|
122
|
+
organization: segments[2],
|
123
|
+
product: segments[3],
|
124
|
+
name: segments[4]
|
125
|
+
}
|
126
|
+
elsif segments.length >= 8 && segments[0] == "" && segments[1] == "v2" &&
|
127
|
+
segments[2] == "id" && (segments[6] == "blobs" || segments[6] == "manifests")
|
128
|
+
|
129
|
+
return {
|
130
|
+
valid_format: true,
|
131
|
+
schema: "id",
|
132
|
+
organization: segments[3],
|
133
|
+
product: segments[4],
|
134
|
+
name: segments[5]
|
135
|
+
}
|
136
|
+
else
|
137
|
+
return {valid_format: false}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def check_blob_push_field_syntax(props)
|
142
|
+
# check basic url field syntax
|
143
|
+
unless props[:valid_format]
|
144
|
+
return render_podman_error(
|
145
|
+
"NAME_INVALID",
|
146
|
+
"Invalid format. Container pushes should follow 'organization_label/product_label/name' OR 'id/organization_id/product_id/name' schema.",
|
147
|
+
:bad_request
|
148
|
+
)
|
149
|
+
end
|
150
|
+
return true
|
151
|
+
end
|
152
|
+
|
153
|
+
# rubocop:disable Metrics/MethodLength
|
154
|
+
def check_blob_push_org_label(props)
|
155
|
+
org_label = props[:organization]
|
156
|
+
unless org_label.present? && org_label.length > 0
|
157
|
+
return render_podman_error(
|
158
|
+
"NAME_INVALID",
|
159
|
+
"Invalid format. Organization label cannot be blank.",
|
160
|
+
:bad_request
|
161
|
+
)
|
162
|
+
end
|
163
|
+
org = Organization.where("LOWER(label) = '#{org_label}'") # convert to lowercase
|
164
|
+
# reject ambiguous orgs (possible due to lowercase conversion)
|
165
|
+
if org.length > 1
|
166
|
+
# Determine if the repo already exists in one of the possible products. If yes,
|
167
|
+
# inform the user they need to destroy the existing repo and use the ID format
|
168
|
+
unless props[:product].blank? || props[:name].blank?
|
169
|
+
org.each do |o|
|
170
|
+
products = get_matching_products_from_org(o, props[:product])
|
171
|
+
products.each do |prod|
|
172
|
+
root_repos = get_root_repo_from_product(prod, props[:name])
|
173
|
+
unless root_repos.empty?
|
174
|
+
return render_podman_error(
|
175
|
+
"NAME_INVALID",
|
176
|
+
"Due to a change in your organizations, this container name has become "\
|
177
|
+
"ambiguous (org name '#{org_label}'). If you wish to continue using this "\
|
178
|
+
"container name, destroy the organization in conflict with '#{o.name} (id "\
|
179
|
+
"#{o.id}). If you wish to keep both orgs, destroy '#{o.label}/#{prod.label}/"\
|
180
|
+
"#{root_repos.first.label}' and retry your push using the id format.",
|
181
|
+
:conflict
|
182
|
+
)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# Otherwise tell them to try pushing with ID format
|
189
|
+
return render_podman_error(
|
190
|
+
"NAME_INVALID",
|
191
|
+
"Organization label '#{org_label}' is ambiguous. Try using an id-based container name.",
|
192
|
+
:conflict
|
193
|
+
)
|
194
|
+
end
|
195
|
+
if org.length == 0
|
196
|
+
return render_podman_error(
|
197
|
+
"NAME_UNKNOWN",
|
198
|
+
"Organization not found: '#{org_label}'",
|
199
|
+
:not_found
|
200
|
+
)
|
201
|
+
end
|
202
|
+
@organization = org.first
|
203
|
+
true
|
204
|
+
end
|
205
|
+
|
206
|
+
def check_blob_push_org_id(props)
|
207
|
+
org_id = props[:organization]
|
208
|
+
unless org_id.present? && org_id == org_id.to_i.to_s
|
209
|
+
return render_podman_error(
|
210
|
+
"NAME_INVALID",
|
211
|
+
"Invalid format. Organization id must be an integer without leading zeros.",
|
212
|
+
:bad_request
|
213
|
+
)
|
214
|
+
end
|
215
|
+
@organization = Organization.find_by_id(org_id.to_i)
|
216
|
+
if @organization.nil?
|
217
|
+
return render_podman_error(
|
218
|
+
"NAME_UNKNOWN",
|
219
|
+
"Organization id not found: '#{org_id}'",
|
220
|
+
:not_found
|
221
|
+
)
|
222
|
+
end
|
223
|
+
true
|
224
|
+
end
|
225
|
+
|
226
|
+
def check_blob_push_product_label(props)
|
227
|
+
prod_label = props[:product]
|
228
|
+
unless prod_label.present? && prod_label.length > 0
|
229
|
+
return render_podman_error(
|
230
|
+
"NAME_INVALID",
|
231
|
+
"Invalid format. Product label cannot be blank.",
|
232
|
+
:bad_request
|
233
|
+
)
|
234
|
+
end
|
235
|
+
product = get_matching_products_from_org(@organization, prod_label)
|
236
|
+
# reject ambiguous products (possible due to lowercase conversion)
|
237
|
+
if product.length > 1
|
238
|
+
# Determine if the repo already exists in one of the possible products. If yes,
|
239
|
+
# inform the user they need to destroy the existing repo and use the ID format
|
240
|
+
unless props[:name].blank?
|
241
|
+
product.each do |prod|
|
242
|
+
root_repos = get_root_repo_from_product(prod, props[:name])
|
243
|
+
unless root_repos.empty?
|
244
|
+
return render_podman_error(
|
245
|
+
"NAME_INVALID",
|
246
|
+
"Due to a change in your products, this container name has become ambiguous "\
|
247
|
+
"(product name '#{prod_label}'). If you wish to continue using this container "\
|
248
|
+
"name, destroy the product in conflict with '#{prod.name}' (id #{prod.id}). If "\
|
249
|
+
"you wish to keep both products, destroy '#{@organization.label}/#{prod.label}/"\
|
250
|
+
"#{root_repos.first.label}' and retry your push using the id format.",
|
251
|
+
:conflict
|
252
|
+
)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
return render_podman_error(
|
258
|
+
"NAME_INVALID",
|
259
|
+
"Product label '#{prod_label}' is ambiguous. Try using an id-based container name.",
|
260
|
+
:conflict
|
261
|
+
)
|
262
|
+
end
|
263
|
+
if product.length == 0
|
264
|
+
return render_podman_error(
|
265
|
+
"NAME_UNKNOWN",
|
266
|
+
"Product not found: '#{prod_label}'",
|
267
|
+
:not_found
|
268
|
+
)
|
269
|
+
end
|
270
|
+
@product = product.first
|
271
|
+
true
|
272
|
+
end
|
273
|
+
|
274
|
+
def check_blob_push_product_id(props)
|
275
|
+
prod_id = props[:product]
|
276
|
+
unless prod_id.present? && prod_id == prod_id.to_i.to_s
|
277
|
+
return render_podman_error(
|
278
|
+
"NAME_INVALID",
|
279
|
+
"Invalid format. Product id must be an integer without leading zeros.",
|
280
|
+
:bad_request
|
281
|
+
)
|
282
|
+
end
|
283
|
+
@product = @organization.products.find_by_id(prod_id.to_i)
|
284
|
+
if @product.nil?
|
285
|
+
return render_podman_error(
|
286
|
+
"NAME_UNKNOWN",
|
287
|
+
"Product id not found: '#{prod_id}'",
|
288
|
+
:not_found
|
289
|
+
)
|
290
|
+
end
|
291
|
+
true
|
292
|
+
end
|
293
|
+
|
294
|
+
def get_matching_products_from_org(organization, product_label)
|
295
|
+
return organization.products.where("LOWER(label) = '#{product_label}'") # convert to lowercase
|
296
|
+
end
|
297
|
+
|
298
|
+
def get_root_repo_from_product(product, root_repo_name)
|
299
|
+
return product.root_repositories.where(label: root_repo_name)
|
300
|
+
end
|
301
|
+
|
302
|
+
def check_blob_push_container(props)
|
303
|
+
unless props[:name].present? && props[:name].length > 0
|
304
|
+
return render_podman_error(
|
305
|
+
"NAME_INVALID",
|
306
|
+
"Invalid format. Container name cannot be blank.",
|
307
|
+
:bad_request
|
308
|
+
)
|
309
|
+
end
|
310
|
+
|
311
|
+
@container_name = props[:name]
|
312
|
+
@container_push_name_format = props[:schema]
|
313
|
+
if @container_push_name_format == "label"
|
314
|
+
@container_path_input = "#{props[:organization]}/#{props[:product]}/#{props[:name]}"
|
315
|
+
else
|
316
|
+
@container_path_input = "id/#{props[:organization]}/#{props[:product]}/#{props[:name]}"
|
317
|
+
end
|
318
|
+
|
319
|
+
# If the repo already exists, check if the existing push format matches
|
320
|
+
root_repo = get_root_repo_from_product(@product, @container_name).first
|
321
|
+
if !root_repo.nil? && @container_push_name_format != root_repo.container_push_name_format
|
322
|
+
return render_podman_error(
|
323
|
+
"NAME_INVALID",
|
324
|
+
"Repository name '#{@container_name}' already exists in this product using a different naming scheme. Please retry your request with the #{root_repo.container_push_name_format} format or destroy and recreate the repository using your preferred schema.",
|
325
|
+
:conflict
|
326
|
+
)
|
327
|
+
end
|
328
|
+
|
329
|
+
true
|
330
|
+
end
|
331
|
+
|
332
|
+
def create_container_repo_if_needed
|
333
|
+
if get_root_repo_from_product(@product, @container_name).empty?
|
334
|
+
root = @product.add_repo(
|
335
|
+
name: @container_name,
|
336
|
+
label: @container_name,
|
337
|
+
download_policy: 'immediate',
|
338
|
+
content_type: Repository::DOCKER_TYPE,
|
339
|
+
unprotected: true,
|
340
|
+
is_container_push: true,
|
341
|
+
container_push_name: @container_path_input,
|
342
|
+
container_push_name_format: @container_push_name_format
|
343
|
+
)
|
344
|
+
sync_task(::Actions::Katello::Repository::CreateRoot, root, @container_path_input)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def blob_push_cleanup
|
349
|
+
# after manifest upload, index content and set version href using pulp api
|
350
|
+
root_repo = get_root_repo_from_product(@product, @container_name)&.first
|
351
|
+
instance_repo = root_repo&.library_instance
|
352
|
+
|
353
|
+
unless root_repo.present? && instance_repo.present?
|
354
|
+
return render_podman_error(
|
355
|
+
"BLOB_UPLOAD_UNKNOWN",
|
356
|
+
"Could not locate local uploaded repository for content indexing.",
|
357
|
+
:not_found
|
358
|
+
)
|
359
|
+
end
|
360
|
+
|
361
|
+
api = ::Katello::Pulp3::Repository.api(SmartProxy.pulp_primary, ::Katello::Repository::DOCKER_TYPE).container_push_api
|
362
|
+
api_response = api.list(name: @container_path_input)&.results&.first
|
363
|
+
latest_version_href = api_response&.latest_version_href
|
364
|
+
pulp_href = api_response&.pulp_href
|
365
|
+
|
366
|
+
if latest_version_href.empty? || pulp_href.empty?
|
367
|
+
return render_podman_error(
|
368
|
+
"BLOB_UPLOAD_UNKNOWN",
|
369
|
+
"Could not locate repository properties for content indexing.",
|
370
|
+
:not_found
|
371
|
+
)
|
372
|
+
end
|
373
|
+
|
374
|
+
instance_repo.update!(version_href: latest_version_href)
|
375
|
+
::Katello::Pulp3::RepositoryReference.where(root_repository_id: instance_repo.root_id,
|
376
|
+
content_view_id: instance_repo.content_view.id, repository_href: pulp_href).create!
|
377
|
+
instance_repo.index_content
|
378
|
+
|
379
|
+
true
|
380
|
+
end
|
381
|
+
|
86
382
|
def find_writable_repository
|
87
383
|
Repository.docker_type.syncable.find_by_container_repository_name(params[:repository])
|
88
384
|
end
|
@@ -182,15 +478,8 @@ module Katello
|
|
182
478
|
end
|
183
479
|
|
184
480
|
def check_blob
|
185
|
-
|
186
|
-
|
187
|
-
response.header['Content-Length'] = "#{r.body.size}"
|
188
|
-
rescue RestClient::NotFound
|
189
|
-
digest_file = tmp_file("#{params[:digest][7..-1]}.tar")
|
190
|
-
raise unless File.exist? digest_file
|
191
|
-
response.header['Content-Length'] = "#{File.size digest_file}"
|
192
|
-
end
|
193
|
-
render json: {}
|
481
|
+
pulp_response = Resources::Registry::Proxy.get(@_request.fullpath, 'Accept' => request.headers['Accept'])
|
482
|
+
head pulp_response.code
|
194
483
|
end
|
195
484
|
|
196
485
|
def redirect_client
|
@@ -210,94 +499,72 @@ module Katello
|
|
210
499
|
redirect_client { Resources::Registry::Proxy.get(@_request.fullpath, headers, max_redirects: 0) }
|
211
500
|
end
|
212
501
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
manifest = create_manifest
|
219
|
-
return if manifest.nil?
|
220
|
-
|
221
|
-
begin
|
222
|
-
files = get_manifest_files(repository, manifest)
|
223
|
-
return if files.nil?
|
224
|
-
|
225
|
-
tar_file = create_tar_file(files, repository, tag)
|
226
|
-
return if tar_file.nil?
|
227
|
-
|
228
|
-
digest = upload_manifest(tar_file)
|
229
|
-
return if digest.nil?
|
502
|
+
def start_upload_blob
|
503
|
+
headers = translated_headers_for_proxy
|
504
|
+
headers['Content-Type'] = request.headers['Content-Type'] if request.headers['Content-Type']
|
505
|
+
headers['Content-Length'] = request.headers['Content-Length'] if request.headers['Content-Length']
|
506
|
+
pulp_response = Resources::Registry::Proxy.post(@_request.fullpath, @_request.body, headers)
|
230
507
|
|
231
|
-
|
232
|
-
|
233
|
-
ensure
|
234
|
-
File.delete(tmp_file('manifest.json')) if File.exist? tmp_file('manifest.json')
|
508
|
+
pulp_response.headers.each do |key, value|
|
509
|
+
response.header[key.to_s] = value
|
235
510
|
end
|
236
511
|
|
237
|
-
|
512
|
+
head pulp_response.code
|
238
513
|
end
|
239
514
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
response.header['Docker-Upload-UUID'] = uuid
|
250
|
-
response.header['Range'] = '0-0'
|
251
|
-
head 202
|
252
|
-
end
|
253
|
-
|
254
|
-
def status_upload_blob
|
255
|
-
response.header['Location'] = "#{request_url}/v2/#{params[:repository]}/blobs/uploads/#{params[:uuid]}"
|
256
|
-
response.header['Range'] = "123"
|
257
|
-
response.header['Docker-Upload-UUID'] = "123"
|
258
|
-
render plain: '', status: :no_content
|
259
|
-
end
|
260
|
-
|
261
|
-
def chunk_upload_blob
|
262
|
-
response.header['Location'] = "#{request_url}/v2/#{params[:repository]}/blobs/uploads/#{params[:uuid]}"
|
263
|
-
render plain: '', status: :accepted
|
515
|
+
def translated_headers_for_proxy
|
516
|
+
current_headers = {}
|
517
|
+
env = request.env.select do |key, _value|
|
518
|
+
key.match("^HTTP_.*")
|
519
|
+
end
|
520
|
+
env.each do |header|
|
521
|
+
current_headers[header[0].split('_')[1..-1].join('-')] = header[1]
|
522
|
+
end
|
523
|
+
current_headers
|
264
524
|
end
|
265
525
|
|
266
526
|
def upload_blob
|
267
|
-
|
268
|
-
|
527
|
+
headers = translated_headers_for_proxy
|
528
|
+
headers['Content-Type'] = request.headers['Content-Type'] if request.headers['Content-Type']
|
529
|
+
headers['Content-Range'] = request.headers['Content-Range'] if request.headers['Content-Range']
|
530
|
+
headers['Content-Length'] = request.headers['Content-Length'] if request.headers['Content-Length']
|
531
|
+
body = @_request.body.read
|
532
|
+
pulp_response = Resources::Registry::Proxy.patch(@_request.fullpath, body, headers)
|
533
|
+
|
534
|
+
pulp_response.headers.each do |key, value|
|
535
|
+
response.header[key.to_s] = value
|
269
536
|
end
|
270
537
|
|
271
|
-
|
272
|
-
if request.headers['Content-Range']
|
273
|
-
render_error 'unprocessable_entity', :status => :unprocessable_entity
|
274
|
-
end
|
275
|
-
|
276
|
-
response.header['Location'] = "#{request_url}/v2/#{params[:repository]}/blobs/uploads/#{params[:uuid]}"
|
277
|
-
response.header['Range'] = "1-#{request.body.size}"
|
278
|
-
response.header['Docker-Upload-UUID'] = params[:uuid]
|
279
|
-
head 204
|
538
|
+
head pulp_response.code
|
280
539
|
end
|
281
540
|
|
282
541
|
def finish_upload_blob
|
283
|
-
|
542
|
+
headers = translated_headers_for_proxy
|
543
|
+
headers['Content-Type'] = request.headers['Content-Type'] if request.headers['Content-Type']
|
544
|
+
headers['Content-Range'] = request.headers['Content-Range'] if request.headers['Content-Range']
|
545
|
+
headers['Content-Length'] = request.headers['Content-Length'] if request.headers['Content-Length']
|
546
|
+
pulp_response = Resources::Registry::Proxy.put(@_request.fullpath, @_request.body, headers)
|
547
|
+
|
548
|
+
pulp_response.headers.each do |key, value|
|
549
|
+
response.header[key.to_s] = value
|
550
|
+
end
|
284
551
|
|
285
|
-
|
286
|
-
|
552
|
+
head pulp_response.code
|
553
|
+
end
|
287
554
|
|
288
|
-
|
289
|
-
|
555
|
+
def push_manifest
|
556
|
+
headers = translated_headers_for_proxy
|
557
|
+
headers['Content-Type'] = request.headers['Content-Type'] if request.headers['Content-Type']
|
558
|
+
body = @_request.body.read
|
559
|
+
pulp_response = Resources::Registry::Proxy.put(@_request.fullpath, body, headers)
|
560
|
+
pulp_response.headers.each do |key, value|
|
561
|
+
response.header[key.to_s] = value
|
562
|
+
end
|
290
563
|
|
291
|
-
|
292
|
-
|
293
|
-
response.header['Content-Range'] = "1-#{File.size(digest_file)}"
|
294
|
-
response.header['Content-Length'] = "0"
|
295
|
-
response.header['Docker-Upload-UUID'] = params[:uuid]
|
296
|
-
head 201
|
297
|
-
end
|
564
|
+
cleanup_result = blob_push_cleanup if pulp_response.code.between?(200, 299)
|
565
|
+
return false unless cleanup_result
|
298
566
|
|
299
|
-
|
300
|
-
render plain: '', status: :ok
|
567
|
+
head pulp_response.code
|
301
568
|
end
|
302
569
|
|
303
570
|
def ping
|
@@ -310,10 +577,10 @@ module Katello
|
|
310
577
|
end
|
311
578
|
|
312
579
|
def v1_search
|
313
|
-
# Checks for
|
580
|
+
# Checks for v2 client and issues a 404 in that case. Podman
|
314
581
|
# examines the response from a /v1_search request. If the result
|
315
582
|
# is a 4XX, it will then proceed with a request to /_catalog
|
316
|
-
if request.headers['
|
583
|
+
if request.headers['HTTP_DOCKER_DISTRIBUTION_API_VERSION'] == 'registry/2.0'
|
317
584
|
render json: {}, status: :not_found
|
318
585
|
return
|
319
586
|
end
|
@@ -411,47 +678,6 @@ module Katello
|
|
411
678
|
tar_file
|
412
679
|
end
|
413
680
|
|
414
|
-
# FIXME: Reimplement for Pulp 3.
|
415
|
-
def upload_manifest(tar_file)
|
416
|
-
upload_id = pulp_content.create_upload_request['upload_id']
|
417
|
-
filename = tmp_file(tar_file)
|
418
|
-
uploads = []
|
419
|
-
|
420
|
-
File.open(filename, 'rb') do |file|
|
421
|
-
content = file.read
|
422
|
-
pulp_content.upload_bits(upload_id, 0, content)
|
423
|
-
|
424
|
-
uploads << {
|
425
|
-
id: upload_id,
|
426
|
-
name: filename,
|
427
|
-
size: file.size,
|
428
|
-
checksum: Digest::SHA256.hexdigest(content)
|
429
|
-
}
|
430
|
-
end
|
431
|
-
|
432
|
-
File.delete(filename)
|
433
|
-
task = sync_task(::Actions::Katello::Repository::ImportUpload,
|
434
|
-
@repository, uploads, generate_metadata: true, sync_capsule: true)
|
435
|
-
task.output['upload_results'][0]['digest']
|
436
|
-
ensure
|
437
|
-
pulp_content.delete_upload_request(upload_id) if upload_id
|
438
|
-
end
|
439
|
-
|
440
|
-
# FIXME: Reimplement for Pulp 3.
|
441
|
-
def upload_tag(digest, tag)
|
442
|
-
upload_id = pulp_content.create_upload_request['upload_id']
|
443
|
-
uploads = [{
|
444
|
-
id: upload_id,
|
445
|
-
name: tag,
|
446
|
-
digest: digest
|
447
|
-
}]
|
448
|
-
sync_task(::Actions::Katello::Repository::ImportUpload, @repository, uploads,
|
449
|
-
:generate_metadata => true, :sync_capsule => true)
|
450
|
-
tag
|
451
|
-
ensure
|
452
|
-
pulp_content.delete_upload_request(upload_id) if upload_id
|
453
|
-
end
|
454
|
-
|
455
681
|
def tmp_dir
|
456
682
|
"#{Rails.root}/tmp"
|
457
683
|
end
|
@@ -496,8 +722,11 @@ module Katello
|
|
496
722
|
|
497
723
|
def confirm_push_settings
|
498
724
|
return true if SETTINGS.dig(:katello, :container_image_registry, :allow_push)
|
499
|
-
|
500
|
-
|
725
|
+
render_podman_error(
|
726
|
+
"UNSUPPORTED",
|
727
|
+
"Registry push is not enabled. To enable, add ':katello:'->':container_image_registry:'->':allow_push: true' in the katello settings file.",
|
728
|
+
:unprocessable_entity
|
729
|
+
)
|
501
730
|
end
|
502
731
|
|
503
732
|
def request_url
|
@@ -519,10 +748,19 @@ module Katello
|
|
519
748
|
Rails.logger.debug "With body: #{filter_sensitive_data(response.body)}\n" unless route_name == 'pull_blob'
|
520
749
|
end
|
521
750
|
|
751
|
+
def render_podman_error(code, message, status = :bad_request)
|
752
|
+
# Renders a podman-compatible error and returns false.
|
753
|
+
# code: uppercase string code from opencontainer error code spec:
|
754
|
+
# https://specs.opencontainers.org/distribution-spec/?v=v1.0.0#DISTRIBUTION-SPEC-140
|
755
|
+
# message: a custom error string
|
756
|
+
# status: a symbol in the 400 block of the rails response code table:
|
757
|
+
# https://guides.rubyonrails.org/layouts_and_rendering.html#the-status-option
|
758
|
+
render json: {errors: [{code: code, message: message}]}, status: status
|
759
|
+
false
|
760
|
+
end
|
761
|
+
|
522
762
|
def item_not_found(item)
|
523
|
-
|
524
|
-
# returning errors based on registry specifications in https://docs.docker.com/registry/spec/api/#errors
|
525
|
-
render json: {errors: [code: :invalid_request, message: msg, details: msg]}, status: :not_found
|
763
|
+
render_podman_error("NAME_UNKNOWN", "#{item} was not found!", :not_found)
|
526
764
|
end
|
527
765
|
end
|
528
766
|
end
|
@@ -15,16 +15,12 @@ module Katello
|
|
15
15
|
#param :id, String, :desc => N_("UUID of the consumer"), :required => true
|
16
16
|
def upload_package_profile
|
17
17
|
User.as_anonymous_admin do
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
uploader.trigger_applicability_generation
|
25
|
-
else
|
26
|
-
async_task(::Actions::Katello::Host::UploadPackageProfile, @host, request.raw_post)
|
27
|
-
end
|
18
|
+
uploader = ::Katello::Host::PackageProfileUploader.new(
|
19
|
+
host: @host,
|
20
|
+
profile_string: request.raw_post
|
21
|
+
)
|
22
|
+
uploader.upload
|
23
|
+
uploader.trigger_applicability_generation
|
28
24
|
end
|
29
25
|
render :json => Resources::Candlepin::Consumer.get(@host.subscription_facet.uuid)
|
30
26
|
end
|
@@ -33,16 +29,12 @@ module Katello
|
|
33
29
|
param :id, String, :desc => N_("UUID of the consumer"), :required => true
|
34
30
|
def upload_profiles
|
35
31
|
User.as_anonymous_admin do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
uploader.trigger_applicability_generation
|
43
|
-
else
|
44
|
-
async_task(::Actions::Katello::Host::UploadProfiles, @host, request.raw_post)
|
45
|
-
end
|
32
|
+
uploader = ::Katello::Host::ProfilesUploader.new(
|
33
|
+
host: @host,
|
34
|
+
profile_string: request.raw_post
|
35
|
+
)
|
36
|
+
uploader.upload
|
37
|
+
uploader.trigger_applicability_generation
|
46
38
|
end
|
47
39
|
render :json => Resources::Candlepin::Consumer.get(@host.subscription_facet.uuid)
|
48
40
|
end
|
@@ -40,7 +40,7 @@ module Katello
|
|
40
40
|
param :unlimited_hosts, :bool, :desc => N_("can the activation key have unlimited hosts")
|
41
41
|
param :release_version, String, :desc => N_("content release version")
|
42
42
|
param :service_level, String, :desc => N_("service level")
|
43
|
-
param :auto_attach, :bool, :desc => N_("auto attach subscriptions upon registration")
|
43
|
+
param :auto_attach, :bool, :desc => N_("auto attach subscriptions upon registration"), deprecated: true
|
44
44
|
param :purpose_usage, String, :desc => N_("Sets the system purpose usage")
|
45
45
|
param :purpose_role, String, :desc => N_("Sets the system purpose usage")
|
46
46
|
param :purpose_addons, Array, :desc => N_("Sets the system add-ons")
|
@@ -163,7 +163,11 @@ module Katello
|
|
163
163
|
respond_for_show(:resource => @activation_key)
|
164
164
|
end
|
165
165
|
|
166
|
-
|
166
|
+
def deprecate_entitlement_mode_endpoint
|
167
|
+
::Foreman::Deprecation.api_deprecation_warning(N_("This endpoint is deprecated and will be removed in an upcoming release. Simple Content Access is the only supported content access mode."))
|
168
|
+
end
|
169
|
+
|
170
|
+
api :PUT, "/activation_keys/:id/add_subscriptions", N_("Attach a subscription"), deprecated: true
|
167
171
|
param :id, :number, :desc => N_("ID of the activation key"), :required => true
|
168
172
|
param :subscription_id, :number, :desc => N_("Subscription identifier"), :required => false
|
169
173
|
param :quantity, :number, :desc => N_("Quantity of this subscription to add"), :required => false
|
@@ -172,6 +176,7 @@ module Katello
|
|
172
176
|
param :quantity, :number, :desc => N_("Quantity of this subscriptions to add"), :required => false
|
173
177
|
end
|
174
178
|
def add_subscriptions
|
179
|
+
deprecate_entitlement_mode_endpoint
|
175
180
|
if params[:subscriptions]
|
176
181
|
params[:subscriptions].each { |subscription| @activation_key.subscribe(subscription[:id], subscription[:quantity]) }
|
177
182
|
elsif params[:subscription_id]
|
@@ -181,13 +186,14 @@ module Katello
|
|
181
186
|
respond_for_index(:collection => subscription_index, :template => 'subscriptions')
|
182
187
|
end
|
183
188
|
|
184
|
-
api :PUT, "/activation_keys/:id/remove_subscriptions", N_("Unattach a subscription")
|
189
|
+
api :PUT, "/activation_keys/:id/remove_subscriptions", N_("Unattach a subscription"), deprecated: true
|
185
190
|
param :id, :number, :desc => N_("ID of the activation key"), :required => true
|
186
191
|
param :subscription_id, String, :desc => N_("Subscription ID"), :required => false
|
187
192
|
param :subscriptions, Array, :desc => N_("Array of subscriptions to add"), :required => false do
|
188
193
|
param :id, String, :desc => N_("Subscription Pool uuid"), :required => false
|
189
194
|
end
|
190
195
|
def remove_subscriptions
|
196
|
+
deprecate_entitlement_mode_endpoint
|
191
197
|
if params[:subscriptions]
|
192
198
|
params[:subscriptions].each { |subscription| @activation_key.unsubscribe(subscription[:id]) }
|
193
199
|
elsif params[:subscription_id]
|
@@ -229,7 +235,7 @@ module Katello
|
|
229
235
|
|
230
236
|
api :GET, "/activation_keys/:id/product_content", N_("Show content available for an activation key")
|
231
237
|
param :id, String, :desc => N_("ID of the activation key"), :required => true
|
232
|
-
param :content_access_mode_all, :bool, :desc => N_("Get all content available, not just that provided by subscriptions")
|
238
|
+
param :content_access_mode_all, :bool, :desc => N_("Get all content available, not just that provided by subscriptions"), deprecated: true, default: true
|
233
239
|
param :content_access_mode_env, :bool, :desc => N_("Limit content to just that available in the activation key's content view version")
|
234
240
|
param_group :search, Api::V2::ApiController
|
235
241
|
def product_content
|