Skip to content

Commit

Permalink
[TEAMCITY-QA-T] Add ability to ignore -staging postfix @ Size Valid…
Browse files Browse the repository at this point in the history
…ation (#109)

* Update registry accessor to ignore 'staging'

* Add option al 'ignoreStaging' argument

* Add docstring.
  • Loading branch information
AndreyKoltsov1997 authored Sep 15, 2023
1 parent 906898a commit f34b5b7
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,23 @@ class ValidateImage : Subcommand("validate", "Validate Docker Image with (option
* Execute image validation option specified via CLI.
*/
override fun execute() {

// 1. Capture current image size
val originalImageName = validationArgs[0]

val image = validationArgs[0]
val username = if (validationArgs.size > 1) validationArgs[1] else null
val token = if (validationArgs.size > 2) validationArgs[2] else null
val credentials: DockerhubCredentials = getDockerhubCredentials(username, token)


val percentageChangeThreshold = ValidationConstants.ALLOWED_IMAGE_SIZE_INCREASE_THRESHOLD_PERCENT
val imagesFailedValidation = DockerImageValidationUtilities.validateImageSize(
originalImageName,
"https://hub.docker.com/v2",
percentageChangeThreshold,
credentials
originalImageFqdn = image,
registryUri = "https://hub.docker.com/v2",
threshold = ValidationConstants.ALLOWED_IMAGE_SIZE_INCREASE_THRESHOLD_PERCENT,
credentials = getDockerhubCredentials(username, token),
ignoreStaging = true
)

if (imagesFailedValidation.isNotEmpty()) {
imagesFailedValidation.forEach {
println("Validation failed for ${originalImageName}, OS: ${it.os}, OS version: ${it.osVersion}, architecture: ${it.architecture}")
println("Validation failed for ${image}, OS: ${it.os}, OS version: ${it.osVersion}, architecture: ${it.architecture}")
}
// throw exception in order to handle it within upstream DSL
throw DockerImageValidationException("Validation had failed for $originalImageName")
throw DockerImageValidationException("Validation had failed for $image")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ object ValidationConstants {
const val ALLOWED_IMAGE_SIZE_INCREASE_THRESHOLD_PERCENT = 5.0f
const val PRE_PRODUCTION_IMAGE_PREFIX = "EAP"
const val LATEST = "latest"
const val STAGING_POSTFIX = "-staging"
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.jetbrains.teamcity.common.network

import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import java.io.IOException
import java.net.ConnectException
import java.net.URI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,26 @@ import java.net.http.HttpResponse
* @param uri - Docker Registry URI
* @param credentials - (optional) - credentials for the access of Dockerhub REST API
*/
class DockerRegistryAccessor(private val uri: String, credentials: DockerhubCredentials?) {

class DockerRegistryAccessor(private val uri: String,
private val ignoreStaging: Boolean,
credentials: DockerhubCredentials?) {
private val httpRequestsUtilities: HttpRequestsUtilities = HttpRequestsUtilities()
private val token: String?
private val jsonSerializer: Json
private val jsonSerializer: Json = Json {
// -- remove the necessity to include parsing of unused fields
ignoreUnknownKeys = true
// -- parse JSON fields that don't have an assigned serializer into a String, e.g.: Number
isLenient = true
}


init {
this.jsonSerializer = Json {
// -- remove the necessity to include parsing of unused fields
ignoreUnknownKeys = true
// -- parse JSON fields that don't have an assigned serializer into a String, e.g.: Number
isLenient = true
}
this.token = if (credentials != null && credentials.isUsable()) this.getPersonalAccessToken(credentials) else ""
}

constructor(uri: String, credentials: DockerhubCredentials?) : this(uri, false, credentials)


/**
* Returns general information about Docker Repository.
* @param image image for which the "repository" (all associated images: OS, OS Version, arch.) would be ...
Expand All @@ -59,9 +63,10 @@ class DockerRegistryAccessor(private val uri: String, credentials: DockerhubCred
* @param pageSize maximal amount of images to be included into Dockerhub's response
*/
fun getInfoAboutImagesInRegistry(image: DockerImage, pageSize: Int): DockerRegistryInfoAboutImages? {
val repo = if (ignoreStaging) image.repo.replace(ValidationConstants.STAGING_POSTFIX, "") else image.repo
val registryResponse: HttpResponse<String?> = httpRequestsUtilities.getJsonWithAuth(
"${this.uri}/repositories"
+ "/${image.repo}/tags?page_size=$pageSize", this.token
+ "/${repo}/tags?page_size=$pageSize", this.token
)
val result = registryResponse.body() ?: ""

Expand Down Expand Up @@ -105,8 +110,7 @@ class DockerRegistryAccessor(private val uri: String, credentials: DockerhubCred
.filter { return@filter isSameDistribution(currentImage.tag, it.name) }
// Sort based on tag
.sortedWith { lhs, rhs -> imageTagComparator(lhs.name, rhs.name) }
.last()

.lastOrNull() ?: throw RuntimeException("Previous images weren't found for $currentImage")

// -- 1. Filter by OS type
previousImageRepository.images = previousImageRepository.images.filter { it.os == targetOs }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,17 @@ class DockerImageValidationUtilities {
* 4. Compare the size of each corresponding image.
* @param originalImageFqdn fully-qualified domain name of the original image
* @param registryUri URI of Docker Registry where image is placed
* @param ignoreStaging if true, staging images would be compared to production ones
* @returns list of associated images that didn't pass the validation.
*/
fun validateImageSize(
originalImageFqdn: String,
registryUri: String,
threshold: Float,
credentials: DockerhubCredentials?
credentials: DockerhubCredentials?,
ignoreStaging: Boolean
): ArrayList<DockerhubImage> {
val registryAccessor = DockerRegistryAccessor(registryUri, credentials)
val registryAccessor = DockerRegistryAccessor(registryUri, ignoreStaging, credentials)

val currentImage = DockerImage(originalImageFqdn)
val imagesFailedValidation = ArrayList<DockerhubImage>()
Expand Down

0 comments on commit f34b5b7

Please sign in to comment.