Skip to content

Commit

Permalink
refactor(pci-block-storage): use volume catalog
Browse files Browse the repository at this point in the history
Signed-off-by: Simon Chaumet <[email protected]>
  • Loading branch information
SimonChaumet committed Jan 16, 2025
1 parent 5be5c2a commit 209036b
Show file tree
Hide file tree
Showing 34 changed files with 608 additions and 613 deletions.
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/manager/apps/pci-block-storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"dependencies": {
"@ovh-ux/manager-config": "^8.0.2",
"@ovh-ux/manager-core-api": "^0.9.0",
"@ovh-ux/manager-pci-common": "file:./ovh-ux-manager-pci-common-v0.15.0-3az.tgz",
"@ovh-ux/manager-pci-common": "^0.15.0",
"@ovh-ux/manager-react-components": "^1.43.0",
"@ovh-ux/manager-react-core-application": "^0.11.5",
"@ovh-ux/manager-react-shell-client": "^0.8.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@
"pci_projects_project_storages_blocks_add_success_message": "Le volume {{volume}} a été ajouté",
"pci_projects_project_storages_blocks_add_error_post": "Une erreur est survenue lors de l'ajout du volume {{ volume }} : {{ message }}",
"pci_projects_project_storages_blocks_add_deployment_mode_title": "Sélectionnez un mode de déploiement",
"pci_projects_project_storages_blocks_add_deployment_mode_description": "Sélectionnez la configuration optimale pour garantir la disponibilité, la résilience et la latence appropriée de vos données en fonction de vos cas d'usage. <Link>En savoir plus</Link>",
"pci_projects_project_storages_blocks_add_deployment_mode_title_1AZ": "Région 1-AZ",
"pci_projects_project_storages_blocks_add_deployment_mode_description_1AZ": "Déploiement résilient et économique sur 1 zone de disponibilité.",
"pci_projects_project_storages_blocks_add_deployment_mode_title_3AZ": "Région 3-AZ",
"pci_projects_project_storages_blocks_add_deployment_mode_description_3AZ": "Déploiement haute résilience/haute disponibilité pour vos applications critiques sur 3 zones de disponibilité.",
"pci_projects_project_storages_blocks_add_deployment_mode_title_LZ": "Local Zone",
"pci_projects_project_storages_blocks_add_deployment_mode_description_LZ": "Déploiement de vos applications au plus près de vos utilisatrices et utilisateurs pour une faible latence et la résidence des données.",
"pci_projects_project_storages_blocks_add_deployment_mode_price_from": "A partir de {{price}} HT/Go/heure"
"pci_projects_project_storages_blocks_add_deployment_mode_description": "Sélectionnez une configuration optimale pour assurer la disponibilité, la résilience et la latence appropriées pour vos données selon vos cas d’usage. <Link>En savoir plus</Link>",
"pci_projects_project_storages_blocks_add_deployment_mode_title_region": "Région 1-AZ",
"pci_projects_project_storages_blocks_add_deployment_mode_description_region": "Déploiement résilient et économique sur 1 zone de disponibilité.",
"pci_projects_project_storages_blocks_add_deployment_mode_title_region-3-az": "Région 3-AZ",
"pci_projects_project_storages_blocks_add_deployment_mode_description_region-3-az": "Déploiement haute résilience/haute disponibilité pour vos applications critiques sur 3 zones de disponibilité.",
"pci_projects_project_storages_blocks_add_deployment_mode_title_localzone": "Local Zone",
"pci_projects_project_storages_blocks_add_deployment_mode_description_localzone": "Déploiement de vos applications au plus près de vos utilisatrices et utilisateurs pour une faible latence et la résidence des données.",
"pci_projects_project_storages_blocks_add_deployment_mode_price_from": "A partir de {{price}} HT/Go/heure",
"pci_projects_project_storages_blocks_add_beta_free": "Gratuit"
}

This file was deleted.

126 changes: 34 additions & 92 deletions packages/manager/apps/pci-block-storage/src/api/data/catalog.ts
Original file line number Diff line number Diff line change
@@ -1,75 +1,36 @@
import { TAddon } from '@ovh-ux/manager-pci-common';
import { v6 } from '@ovh-ux/manager-core-api';
import { TRegion } from '@/api/data/regions';

export type TPricing = {
capacities: string[];
mode: string;
phase: number;
commitment: number;
description: string;
price: {
currencyCode: string;
text: string;
value: number;
};
tax: number;
interval: number;
intervalUnit: string;
quantity: {
max?: number;
min?: number;
};
repeat: {
max?: number;
min?: number;
};
strategy: string;
mustBeCompleted: boolean;
type: string;
promotions: unknown[];
engagementConfiguration?: unknown;
};

export type TRegionGroup = {
export type TCatalogGroup = {
name: string;
tags: string[];
};

export type TModelGroup = {
name: string;
type: string;
tags: string[];
export type TVolumePricing = Pick<TAddon['pricings'][number], 'price'> & {
regions: TRegion['name'][];
showAvailabilityZones: boolean;
interval: 'day' | 'hour' | 'month' | 'none';
specs: TAddon['blobs']['technical'];
};

export type TRegion = {
name: string;
type: '3-az' | 'region' | 'localzone';
availabilityZone: string[];
isInMaintenance: boolean;
isUp: boolean;
isActivated: boolean;
country: string;
regionGroup: string;
datacenter: string;
export type TVolumeCatalogFilter = {
[key in 'deployment' | 'region']: TCatalogGroup[];
};

export type TVolumePricing = Omit<
TAddon['pricings'][number],
'interval' | 'intervalUnit'
> & {
regions: TRegion['name'][];
interval: 'day' | 'hour' | 'month' | 'none';
export type TVolumeCatalogElementFilter = {
[Property in keyof TVolumeCatalogFilter]?: TVolumeCatalogFilter[Property][number]['name'][];
};

export type TVolumeAddon = Omit<TAddon, 'pricings'> & {
groups: TRegionGroup['name'][];
export type TVolumeAddon = {
name: string;
tags: string[];
filters: TVolumeCatalogElementFilter;
pricings: TVolumePricing[];
pricingType: 'consumption' | string;
};

export type TVolumeCatalog = {
modelsGroups: TModelGroup[];
regionsGroups: TRegionGroup[];
filters: TVolumeCatalogFilter;
regions: TRegion[];
models: TVolumeAddon[];
};
Expand All @@ -88,45 +49,26 @@ export function getLeastPrice(pricings: TVolumePricing[]) {
);
}

function isConsumptionAddon(
addon: TVolumeAddon,
): addon is TVolumeAddon & { pricingType: 'consumption' } {
return addon.pricingType === 'consumption';
}

function isConsumptionPricing(p: TVolumePricing) {
return p.capacities.includes('consumption');
}

export function mapPricesToGroups(
groups: TRegionGroup[],
export function getGroupLeastPrice(
group: TCatalogGroup,
regions: TRegion[],
models: TVolumeAddon[],
): (TRegionGroup & { leastPrice: number })[] {
return groups.map((group) => {
const groupRegions = regions
.filter((r) => r.type === group.name)
.map((r) => r.name);
): number | null {
const groupRegions = regions
.filter((r) => r.type === group.name)
.map((r) => r.name);

const hasGroupRegions = (p: TVolumePricing) =>
p.regions.some((r) => groupRegions.includes(r));
const hasGroupRegions = (p: TVolumePricing) =>
p.regions.some((r) => groupRegions.includes(r));

return {
...group,
leastPrice: models
.filter(isConsumptionAddon)
.map((m) =>
getLeastPrice(
m.pricings.filter(isConsumptionPricing).filter(hasGroupRegions),
),
)
.reduce<number | null>(
(leastPrice, modelLeastPrice) =>
leastPrice === null
? modelLeastPrice
: Math.min(modelLeastPrice, leastPrice),
null,
),
};
});
return models
.map((m) => getLeastPrice(m.pricings.filter(hasGroupRegions)))
.filter((p) => p !== null)
.reduce<number | null>(
(leastPrice, modelLeastPrice) =>
leastPrice === null
? modelLeastPrice
: Math.min(modelLeastPrice, leastPrice),
null,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface Instance {
planCode: string;
operationIds: string[];
currentMonthOutgoingTraffic: number;
availabilityZone?: string;
}

export interface MonthlyBilling {
Expand Down
29 changes: 11 additions & 18 deletions packages/manager/apps/pci-block-storage/src/api/data/regions.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import { fetchIcebergV6 } from '@ovh-ux/manager-core-api';
import { TVolumeCatalogElementFilter } from '@/api/data/catalog';

export type TRegion = {
name: string;
type: string;
status: string;
continentCode: string;
services: {
name: string;
status: string;
endpoint: string;
}[];
datacenterLocation: string;
type: 'region-3-az' | 'region' | 'localzone';
availabilityZones: string[];
isInMaintenance: boolean;
isActivated: boolean;
country: string;
filters: TVolumeCatalogElementFilter;
datacenter: string;
};

export const getProjectRegions = async (
projectId: string,
): Promise<TRegion[]> => {
const { data } = await fetchIcebergV6<TRegion>({
route: `/cloud/project/${projectId}/region`,
});
return data;
};
export function isRegionWith3AZ(region: Pick<TRegion, 'type'>) {
return region.type === 'region-3-az';
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type TVolume = {
planCode: string;
type: string;
regionName: string;
availabilityZone?: string;
};

export type VolumeOptions = {
Expand Down Expand Up @@ -185,7 +186,7 @@ export interface AddVolumeProps {
regionName: string;
volumeCapacity: number;
volumeType: string;
availabilityZone?: string;
availabilityZone: string | null;
}

export const addVolume = async ({
Expand All @@ -194,13 +195,15 @@ export const addVolume = async ({
regionName,
volumeCapacity,
volumeType,
availabilityZone,
}: AddVolumeProps): Promise<void> => {
const { data } = await v6.post<void>(
`/cloud/project/${projectId}/region/${regionName}/volume`,
{
name,
size: volumeCapacity,
type: volumeType,
availabilityZone,
},
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useVolumeCatalog } from '@/api/hooks/useCatalog';

export const useHas3AZRegion = (projectId: string) => {
const { data: volumeCatalog, isPending } = useVolumeCatalog(projectId);

return {
has3AZ:
volumeCatalog?.models.some((m) =>
m.filters.deployment.includes('region-3-az'),
) || false,
isPending,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ export const getInstanceQueryKey = (projectId: string, instanceId: string) => [
export const useInstance = (projectId: string, instanceId: string) =>
useQuery({
queryKey: getInstanceQueryKey(projectId, instanceId),
queryFn: (): Promise<Required<Instance>> =>
getInstance(projectId, instanceId),
queryFn: (): Promise<Instance> => getInstance(projectId, instanceId),
enabled: !!instanceId,
});

Expand All @@ -25,7 +24,7 @@ export const getInstancesQueryKey = (projectId: string, region: string) => [
export const useInstances = (projectId: string, region: string) =>
useQuery({
queryKey: getInstancesQueryKey(projectId, region),
queryFn: (): Promise<Required<Instance>[]> =>
getInstancesByRegion(projectId, region) as Promise<Required<Instance>[]>,
queryFn: (): Promise<Instance[]> =>
getInstancesByRegion(projectId, region) as Promise<Instance[]>,
enabled: !!region,
});

This file was deleted.

Loading

0 comments on commit 209036b

Please sign in to comment.