allow specifying images with localhost/

This commit is contained in:
benniekiss 2024-08-13 14:33:04 -04:00
parent 5ed88d269c
commit 5011d975b6
4 changed files with 81 additions and 19 deletions

6
dist/index.js vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View file

@ -6,8 +6,8 @@ import * as os from "os";
import * as path from "path";
import {
isStorageDriverOverlay, findFuseOverlayfsPath,
splitByNewline,
isFullImageName, getFullImageName,
splitByNewline, getFullImageName, isFullImageName,
getImageName, isRegistryLocalhost,
getFullDockerImageName,
} from "./util";
import { Inputs, Outputs } from "./generated/inputs-outputs";
@ -86,12 +86,17 @@ async function run(): Promise<void> {
if (!registry) {
throw new Error(`Input "${Inputs.REGISTRY}" must be provided when using non full name tags`);
}
// special handling if image starts with localhost/
// this will target `localhost/image:tag` as the source, but push `registry/image:tag`
const isImageLocalhost = isRegistryLocalhost(normalizedImage);
const destinationImageName = isImageLocalhost ? getImageName(normalizedImage) : normalizedImage;
const registryWithoutTrailingSlash = registry.replace(/\/$/, "");
const registryPath = `${registryWithoutTrailingSlash}/${normalizedImage}`;
core.info(`Combining image name "${normalizedImage}" and registry "${registry}" `
const registryPath = `${registryWithoutTrailingSlash}/${destinationImageName}`;
core.info(`Combining image name "${destinationImageName}" and registry "${registry}" `
+ `to form registry path "${registryPath}"`);
if (normalizedImage.indexOf("/") > -1 && registry.indexOf("/") > -1) {
if (destinationImageName.indexOf("/") > -1 && registry.indexOf("/") > -1) {
core.warning(`"${registryPath}" does not seem to be a valid registry path. `
+ `The registry path should not contain more than 2 slashes. `
+ `Refer to the Inputs section of the readme for naming image and registry.`);
@ -296,9 +301,10 @@ async function pullImageFromDocker(): Promise<ImageStorageCheckResult> {
const missingTags: string[] = [];
try {
for (const imageWithTag of sourceImages) {
const dockerImageName = getFullDockerImageName(imageWithTag);
const commandResult: ExecResult = await execute(
await getPodmanPath(),
[ ...dockerPodmanOpts, "pull", `docker-daemon:${imageWithTag}` ],
[ ...dockerPodmanOpts, "pull", `docker-daemon:${dockerImageName}` ],
{ ignoreReturnCode: true, failOnStdErr: false, group: true }
);
if (commandResult.exitCode === 0) {

View file

@ -77,17 +77,73 @@ export function getFullImageName(image: string, tag: string): string {
return `${image}:${tag}`;
}
const DOCKER_IO = `docker.io`;
const DOCKER_IO_NAMESPACED = DOCKER_IO + `/library`;
export function isNamespace(image: string): boolean {
return image.indexOf("/") > 0;
}
export function getFullDockerImageName(image: string): string {
switch (image.split("/").length) {
case 1:
return `${DOCKER_IO_NAMESPACED}/${image}`;
case 2:
if (image.includes("amazonaws.com")) return image;
return `${DOCKER_IO}/${image}`;
export function isRegistryDomain(image: string): boolean {
// naively checks if the registry is a domain
if (isNamespace(image)) {
const registry = image.split("/")[0];
return registry.indexOf(".") > 0 && !registry.endsWith(".");
}
return false;
}
export function isRegistryLocalhost(image: string): boolean {
if (isNamespace(image)) {
const registry = image.split("/")[0];
return registry === "localhost";
}
return false;
}
export function isNameFullyQualified(image: string): boolean {
if (isFullImageName(image)) {
return isRegistryDomain(image);
}
return false;
}
export function getImageName(image: string): string {
const imageParts = image.split("/");
switch (true) {
case (imageParts.length <= 2):
if (isRegistryLocalhost(image) || isRegistryDomain(image)) {
return imageParts.slice(1).join("/");
}
return image;
case (isRegistryLocalhost(image)):
return imageParts.slice(1).join("/");
case (isRegistryDomain(image)):
return imageParts.slice(2).join("/");
default:
return image;
}
}
const DOCKER_IO = `docker.io`;
const DOCKER_IO_NAMESPACED = DOCKER_IO + `/library`;
export function getFullDockerImageName(image: string): string {
// docker does not store images with localhost/
// so we get the base image name if it is prepended with localhost/
const sanitizedImageName = isRegistryLocalhost(image) ? getImageName(image) : image;
const imagePartsLength = sanitizedImageName.split("/").length;
switch (true) {
case (isNameFullyQualified(sanitizedImageName)):
// if the docker image is in the form of `registry/image:tag`,
// then it is pulled to podman as the same name
return sanitizedImageName;
case (imagePartsLength === 1):
// if image is in the form of `image:tag`,
// podman pulls it as `docker.io/library/image:tag`
return `${DOCKER_IO_NAMESPACED}/${sanitizedImageName}`;
default:
// otherwise, if the image is in the form of `namespace/image:tag`,
// podman pulls it as `docker.io/namespace/image:tag`
return `${DOCKER_IO}/${sanitizedImageName}`;
}
}