Skip to content

Commit

Permalink
frontend: Add check for adding same name clusters
Browse files Browse the repository at this point in the history
Earlier user were able to submit clusters with same name to the backend,
due to which it was getting overwritten on the proxy. Even if the
cluster was shown in frontend the backend did not knew about the
duplicate cluster.

kubectl throws the error of adding duplicate context name. We are
adding feature for the same.

If now user try to add a context which has the same name as earlier
context the app with throw an error and ask them to change the context
name.

Fixes: #2236
Signed-off-by: Kautilya Tripathi <ktripathi@microsoft.com>
  • Loading branch information
knrt10 committed Sep 2, 2024
1 parent b8fb9ab commit c291058
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 10 deletions.
32 changes: 30 additions & 2 deletions frontend/src/components/cluster/KubeConfigLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useDropzone } from 'react-dropzone';
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { useClustersConf } from '../../lib/k8s';
import { setCluster } from '../../lib/k8s/apiProxy';
import { setStatelessConfig } from '../../redux/configSlice';
import { DialogTitle } from '../common/Dialog';
Expand Down Expand Up @@ -105,6 +106,7 @@ const WideButton = styled(Button)({
const enum Step {
LoadKubeConfig,
SelectClusters,
ValidateKubeConfig,
ConfigureClusters,
Success,
}
Expand All @@ -120,6 +122,7 @@ function KubeConfigLoader() {
currentContext: '',
});
const [selectedClusters, setSelectedClusters] = useState<string[]>([]);
const configuredClusters = useClustersConf(); // Get already configured clusters

useEffect(() => {
if (fileContent.contexts.length > 0) {
Expand All @@ -130,9 +133,27 @@ function KubeConfigLoader() {
}, [fileContent]);

useEffect(() => {
if (state === Step.ValidateKubeConfig) {
const alreadyConfiguredClusters = selectedClusters.filter(
clusterName => configuredClusters && configuredClusters[clusterName]
);

if (alreadyConfiguredClusters.length > 0) {
setError(
t(
'translation|Duplicate cluster: {{ clusterNames }} in the list. Please edit the context name.',
{
clusterNames: alreadyConfiguredClusters.join(', '),
}
)
);
setState(Step.SelectClusters);
} else {
setState(Step.ConfigureClusters);
}
}
if (state === Step.ConfigureClusters) {
function loadClusters() {
//@todo: We need to check if the cluster is already configured.
const selectedClusterConfig = configWithSelectedClusters(fileContent, selectedClusters);
setCluster({ kubeconfig: btoa(yaml.dump(selectedClusterConfig)) })
.then(res => {
Expand Down Expand Up @@ -295,7 +316,7 @@ function KubeConfigLoader() {
variant="contained"
color="primary"
onClick={() => {
setState(Step.ConfigureClusters);
setState(Step.ValidateKubeConfig);
}}
disabled={selectedClusters.length === 0}
>
Expand All @@ -318,6 +339,13 @@ function KubeConfigLoader() {
) : null}
</Box>
);
case Step.ValidateKubeConfig:
return (
<Box style={{ textAlign: 'center' }}>
<Typography>{t('translation|Validating selected clusters')}</Typography>
<Loader title={t('translation|Validating selected clusters')} />
</Box>
);
case Step.ConfigureClusters:
return (
<Box style={{ textAlign: 'center' }}>
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/i18n/locales/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
"Current//context:cluster": "Aktuell",
"Choose cluster": "Cluster auswählen",
"Add Cluster": "Cluster hinzufügen",
"Duplicate cluster: {{ clusterNames }} in the list. Please edit the context name.": "",
"Error setting up clusters, please load a valid kubeconfig file": "Fehler beim Einrichten der Cluster. Bitte laden Sie eine korrekte kubeconfig-Datei",
"Couldn't read kubeconfig file": "Konnte die kubeconfig-Datei nicht lesen",
"No clusters found!": "",
Expand All @@ -119,6 +120,7 @@
"Choose file": "Datei auswählen",
"Select clusters": "Cluster auswählen",
"Next": "Weiter",
"Validating selected clusters": "",
"Setting up clusters": "Einrichten der Cluster",
"Clusters successfully set up!": "Cluster erfolgreich eingerichtet!",
"Finish": "Beenden",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
"Current//context:cluster": "Current",
"Choose cluster": "Choose cluster",
"Add Cluster": "Add Cluster",
"Duplicate cluster: {{ clusterNames }} in the list. Please edit the context name.": "Duplicate cluster: {{ clusterNames }} in the list. Please edit the context name.",
"Error setting up clusters, please load a valid kubeconfig file": "Error setting up clusters, please load a valid kubeconfig file",
"Couldn't read kubeconfig file": "Couldn't read kubeconfig file",
"No clusters found!": "No clusters found!",
Expand All @@ -119,6 +120,7 @@
"Choose file": "Choose file",
"Select clusters": "Select clusters",
"Next": "Next",
"Validating selected clusters": "Validating selected clusters",
"Setting up clusters": "Setting up clusters",
"Clusters successfully set up!": "Clusters successfully set up!",
"Finish": "Finish",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/i18n/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
"Current//context:cluster": "Actuales",
"Choose cluster": "Elegir cluster",
"Add Cluster": "Añadir cluster",
"Duplicate cluster: {{ clusterNames }} in the list. Please edit the context name.": "",
"Error setting up clusters, please load a valid kubeconfig file": "Error al configurar los clusters, por favor cargue un archivo kubeconfig válido",
"Couldn't read kubeconfig file": "No se pudo leer el archivo kubeconfig",
"No clusters found!": "",
Expand All @@ -119,6 +120,7 @@
"Choose file": "Elija el archivo",
"Select clusters": "Seleccione los clusters",
"Next": "Siguiente",
"Validating selected clusters": "",
"Setting up clusters": "Configurando los clusters",
"Clusters successfully set up!": "¡Clusters configurados con éxito!",
"Finish": "Finalizar",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/i18n/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
"Current//context:cluster": "Actuel",
"Choose cluster": "Choisir un cluster",
"Add Cluster": "Ajouter un cluster",
"Duplicate cluster: {{ clusterNames }} in the list. Please edit the context name.": "",
"Error setting up clusters, please load a valid kubeconfig file": "Erreur lors de la configuration des clusters, veuillez charger un fichier kubeconfig valide",
"Couldn't read kubeconfig file": "Impossible de lire le fichier kubeconfig",
"No clusters found!": "",
Expand All @@ -119,6 +120,7 @@
"Choose file": "Choisir un fichier",
"Select clusters": "Sélectionner des clusters",
"Next": "Suivant",
"Validating selected clusters": "",
"Setting up clusters": "Configuration des clusters",
"Clusters successfully set up!": "Clusters configurés avec succès !",
"Finish": "Terminer",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/i18n/locales/pt/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
"Current//context:cluster": "Actual",
"Choose cluster": "Escolha o cluster",
"Add Cluster": "Adicionar Cluster",
"Duplicate cluster: {{ clusterNames }} in the list. Please edit the context name.": "",
"Error setting up clusters, please load a valid kubeconfig file": "Erro ao configurar clusters, por favor carregue um ficheiro kubeconfig válido",
"Couldn't read kubeconfig file": "Não foi possível ler o ficheiro kubeconfig",
"No clusters found!": "",
Expand All @@ -119,6 +120,7 @@
"Choose file": "Escolha o ficheiro",
"Select clusters": "Selecione os clusters",
"Next": "Seguinte",
"Validating selected clusters": "",
"Setting up clusters": "A configurar clusters",
"Clusters successfully set up!": "Clusters configurados com sucesso!",
"Finish": "Terminar",
Expand Down
18 changes: 10 additions & 8 deletions frontend/src/stateless/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ export function findKubeconfigByClusterName(clusterName: string): Promise<string
?.extension.customName === clusterName
);

const matchingKubeconfig = parsedKubeconfig.clusters.find(
cluster => cluster.name === clusterName
const matchingKubeconfig = parsedKubeconfig.contexts.find(
context => context.name === clusterName
);

if (matchingKubeconfig || matchingContext) {
Expand Down Expand Up @@ -437,9 +437,12 @@ export async function deleteClusterKubeconfig(clusterName: string): Promise<stri
const kubeconfig = kubeconfigObject.kubeconfig;

const parsedKubeconfig = jsyaml.load(atob(kubeconfig)) as KubeconfigObject;

const matchingKubeconfig = parsedKubeconfig.clusters.find(
cluster => cluster.name === clusterName
// Find the context with the matching cluster name or custom name in headlamp_info
const matchingKubeconfig = parsedKubeconfig.contexts.find(
context =>
context.name === clusterName ||
context.context.extensions?.find(extension => extension.name === 'headlamp_info')
?.extension.customName === clusterName
);

if (matchingKubeconfig) {
Expand Down Expand Up @@ -489,11 +492,10 @@ export function updateStatelessClusterKubeconfig(
const request = indexedDB.open('kubeconfigs', 1) as any;
// Parse the kubeconfig from base64
const parsedKubeconfig = jsyaml.load(atob(kubeconfig)) as KubeconfigObject;

// Find the context with the matching cluster name or custom name in headlamp_info
const matchingContext = parsedKubeconfig.contexts.find(
context =>
context.context.cluster === clusterName ||
context.name === clusterName ||
context.context.extensions?.find(extension => extension.name === 'headlamp_info')
?.extension.customName === clusterName
);
Expand All @@ -502,7 +504,7 @@ export function updateStatelessClusterKubeconfig(
const extensions = matchingContext.context.extensions || [];
const headlampExtension = extensions.find(extension => extension.name === 'headlamp_info');

if (matchingContext.context.cluster === clusterName) {
if (matchingContext.name === clusterName) {
// Push the new extension if the cluster name matches
extensions.push({
extension: {
Expand Down

0 comments on commit c291058

Please sign in to comment.