Skip to content

Commit

Permalink
Merge pull request #180 from sonatype/NEXUS-42440-add-base-image-refe…
Browse files Browse the repository at this point in the history
…rence

NEXUS-42440 add base image reference
  • Loading branch information
codetreras authored May 6, 2024
2 parents 120f56e + 6a5bef2 commit 210ced0
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 2 deletions.
14 changes: 13 additions & 1 deletion Jenkinsfile-Internal-Release
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ node('ubuntu-zion') {
if (params.java_version == OPENJDK11) {
dockerfilePath = 'Dockerfile.java11'
}
def hash = OsTools.runSafe(this, "docker build --quiet --no-cache --tag ${imageName} . -f ${dockerfilePath}")
def baseImage = extractBaseImage(dockerfilePath)
def baseImageRefFactory = load 'scripts/BaseImageReference.groovy'
def baseImageReference = baseImageRefFactory.build(this, baseImage as String)
def baseImageReferenceStr = baseImageReference.getReference()
def hash = OsTools.runSafe(this, "docker build --quiet --label base-image-ref='${baseImageReferenceStr}' --no-cache --tag ${imageName} . -f ${dockerfilePath}")
imageId = hash.split(':')[1]
}
if (params.scan_for_policy_violations) {
Expand Down Expand Up @@ -156,3 +160,11 @@ def getSha(url) {
).trim()
return sha
}

def extractBaseImage (dockerFileLocation) {
def dockerFile = readFile(file: dockerFileLocation)
def baseImageRegex = "FROM\\s+([^\\s]+)"
def usedImages = dockerFile =~ baseImageRegex

return usedImages[0][1]
}
14 changes: 13 additions & 1 deletion Jenkinsfile-Release
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ node('ubuntu-zion') {
if (params.java_version == OPENJDK11) {
dockerfilePath = 'Dockerfile.java11'
}
def hash = OsTools.runSafe(this, "docker build --quiet --no-cache --tag ${imageName} . -f ${dockerfilePath}")
def baseImage = extractBaseImage(dockerfilePath)
def baseImageRefFactory = load 'scripts/BaseImageReference.groovy'
def baseImageReference = baseImageRefFactory.build(this, baseImage as String)
def baseImageReferenceStr = baseImageReference.getReference()
def hash = OsTools.runSafe(this, "docker build --quiet --label base-image-ref='${baseImageReferenceStr}' --no-cache --tag ${imageName} . -f ${dockerfilePath}")
imageId = hash.split(':')[1]

if (currentBuild.result == 'FAILURE') {
Expand Down Expand Up @@ -295,3 +299,11 @@ def updateRepositoryCookbookVersion(dockerFileLocation) {

writeFile(file: dockerFileLocation, text: dockerFile)
}

def extractBaseImage (dockerFileLocation) {
def dockerFile = readFile(file: dockerFileLocation)
def baseImageRegex = "FROM\\s+([^\\s]+)"
def usedImages = dockerFile =~ baseImageRegex

return usedImages[0][1]
}
168 changes: 168 additions & 0 deletions scripts/BaseImageReference.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright (c) 2016-present Sonatype, Inc. All rights reserved.
* Includes the third-party code listed at http://links.sonatype.com/products/nexus/attributions.
* "Sonatype" is a trademark of Sonatype, Inc.
*/

interface BaseImageReference
{
String getReference()

String getReference(String registryName)
}

class DefaultBaseImageReference
implements BaseImageReference
{
private String baseImage

private DockerImageHelper dockerImageHelper

DefaultBaseImageReference(String baseImage, DockerImageHelper dockerImageHelper) {
this.baseImage = baseImage
this.dockerImageHelper = dockerImageHelper
}

String getReference(String registryName = null) {
def imageDigest = dockerImageHelper.getImageFirstRepoDigest(baseImage)
if (imageDigest == null) {
return baseImage
}
return imageDigest
}
}

class RedHatBaseImageReference
implements BaseImageReference
{
final static RED_HAT_REGISTRY = "registry.access.redhat.com"

private String baseImage

private DockerImageHelper dockerImageHelper

private steps

RedHatBaseImageReference(String baseImage, DockerImageHelper dockerImageHelper, steps) {
this.baseImage = baseImage
this.dockerImageHelper = dockerImageHelper
this.steps = steps
}

String getReference(String registryName = RED_HAT_REGISTRY) {
def repoName = extractRedHatRepoName(baseImage, registryName)
def dockerImageId = dockerImageHelper.getImageId(baseImage)
if (repoName == null || dockerImageId == null) {
return null
}

def imageId = getRedHatImageId(dockerImageId)
def repoId = getRedHatRepoId(repoName, registryName)
if (imageId == null || repoId == null) {
def imageDigest = dockerImageHelper.getImageFirstRepoDigest(baseImage)
return imageDigest
}

def imageArch = dockerImageHelper.getImageArchitecture(baseImage)
if (imageArch != null) {
return "https://catalog.redhat.com/software/containers/${repoName}/${repoId}?architecture=${imageArch}&image=${imageId}"
}
else {
return "https://catalog.redhat.com/software/containers/${repoName}/${repoId}?image=${imageId}"
}
}

private static extractRedHatRepoName(baseImage, registryName) {
if (!baseImage.contains(registryName)) {
return null
}
def repositoryRegex = "${registryName}\\/(.*)"
def repository = (baseImage =~ repositoryRegex)[0][1]
return repository
}

private getRedHatImageId(dockerImageId) {
def imageSearchUrl =
"https://catalog.redhat.com/api/containers/v1/images?filter=docker_image_id==\"${dockerImageId}\""
def imageId = steps.sh(
script: "curl -s -L ${imageSearchUrl} | jq -r '.data[0]._id' ",
returnStdout: true
).trim()

return imageId == "null" ? null : imageId
}

private getRedHatRepoId(repoName, registryName) {
def repoSearchUrl =
"https://catalog.redhat.com/api/containers/v1/repositories/registry/${registryName}/repository/${repoName}"
def repoId = steps.sh(
script: "curl -s -L ${repoSearchUrl} | jq -r '._id' ",
returnStdout: true
).trim()

return repoId == "null" ? null : repoId
}
}

class DockerImageHelper
{
private steps

DockerImageHelper(steps) {
this.steps = steps
}

def getImageId(baseImage) {
pullImage(baseImage)
def dockerImageId = steps.sh(
script: "docker image inspect ${baseImage} | jq -r '.[0].Id' ",
returnStdout: true
).trim()
return dockerImageId == "null" ? null : dockerImageId
}

def getImageArchitecture(baseImage) {
pullImage(baseImage)
def imageArch = steps.sh(
script: "docker image inspect ${baseImage} | jq -r '.[0].Architecture' ",
returnStdout: true
).trim()
return imageArch == "null" ? null : imageArch
}

def getImageFirstRepoDigest(baseImage) {
pullImage(baseImage)
def imageDigest = steps.sh(
script: "docker image inspect ${baseImage} | jq -r '.[0].RepoDigests[0]'",
returnStdout: true
).trim()
return imageDigest == "null" ? null : imageDigest
}

private def pullImage(baseImage) {
if (!isPulled(baseImage)) {
steps.sh("docker pull ${baseImage}")
}
}

private def isPulled(baseImage) {
def status = steps.sh(
script: "docker image inspect ${baseImage} 1> /dev/null",
returnStatus: true
)
return status == 0
}
}

static BaseImageReference build(steps, String baseImage) {
def dockerHelper = new DockerImageHelper(steps)

if (baseImage.contains(RedHatBaseImageReference.RED_HAT_REGISTRY)) {
return new RedHatBaseImageReference(baseImage, dockerHelper, steps)
}
else {
return new DefaultBaseImageReference(baseImage, dockerHelper)
}
}

return this

0 comments on commit 210ced0

Please sign in to comment.