foreman_scc_manager 1.8.3 → 1.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -0
- 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 +36 -25
- 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 +33 -14
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 2d51eed6c2336237f44aa0fad512060a43f4bc0dae6fd9a93daa2baa555f915a
         | 
| 4 | 
            +
              data.tar.gz: 876ebdd4e76443deec6016c657b44ddcb1e60dcc2c8a81631e5f87cccafcc9b1
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ef379e703604fc444d312969f4dd389c952b03dc3f3d5ba98d95989941c9b397b7879bef97d309ae54270f70ffb5b1ef50ee1ba214571800dc82f2ea7d301bd7
         | 
| 7 | 
            +
              data.tar.gz: 70c8ddeef5a5ad620dfb6fe1ed3b2296e56cef24be9fc3b07223bc2978b5fb0f116d996bddea4e0bc50db1accef6a82ed263183d13fad7d23a56a9c15da077fc
         | 
    
        data/README.md
    CHANGED
    
    | @@ -13,6 +13,8 @@ for how to install Foreman plugins | |
| 13 13 |  | 
| 14 14 | 
             
            | Foreman Version | Katello Version | Plugin Version |
         | 
| 15 15 | 
             
            | --------------- | --------------- | -------------- |
         | 
| 16 | 
            +
            | 2.1             | 3.16            | ~> 1.8.5       |
         | 
| 17 | 
            +
            | 2.0             | 3.16            | ~> 1.8.4       |
         | 
| 16 18 | 
             
            | 1.24            | 3.14            | ~> 1.8.0       |
         | 
| 17 19 | 
             
            | 1.22            | 3.12            | ~> 1.7.0       |
         | 
| 18 20 | 
             
            | 1.21            | 3.10            | ~> 1.6.0       |
         | 
| @@ -23,6 +25,9 @@ for how to install Foreman plugins | |
| 23 25 | 
             
            | 1.16            | 3.5             | <= 1.3.0       |
         | 
| 24 26 | 
             
            | 1.15            | 3.4             | ~> 1.1.0       |
         | 
| 25 27 |  | 
| 28 | 
            +
            ## Documentation
         | 
| 29 | 
            +
            The plugin documentation can be found at https://docs.orcharhino.com/sources/management_ui/the_content_menu/suse_subscriptions.html.
         | 
| 30 | 
            +
             | 
| 26 31 | 
             
            ## Contributing
         | 
| 27 32 |  | 
| 28 33 | 
             
            Fork and send a Pull Request. Thanks!
         | 
| @@ -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
         |