mirror of
https://github.com/portainer/portainer.git
synced 2025-08-04 21:35:23 +02:00
feat(k8s/application): Support multi-container pods applications (#4208)
* feat(application): Support multi-container pods applications * feat(application): Support multi-container pods applications * fix(application): use only one pod in app details and fix logs and console links * fix(application): show all containers in containers datatable * fix(application): fix order by pod name * feat(k8s/application): minor UI update * feat(k8s/application): minor UI update * feat(k8s/application): minor UI update * feat(k8s/application): minor UI update * feat(k8s/application): minor UI update * fix(application): fix persisted folders in application details Co-authored-by: Anthony Lapenna <lapenna.anthony@gmail.com>
This commit is contained in:
parent
fe4a80c7bd
commit
00389a7da9
24 changed files with 358 additions and 141 deletions
|
@ -1,5 +1,5 @@
|
|||
import _ from 'lodash-es';
|
||||
import { KubernetesPod, KubernetesPodToleration, KubernetesPodAffinity } from 'Kubernetes/pod/models';
|
||||
import { KubernetesPod, KubernetesPodToleration, KubernetesPodAffinity, KubernetesPodContainer, KubernetesPodContainerTypes } from 'Kubernetes/pod/models';
|
||||
|
||||
function computeStatus(statuses) {
|
||||
const containerStatuses = _.map(statuses, 'state');
|
||||
|
@ -13,6 +13,21 @@ function computeStatus(statuses) {
|
|||
return 'Running';
|
||||
}
|
||||
|
||||
function computeContainerStatus(statuses, name) {
|
||||
const status = _.find(statuses, { name: name });
|
||||
if (!status) {
|
||||
return 'Terminated';
|
||||
}
|
||||
const state = status.state;
|
||||
if (state.waiting) {
|
||||
return 'Waiting';
|
||||
}
|
||||
if (!state.running) {
|
||||
return 'Terminated';
|
||||
}
|
||||
return 'Running';
|
||||
}
|
||||
|
||||
function computeAffinity(affinity) {
|
||||
const res = new KubernetesPodAffinity();
|
||||
if (affinity) {
|
||||
|
@ -33,6 +48,44 @@ function computeTolerations(tolerations) {
|
|||
});
|
||||
}
|
||||
|
||||
function computeContainers(data) {
|
||||
const containers = data.spec.containers;
|
||||
const initContainers = data.spec.initContainers;
|
||||
|
||||
return _.concat(
|
||||
_.map(containers, (item) => {
|
||||
const res = new KubernetesPodContainer();
|
||||
res.Type = KubernetesPodContainerTypes.APP;
|
||||
res.PodName = data.metadata.name;
|
||||
res.Name = item.name;
|
||||
res.Image = item.image;
|
||||
res.Node = data.spec.nodeName;
|
||||
res.CreationDate = data.status.startTime;
|
||||
res.Status = computeContainerStatus(data.status.containerStatuses, item.name);
|
||||
res.Limits = item.resources.limits;
|
||||
res.Requests = item.resources.requests;
|
||||
res.VolumeMounts = item.volumeMounts;
|
||||
res.Env = item.env;
|
||||
return res;
|
||||
}),
|
||||
_.map(initContainers, (item) => {
|
||||
const res = new KubernetesPodContainer();
|
||||
res.Type = KubernetesPodContainerTypes.INIT;
|
||||
res.PodName = data.metadata.name;
|
||||
res.Name = item.name;
|
||||
res.Image = item.image;
|
||||
res.Node = data.spec.nodeName;
|
||||
res.CreationDate = data.status.startTime;
|
||||
res.Status = computeContainerStatus(data.status.containerStatuses, item.name);
|
||||
res.Limits = item.resources.limits;
|
||||
res.Requests = item.resources.requests;
|
||||
res.VolumeMounts = item.volumeMounts;
|
||||
res.Env = item.env;
|
||||
return res;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export default class KubernetesPodConverter {
|
||||
static apiToModel(data) {
|
||||
const res = new KubernetesPod();
|
||||
|
@ -44,7 +97,7 @@ export default class KubernetesPodConverter {
|
|||
res.Restarts = _.sumBy(data.status.containerStatuses, 'restartCount');
|
||||
res.Node = data.spec.nodeName;
|
||||
res.CreationDate = data.status.startTime;
|
||||
res.Containers = data.spec.containers;
|
||||
res.Containers = computeContainers(data);
|
||||
res.Labels = data.metadata.labels;
|
||||
res.Affinity = computeAffinity(data.spec.affinity);
|
||||
res.NodeSelector = data.spec.nodeSelector;
|
||||
|
|
|
@ -40,3 +40,30 @@ export class KubernetesPodToleration {
|
|||
Object.assign(this, JSON.parse(JSON.stringify(_KubernetesPodToleration)));
|
||||
}
|
||||
}
|
||||
|
||||
const _KubernetesPodContainer = Object.freeze({
|
||||
Type: 0,
|
||||
PodName: '',
|
||||
Name: '',
|
||||
Image: '',
|
||||
Node: '',
|
||||
CreationDate: '',
|
||||
Status: '',
|
||||
Limits: {},
|
||||
Requests: {},
|
||||
VolumeMounts: {},
|
||||
ConfigurationVolumes: [],
|
||||
PersistedFolders: [],
|
||||
Env: [],
|
||||
});
|
||||
|
||||
export class KubernetesPodContainer {
|
||||
constructor() {
|
||||
Object.assign(this, JSON.parse(JSON.stringify(_KubernetesPodContainer)));
|
||||
}
|
||||
}
|
||||
|
||||
export const KubernetesPodContainerTypes = {
|
||||
INIT: 1,
|
||||
APP: 2,
|
||||
};
|
||||
|
|
|
@ -36,11 +36,15 @@ class KubernetesPodService {
|
|||
*
|
||||
* @param {string} namespace
|
||||
* @param {string} podName
|
||||
* @param {string} containerName
|
||||
*/
|
||||
async logsAsync(namespace, podName) {
|
||||
async logsAsync(namespace, podName, containerName) {
|
||||
try {
|
||||
const params = new KubernetesCommonParams();
|
||||
params.id = podName;
|
||||
if (containerName) {
|
||||
params.container = containerName;
|
||||
}
|
||||
const data = await this.KubernetesPods(namespace).logs(params).$promise;
|
||||
return data.logs.length === 0 ? [] : data.logs.split('\n');
|
||||
} catch (err) {
|
||||
|
@ -48,8 +52,8 @@ class KubernetesPodService {
|
|||
}
|
||||
}
|
||||
|
||||
logs(namespace, podName) {
|
||||
return this.$async(this.logsAsync, namespace, podName);
|
||||
logs(namespace, podName, containerName) {
|
||||
return this.$async(this.logsAsync, namespace, podName, containerName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue