Skip to content

Commit

Permalink
[LKEAPIFW-428] Migration of non-ipacl'd clusters now working
Browse files Browse the repository at this point in the history
  • Loading branch information
Talmai Oliveira committed Sep 22, 2024
1 parent 3b2f66e commit c2a2ecd
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ export const ControlPlaneACLPane = (props: ControlPlaneACLProps) => {
}
};

const [inputError, setInputError] = React.useState<string | undefined>('');
const [ipV4InputError, setIPV4InputError] = React.useState<
string | undefined
>('');
const [ipV6InputError, setIPV6InputError] = React.useState<
string | undefined
>('');

return (
<FormControl data-testid="control-plane-ipacl-form">
Expand All @@ -81,32 +86,42 @@ export const ControlPlaneACLPane = (props: ControlPlaneACLProps) => {
/>
<Stack sx={{ display: statusStyle(enableControlPlaneACL) }}>
<MultipleIPInput
buttonText="Add IPv4 Address to ACL"
buttonText="Add IP Address"
ips={ipV4Addr}
onChange={(_ips: ExtendedIP[]) => {
const validatedIPs = validateIPs(_ips, {
allowEmptyAddress: false,
errorMessage: 'Must be a valid IPv4 address.',
});
const ipsWithErrors = validatedIPs.filter((thisIP) =>
setInputError(thisIP.error)
setIPV4InputError(thisIP.error)
);
if (ipsWithErrors.length === 0) {
handleIPv4Change(validatedIPs);
}
}}
placeholder="0.0.0.0/0"
title="" // Empty string so a title isn't displayed for each IP input
error={inputError}
title="IPv4 Addresses or CIDR"
error={ipV4InputError}
/>
<MultipleIPInput
buttonText="Add IPv6 Address to ACL"
buttonText="Add IP Address"
ips={ipV6Addr}
onChange={(newIpV6Addr: ExtendedIP[]) => {
handleIPv6Change(newIpV6Addr);
onChange={(_ips: ExtendedIP[]) => {
const validatedIPs = validateIPs(_ips, {
allowEmptyAddress: false,
errorMessage: 'Must be a valid IPv6 address.',
});
const ipsWithErrors: ExtendedIP[] = validatedIPs.filter((thisIP) =>
setIPV6InputError(thisIP.error)
);
if (ipsWithErrors.length === 0) {
handleIPv6Change(validatedIPs);
}
}}
placeholder="::/0"
title="" // Empty string so a title isn't displayed for each IP input
title="IPv6 Addresses or CIDR"
error={ipV6InputError}
/>
</Stack>
</FormControl>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type { Theme } from '@mui/material/styles';

interface Props {
cluster: KubernetesCluster;
setControlPlaneACLMigrated: (s: boolean) => void;
handleOpenDrawer: () => void;
}

Expand Down Expand Up @@ -69,7 +70,7 @@ const useStyles = makeStyles()((theme: Theme) => ({

export const KubeClusterControlPlaneACL = React.memo((props: Props) => {
const theme = useTheme();
const { cluster, handleOpenDrawer } = props;
const { cluster, handleOpenDrawer, setControlPlaneACLMigrated } = props;
const { classes } = useStyles();

const {
Expand All @@ -88,6 +89,12 @@ export const KubeClusterControlPlaneACL = React.memo((props: Props) => {
: 0;
const totalNumberIPs = totalIPv4 + totalIPv6;

const failedMigrationStatus = () => {
// when a cluster has not migrated, the query will always fail
setControlPlaneACLMigrated(!isErrorKubernetesACL);
return isErrorKubernetesACL;
};

const IPACLdClusterToolTip = () => {
return (
<TooltipIcon
Expand Down Expand Up @@ -131,16 +138,20 @@ export const KubeClusterControlPlaneACL = React.memo((props: Props) => {
const NotMigratedCopy = () => {
return (
<>
Cluster Requires Migration
<IPACLdClusterToolTip />
<Box className={classes.aclElement} onClick={handleOpenDrawer}>
<Typography className={classes.aclElementText}>
Cluster Requires Migration
</Typography>
<IPACLdClusterToolTip />
</Box>
</>
);
};

const kubeSpecsLeft = [
isLoadingKubernetesACL ? (
<CircleProgress size="sm" sx={{ marginTop: 2 }} />
) : isErrorKubernetesACL ? (
) : failedMigrationStatus() ? (
<NotMigratedCopy />
) : enabledACL ? (
<EnabledCopy />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Typography } from 'src/components/Typography';
import {
useKubernetesControlPlaneACLMutation,
useKubernetesControlPlaneACLQuery,
useKubernetesClusterMutation,
} from 'src/queries/kubernetes';
import { MultipleIPInput } from 'src/components/MultipleIPInput/MultipleIPInput';
import {
Expand All @@ -25,15 +26,19 @@ interface Props {
closeDrawer: () => void;
clusterId: number;
clusterLabel: string;
clusterMigrated: boolean;
open: boolean;
}

export const KubeControlPlaneACLDrawer = (props: Props) => {
const { closeDrawer, clusterId, clusterLabel, open } = props;
const { closeDrawer, clusterId, clusterLabel, clusterMigrated, open } = props;

const [ipV4InputError, setIPV4InputError] = React.useState<
string | undefined
>('');
const [ipV6InputError, setIPV6InputError] = React.useState<
string | undefined
>('');
const [updateError, setUpdateACLError] = React.useState<string>();
const [updating, setUpdating] = React.useState<boolean>(false);

Expand Down Expand Up @@ -69,11 +74,17 @@ export const KubeControlPlaneACLDrawer = (props: Props) => {
React.useEffect(() => {
if (open && !isLoadingKubernetesACL && !isFetchingKubernetesACL) {
// updates states based on queried data
setIPv4Addr(_ipv4 ? _ipv4 : []);
setIPv6Addr(_ipv6 ? _ipv6 : []);
setIPv4Addr(
_ipv4 ? _ipv4 : clusterMigrated ? [] : [stringToExtendedIP('0.0.0.0/0')]
);
setIPv6Addr(
_ipv6 ? _ipv6 : clusterMigrated ? [] : [stringToExtendedIP('::/0')]
);
setControlPlaneACL(_enabled ? _enabled : false);
setRevisionID(_revisionID ? _revisionID : '');
setUpdateACLError(isErrorKubernetesACL?.[0].reason);
setIPV4InputError(undefined);
setIPV6InputError(undefined);
setUpdating(false);
refetchKubernetesACL();
}
Expand All @@ -83,6 +94,10 @@ export const KubeControlPlaneACLDrawer = (props: Props) => {
mutateAsync: updateKubernetesClusterControlPlaneACL,
} = useKubernetesControlPlaneACLMutation(clusterId);

const { mutateAsync: updateKubernetesCluster } = useKubernetesClusterMutation(
clusterId
);

const updateCluster = () => {
setUpdateACLError(undefined);
setUpdating(true);
Expand All @@ -97,27 +112,41 @@ export const KubeControlPlaneACLDrawer = (props: Props) => {

const payload: KubernetesControlPlaneACLPayload = {
acl: {
enabled: controlPlaneACL,
enabled: clusterMigrated ? controlPlaneACL : true, // new cluster installations default to true
'revision-id': revisionID,
addresses: { ipv4: _newIPv4, ipv6: _newIPv6 },
},
};

updateKubernetesClusterControlPlaneACL(payload)
.then(() => {
closeDrawer();
setUpdating(false);
if (clusterMigrated) {
updateKubernetesClusterControlPlaneACL(payload)
.then(() => {
closeDrawer();
setUpdating(false);
})
.catch((err) => {
const regex = /(?<=\bControl\b: ).*/;
setUpdateACLError(err[0].reason.match(regex));
setUpdating(false);
});
} else {
updateKubernetesCluster({
control_plane: payload,
})
.catch((err) => {
const regex = /(?<=\bControl\b: ).*/;
setUpdateACLError(err[0].reason.match(regex));
});

setUpdating(false);
.then((_) => {
closeDrawer();
setUpdating(false);
})
.catch((err) => {
const regex = /(?<=\bControl\b: ).*/;
setUpdateACLError(err[0].reason.match(regex));
setUpdating(false);
});
}
};

const ErrorMessage = () => {
if (!!updateError) {
if (!!updateError && clusterMigrated) {
return (
<Notice spacingTop={8} variant="error">
{updateError}
Expand All @@ -127,6 +156,22 @@ export const KubeControlPlaneACLDrawer = (props: Props) => {
return <></>;
};

const ClusterNeedsMigration = () => {
if (!clusterMigrated) {
return (
<>
<Notice spacingTop={8} variant="error">
IPACL is not yet installed on this cluster.... may take up to 10
minutes before..
</Notice>
<Divider sx={{ marginTop: 1 }} />
</>
);
} else {
return <></>;
}
};

const EnabledCopy = () => {
return (
<>
Expand All @@ -147,6 +192,25 @@ export const KubeControlPlaneACLDrawer = (props: Props) => {
);
};

const RevisionID = () => {
if (clusterMigrated) {
return (
<>
<RevisionIDCopy />
<TextField
data-qa-label-input
label="Revision ID"
value={revisionID}
onBlur={(e) => setRevisionID(e.target.value)}
/>
<Divider sx={{ marginTop: 4 }} />
</>
);
} else {
return <></>;
}
};

const RevisionIDCopy = () => {
return (
<>
Expand Down Expand Up @@ -182,6 +246,10 @@ export const KubeControlPlaneACLDrawer = (props: Props) => {
);
};

const SubmitButtonCopy = () => {
return clusterMigrated ? 'Update' : 'Install';
};

return (
<Drawer
onClose={closeDrawer}
Expand All @@ -190,7 +258,7 @@ export const KubeControlPlaneACLDrawer = (props: Props) => {
wide
>
<DrawerContent
error={!!isErrorKubernetesACL}
error={!!isErrorKubernetesACL && clusterMigrated} // when cluster has not migrated, we expect an error from the query
errorMessage={isErrorKubernetesACL?.[0].reason} // only on initial loading error do we disable the drawer altogether
loading={isLoadingKubernetesACL || isFetchingKubernetesACL}
title={clusterLabel}
Expand All @@ -210,27 +278,26 @@ export const KubeControlPlaneACLDrawer = (props: Props) => {
</Grid>
<Divider sx={{ marginTop: 4 }} />

<ClusterNeedsMigration />

<EnabledCopy />
<Checkbox
checked={controlPlaneACL}
checked={clusterMigrated ? controlPlaneACL : true}
name="ipacl-checkbox"
text={'IPACL Enabled'}
onChange={(e) => setControlPlaneACL(e.target.checked)}
onChange={(e) => {
if (clusterMigrated) {
return setControlPlaneACL(e.target.checked);
}
}}
/>
<Divider sx={{ marginTop: 4 }} />

<RevisionIDCopy />
<TextField
data-qa-label-input
label="Revision ID"
value={revisionID}
onBlur={(e) => setRevisionID(e.target.value)}
/>
<Divider sx={{ marginTop: 4 }} />
<RevisionID />

<AddressesCopy />
<MultipleIPInput
buttonText="Add IPv4 Address to ACL"
buttonText="Add IP Address"
ips={ipV4Addr}
onChange={(_ips: ExtendedIP[]) => {
const validatedIPs = validateIPs(_ips, {
Expand All @@ -245,17 +312,27 @@ export const KubeControlPlaneACLDrawer = (props: Props) => {
}
}}
placeholder="0.0.0.0/0"
title="" // Empty string so a title isn't displayed for each IP input
title="IPv4 Addresses or CIDR"
error={ipV4InputError}
/>
<MultipleIPInput
buttonText="Add IPv6 Address to ACL"
buttonText="Add IP Address"
ips={ipV6Addr}
onChange={(newIpV6Addr: ExtendedIP[]) => {
setIPv6Addr(newIpV6Addr);
onChange={(_ips: ExtendedIP[]) => {
const validatedIPs = validateIPs(_ips, {
allowEmptyAddress: false,
errorMessage: 'Must be a valid IPv6 address.',
});
const ipsWithErrors: ExtendedIP[] = validatedIPs.filter(
(thisIP) => setIPV6InputError(thisIP.error)
);
if (ipsWithErrors.length === 0) {
setIPv6Addr(validatedIPs);
}
}}
placeholder="::/0"
title="" // Empty string so a title isn't displayed for each IP input
title="IPv6 Addresses or CIDR"
error={ipV6InputError}
/>
<Divider sx={{ marginTop: 4 }} />

Expand All @@ -266,7 +343,7 @@ export const KubeControlPlaneACLDrawer = (props: Props) => {
onClick={updateCluster}
disabled={!!ipV4InputError}
>
Update
<SubmitButtonCopy />
</StyledButton>
<ErrorMessage />
</Stack>
Expand Down
Loading

0 comments on commit c2a2ecd

Please sign in to comment.