Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion modules/fundamental/src/purl/service/gc_purls.sql
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
WITH
alive_qualified_purl AS (
SELECT DISTINCT t2.id, t2.versioned_purl_id
(
SELECT t2.id, t2.versioned_purl_id
FROM sbom_package_purl_ref AS t1
INNER JOIN qualified_purl AS t2
ON t2.id = t1.qualified_purl_id
)
UNION
(
SELECT t1.id, t1.versioned_purl_id
FROM qualified_purl AS t1
INNER JOIN versioned_purl AS t2 ON t2.id = t1.versioned_purl_id
INNER JOIN (
SELECT DISTINCT base_purl_id
FROM purl_status
) AS t3 ON t2.base_purl_id = t3.base_purl_id
)
),
alive_versioned_purl AS (
SELECT DISTINCT t2.id, t2.base_purl_id
Expand Down
48 changes: 34 additions & 14 deletions modules/fundamental/src/purl/service/test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{
advisory::service::AdvisoryService,
purl::{model::details::purl::StatusContext, service::PurlService},
sbom::service::SbomService,
};
Expand Down Expand Up @@ -702,7 +701,7 @@ async fn contextual_status(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {

#[test_context(TrustifyContext)]
#[test(actix_web::test)]
async fn gc_purls(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
async fn gc_purls_from_sbom(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
let purl_service = PurlService::new();
assert_eq!(
0,
Expand Down Expand Up @@ -742,27 +741,18 @@ async fn gc_purls(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
);

// delete the sbom...
async fn delete_sbom_and_advisories(
ctx: &TrustifyContext,
id: Id,
) -> Result<(), anyhow::Error> {
async fn delete_sbom(ctx: &TrustifyContext, id: Id) -> Result<(), anyhow::Error> {
let svc = SbomService::new(ctx.db.clone());
let sbom = svc
.fetch_sbom_details(id, vec![], &ctx.db)
.await?
.expect("fetch_sbom");
assert!(svc.delete_sbom(sbom.summary.head.id, &ctx.db).await?);

// delete the advisories in the sbom...
let svc = AdvisoryService::new(ctx.db.clone());
for a in sbom.advisories {
assert!(svc.delete_advisory(a.head.uuid, &ctx.db).await?);
}
Ok(())
}

// delete the ubi sbom....
delete_sbom_and_advisories(ctx, ubi9_sbom.id).await?;
delete_sbom(ctx, ubi9_sbom.id).await?;

// it should leave behind orphaned purls
let result = purl_service
Expand All @@ -781,7 +771,7 @@ async fn gc_purls(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
assert_eq!(880, result.items.len());

// delete the quarkus sbom....
delete_sbom_and_advisories(ctx, quarkus_sbom.id).await?;
delete_sbom(ctx, quarkus_sbom.id).await?;

// it should leave behind orphaned purls
let result = purl_service
Expand All @@ -801,6 +791,36 @@ async fn gc_purls(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
Ok(())
}

#[test_context(TrustifyContext)]
#[test(actix_web::test)]
async fn gc_purls_from_single_csaf(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
let purl_service = PurlService::new();
assert_eq!(
0,
purl_service
.purls(Query::default(), Paginated::default(), &ctx.db)
.await?
.items
.len()
);

ctx.ingest_document("../datasets/ds1/csaf/2023/cve-2023-2798.json")
.await?;

assert_eq!(
6,
purl_service
.purls(Query::default(), Paginated::default(), &ctx.db)
.await?
.items
.len()
);

assert_eq!(0, purl_service.gc_purls(&ctx.db).await?);

Ok(())
}

async fn ingest_some_log4j_data(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
let log4j = ctx
.graph
Expand Down