From abf517de2826334271507ebeedf92dbbe13cf344 Mon Sep 17 00:00:00 2001
From: Ali <83188384+testA113@users.noreply.github.com>
Date: Fri, 5 Jan 2024 15:42:36 +1300
Subject: [PATCH] refactor(app): migrate app summary section [EE-6239] (#10910)
---
.../applicationsDatatable.html | 14 +-
.../applicationsDatatableController.js | 9 +-
.../nodeApplicationsDatatableController.js | 2 +-
app/kubernetes/converters/application.js | 55 +-
.../converters/persistentVolumeClaim.js | 2 +-
app/kubernetes/converters/service.js | 28 +-
app/kubernetes/filters/applicationFilters.js | 40 +-
app/kubernetes/helpers/application/index.js | 30 +-
app/kubernetes/helpers/volumeHelper.js | 6 +-
.../horizontal-pod-auto-scaler/converter.js | 84 +--
.../horizontal-pod-auto-scaler/helper.js | 21 +-
app/kubernetes/ingress/converter.js | 31 --
.../models/application/formValues.js | 18 +-
.../models/application/models/appConstants.ts | 41 ++
.../models/application/models/constants.js | 32 --
app/kubernetes/react/components/index.ts | 41 +-
app/kubernetes/services/applicationService.js | 26 +-
.../applications/applicationsController.js | 4 +-
.../create/createApplication.html | 28 +-
.../create/createApplicationController.js | 139 ++---
.../summary/resources/applicationResources.js | 34 +-
.../AdvancedMode.tsx | 6 +-
.../EnvironmentVariablesFieldset.tsx | 10 +-
.../EnvironmentVariablesPanel.tsx | 8 +-
.../SimpleMode.tsx | 10 +-
.../EnvironmentVariablesFieldset/index.ts | 2 +-
.../EnvironmentVariablesFieldset/types.ts | 2 +-
.../CreateView/EnvVarsTab/EnvVarsTab.tsx | 15 +-
.../containers/CreateView/EnvVarsTab/index.ts | 1 -
.../CreateView/EnvVarsTab/toRequest.ts | 5 +-
.../containers/CreateView/EnvVarsTab/types.ts | 1 -
.../containers/CreateView/useInitialValues.ts | 9 +-
.../AppDeploymentTypeFormSection.tsx | 6 +-
.../DataAccessPolicyFormSection.tsx | 23 +-
.../application-services/KubeServicesForm.tsx | 31 +-
.../cluster-ip/ClusterIpServiceForm.tsx | 10 +-
.../cluster-ip/ClusterIpServicesForm.tsx | 10 +-
.../components/ContainerPortInput.tsx | 2 +-
.../components/ServicePortInput.tsx | 2 +-
.../components/ServiceTabs.tsx | 8 +-
.../kubeServicesValidation.ts | 31 +-
.../load-balancer/LoadBalancerServiceForm.tsx | 17 +-
.../LoadBalancerServicesForm.tsx | 10 +-
.../node-port/NodePortServiceForm.tsx | 12 +-
.../node-port/NodePortServicesForm.tsx | 9 +-
.../CreateView/application-services/types.ts | 13 +-
.../CreateView/application-services/utils.ts | 83 ++-
.../CreateView/deploymentOptions.tsx | 10 +-
.../ApplicationSummarySection.tsx | 73 +++
.../ApplicationSummarySection/index.ts | 1 +
.../ApplicationSummarySection/types.ts | 21 +
.../ApplicationSummarySection/utils.test.ts | 517 ++++++++++++++++++
.../ApplicationSummarySection/utils.ts | 362 ++++++++++++
.../PersistedFolderItem.tsx | 4 +-
.../PersistedFoldersFormSection.tsx | 38 +-
.../PlacementFormSection.tsx | 6 +-
.../kubernetes/applications/constants.ts | 3 +-
app/react/kubernetes/applications/types.ts | 41 +-
.../CreateIngressView/CreateIngressView.tsx | 4 +-
.../ingresses/CreateIngressView/utils.ts | 8 -
app/react/kubernetes/utils.ts | 13 +
61 files changed, 1461 insertions(+), 661 deletions(-)
create mode 100644 app/kubernetes/models/application/models/appConstants.ts
delete mode 100644 app/react/docker/containers/CreateView/EnvVarsTab/types.ts
create mode 100644 app/react/kubernetes/applications/components/ApplicationSummarySection/ApplicationSummarySection.tsx
create mode 100644 app/react/kubernetes/applications/components/ApplicationSummarySection/index.ts
create mode 100644 app/react/kubernetes/applications/components/ApplicationSummarySection/types.ts
create mode 100644 app/react/kubernetes/applications/components/ApplicationSummarySection/utils.test.ts
create mode 100644 app/react/kubernetes/applications/components/ApplicationSummarySection/utils.ts
diff --git a/app/kubernetes/components/datatables/applications-datatable/applicationsDatatable.html b/app/kubernetes/components/datatables/applications-datatable/applicationsDatatable.html
index 6bbe34867..b4ce05c44 100644
--- a/app/kubernetes/components/datatables/applications-datatable/applicationsDatatable.html
+++ b/app/kubernetes/components/datatables/applications-datatable/applicationsDatatable.html
@@ -219,7 +219,7 @@
@@ -282,7 +282,7 @@
{{ item.Name }}
@@ -297,17 +297,17 @@
{{ item.Image | truncate: 64 }} + {{ item.Containers.length - 1 }} |
-
{{ item.ApplicationType | kubernetesApplicationTypeText }} |
-
+ | {{ item.ApplicationType }} |
+
- Replicated
- Global
+ Replicated
+ Global
{{ item.RunningPodsCount }} / {{ item.TotalPodsCount }}
{{ item.Status }}
|
-
+ |
{{ item.Pods[0].Status }}
|
diff --git a/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js b/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js
index d80b951fe..527a2d6e2 100644
--- a/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js
+++ b/app/kubernetes/components/datatables/applications-datatable/applicationsDatatableController.js
@@ -1,8 +1,8 @@
import _ from 'lodash-es';
-import { KubernetesApplicationDeploymentTypes, KubernetesApplicationTypes } from 'Kubernetes/models/application/models';
import KubernetesApplicationHelper from 'Kubernetes/helpers/application';
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
import { KubernetesConfigurationKinds } from 'Kubernetes/models/configuration/models';
+import { KubernetesApplicationDeploymentTypes, KubernetesApplicationTypes } from 'Kubernetes/models/application/models/appConstants';
angular.module('portainer.kubernetes').controller('KubernetesApplicationsDatatableController', [
'$scope',
@@ -33,13 +33,6 @@ angular.module('portainer.kubernetes').controller('KubernetesApplicationsDatatab
},
};
- this.applicationTypeEnumToParamMap = {
- [KubernetesApplicationTypes.DEPLOYMENT]: 'Deployment',
- [KubernetesApplicationTypes.DAEMONSET]: 'DaemonSet',
- [KubernetesApplicationTypes.STATEFULSET]: 'StatefulSet',
- [KubernetesApplicationTypes.POD]: 'Pod',
- };
-
this.expandAll = function () {
this.state.expandAll = !this.state.expandAll;
this.state.filteredDataSet.forEach((item) => this.expandItem(item, this.state.expandAll));
diff --git a/app/kubernetes/components/datatables/node-applications-datatable/nodeApplicationsDatatableController.js b/app/kubernetes/components/datatables/node-applications-datatable/nodeApplicationsDatatableController.js
index 447dcc013..3c9d19e24 100644
--- a/app/kubernetes/components/datatables/node-applications-datatable/nodeApplicationsDatatableController.js
+++ b/app/kubernetes/components/datatables/node-applications-datatable/nodeApplicationsDatatableController.js
@@ -1,4 +1,4 @@
-import { KubernetesApplicationDeploymentTypes } from 'Kubernetes/models/application/models';
+import { KubernetesApplicationDeploymentTypes } from 'Kubernetes/models/application/models/appConstants';
import KubernetesApplicationHelper from 'Kubernetes/helpers/application';
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
diff --git a/app/kubernetes/converters/application.js b/app/kubernetes/converters/application.js
index d3161b410..524c92511 100644
--- a/app/kubernetes/converters/application.js
+++ b/app/kubernetes/converters/application.js
@@ -1,15 +1,12 @@
import _ from 'lodash-es';
import filesizeParser from 'filesize-parser';
+import { KubernetesApplicationDataAccessPolicies, KubernetesApplicationDeploymentTypes, KubernetesApplicationTypes } from 'Kubernetes/models/application/models/appConstants';
import {
KubernetesApplication,
KubernetesApplicationConfigurationVolume,
- KubernetesApplicationDataAccessPolicies,
- KubernetesApplicationDeploymentTypes,
KubernetesApplicationPersistedFolder,
KubernetesApplicationPort,
- KubernetesApplicationPublishingTypes,
- KubernetesApplicationTypes,
KubernetesPortainerApplicationNameLabel,
KubernetesPortainerApplicationNote,
KubernetesPortainerApplicationOwnerLabel,
@@ -241,16 +238,16 @@ class KubernetesApplicationConverter {
static apiPodToApplication(data, pods, service, ingresses) {
const res = new KubernetesApplication();
KubernetesApplicationConverter.applicationCommon(res, data, pods, service, ingresses);
- res.ApplicationType = KubernetesApplicationTypes.POD;
+ res.ApplicationType = KubernetesApplicationTypes.Pod;
return res;
}
static apiDeploymentToApplication(data, pods, service, ingresses) {
const res = new KubernetesApplication();
KubernetesApplicationConverter.applicationCommon(res, data, pods, service, ingresses);
- res.ApplicationType = KubernetesApplicationTypes.DEPLOYMENT;
- res.DeploymentType = KubernetesApplicationDeploymentTypes.REPLICATED;
- res.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.SHARED;
+ res.ApplicationType = KubernetesApplicationTypes.Deployment;
+ res.DeploymentType = KubernetesApplicationDeploymentTypes.Replicated;
+ res.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.Shared;
res.RunningPodsCount = data.status.availableReplicas || data.status.replicas - data.status.unavailableReplicas || 0;
res.TotalPodsCount = data.spec.replicas;
return res;
@@ -259,9 +256,9 @@ class KubernetesApplicationConverter {
static apiDaemonSetToApplication(data, pods, service, ingresses) {
const res = new KubernetesApplication();
KubernetesApplicationConverter.applicationCommon(res, data, pods, service, ingresses);
- res.ApplicationType = KubernetesApplicationTypes.DAEMONSET;
- res.DeploymentType = KubernetesApplicationDeploymentTypes.GLOBAL;
- res.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.SHARED;
+ res.ApplicationType = KubernetesApplicationTypes.DaemonSet;
+ res.DeploymentType = KubernetesApplicationDeploymentTypes.Global;
+ res.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.Shared;
res.RunningPodsCount = data.status.numberAvailable || data.status.desiredNumberScheduled - data.status.numberUnavailable || 0;
res.TotalPodsCount = data.status.desiredNumberScheduled;
return res;
@@ -270,9 +267,9 @@ class KubernetesApplicationConverter {
static apiStatefulSetToapplication(data, pods, service, ingresses) {
const res = new KubernetesApplication();
KubernetesApplicationConverter.applicationCommon(res, data, pods, service, ingresses);
- res.ApplicationType = KubernetesApplicationTypes.STATEFULSET;
- res.DeploymentType = KubernetesApplicationDeploymentTypes.REPLICATED;
- res.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.ISOLATED;
+ res.ApplicationType = KubernetesApplicationTypes.StatefulSet;
+ res.DeploymentType = KubernetesApplicationDeploymentTypes.Replicated;
+ res.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.Isolated;
res.RunningPodsCount = data.status.readyReplicas || 0;
res.TotalPodsCount = data.spec.replicas;
res.HeadlessServiceName = data.spec.serviceName;
@@ -313,16 +310,7 @@ class KubernetesApplicationConverter {
res.PublishedPorts = KubernetesApplicationHelper.generatePublishedPortsFormValuesFromPublishedPorts(app.ServiceType, app.PublishedPorts, ingresses);
res.Containers = app.Containers;
- const isIngress = _.filter(res.PublishedPorts, (p) => p.IngressName).length;
- if (app.ServiceType === KubernetesServiceTypes.LOAD_BALANCER) {
- res.PublishingType = KubernetesApplicationPublishingTypes.LOAD_BALANCER;
- } else if (app.ServiceType === KubernetesServiceTypes.NODE_PORT) {
- res.PublishingType = KubernetesApplicationPublishingTypes.NODE_PORT;
- } else if (app.ServiceType === KubernetesServiceTypes.CLUSTER_IP && isIngress) {
- res.PublishingType = KubernetesApplicationPublishingTypes.INGRESS;
- } else {
- res.PublishingType = KubernetesApplicationPublishingTypes.CLUSTER_IP;
- }
+ res.PublishingType = app.ServiceType;
if (app.Pods && app.Pods.length) {
KubernetesApplicationHelper.generatePlacementsFormValuesFromAffinity(res, app.Pods[0].Affinity);
@@ -338,20 +326,20 @@ class KubernetesApplicationConverter {
const rwx = KubernetesApplicationHelper.hasRWX(claims);
const deployment =
- (formValues.DeploymentType === KubernetesApplicationDeploymentTypes.REPLICATED &&
- (claims.length === 0 || (claims.length > 0 && formValues.DataAccessPolicy === KubernetesApplicationDataAccessPolicies.SHARED))) ||
- formValues.ApplicationType === KubernetesApplicationTypes.DEPLOYMENT;
+ (formValues.DeploymentType === KubernetesApplicationDeploymentTypes.Replicated &&
+ (claims.length === 0 || (claims.length > 0 && formValues.DataAccessPolicy === KubernetesApplicationDataAccessPolicies.Shared))) ||
+ formValues.ApplicationType === KubernetesApplicationTypes.Deployment;
const statefulSet =
- (formValues.DeploymentType === KubernetesApplicationDeploymentTypes.REPLICATED &&
+ (formValues.DeploymentType === KubernetesApplicationDeploymentTypes.Replicated &&
claims.length > 0 &&
- formValues.DataAccessPolicy === KubernetesApplicationDataAccessPolicies.ISOLATED) ||
- formValues.ApplicationType === KubernetesApplicationTypes.STATEFULSET;
+ formValues.DataAccessPolicy === KubernetesApplicationDataAccessPolicies.Isolated) ||
+ formValues.ApplicationType === KubernetesApplicationTypes.StatefulSet;
const daemonSet =
- (formValues.DeploymentType === KubernetesApplicationDeploymentTypes.GLOBAL &&
- (claims.length === 0 || (claims.length > 0 && formValues.DataAccessPolicy === KubernetesApplicationDataAccessPolicies.SHARED && rwx))) ||
- formValues.ApplicationType === KubernetesApplicationTypes.DAEMONSET;
+ (formValues.DeploymentType === KubernetesApplicationDeploymentTypes.Global &&
+ (claims.length === 0 || (claims.length > 0 && formValues.DataAccessPolicy === KubernetesApplicationDataAccessPolicies.Shared && rwx))) ||
+ formValues.ApplicationType === KubernetesApplicationTypes.DaemonSet;
let app;
if (deployment) {
@@ -363,6 +351,7 @@ class KubernetesApplicationConverter {
} else {
throw new PortainerError('Unable to determine which association to use to convert form');
}
+ app.ApplicationType = formValues.ApplicationType;
let headlessService;
if (statefulSet) {
diff --git a/app/kubernetes/converters/persistentVolumeClaim.js b/app/kubernetes/converters/persistentVolumeClaim.js
index 363c7365e..c80563682 100644
--- a/app/kubernetes/converters/persistentVolumeClaim.js
+++ b/app/kubernetes/converters/persistentVolumeClaim.js
@@ -71,7 +71,7 @@ class KubernetesPersistentVolumeClaimConverter {
res.metadata.namespace = pvc.Namespace;
res.spec.resources.requests.storage = pvc.Storage;
res.spec.storageClassName = pvc.storageClass ? pvc.storageClass.Name : '';
- const accessModes = pvc.StorageClass && pvc.StorageClass.AccessModes ? pvc.StorageClass.AccessModes.map((accessMode) => storageClassToPVCAccessModes[accessMode]) : [];
+ const accessModes = pvc.storageClass && pvc.storageClass.AccessModes ? pvc.storageClass.AccessModes.map((accessMode) => storageClassToPVCAccessModes[accessMode]) : [];
res.spec.accessModes = accessModes;
res.metadata.labels.app = pvc.ApplicationName;
res.metadata.labels[KubernetesPortainerApplicationOwnerLabel] = pvc.ApplicationOwner;
diff --git a/app/kubernetes/converters/service.js b/app/kubernetes/converters/service.js
index 420c6df26..bda4b6a0e 100644
--- a/app/kubernetes/converters/service.js
+++ b/app/kubernetes/converters/service.js
@@ -3,7 +3,6 @@ import * as JsonPatch from 'fast-json-patch';
import { KubernetesServiceCreatePayload } from 'Kubernetes/models/service/payloads';
import {
- KubernetesApplicationPublishingTypes,
KubernetesPortainerApplicationNameLabel,
KubernetesPortainerApplicationOwnerLabel,
KubernetesPortainerApplicationStackNameLabel,
@@ -42,11 +41,7 @@ class KubernetesServiceConverter {
res.StackName = formValues.StackName ? formValues.StackName : formValues.Name;
res.ApplicationOwner = formValues.ApplicationOwner;
res.ApplicationName = formValues.Name;
- if (formValues.PublishingType === KubernetesApplicationPublishingTypes.NODE_PORT) {
- res.Type = KubernetesServiceTypes.NODE_PORT;
- } else if (formValues.PublishingType === KubernetesApplicationPublishingTypes.LOAD_BALANCER) {
- res.Type = KubernetesServiceTypes.LOAD_BALANCER;
- }
+ res.Type = formValues.PublishingType;
const ports = _.map(formValues.PublishedPorts, (item) => _publishedPortToServicePort(formValues, item, res.Type));
res.Ports = _.uniqBy(_.without(ports, undefined), (p) => p.targetPort + p.protocol);
return res;
@@ -61,13 +56,7 @@ class KubernetesServiceConverter {
res.StackName = formValues.StackName ? formValues.StackName : formValues.Name;
res.ApplicationOwner = formValues.ApplicationOwner;
res.ApplicationName = formValues.Name;
- if (service.Type === KubernetesApplicationPublishingTypes.NODE_PORT) {
- res.Type = KubernetesServiceTypes.NODE_PORT;
- } else if (service.Type === KubernetesApplicationPublishingTypes.LOAD_BALANCER) {
- res.Type = KubernetesServiceTypes.LOAD_BALANCER;
- } else if (service.Type === KubernetesApplicationPublishingTypes.CLUSTER_IP) {
- res.Type = KubernetesServiceTypes.CLUSTER_IP;
- }
+ res.Type = service.Type;
res.Ingress = service.Ingress;
if (service.Selector !== undefined) {
@@ -120,18 +109,7 @@ class KubernetesServiceConverter {
payload.metadata.labels[KubernetesPortainerApplicationNameLabel] = service.ApplicationName;
payload.metadata.labels[KubernetesPortainerApplicationOwnerLabel] = service.ApplicationOwner;
- const ports = [];
- service.Ports.forEach((port) => {
- const p = {};
- p.name = port.name;
- p.port = port.port;
- p.nodePort = port.nodePort;
- p.protocol = port.protocol;
- p.targetPort = port.targetPort;
- ports.push(p);
- });
- payload.spec.ports = ports;
-
+ payload.spec.ports = service.Ports;
payload.spec.selector = service.Selector;
if (service.Headless) {
payload.spec.clusterIP = KubernetesServiceHeadlessClusterIP;
diff --git a/app/kubernetes/filters/applicationFilters.js b/app/kubernetes/filters/applicationFilters.js
index 8b4fe62c0..4b1c97649 100644
--- a/app/kubernetes/filters/applicationFilters.js
+++ b/app/kubernetes/filters/applicationFilters.js
@@ -1,29 +1,8 @@
import _ from 'lodash-es';
-import { KubernetesApplicationDataAccessPolicies } from 'Kubernetes/models/application/models';
-import { KubernetesApplicationTypes, KubernetesApplicationTypeStrings } from 'Kubernetes/models/application/models';
import { nodeAffinityValues } from './application';
angular
.module('portainer.kubernetes')
- .filter('kubernetesApplicationTypeText', function () {
- 'use strict';
- return function (type) {
- switch (type) {
- case KubernetesApplicationTypes.DEPLOYMENT:
- return KubernetesApplicationTypeStrings.DEPLOYMENT;
- case KubernetesApplicationTypes.DAEMONSET:
- return KubernetesApplicationTypeStrings.DAEMONSET;
- case KubernetesApplicationTypes.STATEFULSET:
- return KubernetesApplicationTypeStrings.STATEFULSET;
- case KubernetesApplicationTypes.POD:
- return KubernetesApplicationTypeStrings.POD;
- case KubernetesApplicationTypes.HELM:
- return KubernetesApplicationTypeStrings.HELM;
- default:
- return '-';
- }
- };
- })
.filter('kubernetesApplicationCPUValue', function () {
'use strict';
return function (value) {
@@ -34,31 +13,20 @@ angular
'use strict';
return function (value) {
switch (value) {
- case KubernetesApplicationDataAccessPolicies.ISOLATED:
+ case 'Isolated':
return 'boxes';
- case KubernetesApplicationDataAccessPolicies.SHARED:
+ case 'Shared':
return 'box';
}
};
})
- .filter('kubernetesApplicationDataAccessPolicyText', function () {
- 'use strict';
- return function (value) {
- switch (value) {
- case KubernetesApplicationDataAccessPolicies.ISOLATED:
- return 'Isolated';
- case KubernetesApplicationDataAccessPolicies.SHARED:
- return 'Shared';
- }
- };
- })
.filter('kubernetesApplicationDataAccessPolicyTooltip', function () {
'use strict';
return function (value) {
switch (value) {
- case KubernetesApplicationDataAccessPolicies.ISOLATED:
+ case 'Isolated':
return 'All the instances of this application are using their own data.';
- case KubernetesApplicationDataAccessPolicies.SHARED:
+ case 'Shared':
return 'All the instances of this application are sharing the same data.';
}
};
diff --git a/app/kubernetes/helpers/application/index.js b/app/kubernetes/helpers/application/index.js
index 115f5208f..9d21e469e 100644
--- a/app/kubernetes/helpers/application/index.js
+++ b/app/kubernetes/helpers/application/index.js
@@ -22,7 +22,8 @@ import {
KubernetesApplicationVolumeSecretPayload,
} from 'Kubernetes/models/application/payloads';
import KubernetesVolumeHelper from 'Kubernetes/helpers/volumeHelper';
-import { KubernetesApplicationDeploymentTypes, KubernetesApplicationTypes, HelmApplication } from 'Kubernetes/models/application/models';
+import { HelmApplication } from 'Kubernetes/models/application/models';
+import { KubernetesApplicationDeploymentTypes, KubernetesApplicationTypes } from 'Kubernetes/models/application/models/appConstants';
import { KubernetesPodAffinity, KubernetesPodNodeAffinityNodeSelectorRequirementOperators } from 'Kubernetes/pod/models';
import {
KubernetesNodeSelectorRequirementPayload,
@@ -287,13 +288,6 @@ class KubernetesApplicationHelper {
svc.ApplicationOwner = app.ApplicationOwner;
svc.ApplicationName = app.ApplicationName;
svc.Type = service.spec.type;
- if (service.spec.type === KubernetesServiceTypes.CLUSTER_IP) {
- svc.Type = 1;
- } else if (service.spec.type === KubernetesServiceTypes.NODE_PORT) {
- svc.Type = 2;
- } else if (service.spec.type === KubernetesServiceTypes.LOAD_BALANCER) {
- svc.Type = 3;
- }
let ports = [];
service.spec.ports.forEach(function (port) {
@@ -373,15 +367,15 @@ class KubernetesApplicationHelper {
static generateAutoScalerFormValueFromHorizontalPodAutoScaler(autoScaler, replicasCount) {
const res = new KubernetesApplicationAutoScalerFormValue();
if (autoScaler) {
- res.IsUsed = true;
- res.MinReplicas = autoScaler.MinReplicas;
- res.MaxReplicas = autoScaler.MaxReplicas;
- res.TargetCPUUtilization = autoScaler.TargetCPUUtilization;
- res.ApiVersion = autoScaler.ApiVersion;
+ res.isUsed = true;
+ res.minReplicas = autoScaler.MinReplicas;
+ res.maxReplicas = autoScaler.MaxReplicas;
+ res.targetCpuUtilizationPercentage = autoScaler.TargetCPUUtilization;
+ res.apiVersion = autoScaler.ApiVersion;
} else {
- res.ApiVersion = 'apps/v1';
- res.MinReplicas = replicasCount;
- res.MaxReplicas = replicasCount;
+ res.apiVersion = 'apps/v1';
+ res.minReplicas = replicasCount;
+ res.maxReplicas = replicasCount;
}
return res;
}
@@ -461,7 +455,7 @@ class KubernetesApplicationHelper {
}
static generateAffinityFromPlacements(app, formValues) {
- if (formValues.DeploymentType === KubernetesApplicationDeploymentTypes.REPLICATED) {
+ if (formValues.DeploymentType === KubernetesApplicationDeploymentTypes.Replicated) {
const placements = formValues.Placements;
const res = new KubernetesPodNodeAffinityPayload();
let expressions = _.map(placements, (p) => {
@@ -545,7 +539,7 @@ class KubernetesApplicationHelper {
const helmAppsList = helmAppsEntriesList.map(([helmInstance, applications]) => {
const helmApp = new HelmApplication();
helmApp.Name = helmInstance;
- helmApp.ApplicationType = KubernetesApplicationTypes.HELM;
+ helmApp.ApplicationType = KubernetesApplicationTypes.Helm;
helmApp.ApplicationOwner = applications[0].ApplicationOwner;
helmApp.KubernetesApplications = applications;
diff --git a/app/kubernetes/helpers/volumeHelper.js b/app/kubernetes/helpers/volumeHelper.js
index c357ffb14..0b158d8f5 100644
--- a/app/kubernetes/helpers/volumeHelper.js
+++ b/app/kubernetes/helpers/volumeHelper.js
@@ -1,11 +1,11 @@
import _ from 'lodash-es';
import uuidv4 from 'uuid/v4';
-import { KubernetesApplicationTypes } from 'Kubernetes/models/application/models';
+import { KubernetesApplicationTypes } from 'Kubernetes/models/application/models/appConstants';
class KubernetesVolumeHelper {
// TODO: review
// the following condition
- // && (app.ApplicationType === KubernetesApplicationTypes.STATEFULSET ? _.includes(volume.PersistentVolumeClaim.Name, app.Name) : true);
+ // && (app.ApplicationType === KubernetesApplicationTypes.StatefulSet ? _.includes(volume.PersistentVolumeClaim.Name, app.Name) : true);
// is made to enforce finding the good SFS when multiple SFS in the same namespace
// are referencing an internal PVC using the same internal name
// (PVC are not exposed to other apps so they can have the same name in differents SFS)
@@ -16,7 +16,7 @@ class KubernetesVolumeHelper {
return (
volume.ResourcePool.Namespace.Name === app.ResourcePool &&
matchingNames.length &&
- (app.ApplicationType === KubernetesApplicationTypes.STATEFULSET ? _.includes(volume.PersistentVolumeClaim.Name, app.Name) : true)
+ (app.ApplicationType === KubernetesApplicationTypes.StatefulSet ? _.includes(volume.PersistentVolumeClaim.Name, app.Name) : true)
);
});
}
diff --git a/app/kubernetes/horizontal-pod-auto-scaler/converter.js b/app/kubernetes/horizontal-pod-auto-scaler/converter.js
index 5ccfdf9c9..12841b0bf 100644
--- a/app/kubernetes/horizontal-pod-auto-scaler/converter.js
+++ b/app/kubernetes/horizontal-pod-auto-scaler/converter.js
@@ -30,7 +30,7 @@ export class KubernetesHorizontalPodAutoScalerConverter {
payload.metadata.name = data.TargetEntity.Name;
payload.spec.minReplicas = data.MinReplicas;
payload.spec.maxReplicas = data.MaxReplicas;
- payload.spec.targetCPUUtilizationPercentage = data.TargetCPUUtilization;
+ payload.spec.targetCPUUtilizationPercentage = data.targetCpuUtilizationPercentage;
payload.spec.scaleTargetRef.apiVersion = data.TargetEntity.ApiVersion;
payload.spec.scaleTargetRef.kind = data.TargetEntity.Kind;
payload.spec.scaleTargetRef.name = data.TargetEntity.Name;
@@ -48,86 +48,12 @@ export class KubernetesHorizontalPodAutoScalerConverter {
const res = new KubernetesHorizontalPodAutoScaler();
res.Name = formValues.Name;
res.Namespace = formValues.ResourcePool.Namespace.Name;
- res.MinReplicas = formValues.AutoScaler.MinReplicas;
- res.MaxReplicas = formValues.AutoScaler.MaxReplicas;
- res.TargetCPUUtilization = formValues.AutoScaler.TargetCPUUtilization;
+ res.MinReplicas = formValues.AutoScaler.minReplicas;
+ res.MaxReplicas = formValues.AutoScaler.maxReplicas;
+ res.TargetCPUUtilization = formValues.AutoScaler.targetCpuUtilizationPercentage;
res.TargetEntity.Name = formValues.Name;
res.TargetEntity.Kind = kind;
- res.TargetEntity.ApiVersion = formValues.AutoScaler.ApiVersion;
+ res.TargetEntity.ApiVersion = formValues.AutoScaler.apiVersion;
return res;
}
-
- /**
- * Convertion functions to use with v2beta2 model
- */
-
- // static apiToModel(data, yaml) {
- // const res = new KubernetesHorizontalPodAutoScaler();
- // res.Id = data.metadata.uid;
- // res.Namespace = data.metadata.namespace;
- // res.Name = data.metadata.name;
- // res.MinReplicas = data.spec.minReplicas;
- // res.MaxReplicas = data.spec.maxReplicas;
- // res.TargetCPUUtilization = data.spec.targetCPUUtilization;
-
- // _.forEach(data.spec.metrics, (metric) => {
- // if (metric.type === 'Resource') {
- // if (metric.resource.name === 'cpu') {
- // res.TargetCPUUtilization = metric.resource.target.averageUtilization;
- // }
- // if (metric.resource.name === 'memory') {
- // res.TargetMemoryValue = parseFloat(metric.resource.target.averageValue) / 1000;
- // }
- // }
- // });
-
- // if (data.spec.scaleTargetRef) {
- // res.TargetEntity.ApiVersion = data.spec.scaleTargetRef.apiVersion;
- // res.TargetEntity.Kind = data.spec.scaleTargetRef.kind;
- // res.TargetEntity.Name = data.spec.scaleTargetRef.name;
- // }
- // res.Yaml = yaml ? yaml.data : '';
- // return res;
- // }
-
- // static createPayload(data) {
- // const payload = new KubernetesHorizontalPodAutoScalerCreatePayload();
- // payload.metadata.namespace = data.Namespace;
- // payload.metadata.name = data.TargetEntity.Name;
- // payload.spec.minReplicas = data.MinReplicas;
- // payload.spec.maxReplicas = data.MaxReplicas;
-
- // if (data.TargetMemoryValue) {
- // const memoryMetric = new KubernetesHorizontalPodAutoScalerMemoryMetric();
- // memoryMetric.resource.target.averageValue = data.TargetMemoryValue;
- // payload.spec.metrics.push(memoryMetric);
- // }
-
- // if (data.TargetCPUUtilization) {
- // const cpuMetric = new KubernetesHorizontalPodAutoScalerCPUMetric();
- // cpuMetric.resource.target.averageUtilization = data.TargetCPUUtilization;
- // payload.spec.metrics.push(cpuMetric);
- // }
-
- // payload.spec.scaleTargetRef.apiVersion = data.TargetEntity.ApiVersion;
- // payload.spec.scaleTargetRef.kind = data.TargetEntity.Kind;
- // payload.spec.scaleTargetRef.name = data.TargetEntity.Name;
-
- // return payload;
- // }
-
- // static applicationFormValuesToModel(formValues, kind) {
- // const res = new KubernetesHorizontalPodAutoScaler();
- // res.Name = formValues.Name;
- // res.Namespace = formValues.ResourcePool.Namespace.Name;
- // res.MinReplicas = formValues.AutoScaler.MinReplicas;
- // res.MaxReplicas = formValues.AutoScaler.MaxReplicas;
- // res.TargetCPUUtilization = formValues.AutoScaler.TargetCPUUtilization;
- // if (formValues.AutoScaler.TargetMemoryValue) {
- // res.TargetMemoryValue = formValues.AutoScaler.TargetMemoryValue + 'M';
- // }
- // res.TargetEntity.Name = formValues.Name;
- // res.TargetEntity.Kind = kind;
- // return res;
- // }
}
diff --git a/app/kubernetes/horizontal-pod-auto-scaler/helper.js b/app/kubernetes/horizontal-pod-auto-scaler/helper.js
index 44bc10c49..43ce119c6 100644
--- a/app/kubernetes/horizontal-pod-auto-scaler/helper.js
+++ b/app/kubernetes/horizontal-pod-auto-scaler/helper.js
@@ -1,27 +1,8 @@
import _ from 'lodash-es';
-import PortainerError from 'Portainer/error';
-import { KubernetesApplication, KubernetesApplicationTypes, KubernetesApplicationTypeStrings } from 'Kubernetes/models/application/models';
-import { KubernetesDeployment } from 'Kubernetes/models/deployment/models';
-import { KubernetesStatefulSet } from 'Kubernetes/models/stateful-set/models';
-import { KubernetesDaemonSet } from 'Kubernetes/models/daemon-set/models';
export class KubernetesHorizontalPodAutoScalerHelper {
static findApplicationBoundScaler(sList, app) {
- const kind = KubernetesHorizontalPodAutoScalerHelper.getApplicationTypeString(app);
+ const kind = app.ApplicationType;
return _.find(sList, (item) => item.TargetEntity.Kind === kind && item.TargetEntity.Name === app.Name);
}
-
- static getApplicationTypeString(app) {
- if ((app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.DEPLOYMENT) || app instanceof KubernetesDeployment) {
- return KubernetesApplicationTypeStrings.DEPLOYMENT;
- } else if ((app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.DAEMONSET) || app instanceof KubernetesDaemonSet) {
- return KubernetesApplicationTypeStrings.DAEMONSET;
- } else if ((app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.STATEFULSET) || app instanceof KubernetesStatefulSet) {
- return KubernetesApplicationTypeStrings.STATEFULSET;
- } else if (app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.POD) {
- return KubernetesApplicationTypeStrings.POD;
- } else {
- throw new PortainerError('Unable to determine application type');
- }
- }
}
diff --git a/app/kubernetes/ingress/converter.js b/app/kubernetes/ingress/converter.js
index df04d7e06..897a2d19e 100644
--- a/app/kubernetes/ingress/converter.js
+++ b/app/kubernetes/ingress/converter.js
@@ -7,7 +7,6 @@ import {
KubernetesResourcePoolIngressClassFormValue,
KubernetesResourcePoolIngressClassHostFormValue,
} from 'Kubernetes/models/resource-pool/formValues';
-import { KubernetesApplicationPublishingTypes } from '../models/application/models';
import { KubernetesIngress, KubernetesIngressRule } from './models';
import { KubernetesIngressCreatePayload, KubernetesIngressRuleCreatePayload, KubernetesIngressRulePathCreatePayload } from './payloads';
import { KubernetesIngressClassAnnotation, PortainerIngressClassTypes } from './constants';
@@ -48,36 +47,6 @@ export class KubernetesIngressConverter {
return res;
}
- /**
- * Converts Application Form Value (from Create Application View) to Ingresses
- * @param {KubernetesApplicationFormValues} formValues
- * @param {string} serviceName
- * @returns {KubernetesIngressRule[]}
- */
- static applicationFormValuesToIngresses(formValues, serviceName) {
- const isPublishingToIngress = formValues.PublishingType === KubernetesApplicationPublishingTypes.INGRESS;
- const ingresses = angular.copy(formValues.OriginalIngresses);
- _.forEach(formValues.PublishedPorts, (p) => {
- const ingress = _.find(ingresses, { Name: p.IngressName });
- if (ingress) {
- if (p.NeedsDeletion) {
- _.remove(ingress.Paths, (path) => path.Port === p.ContainerPort && path.ServiceName === serviceName && path.Path === p.IngressRoute);
- } else if (isPublishingToIngress && p.IsNew) {
- const rule = new KubernetesIngressRule();
- rule.IngressName = ingress.Name;
- rule.ServiceName = serviceName;
- rule.Port = p.ContainerPort;
- if (p.IngressRoute) {
- rule.Path = _.startsWith(p.IngressRoute, '/') ? p.IngressRoute : '/' + p.IngressRoute;
- }
- rule.Host = p.IngressHost;
- ingress.Paths.push(rule);
- }
- }
- });
- return ingresses;
- }
-
static applicationFormValuesToDeleteIngresses(formValues, application) {
const ingresses = angular.copy(formValues.OriginalIngresses);
application.Services.forEach((service) => {
diff --git a/app/kubernetes/models/application/formValues.js b/app/kubernetes/models/application/formValues.js
index 57eefcade..b1cac46bc 100644
--- a/app/kubernetes/models/application/formValues.js
+++ b/app/kubernetes/models/application/formValues.js
@@ -1,11 +1,11 @@
import { PorImageRegistryModel } from '@/docker/models/porImageRegistry';
-import { KubernetesApplicationDataAccessPolicies, KubernetesApplicationDeploymentTypes } from './models';
+import { KubernetesApplicationTypes, KubernetesApplicationDeploymentTypes, KubernetesApplicationDataAccessPolicies } from 'Kubernetes/models/application/models/appConstants';
/**
* KubernetesApplicationFormValues Model
*/
export function KubernetesApplicationFormValues() {
- this.ApplicationType = undefined; // will only exist for formValues generated from Application (app edit situation;
+ this.ApplicationType = KubernetesApplicationTypes.Deployment; // will only exist for formValues generated from Application (app edit situation;
this.ResourcePool = {};
this.Name = '';
this.StackName = '';
@@ -14,13 +14,13 @@ export function KubernetesApplicationFormValues() {
this.Note = '';
this.MemoryLimit = 0;
this.CpuLimit = 0;
- this.DeploymentType = KubernetesApplicationDeploymentTypes.REPLICATED;
+ this.DeploymentType = KubernetesApplicationDeploymentTypes.Replicated;
this.ReplicaCount = 1;
this.AutoScaler = {};
this.Containers = [];
this.Services = [];
this.EnvironmentVariables = []; // KubernetesApplicationEnvironmentVariableFormValue lis;
- this.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.ISOLATED;
+ this.DataAccessPolicy = KubernetesApplicationDataAccessPolicies.Isolated;
this.PersistedFolders = []; // KubernetesApplicationPersistedFolderFormValue lis;
this.ConfigMaps = [];
this.Secrets = [];
@@ -130,11 +130,11 @@ export function KubernetesApplicationPlacementFormValue() {
* KubernetesApplicationAutoScalerFormValue Model
*/
const _KubernetesApplicationAutoScalerFormValue = Object.freeze({
- MinReplicas: 0,
- MaxReplicas: 0,
- TargetCPUUtilization: 50,
- ApiVersion: '',
- IsUsed: false,
+ minReplicas: 0,
+ maxReplicas: 0,
+ targetCpuUtilizationPercentage: 50,
+ apiVersion: '',
+ isUsed: false,
});
export class KubernetesApplicationAutoScalerFormValue {
diff --git a/app/kubernetes/models/application/models/appConstants.ts b/app/kubernetes/models/application/models/appConstants.ts
new file mode 100644
index 000000000..658fc30c2
--- /dev/null
+++ b/app/kubernetes/models/application/models/appConstants.ts
@@ -0,0 +1,41 @@
+import {
+ AppType,
+ AppDataAccessPolicy,
+ DeploymentType,
+} from '@/react/kubernetes/applications/types';
+import { ServiceType } from '@/react/kubernetes/services/types';
+
+// The following constants are used by angular views and can be removed once they are no longer referenced
+export const KubernetesApplicationTypes: Record = {
+ Deployment: 'Deployment',
+ StatefulSet: 'StatefulSet',
+ DaemonSet: 'DaemonSet',
+ Pod: 'Pod',
+ Helm: 'Helm',
+} as const;
+
+export const KubernetesApplicationDeploymentTypes: Record<
+ DeploymentType,
+ DeploymentType
+> = {
+ Global: 'Global',
+ Replicated: 'Replicated',
+} as const;
+
+export const KubernetesApplicationDataAccessPolicies: Record<
+ AppDataAccessPolicy,
+ AppDataAccessPolicy
+> = {
+ Isolated: 'Isolated',
+ Shared: 'Shared',
+} as const;
+
+export const KubernetesApplicationServiceTypes: Record<
+ ServiceType,
+ ServiceType
+> = {
+ ClusterIP: 'ClusterIP',
+ NodePort: 'NodePort',
+ LoadBalancer: 'LoadBalancer',
+ ExternalName: 'ExternalName',
+} as const;
diff --git a/app/kubernetes/models/application/models/constants.js b/app/kubernetes/models/application/models/constants.js
index aa06f7f25..d4caab60e 100644
--- a/app/kubernetes/models/application/models/constants.js
+++ b/app/kubernetes/models/application/models/constants.js
@@ -1,35 +1,3 @@
-export const KubernetesApplicationDeploymentTypes = Object.freeze({
- REPLICATED: 1,
- GLOBAL: 2,
-});
-
-export const KubernetesApplicationDataAccessPolicies = Object.freeze({
- SHARED: 1,
- ISOLATED: 2,
-});
-
-export const KubernetesApplicationTypes = Object.freeze({
- DEPLOYMENT: 1,
- DAEMONSET: 2,
- STATEFULSET: 3,
- POD: 4,
- HELM: 5,
-});
-
-export const KubernetesApplicationTypeStrings = Object.freeze({
- HELM: 'Helm',
- DEPLOYMENT: 'Deployment',
- DAEMONSET: 'DaemonSet',
- STATEFULSET: 'StatefulSet',
- POD: 'Pod',
-});
-
-export const KubernetesApplicationPublishingTypes = Object.freeze({
- CLUSTER_IP: 1,
- NODE_PORT: 2,
- LOAD_BALANCER: 3,
-});
-
export const KubernetesApplicationQuotaDefaults = {
CpuLimit: 0.1,
MemoryLimit: 64, // MB
diff --git a/app/kubernetes/react/components/index.ts b/app/kubernetes/react/components/index.ts
index c4473c3b8..e5ef79c44 100644
--- a/app/kubernetes/react/components/index.ts
+++ b/app/kubernetes/react/components/index.ts
@@ -6,7 +6,6 @@ import { NamespacesSelector } from '@/react/kubernetes/cluster/RegistryAccessVie
import { StorageAccessModeSelector } from '@/react/kubernetes/cluster/ConfigureView/ConfigureForm/StorageAccessModeSelector';
import { NamespaceAccessUsersSelector } from '@/react/kubernetes/namespaces/AccessView/NamespaceAccessUsersSelector';
import { RegistriesSelector } from '@/react/kubernetes/namespaces/components/RegistriesFormSection/RegistriesSelector';
-import { DataAccessPolicyFormSection } from '@/react/kubernetes/applications/CreateView/DataAccessPolicyFormSection';
import { KubeServicesForm } from '@/react/kubernetes/applications/CreateView/application-services/KubeServicesForm';
import { kubeServicesValidation } from '@/react/kubernetes/applications/CreateView/application-services/kubeServicesValidation';
import { AppDeploymentTypeFormSection } from '@/react/kubernetes/applications/CreateView/AppDeploymentTypeFormSection';
@@ -22,6 +21,7 @@ import {
PlacementFormSection,
placementValidation,
} from '@/react/kubernetes/applications/components/PlacementFormSection';
+import { ApplicationSummarySection } from '@/react/kubernetes/applications/components/ApplicationSummarySection';
import { withFormValidation } from '@/react-tools/withFormValidation';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { YAMLInspector } from '@/react/kubernetes/components/YAMLInspector';
@@ -33,6 +33,7 @@ import { SecretsFormSection } from '@/react/kubernetes/applications/components/C
import { configurationsValidationSchema } from '@/react/kubernetes/applications/components/ConfigurationsFormSection/configurationValidationSchema';
import { ConfigMapsFormSection } from '@/react/kubernetes/applications/components/ConfigurationsFormSection/ConfigMapsFormSection';
import { PersistedFoldersFormSection } from '@/react/kubernetes/applications/components/PersistedFoldersFormSection';
+import { DataAccessPolicyFormSection } from '@/react/kubernetes/applications/CreateView/DataAccessPolicyFormSection';
import { persistedFoldersValidation } from '@/react/kubernetes/applications/components/PersistedFoldersFormSection/persistedFoldersValidation';
import {
ResourceReservationFormSection,
@@ -46,6 +47,7 @@ import {
AutoScalingFormSection,
autoScalingValidation,
} from '@/react/kubernetes/applications/components/AutoScalingFormSection';
+import { withControlledInput } from '@/react-tools/withControlledInput';
import { EnvironmentVariablesFieldset } from '@@/form-components/EnvironmentVariablesFieldset';
@@ -112,7 +114,7 @@ export const ngModule = angular
r2a(withUIRouter(withReactQuery(withCurrentUser(NodesDatatable))), [])
)
.component(
- 'dataAccessPolicyFormSection',
+ 'accessPolicyFormSection',
r2a(DataAccessPolicyFormSection, [
'value',
'onChange',
@@ -174,6 +176,13 @@ export const ngModule = angular
[]
)
)
+ .component(
+ 'applicationSummarySection',
+ r2a(
+ withUIRouter(withReactQuery(withCurrentUser(ApplicationSummarySection))),
+ ['formValues', 'oldFormValues']
+ )
+ )
.component(
'kubernetesApplicationsStacksDatatable',
r2a(withUIRouter(withCurrentUser(ApplicationsStacksDatatable)), [
@@ -193,7 +202,9 @@ export const componentsModule = ngModule.name;
withFormValidation(
ngModule,
- withUIRouter(withCurrentUser(withReactQuery(KubeServicesForm))),
+ withControlledInput(
+ withUIRouter(withCurrentUser(withReactQuery(KubeServicesForm)))
+ ),
'kubeServicesForm',
['values', 'onChange', 'appName', 'selector', 'isEditMode', 'namespace'],
kubeServicesValidation
@@ -201,7 +212,7 @@ withFormValidation(
withFormValidation(
ngModule,
- EnvironmentVariablesFieldset,
+ withControlledInput(EnvironmentVariablesFieldset),
'kubeEnvironmentVariablesFieldset',
['canUndoDelete'],
// use kubeEnvVarValidationSchema instead of envVarValidation to add a regex matches rule
@@ -210,7 +221,9 @@ withFormValidation(
withFormValidation(
ngModule,
- withUIRouter(withCurrentUser(withReactQuery(ConfigMapsFormSection))),
+ withControlledInput(
+ withUIRouter(withCurrentUser(withReactQuery(ConfigMapsFormSection)))
+ ),
'configMapsFormSection',
['values', 'onChange', 'namespace'],
configurationsValidationSchema
@@ -218,7 +231,9 @@ withFormValidation(
withFormValidation(
ngModule,
- withUIRouter(withCurrentUser(withReactQuery(SecretsFormSection))),
+ withControlledInput(
+ withUIRouter(withCurrentUser(withReactQuery(SecretsFormSection)))
+ ),
'secretsFormSection',
['values', 'onChange', 'namespace'],
configurationsValidationSchema
@@ -240,7 +255,11 @@ withFormValidation(
withFormValidation(
ngModule,
- withUIRouter(withCurrentUser(withReactQuery(ResourceReservationFormSection))),
+ withControlledInput(
+ withUIRouter(
+ withCurrentUser(withReactQuery(ResourceReservationFormSection))
+ )
+ ),
'resourceReservationFormSection',
[
'namespaceHasQuota',
@@ -253,7 +272,9 @@ withFormValidation(
withFormValidation(
ngModule,
- withUIRouter(withCurrentUser(withReactQuery(ReplicationFormSection))),
+ withControlledInput(
+ withUIRouter(withCurrentUser(withReactQuery(ReplicationFormSection)))
+ ),
'replicationFormSection',
[
'supportScalableReplicaDeployment',
@@ -266,7 +287,9 @@ withFormValidation(
withFormValidation(
ngModule,
- withUIRouter(withCurrentUser(withReactQuery(AutoScalingFormSection))),
+ withControlledInput(
+ withUIRouter(withCurrentUser(withReactQuery(AutoScalingFormSection)))
+ ),
'autoScalingFormSection',
['isMetricsEnabled'],
autoScalingValidation
diff --git a/app/kubernetes/services/applicationService.js b/app/kubernetes/services/applicationService.js
index efd9217a7..c473f2604 100644
--- a/app/kubernetes/services/applicationService.js
+++ b/app/kubernetes/services/applicationService.js
@@ -2,12 +2,9 @@ import _ from 'lodash-es';
import angular from 'angular';
import PortainerError from 'Portainer/error';
-import { KubernetesApplication, KubernetesApplicationDeploymentTypes, KubernetesApplicationTypes } from 'Kubernetes/models/application/models';
import KubernetesApplicationHelper from 'Kubernetes/helpers/application';
import KubernetesApplicationConverter from 'Kubernetes/converters/application';
-import { KubernetesDeployment } from 'Kubernetes/models/deployment/models';
import { KubernetesStatefulSet } from 'Kubernetes/models/stateful-set/models';
-import { KubernetesDaemonSet } from 'Kubernetes/models/daemon-set/models';
import KubernetesServiceHelper from 'Kubernetes/helpers/serviceHelper';
import { KubernetesHorizontalPodAutoScalerHelper } from 'Kubernetes/horizontal-pod-auto-scaler/helper';
import { KubernetesHorizontalPodAutoScalerConverter } from 'Kubernetes/horizontal-pod-auto-scaler/converter';
@@ -15,6 +12,7 @@ import KubernetesPodConverter from 'Kubernetes/pod/converter';
import { notifyError } from '@/portainer/services/notifications';
import { KubernetesIngressConverter } from 'Kubernetes/ingress/converter';
import { generateNewIngressesFromFormPaths } from '@/react/kubernetes/applications/CreateView/application-services/utils';
+import { KubernetesApplicationDeploymentTypes, KubernetesApplicationTypes } from 'Kubernetes/models/application/models/appConstants';
class KubernetesApplicationService {
/* #region CONSTRUCTOR */
@@ -58,13 +56,13 @@ class KubernetesApplicationService {
/* #region UTILS */
_getApplicationApiService(app) {
let apiService;
- if (app instanceof KubernetesDeployment || (app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.DEPLOYMENT)) {
+ if (app.ApplicationType === KubernetesApplicationTypes.Deployment) {
apiService = this.KubernetesDeploymentService;
- } else if (app instanceof KubernetesDaemonSet || (app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.DAEMONSET)) {
+ } else if (app.ApplicationType === KubernetesApplicationTypes.DaemonSet) {
apiService = this.KubernetesDaemonSetService;
- } else if (app instanceof KubernetesStatefulSet || (app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.STATEFULSET)) {
+ } else if (app.ApplicationType === KubernetesApplicationTypes.StatefulSet) {
apiService = this.KubernetesStatefulSetService;
- } else if (app instanceof KubernetesApplication && app.ApplicationType === KubernetesApplicationTypes.POD) {
+ } else if (app.ApplicationType === KubernetesApplicationTypes.Pod) {
apiService = this.KubernetesPodService;
} else {
throw new PortainerError('Unable to determine which association to use to retrieve API Service');
@@ -257,8 +255,8 @@ class KubernetesApplicationService {
await Promise.all(_.without(claimPromises, undefined));
}
- if (formValues.AutoScaler.IsUsed && formValues.DeploymentType !== KubernetesApplicationDeploymentTypes.GLOBAL) {
- const kind = KubernetesHorizontalPodAutoScalerHelper.getApplicationTypeString(app);
+ if (formValues.AutoScaler.isUsed && formValues.DeploymentType !== KubernetesApplicationDeploymentTypes.Global) {
+ const kind = app.ApplicationType;
const autoScaler = KubernetesHorizontalPodAutoScalerConverter.applicationFormValuesToModel(formValues, kind);
await this.KubernetesHorizontalPodAutoScalerService.create(autoScaler);
}
@@ -378,16 +376,16 @@ class KubernetesApplicationService {
}
}
- const newKind = KubernetesHorizontalPodAutoScalerHelper.getApplicationTypeString(newApp);
+ const newKind = newApp.ApplicationType;
const newAutoScaler = KubernetesHorizontalPodAutoScalerConverter.applicationFormValuesToModel(newFormValues, newKind);
- if (!oldFormValues.AutoScaler.IsUsed) {
- if (newFormValues.AutoScaler.IsUsed) {
+ if (!oldFormValues.AutoScaler.isUsed) {
+ if (newFormValues.AutoScaler.isUsed) {
await this.KubernetesHorizontalPodAutoScalerService.create(newAutoScaler);
}
} else {
- const oldKind = KubernetesHorizontalPodAutoScalerHelper.getApplicationTypeString(oldApp);
+ const oldKind = oldApp.ApplicationType;
const oldAutoScaler = KubernetesHorizontalPodAutoScalerConverter.applicationFormValuesToModel(oldFormValues, oldKind);
- if (newFormValues.AutoScaler.IsUsed) {
+ if (newFormValues.AutoScaler.isUsed) {
await this.KubernetesHorizontalPodAutoScalerService.patch(oldAutoScaler, newAutoScaler);
} else {
await this.KubernetesHorizontalPodAutoScalerService.delete(oldAutoScaler);
diff --git a/app/kubernetes/views/applications/applicationsController.js b/app/kubernetes/views/applications/applicationsController.js
index 9965373c9..5ac361176 100644
--- a/app/kubernetes/views/applications/applicationsController.js
+++ b/app/kubernetes/views/applications/applicationsController.js
@@ -3,7 +3,7 @@ import _ from 'lodash-es';
import KubernetesStackHelper from 'Kubernetes/helpers/stackHelper';
import KubernetesApplicationHelper from 'Kubernetes/helpers/application';
import KubernetesConfigurationHelper from 'Kubernetes/helpers/configurationHelper';
-import { KubernetesApplicationTypes } from 'Kubernetes/models/application/models';
+import { KubernetesApplicationTypes } from 'Kubernetes/models/application/models/appConstants';
import { KubernetesPortainerApplicationStackNameLabel } from 'Kubernetes/models/application/models';
import { confirmDelete } from '@@/modals/confirm';
import { getDeploymentOptions } from '@/react/portainer/environments/environment.service';
@@ -90,7 +90,7 @@ class KubernetesApplicationsController {
let actionCount = selectedItems.length;
for (const application of selectedItems) {
try {
- if (application.ApplicationType === KubernetesApplicationTypes.HELM) {
+ if (application.ApplicationType === KubernetesApplicationTypes.Helm) {
await this.HelmService.uninstall(this.endpoint.Id, application);
} else {
await this.KubernetesApplicationService.delete(application);
diff --git a/app/kubernetes/views/applications/create/createApplication.html b/app/kubernetes/views/applications/create/createApplication.html
index 90093a1f8..6fdd2cf9d 100644
--- a/app/kubernetes/views/applications/create/createApplication.html
+++ b/app/kubernetes/views/applications/create/createApplication.html
@@ -103,9 +103,16 @@
>
-
-
+
+
+
Actions
+
|