fix(app): fix app ingress edge cases [EE-5663] (#9150)

Co-authored-by: testa113 <testa113>
pull/9181/head
Ali 2023-07-10 16:20:22 +12:00 committed by GitHub
parent 8b11e1678e
commit c752b98120
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 10 deletions

View File

@ -512,6 +512,17 @@ class KubernetesCreateApplicationController {
/* #region SERVICES UI MANAGEMENT */
onServicesChange(services) {
return this.$async(async () => {
// if the ingress isn't found in the currently loaded ingresses, then refresh the ingresses
const ingressNamesUsed = services.flatMap((s) => s.Ports.flatMap((p) => (p.ingressPaths ? p.ingressPaths.flatMap((ip) => ip.IngressName || []) : [])));
if (ingressNamesUsed.length) {
const uniqueIngressNamesUsed = Array.from(new Set(ingressNamesUsed)); // get the unique ingress names used
const ingressNamesLoaded = this.ingresses.map((i) => i.Name);
const areAllIngressesLoaded = uniqueIngressNamesUsed.every((ingressNameUsed) => ingressNamesLoaded.includes(ingressNameUsed));
if (!areAllIngressesLoaded) {
this.refreshIngresses();
}
}
// update the services
this.formValues.Services = services;
});
}
@ -1127,7 +1138,6 @@ class KubernetesCreateApplicationController {
this.nodesLabels,
this.ingresses
);
this.originalServicePorts = structuredClone(this.formValues.Services.flatMap((service) => service.Ports));
this.originalIngressPaths = structuredClone(this.originalServicePorts.flatMap((port) => port.ingressPaths).filter((ingressPath) => ingressPath.Host));

View File

@ -79,7 +79,7 @@ export function ClusterIpServiceForm({
return (
<Card key={portIndex} className="flex flex-col gap-y-3">
<div className="flex flex-grow flex-wrap justify-between gap-x-4 gap-y-1">
<div className="inline-flex min-w-min flex-grow basis-3/4 flex-wrap gap-2">
<div className="inline-flex min-w-min flex-grow basis-3/4 flex-wrap gap-x-4 gap-y-1">
<div className="flex min-w-min basis-1/3 flex-col">
<ContainerPortInput
serviceIndex={serviceIndex}

View File

@ -5,8 +5,8 @@ import { InputGroup } from '@@/form-components/InputGroup';
type Props = {
serviceIndex: number;
portIndex: number;
value?: number;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
value?: number;
};
export function ContainerPortInput({

View File

@ -63,13 +63,29 @@ export function AppIngressPathForm({
isEditMode,
]);
// when the hostname options change (e.g. after a namespace change), update the selected ingress to the first available one
// when the hostname options change (e.g. after a namespace change) and the host and ingress is no longer available, update the selected ingress to the first available one
useEffect(() => {
if (ingressHostOptionsWithCurrentValue) {
// some rerenders might not be from a namespace or hostname change so keep the current values if they're still valid
const ingressHosts = ingressHostOptionsWithCurrentValue.map(
(i) => i.value
);
const newIngressHostValue = ingressHosts.includes(ingressPath?.Host ?? '')
? ingressPath?.Host
: ingressHosts[0] ?? '';
const ingressNames = ingressHostOptionsWithCurrentValue.map(
(i) => i.ingressName
);
const newIngressNameValue = ingressNames.includes(
ingressPath?.IngressName ?? ''
)
? ingressPath?.IngressName ?? ''
: ingressNames[0] ?? '';
const newIngressPath = {
...ingressPath,
Host: ingressHostOptionsWithCurrentValue[0]?.value,
IngressName: ingressHostOptionsWithCurrentValue[0]?.ingressName,
Host: newIngressHostValue,
IngressName: newIngressNameValue,
};
onChangeIngressPath(newIngressPath);
setSelectedIngress(ingressHostOptionsWithCurrentValue[0] ?? null);
@ -78,7 +94,7 @@ export function AppIngressPathForm({
}, [ingressHostOptionsWithCurrentValue]);
return (
<div className="flex w-full flex-wrap gap-x-4">
<div className="flex w-full flex-wrap gap-x-4 gap-y-1">
<div className="flex min-w-[250px] basis-1/3 flex-col">
<InputGroup size="small">
<InputGroup.Addon>Hostname</InputGroup.Addon>

View File

@ -1,4 +1,4 @@
import { Plus } from 'lucide-react';
import { Loader2, Plus } from 'lucide-react';
import { FormikErrors } from 'formik';
import { useMemo } from 'react';
@ -13,6 +13,7 @@ import { Button } from '@@/buttons';
import { SwitchField } from '@@/form-components/SwitchField';
import { TextTip } from '@@/Tip/TextTip';
import { Link } from '@@/Link';
import { Icon } from '@@/Icon';
import { ServicePortIngressPath } from '../types';
@ -75,7 +76,12 @@ export function AppIngressPathsForm({
}
if (ingressesQuery.isLoading || ingressControllersQuery.isLoading) {
return <p>Loading ingresses...</p>;
return (
<p className="text-muted mt-2 flex items-center gap-x-2 text-sm">
<Icon icon={Loader2} className="animate-spin-slow" />
Loading ingresses...
</p>
);
}
return (

View File

@ -154,6 +154,8 @@ export function generateNewIngressesFromFormPaths(
return newIngresses;
}
/** prependWithSlash puts a '/' in front of a string if there isn't one there already. If the string is empty, it stays empty */
export function prependWithSlash(path?: string) {
return path?.startsWith('/') ? path : `/${path}`;
if (!path) return '';
return path.startsWith('/') ? path : `/${path}`;
}