2020-07-05 23:21:03 +00:00
|
|
|
import angular from 'angular';
|
2021-02-26 15:50:33 +00:00
|
|
|
import _ from 'lodash-es';
|
2020-07-29 22:25:59 +00:00
|
|
|
import * as JsonPatch from 'fast-json-patch';
|
2022-12-12 01:30:05 +00:00
|
|
|
import { FeatureId } from '@/react/portainer/feature-flags/enums';
|
2022-01-16 19:37:46 +00:00
|
|
|
|
2021-09-07 00:37:26 +00:00
|
|
|
import {
|
|
|
|
KubernetesApplicationDataAccessPolicies,
|
|
|
|
KubernetesApplicationDeploymentTypes,
|
|
|
|
KubernetesApplicationTypes,
|
|
|
|
KubernetesDeploymentTypes,
|
|
|
|
} from 'Kubernetes/models/application/models';
|
2020-07-05 23:21:03 +00:00
|
|
|
import KubernetesEventHelper from 'Kubernetes/helpers/eventHelper';
|
|
|
|
import KubernetesApplicationHelper from 'Kubernetes/helpers/application';
|
2020-07-14 20:45:19 +00:00
|
|
|
import { KubernetesServiceTypes } from 'Kubernetes/models/service/models';
|
2020-07-29 22:25:59 +00:00
|
|
|
import { KubernetesPodNodeAffinityNodeSelectorRequirementOperators } from 'Kubernetes/pod/models';
|
2020-08-13 23:27:10 +00:00
|
|
|
import { KubernetesPodContainerTypes } from 'Kubernetes/pod/models/index';
|
2021-08-26 14:00:59 +00:00
|
|
|
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
|
2023-02-14 08:19:41 +00:00
|
|
|
import { confirmUpdate, confirm } from '@@/modals/confirm';
|
|
|
|
import { buildConfirmButton } from '@@/modals/utils';
|
|
|
|
import { ModalType } from '@@/modals';
|
2020-07-29 22:25:59 +00:00
|
|
|
|
|
|
|
function computeTolerations(nodes, application) {
|
|
|
|
const pod = application.Pods[0];
|
|
|
|
_.forEach(nodes, (n) => {
|
|
|
|
n.AcceptsApplication = true;
|
|
|
|
n.Expanded = false;
|
|
|
|
if (!pod) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
n.UnmetTaints = [];
|
|
|
|
_.forEach(n.Taints, (t) => {
|
2020-08-11 23:42:55 +00:00
|
|
|
const matchKeyMatchValueMatchEffect = _.find(pod.Tolerations, { Key: t.Key, Operator: 'Equal', Value: t.Value, Effect: t.Effect });
|
|
|
|
const matchKeyAnyValueMatchEffect = _.find(pod.Tolerations, { Key: t.Key, Operator: 'Exists', Effect: t.Effect });
|
|
|
|
const matchKeyMatchValueAnyEffect = _.find(pod.Tolerations, { Key: t.Key, Operator: 'Equal', Value: t.Value, Effect: '' });
|
|
|
|
const matchKeyAnyValueAnyEffect = _.find(pod.Tolerations, { Key: t.Key, Operator: 'Exists', Effect: '' });
|
2020-07-29 22:25:59 +00:00
|
|
|
const anyKeyAnyValueAnyEffect = _.find(pod.Tolerations, { Key: '', Operator: 'Exists', Effect: '' });
|
|
|
|
|
|
|
|
if (!matchKeyMatchValueMatchEffect && !matchKeyAnyValueMatchEffect && !matchKeyMatchValueAnyEffect && !matchKeyAnyValueAnyEffect && !anyKeyAnyValueAnyEffect) {
|
|
|
|
n.AcceptsApplication = false;
|
|
|
|
n.UnmetTaints.push(t);
|
|
|
|
} else {
|
|
|
|
n.AcceptsApplication = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return nodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
// For node requirement format depending on operator value
|
|
|
|
// see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#nodeselectorrequirement-v1-core
|
|
|
|
// Some operators require empty "values" field, some only one element in "values" field, etc
|
|
|
|
|
|
|
|
function computeAffinities(nodes, application) {
|
2020-08-31 05:21:25 +00:00
|
|
|
if (!application.Pods || application.Pods.length === 0) {
|
|
|
|
return nodes;
|
|
|
|
}
|
|
|
|
|
2020-07-29 22:25:59 +00:00
|
|
|
const pod = application.Pods[0];
|
|
|
|
_.forEach(nodes, (n) => {
|
|
|
|
if (pod.NodeSelector) {
|
|
|
|
const patch = JsonPatch.compare(n.Labels, pod.NodeSelector);
|
|
|
|
_.remove(patch, { op: 'remove' });
|
|
|
|
n.UnmatchedNodeSelectorLabels = _.map(patch, (i) => {
|
|
|
|
return { key: _.trimStart(i.path, '/'), value: i.value };
|
|
|
|
});
|
|
|
|
if (n.UnmatchedNodeSelectorLabels.length) {
|
|
|
|
n.AcceptsApplication = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-13 23:56:53 +00:00
|
|
|
if (pod.Affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution) {
|
|
|
|
const unmatchedTerms = _.map(pod.Affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms, (t) => {
|
2020-07-29 22:25:59 +00:00
|
|
|
const unmatchedExpressions = _.map(t.matchExpressions, (e) => {
|
|
|
|
const exists = {}.hasOwnProperty.call(n.Labels, e.key);
|
|
|
|
const isIn = exists && _.includes(e.values, n.Labels[e.key]);
|
|
|
|
if (
|
|
|
|
(e.operator === KubernetesPodNodeAffinityNodeSelectorRequirementOperators.EXISTS && exists) ||
|
|
|
|
(e.operator === KubernetesPodNodeAffinityNodeSelectorRequirementOperators.DOES_NOT_EXIST && !exists) ||
|
|
|
|
(e.operator === KubernetesPodNodeAffinityNodeSelectorRequirementOperators.IN && isIn) ||
|
|
|
|
(e.operator === KubernetesPodNodeAffinityNodeSelectorRequirementOperators.NOT_IN && !isIn) ||
|
2021-02-26 15:50:33 +00:00
|
|
|
(e.operator === KubernetesPodNodeAffinityNodeSelectorRequirementOperators.GREATER_THAN && exists && parseInt(n.Labels[e.key], 10) > parseInt(e.values[0], 10)) ||
|
|
|
|
(e.operator === KubernetesPodNodeAffinityNodeSelectorRequirementOperators.LOWER_THAN && exists && parseInt(n.Labels[e.key], 10) < parseInt(e.values[0], 10))
|
2020-07-29 22:25:59 +00:00
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
});
|
|
|
|
return _.without(unmatchedExpressions, undefined);
|
|
|
|
});
|
|
|
|
_.remove(unmatchedTerms, (i) => i.length === 0);
|
|
|
|
n.UnmatchedNodeAffinities = unmatchedTerms;
|
|
|
|
if (n.UnmatchedNodeAffinities.length) {
|
|
|
|
n.AcceptsApplication = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return nodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
function computePlacements(nodes, application) {
|
|
|
|
nodes = computeTolerations(nodes, application);
|
|
|
|
nodes = computeAffinities(nodes, application);
|
|
|
|
return nodes;
|
|
|
|
}
|
2020-07-05 23:21:03 +00:00
|
|
|
|
|
|
|
class KubernetesApplicationController {
|
|
|
|
/* @ngInject */
|
|
|
|
constructor(
|
|
|
|
$async,
|
|
|
|
$state,
|
|
|
|
clipboard,
|
|
|
|
Notifications,
|
|
|
|
LocalStorage,
|
2022-10-11 21:06:57 +00:00
|
|
|
KubernetesResourcePoolService,
|
2020-07-05 23:21:03 +00:00
|
|
|
KubernetesApplicationService,
|
|
|
|
KubernetesEventService,
|
|
|
|
KubernetesStackService,
|
|
|
|
KubernetesPodService,
|
2020-07-29 22:25:59 +00:00
|
|
|
KubernetesNodeService,
|
2021-09-02 05:28:51 +00:00
|
|
|
StackService
|
2020-07-05 23:21:03 +00:00
|
|
|
) {
|
|
|
|
this.$async = $async;
|
|
|
|
this.$state = $state;
|
|
|
|
this.clipboard = clipboard;
|
|
|
|
this.Notifications = Notifications;
|
|
|
|
this.LocalStorage = LocalStorage;
|
2022-10-11 21:06:57 +00:00
|
|
|
this.KubernetesResourcePoolService = KubernetesResourcePoolService;
|
2021-09-02 05:28:51 +00:00
|
|
|
this.StackService = StackService;
|
2020-07-05 23:21:03 +00:00
|
|
|
|
|
|
|
this.KubernetesApplicationService = KubernetesApplicationService;
|
|
|
|
this.KubernetesEventService = KubernetesEventService;
|
|
|
|
this.KubernetesStackService = KubernetesStackService;
|
|
|
|
this.KubernetesPodService = KubernetesPodService;
|
2020-07-29 22:25:59 +00:00
|
|
|
this.KubernetesNodeService = KubernetesNodeService;
|
2020-07-05 23:21:03 +00:00
|
|
|
|
2020-10-26 18:47:23 +00:00
|
|
|
this.KubernetesApplicationDeploymentTypes = KubernetesApplicationDeploymentTypes;
|
|
|
|
this.KubernetesApplicationTypes = KubernetesApplicationTypes;
|
2021-09-07 00:37:26 +00:00
|
|
|
this.KubernetesDeploymentTypes = KubernetesDeploymentTypes;
|
2021-04-29 01:10:14 +00:00
|
|
|
|
2020-07-05 23:21:03 +00:00
|
|
|
this.ApplicationDataAccessPolicies = KubernetesApplicationDataAccessPolicies;
|
2020-07-14 20:45:19 +00:00
|
|
|
this.KubernetesServiceTypes = KubernetesServiceTypes;
|
2020-08-13 23:27:10 +00:00
|
|
|
this.KubernetesPodContainerTypes = KubernetesPodContainerTypes;
|
2020-07-05 23:21:03 +00:00
|
|
|
|
|
|
|
this.onInit = this.onInit.bind(this);
|
|
|
|
this.getApplication = this.getApplication.bind(this);
|
|
|
|
this.getApplicationAsync = this.getApplicationAsync.bind(this);
|
|
|
|
this.getEvents = this.getEvents.bind(this);
|
|
|
|
this.getEventsAsync = this.getEventsAsync.bind(this);
|
2021-09-07 00:37:26 +00:00
|
|
|
this.updateApplicationKindText = this.updateApplicationKindText.bind(this);
|
2020-07-05 23:21:03 +00:00
|
|
|
this.updateApplicationAsync = this.updateApplicationAsync.bind(this);
|
|
|
|
this.redeployApplicationAsync = this.redeployApplicationAsync.bind(this);
|
|
|
|
this.rollbackApplicationAsync = this.rollbackApplicationAsync.bind(this);
|
|
|
|
this.copyLoadBalancerIP = this.copyLoadBalancerIP.bind(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
selectTab(index) {
|
|
|
|
this.LocalStorage.storeActiveTab('application', index);
|
|
|
|
}
|
|
|
|
|
|
|
|
showEditor() {
|
|
|
|
this.state.showEditorTab = true;
|
2020-12-10 06:44:24 +00:00
|
|
|
this.selectTab(3);
|
2020-07-05 23:21:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isSystemNamespace() {
|
2021-08-26 14:00:59 +00:00
|
|
|
return KubernetesNamespaceHelper.isSystemNamespace(this.application.ResourcePool);
|
2020-07-05 23:21:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isExternalApplication() {
|
|
|
|
return KubernetesApplicationHelper.isExternalApplication(this.application);
|
|
|
|
}
|
|
|
|
|
|
|
|
copyLoadBalancerIP() {
|
|
|
|
this.clipboard.copyText(this.application.LoadBalancerIPAddress);
|
|
|
|
$('#copyNotificationLB').show().fadeOut(2500);
|
|
|
|
}
|
|
|
|
|
|
|
|
copyApplicationName() {
|
|
|
|
this.clipboard.copyText(this.application.Name);
|
|
|
|
$('#copyNotificationApplicationName').show().fadeOut(2500);
|
|
|
|
}
|
|
|
|
|
|
|
|
hasPersistedFolders() {
|
|
|
|
return this.application && this.application.PersistedFolders.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
hasVolumeConfiguration() {
|
|
|
|
return this.application && this.application.ConfigurationVolumes.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
hasEventWarnings() {
|
|
|
|
return this.state.eventWarningCount;
|
|
|
|
}
|
|
|
|
|
2020-07-14 20:45:19 +00:00
|
|
|
buildIngressRuleURL(rule) {
|
|
|
|
const hostname = rule.Host ? rule.Host : rule.IP;
|
|
|
|
return 'http://' + hostname + rule.Path;
|
|
|
|
}
|
|
|
|
|
|
|
|
portHasIngressRules(port) {
|
|
|
|
return port.IngressRules.length > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ruleCanBeDisplayed(rule) {
|
|
|
|
return !rule.Host && !rule.IP ? false : true;
|
|
|
|
}
|
|
|
|
|
2021-09-02 05:28:51 +00:00
|
|
|
isStack() {
|
|
|
|
return this.application.StackId;
|
|
|
|
}
|
|
|
|
|
2020-07-05 23:21:03 +00:00
|
|
|
/**
|
|
|
|
* ROLLBACK
|
|
|
|
*/
|
|
|
|
async rollbackApplicationAsync() {
|
|
|
|
try {
|
|
|
|
// await this.KubernetesApplicationService.rollback(this.application, this.formValues.SelectedRevision);
|
|
|
|
const revision = _.nth(this.application.Revisions, -2);
|
|
|
|
await this.KubernetesApplicationService.rollback(this.application, revision);
|
2022-08-10 05:07:35 +00:00
|
|
|
this.Notifications.success('Success', 'Application successfully rolled back');
|
2021-09-24 08:21:50 +00:00
|
|
|
this.$state.reload(this.$state.current);
|
2020-07-05 23:21:03 +00:00
|
|
|
} catch (err) {
|
|
|
|
this.Notifications.error('Failure', err, 'Unable to rollback the application');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rollbackApplication() {
|
2023-02-14 08:19:41 +00:00
|
|
|
confirmUpdate('Rolling back the application to a previous configuration may cause service interruption. Do you wish to continue?', (confirmed) => {
|
2020-07-05 23:21:03 +00:00
|
|
|
if (confirmed) {
|
|
|
|
return this.$async(this.rollbackApplicationAsync);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* REDEPLOY
|
|
|
|
*/
|
|
|
|
async redeployApplicationAsync() {
|
2023-02-14 08:19:41 +00:00
|
|
|
const confirmed = await confirm({
|
|
|
|
modalType: ModalType.Warn,
|
2023-01-09 21:02:07 +00:00
|
|
|
title: 'Are you sure?',
|
2023-01-17 19:30:06 +00:00
|
|
|
message: 'Redeploying the application may cause a service interruption. Do you wish to continue?',
|
2023-02-14 08:19:41 +00:00
|
|
|
confirmButton: buildConfirmButton('Redeploy'),
|
2023-01-09 21:02:07 +00:00
|
|
|
});
|
|
|
|
if (!confirmed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-05 23:21:03 +00:00
|
|
|
try {
|
|
|
|
const promises = _.map(this.application.Pods, (item) => this.KubernetesPodService.delete(item));
|
|
|
|
await Promise.all(promises);
|
2022-08-10 05:07:35 +00:00
|
|
|
this.Notifications.success('Success', 'Application successfully redeployed');
|
2021-09-24 08:21:50 +00:00
|
|
|
this.$state.reload(this.$state.current);
|
2020-07-05 23:21:03 +00:00
|
|
|
} catch (err) {
|
|
|
|
this.Notifications.error('Failure', err, 'Unable to redeploy the application');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
redeployApplication() {
|
2023-01-09 21:02:07 +00:00
|
|
|
return this.$async(this.redeployApplicationAsync);
|
2020-07-05 23:21:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* UPDATE
|
|
|
|
*/
|
|
|
|
async updateApplicationAsync() {
|
|
|
|
try {
|
|
|
|
const application = angular.copy(this.application);
|
|
|
|
application.Note = this.formValues.Note;
|
|
|
|
await this.KubernetesApplicationService.patch(this.application, application, true);
|
2022-08-10 05:07:35 +00:00
|
|
|
this.Notifications.success('Success', 'Application successfully updated');
|
2021-09-24 08:21:50 +00:00
|
|
|
this.$state.reload(this.$state.current);
|
2020-07-05 23:21:03 +00:00
|
|
|
} catch (err) {
|
|
|
|
this.Notifications.error('Failure', err, 'Unable to update application');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
updateApplication() {
|
|
|
|
return this.$async(this.updateApplicationAsync);
|
|
|
|
}
|
|
|
|
|
2021-09-07 00:37:26 +00:00
|
|
|
updateApplicationKindText() {
|
|
|
|
if (this.application.ApplicationKind === this.KubernetesDeploymentTypes.GIT) {
|
|
|
|
this.state.appType = `git repository`;
|
|
|
|
} else if (this.application.ApplicationKind === this.KubernetesDeploymentTypes.CONTENT) {
|
2021-09-29 23:59:19 +00:00
|
|
|
this.state.appType = `manifest`;
|
|
|
|
} else if (this.application.ApplicationKind === this.KubernetesDeploymentTypes.URL) {
|
|
|
|
this.state.appType = `manifest`;
|
2021-09-07 00:37:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-05 23:21:03 +00:00
|
|
|
/**
|
|
|
|
* EVENTS
|
|
|
|
*/
|
|
|
|
async getEventsAsync() {
|
|
|
|
try {
|
|
|
|
this.state.eventsLoading = true;
|
|
|
|
const events = await this.KubernetesEventService.get(this.state.params.namespace);
|
|
|
|
this.events = _.filter(
|
|
|
|
events,
|
|
|
|
(event) =>
|
|
|
|
event.Involved.uid === this.application.Id ||
|
|
|
|
event.Involved.uid === this.application.ServiceId ||
|
|
|
|
_.find(this.application.Pods, (pod) => pod.Id === event.Involved.uid) !== undefined
|
|
|
|
);
|
|
|
|
this.state.eventWarningCount = KubernetesEventHelper.warningCount(this.events);
|
|
|
|
} catch (err) {
|
|
|
|
this.Notifications.error('Failure', err, 'Unable to retrieve application related events');
|
|
|
|
} finally {
|
|
|
|
this.state.eventsLoading = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
getEvents() {
|
|
|
|
return this.$async(this.getEventsAsync);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* APPLICATION
|
|
|
|
*/
|
|
|
|
async getApplicationAsync() {
|
|
|
|
try {
|
|
|
|
this.state.dataLoading = true;
|
2020-07-29 22:25:59 +00:00
|
|
|
const [application, nodes] = await Promise.all([
|
|
|
|
this.KubernetesApplicationService.get(this.state.params.namespace, this.state.params.name),
|
|
|
|
this.KubernetesNodeService.get(),
|
|
|
|
]);
|
|
|
|
this.application = application;
|
2023-01-26 03:03:44 +00:00
|
|
|
if (this.application.StackId) {
|
|
|
|
this.stack = await this.StackService.stack(application.StackId);
|
|
|
|
}
|
2020-08-13 23:27:10 +00:00
|
|
|
this.allContainers = KubernetesApplicationHelper.associateAllContainersAndApplication(application);
|
2020-07-05 23:21:03 +00:00
|
|
|
this.formValues.Note = this.application.Note;
|
2022-01-16 19:37:46 +00:00
|
|
|
this.formValues.Services = this.application.Services;
|
2020-07-05 23:21:03 +00:00
|
|
|
if (this.application.Note) {
|
|
|
|
this.state.expandedNote = true;
|
|
|
|
}
|
|
|
|
if (this.application.CurrentRevision) {
|
|
|
|
this.formValues.SelectedRevision = _.find(this.application.Revisions, { revision: this.application.CurrentRevision.revision });
|
|
|
|
}
|
2020-07-29 22:25:59 +00:00
|
|
|
|
2020-08-20 00:51:14 +00:00
|
|
|
this.state.useIngress = _.find(application.PublishedPorts, (p) => {
|
|
|
|
return this.portHasIngressRules(p);
|
|
|
|
});
|
|
|
|
|
2020-07-29 22:25:59 +00:00
|
|
|
this.placements = computePlacements(nodes, this.application);
|
2021-01-20 00:02:18 +00:00
|
|
|
this.state.placementWarning = _.find(this.placements, { AcceptsApplication: true }) ? false : true;
|
2021-09-02 05:28:51 +00:00
|
|
|
|
|
|
|
if (application.StackId) {
|
|
|
|
const file = await this.StackService.getStackFile(application.StackId);
|
|
|
|
this.stackFileContent = file;
|
|
|
|
}
|
2020-07-05 23:21:03 +00:00
|
|
|
} catch (err) {
|
|
|
|
this.Notifications.error('Failure', err, 'Unable to retrieve application details');
|
|
|
|
} finally {
|
|
|
|
this.state.dataLoading = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
getApplication() {
|
|
|
|
return this.$async(this.getApplicationAsync);
|
|
|
|
}
|
|
|
|
|
|
|
|
async onInit() {
|
2022-12-12 01:30:05 +00:00
|
|
|
this.limitedFeature = FeatureId.K8S_ROLLING_RESTART;
|
|
|
|
|
2020-07-05 23:21:03 +00:00
|
|
|
this.state = {
|
|
|
|
activeTab: 0,
|
|
|
|
currentName: this.$state.$current.name,
|
|
|
|
showEditorTab: false,
|
|
|
|
DisplayedPanel: 'pods',
|
|
|
|
eventsLoading: true,
|
|
|
|
dataLoading: true,
|
|
|
|
viewReady: false,
|
|
|
|
params: {
|
|
|
|
namespace: this.$transition$.params().namespace,
|
|
|
|
name: this.$transition$.params().name,
|
|
|
|
},
|
2021-09-07 00:37:26 +00:00
|
|
|
appType: this.KubernetesDeploymentTypes.APPLICATION_FORM,
|
2020-07-05 23:21:03 +00:00
|
|
|
eventWarningCount: 0,
|
2021-01-20 00:02:18 +00:00
|
|
|
placementWarning: false,
|
2020-07-05 23:21:03 +00:00
|
|
|
expandedNote: false,
|
2020-08-20 00:51:14 +00:00
|
|
|
useIngress: false,
|
2021-12-14 07:34:54 +00:00
|
|
|
useServerMetrics: this.endpoint.Kubernetes.Configuration.UseServerMetrics,
|
2022-03-08 12:14:23 +00:00
|
|
|
publicUrl: this.endpoint.PublicURL,
|
2020-07-05 23:21:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
this.state.activeTab = this.LocalStorage.getActiveTab('application');
|
|
|
|
|
|
|
|
this.formValues = {
|
|
|
|
Note: '',
|
|
|
|
SelectedRevision: undefined,
|
|
|
|
};
|
|
|
|
|
2022-10-11 21:06:57 +00:00
|
|
|
const resourcePools = await this.KubernetesResourcePoolService.get();
|
|
|
|
this.allNamespaces = resourcePools.map(({ Namespace }) => Namespace.Name);
|
|
|
|
|
2020-07-05 23:21:03 +00:00
|
|
|
await this.getApplication();
|
|
|
|
await this.getEvents();
|
2021-09-07 00:37:26 +00:00
|
|
|
this.updateApplicationKindText();
|
2020-07-05 23:21:03 +00:00
|
|
|
this.state.viewReady = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$onInit() {
|
|
|
|
return this.$async(this.onInit);
|
|
|
|
}
|
|
|
|
|
|
|
|
$onDestroy() {
|
|
|
|
if (this.state.currentName !== this.$state.$current.name) {
|
|
|
|
this.LocalStorage.storeActiveTab('application', 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default KubernetesApplicationController;
|
|
|
|
angular.module('portainer.kubernetes').controller('KubernetesApplicationController', KubernetesApplicationController);
|