foreman_scc_manager 1.8.20 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -11
- data/app/controllers/api/v2/scc_accounts_controller.rb +55 -4
- data/app/controllers/api/v2/scc_products_controller.rb +1 -1
- data/app/controllers/scc_accounts_controller.rb +49 -0
- data/app/lib/actions/scc_manager/subscribe_product.rb +56 -22
- data/app/models/scc_account.rb +22 -1
- data/app/models/scc_product.rb +2 -5
- data/app/views/api/v2/scc_accounts/main.json.rabl +1 -1
- data/app/views/scc_accounts/_form.html.erb +8 -4
- data/app/views/scc_accounts/show.html.erb +7 -51
- data/config/routes.rb +1 -0
- data/db/migrate/20220429102717_populate_scc_katello_repositories.rb +5 -0
- data/db/migrate/20220531120722_add_product_category_to_scc_products.rb +5 -0
- data/db/migrate/20221013214310_add_sync_options_to_scc_account.rb +11 -0
- data/lib/foreman_scc_manager/engine.rb +1 -1
- data/lib/foreman_scc_manager/version.rb +1 -1
- data/lib/tasks/republish_repositories.rake +13 -0
- data/package.json +54 -0
- data/test/controllers/scc_accounts_controller_test.rb +7 -1
- data/test/fixtures/models/katello_root_repositories.yml +0 -12
- data/test/test_plugin_helper.rb +0 -6
- data/webpack/components/SCCProductPage/EmptySccProducts.js +46 -0
- data/webpack/components/SCCProductPage/SCCProductPage.js +96 -0
- data/webpack/components/SCCProductPage/SCCProductPageActions.js +27 -0
- data/webpack/components/SCCProductPage/SCCProductPageConstants.js +5 -0
- data/webpack/components/SCCProductPage/SCCProductPageReducer.js +34 -0
- data/webpack/components/SCCProductPage/SCCProductPageSelectors.js +7 -0
- data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCGenericPicker/index.js +80 -0
- data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCTreePicker/components/SCCRepoPicker/index.js +174 -0
- data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCTreePicker/components/SCCRepoPicker/styles.scss +3 -0
- data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCTreePicker/index.js +303 -0
- data/webpack/components/SCCProductPage/components/SCCProductPicker/index.js +235 -0
- data/webpack/components/SCCProductPage/components/SCCProductPicker/styles.scss +10 -0
- data/webpack/components/SCCProductPage/components/SCCProductPickerModal/index.js +81 -0
- data/webpack/components/SCCProductPage/components/SCCProductView/components/SCCRepoView/index.js +113 -0
- data/webpack/components/SCCProductPage/components/SCCProductView/components/SCCRepoView/styles.scss +14 -0
- data/webpack/components/SCCProductPage/components/SCCProductView/index.js +236 -0
- data/webpack/components/SCCProductPage/components/common/SCCGenericExpander/index.js +58 -0
- data/webpack/components/SCCProductPage/components/common/SCCProductTreeExpander/index.js +21 -0
- data/webpack/components/SCCProductPage/components/common/SCCSubscribedProductsExpander/index.js +21 -0
- data/webpack/components/SCCProductPage/index.js +18 -0
- data/webpack/components/SCCProductPage/sccProductPage.scss +8 -0
- data/webpack/index.js +11 -0
- data/webpack/reducer.js +7 -0
- metadata +43 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6946578ff8b15ec04a5c14a78e12107481d47d9f5093a4e1d2501bc79c4c4f94
|
4
|
+
data.tar.gz: f800326b64951b7909427f7fa7d126e6300550f5bee9afacbb394f83d5fe1cf7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d90c05393fe090f811d6cfbb038dd2cb5e45f73ed1359e3bd172c422131a9acb53ac17c0e85c253f9a350462fa5a7954d767af01ffdb9baf3766fcae5acee014
|
7
|
+
data.tar.gz: acbbdc19ee139f505415d328fe51f463e2d249a82635b75750b73bfbbdd4fd3a84a32f465cac22c806d36b8044f6d07f14045ecb931830af58a39dac19ce94ee
|
data/README.md
CHANGED
@@ -8,7 +8,13 @@ Foreman plugin to sync SUSE Customer Center products and repositories into Katel
|
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
11
|
-
This plugin installation is
|
11
|
+
This plugin installation is supported since Foreman 3.4 / Katello 4.6 by the foreman-installer, but only with the scenario Katello:
|
12
|
+
|
13
|
+
```sh
|
14
|
+
foreman-installer --scenario katello --enable-foreman-plugin-scc-manager
|
15
|
+
```
|
16
|
+
|
17
|
+
You can also install it manually:
|
12
18
|
|
13
19
|
```sh
|
14
20
|
yum install tfm-rubygem-foreman_scc_manager
|
@@ -20,22 +26,20 @@ foreman-installer
|
|
20
26
|
|
21
27
|
| Foreman Version | Katello Version | Plugin Version |
|
22
28
|
| --------------- | --------------- | -------------- |
|
29
|
+
| 3.3 | 4.5 | ~> 2.0.0 |
|
30
|
+
| 3.1 | 4.3 | ~> 1.8.20\* |
|
31
|
+
| 3.0 | 4.2 | ~> 1.8.20 |
|
32
|
+
| 2.5 | 4.1 | ~> 1.8.20 |
|
23
33
|
| 2.3 | 3.18 | ~> 1.8.9 |
|
24
34
|
| 2.1 | 3.16 | ~> 1.8.5 |
|
25
35
|
| 2.0 | 3.16 | ~> 1.8.4 |
|
26
36
|
| 1.24 | 3.14 | ~> 1.8.0 |
|
27
|
-
|
28
|
-
|
29
|
-
| 1.20 | 3.9 | ~> 1.6.0 |
|
30
|
-
| 1.19 | 3.8 | ~> 1.5.1 |
|
31
|
-
| 1.18 | 3.7 | ~> 1.5.0 |
|
32
|
-
| 1.17 | 3.6 | >= 1.3.1 |
|
33
|
-
| 1.16 | 3.5 | <= 1.3.0 |
|
34
|
-
| 1.15 | 3.4 | ~> 1.1.0 |
|
37
|
+
|
38
|
+
\* If you are using foreman_scc_manager in version 1.8.20 and then upgrade to Katello 4.3, you need to manually run the following rake task on your Foreman instance: `foreman-rake foreman_scc_manager:setup_authentication_tokens`.
|
35
39
|
|
36
40
|
## Documentation
|
37
41
|
|
38
|
-
[Plugin documentation](https://docs.orcharhino.com/or/docs/sources/
|
42
|
+
[Plugin documentation](https://docs.orcharhino.com/or/docs/sources/guides/suse_linux_enterprise_server/managing_content/managing_suse_content.html)
|
39
43
|
|
40
44
|
## Hammer CLI Extension
|
41
45
|
|
@@ -47,7 +51,7 @@ Fork and send a Pull Request. Thanks!
|
|
47
51
|
|
48
52
|
## Copyright
|
49
53
|
|
50
|
-
Copyright (c)
|
54
|
+
Copyright (c) 2022 ATIX AG - https://atix.de
|
51
55
|
|
52
56
|
This program is free software: you can redistribute it and/or modify
|
53
57
|
it under the terms of the GNU General Public License as published by
|
@@ -10,7 +10,7 @@ module Api
|
|
10
10
|
api_base_url '/api/v2'
|
11
11
|
end
|
12
12
|
|
13
|
-
before_action :find_resource, :only => [:show, :update, :destroy, :sync, :bulk_subscribe]
|
13
|
+
before_action :find_resource, :only => [:show, :update, :destroy, :sync, :bulk_subscribe, :bulk_subscribe_with_repos]
|
14
14
|
|
15
15
|
api :GET, '/scc_accounts/', N_('List all scc_accounts')
|
16
16
|
param :organization_id, :identifier, :required => true
|
@@ -34,6 +34,14 @@ module Api
|
|
34
34
|
param :password, String, :required => true, :desc => N_('Password of scc_account')
|
35
35
|
param :base_url, String, :required => false, :desc => N_('URL of SUSE for scc_account')
|
36
36
|
param :interval, ['never', 'daily', 'weekly', 'monthly'], :desc => N_('Interval for syncing scc_account')
|
37
|
+
param :download_policy,
|
38
|
+
::Katello::RootRepository::DOWNLOAD_POLICIES,
|
39
|
+
:required => false,
|
40
|
+
:desc => N_('The default download policy for repositories which were created using this SCC Account.')
|
41
|
+
param :mirroring_policy,
|
42
|
+
SccAccount::SCC_MIRRORING_POLICIES,
|
43
|
+
:required => false,
|
44
|
+
:desc => N_('The default mirroring policy for repositories which were created using this SCC Account.')
|
37
45
|
param :sync_date, String, :desc => N_('Date and time relative to which the sync interval is run')
|
38
46
|
param :katello_gpg_key_id, :identifier, :required => false, :desc => N_('Associated GPG key of scc_account')
|
39
47
|
end
|
@@ -105,12 +113,16 @@ module Api
|
|
105
113
|
param :id, :identifier_dottable, :required => true
|
106
114
|
param :scc_subscribe_product_ids, Array, :required => true
|
107
115
|
def bulk_subscribe
|
108
|
-
scc_products_to_subscribe = @scc_account.scc_products.where(:id => params[:scc_subscribe_product_ids])
|
109
116
|
respond_to do |format|
|
110
|
-
if
|
117
|
+
if params[:scc_subscribe_product_ids].count > 0
|
118
|
+
# we need to pass two parameters to the product subscribe task,
|
119
|
+
# the product itself and an array of repo ids
|
120
|
+
# if the id array is empty, all repositories will be subscribed to
|
121
|
+
scc_products = @scc_account.scc_products.where(:id => params[:scc_subscribe_product_ids])
|
111
122
|
subscribe_task = ForemanTasks.async_task(::Actions::BulkAction,
|
112
123
|
::Actions::SccManager::SubscribeProduct,
|
113
|
-
|
124
|
+
scc_products,
|
125
|
+
{})
|
114
126
|
format.json { render json: subscribe_task.to_json, status: :ok }
|
115
127
|
else
|
116
128
|
format.json { render json: { error: 'No Product selected' }, status: :expectation_failed }
|
@@ -122,6 +134,43 @@ module Api
|
|
122
134
|
render json: { error: ('Lock on SCC account already taken: %s' % e).to_s }, status: :unprocessable_entity
|
123
135
|
end
|
124
136
|
|
137
|
+
def_param_group :scc_product_data do
|
138
|
+
param :scc_product_data, Array, :required => true, :desc => 'Array of Hash elements. One hash element contains an scc_product_id and a repository_list.' do
|
139
|
+
param :scc_product_id, Integer, :required => true, :desc => 'Product ID of SCC product'
|
140
|
+
param :repository_list, Array, of: Integer, :required => false,
|
141
|
+
:desc => 'List of SCC repositories belonging to the SCC product. If the list is empty, all repositories will be subscribed to.'
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
api :PUT, '/scc_accounts/:id/bulk_subscribe_with_repos/', N_('Bulk subscription of scc_products with individual repository selection for scc_account.')
|
146
|
+
param :id, :identifier_dottable, :required => true
|
147
|
+
param_group :scc_product_data
|
148
|
+
def bulk_subscribe_with_repos
|
149
|
+
respond_to do |format|
|
150
|
+
# if we want to subscribe to specific repos, we need to pass the product and the
|
151
|
+
# corresponding repository ids instead of scc products only
|
152
|
+
if params[:scc_product_data].count > 0
|
153
|
+
scc_products = @scc_account.scc_products.where(:id => params[:scc_product_data].pluck(:scc_product_id))
|
154
|
+
if scc_products.empty?
|
155
|
+
format.json { render json: { error: _('The selected products cannot be found for this SCC account.') }, status: :unprocessable_entity }
|
156
|
+
else
|
157
|
+
action_args = params[:scc_product_data].map { |p| { p['scc_product_id'] => p['repository_list'] } }.inject(:merge)
|
158
|
+
subscribe_task = ForemanTasks.async_task(::Actions::BulkAction,
|
159
|
+
::Actions::SccManager::SubscribeProduct,
|
160
|
+
scc_products,
|
161
|
+
action_args)
|
162
|
+
format.json { render json: subscribe_task.to_json, status: :ok }
|
163
|
+
end
|
164
|
+
else
|
165
|
+
format.json { render json: { error: 'No Product selected' }, status: :expectation_failed }
|
166
|
+
end
|
167
|
+
end
|
168
|
+
rescue ::Foreman::Exception => e
|
169
|
+
render json: { error: ('Failed to add task to queue: %s' % e).to_s }, status: :unprocessable_entity
|
170
|
+
rescue ForemanTasks::Lock::LockConflict => e
|
171
|
+
render json: { error: ('Lock on SCC account already taken: %s' % e).to_s }, status: :unprocessable_entity
|
172
|
+
end
|
173
|
+
|
125
174
|
private
|
126
175
|
|
127
176
|
def scc_account_params
|
@@ -152,6 +201,8 @@ module Api
|
|
152
201
|
:sync
|
153
202
|
when 'bulk_subscribe'
|
154
203
|
:bulk_subscribe
|
204
|
+
when 'bulk_subscribe_with_repos'
|
205
|
+
:bulk_subscribe_with_repos
|
155
206
|
else
|
156
207
|
super
|
157
208
|
end
|
@@ -41,7 +41,7 @@ module Api
|
|
41
41
|
param :id, :identifier_dottable, :required => true
|
42
42
|
param :scc_account_id, :identifier_dottable, :required => true
|
43
43
|
def subscribe
|
44
|
-
subcribe_task = ForemanTasks.async_task(::Actions::SccManager::SubscribeProduct, @scc_product) if @scc_product
|
44
|
+
subcribe_task = ForemanTasks.async_task(::Actions::SccManager::SubscribeProduct, @scc_product, {}) if @scc_product
|
45
45
|
respond_to do |format|
|
46
46
|
if subcribe_task
|
47
47
|
format.json { render json: subcribe_task.to_json, status: :ok }
|
@@ -1,5 +1,6 @@
|
|
1
1
|
class SccAccountsController < ApplicationController
|
2
2
|
helper_method :scc_filtered_products
|
3
|
+
helper_method :create_nested_product_tree
|
3
4
|
before_action :find_organization
|
4
5
|
before_action :find_resource, only: %i[show edit update destroy sync bulk_subscribe]
|
5
6
|
before_action :find_available_gpg_keys, only: %i[new edit update create]
|
@@ -97,6 +98,52 @@ class SccAccountsController < ApplicationController
|
|
97
98
|
redirect_to scc_accounts_path
|
98
99
|
end
|
99
100
|
|
101
|
+
def create_nested_product_tree(scc_products, subscribed_only:)
|
102
|
+
if subscribed_only
|
103
|
+
scc_products_base = scc_products.where(:product_type => 'base').where.not(:product_id => nil).includes([:scc_extensions])
|
104
|
+
else
|
105
|
+
scc_products_base = scc_products.where(:product_type => 'base').includes([:scc_extensions])
|
106
|
+
end
|
107
|
+
tree = []
|
108
|
+
scc_products_base.each do |p|
|
109
|
+
tree.push(get_product_tree_hash(p))
|
110
|
+
end
|
111
|
+
|
112
|
+
tree
|
113
|
+
end
|
114
|
+
|
115
|
+
def scc_product_hash(scc_product)
|
116
|
+
scc_product_json = scc_product.as_json(:only => [:scc_id, :id, :arch, :version, :product_id, :subscription_valid],
|
117
|
+
include: { :scc_repositories => { :only => [:id, :name, :subscription_valid] } })
|
118
|
+
.merge('name' => scc_product.pretty_name, 'product_category' => scc_product.product_category)
|
119
|
+
# find if and which Katello root repository is associated with this SCC product
|
120
|
+
repo_ids_katello = scc_product.product.blank? || scc_product.product.root_repository_ids.blank? ? nil : scc_product.product.root_repository_ids
|
121
|
+
scc_product_json['scc_repositories'].each do |repo|
|
122
|
+
# byebug
|
123
|
+
if repo_ids_katello.blank?
|
124
|
+
repo['katello_root_repository_id'] = nil
|
125
|
+
else
|
126
|
+
repo_ids_scc = scc_product.scc_repositories.find(repo['id']).katello_root_repository_ids
|
127
|
+
repo['katello_root_repository_id'] = repo_ids_scc.blank? ? nil : (repo_ids_scc & repo_ids_katello).first
|
128
|
+
end
|
129
|
+
end
|
130
|
+
scc_product_json
|
131
|
+
end
|
132
|
+
|
133
|
+
def get_product_tree_hash(scc_product_base)
|
134
|
+
if scc_product_base.scc_extensions.blank?
|
135
|
+
scc_product_hash(scc_product_base)
|
136
|
+
else
|
137
|
+
children = []
|
138
|
+
scc_product_base.scc_extensions.each do |ext|
|
139
|
+
children.push(get_product_tree_hash(ext))
|
140
|
+
end
|
141
|
+
scc_product_base_hash = scc_product_hash(scc_product_base)
|
142
|
+
scc_product_base_hash['children'] = children
|
143
|
+
scc_product_base_hash
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
100
147
|
private
|
101
148
|
|
102
149
|
def find_available_gpg_keys
|
@@ -123,6 +170,8 @@ class SccAccountsController < ApplicationController
|
|
123
170
|
:password,
|
124
171
|
:base_url,
|
125
172
|
:interval,
|
173
|
+
:download_policy,
|
174
|
+
:mirroring_policy,
|
126
175
|
:sync_date,
|
127
176
|
:organization_id,
|
128
177
|
:katello_gpg_key_id
|
@@ -1,41 +1,79 @@
|
|
1
1
|
module Actions
|
2
2
|
module SccManager
|
3
3
|
class SubscribeProduct < Actions::EntryAction
|
4
|
-
|
5
|
-
|
4
|
+
# scc_product is an ActiveRecord object of Class SccProduct
|
5
|
+
# scc_repos_to_subscribe is a hash with the product id as keys and an array of
|
6
|
+
# repos to subscribe as values
|
7
|
+
# rubocop:disable Metrics/MethodLength
|
8
|
+
def plan(scc_product, scc_repos_to_subscribe)
|
9
|
+
if scc_product.product
|
10
|
+
::Foreman::Logging.logger('foreman_scc_manager')
|
11
|
+
.info("SccProduct '#{scc_product.friendly_name}' is already subscribed to.")
|
12
|
+
else
|
13
|
+
::Foreman::Logging.logger('foreman_scc_manager')
|
14
|
+
.info("Initiating subscription for SccProduct '#{scc_product.friendly_name}'.")
|
15
|
+
end
|
6
16
|
|
7
|
-
::Foreman::Logging.logger('foreman_scc_manager')
|
8
|
-
.info("Initiating subscription for SccProduct '#{scc_product.friendly_name}'.")
|
9
17
|
sequence do
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
if scc_product.product_id.nil?
|
19
|
+
product_create_action = plan_action(CreateProduct,
|
20
|
+
:product_name => scc_product.pretty_name,
|
21
|
+
:product_description => scc_product.pretty_description,
|
22
|
+
:organization_id => scc_product.organization.id,
|
23
|
+
:gpg_key => scc_product.scc_account.katello_gpg_key_id)
|
24
|
+
end
|
15
25
|
katello_repos = {}
|
16
|
-
|
26
|
+
# we need to set the repositories to subscribe to
|
27
|
+
scc_repos = []
|
28
|
+
if scc_repos_to_subscribe.empty?
|
29
|
+
scc_repos = scc_product.scc_repositories
|
30
|
+
else
|
31
|
+
# at this point, we need to make sure that the repository list is valid
|
32
|
+
# we want to subscribe only to repos that we have not subscribed before
|
33
|
+
repo_ids_katello = scc_product.product.blank? || scc_product.product.root_repository_ids.blank? ? nil : scc_product.product.root_repository_ids
|
34
|
+
scc_repos = scc_product.scc_repositories.where(id: scc_repos_to_subscribe[scc_product.id])
|
35
|
+
unless repo_ids_katello.nil? || scc_repos.empty?
|
36
|
+
# remove repo if Katello repo is already associated
|
37
|
+
scc_repos.reject { |repo| (repo.katello_root_repositories & repo_ids_katello).present? }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
if scc_repos.empty?
|
41
|
+
::Foreman::Logging.logger('foreman_scc_manager')
|
42
|
+
.info('The repositories you have selected are either already subscribed to or invalid.')
|
43
|
+
else
|
44
|
+
::Foreman::Logging.logger('foreman_scc_manager')
|
45
|
+
.info("Subscribing to SCC repositories '#{scc_repos.pluck(:id)}'.
|
46
|
+
If you requested more repositories, please check if those are already subscribed to or invalid.")
|
47
|
+
end
|
48
|
+
scc_repos.each do |repo|
|
17
49
|
arch = scc_product.arch || 'noarch'
|
18
50
|
repo_create_action = plan_action(CreateRepository,
|
19
|
-
:product_id => product_create_action.output[:product_id],
|
51
|
+
:product_id => scc_product.product_id || product_create_action.output[:product_id],
|
20
52
|
:uniq_name => repo.uniq_name(scc_product),
|
21
53
|
:pretty_repo_name => repo.pretty_name,
|
22
54
|
:url => repo.url,
|
23
55
|
:token => repo.token,
|
24
|
-
:arch => arch
|
56
|
+
:arch => arch,
|
57
|
+
:download_policy => scc_product.scc_account.download_policy,
|
58
|
+
:mirroring_policy => scc_product.scc_account.mirroring_policy)
|
25
59
|
katello_repos[repo.id] = repo_create_action.output[:katello_root_repository_id]
|
26
60
|
end
|
61
|
+
|
27
62
|
# connect action to resource (=> make parameters accessable in input)
|
28
|
-
action_subject(scc_product, product_id: product_create_action.output[:product_id])
|
63
|
+
action_subject(scc_product, product_id: product_create_action.output[:product_id]) if scc_product.product_id.nil?
|
29
64
|
input.update(katello_repos: katello_repos)
|
30
65
|
plan_self
|
31
66
|
end
|
32
67
|
end
|
68
|
+
# rubocop:enable Metrics/MethodLength
|
33
69
|
|
34
70
|
def finalize
|
35
71
|
# connect Scc products and Katello products
|
36
|
-
|
37
|
-
|
38
|
-
|
72
|
+
# it may happen that we only append repos to an existing product
|
73
|
+
unless input[:scc_product].nil?
|
74
|
+
scc_product = SccProduct.find(input[:scc_product][:id])
|
75
|
+
scc_product.update!(product_id: input[:product_id])
|
76
|
+
end
|
39
77
|
# extract Katello repo ids from input hash and store to database
|
40
78
|
input[:katello_repos].each do |scc_repo_id, katello_root_repository_id|
|
41
79
|
SccKatelloRepository.find_or_create_by(scc_repository_id: scc_repo_id, katello_root_repository_id: katello_root_repository_id)
|
@@ -83,13 +121,9 @@ module Actions
|
|
83
121
|
:unprotected => unprotected,
|
84
122
|
:gpg_key => gpg_key,
|
85
123
|
:arch => input[:arch],
|
86
|
-
:download_policy =>
|
124
|
+
:download_policy => input[:download_policy],
|
125
|
+
:mirroring_policy => input[:mirroring_policy] }
|
87
126
|
repository = product.add_repo(repo_param)
|
88
|
-
if repository.has_attribute?('mirror_on_sync')
|
89
|
-
repository.mirror_on_sync = true
|
90
|
-
else
|
91
|
-
repository.mirroring_policy = ::Katello::RootRepository::MIRRORING_POLICY_CONTENT
|
92
|
-
end
|
93
127
|
if repository.has_attribute?('upstream_authentication_token')
|
94
128
|
repository.url = input[:url]
|
95
129
|
repository.upstream_authentication_token = input[:token]
|
data/app/models/scc_account.rb
CHANGED
@@ -13,6 +13,11 @@ class SccAccount < ApplicationRecord
|
|
13
13
|
MONTHLY = 'monthly'.freeze
|
14
14
|
TYPES = [NEVER, DAILY, WEEKLY, MONTHLY].freeze
|
15
15
|
|
16
|
+
# MIRRORING_POLICY_COMPLETE doesn't work for suse repository because deltarpm metadata is not supported by pulp3
|
17
|
+
SCC_MIRRORING_POLICIES = ::Katello::RootRepository::MIRRORING_POLICIES.dup
|
18
|
+
SCC_MIRRORING_POLICIES.delete(::Katello::RootRepository::MIRRORING_POLICY_COMPLETE)
|
19
|
+
SCC_MIRRORING_POLICIES.freeze
|
20
|
+
|
16
21
|
self.include_root_in_json = false
|
17
22
|
|
18
23
|
belongs_to :organization
|
@@ -29,6 +34,8 @@ class SccAccount < ApplicationRecord
|
|
29
34
|
validates :password, presence: true
|
30
35
|
validates :base_url, presence: true
|
31
36
|
validates :interval, :inclusion => { :in => TYPES }, :allow_blank => false
|
37
|
+
validates :download_policy, :inclusion => { :in => ::Katello::RootRepository::DOWNLOAD_POLICIES }, :allow_blank => false
|
38
|
+
validates :mirroring_policy, :inclusion => { :in => SCC_MIRRORING_POLICIES }, :allow_blank => false
|
32
39
|
validate :sync_date_is_valid_datetime
|
33
40
|
|
34
41
|
after_initialize :init
|
@@ -219,8 +226,8 @@ class SccAccount < ApplicationRecord
|
|
219
226
|
cached_product.product_type = up['product_type']
|
220
227
|
cached_product.scc_repositories =
|
221
228
|
scc_repositories.where(scc_id: up['repositories'].map { |repo| repo['id'] })
|
222
|
-
# name should be set after friendly_name because it depends on friendly_name
|
223
229
|
cached_product.name = cached_product.pretty_name
|
230
|
+
cached_product.product_category = up['name']
|
224
231
|
cached_product.description = cached_product.pretty_description
|
225
232
|
cached_product.subscription_valid = true
|
226
233
|
cached_product.save!
|
@@ -278,4 +285,18 @@ class SccAccount < ApplicationRecord
|
|
278
285
|
end
|
279
286
|
items_to_invalidate
|
280
287
|
end
|
288
|
+
|
289
|
+
def self.download_policy_selection_values
|
290
|
+
names = { 'on_demand' => _('On Demand'), 'immediate' => _('Immediate') }
|
291
|
+
::Katello::RootRepository::DOWNLOAD_POLICIES.map do |p|
|
292
|
+
names.include?(p) ? [names[p], p] : [p, p]
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def self.mirroring_policy_selection_values
|
297
|
+
names = { 'additive' => _('Additive'), 'mirror_content_only' => _('Content Only') }
|
298
|
+
SCC_MIRRORING_POLICIES.map do |p|
|
299
|
+
names.include?(p) ? [names[p], p] : [p, p]
|
300
|
+
end
|
301
|
+
end
|
281
302
|
end
|
data/app/models/scc_product.rb
CHANGED
@@ -58,11 +58,8 @@ class SccProduct < ApplicationRecord
|
|
58
58
|
gpg_key = new_product.gpg_key
|
59
59
|
new_repo = new_product.add_repo(label, uniq_repo_name, repo.url, 'yum', unprotected, gpg_key)
|
60
60
|
new_repo.arch = arch || 'noarch'
|
61
|
-
|
62
|
-
|
63
|
-
else
|
64
|
-
new_repo.mirroring_policy = ::Katello::RootRepository::MIRRORING_POLICY_CONTENT
|
65
|
-
end
|
61
|
+
new_repo.mirroring_policy = scc_account.mirroring_policy
|
62
|
+
new_repo.download_policy = scc_account.download_policy
|
66
63
|
if new_repo.has_attribute?('upstream_authentication_token')
|
67
64
|
new_repo.upstream_authentication_token = repo.token
|
68
65
|
new_repo.url = repo.url
|
@@ -2,4 +2,4 @@
|
|
2
2
|
|
3
3
|
object @scc_account
|
4
4
|
extends 'api/v2/scc_accounts/base'
|
5
|
-
attributes :organization_id, :organization_name, :login, :base_url, :interval, :sync_date
|
5
|
+
attributes :organization_id, :organization_name, :login, :base_url, :interval, :download_policy, :mirroring_policy, :sync_date
|
@@ -19,11 +19,15 @@
|
|
19
19
|
<%= field f, :sync_date, label: _('Sync Date') do
|
20
20
|
f.datetime_field :sync_date, placeholder: Time.now
|
21
21
|
end %>
|
22
|
-
<%= selectable_f f, :katello_gpg_key_id, @selectable_gpg_keys, {},
|
23
|
-
{ :include_blank => _("None"),
|
24
|
-
:label => _('Use GPG key for SUSE products'),
|
25
|
-
:selected => @scc_account.katello_gpg_key_id,
|
22
|
+
<%= selectable_f f, :katello_gpg_key_id, @selectable_gpg_keys, {},
|
23
|
+
{ :include_blank => _("None"),
|
24
|
+
:label => _('Use GPG key for SUSE products'),
|
25
|
+
:selected => @scc_account.katello_gpg_key_id,
|
26
26
|
:help_block => _("Use this setting if you want to automatically add a GPG key to your SUSE products upon subscription. You can change this setting in the 'Content' > 'Products' menu, later.") } %>
|
27
|
+
<%= selectable_f f, :download_policy, SccAccount::download_policy_selection_values,
|
28
|
+
{ :label => _('Download Policy'), :help_block => _("The default download policy for repositories which were created using this SCC Account.") } %>
|
29
|
+
<%= selectable_f f, :mirroring_policy, SccAccount::mirroring_policy_selection_values,
|
30
|
+
{ :label => _('Mirroring Policy'), :help_block => _("The default mirroring policy for repositories which were created using this SCC Account.") } %>
|
27
31
|
<div class='clearfix'>
|
28
32
|
<div class='form-group'>
|
29
33
|
<div class='col-md-2'></div>
|
@@ -1,52 +1,8 @@
|
|
1
1
|
<% title (_("Product Selection for Account %s") % @scc_account) %>
|
2
|
-
|
3
|
-
|
4
|
-
<%=
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
<%= check_box_tag("scc_account[scc_unsubscribe_product_ids][]", scc_product.id, true, disabled: true) %>
|
10
|
-
<%= link_to(scc_product.pretty_name, "/products/#{scc_product.product_id}") %>
|
11
|
-
<% else %>
|
12
|
-
<%= check_box_tag("scc_account[scc_subscribe_product_ids][]", scc_product.id, false) %>
|
13
|
-
<%= scc_product.pretty_name %>
|
14
|
-
<% end %>
|
15
|
-
<% unless scc_product.subscription_valid? %>
|
16
|
-
<span style="color:red">
|
17
|
-
<%= _('(WARNING: Please check your SUSE subscription)') %>
|
18
|
-
</span>
|
19
|
-
<% end %>
|
20
|
-
</span>
|
21
|
-
<% if scc_product.scc_extensions.any? %>
|
22
|
-
<ul style='padding-left: 20px;'>
|
23
|
-
<% scc_filtered_products(scc_product.scc_extensions, 'extension').each do |scc_extension| %>
|
24
|
-
<% render_list_node(f, scc_extension, parent_id + "_" + scc_product.id.to_s) %>
|
25
|
-
<% end %>
|
26
|
-
</ul>
|
27
|
-
<% end %>
|
28
|
-
</li>
|
29
|
-
<% end %>
|
30
|
-
|
31
|
-
<%= f.hidden_field :prevent_missing, value: 1 %>
|
32
|
-
<ul class="nav nav-tabs" data-tabs="tabs">
|
33
|
-
<li class="active"><a href="#primary" data-toggle="tab"><%= _("SUSE Customer Center") %></a></li>
|
34
|
-
</ul>
|
35
|
-
|
36
|
-
<div class="tab-content">
|
37
|
-
<div class="tab-pane active" id="primary">
|
38
|
-
<ul>
|
39
|
-
<% if @scc_account.synced %>
|
40
|
-
<% scc_filtered_products(@scc_account.scc_products).each do |scc_product| %>
|
41
|
-
<% render_list_node(f, scc_product) %>
|
42
|
-
<% end %>
|
43
|
-
<% else %>
|
44
|
-
<%= _('Please sync your SUSE subscriptions first.') %>
|
45
|
-
<% submit_disabled = true %>
|
46
|
-
<% end %>
|
47
|
-
</ul>
|
48
|
-
</div>
|
49
|
-
<%= submit_or_cancel f, false, {disabled: submit_disabled || false} %>
|
50
|
-
</div>
|
51
|
-
<% end %>
|
52
|
-
|
2
|
+
<%= webpacked_plugins_js_for :foreman_scc_manager %>
|
3
|
+
<%= webpacked_plugins_css_for :foreman_scc_manager %>
|
4
|
+
<%= react_component('SCCProductPage', {
|
5
|
+
:canCreate => authorized_for(action: :sync),
|
6
|
+
:sccAccountId => @scc_account.id,
|
7
|
+
:sccProductsInit => create_nested_product_tree(@scc_account.scc_products, subscribed_only: false)
|
8
|
+
}) %>
|
data/config/routes.rb
CHANGED
@@ -3,6 +3,11 @@ class PopulateSccKatelloRepositories < ActiveRecord::Migration[6.0]
|
|
3
3
|
belongs_to :product, class_name: 'Katello::Product'
|
4
4
|
has_and_belongs_to_many :scc_repositories
|
5
5
|
end
|
6
|
+
class SccRepository < ApplicationRecord
|
7
|
+
has_many :scc_katello_repositories
|
8
|
+
has_many :katello_root_repositories, through: :scc_katello_repositories
|
9
|
+
has_and_belongs_to_many :scc_products
|
10
|
+
end
|
6
11
|
|
7
12
|
def up
|
8
13
|
SccProduct.where.not(product_id: nil).each do |scc_p|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class AddSyncOptionsToSccAccount < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
add_column :scc_accounts, :download_policy, :string, default: ::Katello::RootRepository::DOWNLOAD_IMMEDIATE
|
4
|
+
add_column :scc_accounts, :mirroring_policy, :string, default: ::Katello::RootRepository::MIRRORING_POLICY_CONTENT
|
5
|
+
SccAccount.all.each do |a|
|
6
|
+
a.download_policy = ::Katello::RootRepository::DOWNLOAD_IMMEDIATE
|
7
|
+
a.mirroring_policy = ::Katello::RootRepository::MIRRORING_POLICY_CONTENT
|
8
|
+
a.save!
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -38,7 +38,7 @@ module ForemanSccManager
|
|
38
38
|
|
39
39
|
permission :use_scc_accounts,
|
40
40
|
{ :scc_accounts => [:bulk_subscribe],
|
41
|
-
:'api/v2/scc_accounts' => [:bulk_subscribe] },
|
41
|
+
:'api/v2/scc_accounts' => [:bulk_subscribe, :bulk_subscribe_with_repos] },
|
42
42
|
:resource_type => 'SccAccount'
|
43
43
|
|
44
44
|
permission :new_scc_accounts,
|
@@ -0,0 +1,13 @@
|
|
1
|
+
namespace :foreman_scc_manager do
|
2
|
+
desc 'Republish all SCC-repositories.'
|
3
|
+
task :republish_scc_repositories => ['dynflow:client', 'katello:check_ping'] do
|
4
|
+
needing_publish = SccKatelloRepository.joins(:katello_root_repository)
|
5
|
+
.joins(:katello_root_repository => :repositories)
|
6
|
+
.pluck("#{Katello::Repository.table_name}.id")
|
7
|
+
if needing_publish.any?
|
8
|
+
ForemanTasks.async_task(::Actions::Katello::Repository::BulkMetadataGenerate, Katello::Repository.where(:id => needing_publish))
|
9
|
+
else
|
10
|
+
puts 'Skipped. No repository found which was created by the SCC plugin.'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/package.json
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
{
|
2
|
+
"name": "foreman_scc_manager",
|
3
|
+
"version": "1.8.16",
|
4
|
+
"description": "Foreman plugin to sync SUSE Customer Center products and repositories into Katello ",
|
5
|
+
"main": "index.js",
|
6
|
+
"directories": {
|
7
|
+
"lib": "lib",
|
8
|
+
"test": "test"
|
9
|
+
},
|
10
|
+
"scripts": {
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
12
|
+
"create-react-component": "yo react-domain"
|
13
|
+
},
|
14
|
+
"repository": {
|
15
|
+
"type": "git",
|
16
|
+
"url": "git+ssh://git@github.com/ATIX-AG/foreman_scc_manager.git"
|
17
|
+
},
|
18
|
+
"peerDependencies": {
|
19
|
+
"@theforeman/vendor": "^4.14.0"
|
20
|
+
},
|
21
|
+
"devDependencies": {
|
22
|
+
"@babel/core": "^7.7.0",
|
23
|
+
"babel-eslint": "^10.0.0",
|
24
|
+
"babel-loader": "^8.0.0",
|
25
|
+
"@theforeman/builder": "^4.14.0",
|
26
|
+
"@theforeman/eslint-plugin-foreman": "^8.16.0",
|
27
|
+
"@theforeman/find-foreman": "^4.14.0",
|
28
|
+
"@theforeman/stories": "^4.14.0",
|
29
|
+
"@theforeman/test": "^4.14.0",
|
30
|
+
"@theforeman/vendor-dev": "^4.14.0",
|
31
|
+
"eslint": "^6.7.2",
|
32
|
+
"eslint-plugin-spellcheck": "0.0.17",
|
33
|
+
"eslint-plugin-react": "^7.27.1",
|
34
|
+
"eslint-plugin-react-hooks": "^4.3.0",
|
35
|
+
"prettier": "^2.5.1",
|
36
|
+
"react-redux-test-utils": "^0.2.0"
|
37
|
+
},
|
38
|
+
"keywords": [
|
39
|
+
"SUSE",
|
40
|
+
"Katello",
|
41
|
+
"products",
|
42
|
+
"repositories"
|
43
|
+
],
|
44
|
+
"author": "ATIX AG",
|
45
|
+
"license": "GPL-3.0",
|
46
|
+
"bugs": {
|
47
|
+
"url": "https://github.com/ATIX-AG/foreman_scc_manager/issues"
|
48
|
+
},
|
49
|
+
"homepage": "https://github.com/ATIX-AG/foreman_scc_manager#readme",
|
50
|
+
"dependencies": {
|
51
|
+
"react-native-elements": "^3.4.2",
|
52
|
+
"react-native-vector-icons": "^9.0.0"
|
53
|
+
}
|
54
|
+
}
|