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,
 | 
			
		||||
  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, KubernetesIngressClassRewriteTargetAnnotations } from './constants';
 | 
			
		||||
| 
						 | 
				
			
			@ -45,23 +46,31 @@ 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 && p.NeedsDeletion) {
 | 
			
		||||
        const path = _.find(ingress.Paths, { Port: p.ContainerPort, ServiceName: serviceName, Path: p.IngressRoute });
 | 
			
		||||
        _.remove(ingress.Paths, path);
 | 
			
		||||
      } else if (ingress && 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;
 | 
			
		||||
      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);
 | 
			
		||||
        }
 | 
			
		||||
        rule.Host = p.IngressHost;
 | 
			
		||||
        ingress.Paths.push(rule);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    return ingresses;
 | 
			
		||||
| 
						 | 
				
			
			@ -69,7 +78,8 @@ export class KubernetesIngressConverter {
 | 
			
		|||
 | 
			
		||||
  /**
 | 
			
		||||
   *
 | 
			
		||||
   * @param {KubernetesResourcePoolIngressClassFormValue} formValues
 | 
			
		||||
   * @param {KubernetesResourcePoolIngressClassFormValue[]} formValues
 | 
			
		||||
   * @returns {KubernetesIngress} Ingress
 | 
			
		||||
   */
 | 
			
		||||
  static resourcePoolIngressClassFormValueToIngress(formValues) {
 | 
			
		||||
    const res = new KubernetesIngress();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ export function KubernetesApplicationFormValues() {
 | 
			
		|||
  this.PlacementType = KubernetesApplicationPlacementTypes.PREFERRED;
 | 
			
		||||
  this.Placements = []; // KubernetesApplicationPlacementFormValue lis;
 | 
			
		||||
  this.OriginalIngresses = undefined;
 | 
			
		||||
  this.IsPublishingService = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const KubernetesApplicationConfigurationFormValueOverridenKeyTypes = Object.freeze({
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -346,10 +346,14 @@ class KubernetesApplicationService {
 | 
			
		|||
    await apiService.patch(oldAppPayload, newAppPayload);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // accept either formValues or applications as parameters
 | 
			
		||||
  // depending on partial value
 | 
			
		||||
  // accept either formValues or applications as parameters depending on partial value
 | 
			
		||||
  // true = KubernetesApplication
 | 
			
		||||
  // 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) {
 | 
			
		||||
    if (partial) {
 | 
			
		||||
      return this.$async(this.patchPartialAsync, oldValues, newValues);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1246,7 +1246,13 @@
 | 
			
		|||
                      Enable publishing for this application
 | 
			
		||||
                    </label>
 | 
			
		||||
                    <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>
 | 
			
		||||
                    </label>
 | 
			
		||||
                  </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -144,8 +144,6 @@ class KubernetesCreateApplicationController {
 | 
			
		|||
    this.setPullImageValidity = this.setPullImageValidity.bind(this);
 | 
			
		||||
    this.onChangeFileContent = this.onChangeFileContent.bind(this);
 | 
			
		||||
    this.onServicePublishChange = this.onServicePublishChange.bind(this);
 | 
			
		||||
 | 
			
		||||
    this.$scope.$watch(() => this.formValues.IsPublishingService, this.onServicePublishChange);
 | 
			
		||||
  }
 | 
			
		||||
  /* #endregion */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -426,34 +424,31 @@ class KubernetesCreateApplicationController {
 | 
			
		|||
 | 
			
		||||
  /* #endregion */
 | 
			
		||||
 | 
			
		||||
  /* #region  PUBLISHED PORTS UI MANAGEMENT */
 | 
			
		||||
  onServicePublishChange() {
 | 
			
		||||
    // service creation
 | 
			
		||||
    if (this.formValues.PublishedPorts.length === 0) {
 | 
			
		||||
      if (this.formValues.IsPublishingService) {
 | 
			
		||||
        // toggle enabled
 | 
			
		||||
        this.addPublishedPort();
 | 
			
		||||
      }
 | 
			
		||||
    // enable publishing with no previous ports exposed
 | 
			
		||||
    if (this.formValues.IsPublishingService && !this.formValues.PublishedPorts.length) {
 | 
			
		||||
      this.addPublishedPort();
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // service update
 | 
			
		||||
    if (this.formValues.IsPublishingService) {
 | 
			
		||||
      // toggle enabled
 | 
			
		||||
      this.formValues.PublishedPorts.forEach((port) => (port.NeedsDeletion = false));
 | 
			
		||||
    } else {
 | 
			
		||||
      // toggle disabled
 | 
			
		||||
      // all new ports need to be deleted, existing ports need to be marked as needing deletion
 | 
			
		||||
      // delete new ports, mark old ports to be deleted
 | 
			
		||||
      this.formValues.PublishedPorts = this.formValues.PublishedPorts.filter((port) => !port.IsNew).map((port) => ({ ...port, NeedsDeletion: true }));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* #region  PUBLISHED PORTS UI MANAGEMENT */
 | 
			
		||||
  addPublishedPort() {
 | 
			
		||||
    const p = new KubernetesApplicationPublishedPortFormValue();
 | 
			
		||||
    const ingresses = this.ingresses;
 | 
			
		||||
    p.IngressName = ingresses && ingresses.length ? ingresses[0].Name : undefined;
 | 
			
		||||
    p.IngressHost = ingresses && ingresses.length ? ingresses[0].Hosts[0] : undefined;
 | 
			
		||||
    p.IngressHosts = ingresses && ingresses.length ? ingresses[0].Hosts : undefined;
 | 
			
		||||
    if (this.formValues.PublishingType === KubernetesApplicationPublishingTypes.INGRESS) {
 | 
			
		||||
      p.IngressName = ingresses && ingresses.length ? ingresses[0].Name : 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) {
 | 
			
		||||
      p.Protocol = this.formValues.PublishedPorts[0].Protocol;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,12 @@
 | 
			
		|||
    "lib": ["dom", "dom.iterable", "esnext"],
 | 
			
		||||
    "paths": {
 | 
			
		||||
      // 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"],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue