mirror of https://github.com/portainer/portainer
fix(ing): nodeport validate and show errors [EE-4373] (#7801)
parent
fd91de3571
commit
7a6ff10268
|
@ -1,5 +1,5 @@
|
|||
import _ from 'lodash-es';
|
||||
import { KubernetesServicePort, KubernetesIngressServiceRoute } from 'Kubernetes/models/service/models';
|
||||
import { KubernetesServicePort } from 'Kubernetes/models/service/models';
|
||||
import { KubernetesFormValidationReferences } from 'Kubernetes/models/application/formValues';
|
||||
import KubernetesFormValidationHelper from 'Kubernetes/helpers/formValidationHelper';
|
||||
import { KubernetesApplicationPublishingTypes } from 'Kubernetes/models/application/models/constants';
|
||||
|
@ -18,34 +18,17 @@ export default class KubeServicesItemViewController {
|
|||
port.port = '';
|
||||
port.targetPort = '';
|
||||
port.protocol = 'TCP';
|
||||
|
||||
if (this.ingressType) {
|
||||
const route = new KubernetesIngressServiceRoute();
|
||||
route.ServiceName = this.serviceName;
|
||||
|
||||
if (this.serviceType === KubernetesApplicationPublishingTypes.CLUSTER_IP && this.originalIngresses && this.originalIngresses.length > 0) {
|
||||
if (!route.IngressName) {
|
||||
route.IngressName = this.originalIngresses[0].Name;
|
||||
}
|
||||
|
||||
if (!route.Host) {
|
||||
route.Host = this.originalIngresses[0].Hosts[0];
|
||||
}
|
||||
}
|
||||
|
||||
port.ingress = route;
|
||||
port.Ingress = true;
|
||||
}
|
||||
this.servicePorts.push(port);
|
||||
this.service.Ports.push(port);
|
||||
}
|
||||
|
||||
removePort(index) {
|
||||
this.servicePorts.splice(index, 1);
|
||||
this.service.Ports.splice(index, 1);
|
||||
}
|
||||
|
||||
servicePort(index) {
|
||||
const targetPort = this.servicePorts[index].targetPort;
|
||||
this.servicePorts[index].port = targetPort;
|
||||
const targetPort = this.service.Ports[index].targetPort;
|
||||
this.service.Ports[index].port = targetPort;
|
||||
this.onChangeServicePort();
|
||||
}
|
||||
|
||||
isAdmin() {
|
||||
|
@ -54,7 +37,7 @@ export default class KubeServicesItemViewController {
|
|||
|
||||
onChangeContainerPort() {
|
||||
const state = this.state.duplicates.targetPort;
|
||||
const source = _.map(this.servicePorts, (sp) => sp.targetPort);
|
||||
const source = _.map(this.service.Ports, (sp) => sp.targetPort);
|
||||
const duplicates = KubernetesFormValidationHelper.getDuplicates(source);
|
||||
state.refs = duplicates;
|
||||
state.hasRefs = Object.keys(duplicates).length > 0;
|
||||
|
@ -62,22 +45,41 @@ export default class KubeServicesItemViewController {
|
|||
|
||||
onChangeServicePort() {
|
||||
const state = this.state.duplicates.servicePort;
|
||||
const source = _.map(this.servicePorts, (sp) => sp.port);
|
||||
const source = _.map(this.service.Ports, (sp) => sp.port);
|
||||
const duplicates = KubernetesFormValidationHelper.getDuplicates(source);
|
||||
state.refs = duplicates;
|
||||
state.hasRefs = Object.keys(duplicates).length > 0;
|
||||
|
||||
this.service.servicePortError = state.hasRefs;
|
||||
}
|
||||
|
||||
onChangeNodePort() {
|
||||
const state = this.state.duplicates.nodePort;
|
||||
const source = _.map(this.servicePorts, (sp) => sp.nodePort);
|
||||
const duplicates = KubernetesFormValidationHelper.getDuplicates(source);
|
||||
|
||||
// create a list of all the node ports (number[]) in the cluster and current form
|
||||
const clusterNodePortsWithoutCurrentService = this.nodePortServices
|
||||
.filter((npService) => npService.Name !== this.service.Name)
|
||||
.map((npService) => npService.Ports)
|
||||
.flat()
|
||||
.map((npServicePorts) => npServicePorts.NodePort);
|
||||
const formNodePortsWithoutCurrentService = this.formServices
|
||||
.filter((formService) => formService.Type === KubernetesApplicationPublishingTypes.NODE_PORT && formService.Name !== this.service.Name)
|
||||
.map((formService) => formService.Ports)
|
||||
.flat()
|
||||
.map((formServicePorts) => formServicePorts.nodePort);
|
||||
const serviceNodePorts = this.service.Ports.map((sp) => sp.nodePort);
|
||||
// getDuplicates cares about the index, so put the serviceNodePorts at the start
|
||||
const allNodePortsWithoutCurrentService = [...clusterNodePortsWithoutCurrentService, ...formNodePortsWithoutCurrentService];
|
||||
|
||||
const duplicates = KubernetesFormValidationHelper.getDuplicateNodePorts(serviceNodePorts, allNodePortsWithoutCurrentService);
|
||||
state.refs = duplicates;
|
||||
state.hasRefs = Object.keys(duplicates).length > 0;
|
||||
|
||||
this.service.nodePortError = state.hasRefs;
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (this.servicePorts.length === 0) {
|
||||
if (this.service.Ports.length === 0) {
|
||||
this.addPort();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<ng-form name="serviceForm">
|
||||
<div ng-if="$ctrl.isAdmin()" class="small" ng-show="$ctrl.serviceType === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && !$ctrl.loadbalancerEnabled">
|
||||
<div ng-if="$ctrl.isAdmin()" class="small" ng-show="$ctrl.service.Type === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && !$ctrl.loadbalancerEnabled">
|
||||
<p class="text-warning pt-2 vertical-center">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> No Load balancer is available in this cluster, click
|
||||
<a class="hyperlink" ui-sref="kubernetes.cluster.setup">here</a> to configure load balancer.
|
||||
</p>
|
||||
</div>
|
||||
<div ng-if="!$ctrl.isAdmin()" class="small" ng-show="$ctrl.serviceType === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && !$ctrl.loadbalancerEnabled">
|
||||
<div ng-if="!$ctrl.isAdmin()" class="small" ng-show="$ctrl.service.Type === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && !$ctrl.loadbalancerEnabled">
|
||||
<p class="text-warning pt-2 vertical-center">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> No Load balancer is available in this cluster, contact your administrator.
|
||||
</p>
|
||||
|
@ -13,9 +13,9 @@
|
|||
|
||||
<div
|
||||
ng-if="
|
||||
($ctrl.serviceType === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && $ctrl.loadbalancerEnabled) ||
|
||||
$ctrl.serviceType === $ctrl.KubernetesApplicationPublishingTypes.CLUSTER_IP ||
|
||||
$ctrl.serviceType === $ctrl.KubernetesApplicationPublishingTypes.NODE_PORT
|
||||
($ctrl.service.Type === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && $ctrl.loadbalancerEnabled) ||
|
||||
$ctrl.service.Type === $ctrl.KubernetesApplicationPublishingTypes.CLUSTER_IP ||
|
||||
$ctrl.service.Type === $ctrl.KubernetesApplicationPublishingTypes.NODE_PORT
|
||||
"
|
||||
>
|
||||
<div ng-show="!$ctrl.multiItemDisable" class="mt-5 mb-5 vertical-center">
|
||||
|
@ -24,7 +24,7 @@
|
|||
<pr-icon icon="'plus'" mode="'alt'" size="'sm'" feather="true"></pr-icon> publish a new port
|
||||
</span>
|
||||
</div>
|
||||
<div ng-repeat="servicePort in $ctrl.servicePorts" class="mt-5 service-form row">
|
||||
<div ng-repeat="servicePort in $ctrl.service.Ports" class="mt-5 service-form row">
|
||||
<div class="form-group !mx-0 !pl-0 col-sm-3">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon required">Container port</span>
|
||||
|
@ -40,7 +40,7 @@
|
|||
max="65535"
|
||||
ng-change="$ctrl.servicePort($index)"
|
||||
required
|
||||
ng-disabled="$ctrl.originalIngresses.length === 0 || ($ctrl.serviceType === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && !$ctrl.loadbalancerEnabled)"
|
||||
ng-disabled="$ctrl.originalIngresses.length === 0 || ($ctrl.service.Type === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && !$ctrl.loadbalancerEnabled)"
|
||||
ng-change="$ctrl.onChangeContainerPort()"
|
||||
data-cy="k8sAppCreate-containerPort_{{ $index }}"
|
||||
/>
|
||||
|
@ -75,7 +75,7 @@
|
|||
min="1"
|
||||
max="65535"
|
||||
required
|
||||
ng-disabled="$ctrl.originalIngresses.length === 0 || ($ctrl.serviceType === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && !$ctrl.loadbalancerEnabled)"
|
||||
ng-disabled="$ctrl.originalIngresses.length === 0 || ($ctrl.service.Type === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && !$ctrl.loadbalancerEnabled)"
|
||||
ng-change="$ctrl.onChangeServicePort()"
|
||||
data-cy="k8sAppCreate-servicePort_{{ $index }}"
|
||||
/>
|
||||
|
@ -98,7 +98,7 @@
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group !mx-0 !pl-0 col-sm-3" ng-if="$ctrl.serviceType === $ctrl.KubernetesApplicationPublishingTypes.NODE_PORT">
|
||||
<div class="form-group !mx-0 !pl-0 col-sm-3" ng-if="$ctrl.service.Type === $ctrl.KubernetesApplicationPublishingTypes.NODE_PORT">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon required">Nodeport</span>
|
||||
<input
|
||||
|
@ -129,12 +129,15 @@
|
|||
><pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> Nodeport number must be inside the range 30000-32767 or blank for system
|
||||
allocated.</p
|
||||
>
|
||||
<div class="mt-1 text-warning" ng-if="$ctrl.state.duplicates.nodePort.refs[$index] !== undefined">
|
||||
<pr-icon icon="'alert-triangle'" mode="'warning'" feather="true"></pr-icon> This node port is already used.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group !mx-0 !pl-0 col-sm-3" ng-if="$ctrl.serviceType === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER">
|
||||
<div class="form-group !mx-0 !pl-0 col-sm-3" ng-if="$ctrl.service.Type === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-addon">Loadbalancer port</span>
|
||||
<input
|
||||
|
@ -148,7 +151,7 @@
|
|||
min="1"
|
||||
max="65535"
|
||||
required
|
||||
ng-disabled="$ctrl.serviceType === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && !$ctrl.loadbalancerEnabled"
|
||||
ng-disabled="$ctrl.service.Type === $ctrl.KubernetesApplicationPublishingTypes.LOAD_BALANCER && !$ctrl.loadbalancerEnabled"
|
||||
data-cy="k8sAppCreate-loadbalancerPort_{{ $index }}"
|
||||
/>
|
||||
</div>
|
||||
|
@ -177,7 +180,7 @@
|
|||
>
|
||||
</div>
|
||||
<button
|
||||
ng-disabled="$ctrl.servicePorts.length === 1"
|
||||
ng-disabled="$ctrl.service.Ports.length === 1"
|
||||
ng-show="!$ctrl.multiItemDisable"
|
||||
class="btn btn-sm btn-dangerlight btn-only-icon"
|
||||
type="button"
|
||||
|
|
|
@ -5,15 +5,10 @@ angular.module('portainer.kubernetes').component('kubeServicesItemView', {
|
|||
templateUrl: './kube-services-item.html',
|
||||
controller,
|
||||
bindings: {
|
||||
serviceType: '<',
|
||||
servicePorts: '=',
|
||||
serviceRoutes: '=',
|
||||
ingressType: '<',
|
||||
originalIngresses: '<',
|
||||
nodePortServices: '<',
|
||||
formServices: '<',
|
||||
service: '=',
|
||||
isEdit: '<',
|
||||
serviceName: '<',
|
||||
multiItemDisable: '<',
|
||||
serviceIndex: '<',
|
||||
loadbalancerEnabled: '<',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { KubernetesService, KubernetesServicePort, KubernetesServiceTypes } from 'Kubernetes/models/service/models';
|
||||
import { KubernetesApplicationPublishingTypes } from 'Kubernetes/models/application/models/constants';
|
||||
import { getServices } from 'Kubernetes/react/views/networks/services/service';
|
||||
import { notifyError } from '@/portainer/services/notifications';
|
||||
|
||||
export default class KubeServicesViewController {
|
||||
/* @ngInject */
|
||||
|
@ -7,6 +9,7 @@ export default class KubeServicesViewController {
|
|||
this.$async = $async;
|
||||
this.EndpointProvider = EndpointProvider;
|
||||
this.Authentication = Authentication;
|
||||
this.asyncOnInit = this.asyncOnInit.bind(this);
|
||||
}
|
||||
|
||||
addEntry(service) {
|
||||
|
@ -74,6 +77,21 @@ export default class KubeServicesViewController {
|
|||
return 'fa fa-project-diagram';
|
||||
}
|
||||
}
|
||||
|
||||
async asyncOnInit() {
|
||||
try {
|
||||
// get all nodeport services in the cluster, to validate unique nodeports in the form
|
||||
const allSettledServices = await Promise.allSettled(this.namespaces.map((namespace) => getServices(this.state.endpointId, namespace)));
|
||||
const allServices = allSettledServices
|
||||
.filter((settledService) => settledService.status === 'fulfilled' && settledService.value)
|
||||
.map((fulfilledService) => fulfilledService.value)
|
||||
.flat();
|
||||
this.nodePortServices = allServices.filter((service) => service.Type === 'NodePort');
|
||||
} catch (error) {
|
||||
notifyError('Failure', error, 'Failed getting services');
|
||||
}
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.state = {
|
||||
serviceType: [
|
||||
|
@ -93,5 +111,6 @@ export default class KubeServicesViewController {
|
|||
selected: KubernetesApplicationPublishingTypes.CLUSTER_IP,
|
||||
endpointId: this.EndpointProvider.endpointID(),
|
||||
};
|
||||
return this.$async(this.asyncOnInit);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,10 +44,9 @@
|
|||
{{ $ctrl.serviceType(service.Type) }}
|
||||
</div>
|
||||
<kube-services-item-view
|
||||
service-routes="$ctrl.formValues.Services[$index].IngressRoute"
|
||||
ingress-type="$ctrl.formValues.Services[$index].Ingress"
|
||||
service-type="$ctrl.formValues.Services[$index].Type"
|
||||
service-ports="$ctrl.formValues.Services[$index].Ports"
|
||||
node-port-services="$ctrl.nodePortServices"
|
||||
form-services="$ctrl.formValues.Services"
|
||||
service="$ctrl.formValues.Services[$index]"
|
||||
is-edit="$ctrl.isEdit"
|
||||
loadbalancer-enabled="$ctrl.loadbalancerEnabled"
|
||||
></kube-services-item-view>
|
||||
|
|
|
@ -7,6 +7,7 @@ angular.module('portainer.kubernetes').component('kubeServicesView', {
|
|||
bindings: {
|
||||
formValues: '=',
|
||||
isEdit: '<',
|
||||
namespaces: '<',
|
||||
loadbalancerEnabled: '<',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -13,14 +13,24 @@ class KubernetesFormValidationHelper {
|
|||
}
|
||||
|
||||
static getDuplicates(names) {
|
||||
const groupped = _.groupBy(names);
|
||||
const grouped = _.groupBy(names);
|
||||
const res = {};
|
||||
_.forEach(names, (name, index) => {
|
||||
if (name && groupped[name].length > 1) {
|
||||
if (name && grouped[name].length > 1) {
|
||||
res[index] = name;
|
||||
}
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
static getDuplicateNodePorts(serviceNodePorts, allOtherNodePorts) {
|
||||
const res = {};
|
||||
serviceNodePorts.forEach((sNodePort, index) => {
|
||||
if (allOtherNodePorts.includes(sNodePort) || serviceNodePorts.filter((snp) => snp === sNodePort).length > 1) {
|
||||
res[index] = sNodePort;
|
||||
}
|
||||
});
|
||||
return res;
|
||||
}
|
||||
}
|
||||
export default KubernetesFormValidationHelper;
|
||||
|
|
|
@ -23,6 +23,8 @@ const _KubernetesService = Object.freeze({
|
|||
Note: '',
|
||||
Ingress: false,
|
||||
Selector: {},
|
||||
nodePortError: false,
|
||||
servicePortError: false,
|
||||
});
|
||||
|
||||
export class KubernetesService {
|
||||
|
|
|
@ -13,6 +13,7 @@ import KubernetesServiceHelper from 'Kubernetes/helpers/serviceHelper';
|
|||
import { KubernetesHorizontalPodAutoScalerHelper } from 'Kubernetes/horizontal-pod-auto-scaler/helper';
|
||||
import { KubernetesHorizontalPodAutoScalerConverter } from 'Kubernetes/horizontal-pod-auto-scaler/converter';
|
||||
import KubernetesPodConverter from 'Kubernetes/pod/converter';
|
||||
import { notifyError } from '@/portainer/services/notifications';
|
||||
|
||||
class KubernetesApplicationService {
|
||||
/* #region CONSTRUCTOR */
|
||||
|
@ -213,7 +214,11 @@ class KubernetesApplicationService {
|
|||
|
||||
if (services) {
|
||||
services.forEach(async (service) => {
|
||||
await this.KubernetesServiceService.create(service);
|
||||
try {
|
||||
await this.KubernetesServiceService.create(service);
|
||||
} catch (error) {
|
||||
notifyError('Unable to create service', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -221,7 +226,11 @@ class KubernetesApplicationService {
|
|||
|
||||
if (app instanceof KubernetesStatefulSet) {
|
||||
app.VolumeClaims = claims;
|
||||
headlessService = await this.KubernetesServiceService.create(headlessService);
|
||||
try {
|
||||
headlessService = await this.KubernetesServiceService.create(headlessService);
|
||||
} catch (error) {
|
||||
notifyError('Unable to create service', error);
|
||||
}
|
||||
app.ServiceName = headlessService.metadata.name;
|
||||
} else {
|
||||
const claimPromises = _.map(claims, (item) => {
|
||||
|
@ -276,7 +285,11 @@ class KubernetesApplicationService {
|
|||
}
|
||||
|
||||
if (newApp instanceof KubernetesStatefulSet) {
|
||||
await this.KubernetesServiceService.patch(oldHeadlessService, newHeadlessService);
|
||||
try {
|
||||
await this.KubernetesServiceService.patch(oldHeadlessService, newHeadlessService);
|
||||
} catch (error) {
|
||||
notifyError('Unable to update service', error);
|
||||
}
|
||||
} else {
|
||||
const claimPromises = _.map(newClaims, (newClaim) => {
|
||||
if (!newClaim.PreviousName && !newClaim.Id) {
|
||||
|
@ -294,7 +307,11 @@ class KubernetesApplicationService {
|
|||
// Create services
|
||||
if (oldServices.length === 0 && newServices.length !== 0) {
|
||||
newServices.forEach(async (service) => {
|
||||
await this.KubernetesServiceService.create(service);
|
||||
try {
|
||||
await this.KubernetesServiceService.create(service);
|
||||
} catch (error) {
|
||||
notifyError('Unable to create service', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -315,9 +332,17 @@ class KubernetesApplicationService {
|
|||
newServices.forEach(async (newService) => {
|
||||
const oldServiceMatched = _.find(oldServices, { Name: newService.Name });
|
||||
if (oldServiceMatched) {
|
||||
await this.KubernetesServiceService.patch(oldServiceMatched, newService);
|
||||
try {
|
||||
await this.KubernetesServiceService.patch(oldServiceMatched, newService);
|
||||
} catch (error) {
|
||||
notifyError('Unable to update service', error);
|
||||
}
|
||||
} else {
|
||||
await this.KubernetesServiceService.create(newService);
|
||||
try {
|
||||
await this.KubernetesServiceService.create(newService);
|
||||
} catch (error) {
|
||||
notifyError('Unable to create service', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1291,7 +1291,12 @@
|
|||
</div>
|
||||
|
||||
<!-- kubernetes services options -->
|
||||
<kube-services-view form-values="ctrl.formValues" is-edit="ctrl.state.isEdit" loadbalancer-enabled="ctrl.publishViaLoadBalancerEnabled()"></kube-services-view>
|
||||
<kube-services-view
|
||||
form-values="ctrl.formValues"
|
||||
is-edit="ctrl.state.isEdit"
|
||||
namespaces="ctrl.allNamespaces"
|
||||
loadbalancer-enabled="ctrl.publishViaLoadBalancerEnabled()"
|
||||
></kube-services-view>
|
||||
<!-- kubernetes services options -->
|
||||
|
||||
<!-- summary -->
|
||||
|
@ -1349,7 +1354,7 @@
|
|||
ng-if="ctrl.state.appType === ctrl.KubernetesDeploymentTypes.APPLICATION_FORM"
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm !ml-0"
|
||||
ng-disabled="!kubernetesApplicationCreationForm.$valid || ctrl.isDeployUpdateButtonDisabled() || !ctrl.imageValidityIsValid()"
|
||||
ng-disabled="!kubernetesApplicationCreationForm.$valid || ctrl.isDeployUpdateButtonDisabled() || !ctrl.imageValidityIsValid() || ctrl.hasPortErrors()"
|
||||
ng-click="ctrl.deployApplication()"
|
||||
button-spinner="ctrl.state.actionInProgress"
|
||||
data-cy="k8sAppCreate-deployButton"
|
||||
|
|
|
@ -680,6 +680,11 @@ class KubernetesCreateApplicationController {
|
|||
return this.formValues.DeploymentType === this.ApplicationDeploymentTypes.GLOBAL ? this.nodeNumber : this.formValues.ReplicaCount;
|
||||
}
|
||||
|
||||
hasPortErrors() {
|
||||
const portError = this.formValues.Services.some((service) => service.nodePortError || service.servicePortError);
|
||||
return portError;
|
||||
}
|
||||
|
||||
resourceReservationsOverflow() {
|
||||
const instances = this.effectiveInstances();
|
||||
const cpu = this.formValues.CpuLimit;
|
||||
|
@ -1187,6 +1192,7 @@ class KubernetesCreateApplicationController {
|
|||
|
||||
const nonSystemNamespaces = _.filter(resourcePools, (resourcePool) => !KubernetesNamespaceHelper.isSystemNamespace(resourcePool.Namespace.Name));
|
||||
|
||||
this.allNamespaces = resourcePools.map(({ Namespace }) => Namespace.Name);
|
||||
this.resourcePools = _.sortBy(nonSystemNamespaces, ({ Namespace }) => (Namespace.Name === 'default' ? 0 : 1));
|
||||
|
||||
this.formValues.ResourcePool = this.resourcePools[0];
|
||||
|
|
|
@ -284,6 +284,7 @@
|
|||
<!-- table -->
|
||||
<kubernetes-application-services-table
|
||||
services="ctrl.application.Services"
|
||||
namespaces="ctrl.allNamespaces"
|
||||
application="ctrl.application"
|
||||
public-url="ctrl.state.publicUrl"
|
||||
></kubernetes-application-services-table>
|
||||
|
|
|
@ -108,6 +108,7 @@ class KubernetesApplicationController {
|
|||
Notifications,
|
||||
LocalStorage,
|
||||
ModalService,
|
||||
KubernetesResourcePoolService,
|
||||
KubernetesApplicationService,
|
||||
KubernetesEventService,
|
||||
KubernetesStackService,
|
||||
|
@ -121,6 +122,7 @@ class KubernetesApplicationController {
|
|||
this.Notifications = Notifications;
|
||||
this.LocalStorage = LocalStorage;
|
||||
this.ModalService = ModalService;
|
||||
this.KubernetesResourcePoolService = KubernetesResourcePoolService;
|
||||
this.StackService = StackService;
|
||||
|
||||
this.KubernetesApplicationService = KubernetesApplicationService;
|
||||
|
@ -376,6 +378,9 @@ class KubernetesApplicationController {
|
|||
SelectedRevision: undefined,
|
||||
};
|
||||
|
||||
const resourcePools = await this.KubernetesResourcePoolService.get();
|
||||
this.allNamespaces = resourcePools.map(({ Namespace }) => Namespace.Name);
|
||||
|
||||
await this.getApplication();
|
||||
await this.getEvents();
|
||||
this.updateApplicationKindText();
|
||||
|
|
Loading…
Reference in New Issue