portainer/app/kubernetes/helpers/application/index.js

275 lines
10 KiB
JavaScript

import _ from 'lodash-es';
import { KubernetesPortMapping, KubernetesPortMappingPort } from 'Kubernetes/models/port/models';
import { KubernetesServiceTypes } from 'Kubernetes/models/service/models';
import { KubernetesConfigurationTypes } from 'Kubernetes/models/configuration/models';
import {
KubernetesApplicationConfigurationFormValueOverridenKeyTypes,
KubernetesApplicationEnvironmentVariableFormValue,
KubernetesApplicationConfigurationFormValue,
KubernetesApplicationConfigurationFormValueOverridenKey,
KubernetesApplicationPersistedFolderFormValue,
KubernetesApplicationPublishedPortFormValue,
} from 'Kubernetes/models/application/formValues';
import {
KubernetesApplicationEnvConfigMapPayload,
KubernetesApplicationEnvPayload,
KubernetesApplicationEnvSecretPayload,
KubernetesApplicationVolumeConfigMapPayload,
KubernetesApplicationVolumeEntryPayload,
KubernetesApplicationVolumeMountPayload,
KubernetesApplicationVolumePersistentPayload,
KubernetesApplicationVolumeSecretPayload,
} from 'Kubernetes/models/application/payloads';
import KubernetesVolumeHelper from 'Kubernetes/helpers/volumeHelper';
class KubernetesApplicationHelper {
static associatePodsAndApplication(pods, app) {
return _.filter(pods, { Labels: app.spec.selector.matchLabels });
}
static portMappingsFromApplications(applications) {
const res = _.reduce(
applications,
(acc, app) => {
if (app.PublishedPorts.length > 0) {
const mapping = new KubernetesPortMapping();
mapping.Name = app.Name;
mapping.ResourcePool = app.ResourcePool;
mapping.ServiceType = app.ServiceType;
mapping.LoadBalancerIPAddress = app.LoadBalancerIPAddress;
mapping.ApplicationOwner = app.ApplicationOwner;
mapping.Ports = _.map(app.PublishedPorts, (item) => {
const port = new KubernetesPortMappingPort();
port.Port = mapping.ServiceType === KubernetesServiceTypes.NODE_PORT ? item.NodePort : item.Port;
port.TargetPort = item.TargetPort;
port.Protocol = item.Protocol;
port.IngressRules = item.IngressRules;
return port;
});
acc.push(mapping);
}
return acc;
},
[]
);
return res;
}
/**
* FORMVALUES TO APPLICATION FUNCTIONS
*/
static generateEnvFromEnvVariables(envVariables) {
_.remove(envVariables, (item) => item.NeedsDeletion);
const env = _.map(envVariables, (item) => {
const res = new KubernetesApplicationEnvPayload();
res.name = item.Name;
res.value = item.Value;
return res;
});
return env;
}
static generateEnvOrVolumesFromConfigurations(app, configurations) {
let finalEnv = [];
let finalVolumes = [];
let finalMounts = [];
_.forEach(configurations, (config) => {
const isBasic = config.SelectedConfiguration.Type === KubernetesConfigurationTypes.CONFIGMAP;
if (!config.Overriden) {
const envKeys = _.keys(config.SelectedConfiguration.Data);
_.forEach(envKeys, (item) => {
const res = isBasic ? new KubernetesApplicationEnvConfigMapPayload() : new KubernetesApplicationEnvSecretPayload();
res.name = item;
if (isBasic) {
res.valueFrom.configMapKeyRef.name = config.SelectedConfiguration.Name;
res.valueFrom.configMapKeyRef.key = item;
} else {
res.valueFrom.secretKeyRef.name = config.SelectedConfiguration.Name;
res.valueFrom.secretKeyRef.key = item;
}
finalEnv.push(res);
});
} else {
const envKeys = _.filter(config.OverridenKeys, (item) => item.Type === KubernetesApplicationConfigurationFormValueOverridenKeyTypes.ENVIRONMENT);
_.forEach(envKeys, (item) => {
const res = isBasic ? new KubernetesApplicationEnvConfigMapPayload() : new KubernetesApplicationEnvSecretPayload();
res.name = item.Key;
if (isBasic) {
res.valueFrom.configMapKeyRef.name = config.SelectedConfiguration.Name;
res.valueFrom.configMapKeyRef.key = item.Key;
} else {
res.valueFrom.secretKeyRef.name = config.SelectedConfiguration.Name;
res.valueFrom.secretKeyRef.key = item.Key;
}
finalEnv.push(res);
});
const volKeys = _.filter(config.OverridenKeys, (item) => item.Type === KubernetesApplicationConfigurationFormValueOverridenKeyTypes.FILESYSTEM);
const groupedVolKeys = _.groupBy(volKeys, 'Path');
_.forEach(groupedVolKeys, (items, path) => {
const volumeName = KubernetesVolumeHelper.generatedApplicationConfigVolumeName(app.Name);
const configurationName = config.SelectedConfiguration.Name;
const itemsMap = _.map(items, (item) => {
const entry = new KubernetesApplicationVolumeEntryPayload();
entry.key = item.Key;
entry.path = item.Key;
return entry;
});
const mount = isBasic ? new KubernetesApplicationVolumeMountPayload() : new KubernetesApplicationVolumeMountPayload(true);
const volume = isBasic ? new KubernetesApplicationVolumeConfigMapPayload() : new KubernetesApplicationVolumeSecretPayload();
mount.name = volumeName;
mount.mountPath = path;
volume.name = volumeName;
if (isBasic) {
volume.configMap.name = configurationName;
volume.configMap.items = itemsMap;
} else {
volume.secret.secretName = configurationName;
volume.secret.items = itemsMap;
}
finalMounts.push(mount);
finalVolumes.push(volume);
});
}
});
app.Env = _.concat(app.Env, finalEnv);
app.Volumes = _.concat(app.Volumes, finalVolumes);
app.VolumeMounts = _.concat(app.VolumeMounts, finalMounts);
return app;
}
static generateVolumesFromPersistentVolumClaims(app, volumeClaims) {
app.VolumeMounts = [];
app.Volumes = [];
_.forEach(volumeClaims, (item) => {
const volumeMount = new KubernetesApplicationVolumeMountPayload();
const name = item.Name;
volumeMount.name = name;
volumeMount.mountPath = item.MountPath;
app.VolumeMounts.push(volumeMount);
const volume = new KubernetesApplicationVolumePersistentPayload();
volume.name = name;
volume.persistentVolumeClaim.claimName = name;
app.Volumes.push(volume);
});
}
/**
* !FORMVALUES TO APPLICATION FUNCTIONS
*/
/**
* APPLICATION TO FORMVALUES FUNCTIONS
*/
static generateEnvVariablesFromEnv(env) {
const envVariables = _.map(env, (item) => {
if (!item.value) {
return;
}
const res = new KubernetesApplicationEnvironmentVariableFormValue();
res.Name = item.name;
res.Value = item.value;
res.IsNew = false;
return res;
});
return _.without(envVariables, undefined);
}
static generateConfigurationFormValuesFromEnvAndVolumes(env, volumes, configurations) {
const finalRes = _.flatMap(configurations, (cfg) => {
const filterCondition = cfg.Type === KubernetesConfigurationTypes.CONFIGMAP ? 'valueFrom.configMapKeyRef.name' : 'valueFrom.secretKeyRef.name';
const cfgEnv = _.filter(env, [filterCondition, cfg.Name]);
const cfgVol = _.filter(volumes, { configurationName: cfg.Name });
if (!cfgEnv.length && !cfgVol.length) {
return;
}
const keys = _.reduce(
_.keys(cfg.Data),
(acc, k) => {
const keyEnv = _.filter(cfgEnv, { name: k });
const keyVol = _.filter(cfgVol, { configurationKey: k });
const key = {
Key: k,
Count: keyEnv.length + keyVol.length,
Sum: _.concat(keyEnv, keyVol),
EnvCount: keyEnv.length,
VolCount: keyVol.length,
};
acc.push(key);
return acc;
},
[]
);
const max = _.max(_.map(keys, 'Count'));
const overrideThreshold = max - _.max(_.map(keys, 'VolCount'));
const res = _.map(new Array(max), () => new KubernetesApplicationConfigurationFormValue());
_.forEach(res, (item, index) => {
item.SelectedConfiguration = cfg;
const overriden = index >= overrideThreshold;
if (overriden) {
item.Overriden = true;
item.OverridenKeys = _.map(keys, (k) => {
const fvKey = new KubernetesApplicationConfigurationFormValueOverridenKey();
fvKey.Key = k.Key;
if (index < k.EnvCount) {
fvKey.Type = KubernetesApplicationConfigurationFormValueOverridenKeyTypes.ENVIRONMENT;
} else {
fvKey.Type = KubernetesApplicationConfigurationFormValueOverridenKeyTypes.FILESYSTEM;
fvKey.Path = k.Sum[index].rootMountPath;
}
return fvKey;
});
}
});
return res;
});
return _.without(finalRes, undefined);
}
static generatePersistedFoldersFormValuesFromPersistedFolders(persistedFolders, persistentVolumeClaims) {
const finalRes = _.map(persistedFolders, (folder) => {
const pvc = _.find(persistentVolumeClaims, (item) => _.startsWith(item.Name, folder.PersistentVolumeClaimName));
const res = new KubernetesApplicationPersistedFolderFormValue(pvc.StorageClass);
res.PersistentVolumeClaimName = folder.PersistentVolumeClaimName;
res.Size = parseInt(pvc.Storage.slice(0, -2));
res.SizeUnit = pvc.Storage.slice(-2);
res.ContainerPath = folder.MountPath;
return res;
});
return finalRes;
}
static generatePublishedPortsFormValuesFromPublishedPorts(serviceType, publishedPorts) {
const finalRes = _.map(publishedPorts, (port) => {
const res = new KubernetesApplicationPublishedPortFormValue();
res.Protocol = port.Protocol;
res.ContainerPort = port.TargetPort;
if (serviceType === KubernetesServiceTypes.LOAD_BALANCER) {
res.LoadBalancerPort = port.Port;
res.LoadBalancerNodePort = port.NodePort;
} else if (serviceType === KubernetesServiceTypes.NODE_PORT) {
res.NodePort = port.NodePort;
}
return res;
});
return finalRes;
}
/**
* !APPLICATION TO FORMVALUES FUNCTIONS
*/
static isExternalApplication(application) {
return !application.ApplicationOwner;
}
}
export default KubernetesApplicationHelper;