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

feat(helm): add registry dropdown [r8s-340] (#779)

This commit is contained in:
Ali 2025-06-09 20:08:50 +12:00 committed by GitHub
parent c9e3717ce3
commit 1963edda66
16 changed files with 288 additions and 190 deletions

View file

@ -1,66 +1,11 @@
import { useQuery, useQueries } from '@tanstack/react-query';
import { useQueries } from '@tanstack/react-query';
import { compact, flatMap } from 'lodash';
import { useMemo } from 'react';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import axios from '@/portainer/services/axios';
import { withGlobalError } from '@/react-tools/react-query';
import { UserId } from '@/portainer/users/types';
import { Chart, HelmChartsResponse, HelmRepositoriesResponse } from '../types';
/**
* Get Helm repositories for user
*/
export async function getHelmRepositories(userId: UserId) {
try {
const { data } = await axios.get<HelmRepositoriesResponse>(
`users/${userId}/helm/repositories`
);
const repos = compact([
// compact will remove the global repository if it's empty
data.GlobalRepository.toLowerCase(),
...data.UserRepositories.map((repo) => repo.URL.toLowerCase()),
]);
return [...new Set(repos)];
} catch (err) {
throw parseAxiosError(err, 'Unable to retrieve helm repositories for user');
}
}
async function getChartsFromRepo(repo: string): Promise<Chart[]> {
try {
// Construct the URL with required repo parameter
const response = await axios.get<HelmChartsResponse>('templates/helm', {
params: { repo },
});
return compact(
Object.values(response.data.entries).map((versions) =>
versions[0] ? { ...versions[0], repo } : null
)
);
} catch (error) {
// Ignore errors from chart repositories as some may error but others may not
return [];
}
}
/**
* Hook to fetch all accessible Helm repositories for a user
*
* @param userId User ID
* @returns Query result with list of repository URLs
*/
export function useHelmRepositories(userId: number) {
return useQuery(
[userId, 'helm-repositories'],
() => getHelmRepositories(userId),
{
enabled: !!userId,
...withGlobalError('Unable to retrieve Helm repositories'),
}
);
}
import { Chart, HelmChartsResponse } from '../types';
/**
* React hook to fetch helm charts from the provided repositories
@ -103,3 +48,28 @@ export function useHelmChartList(userId: number, repositories: string[] = []) {
isError: chartQueries.some((q) => q.isError),
};
}
async function getChartsFromRepo(repo: string): Promise<Chart[]> {
try {
// Construct the URL with required repo parameter
const response = await axios.get<HelmChartsResponse>('templates/helm', {
params: { repo },
});
return compact(
Object.values(response.data.entries).map((versions) =>
versions[0]
? {
...versions[0],
repo,
// versions are within this response too, so we don't need a new query to fetch versions when this is used
versions: versions.map((v) => v.version),
}
: null
)
);
} catch (error) {
// Ignore errors from chart repositories as some may error but others may not
return [];
}
}

View file

@ -0,0 +1,43 @@
import { useQuery } from '@tanstack/react-query';
import { compact } from 'lodash';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { UserId } from '@/portainer/users/types';
import { withGlobalError } from '@/react-tools/react-query';
import { useCurrentUser } from '@/react/hooks/useUser';
import { HelmRegistriesResponse } from '../types';
/**
* Hook to fetch all Helm registries for the current user
*/
export function useHelmRegistries() {
const { user } = useCurrentUser();
return useQuery(
['helm', 'registries'],
async () => getHelmRegistries(user.Id),
{
enabled: !!user.Id,
...withGlobalError('Unable to retrieve helm registries'),
}
);
}
/**
* Get Helm registries for user
*/
async function getHelmRegistries(userId: UserId) {
try {
const { data } = await axios.get<HelmRegistriesResponse>(
`users/${userId}/helm/repositories`
);
const repos = compact([
// compact will remove the global repository if it's empty
data.GlobalRepository.toLowerCase(),
...data.UserRepositories.map((repo) => repo.URL.toLowerCase()),
]);
return [...new Set(repos)];
} catch (err) {
throw parseAxiosError(err, 'Unable to retrieve helm repositories for user');
}
}

View file

@ -1,12 +1,9 @@
import { useQuery, useQueries } from '@tanstack/react-query';
import { useQueries } from '@tanstack/react-query';
import { useMemo } from 'react';
import { compact, flatMap } from 'lodash';
import { withGlobalError } from '@/react-tools/react-query';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { useCurrentUser } from '@/react/hooks/useUser';
import { getHelmRepositories } from './useHelmChartList';
interface HelmSearch {
entries: Entries;
@ -21,26 +18,13 @@ export interface ChartVersion {
Version: string;
}
/**
* Hook to fetch all Helm repositories for the current user
*/
export function useHelmRepositories() {
const { user } = useCurrentUser();
return useQuery(
['helm', 'repositories'],
async () => getHelmRepositories(user.Id),
{
enabled: !!user.Id,
...withGlobalError('Unable to retrieve helm repositories'),
}
);
}
/**
* React hook to get a list of available versions for a chart from specified repositories
*
* @param chart The chart name to get versions for
* @param repositories Array of repository URLs to search in
* @param staleTime Stale time for the query
* @param useCache Whether to use the cache for the query
*/
export function useHelmRepoVersions(
chart: string,