diff --git a/ee/app/services/security/analyzers_status/update_service.rb b/ee/app/services/security/analyzers_status/update_service.rb index 11db9808c438a4284c6ef602ca11b378c4530d9d..841bc08b5968227a30c341b40f86917c8ef468b2 100644 --- a/ee/app/services/security/analyzers_status/update_service.rb +++ b/ee/app/services/security/analyzers_status/update_service.rb @@ -129,8 +129,6 @@ def aggregated_statuses(analyzers_statuses) end def upsert_analyzers_statuses - return unless analyzers_statuses.present? - AnalyzerProjectStatus.upsert_all(analyzers_statuses.values, unique_by: [:project_id, :analyzer_type]) InventoryFilters::AnalyzerStatusUpdateService.execute([project], analyzers_statuses.values) end diff --git a/ee/app/services/security/inventory_filters/analyzer_status_update_service.rb b/ee/app/services/security/inventory_filters/analyzer_status_update_service.rb index d854a2db9df41002129cc71dde3e3d6e2aa9d48f..ae7728826320e901b02848c57da4538468b8ea44 100644 --- a/ee/app/services/security/inventory_filters/analyzer_status_update_service.rb +++ b/ee/app/services/security/inventory_filters/analyzer_status_update_service.rb @@ -25,18 +25,23 @@ def execute attr_reader :projects, :analyzer_statuses, :analyzer_type def upsert_inventory_filters_analyzer_statuses - return if inventory_filters_data.empty? - - grouped_by_keys = inventory_filters_data.group_by do |record| - analyzer_keys = record.keys.select { |k| k.in?(Enums::Security.extended_analyzer_types.keys) } - analyzer_keys.sort - end - - # upsert in groups based on analyzers records keys. There should be a single update for single project, - # and upto 2 updated for many projects because the bulk setting based update can only pass - # setting type and the aggregated type as input to this service. - grouped_by_keys.each_value do |records| - Security::InventoryFilter.upsert_all(records, unique_by: :project_id) + if inventory_filters_data.empty? && analyzer_statuses.present? + # NO-OP, this means there were projects and analyzer_statuses, but they didn't match up + elsif inventory_filters_data.empty? + # we need to create blank filter records for projects that don't have any analyzer_statuses + Security::InventoryFilter.upsert_all(projects_with_no_analyzer_statuses, unique_by: :project_id) + else + grouped_by_keys = inventory_filters_data.group_by do |record| + analyzer_keys = record.keys.select { |k| k.in?(Enums::Security.extended_analyzer_types.keys) } + analyzer_keys.sort + end + + # upsert in groups based on analyzers records keys. There should be a single update for single project, + # and upto 2 updated for many projects because the bulk setting based update can only pass + # setting type and the aggregated type as input to this service. + grouped_by_keys.each_value do |records| + Security::InventoryFilter.upsert_all(records, unique_by: :project_id) + end end end @@ -56,12 +61,18 @@ def inventory_filters_data end end + def projects_with_no_analyzer_statuses + projects.filter_map do |project| + build_inventory_filter_for_project(project.id, {}) + end + end + def grouped_analyzer_statuses @grouped_analyzer_statuses ||= analyzer_statuses.group_by { |status| status[:project_id] } end def build_inventory_filter_for_project(project_id, statuses) - return unless project_id.present? && statuses.present? + return unless project_id.present? project_attributes = project_id_to_attributes[project_id] return unless project_attributes.present? diff --git a/ee/spec/services/security/analyzers_status/update_service_spec.rb b/ee/spec/services/security/analyzers_status/update_service_spec.rb index 19fb8e35235a18e7cf24e8ee14098d4c77dcbbde..d01e954a0ae86844a5cb3238a8130073c6de01bb 100644 --- a/ee/spec/services/security/analyzers_status/update_service_spec.rb +++ b/ee/spec/services/security/analyzers_status/update_service_spec.rb @@ -359,7 +359,14 @@ }.from(nil).to('not_configured') end - include_examples 'does not call inventory filters service' + it 'calls InventoryFilters service with pipeline and aggregated statuses' do + expect(inventory_filters_update_service).to receive(:execute).once.with( + [project], [] + ) + + execute + end + include_examples 'calls namespace related services' end diff --git a/ee/spec/services/security/inventory_filters/analyzer_status_update_service_spec.rb b/ee/spec/services/security/inventory_filters/analyzer_status_update_service_spec.rb index 091b4805161ab80cc036c5ab2f2ba5b01b6e78c8..18a96facdc65006a2b6af4184696fdd659e1a9c2 100644 --- a/ee/spec/services/security/inventory_filters/analyzer_status_update_service_spec.rb +++ b/ee/spec/services/security/inventory_filters/analyzer_status_update_service_spec.rb @@ -82,8 +82,8 @@ context 'when analyzer_statuses is empty' do let(:analyzer_statuses) { [] } - it 'returns early' do - expect { service.execute }.not_to change { Security::InventoryFilter.count } + it 'processes the project' do + expect { service.execute }.to change { Security::InventoryFilter.count } end end