fix(ingress): empty initial selection + fixes [EE-5852] (#10067)

Co-authored-by: testa113 <testa113>
pull/10070/head
Ali 1 year ago committed by GitHub
parent d54dd47b21
commit 55236129ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -53,6 +53,8 @@ export function CreateIngressView() {
const [namespace, setNamespace] = useState<string>(params.namespace || ''); const [namespace, setNamespace] = useState<string>(params.namespace || '');
const [ingressRule, setIngressRule] = useState<Rule>({} as Rule); const [ingressRule, setIngressRule] = useState<Rule>({} as Rule);
// isEditClassNameSet is used to prevent premature validation of the classname in the edit view
const [isEditClassNameSet, setIsEditClassNameSet] = useState<boolean>(false);
const [errors, setErrors] = useState<Record<string, ReactNode>>( const [errors, setErrors] = useState<Record<string, ReactNode>>(
{} as Record<string, string> {} as Record<string, string>
@ -243,14 +245,21 @@ export function CreateIngressView() {
[ingressControllers] [ingressControllers]
); );
// when the ingress class options update the value to an available one // when them selected ingress class option update is no longer available set to an empty value
useEffect(() => { useEffect(() => {
const ingressClasses = ingressClassOptions.map((option) => option.value); const ingressClasses = ingressClassOptions.map((option) => option.value);
if (!ingressClasses.includes(ingressRule.IngressClassName)) { if (
// setting to the first available option (or undefined when there are no options) !ingressClasses.includes(ingressRule.IngressClassName) &&
handleIngressChange('IngressClassName', ingressClasses[0]); ingressControllersQuery.isSuccess
) {
handleIngressChange('IngressClassName', '');
} }
}, [handleIngressChange, ingressClassOptions, ingressRule.IngressClassName]); }, [
handleIngressChange,
ingressClassOptions,
ingressControllersQuery.isSuccess,
ingressRule.IngressClassName,
]);
const matchedConfigs = configResults?.data?.filter( const matchedConfigs = configResults?.data?.filter(
(config) => (config) =>
@ -289,6 +298,7 @@ export function CreateIngressView() {
const r = prepareRuleFromIngress(ing, type); const r = prepareRuleFromIngress(ing, type);
r.IngressType = type || r.IngressType; r.IngressType = type || r.IngressType;
setIngressRule(r); setIngressRule(r);
setIsEditClassNameSet(true);
} }
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
@ -365,12 +375,15 @@ export function CreateIngressView() {
errors.ingressName = 'Ingress name already exists'; errors.ingressName = 'Ingress name already exists';
} }
if (!ingressClassOptions.length && ingressControllersQuery.isSuccess) { if (
(!ingressClassOptions.length || !rule.IngressClassName) &&
ingressControllersQuery.isSuccess
) {
errors.className = 'Ingress class is required'; errors.className = 'Ingress class is required';
} }
} }
if (isEdit && !ingressRule.IngressClassName) { if (isEdit && !ingressRule.IngressClassName && isEditClassNameSet) {
errors.className = errors.className =
'No ingress class is currently set for this ingress - use of the Portainer UI requires one to be set.'; 'No ingress class is currently set for this ingress - use of the Portainer UI requires one to be set.';
} }
@ -513,7 +526,8 @@ export function CreateIngressView() {
}, },
[ [
isEdit, isEdit,
ingressClassOptions, isEditClassNameSet,
ingressClassOptions.length,
ingressControllersQuery.isSuccess, ingressControllersQuery.isSuccess,
environmentId, environmentId,
ingresses, ingresses,
@ -583,6 +597,8 @@ export function CreateIngressView() {
handleNamespaceChange={handleNamespaceChange} handleNamespaceChange={handleNamespaceChange}
namespacesOptions={namespaceOptions} namespacesOptions={namespaceOptions}
isNamespaceOptionsLoading={namespacesQuery.isLoading} isNamespaceOptionsLoading={namespacesQuery.isLoading}
// wait for ingress results too to set a name that's not taken with handleNamespaceChange()
isIngressNamesLoading={ingressesResults.isLoading}
/> />
</div> </div>
{namespace && ( {namespace && (
@ -688,6 +704,7 @@ export function CreateIngressView() {
Namespace: namespace, Namespace: namespace,
IngressName: newKey, IngressName: newKey,
IngressClassName: ingressRule.IngressClassName || '', IngressClassName: ingressRule.IngressClassName || '',
IngressType: ingressRule.IngressType || '',
Hosts: [host], Hosts: [host],
}; };

@ -47,6 +47,7 @@ interface Props {
tlsOptions: Option<string>[]; tlsOptions: Option<string>[];
namespacesOptions: Option<string>[]; namespacesOptions: Option<string>[];
isNamespaceOptionsLoading: boolean; isNamespaceOptionsLoading: boolean;
isIngressNamesLoading: boolean;
removeIngressRoute: (hostIndex: number, pathIndex: number) => void; removeIngressRoute: (hostIndex: number, pathIndex: number) => void;
removeIngressHost: (hostIndex: number) => void; removeIngressHost: (hostIndex: number) => void;
@ -102,6 +103,7 @@ export function IngressForm({
errors, errors,
namespacesOptions, namespacesOptions,
isNamespaceOptionsLoading, isNamespaceOptionsLoading,
isIngressNamesLoading,
handleNamespaceChange, handleNamespaceChange,
namespace, namespace,
}: Props) { }: Props) {
@ -114,10 +116,21 @@ export function IngressForm({
// when the namespace options update the value to an available one // when the namespace options update the value to an available one
useEffect(() => { useEffect(() => {
const namespaces = namespacesOptions.map((option) => option.value); const namespaces = namespacesOptions.map((option) => option.value);
if (!namespaces.includes(namespace) && namespaces.length > 0) { if (
!namespaces.includes(namespace) &&
namespaces.length > 0 &&
(!isIngressNamesLoading || isEdit)
) {
handleNamespaceChange(namespaces[0]); handleNamespaceChange(namespaces[0]);
} }
}, [namespacesOptions, namespace, handleNamespaceChange]); }, [
namespacesOptions,
namespace,
handleNamespaceChange,
isNamespaceOptionsLoading,
isEdit,
isIngressNamesLoading,
]);
return ( return (
<Widget> <Widget>
@ -526,7 +539,7 @@ export function IngressForm({
)} )}
</div> </div>
<div className="form-group col-sm-2 col-xl-2 !m-0 !pl-0"> <div className="form-group col-sm-2 col-xl-2 !m-0 min-w-[170px] !pl-0">
{servicePorts && ( {servicePorts && (
<> <>
<InputGroup size="small"> <InputGroup size="small">
@ -669,7 +682,7 @@ export function IngressForm({
<div className="form-group col-sm-1 !m-0 !pl-0"> <div className="form-group col-sm-1 !m-0 !pl-0">
<Button <Button
className="btn-only-icon vertical-center !ml-0" className="!ml-0 h-[30px]"
color="dangerlight" color="dangerlight"
type="button" type="button"
data-cy={`k8sAppCreate-rmPortButton_${hostIndex}-${pathIndex}`} data-cy={`k8sAppCreate-rmPortButton_${hostIndex}-${pathIndex}`}

Loading…
Cancel
Save