Skip to content

Instantly share code, notes, and snippets.

@pere3
Last active December 18, 2020 07:42
Show Gist options
  • Save pere3/15e479f41ac977b40588c6e5e1d1d00f to your computer and use it in GitHub Desktop.
Save pere3/15e479f41ac977b40588c6e5e1d1d00f to your computer and use it in GitHub Desktop.
jenkins shared-library dangled images cleaner / images untag, can be used with gcr.io and other docker-compatible registries
class DockerCleaner {
DockerRegistry dockerRegistry
DockerCleaner(DockerRegistry dockerRegistry) {
this.dockerRegistry = dockerRegistry
}
ArrayList getImageDangledManifests(String imageName) {
def imageTags = dockerRegistry.getImageTags(imageName)
return imageTags.manifest.findAll {
!it.value.tag
}.keySet().collect() as ArrayList
}
void deleteImageDangledManifests(String imageName, ArrayList manifests = []) {
ArrayList dangledManifests = manifests ?: getImageDangledManifests(imageName)
dangledManifests.each { manifest ->
dockerRegistry.deleteManifest(imageName, manifest as String)
}
}
}
import groovy.json.JsonSlurper
class DockerRegistry {
String apiBaseUrl
String apiToken
DockerRegistry(String apiBaseUrl, String apiToken) {
this.apiBaseUrl = apiBaseUrl
this.apiToken = apiToken
}
HashMap getCatalog() {
URL url = new URL(this.apiBaseUrl + "_catalog/")
URLConnection uc = url.openConnection()
uc.setRequestProperty("Authorization", "Bearer ${apiToken}")
HashMap catalog = [
"repositories" : []
]
HashMap catalogPart = new JsonSlurper().parseText(
uc.getInputStream().getText()
) as HashMap
catalog.repositories.addAll(catalogPart.repositories)
while (catalogPart.next) {
url = new URL(catalogPart.next)
uc = url.openConnection()
uc.setRequestProperty("Authorization", "Bearer ${apiToken}")
catalogPart = new JsonSlurper().parseText(
uc.getInputStream().getText()
) as HashMap
catalog.repositories.addAll(catalogPart.repositories)
}
return catalog
}
HashMap untagImage(String imageName, String tagName) {
deleteManifest(imageName, tagName)
}
HashMap deleteManifest(String imageName, String manifestName) {
URL url = new URL(this.apiBaseUrl + imageName + "/manifests/" + manifestName)
HttpURLConnection uc = (HttpURLConnection) url.openConnection()
uc.setRequestProperty("Authorization", "Bearer ${apiToken}")
uc.setRequestMethod("DELETE")
return new JsonSlurper().parseText(
uc.getInputStream().getText()
) as HashMap
}
}
@pere3
Copy link
Author

pere3 commented Aug 20, 2020

Scripted pipeline usage example:

import com.example.docker.DockerCleaner
import com.example.docker.DockerRegistry

String apiBaseUrl = "https://gcr.io/v2/"
String apiToken = "xxx"

DockerRegistry gcrRegistry = new DockerRegistry(apiBaseUrl, apiToken)
DockerCleaner cleaner = new DockerCleaner(gcrRegistry)

def catalog = gcrRegistry.getCatalog()
catalog.repositories.each {
    def dangledManifests = cleaner.getImageDangledManifests(it)
    println("Image: ${it}, dangled manifests: ${dangledManifests}")
    if (dangledManifests) {
        println("Dangled manifests found, removing..")
        cleaner.deleteImageDangledManifests(it, dangledManifests)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment