mirror of
https://github.com/portainer/portainer.git
synced 2025-07-25 08:19:40 +02:00
refactor(app): details widget migration [EE-5352] (#8886)
This commit is contained in:
parent
fdd79cece8
commit
af77e33993
57 changed files with 2046 additions and 1079 deletions
|
@ -1,76 +0,0 @@
|
|||
import angular from 'angular';
|
||||
import _ from 'lodash-es';
|
||||
import PortainerError from 'Portainer/error';
|
||||
|
||||
import { KubernetesApplicationTypes } from 'Kubernetes/models/application/models';
|
||||
import { KubernetesSystem_DefaultDeploymentUniqueLabelKey, KubernetesSystem_AnnotationsToSkip } from 'Kubernetes/models/history/models';
|
||||
|
||||
class KubernetesApplicationRollbackHelper {
|
||||
static getPatchPayload(application, targetRevision) {
|
||||
let result;
|
||||
|
||||
switch (application.ApplicationType) {
|
||||
case KubernetesApplicationTypes.DEPLOYMENT:
|
||||
result = KubernetesApplicationRollbackHelper._getDeploymentPayload(application, targetRevision);
|
||||
break;
|
||||
case KubernetesApplicationTypes.DAEMONSET:
|
||||
result = KubernetesApplicationRollbackHelper._getDaemonSetPayload(application, targetRevision);
|
||||
break;
|
||||
case KubernetesApplicationTypes.STATEFULSET:
|
||||
result = KubernetesApplicationRollbackHelper._getStatefulSetPayload(application, targetRevision);
|
||||
break;
|
||||
default:
|
||||
throw new PortainerError('Unable to determine which association to use to convert patch');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static _getDeploymentPayload(deploymentApp, targetRevision) {
|
||||
const target = angular.copy(targetRevision);
|
||||
const deployment = deploymentApp.Raw;
|
||||
|
||||
// remove hash label before patching back into the deployment
|
||||
delete target.spec.template.metadata.labels[KubernetesSystem_DefaultDeploymentUniqueLabelKey];
|
||||
|
||||
// compute deployment annotations
|
||||
const annotations = {};
|
||||
_.forEach(KubernetesSystem_AnnotationsToSkip, (_, k) => {
|
||||
const v = deployment.metadata.annotations[k];
|
||||
if (v) {
|
||||
annotations[k] = v;
|
||||
}
|
||||
});
|
||||
_.forEach(target.metadata.annotations, (v, k) => {
|
||||
if (!KubernetesSystem_AnnotationsToSkip[k]) {
|
||||
annotations[k] = v;
|
||||
}
|
||||
});
|
||||
// Create a patch of the Deployment that replaces spec.template
|
||||
const patch = [
|
||||
{
|
||||
op: 'replace',
|
||||
path: '/spec/template',
|
||||
value: target.spec.template,
|
||||
},
|
||||
{
|
||||
op: 'replace',
|
||||
path: '/metadata/annotations',
|
||||
value: annotations,
|
||||
},
|
||||
];
|
||||
|
||||
return patch;
|
||||
}
|
||||
|
||||
static _getDaemonSetPayload(daemonSet, targetRevision) {
|
||||
void daemonSet;
|
||||
return targetRevision.data;
|
||||
}
|
||||
|
||||
static _getStatefulSetPayload(statefulSet, targetRevision) {
|
||||
void statefulSet;
|
||||
return targetRevision.data;
|
||||
}
|
||||
}
|
||||
|
||||
export default KubernetesApplicationRollbackHelper;
|
|
@ -1,27 +0,0 @@
|
|||
import _ from 'lodash-es';
|
||||
|
||||
class KubernetesDaemonSetHistoryHelper {
|
||||
static _isControlledBy(daemonSet) {
|
||||
return (item) => _.find(item.metadata.ownerReferences, { uid: daemonSet.metadata.uid }) !== undefined;
|
||||
}
|
||||
|
||||
static filterOwnedRevisions(crList, daemonSet) {
|
||||
// filter ControllerRevisions that has the same selector as the DaemonSet
|
||||
// NOTE : this should be done in HTTP request based on daemonSet.spec.selector.matchLabels
|
||||
// instead of getting all CR and filtering them here
|
||||
const sameLabelsCR = _.filter(crList, ['metadata.labels', daemonSet.spec.selector.matchLabels]);
|
||||
// Only include the RS whose ControllerRef matches the DaemonSet.
|
||||
const controlledCR = _.filter(sameLabelsCR, KubernetesDaemonSetHistoryHelper._isControlledBy(daemonSet));
|
||||
// sorts the list of ControllerRevisions by revision, using the creationTimestamp as a tie breaker (old to new)
|
||||
const sortedList = _.sortBy(controlledCR, ['revision', 'metadata.creationTimestamp']);
|
||||
return sortedList;
|
||||
}
|
||||
|
||||
// getCurrentRS returns the newest CR the given daemonSet targets (latest version)
|
||||
static getCurrentRevision(crList) {
|
||||
const current = _.last(crList);
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
export default KubernetesDaemonSetHistoryHelper;
|
|
@ -1,56 +0,0 @@
|
|||
import _ from 'lodash-es';
|
||||
import angular from 'angular';
|
||||
import { KubernetesSystem_DefaultDeploymentUniqueLabelKey, KubernetesSystem_RevisionAnnotation } from 'Kubernetes/models/history/models';
|
||||
|
||||
class KubernetesDeploymentHistoryHelper {
|
||||
static _isControlledBy(deployment) {
|
||||
return (item) => _.find(item.metadata.ownerReferences, { uid: deployment.metadata.uid }) !== undefined;
|
||||
}
|
||||
|
||||
static filterOwnedRevisions(rsList, deployment) {
|
||||
// filter RS that has the same selector as the Deployment
|
||||
// NOTE : this should be done in HTTP request based on deployment.spec.selector
|
||||
// instead of getting all RS and filtering them here
|
||||
const sameLabelsRS = _.filter(rsList, ['spec.selector', deployment.spec.selector]);
|
||||
// Only include the RS whose ControllerRef matches the Deployment.
|
||||
const controlledRS = _.filter(sameLabelsRS, KubernetesDeploymentHistoryHelper._isControlledBy(deployment));
|
||||
// sorts the list of ReplicaSet by creation timestamp, using the names as a tie breaker (old to new)
|
||||
const sortedList = _.sortBy(controlledRS, ['metadata.creationTimestamp', 'metadata.name']);
|
||||
return sortedList;
|
||||
}
|
||||
|
||||
// getCurrentRS returns the new RS the given deployment targets (the one with the same pod template).
|
||||
static getCurrentRevision(rsListOriginal, deployment) {
|
||||
const rsList = angular.copy(rsListOriginal);
|
||||
|
||||
// In rare cases, such as after cluster upgrades, Deployment may end up with
|
||||
// having more than one new ReplicaSets that have the same template as its template,
|
||||
// see https://github.com/kubernetes/kubernetes/issues/40415
|
||||
// We deterministically choose the oldest new ReplicaSet (first match)
|
||||
const current = _.find(rsList, (item) => {
|
||||
// returns true if two given template.spec are equal, ignoring the diff in value of Labels[pod-template-hash]
|
||||
// We ignore pod-template-hash because:
|
||||
// 1. The hash result would be different upon podTemplateSpec API changes
|
||||
// (e.g. the addition of a new field will cause the hash code to change)
|
||||
// 2. The deployment template won't have hash labels
|
||||
delete item.spec.template.metadata.labels[KubernetesSystem_DefaultDeploymentUniqueLabelKey];
|
||||
return _.isEqual(deployment.spec.template, item.spec.template);
|
||||
});
|
||||
current.revision = current.metadata.annotations[KubernetesSystem_RevisionAnnotation];
|
||||
return current;
|
||||
}
|
||||
|
||||
// filters the RSList to drop all RS that have never been a version of the Deployment
|
||||
// also add the revision as a field inside the RS
|
||||
// Note: this should not impact rollback process as we only patch
|
||||
// metadata.annotations and spec.template
|
||||
static filterVersionedRevisions(rsList) {
|
||||
const filteredRS = _.filter(rsList, (item) => item.metadata.annotations[KubernetesSystem_RevisionAnnotation] !== undefined);
|
||||
return _.map(filteredRS, (item) => {
|
||||
item.revision = item.metadata.annotations[KubernetesSystem_RevisionAnnotation];
|
||||
return item;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default KubernetesDeploymentHistoryHelper;
|
|
@ -1,50 +0,0 @@
|
|||
import _ from 'lodash-es';
|
||||
import PortainerError from 'Portainer/error';
|
||||
|
||||
import KubernetesDeploymentHistoryHelper from 'Kubernetes/helpers/history/deployment';
|
||||
import KubernetesDaemonSetHistoryHelper from 'Kubernetes/helpers/history/daemonset';
|
||||
import KubernetesStatefulSetHistoryHelper from 'Kubernetes/helpers/history/statefulset';
|
||||
import { KubernetesApplicationTypes } from 'Kubernetes/models/application/models';
|
||||
|
||||
class KubernetesHistoryHelper {
|
||||
static getRevisions(rawRevisions, application) {
|
||||
let currentRevision, revisionsList;
|
||||
|
||||
switch (application.ApplicationType) {
|
||||
case KubernetesApplicationTypes.DEPLOYMENT:
|
||||
[currentRevision, revisionsList] = KubernetesHistoryHelper._getDeploymentRevisions(rawRevisions, application.Raw);
|
||||
break;
|
||||
case KubernetesApplicationTypes.DAEMONSET:
|
||||
[currentRevision, revisionsList] = KubernetesHistoryHelper._getDaemonSetRevisions(rawRevisions, application.Raw);
|
||||
break;
|
||||
case KubernetesApplicationTypes.STATEFULSET:
|
||||
[currentRevision, revisionsList] = KubernetesHistoryHelper._getStatefulSetRevisions(rawRevisions, application.Raw);
|
||||
break;
|
||||
default:
|
||||
throw new PortainerError('Unable to determine which association to use to get revisions');
|
||||
}
|
||||
revisionsList = _.sortBy(revisionsList, 'revision');
|
||||
return [currentRevision, revisionsList];
|
||||
}
|
||||
|
||||
static _getDeploymentRevisions(rsList, deployment) {
|
||||
const appRS = KubernetesDeploymentHistoryHelper.filterOwnedRevisions(rsList, deployment);
|
||||
const currentRS = KubernetesDeploymentHistoryHelper.getCurrentRevision(appRS, deployment);
|
||||
const versionedRS = KubernetesDeploymentHistoryHelper.filterVersionedRevisions(appRS);
|
||||
return [currentRS, versionedRS];
|
||||
}
|
||||
|
||||
static _getDaemonSetRevisions(crList, daemonSet) {
|
||||
const appCR = KubernetesDaemonSetHistoryHelper.filterOwnedRevisions(crList, daemonSet);
|
||||
const currentCR = KubernetesDaemonSetHistoryHelper.getCurrentRevision(appCR, daemonSet);
|
||||
return [currentCR, appCR];
|
||||
}
|
||||
|
||||
static _getStatefulSetRevisions(crList, statefulSet) {
|
||||
const appCR = KubernetesStatefulSetHistoryHelper.filterOwnedRevisions(crList, statefulSet);
|
||||
const currentCR = KubernetesStatefulSetHistoryHelper.getCurrentRevision(appCR, statefulSet);
|
||||
return [currentCR, appCR];
|
||||
}
|
||||
}
|
||||
|
||||
export default KubernetesHistoryHelper;
|
|
@ -1,27 +0,0 @@
|
|||
import _ from 'lodash-es';
|
||||
|
||||
class KubernetesStatefulSetHistoryHelper {
|
||||
static _isControlledBy(statefulSet) {
|
||||
return (item) => _.find(item.metadata.ownerReferences, { uid: statefulSet.metadata.uid }) !== undefined;
|
||||
}
|
||||
|
||||
static filterOwnedRevisions(crList, statefulSet) {
|
||||
// filter ControllerRevisions that has the same selector as the StatefulSet
|
||||
// NOTE : this should be done in HTTP request based on statefulSet.spec.selector.matchLabels
|
||||
// instead of getting all CR and filtering them here
|
||||
const sameLabelsCR = _.filter(crList, ['metadata.labels', statefulSet.spec.selector.matchLabels]);
|
||||
// Only include the RS whose ControllerRef matches the StatefulSet.
|
||||
const controlledCR = _.filter(sameLabelsCR, KubernetesStatefulSetHistoryHelper._isControlledBy(statefulSet));
|
||||
// sorts the list of ControllerRevisions by revision, using the creationTimestamp as a tie breaker (old to new)
|
||||
const sortedList = _.sortBy(controlledCR, ['revision', 'metadata.creationTimestamp']);
|
||||
return sortedList;
|
||||
}
|
||||
|
||||
// getCurrentRS returns the newest CR the given statefulSet targets (latest version)
|
||||
static getCurrentRevision(crList) {
|
||||
const current = _.last(crList);
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
export default KubernetesStatefulSetHistoryHelper;
|
Loading…
Add table
Add a link
Reference in a new issue