Cleanup all other resources when deleting an image

This commit is contained in:
SeanOMik 2023-04-18 00:47:13 -04:00
parent 82774a4931
commit 3d70301c54
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
3 changed files with 48 additions and 12 deletions

View File

@ -132,13 +132,27 @@ pub async fn delete_manifest(path: web::Path<(String, String)>, req: HttpRequest
let _authorization = headers.get("Authorization").unwrap(); // TODO:
let database = &state.database;
let digest = match Digest::is_digest(&reference) {
true => {
// Check if the manifest exists
if database.get_manifest(&name, &reference).await.unwrap().is_none() {
return HttpResponse::NotFound()
.finish();
}
// If `reference` is a digest, then we're deleting a manifest, else a tag
if Digest::is_digest(&reference) {
database.delete_manifest(&name, &reference).await.unwrap();
} else {
database.delete_tag(&name, &reference).await.unwrap();
}
reference.clone()
},
false => {
if let Some(tag) = database.get_tag(&name, &reference).await.unwrap() {
tag.manifest_digest
} else {
return HttpResponse::NotFound()
.finish();
}
}
};
database.delete_manifest(&name, &digest).await.unwrap();
HttpResponse::Accepted()
.append_header(("Content-Length", "None"))

View File

@ -27,7 +27,7 @@ pub trait Database {
/// Replace the uuid with a digest
async fn replace_digest(&self, uuid: &str, new_digest: &str) -> sqlx::Result<()>;
async fn link_manifest_layer(&self, manifest_digest: &str, layer_digest: &str) -> sqlx::Result<()>;
async fn unlink_manifest_layer(&self, repository: &str, layer_digest: &str) -> sqlx::Result<()>;
async fn unlink_manifest_layer(&self, manifest_digest: &str, layer_digest: &str) -> sqlx::Result<()>;
// Tag related functions
@ -147,13 +147,13 @@ impl Database for Pool<Sqlite> {
Ok(())
}
async fn unlink_manifest_layer(&self, repository: &str, layer_digest: &str) -> sqlx::Result<()> {
sqlx::query("DELETE FROM manifest_layers WHERE layer_digest = ? AND manifest IN (SELECT digest FROM image_manifests WHERE repository = ?) RETURNING manifest, layer_digest")
async fn unlink_manifest_layer(&self, manifest_digest: &str, layer_digest: &str) -> sqlx::Result<()> {
sqlx::query("DELETE FROM manifest_layers WHERE manifest = ? AND layer_digest = ?")
.bind(manifest_digest)
.bind(layer_digest)
.bind(repository)
.execute(self).await?;
debug!("Removed link of layer {} from manifest in {} repository", layer_digest, repository);
debug!("Removed link between manifest {} and layer {}", manifest_digest, layer_digest);
Ok(())
}
@ -275,6 +275,28 @@ impl Database for Pool<Sqlite> {
.bind(repository)
.execute(self).await?;
debug!("Deleted manifest {} in repository {}", digest, repository);
let rows: Vec<(String, )> = sqlx::query_as("DELETE FROM manifest_layers WHERE manifest = ? RETURNING layer_digest")
.bind(digest)
.fetch_all(self).await?;
debug!("Unlinked manifest {} from all linked layers", digest);
for row in rows.into_iter() {
let layer_digest = row.0;
self.delete_digest(&layer_digest).await?;
}
debug!("Deleted all digests for manifest {}", digest);
sqlx::query("DELETE FROM image_tags where image_manifest = ?")
.bind(digest)
.execute(self).await?;
debug!("Deleted all image tags for manifest {}", digest);
Ok(())
}

View File

@ -55,7 +55,7 @@ async fn main() -> std::io::Result<()> {
.service(api::manifests::upload_manifest)
.service(api::manifests::pull_manifest)
.service(api::manifests::manifest_exists)
.service(api::manifests::delete_manifest)
.service(api::manifests::delete_manifest) // delete image
)
.service(
web::scope("/blobs")