1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-05 05:45:22 +02:00

refactor(azure): migrate module to react [EE-2782] (#6689)

* refactor(azure): migrate module to react [EE-2782]

* fix(azure): remove optional chain

* feat(azure): apply new icons in dashboard

* feat(azure): apply new icons in dashboard

* feat(ui): allow single string for breadcrumbs

* refactor(azure/containers): use Table.content

* feat(azure/containers): implement new ui [EE-3538]

* fix(azure/containers): use correct icon

* chore(tests): mock svg as component

* fix(azure): fix tests

Co-authored-by: matias.spinarolli <matias.spinarolli@portainer.io>
This commit is contained in:
Chaim Lev-Ari 2022-07-26 21:44:08 +02:00 committed by GitHub
parent b059641c80
commit 82b848af0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
97 changed files with 1723 additions and 1430 deletions

View file

@ -0,0 +1,47 @@
import { EnvironmentId } from '@/portainer/environments/types';
export const queryKeys = {
subscriptions: (environmentId: EnvironmentId) =>
['azure', environmentId, 'subscriptions'] as const,
subscription: (environmentId: EnvironmentId, subscriptionId: string) =>
[...queryKeys.subscriptions(environmentId), subscriptionId] as const,
resourceGroups: (environmentId: EnvironmentId, subscriptionId: string) =>
[
...queryKeys.subscription(environmentId, subscriptionId),
'resourceGroups',
] as const,
resourceGroup: (
environmentId: EnvironmentId,
subscriptionId: string,
resourceGroupName: string
) =>
[
...queryKeys.resourceGroups(environmentId, subscriptionId),
resourceGroupName,
] as const,
provider: (environmentId: EnvironmentId, subscriptionId: string) =>
[
...queryKeys.subscription(environmentId, subscriptionId),
'provider',
] as const,
containerGroups: (environmentId: EnvironmentId, subscriptionId: string) =>
[
...queryKeys.subscription(environmentId, subscriptionId),
'containerGroups',
] as const,
containerGroup: (
environmentId: EnvironmentId,
subscriptionId: string,
resourceGroupName: string,
containerGroupName: string
) =>
[
...queryKeys.resourceGroup(
environmentId,
subscriptionId,
resourceGroupName
),
'containerGroups',
containerGroupName,
] as const,
};

View file

@ -0,0 +1,59 @@
import { useQuery } from 'react-query';
import { EnvironmentId } from '@/portainer/environments/types';
import { withError } from '@/react-tools/react-query';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { ContainerGroup } from '../types';
import { queryKeys } from './query-keys';
import { buildContainerGroupUrl } from './utils';
export function useContainerGroup(
environmentId: EnvironmentId,
subscriptionId: string,
resourceGroupName: string,
containerGroupName: string
) {
return useQuery(
queryKeys.containerGroup(
environmentId,
subscriptionId,
resourceGroupName,
containerGroupName
),
() =>
getContainerGroup(
environmentId,
subscriptionId,
resourceGroupName,
containerGroupName
),
{
...withError('Unable to retrieve Azure container group'),
}
);
}
async function getContainerGroup(
environmentId: EnvironmentId,
subscriptionId: string,
resourceGroupName: string,
containerGroupName: string
) {
try {
const { data } = await axios.get<ContainerGroup>(
buildContainerGroupUrl(
environmentId,
subscriptionId,
resourceGroupName,
containerGroupName
),
{ params: { 'api-version': '2018-04-01' } }
);
return data;
} catch (e) {
throw parseAxiosError(e as Error);
}
}

View file

@ -0,0 +1,59 @@
import _ from 'lodash';
import { useMemo } from 'react';
import { useQueries } from 'react-query';
import { withError } from '@/react-tools/react-query';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { EnvironmentId } from '@/portainer/environments/types';
import { Subscription, ContainerGroup } from '../types';
import { queryKeys } from './query-keys';
import { buildContainerGroupUrl } from './utils';
export function useContainerGroups(
environmentId: EnvironmentId,
subscriptions: Subscription[] = [],
enabled?: boolean
) {
const queries = useQueries(
useMemo(
() =>
subscriptions.map((subscription) => ({
queryKey: queryKeys.containerGroups(
environmentId,
subscription.subscriptionId
),
queryFn: async () =>
getContainerGroups(environmentId, subscription.subscriptionId),
...withError('Unable to retrieve Azure container groups'),
enabled,
})),
[subscriptions, enabled, environmentId]
)
);
return useMemo(
() => ({
containerGroups: _.flatMap(_.compact(queries.map((q) => q.data))),
isLoading: queries.some((q) => q.isLoading),
}),
[queries]
);
}
export async function getContainerGroups(
environmentId: EnvironmentId,
subscriptionId: string
) {
try {
const { data } = await axios.get<{ value: ContainerGroup[] }>(
buildContainerGroupUrl(environmentId, subscriptionId),
{ params: { 'api-version': '2018-04-01' } }
);
return data.value;
} catch (e) {
throw parseAxiosError(e as Error, 'Unable to retrieve container groups');
}
}

View file

@ -0,0 +1,87 @@
import _ from 'lodash';
import { useQueries } from 'react-query';
import { EnvironmentId } from '@/portainer/environments/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { withError } from '@/react-tools/react-query';
import { ProviderViewModel, Subscription } from '../types';
import { azureErrorParser } from '../services/utils';
import { queryKeys } from './query-keys';
export function useProvider(
environmentId: EnvironmentId,
subscriptions: Subscription[] = []
) {
const queries = useQueries(
subscriptions.map((subscription) => ({
queryKey: queryKeys.provider(environmentId, subscription.subscriptionId),
queryFn: async () => {
const provider = await getContainerInstanceProvider(
environmentId,
subscription.subscriptionId
);
return [subscription.subscriptionId, provider] as const;
},
...withError('Unable to retrieve Azure providers'),
}))
);
return {
providers: Object.fromEntries(
_.compact(
queries.map((q) => {
if (q.data) {
return q.data;
}
return null;
})
)
),
isLoading: queries.some((q) => q.isLoading),
};
}
interface ResourceType {
resourceType: 'containerGroups' | string;
locations: string[];
}
interface ProviderResponse {
id: string;
namespace: string;
resourceTypes: ResourceType[];
}
async function getContainerInstanceProvider(
environmentId: EnvironmentId,
subscriptionId: string
) {
try {
const url = `/endpoints/${environmentId}/azure/subscriptions/${subscriptionId}/providers/Microsoft.ContainerInstance`;
const { data } = await axios.get<ProviderResponse>(url, {
params: { 'api-version': '2018-02-01' },
});
return parseViewModel(data);
} catch (error) {
throw parseAxiosError(
error as Error,
'Unable to retrieve provider',
azureErrorParser
);
}
}
function parseViewModel({
id,
namespace,
resourceTypes,
}: ProviderResponse): ProviderViewModel {
const containerGroupType = _.find(resourceTypes, {
resourceType: 'containerGroups',
});
const { locations = [] } = containerGroupType || {};
return { id, namespace, locations };
}

View file

@ -0,0 +1,46 @@
import { useQuery } from 'react-query';
import { EnvironmentId } from '@/portainer/environments/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { withError } from '@/react-tools/react-query';
import { azureErrorParser } from '../services/utils';
import { ResourceGroup } from '../types';
import { queryKeys } from './query-keys';
import { buildResourceGroupUrl } from './utils';
export function useResourceGroup(
environmentId: EnvironmentId,
subscriptionId: string,
resourceGroupName: string
) {
return useQuery(
queryKeys.resourceGroup(environmentId, subscriptionId, resourceGroupName),
() => getResourceGroup(environmentId, subscriptionId, resourceGroupName),
{
...withError('Unable to retrieve Azure resource group'),
}
);
}
export async function getResourceGroup(
environmentId: EnvironmentId,
subscriptionId: string,
resourceGroupName: string
) {
try {
const { data } = await axios.get<ResourceGroup>(
buildResourceGroupUrl(environmentId, subscriptionId, resourceGroupName),
{ params: { 'api-version': '2018-02-01' } }
);
return data;
} catch (err) {
throw parseAxiosError(
err as Error,
'Unable to retrieve resource group',
azureErrorParser
);
}
}

View file

@ -0,0 +1,72 @@
import _ from 'lodash';
import { useQueries } from 'react-query';
import { EnvironmentId } from '@/portainer/environments/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { withError } from '@/react-tools/react-query';
import { azureErrorParser } from '../services/utils';
import { Subscription, ResourceGroup } from '../types';
import { queryKeys } from './query-keys';
import { buildResourceGroupUrl } from './utils';
export function useResourceGroups(
environmentId: EnvironmentId,
subscriptions: Subscription[] = []
) {
const queries = useQueries(
subscriptions.map((subscription) => ({
queryKey: queryKeys.resourceGroups(
environmentId,
subscription.subscriptionId
),
queryFn: async () => {
const groups = await getResourceGroups(
environmentId,
subscription.subscriptionId
);
return [subscription.subscriptionId, groups] as const;
},
...withError('Unable to retrieve Azure resource groups'),
}))
);
return {
resourceGroups: Object.fromEntries(
_.compact(
queries.map((q) => {
if (q.data) {
return q.data;
}
return null;
})
)
),
isLoading: queries.some((q) => q.isLoading),
isError: queries.some((q) => q.isError),
};
}
async function getResourceGroups(
environmentId: EnvironmentId,
subscriptionId: string
) {
try {
const {
data: { value },
} = await axios.get<{ value: ResourceGroup[] }>(
buildResourceGroupUrl(environmentId, subscriptionId),
{ params: { 'api-version': '2018-02-01' } }
);
return value;
} catch (err) {
throw parseAxiosError(
err as Error,
'Unable to retrieve resource groups',
azureErrorParser
);
}
}

View file

@ -0,0 +1,44 @@
import { useQuery } from 'react-query';
import { EnvironmentId } from '@/portainer/environments/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { withError } from '@/react-tools/react-query';
import { Subscription } from '../types';
import { azureErrorParser } from '../services/utils';
import { queryKeys } from './query-keys';
import { buildSubscriptionsUrl } from './utils';
export function useSubscription(
environmentId: EnvironmentId,
subscriptionId: string
) {
return useQuery(
queryKeys.subscription(environmentId, subscriptionId),
() => getSubscription(environmentId, subscriptionId),
{
...withError('Unable to retrieve Azure subscription'),
}
);
}
async function getSubscription(
environmentId: EnvironmentId,
subscriptionId: string
) {
try {
const { data } = await axios.get<Subscription>(
buildSubscriptionsUrl(environmentId, subscriptionId),
{ params: { 'api-version': '2016-06-01' } }
);
return data;
} catch (e) {
throw parseAxiosError(
e as Error,
'Unable to retrieve subscription',
azureErrorParser
);
}
}

View file

@ -0,0 +1,37 @@
import { useQuery } from 'react-query';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { EnvironmentId } from '@/portainer/environments/types';
import { withError } from '@/react-tools/react-query';
import { azureErrorParser } from '../services/utils';
import { Subscription } from '../types';
import { queryKeys } from './query-keys';
import { buildSubscriptionsUrl } from './utils';
export function useSubscriptions(environmentId: EnvironmentId) {
return useQuery(
queryKeys.subscriptions(environmentId),
() => getSubscriptions(environmentId),
{
...withError('Unable to retrieve Azure subscriptions'),
}
);
}
async function getSubscriptions(environmentId: EnvironmentId) {
try {
const { data } = await axios.get<{ value: Subscription[] }>(
buildSubscriptionsUrl(environmentId),
{ params: { 'api-version': '2016-06-01' } }
);
return data.value;
} catch (e) {
throw parseAxiosError(
e as Error,
'Unable to retrieve subscriptions',
azureErrorParser
);
}
}

View file

@ -0,0 +1,51 @@
import { EnvironmentId } from '@/portainer/environments/types';
export function buildSubscriptionsUrl(
environmentId: EnvironmentId,
id?: string
) {
let url = `/endpoints/${environmentId}/azure/subscriptions`;
if (id) {
url += `/${id}`;
}
return url;
}
export function buildResourceGroupUrl(
environmentId: EnvironmentId,
subscriptionId: string,
resourceGroupName?: string
) {
let url = `${buildSubscriptionsUrl(
environmentId,
subscriptionId
)}/resourcegroups`;
if (resourceGroupName) {
url += `/${resourceGroupName}`;
}
return url;
}
export function buildContainerGroupUrl(
environmentId: EnvironmentId,
subscriptionId: string,
resourceGroupName?: string,
containerGroupName?: string
) {
let url = buildSubscriptionsUrl(environmentId, subscriptionId);
if (resourceGroupName) {
url += `/resourceGroups/${resourceGroupName}`;
}
url += `/providers/Microsoft.ContainerInstance/containerGroups`;
if (containerGroupName) {
url += `/${containerGroupName}`;
}
return url;
}