mirror of https://github.com/portainer/portainer
fix(k8s/ingress): ensure new ports are only added to ingress only if app is published via ingress (#6153)
* fix(k8s/ingress): ensure new ports are only added to ingress only if app is published via ingress * refactor(k8s/ingress): removed deleted ports of ingress in a single passpull/6176/head
parent
69c17986d9
commit
b6fbf8eecc
|
@ -7,6 +7,7 @@ import {
|
||||||
KubernetesResourcePoolIngressClassFormValue,
|
KubernetesResourcePoolIngressClassFormValue,
|
||||||
KubernetesResourcePoolIngressClassHostFormValue,
|
KubernetesResourcePoolIngressClassHostFormValue,
|
||||||
} from 'Kubernetes/models/resource-pool/formValues';
|
} from 'Kubernetes/models/resource-pool/formValues';
|
||||||
|
import { KubernetesApplicationPublishingTypes } from '../models/application/models';
|
||||||
import { KubernetesIngress, KubernetesIngressRule } from './models';
|
import { KubernetesIngress, KubernetesIngressRule } from './models';
|
||||||
import { KubernetesIngressCreatePayload, KubernetesIngressRuleCreatePayload, KubernetesIngressRulePathCreatePayload } from './payloads';
|
import { KubernetesIngressCreatePayload, KubernetesIngressRuleCreatePayload, KubernetesIngressRulePathCreatePayload } from './payloads';
|
||||||
import { KubernetesIngressClassAnnotation, KubernetesIngressClassRewriteTargetAnnotations } from './constants';
|
import { KubernetesIngressClassAnnotation, KubernetesIngressClassRewriteTargetAnnotations } from './constants';
|
||||||
|
@ -45,23 +46,31 @@ export class KubernetesIngressConverter {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts Application Form Value (from Create Application View) to Ingresses
|
||||||
|
* @param {KubernetesApplicationFormValues} formValues
|
||||||
|
* @param {string} serviceName
|
||||||
|
* @returns {KubernetesIngressRule[]}
|
||||||
|
*/
|
||||||
static applicationFormValuesToIngresses(formValues, serviceName) {
|
static applicationFormValuesToIngresses(formValues, serviceName) {
|
||||||
|
const isPublishingToIngress = formValues.PublishingType === KubernetesApplicationPublishingTypes.INGRESS;
|
||||||
const ingresses = angular.copy(formValues.OriginalIngresses);
|
const ingresses = angular.copy(formValues.OriginalIngresses);
|
||||||
_.forEach(formValues.PublishedPorts, (p) => {
|
_.forEach(formValues.PublishedPorts, (p) => {
|
||||||
const ingress = _.find(ingresses, { Name: p.IngressName });
|
const ingress = _.find(ingresses, { Name: p.IngressName });
|
||||||
if (ingress && p.NeedsDeletion) {
|
if (ingress) {
|
||||||
const path = _.find(ingress.Paths, { Port: p.ContainerPort, ServiceName: serviceName, Path: p.IngressRoute });
|
if (p.NeedsDeletion) {
|
||||||
_.remove(ingress.Paths, path);
|
_.remove(ingress.Paths, (path) => path.Port === p.ContainerPort && path.ServiceName === serviceName && path.Path === p.IngressRoute);
|
||||||
} else if (ingress && p.IsNew) {
|
} else if (isPublishingToIngress && p.IsNew) {
|
||||||
const rule = new KubernetesIngressRule();
|
const rule = new KubernetesIngressRule();
|
||||||
rule.IngressName = ingress.Name;
|
rule.IngressName = ingress.Name;
|
||||||
rule.ServiceName = serviceName;
|
rule.ServiceName = serviceName;
|
||||||
rule.Port = p.ContainerPort;
|
rule.Port = p.ContainerPort;
|
||||||
if (p.IngressRoute) {
|
if (p.IngressRoute) {
|
||||||
rule.Path = _.startsWith(p.IngressRoute, '/') ? p.IngressRoute : '/' + p.IngressRoute;
|
rule.Path = _.startsWith(p.IngressRoute, '/') ? p.IngressRoute : '/' + p.IngressRoute;
|
||||||
|
}
|
||||||
|
rule.Host = p.IngressHost;
|
||||||
|
ingress.Paths.push(rule);
|
||||||
}
|
}
|
||||||
rule.Host = p.IngressHost;
|
|
||||||
ingress.Paths.push(rule);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return ingresses;
|
return ingresses;
|
||||||
|
@ -69,7 +78,8 @@ export class KubernetesIngressConverter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {KubernetesResourcePoolIngressClassFormValue} formValues
|
* @param {KubernetesResourcePoolIngressClassFormValue[]} formValues
|
||||||
|
* @returns {KubernetesIngress} Ingress
|
||||||
*/
|
*/
|
||||||
static resourcePoolIngressClassFormValueToIngress(formValues) {
|
static resourcePoolIngressClassFormValueToIngress(formValues) {
|
||||||
const res = new KubernetesIngress();
|
const res = new KubernetesIngress();
|
||||||
|
|
|
@ -27,6 +27,7 @@ export function KubernetesApplicationFormValues() {
|
||||||
this.PlacementType = KubernetesApplicationPlacementTypes.PREFERRED;
|
this.PlacementType = KubernetesApplicationPlacementTypes.PREFERRED;
|
||||||
this.Placements = []; // KubernetesApplicationPlacementFormValue lis;
|
this.Placements = []; // KubernetesApplicationPlacementFormValue lis;
|
||||||
this.OriginalIngresses = undefined;
|
this.OriginalIngresses = undefined;
|
||||||
|
this.IsPublishingService = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const KubernetesApplicationConfigurationFormValueOverridenKeyTypes = Object.freeze({
|
export const KubernetesApplicationConfigurationFormValueOverridenKeyTypes = Object.freeze({
|
||||||
|
|
|
@ -346,10 +346,14 @@ class KubernetesApplicationService {
|
||||||
await apiService.patch(oldAppPayload, newAppPayload);
|
await apiService.patch(oldAppPayload, newAppPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
// accept either formValues or applications as parameters
|
// accept either formValues or applications as parameters depending on partial value
|
||||||
// depending on partial value
|
|
||||||
// true = KubernetesApplication
|
// true = KubernetesApplication
|
||||||
// false = KubernetesApplicationFormValues
|
// false = KubernetesApplicationFormValues
|
||||||
|
//
|
||||||
|
// e.g. signatures are
|
||||||
|
//
|
||||||
|
// patch(oldValues: KubernetesApplication, newValues: KubernetesApplication, partial: (undefined | false)): Promise<unknown>
|
||||||
|
// patch(oldValues: KubernetesApplicationFormValues, newValues: KubernetesApplicationFormValues, partial: true): Promise<unknown>
|
||||||
patch(oldValues, newValues, partial = false) {
|
patch(oldValues, newValues, partial = false) {
|
||||||
if (partial) {
|
if (partial) {
|
||||||
return this.$async(this.patchPartialAsync, oldValues, newValues);
|
return this.$async(this.patchPartialAsync, oldValues, newValues);
|
||||||
|
|
|
@ -1246,7 +1246,13 @@
|
||||||
Enable publishing for this application
|
Enable publishing for this application
|
||||||
</label>
|
</label>
|
||||||
<label class="switch" style="margin-left: 20px;">
|
<label class="switch" style="margin-left: 20px;">
|
||||||
<input type="checkbox" class="form-control" name="enable_port_publishing" ng-model="ctrl.formValues.IsPublishingService" />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="form-control"
|
||||||
|
name="enable_port_publishing"
|
||||||
|
ng-model="ctrl.formValues.IsPublishingService"
|
||||||
|
ng-change="ctrl.onServicePublishChange()"
|
||||||
|
/>
|
||||||
<i></i>
|
<i></i>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -144,8 +144,6 @@ class KubernetesCreateApplicationController {
|
||||||
this.setPullImageValidity = this.setPullImageValidity.bind(this);
|
this.setPullImageValidity = this.setPullImageValidity.bind(this);
|
||||||
this.onChangeFileContent = this.onChangeFileContent.bind(this);
|
this.onChangeFileContent = this.onChangeFileContent.bind(this);
|
||||||
this.onServicePublishChange = this.onServicePublishChange.bind(this);
|
this.onServicePublishChange = this.onServicePublishChange.bind(this);
|
||||||
|
|
||||||
this.$scope.$watch(() => this.formValues.IsPublishingService, this.onServicePublishChange);
|
|
||||||
}
|
}
|
||||||
/* #endregion */
|
/* #endregion */
|
||||||
|
|
||||||
|
@ -426,34 +424,31 @@ class KubernetesCreateApplicationController {
|
||||||
|
|
||||||
/* #endregion */
|
/* #endregion */
|
||||||
|
|
||||||
|
/* #region PUBLISHED PORTS UI MANAGEMENT */
|
||||||
onServicePublishChange() {
|
onServicePublishChange() {
|
||||||
// service creation
|
// enable publishing with no previous ports exposed
|
||||||
if (this.formValues.PublishedPorts.length === 0) {
|
if (this.formValues.IsPublishingService && !this.formValues.PublishedPorts.length) {
|
||||||
if (this.formValues.IsPublishingService) {
|
this.addPublishedPort();
|
||||||
// toggle enabled
|
|
||||||
this.addPublishedPort();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// service update
|
// service update
|
||||||
if (this.formValues.IsPublishingService) {
|
if (this.formValues.IsPublishingService) {
|
||||||
// toggle enabled
|
|
||||||
this.formValues.PublishedPorts.forEach((port) => (port.NeedsDeletion = false));
|
this.formValues.PublishedPorts.forEach((port) => (port.NeedsDeletion = false));
|
||||||
} else {
|
} else {
|
||||||
// toggle disabled
|
// delete new ports, mark old ports to be deleted
|
||||||
// all new ports need to be deleted, existing ports need to be marked as needing deletion
|
|
||||||
this.formValues.PublishedPorts = this.formValues.PublishedPorts.filter((port) => !port.IsNew).map((port) => ({ ...port, NeedsDeletion: true }));
|
this.formValues.PublishedPorts = this.formValues.PublishedPorts.filter((port) => !port.IsNew).map((port) => ({ ...port, NeedsDeletion: true }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #region PUBLISHED PORTS UI MANAGEMENT */
|
|
||||||
addPublishedPort() {
|
addPublishedPort() {
|
||||||
const p = new KubernetesApplicationPublishedPortFormValue();
|
const p = new KubernetesApplicationPublishedPortFormValue();
|
||||||
const ingresses = this.ingresses;
|
const ingresses = this.ingresses;
|
||||||
p.IngressName = ingresses && ingresses.length ? ingresses[0].Name : undefined;
|
if (this.formValues.PublishingType === KubernetesApplicationPublishingTypes.INGRESS) {
|
||||||
p.IngressHost = ingresses && ingresses.length ? ingresses[0].Hosts[0] : undefined;
|
p.IngressName = ingresses && ingresses.length ? ingresses[0].Name : undefined;
|
||||||
p.IngressHosts = ingresses && ingresses.length ? ingresses[0].Hosts : undefined;
|
p.IngressHost = ingresses && ingresses.length ? ingresses[0].Hosts[0] : undefined;
|
||||||
|
p.IngressHosts = ingresses && ingresses.length ? ingresses[0].Hosts : undefined;
|
||||||
|
}
|
||||||
if (this.formValues.PublishedPorts.length) {
|
if (this.formValues.PublishedPorts.length) {
|
||||||
p.Protocol = this.formValues.PublishedPorts[0].Protocol;
|
p.Protocol = this.formValues.PublishedPorts[0].Protocol;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,12 @@
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"paths": {
|
"paths": {
|
||||||
// paths relative to the baseUrl
|
// paths relative to the baseUrl
|
||||||
"@/*": ["./*", "../app/*"]
|
"@/*": ["./*", "../app/*"],
|
||||||
|
"Agent/*": ["agent/*"],
|
||||||
|
"Azure/*": ["azure/*"],
|
||||||
|
"Docker/*": ["docker/*"],
|
||||||
|
"Kubernetes/*": ["kubernetes/*"],
|
||||||
|
"Portainer/*": ["portainer/*"],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"exclude": ["api", "build", "dist", "distribution", "node_modules", "test", "webpack"],
|
"exclude": ["api", "build", "dist", "distribution", "node_modules", "test", "webpack"],
|
||||||
|
|
Loading…
Reference in New Issue