1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-25 00:09:40 +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:
Maxime Bajeux 2020-08-14 01:27:10 +02:00 committed by GitHub
parent fe4a80c7bd
commit 00389a7da9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 358 additions and 141 deletions

View file

@ -50,6 +50,7 @@ function _apiPortsToPublishedPorts(pList, pRefs) {
class KubernetesApplicationConverter {
static applicationCommon(res, data, service, ingresses) {
const containers = _.without(_.concat(data.spec.template.spec.containers, data.spec.template.spec.initContainers), undefined);
res.Id = data.metadata.uid;
res.Name = data.metadata.name;
res.StackName = data.metadata.labels ? data.metadata.labels[KubernetesPortainerApplicationStackNameLabel] || '-' : '-';
@ -57,16 +58,16 @@ class KubernetesApplicationConverter {
res.Note = data.metadata.annotations ? data.metadata.annotations[KubernetesPortainerApplicationNote] || '' : '';
res.ApplicationName = data.metadata.labels ? data.metadata.labels[KubernetesPortainerApplicationNameLabel] || res.Name : res.Name;
res.ResourcePool = data.metadata.namespace;
res.Image = data.spec.template.spec.containers[0].image;
res.Image = containers[0].image;
res.CreationDate = data.metadata.creationTimestamp;
res.Pods = data.Pods;
res.Env = data.spec.template.spec.containers[0].env;
res.Env = _.without(_.flatMap(_.map(containers, 'env')), undefined);
const limits = {
Cpu: 0,
Memory: 0,
};
res.Limits = _.reduce(
data.spec.template.spec.containers,
containers,
(acc, item) => {
if (item.resources.limits && item.resources.limits.cpu) {
acc.Cpu += KubernetesResourceReservationHelper.parseCPU(item.resources.limits.cpu);
@ -84,7 +85,7 @@ class KubernetesApplicationConverter {
Memory: 0,
};
res.Requests = _.reduce(
data.spec.template.spec.containers,
containers,
(acc, item) => {
if (item.resources.requests && item.resources.requests.cpu) {
acc.Cpu += KubernetesResourceReservationHelper.parseCPU(item.resources.requests.cpu);
@ -109,7 +110,7 @@ class KubernetesApplicationConverter {
}
}
const portsRefs = _.concat(..._.map(data.spec.template.spec.containers, (container) => container.ports));
const portsRefs = _.concat(..._.map(containers, (container) => container.ports));
const ports = _apiPortsToPublishedPorts(service.spec.ports, portsRefs);
const rules = KubernetesIngressHelper.findSBoundServiceIngressesRules(ingresses, service.metadata.name);
_.forEach(ports, (port) => (port.IngressRules = _.filter(rules, (rule) => rule.Port === port.Port)));
@ -147,7 +148,8 @@ class KubernetesApplicationConverter {
const persistedFolders = _.filter(res.Volumes, (volume) => volume.persistentVolumeClaim || volume.hostPath);
res.PersistedFolders = _.map(persistedFolders, (volume) => {
const matchingVolumeMount = _.find(data.spec.template.spec.containers[0].volumeMounts, { name: volume.name });
const volumeMounts = _.uniq(_.flatMap(_.map(containers, 'volumeMounts')), 'name');
const matchingVolumeMount = _.find(volumeMounts, { name: volume.name });
if (matchingVolumeMount) {
const persistedFolder = new KubernetesApplicationPersistedFolder();
@ -169,7 +171,7 @@ class KubernetesApplicationConverter {
data.spec.template.spec.volumes,
(acc, volume) => {
if (volume.configMap || volume.secret) {
const matchingVolumeMount = _.find(data.spec.template.spec.containers[0].volumeMounts, { name: volume.name });
const matchingVolumeMount = _.find(_.flatMap(_.map(containers, 'volumeMounts')), { name: volume.name });
if (matchingVolumeMount) {
let items = [];
@ -262,6 +264,7 @@ class KubernetesApplicationConverter {
res.Configurations = KubernetesApplicationHelper.generateConfigurationFormValuesFromEnvAndVolumes(app.Env, app.ConfigurationVolumes, configurations);
res.AutoScaler = KubernetesApplicationHelper.generateAutoScalerFormValueFromHorizontalPodAutoScaler(app.AutoScaler, res.ReplicaCount);
res.PublishedPorts = KubernetesApplicationHelper.generatePublishedPortsFormValuesFromPublishedPorts(app.ServiceType, app.PublishedPorts);
res.Containers = app.Containers;
const isIngress = _.filter(res.PublishedPorts, (p) => p.IngressName).length;
if (app.ServiceType === KubernetesServiceTypes.LOAD_BALANCER) {