1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-24 15:59:41 +02:00

feat(podman): support add podman envs in the wizard [r8s-20] (#12056)
Some checks failed
ci / build_images (map[arch:amd64 platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:amd64 platform:windows version:1809]) (push) Has been cancelled
ci / build_images (map[arch:amd64 platform:windows version:ltsc2022]) (push) Has been cancelled
ci / build_images (map[arch:arm platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:arm64 platform:linux version:]) (push) Has been cancelled
ci / build_images (map[arch:ppc64le platform:linux version:]) (push) Has been cancelled
/ triage (push) Has been cancelled
Lint / Run linters (push) Has been cancelled
Test / test-client (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:linux]) (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:windows version:1809]) (push) Has been cancelled
Test / test-server (map[arch:amd64 platform:windows version:ltsc2022]) (push) Has been cancelled
Test / test-server (map[arch:arm64 platform:linux]) (push) Has been cancelled
ci / build_manifests (push) Has been cancelled

This commit is contained in:
Ali 2024-09-25 11:55:07 +12:00 committed by GitHub
parent db616bc8a5
commit 32e94d4e4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
108 changed files with 1921 additions and 272 deletions

View file

@ -47,6 +47,14 @@ export class ContainerStatsViewModel {
this.NumProcs = data.num_procs || 0;
this.isWindows = true;
}
// Podman has memory limit and usage but not stats
else if (
data?.memory_stats?.usage !== undefined &&
data?.memory_stats?.stats === undefined
) {
this.MemoryUsage = data.memory_stats.usage || 0;
this.MemoryCache = 0;
}
// Linux
else if (
data?.memory_stats?.stats === undefined ||

View file

@ -118,7 +118,7 @@ const ngModule = angular
)
.component(
'dockerContainerProcessesDatatable',
r2a(ProcessesDatatable, ['dataset', 'headers'])
r2a(withUIRouter(withReactQuery(withCurrentUser(ProcessesDatatable))), [])
)
.component('dockerEventsDatatable', r2a(EventsDatatable, ['dataset']))
.component(

View file

@ -17,7 +17,7 @@ import { resizeTTY } from '@/react/docker/containers/queries/useContainerResizeT
import { updateContainer } from '@/react/docker/containers/queries/useUpdateContainer';
import { createExec } from '@/react/docker/containers/queries/useCreateExecMutation';
import { containerStats } from '@/react/docker/containers/queries/useContainerStats';
import { containerTop } from '@/react/docker/containers/queries/useContainerTop';
import { getContainerTop } from '@/react/docker/containers/queries/useContainerTop';
import { ContainerDetailsViewModel } from '../models/containerDetails';
import { ContainerStatsViewModel } from '../models/containerStats';
@ -45,7 +45,7 @@ function ContainerServiceFactory(AngularToReact) {
updateRestartPolicy: useAxios(updateRestartPolicyAngularJS), // container edit
createExec: useAxios(createExec), // container console
containerStats: useAxios(containerStatsAngularJS), // container stats
containerTop: useAxios(containerTop), // container stats
containerTop: useAxios(getContainerTop), // container stats
inspect: useAxios(getContainer), // container inspect
logs: useAxios(containerLogsAngularJS), // container logs
};

View file

@ -1,6 +1,6 @@
import { isFulfilled } from '@/portainer/helpers/promise-utils';
import { getInfo } from '@/react/docker/proxy/queries/useInfo';
import { aggregateData, getPlugins } from '@/react/docker/proxy/queries/useServicePlugins';
import { aggregateData, getPlugins } from '@/react/docker/proxy/queries/usePlugins';
angular.module('portainer.docker').factory('PluginService', PluginServiceFactory);

View file

@ -43,11 +43,12 @@
Remove</button
>
</div>
<div class="btn-group" role="group" aria-label="..." ng-if="displayRecreateButton" authorization="DockerContainerCreate">
<div class="btn-group" role="group" aria-label="..." ng-if="displayRecreateButton || displayDuplicateEditButton" authorization="DockerContainerCreate">
<button
type="button"
class="btn btn-light btn-sm"
ng-disabled="state.recreateContainerInProgress || container.IsPortainer"
ng-if="displayRecreateButton"
ng-click="recreate()"
button-spinner="state.recreateContainerInProgress"
>
@ -57,7 +58,13 @@
>
<span ng-show="state.recreateContainerInProgress">Recreation in progress...</span>
</button>
<a class="btn btn-light btn-sm" type="button" ui-sref="docker.containers.new({ from: container.Id, nodeName: nodeName })" ng-disabled="container.IsPortainer">
<a
class="btn btn-light btn-sm"
type="button"
ui-sref="docker.containers.new({ from: container.Id, nodeName: nodeName })"
ng-disabled="container.IsPortainer"
ng-if="displayDuplicateEditButton"
>
<pr-icon icon="'copy'"></pr-icon>
Duplicate/Edit</a
>
@ -218,7 +225,7 @@
<div class="col-sm-12">
<button
type="button"
class="btn btn-primary btn-sm"
class="btn btn-primary btn-sm !ml-0"
ng-disabled="!state.pullImageValidity || !config.RegistryModel.Image || config.commitInProgress"
ng-click="commit()"
>

View file

@ -6,6 +6,7 @@ import { FeatureId } from '@/react/portainer/feature-flags/enums';
import { ResourceControlType } from '@/react/portainer/access-control/types';
import { confirmContainerRecreation } from '@/react/docker/containers/ItemView/ConfirmRecreationModal';
import { commitContainer } from '@/react/docker/proxy/queries/useCommitContainerMutation';
import { ContainerEngine } from '@/react/portainer/environments/types';
angular.module('portainer.docker').controller('ContainerController', [
'$q',
@ -123,7 +124,11 @@ angular.module('portainer.docker').controller('ContainerController', [
!allowHostNamespaceForRegularUsers ||
!allowPrivilegedModeForRegularUsers;
$scope.displayRecreateButton = !inSwarm && !autoRemove && (admin || !settingRestrictsRegularUsers);
// displayRecreateButton should false for podman because recreating podman containers give and error: cannot set memory swappiness with cgroupv2
// https://github.com/containrrr/watchtower/issues/1060#issuecomment-2319076222
const isPodman = endpoint.ContainerEngine === ContainerEngine.Podman;
$scope.displayDuplicateEditButton = !inSwarm && !autoRemove && (admin || !settingRestrictsRegularUsers);
$scope.displayRecreateButton = !inSwarm && !autoRemove && (admin || !settingRestrictsRegularUsers) && !isPodman;
$scope.displayCreateWebhookButton = $scope.displayRecreateButton;
})
.catch(function error(err) {

View file

@ -97,11 +97,9 @@ angular.module('portainer.docker').controller('ContainerStatsController', [
function startChartUpdate(networkChart, cpuChart, memoryChart, ioChart) {
$q.all({
stats: ContainerService.containerStats(endpoint.Id, $transition$.params().id),
top: ContainerService.containerTop(endpoint.Id, $transition$.params().id),
})
.then(function success(data) {
var stats = data.stats;
$scope.processInfo = data.top;
if (stats.Networks.length === 0) {
$scope.state.networkStatsUnavailable = true;
}
@ -125,11 +123,9 @@ angular.module('portainer.docker').controller('ContainerStatsController', [
$scope.repeater = $interval(function () {
$q.all({
stats: ContainerService.containerStats(endpoint.Id, $transition$.params().id),
top: ContainerService.containerTop(endpoint.Id, $transition$.params().id),
})
.then(function success(data) {
var stats = data.stats;
$scope.processInfo = data.top;
updateNetworkChart(stats, networkChart);
updateMemoryChart(stats, memoryChart);
updateCPUChart(stats, cpuChart);

View file

@ -108,4 +108,4 @@
</div>
</div>
<docker-container-processes-datatable dataset="processInfo.Processes" headers="processInfo.Titles"></docker-container-processes-datatable>
<docker-container-processes-datatable></docker-container-processes-datatable>

View file

@ -30,7 +30,7 @@
<div class="form-group">
<span class="col-sm-12 text-muted small">
A name must be specified in one of the following formats: <code>name:tag</code>, <code>repository/name:tag</code> or
<code>registryfqdn:port/repository/name:tag</code> format. If you omit the tag the default <b>latest</b> value is assumed.
<code>registry:port/repository/name:tag</code> format. If you omit the tag the default <b>latest</b> value is assumed.
</span>
</div>
<div class="form-group">

View file

@ -86,7 +86,7 @@
<!-- !tag-note -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.RegistryModel.Image" ng-click="tagImage()">Tag</button>
<button type="button" class="btn btn-primary btn-sm !ml-0" ng-disabled="!formValues.RegistryModel.Image" ng-click="tagImage()">Tag</button>
</div>
</div>
</form>
@ -103,7 +103,7 @@
<table class="table">
<tbody>
<tr>
<td>ID</td>
<td class="min-w-[80px]">ID</td>
<td>
{{ image.Id }}
<button authorization="DockerImageDelete" class="btn btn-xs btn-danger" ng-click="removeImage(image.Id)">
@ -145,7 +145,7 @@
<td>
<table class="table-bordered table-condensed table">
<tr ng-repeat="(k, v) in image.Labels">
<td>{{ k }}</td>
<td class="min-w-[80px]">{{ k }}</td>
<td>{{ v }}</td>
</tr>
</table>

View file

@ -2,6 +2,7 @@ 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 +72,9 @@ angular.module('portainer.docker').controller('ImageController', [
const registryModel = $scope.formValues.RegistryModel;
const image = ImageHelper.createImageConfigForContainer(registryModel);
const { repo, tag } = fullURIIntoRepoAndTag(image.fromImage);
ImageService.tagImage($transition$.params().id, image.fromImage)
ImageService.tagImage($transition$.params().id, repo, tag)
.then(function success() {
Notifications.success('Success', 'Image successfully tagged');
$state.go('docker.images.image', { id: $transition$.params().id }, { reload: true });

View file

@ -1,15 +1,17 @@
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry';
import { fullURIIntoRepoAndTag } from '@/react/docker/images/utils';
angular.module('portainer.docker').controller('ImportImageController', [
'$scope',
'$state',
'$async',
'ImageService',
'Notifications',
'HttpRequestHelper',
'Authentication',
'ImageHelper',
'endpoint',
function ($scope, $state, ImageService, Notifications, HttpRequestHelper, Authentication, ImageHelper, endpoint) {
function ($scope, $state, $async, ImageService, Notifications, HttpRequestHelper, Authentication, ImageHelper, endpoint) {
$scope.state = {
actionInProgress: false,
};
@ -33,15 +35,20 @@ angular.module('portainer.docker').controller('ImportImageController', [
const registryModel = $scope.formValues.RegistryModel;
if (registryModel.Image) {
const image = ImageHelper.createImageConfigForContainer(registryModel);
const { repo, tag } = fullURIIntoRepoAndTag(image.fromImage);
try {
await ImageService.tagImage(id, image.fromImage);
await ImageService.tagImage(id, repo, tag);
} catch (err) {
Notifications.error('Failure', err, 'Unable to tag image');
}
}
}
$scope.uploadImage = async function () {
$scope.uploadImage = function () {
return $async(uploadImageAsync);
};
async function uploadImageAsync() {
$scope.state.actionInProgress = true;
var nodeName = $scope.formValues.NodeName;
@ -52,7 +59,8 @@ angular.module('portainer.docker').controller('ImportImageController', [
if (data.error) {
Notifications.error('Failure', data.error, 'Unable to upload image');
} else if (data.stream) {
var regex = /Loaded.*?: (.*?)\n$/g;
// docker has /n at the end of the stream, podman doesn't
var regex = /Loaded.*?: (.*?)(?:\n|$)/g;
var imageIds = regex.exec(data.stream);
if (imageIds && imageIds.length == 2) {
await tagImage(imageIds[1]);
@ -67,6 +75,6 @@ angular.module('portainer.docker').controller('ImportImageController', [
} finally {
$scope.state.actionInProgress = false;
}
};
}
},
]);

View file

@ -12,7 +12,7 @@
</div>
<div class="form-group">
<div class="col-sm-12 vertical-center">
<button type="button" class="btn btn-sm btn-primary" ngf-select ngf-min-size="10" ng-model="formValues.UploadFile">Select file</button>
<button type="button" class="btn btn-sm btn-primary !ml-0" ngf-select ngf-min-size="10" ng-model="formValues.UploadFile">Select file</button>
<span class="ml-1">
{{ formValues.UploadFile.name }}
<pr-icon icon="'x'" mode="'danger'" ng-if="!formValues.UploadFile"></pr-icon>
@ -27,7 +27,7 @@
<!-- !node-selection -->
</div>
<div class="row" authorization="DockerImageCreate">
<div class="col-lg-12 col-md-12 col-xs-12">
<div class="col-lg-12 col-md-12 col-xs-12 p-0">
<rd-widget>
<rd-widget-header icon="tag" title-text="Tag the image"></rd-widget-header>
<rd-widget-body>
@ -51,7 +51,7 @@
<div class="col-sm-12">
<button
type="button"
class="btn btn-primary btn-sm"
class="btn btn-primary btn-sm !ml-0"
ng-disabled="state.actionInProgress || !formValues.UploadFile"
ng-click="uploadImage()"
button-spinner="state.actionInProgress"

View file

@ -11,6 +11,15 @@
<td>ID</td>
<td>
{{ volume.Id }}
<button
ng-if="showBrowseAction"
class="btn btn-xs btn-primary"
ui-sref="docker.volumes.volume.browse({ id: volume.Id, nodeName: volume.NodeName })"
authorization="DockerAgentBrowseList"
>
<pr-icon icon="'search'" class="leading-none"></pr-icon>
Browse
</button>
<button authorization="DockerVolumeDelete" class="btn btn-xs btn-danger" ng-click="removeVolume()"
><pr-icon icon="'trash-2'" class="leading-none"></pr-icon> Remove this volume</button
>

View file

@ -9,10 +9,12 @@ angular.module('portainer.docker').controller('VolumeController', [
'ContainerService',
'Notifications',
'HttpRequestHelper',
'Authentication',
'endpoint',
function ($scope, $state, $transition$, VolumeService, ContainerService, Notifications, HttpRequestHelper, endpoint) {
function ($scope, $state, $transition$, VolumeService, ContainerService, Notifications, HttpRequestHelper, Authentication, endpoint) {
$scope.resourceType = ResourceControlType.Volume;
$scope.endpoint = endpoint;
$scope.showBrowseAction = false;
$scope.onUpdateResourceControlSuccess = function () {
$state.reload();
@ -41,6 +43,7 @@ angular.module('portainer.docker').controller('VolumeController', [
function initView() {
HttpRequestHelper.setPortainerAgentTargetHeader($transition$.params().nodeName);
$scope.showBrowseAction = $scope.applicationState.endpoint.mode.agentProxy && (Authentication.isAdmin() || endpoint.SecuritySettings.allowVolumeBrowserForRegularUsers);
VolumeService.volume($transition$.params().id)
.then(function success(data) {