Use --root to when pulling from docker

This commit is contained in:
なつき 2021-10-08 04:03:51 +00:00
parent 6b269c55d3
commit d6ba509bbd
4 changed files with 50 additions and 39 deletions

2
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

@ -2,8 +2,13 @@ import * as core from "@actions/core";
import * as exec from "@actions/exec"; import * as exec from "@actions/exec";
import * as io from "@actions/io"; import * as io from "@actions/io";
import * as fs from "fs"; import * as fs from "fs";
import * as os from "os";
import * as path from "path"; import * as path from "path";
import { splitByNewline, isFullImageName, getFullImageName } from "./util"; import {
splitByNewline,
isFullImageName, getFullImageName,
getFullDockerImageName,
} from "./util";
import { Inputs, Outputs } from "./generated/inputs-outputs"; import { Inputs, Outputs } from "./generated/inputs-outputs";
interface ExecResult { interface ExecResult {
@ -23,7 +28,7 @@ let podmanPath: string | undefined;
let isImageFromDocker = false; let isImageFromDocker = false;
let sourceImages: string[]; let sourceImages: string[];
let destinationImages: string[]; let destinationImages: string[];
let dockerBaseUrl: string; let dockerPodmanRoot: string;
async function getPodmanPath(): Promise<string> { async function getPodmanPath(): Promise<string> {
if (podmanPath == null) { if (podmanPath == null) {
@ -34,10 +39,6 @@ async function getPodmanPath(): Promise<string> {
return podmanPath; return podmanPath;
} }
// base URL that gets appended if image is pulled from the Docker imaege storage
const DOCKER_IO = `docker.io`;
const DOCKER_IO_NAMESPACED = DOCKER_IO + `/library`;
async function run(): Promise<void> { async function run(): Promise<void> {
const DEFAULT_TAG = "latest"; const DEFAULT_TAG = "latest";
const imageInput = core.getInput(Inputs.IMAGE); const imageInput = core.getInput(Inputs.IMAGE);
@ -45,9 +46,6 @@ async function run(): Promise<void> {
// split tags // split tags
const tagsList = tags.trim().split(/\s+/); const tagsList = tags.trim().split(/\s+/);
// handle the case when image name is 'namespace/imagename' and image is present in docker storage
dockerBaseUrl = imageInput.indexOf("/") > -1 ? DOCKER_IO : DOCKER_IO_NAMESPACED;
// info message if user doesn't provides any tag // info message if user doesn't provides any tag
if (tagsList.length === 0) { if (tagsList.length === 0) {
core.info(`Input "${Inputs.TAGS}" is not provided, using default tag "${DEFAULT_TAG}"`); core.info(`Input "${Inputs.TAGS}" is not provided, using default tag "${DEFAULT_TAG}"`);
@ -157,9 +155,6 @@ async function run(): Promise<void> {
+ `than the version in the Podman image storage. The image(s) from the Docker image storage ` + `than the version in the Podman image storage. The image(s) from the Docker image storage `
+ `will be pushed.` + `will be pushed.`
); );
if (!isFullImageNameTag) {
sourceImages = sourceImages.map((image) => `${dockerBaseUrl}/${image}`);
}
isImageFromDocker = true; isImageFromDocker = true;
} }
else { else {
@ -171,9 +166,6 @@ async function run(): Promise<void> {
} }
} }
else if (allTagsinDocker) { else if (allTagsinDocker) {
if (!isFullImageNameTag) {
sourceImages = sourceImages.map((image) => `${dockerBaseUrl}/${image}`);
}
core.info( core.info(
`"${sourceImages[0]}" was found in the Docker image storage, but not in the Podman ` `"${sourceImages[0]}" was found in the Docker image storage, but not in the Podman `
+ `image storage. The image(s) will be pulled into Podman image storage, pushed, and then ` + `image storage. The image(s) will be pulled into Podman image storage, pushed, and then `
@ -188,7 +180,7 @@ async function run(): Promise<void> {
); );
} }
let pushMsg = `⏳ Pushing "${sourceImages[0]}" to ${destinationImages.map((image) => `"${image}"`).join(", ")}`; let pushMsg = `⏳ Pushing "${sourceImages[0]}" to ${destinationImages.join(", ")}`;
if (username) { if (username) {
pushMsg += ` as "${username}"`; pushMsg += ` as "${username}"`;
} }
@ -216,11 +208,12 @@ async function run(): Promise<void> {
// push the image // push the image
for (const destinationImage of destinationImages) { for (const destinationImage of destinationImages) {
const args = [ const args = [
...(isImageFromDocker ? [ "--root", dockerPodmanRoot ] : []),
"push", "push",
"--quiet", "--quiet",
"--digestfile", "--digestfile",
digestFile, digestFile,
sourceImages[0], isImageFromDocker ? getFullDockerImageName(sourceImages[0]) : sourceImages[0],
destinationImage, destinationImage,
]; ];
@ -260,14 +253,14 @@ async function run(): Promise<void> {
} }
async function pullImageFromDocker(): Promise<ImageStorageCheckResult> { async function pullImageFromDocker(): Promise<ImageStorageCheckResult> {
core.info(`🔍 Checking if "${sourceImages.join(",")}" present in the local Docker image storage`); core.info(`🔍 Checking if "${sourceImages.join(", ")}" present in the local Docker image storage`);
const foundTags: string[] = []; const foundTags: string[] = [];
const missingTags: string[] = []; const missingTags: string[] = [];
try { try {
for (const imageWithTag of sourceImages) { for (const imageWithTag of sourceImages) {
const commandResult: ExecResult = await execute( const commandResult: ExecResult = await execute(
await getPodmanPath(), await getPodmanPath(),
[ "pull", `docker-daemon:${imageWithTag}` ], [ "--root", dockerPodmanRoot, "pull", `docker-daemon:${imageWithTag}` ],
{ ignoreReturnCode: true, failOnStdErr: false, group: true } { ignoreReturnCode: true, failOnStdErr: false, group: true }
); );
if (commandResult.exitCode === 0) { if (commandResult.exitCode === 0) {
@ -323,12 +316,6 @@ async function isPodmanLocalImageLatest(): Promise<boolean> {
// same for all the tags present // same for all the tags present
const imageWithTag = sourceImages[0]; const imageWithTag = sourceImages[0];
// do not check if full name is specified as image pulled from docker
// will not have a different name
if (isFullImageName(imageWithTag)) {
return true;
}
// get creation time of the image present in the Podman image storage // get creation time of the image present in the Podman image storage
const podmanLocalImageTimeStamp = await execute(await getPodmanPath(), [ const podmanLocalImageTimeStamp = await execute(await getPodmanPath(), [
"image", "image",
@ -342,9 +329,10 @@ async function isPodmanLocalImageLatest(): Promise<boolean> {
// appending 'docker.io/library' infront of image name as pulled image name // appending 'docker.io/library' infront of image name as pulled image name
// from Docker image storage starts with the 'docker.io/library' // from Docker image storage starts with the 'docker.io/library'
const pulledImageCreationTimeStamp = await execute(await getPodmanPath(), [ const pulledImageCreationTimeStamp = await execute(await getPodmanPath(), [
"--root", dockerPodmanRoot,
"image", "image",
"inspect", "inspect",
`${dockerBaseUrl}/${imageWithTag}`, getFullDockerImageName(imageWithTag),
"--format", "--format",
"{{.Created}}", "{{.Created}}",
]); ]);
@ -356,11 +344,15 @@ async function isPodmanLocalImageLatest(): Promise<boolean> {
return podmanImageTime > dockerImageTime; return podmanImageTime > dockerImageTime;
} }
// remove the pulled image from the Podman image storage async function createDockerPodmanImageStroage(): Promise<void> {
async function removeDockerImage(): Promise<void> { core.info(`Creating temporary Podman image storage for pulling from Docker daemon`);
core.info(`Removing "${sourceImages[0]}" from the Podman image storage`); dockerPodmanRoot = await fs.promises.mkdtemp(path.join(os.tmpdir(), "docker-podman"));
for (const imageWithTag of sourceImages) { }
await execute(await getPodmanPath(), [ "rmi", imageWithTag ]);
async function removeDockerPodmanImageStroage(): Promise<void> {
if (dockerPodmanRoot) {
core.info(`Removing temporary Podman image storage for pulling from Docker daemon`);
await fs.promises.rmdir(dockerPodmanRoot, { recursive: true });
} }
} }
@ -416,12 +408,17 @@ async function execute(
} }
} }
run() async function main(): Promise<void> {
.then(async () => { try {
if (isImageFromDocker) { await createDockerPodmanImageStroage();
await removeDockerImage(); await run();
} }
}) finally {
await removeDockerPodmanImageStroage();
}
}
main()
.catch((err) => { .catch((err) => {
core.setFailed(err.message); core.setFailed(err.message);
}); });

View file

@ -17,3 +17,17 @@ export function getFullImageName(image: string, tag: string): string {
} }
return `${image}:${tag}`; return `${image}:${tag}`;
} }
const DOCKER_IO = `docker.io`;
const DOCKER_IO_NAMESPACED = DOCKER_IO + `/library`;
export function getFullDockerImageName(image: string): string {
switch (image.split("/").length) {
case 1:
return `${DOCKER_IO_NAMESPACED}/${image}`;
case 2:
return `${DOCKER_IO}/${image}`;
default:
return image;
}
}