Skip to content

Commit

Permalink
fix(pci-private-network): add vrack creation (#13627)
Browse files Browse the repository at this point in the history
ref: DTCORE-2764

Signed-off-by: Florian Renaut <[email protected]>
  • Loading branch information
frenautvh authored Oct 31, 2024
1 parent 2ab743b commit 84b8d2e
Show file tree
Hide file tree
Showing 31 changed files with 2,074 additions and 90 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"pci_projects_project_network_private_vrack_create_heading": "vRack erstellen",
"pci_projects_project_network_private_vrack_create_new": "Neues vRack",
"pci_projects_project_network_private_vrack_create_existing": "Vorhandenes vRack",
"pci_projects_project_network_private_vrack_create_description": "Klicken Sie auf „Erstellen“, um Ihr neues vRack zu aktivieren",
"pci_projects_project_network_private_vrack_create_choose": "Vorhandenes vRack auswählen",
"pci_projects_project_network_private_vrack_create_action": "Erstellen",
"pci_projects_project_network_private_vrack_create_cancel": "Abbrechen",
"pci_projects_project_network_private_vrack_create_init_error": "Beim Laden der Informationen ist ein Fehler aufgetreten: {{ message }}",
"pci_projects_project_network_private_vrack_create_error": "Bei der Aktivierung des vRack ist ein Fehler aufgetreten: {{message}}",
"pci_projects_project_network_private_vrack_pending": "vRack wird aktiviert. Dieser Vorgang kann einige Minuten dauern"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"pci_projects_project_network_private_vrack_create_heading": "Create a vRack",
"pci_projects_project_network_private_vrack_create_new": "New vRack",
"pci_projects_project_network_private_vrack_create_existing": "Existing vRack",
"pci_projects_project_network_private_vrack_create_description": "Click “Create” to enable your new vRack",
"pci_projects_project_network_private_vrack_create_choose": "Select an existing vRack",
"pci_projects_project_network_private_vrack_create_action": "Create",
"pci_projects_project_network_private_vrack_create_cancel": "Cancel",
"pci_projects_project_network_private_vrack_create_init_error": "An error has occurred loading the information {{ message }}",
"pci_projects_project_network_private_vrack_create_error": "An error has occurred enabling the vRack {{ message }}",
"pci_projects_project_network_private_vrack_pending": "Your vRack is being enabled. This operation may take several minutes."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"pci_projects_project_network_private_vrack_create_heading": "Crear un vRack",
"pci_projects_project_network_private_vrack_create_new": "Nuevo vRack",
"pci_projects_project_network_private_vrack_create_existing": "vRack existente",
"pci_projects_project_network_private_vrack_create_description": "Haga clic en «Crear» para activar el nuevo vRack",
"pci_projects_project_network_private_vrack_create_choose": "Seleccionar un vRack existente",
"pci_projects_project_network_private_vrack_create_action": "Crear",
"pci_projects_project_network_private_vrack_create_cancel": "Cancelar",
"pci_projects_project_network_private_vrack_create_init_error": "Se ha producido un error al cargar la información: {{ message }}.",
"pci_projects_project_network_private_vrack_create_error": "Se ha producido un error al activar el vRack: {{message}}.",
"pci_projects_project_network_private_vrack_pending": "Activando el vRack... Esta operación puede tardar unos minutos."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"pci_projects_project_network_private_vrack_create_heading": "Créez un vRack",
"pci_projects_project_network_private_vrack_create_new": "Nouveau vRack",
"pci_projects_project_network_private_vrack_create_existing": "vRack existant",
"pci_projects_project_network_private_vrack_create_description": "Cliquez sur \"Créer\" pour activer votre nouveau vRack",
"pci_projects_project_network_private_vrack_create_choose": "Choisir un vRack existant",
"pci_projects_project_network_private_vrack_create_action": "Créer",
"pci_projects_project_network_private_vrack_create_cancel": "Annuler",
"pci_projects_project_network_private_vrack_create_init_error": "Une erreur est survenue lors du chargement des informations {{ message }}",
"pci_projects_project_network_private_vrack_create_error": "Une erreur est survenue lors de l'activation du vRack {{ message }}",
"pci_projects_project_network_private_vrack_pending": "Votre vRack est en cours d'activation. L'opération peut prendre plusieurs minutes"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"pci_projects_project_network_private_vrack_create_heading": "Créez un vRack",
"pci_projects_project_network_private_vrack_create_new": "Nouveau vRack",
"pci_projects_project_network_private_vrack_create_existing": "vRack existant",
"pci_projects_project_network_private_vrack_create_description": "Cliquez sur \"Créer\" pour activer votre nouveau vRack",
"pci_projects_project_network_private_vrack_create_choose": "Choisir un vRack existant",
"pci_projects_project_network_private_vrack_create_action": "Créer",
"pci_projects_project_network_private_vrack_create_cancel": "Annuler",
"pci_projects_project_network_private_vrack_create_init_error": "Une erreur est survenue lors du chargement des informations {{ message }}",
"pci_projects_project_network_private_vrack_create_error": "Une erreur est survenue lors de l'activation du vRack {{ message }}",
"pci_projects_project_network_private_vrack_pending": "Votre vRack est en cours d'activation. L'opération peut prendre plusieurs minutes"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"pci_projects_project_network_private_vrack_create_heading": "Crea una vRack",
"pci_projects_project_network_private_vrack_create_new": "Nuova vRack",
"pci_projects_project_network_private_vrack_create_existing": "vRack esistente",
"pci_projects_project_network_private_vrack_create_description": "Per attivare la tua nuova vRack, clicca su “Crea”.",
"pci_projects_project_network_private_vrack_create_choose": "Seleziona una vRack esistente",
"pci_projects_project_network_private_vrack_create_action": "Crea",
"pci_projects_project_network_private_vrack_create_cancel": "Annulla",
"pci_projects_project_network_private_vrack_create_init_error": "Si è verificato un errore durante il caricamento delle informazioni: {{ message }}",
"pci_projects_project_network_private_vrack_create_error": "Si è verificato un errore durante l’attivazione della vRack: {{ message }}",
"pci_projects_project_network_private_vrack_pending": "La tua vRack è in corso di attivazione. L’operazione potrebbe richiedere qualche minuto."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"pci_projects_project_network_private_vrack_create_heading": "Utwórz vRack",
"pci_projects_project_network_private_vrack_create_new": "Nowy vRack",
"pci_projects_project_network_private_vrack_create_existing": "Istniejący vRack",
"pci_projects_project_network_private_vrack_create_description": "Kliknij „Utwórz”, aby aktywować Twój nowy vRack.",
"pci_projects_project_network_private_vrack_create_choose": "Wybierz istniejący vRack",
"pci_projects_project_network_private_vrack_create_action": "Utwórz",
"pci_projects_project_network_private_vrack_create_cancel": "Anuluj",
"pci_projects_project_network_private_vrack_create_init_error": "Wystąpił błąd podczas pobierania informacji {{ message }}.",
"pci_projects_project_network_private_vrack_create_error": "Wystąpił błąd podczas tworzenia sieci vRack: {{message}}.",
"pci_projects_project_network_private_vrack_pending": "Trwa tworzenie Twojej sieci vRack. Może to potrwać kilka minut."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"pci_projects_project_network_private_vrack_create_heading": "Criar um vRack",
"pci_projects_project_network_private_vrack_create_new": "Novo vRack",
"pci_projects_project_network_private_vrack_create_existing": "vRack existente",
"pci_projects_project_network_private_vrack_create_description": "Clique em “Criar” para ativar o seu novo vRack",
"pci_projects_project_network_private_vrack_create_choose": "Selecionar um vRack existente",
"pci_projects_project_network_private_vrack_create_action": "Criar",
"pci_projects_project_network_private_vrack_create_cancel": "Anular",
"pci_projects_project_network_private_vrack_create_init_error": "Ocorreu um erro ao carregar as informações {{ message }}",
"pci_projects_project_network_private_vrack_create_error": "Ocorreu um erro ao ativar o vRack {{ message }}",
"pci_projects_project_network_private_vrack_pending": "A ativação do seu vRack está em curso. A operação pode demorar alguns minutos"
}
12 changes: 0 additions & 12 deletions packages/manager/apps/pci-private-network/setupTests.ts

This file was deleted.

77 changes: 77 additions & 0 deletions packages/manager/apps/pci-private-network/src/api/data/vrack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { fetchIcebergV6, v6 } from '@ovh-ux/manager-core-api';

export enum VrackTaskStatus {
Cancelled = 'cancelled',
Doing = 'doing',
Done = 'done',
Init = 'init',
Todo = 'todo',
}

export type TVrackTask = {
function: string;
id: number;
lastUpdate: string | null;
orderId: number | null;
serviceName: string | null;
status: VrackTaskStatus;
targetDomain: string | null;
todoDate: string | null;
};

export type TVrack = {
name: string;
description: string;
iam?: {
id: string;
displayName: string;
tags: Record<string, string>;
urn: string;
};
};

export const getVrackTask = async (vrack: string, taskId: string) => {
try {
const { data } = await v6.get<TVrackTask>(`/vrack/${vrack}/task/${taskId}`);
return data;
} catch (err) {
if (err?.response?.status === 404) return null;
throw err;
}
};

export const getProjectVrack = async (projectId: string) => {
const { data } = await v6.get<{
id: string;
name: string;
}>(`/cloud/project/${projectId}/vrack`);
return data;
};

export const getVracks = async (): Promise<TVrack[]> => {
const { data } = await fetchIcebergV6<TVrack>({
route: `/vrack`,
disableCache: true,
});
return data;
};

export const createVrack = async (projectId: string) => {
const { data } = await v6.post<{ id: string }>(
`/cloud/project/${projectId}/vrack`,
);
return data;
};

export const associateVrack = async (
serviceName: string,
projectId: string,
) => {
const { data } = await v6.post<{ id: number }>(
`/vrack/${serviceName}/cloudProject`,
{
project: projectId,
},
);
return data;
};
129 changes: 129 additions & 0 deletions packages/manager/apps/pci-private-network/src/api/hooks/useVrack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { useEffect, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
associateVrack,
createVrack,
getProjectVrack,
getVracks,
getVrackTask,
TVrackTask,
VrackTaskStatus,
} from '@/api/data/vrack';

export const VRACK_QUERY_KEY = 'vrack';
export const PROJECT_VRACK_QUERY_KEY = 'project-vrack';

export const useProjectVrack = (projectId: string) =>
useQuery({
queryKey: [PROJECT_VRACK_QUERY_KEY],
queryFn: async () => getProjectVrack(projectId),
retry: false,
throwOnError: false,
});

export const useVracks = () =>
useQuery({
queryKey: [VRACK_QUERY_KEY],
queryFn: () => getVracks(),
select: (data) =>
data?.map((vrack) => {
const vrackId = (vrack.iam?.urn?.match(/vrack:(.*)$/) || [])[1];
return {
vrackId,
displayName: vrack.name || vrack.iam?.displayName || vrackId,
...vrack,
};
}),
});

export const useCreateVrack = ({
onError,
onSuccess,
}: {
onError: (cause: Error) => void;
onSuccess: (operationId: string) => void;
}) => {
const mutation = useMutation({
mutationFn: createVrack,
onError,
onSuccess: async ({ id }) => {
onSuccess(id);
},
});
return {
createVrack: (projectId: string) => mutation.mutate(projectId),
...mutation,
};
};

export const useAssociateVrack = ({
projectId,
vrackId,
onError,
onSuccess,
}: {
projectId: string;
vrackId: string;
onError: (cause: Error) => void;
onSuccess: () => void;
}) => {
const queryClient = useQueryClient();
const [taskId, setTaskId] = useState(null);
const [isPending, setIsPending] = useState(false);

const mutation = useMutation({
mutationFn: async () => {
setIsPending(true);
const { id } = await associateVrack(vrackId, projectId);
return id;
},
onError,
onSuccess: setTaskId,
});

// polling of task association
const { data: task, error } = useQuery<TVrackTask>({
queryKey: ['pci-vrack-task', vrackId, taskId],
queryFn: () => getVrackTask(vrackId, taskId),
enabled: (query) =>
!!projectId &&
!!taskId &&
![VrackTaskStatus.Cancelled, VrackTaskStatus.Done].includes(
query.state.data?.status,
),
refetchInterval: 3000,
retry: 5,
});

// report an error if failling task polling after retries
useEffect(() => {
if (error && isPending) {
setIsPending(false);
onError(error);
}
}, [error, isPending]);

// report after polling
useEffect(() => {
if (!isPending) return;
// if task is missing (404) it is assumed to be done
if (task === null || task?.status === VrackTaskStatus.Done) {
queryClient.invalidateQueries({
queryKey: [VRACK_QUERY_KEY],
});
queryClient.invalidateQueries({
queryKey: [PROJECT_VRACK_QUERY_KEY],
});
setIsPending(false);
onSuccess();
} else if (task?.status === VrackTaskStatus.Cancelled) {
setIsPending(false);
onError(new Error(task.status));
}
}, [task, isPending]);

return {
associateVrack: mutation.mutate,
isPending,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ import { act, fireEvent, render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import DeleteModal from './DeleteModal.component';

vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key) => key }),
}));

describe('DeleteModal', () => {
const mockOnClose = vi.fn();
const mockOnConfirm = vi.fn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { describe, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import DataGridNoResults from '@/components/global-regions/DatagridNoResults';

vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key: string) => key }),
}));

describe('DataGridNoResults', () => {
it('should render no results message', () => {
render(<DataGridNoResults />);
render(
<table>
<thead>
<DataGridNoResults />
</thead>
</table>,
);
expect(
screen.getByText('common_pagination_no_results'),
).toBeInTheDocument();
Expand Down
Loading

0 comments on commit 84b8d2e

Please sign in to comment.