From 371e84d9a559233d3a2edf59b7ebfa6c13d49c2c Mon Sep 17 00:00:00 2001 From: Ali <83188384+testA113@users.noreply.github.com> Date: Wed, 5 Feb 2025 20:22:33 +1300 Subject: [PATCH] fix(podman): create new image from a container in podman [r8s-90] (#347) --- app/docker/helpers/imageHelper.js | 8 ++++++-- .../containers/edit/containerController.js | 4 ++-- .../views/images/edit/imageController.js | 4 +--- .../images/import/importImageController.js | 4 +--- app/react/docker/images/utils.test.ts | 18 ++++++++++++++++++ app/react/docker/images/utils.ts | 9 +++++++++ 6 files changed, 37 insertions(+), 10 deletions(-) diff --git a/app/docker/helpers/imageHelper.js b/app/docker/helpers/imageHelper.js index 0bacd6c53..3ce3d4a45 100644 --- a/app/docker/helpers/imageHelper.js +++ b/app/docker/helpers/imageHelper.js @@ -1,4 +1,4 @@ -import { buildImageFullURIFromModel, imageContainsURL } from '@/react/docker/images/utils'; +import { buildImageFullURIFromModel, imageContainsURL, fullURIIntoRepoAndTag } from '@/react/docker/images/utils'; angular.module('portainer.docker').factory('ImageHelper', ImageHelperFactory); function ImageHelperFactory() { @@ -18,8 +18,12 @@ function ImageHelperFactory() { * @param {PorImageRegistryModel} registry */ function createImageConfigForContainer(imageModel) { + const fromImage = buildImageFullURIFromModel(imageModel); + const { tag, repo } = fullURIIntoRepoAndTag(fromImage); return { - fromImage: buildImageFullURIFromModel(imageModel), + fromImage, + tag, + repo, }; } diff --git a/app/docker/views/containers/edit/containerController.js b/app/docker/views/containers/edit/containerController.js index 085b2d73d..78f153e27 100644 --- a/app/docker/views/containers/edit/containerController.js +++ b/app/docker/views/containers/edit/containerController.js @@ -207,9 +207,9 @@ angular.module('portainer.docker').controller('ContainerController', [ async function commitContainerAsync() { $scope.config.commitInProgress = true; const registryModel = $scope.config.RegistryModel; - const imageConfig = ImageHelper.createImageConfigForContainer(registryModel); + const { repo, tag } = ImageHelper.createImageConfigForContainer(registryModel); try { - await commitContainer(endpoint.Id, { container: $transition$.params().id, repo: imageConfig.fromImage }); + await commitContainer(endpoint.Id, { container: $transition$.params().id, repo, tag }); Notifications.success('Image created', $transition$.params().id); $state.reload(); } catch (err) { diff --git a/app/docker/views/images/edit/imageController.js b/app/docker/views/images/edit/imageController.js index 78ae6107c..8ed5c9495 100644 --- a/app/docker/views/images/edit/imageController.js +++ b/app/docker/views/images/edit/imageController.js @@ -2,7 +2,6 @@ import _ from 'lodash-es'; import { PorImageRegistryModel } from 'Docker/models/porImageRegistry'; import { confirmImageExport } from '@/react/docker/images/common/ConfirmExportModal'; import { confirmDelete } from '@@/modals/confirm'; -import { fullURIIntoRepoAndTag } from '@/react/docker/images/utils'; angular.module('portainer.docker').controller('ImageController', [ '$async', @@ -71,8 +70,7 @@ angular.module('portainer.docker').controller('ImageController', [ $scope.tagImage = function () { const registryModel = $scope.formValues.RegistryModel; - const image = ImageHelper.createImageConfigForContainer(registryModel); - const { repo, tag } = fullURIIntoRepoAndTag(image.fromImage); + const { repo, tag } = ImageHelper.createImageConfigForContainer(registryModel); ImageService.tagImage($transition$.params().id, repo, tag) .then(function success() { diff --git a/app/docker/views/images/import/importImageController.js b/app/docker/views/images/import/importImageController.js index dfdb8ab1a..d5587ecb9 100644 --- a/app/docker/views/images/import/importImageController.js +++ b/app/docker/views/images/import/importImageController.js @@ -1,5 +1,4 @@ import { PorImageRegistryModel } from 'Docker/models/porImageRegistry'; -import { fullURIIntoRepoAndTag } from '@/react/docker/images/utils'; angular.module('portainer.docker').controller('ImportImageController', [ '$scope', @@ -34,8 +33,7 @@ angular.module('portainer.docker').controller('ImportImageController', [ async function tagImage(id) { const registryModel = $scope.formValues.RegistryModel; if (registryModel.Image) { - const image = ImageHelper.createImageConfigForContainer(registryModel); - const { repo, tag } = fullURIIntoRepoAndTag(image.fromImage); + const { repo, tag } = ImageHelper.createImageConfigForContainer(registryModel); try { await ImageService.tagImage(id, repo, tag); } catch (err) { diff --git a/app/react/docker/images/utils.test.ts b/app/react/docker/images/utils.test.ts index 05f0e39ff..70e1cf74c 100644 --- a/app/react/docker/images/utils.test.ts +++ b/app/react/docker/images/utils.test.ts @@ -16,6 +16,24 @@ describe('fullURIIntoRepoAndTag', () => { expect(result).toEqual({ repo: 'nginx', tag: 'latest' }); }); + it('splits image-repo:port/image correctly', () => { + const result = fullURIIntoRepoAndTag('registry.example.com:5000/my-image'); + expect(result).toEqual({ + repo: 'registry.example.com:5000/my-image', + tag: 'latest', + }); + }); + + it('splits image-repo:port/image:tag correctly', () => { + const result = fullURIIntoRepoAndTag( + 'registry.example.com:5000/my-image:v1' + ); + expect(result).toEqual({ + repo: 'registry.example.com:5000/my-image', + tag: 'v1', + }); + }); + it('splits registry:port/image-repo:tag correctly', () => { const result = fullURIIntoRepoAndTag( 'registry.example.com:5000/my-image:v2.1' diff --git a/app/react/docker/images/utils.ts b/app/react/docker/images/utils.ts index 10d6ae0e9..e9aeaf661 100644 --- a/app/react/docker/images/utils.ts +++ b/app/react/docker/images/utils.ts @@ -121,9 +121,18 @@ export function fullURIIntoRepoAndTag(fullURI: string) { // - registry/image-repo:tag // - image-repo:tag // - registry:port/image-repo:tag + // - localhost:5000/nginx // buildImageFullURIFromModel always gives a tag (defaulting to 'latest'), so the tag is always present after the last ':' const parts = fullURI.split(':'); const tag = parts.pop() || 'latest'; + + // handle the case of a repo with a non standard port + if (tag.includes('/')) { + return { + repo: fullURI, + tag: 'latest', + }; + } const repo = parts.join(':'); return { repo,