foreman_scc_manager 1.8.4 → 1.8.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -1
- data/app/controllers/api/v2/scc_accounts_controller.rb +9 -7
- data/app/controllers/scc_accounts_controller.rb +30 -4
- data/app/lib/actions/scc_manager/subscribe_product.rb +26 -13
- data/app/lib/actions/scc_manager/sync.rb +5 -5
- data/app/lib/actions/scc_manager/sync_products.rb +10 -13
- data/app/lib/actions/scc_manager/sync_repositories.rb +9 -13
- data/app/models/scc_account.rb +63 -5
- data/app/models/scc_product.rb +20 -2
- data/app/models/scc_repository.rb +11 -9
- data/app/views/scc_accounts/_form.html.erb +6 -0
- data/app/views/scc_accounts/index.html.erb +4 -3
- data/app/views/scc_accounts/show.html.erb +13 -4
- data/db/migrate/20200520281300_fix_scc_permissions.rb +22 -0
- data/db/migrate/20201119084201_add_gpg_key_to_scc_account.rb +6 -0
- data/db/migrate/20210205082733_add_subscription_valid_to_scc_products_and_repos.rb +6 -0
- data/db/migrate/20210210104407_add_root_repository_id_to_scc_repository.rb +6 -0
- data/db/migrate/20210224095050_connect_katello_root_repository_to_scc_repository.rb +28 -0
- data/lib/foreman_scc_manager/engine.rb +40 -27
- data/lib/foreman_scc_manager/version.rb +1 -1
- data/lib/tasks/test.rake +1 -1
- data/locale/de/LC_MESSAGES/foreman_scc_manager.mo +0 -0
- data/locale/de/foreman_scc_manager.edit.po +574 -0
- data/locale/de/foreman_scc_manager.po +40 -21
- data/locale/de/foreman_scc_manager.po.time_stamp +0 -0
- data/locale/en/foreman_scc_manager.edit.po +566 -0
- data/locale/en/foreman_scc_manager.po +21 -3
- data/locale/en/foreman_scc_manager.po.time_stamp +0 -0
- data/locale/foreman_scc_manager.pot +65 -38
- data/test/controllers/api/v2/scc_accounts_test.rb +9 -3
- data/test/controllers/scc_accounts_controller_test.rb +104 -0
- data/test/controllers/scc_accounts_controller_test2.rb +51 -0
- data/test/fixtures/models/scc_extendings.yml +6 -0
- data/test/fixtures/models/scc_products.yml +30 -2
- data/test/fixtures/models/scc_repositories.yml +29 -0
- data/test/models/scc_account_test.rb +70 -0
- data/test/models/scc_product_test.rb +69 -1
- data/test/support/fixtures_support.rb +3 -2
- data/test/test_controller_helper.rb +15 -0
- data/test/test_plugin_helper.rb +9 -0
- metadata +31 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab78f155bda869b47a6124ada7ebcdf9d067c6173c400dfd9c052c70227695f9
|
4
|
+
data.tar.gz: '009d1c1db82b1c52e4e0ab47ebdb1769dbb4ea0e71fb6a2a0b5b26fff5b0cb41'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da25af4b803899a68ef9b3fae9646901437051d5b69dd4b5c588cca5e0018ea0b797d32255ed4dc5ba6ccb5044a119c2d712bb3b35905aeb231182145f910878
|
7
|
+
data.tar.gz: 15b7aa5a3f7a05e3c517aa6aa41fcef1c9bee3fb00d5f49405166264d21a7857fc348940c06a0279d88330d29b7480e90d2f3e32025ee2bcba95c1acf84f1c7b
|
data/README.md
CHANGED
@@ -13,6 +13,9 @@ for how to install Foreman plugins
|
|
13
13
|
|
14
14
|
| Foreman Version | Katello Version | Plugin Version |
|
15
15
|
| --------------- | --------------- | -------------- |
|
16
|
+
| 2.3 | 3.18 | ~> 1.8.9 |
|
17
|
+
| 2.1 | 3.16 | ~> 1.8.5 |
|
18
|
+
| 2.0 | 3.16 | ~> 1.8.4 |
|
16
19
|
| 1.24 | 3.14 | ~> 1.8.0 |
|
17
20
|
| 1.22 | 3.12 | ~> 1.7.0 |
|
18
21
|
| 1.21 | 3.10 | ~> 1.6.0 |
|
@@ -23,13 +26,19 @@ for how to install Foreman plugins
|
|
23
26
|
| 1.16 | 3.5 | <= 1.3.0 |
|
24
27
|
| 1.15 | 3.4 | ~> 1.1.0 |
|
25
28
|
|
29
|
+
## Documentation
|
30
|
+
The plugin documentation can be found at https://docs.orcharhino.com/sources/management_ui/the_content_menu/suse_subscriptions.html.
|
31
|
+
|
32
|
+
A Hammer CLI extension is available for this plugin:
|
33
|
+
https://github.com/ATIX-AG/hammer-cli-foreman-scc-manager
|
34
|
+
|
26
35
|
## Contributing
|
27
36
|
|
28
37
|
Fork and send a Pull Request. Thanks!
|
29
38
|
|
30
39
|
## Copyright
|
31
40
|
|
32
|
-
Copyright (c)
|
41
|
+
Copyright (c) 2021 ATIX AG - http://www.atix.de
|
33
42
|
|
34
43
|
This program is free software: you can redistribute it and/or modify
|
35
44
|
it under the terms of the GNU General Public License as published by
|
@@ -18,7 +18,7 @@ module Api
|
|
18
18
|
def index
|
19
19
|
scope = resource_scope
|
20
20
|
scope = scope.where(:organization => params[:organization_id]) if params[:organization_id].present?
|
21
|
-
@scc_accounts = scope.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
|
21
|
+
@scc_accounts = scope.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page], :per_page => params[:per_page])
|
22
22
|
end
|
23
23
|
|
24
24
|
api :GET, '/scc_accounts/:id/', N_('Show scc_account')
|
@@ -34,7 +34,8 @@ 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', 'monthy'], :desc => N_('Interval for syncing scc_account')
|
37
|
-
param :sync_date, String, :desc => N_('
|
37
|
+
param :sync_date, String, :desc => N_('Date and time relative to which the sync interval is run')
|
38
|
+
param :katello_gpg_key_id, :identifier, :required => false, :desc => N_('Associated GPG key of scc_account')
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
@@ -79,9 +80,9 @@ module Api
|
|
79
80
|
end
|
80
81
|
respond_to do |format|
|
81
82
|
if @scc_account.test_connection
|
82
|
-
format.json { render json: '
|
83
|
+
format.json { render json: { 'success' => true }.to_json, status: :ok }
|
83
84
|
else
|
84
|
-
format.json { render json: '
|
85
|
+
format.json { render json: { 'success' => false, 'error' => 'Test failed. Check your credentials.' }.to_json, status: :not_found }
|
85
86
|
end
|
86
87
|
end
|
87
88
|
end
|
@@ -102,7 +103,7 @@ module Api
|
|
102
103
|
|
103
104
|
api :PUT, '/scc_accounts/:id/bulk_subscribe/', N_('Bulk subscription of scc_products for scc_account')
|
104
105
|
param :id, :identifier_dottable, :required => true
|
105
|
-
param :scc_subscribe_product_ids, Array
|
106
|
+
param :scc_subscribe_product_ids, Array, :required => true
|
106
107
|
def bulk_subscribe
|
107
108
|
scc_products_to_subscribe = @scc_account.scc_products.where(:id => params[:scc_subscribe_product_ids])
|
108
109
|
respond_to do |format|
|
@@ -112,7 +113,7 @@ module Api
|
|
112
113
|
scc_products_to_subscribe)
|
113
114
|
format.json { render json: subscribe_task.to_json, status: :ok }
|
114
115
|
else
|
115
|
-
format.json { render json: 'No Product selected'
|
116
|
+
format.json { render json: { error: 'No Product selected' }, status: :expectation_failed }
|
116
117
|
end
|
117
118
|
end
|
118
119
|
rescue ::Foreman::Exception => e
|
@@ -132,7 +133,8 @@ module Api
|
|
132
133
|
:base_url,
|
133
134
|
:interval,
|
134
135
|
:sync_date,
|
135
|
-
:organization_id
|
136
|
+
:organization_id,
|
137
|
+
:katello_gpg_key_id
|
136
138
|
)
|
137
139
|
end
|
138
140
|
|
@@ -1,12 +1,19 @@
|
|
1
1
|
class SccAccountsController < ApplicationController
|
2
|
+
helper_method :scc_filtered_products
|
2
3
|
before_action :find_organization
|
3
4
|
before_action :find_resource, only: %i[show edit update destroy sync bulk_subscribe]
|
5
|
+
before_action :find_available_gpg_keys, only: %i[new edit]
|
4
6
|
include Foreman::Controller::AutoCompleteSearch
|
5
7
|
|
6
8
|
# GET /scc_accounts
|
7
9
|
def index
|
8
|
-
@scc_accounts = resource_base.
|
9
|
-
.
|
10
|
+
@scc_accounts = resource_base.where(organization: @organization)
|
11
|
+
.search_for(params[:search], order: params[:order])
|
12
|
+
.paginate(:page => params[:page], :per_page => params[:per_page])
|
13
|
+
# overwrite the product list with filtered products that do not include products with empty repositories
|
14
|
+
@scc_accounts.each do |scc_account|
|
15
|
+
scc_account.scc_products_with_repos_count = scc_account.scc_products.only_products_with_repos.count
|
16
|
+
end
|
10
17
|
end
|
11
18
|
|
12
19
|
# GET /scc_accounts/new
|
@@ -92,6 +99,11 @@ class SccAccountsController < ApplicationController
|
|
92
99
|
|
93
100
|
private
|
94
101
|
|
102
|
+
def find_available_gpg_keys
|
103
|
+
@scc_account ? org = @scc_account.organization : org = @organization
|
104
|
+
@selectable_gpg_keys = ::Katello::GpgKey.where(organization: org).collect { |p| [p.name, p.id] }.unshift ['None', nil]
|
105
|
+
end
|
106
|
+
|
95
107
|
def find_organization
|
96
108
|
@organization = Organization.current
|
97
109
|
redirect_to '/select_organization?toState=' + request.path unless @organization
|
@@ -108,7 +120,8 @@ class SccAccountsController < ApplicationController
|
|
108
120
|
:base_url,
|
109
121
|
:interval,
|
110
122
|
:sync_date,
|
111
|
-
:organization_id
|
123
|
+
:organization_id,
|
124
|
+
:katello_gpg_key_id
|
112
125
|
)
|
113
126
|
end
|
114
127
|
|
@@ -121,9 +134,22 @@ class SccAccountsController < ApplicationController
|
|
121
134
|
when 'sync', 'test_connection'
|
122
135
|
:sync
|
123
136
|
when 'bulk_subscribe'
|
124
|
-
:
|
137
|
+
:use
|
125
138
|
else
|
126
139
|
super
|
127
140
|
end
|
128
141
|
end
|
142
|
+
|
143
|
+
# Function filters a product list and removes all products without valid repositories
|
144
|
+
# The .order call is necessary to apply the ordering to repository that have already been loaded from the database.
|
145
|
+
# Input parameters:
|
146
|
+
# product_list: list of SccProduct
|
147
|
+
# product_type: return only base products if type is set (default), else all
|
148
|
+
def scc_filtered_products(product_list, product_type = 'base')
|
149
|
+
if product_type == 'base'
|
150
|
+
product_list.only_products_with_repos.where(product_type: 'base').order(:friendly_name)
|
151
|
+
else
|
152
|
+
product_list.only_products_with_repos.order(:friendly_name)
|
153
|
+
end
|
154
|
+
end
|
129
155
|
end
|
@@ -8,27 +8,38 @@ module Actions
|
|
8
8
|
.info("Initiating subscription for SccProduct '#{scc_product.friendly_name}'.")
|
9
9
|
sequence do
|
10
10
|
product_create_action = plan_action(CreateProduct,
|
11
|
-
product_name
|
12
|
-
product_description
|
13
|
-
organization_id
|
11
|
+
:product_name => scc_product.pretty_name,
|
12
|
+
:product_description => scc_product.pretty_description,
|
13
|
+
:organization_id => scc_product.organization.id,
|
14
|
+
:gpg_key => scc_product.scc_account.katello_gpg_key_id)
|
15
|
+
katello_repos = {}
|
14
16
|
scc_product.scc_repositories.each do |repo|
|
15
|
-
uniq_name = scc_product.uniq_name + ' ' + repo.description
|
16
17
|
arch = scc_product.arch || 'noarch'
|
17
|
-
plan_action(CreateRepository,
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
repo_create_action = plan_action(CreateRepository,
|
19
|
+
:product_id => product_create_action.output[:product_id],
|
20
|
+
:uniq_name => repo.uniq_name(scc_product),
|
21
|
+
:pretty_repo_name => repo.pretty_name,
|
22
|
+
:url => repo.full_url,
|
23
|
+
:arch => arch)
|
24
|
+
katello_repos[repo.id] = repo_create_action.output[:katello_root_repository_id]
|
22
25
|
end
|
26
|
+
# connect action to resource (=> make parameters accessable in input)
|
23
27
|
action_subject(scc_product, product_id: product_create_action.output[:product_id])
|
28
|
+
input.update(katello_repos: katello_repos)
|
24
29
|
plan_self
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
28
33
|
def finalize
|
34
|
+
# connect Scc products and Katello products
|
29
35
|
scc_product = SccProduct.find(input[:scc_product][:id])
|
30
36
|
product = ::Katello::Product.find(input[:product_id])
|
31
37
|
scc_product.update!(product: product)
|
38
|
+
# extract Katello repo ids from input hash and store to database
|
39
|
+
input[:katello_repos].each do |scc_repo_id, katello_root_repository_id|
|
40
|
+
scc_repo = SccRepository.find(scc_repo_id)
|
41
|
+
scc_repo.update!(katello_root_repository_id: katello_root_repository_id)
|
42
|
+
end
|
32
43
|
end
|
33
44
|
|
34
45
|
def humanized_name
|
@@ -43,6 +54,7 @@ module Actions
|
|
43
54
|
def create_sub_plans
|
44
55
|
product = ::Katello::Product.new
|
45
56
|
product.name = input[:product_name]
|
57
|
+
product.gpg_key = ::Katello::GpgKey.find_by(id: input[:gpg_key], organization: input[:organization_id])
|
46
58
|
product.description = input[:product_description]
|
47
59
|
trigger(::Actions::Katello::Product::Create,
|
48
60
|
product,
|
@@ -58,12 +70,11 @@ module Actions
|
|
58
70
|
|
59
71
|
def create_sub_plans
|
60
72
|
product = ::Katello::Product.find(input[:product_id])
|
61
|
-
|
62
|
-
label = ::Katello::Util::Model.labelize(uniq_name)
|
73
|
+
label = ::Katello::Util::Model.labelize(input[:uniq_name])
|
63
74
|
unprotected = true
|
64
75
|
gpg_key = product.gpg_key
|
65
76
|
repo_param = { :label => label,
|
66
|
-
:name =>
|
77
|
+
:name => input[:pretty_repo_name],
|
67
78
|
:url => input[:url],
|
68
79
|
:content_type => 'yum',
|
69
80
|
:unprotected => unprotected,
|
@@ -73,7 +84,9 @@ module Actions
|
|
73
84
|
repository = product.add_repo(repo_param)
|
74
85
|
repository.mirror_on_sync = true
|
75
86
|
repository.verify_ssl_on_sync = true
|
76
|
-
trigger(::Actions::Katello::Repository::CreateRoot, repository)
|
87
|
+
trigger(::Actions::Katello::Repository::CreateRoot, repository).tap do
|
88
|
+
output[:katello_root_repository_id] = repository.id
|
89
|
+
end
|
77
90
|
end
|
78
91
|
end
|
79
92
|
end
|
@@ -1,21 +1,21 @@
|
|
1
1
|
module Actions
|
2
2
|
module SccManager
|
3
|
+
# for dynflow documentation see here: https://dynflow.github.io/documentation/
|
3
4
|
class Sync < Actions::EntryAction
|
4
5
|
def plan(scc_account)
|
5
6
|
::Foreman::Logging.logger('foreman_scc_manager')
|
6
7
|
.info("Initiating 'sync' for SccAccount '#{scc_account.name}'.")
|
7
8
|
action_subject(scc_account)
|
8
9
|
sequence do
|
9
|
-
|
10
|
-
|
11
|
-
plan_self
|
10
|
+
plan_action(::Actions::SccManager::SyncRepositories, scc_account)
|
11
|
+
plan_action(::Actions::SccManager::SyncProducts, scc_account)
|
12
|
+
plan_self
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
15
16
|
def finalize
|
17
|
+
# this is only executed if run actions of SyncRepositories and SyncProducts were successful
|
16
18
|
scc_account = SccAccount.find(input[:scc_account][:id])
|
17
|
-
raise 'Updating failed' unless input[:repo_status] == 'SUCCESS' && input[:prod_status] == 'SUCCESS'
|
18
|
-
|
19
19
|
scc_account.update! synced: Time.current
|
20
20
|
end
|
21
21
|
|
@@ -13,22 +13,19 @@ module Actions
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def run
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
::Foreman::Logging.logger('foreman_scc_manager').error "Error while syncronizing SCC-Products: #{e}"
|
25
|
-
output[:error] = e.to_s
|
26
|
-
output[:status] = 'FAILURE'
|
27
|
-
end
|
16
|
+
products = ::SccManager.get_scc_data(input.fetch(:base_url),
|
17
|
+
'/connect/organizations/products',
|
18
|
+
input.fetch(:login),
|
19
|
+
decrypt_field(input.fetch(:password)))
|
20
|
+
output[:data] = ::SccManager.sanitize_products(products).values
|
21
|
+
rescue StandardError => e
|
22
|
+
::Foreman::Logging.logger('foreman_scc_manager').error "Error while syncronizing SCC-Products: #{e}"
|
23
|
+
error! e.to_s
|
28
24
|
end
|
29
25
|
|
30
26
|
def finalize
|
31
|
-
|
27
|
+
# this is only executed if 'run' succeeds
|
28
|
+
SccAccount.find(input.fetch(:id)).update_scc_products(output.fetch(:data))
|
32
29
|
end
|
33
30
|
|
34
31
|
def rescue_strategy
|
@@ -12,22 +12,18 @@ module Actions
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def run
|
15
|
-
output[:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
rescue StandardError => e
|
23
|
-
::Foreman::Logging.logger('foreman_scc_manager').error "Error while syncronizing SCC-Repositories: #{e}"
|
24
|
-
output[:error] = e.to_s
|
25
|
-
output[:status] = 'FAILURE'
|
26
|
-
end
|
15
|
+
output[:data] = ::SccManager.get_scc_data(input[:base_url],
|
16
|
+
'/connect/organizations/repositories',
|
17
|
+
input[:login],
|
18
|
+
decrypt_field(input[:password]))
|
19
|
+
rescue StandardError => e
|
20
|
+
::Foreman::Logging.logger('foreman_scc_manager').error "Error while syncronizing SCC-Repositories: #{e}"
|
21
|
+
error! e.to_s
|
27
22
|
end
|
28
23
|
|
29
24
|
def finalize
|
30
|
-
|
25
|
+
# this is only executed if 'run' succeeds
|
26
|
+
SccAccount.find(input[:scc_account][:id]).update_scc_repositories(output[:data])
|
31
27
|
end
|
32
28
|
|
33
29
|
def rescue_strategy
|
data/app/models/scc_account.rb
CHANGED
@@ -2,6 +2,9 @@ class SccAccount < ApplicationRecord
|
|
2
2
|
include Authorizable
|
3
3
|
include Encryptable
|
4
4
|
include ForemanTasks::Concerns::ActionSubject
|
5
|
+
|
6
|
+
attr_accessor :scc_products_with_repos_count
|
7
|
+
|
5
8
|
encrypts :password
|
6
9
|
|
7
10
|
NEVER = 'never'.freeze
|
@@ -173,21 +176,34 @@ class SccAccount < ApplicationRecord
|
|
173
176
|
|
174
177
|
def update_scc_repositories(upstream_repositories)
|
175
178
|
upstream_repo_ids = []
|
179
|
+
# initially invalidate all repositories and validate them during update
|
180
|
+
invalidated_repos = invalidate_subscription_status(scc_repositories)
|
176
181
|
# import repositories
|
177
182
|
upstream_repositories.each do |ur|
|
178
183
|
cached_repository = scc_repositories.find_or_initialize_by(scc_id: ur['id'])
|
179
|
-
cached_repository.name = ur['name']
|
180
184
|
cached_repository.distro_target = ur['distro_target']
|
181
185
|
cached_repository.description = ur['description']
|
182
186
|
cached_repository.url, cached_repository.token = ur['url'].split('?')
|
183
187
|
cached_repository.enabled = ur['enabled']
|
184
188
|
cached_repository.autorefresh = ur['autorefresh']
|
185
189
|
cached_repository.installer_updates = ur['installer_updates']
|
190
|
+
# should be called after all attributes are set in case of dependencies (currently: description)
|
191
|
+
cached_repository.name = cached_repository.pretty_name
|
192
|
+
cached_repository.subscription_valid = true
|
186
193
|
cached_repository.save!
|
187
194
|
upstream_repo_ids << ur['id']
|
195
|
+
# set invalidated record to true, if exists
|
196
|
+
invalidated_repos = revalidate_subscription_status(invalidated_repos, ur[id])
|
188
197
|
end
|
189
198
|
::Foreman::Logging.logger('foreman_scc_manager').debug "Found #{upstream_repo_ids.length} repositories"
|
190
|
-
|
199
|
+
|
200
|
+
# all scc repos that are kept but not available upstream need to be marked invalid
|
201
|
+
# subscription_valid can be set to nil
|
202
|
+
to_invalidate = invalidated_repos.select { |ir| ir.katello_root_repository_id.present? && !ir.subscription_valid }
|
203
|
+
::Foreman::Logging.logger('foreman_scc_manager').debug "Invalidating #{to_invalidate.count} expired repositories"
|
204
|
+
invalidate_subscription_status(to_invalidate, true)
|
205
|
+
|
206
|
+
# delete repositories being removed upstream and that are not subscribed to
|
191
207
|
to_delete = scc_repositories.where.not(scc_id: upstream_repo_ids)
|
192
208
|
::Foreman::Logging.logger('foreman_scc_manager').debug "Deleting #{to_delete.count} old repositories"
|
193
209
|
to_delete.destroy_all
|
@@ -195,10 +211,11 @@ class SccAccount < ApplicationRecord
|
|
195
211
|
|
196
212
|
def update_scc_products(upstream_products)
|
197
213
|
upstream_product_ids = []
|
214
|
+
# initially invalidate all products and validate them during update
|
215
|
+
invalidated_products = invalidate_subscription_status(scc_products)
|
198
216
|
# import products
|
199
217
|
upstream_products.each do |up|
|
200
218
|
cached_product = scc_products.find_or_initialize_by(scc_id: up['id'])
|
201
|
-
cached_product.name = up['name']
|
202
219
|
cached_product.version = up['version']
|
203
220
|
cached_product.arch = up['arch']
|
204
221
|
cached_product.description = up['description']
|
@@ -206,12 +223,25 @@ class SccAccount < ApplicationRecord
|
|
206
223
|
cached_product.product_type = up['product_type']
|
207
224
|
cached_product.scc_repositories =
|
208
225
|
scc_repositories.where(scc_id: up['repositories'].map { |repo| repo['id'] })
|
226
|
+
# name should be set after friendly_name because it depends on friendly_name
|
227
|
+
cached_product.name = cached_product.pretty_name
|
228
|
+
cached_product.description = cached_product.pretty_description
|
229
|
+
cached_product.subscription_valid = true
|
209
230
|
cached_product.save!
|
210
231
|
upstream_product_ids << up['id']
|
232
|
+
# set invalidated record to true, if exists
|
233
|
+
invalidated_products = revalidate_subscription_status(invalidated_products, up['id'])
|
211
234
|
end
|
212
235
|
::Foreman::Logging.logger('foreman_scc_manager').debug "Found #{upstream_product_ids.length} products"
|
213
|
-
|
214
|
-
|
236
|
+
|
237
|
+
# all scc products that are kept but not available upstream need to be marked invalid
|
238
|
+
# subscription_valid can be set to nil
|
239
|
+
to_invalidate = invalidated_products.select { |ip| ip.product_id.present? && !ip.subscription_valid }
|
240
|
+
::Foreman::Logging.logger('foreman_scc_manager').debug "Invalidating #{to_invalidate.count} expired products"
|
241
|
+
invalidate_subscription_status(to_invalidate, true)
|
242
|
+
|
243
|
+
# delete products being removed upstream and that are not subscribed to
|
244
|
+
to_delete = scc_products.where.not(scc_id: upstream_product_ids).where(product_id: nil)
|
215
245
|
::Foreman::Logging.logger('foreman_scc_manager').debug "Deleting #{to_delete.count} old products"
|
216
246
|
to_delete.destroy_all
|
217
247
|
# rewire product to product relationships
|
@@ -224,4 +254,32 @@ class SccAccount < ApplicationRecord
|
|
224
254
|
end
|
225
255
|
end
|
226
256
|
end
|
257
|
+
|
258
|
+
# validate the subscription status of a product/repo
|
259
|
+
# no saving to database
|
260
|
+
# params: elements: scc repos or products, Array or ActiveRecord_(*)
|
261
|
+
# scc_id: scc_id of the element that should be revalidated
|
262
|
+
# return: elements where for the element with scc_id subscription_valid is true
|
263
|
+
def revalidate_subscription_status(elements, scc_id)
|
264
|
+
return nil if elements.nil?
|
265
|
+
|
266
|
+
revalidate = elements.find { |e| e.scc_id == scc_id }
|
267
|
+
revalidate.subscription_valid = true unless revalidate.nil?
|
268
|
+
# return modified list
|
269
|
+
elements
|
270
|
+
end
|
271
|
+
|
272
|
+
# set all products/repos invalid
|
273
|
+
# params: items_to_invalidate: ActiveRecord_(*)
|
274
|
+
# save_record: store in database or not (default)
|
275
|
+
# return: ActiveRecord elements with invalidated subscription status
|
276
|
+
def invalidate_subscription_status(items_to_invalidate, save_record = false)
|
277
|
+
if items_to_invalidate.present?
|
278
|
+
items_to_invalidate.each do |inv|
|
279
|
+
inv.subscription_valid = false
|
280
|
+
inv.save! if save_record
|
281
|
+
end
|
282
|
+
end
|
283
|
+
items_to_invalidate
|
284
|
+
end
|
227
285
|
end
|