mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 15:59:41 +02:00
feat(oci): oci helm support [r8s-361] (#787)
This commit is contained in:
parent
b6a6ce9aaf
commit
2697d6c5d7
80 changed files with 4264 additions and 812 deletions
|
@ -39,11 +39,6 @@ export function ChartActions({
|
|||
release={release}
|
||||
updateRelease={updateRelease}
|
||||
/>
|
||||
<UninstallButton
|
||||
environmentId={environmentId}
|
||||
releaseName={releaseName}
|
||||
namespace={namespace}
|
||||
/>
|
||||
{showRollbackButton && (
|
||||
<RollbackButton
|
||||
latestRevision={latestRevision}
|
||||
|
@ -53,6 +48,11 @@ export function ChartActions({
|
|||
namespace={namespace}
|
||||
/>
|
||||
)}
|
||||
<UninstallButton
|
||||
environmentId={environmentId}
|
||||
releaseName={releaseName}
|
||||
namespace={namespace}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ vi.mock('@/portainer/services/notifications', () => ({
|
|||
notifySuccess: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../../queries/useHelmRegistries', () => ({
|
||||
useHelmRegistries: vi.fn(() => ({
|
||||
vi.mock('../../queries/useHelmRepositories', () => ({
|
||||
useUserHelmRepositories: vi.fn(() => ({
|
||||
data: ['repo1', 'repo2'],
|
||||
isInitialLoading: false,
|
||||
isError: false,
|
||||
|
@ -146,7 +146,7 @@ describe('UpgradeButton', () => {
|
|||
|
||||
renderButton();
|
||||
|
||||
expect(screen.getByText('No versions available')).toBeInTheDocument();
|
||||
expect(screen.getByText(/No versions available/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should open upgrade modal when clicked', async () => {
|
||||
|
|
|
@ -15,7 +15,7 @@ import { HelmRelease, UpdateHelmReleasePayload } from '../../types';
|
|||
import { useUpdateHelmReleaseMutation } from '../../queries/useUpdateHelmReleaseMutation';
|
||||
import { useHelmRepoVersions } from '../../queries/useHelmRepoVersions';
|
||||
import { useHelmRelease } from '../queries/useHelmRelease';
|
||||
import { useHelmRegistries } from '../../queries/useHelmRegistries';
|
||||
import { useUserHelmRepositories } from '../../queries/useHelmRepositories';
|
||||
|
||||
import { openUpgradeHelmModal } from './UpgradeHelmModal';
|
||||
|
||||
|
@ -36,19 +36,22 @@ export function UpgradeButton({
|
|||
const [useCache, setUseCache] = useState(true);
|
||||
const updateHelmReleaseMutation = useUpdateHelmReleaseMutation(environmentId);
|
||||
|
||||
const registriesQuery = useHelmRegistries();
|
||||
const userRepositoriesQuery = useUserHelmRepositories();
|
||||
const helmRepoVersionsQuery = useHelmRepoVersions(
|
||||
release?.chart.metadata?.name || '',
|
||||
60 * 60 * 1000, // 1 hour
|
||||
registriesQuery.data,
|
||||
userRepositoriesQuery.data?.map((repo) => ({
|
||||
repo,
|
||||
})),
|
||||
useCache
|
||||
);
|
||||
const versions = helmRepoVersionsQuery.data;
|
||||
|
||||
// Combined loading state
|
||||
const isLoading =
|
||||
registriesQuery.isInitialLoading || helmRepoVersionsQuery.isFetching; // use 'isFetching' for helmRepoVersionsQuery because we want to show when it's refetching
|
||||
const isError = registriesQuery.isError || helmRepoVersionsQuery.isError;
|
||||
userRepositoriesQuery.isInitialLoading || helmRepoVersionsQuery.isFetching; // use 'isFetching' for helmRepoVersionsQuery because we want to show when it's refetching
|
||||
const isError =
|
||||
userRepositoriesQuery.isError || helmRepoVersionsQuery.isError;
|
||||
const latestVersionQuery = useHelmRelease(
|
||||
environmentId,
|
||||
releaseName,
|
||||
|
@ -101,7 +104,7 @@ export function UpgradeButton({
|
|||
icon={ArrowUp}
|
||||
size="medium"
|
||||
>
|
||||
Upgrade
|
||||
Edit/Upgrade
|
||||
</LoadingButton>
|
||||
{isLoading && (
|
||||
<InlineLoader
|
||||
|
|
|
@ -137,6 +137,47 @@ const helmReleaseHistory = [
|
|||
},
|
||||
];
|
||||
|
||||
// Common MSW handlers for all tests
|
||||
function createCommonHandlers() {
|
||||
return [
|
||||
http.get('/api/users/undefined/helm/repositories', () =>
|
||||
HttpResponse.json({
|
||||
GlobalRepository: 'https://charts.helm.sh/stable',
|
||||
UserRepositories: [{ Id: '1', URL: 'https://charts.helm.sh/stable' }],
|
||||
})
|
||||
),
|
||||
http.get('/api/templates/helm', () =>
|
||||
HttpResponse.json({
|
||||
entries: {
|
||||
'test-chart': [{ version: '1.0.0' }],
|
||||
},
|
||||
})
|
||||
),
|
||||
http.get('/api/endpoints/3/kubernetes/helm/test-release/history', () =>
|
||||
HttpResponse.json(helmReleaseHistory)
|
||||
),
|
||||
http.get('/api/kubernetes/3/namespaces/default/events', () =>
|
||||
HttpResponse.json([])
|
||||
),
|
||||
http.get('/api/kubernetes/3/namespaces/default', () =>
|
||||
HttpResponse.json({
|
||||
Id: 'default',
|
||||
Name: 'default',
|
||||
Status: { phase: 'Active' },
|
||||
Annotations: {},
|
||||
CreationDate: '2021-01-01T00:00:00Z',
|
||||
NamespaceOwner: '',
|
||||
IsSystem: false,
|
||||
IsDefault: true,
|
||||
})
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
function setupMockHandlers(helmReleaseHandler: ReturnType<typeof http.get>) {
|
||||
server.use(helmReleaseHandler, ...createCommonHandlers());
|
||||
}
|
||||
|
||||
function renderComponent() {
|
||||
const user = new UserViewModel({ Username: 'user' });
|
||||
const Wrapped = withTestQueryProvider(
|
||||
|
@ -162,30 +203,9 @@ describe(
|
|||
it('should display helm release details for minimal release when data is loaded', async () => {
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
server.use(
|
||||
setupMockHandlers(
|
||||
http.get('/api/endpoints/3/kubernetes/helm/test-release', () =>
|
||||
HttpResponse.json(minimalHelmRelease)
|
||||
),
|
||||
http.get('/api/users/undefined/helm/repositories', () =>
|
||||
HttpResponse.json({
|
||||
GlobalRepository: 'https://charts.helm.sh/stable',
|
||||
UserRepositories: [
|
||||
{ Id: '1', URL: 'https://charts.helm.sh/stable' },
|
||||
],
|
||||
})
|
||||
),
|
||||
http.get('/api/templates/helm', () =>
|
||||
HttpResponse.json({
|
||||
entries: {
|
||||
'test-chart': [{ version: '1.0.0' }],
|
||||
},
|
||||
})
|
||||
),
|
||||
http.get('/api/endpoints/3/kubernetes/helm/test-release/history', () =>
|
||||
HttpResponse.json(helmReleaseHistory)
|
||||
),
|
||||
http.get('/api/kubernetes/3/namespaces/default/events', () =>
|
||||
HttpResponse.json([])
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -224,13 +244,9 @@ describe(
|
|||
|
||||
it('should display error message when API request fails', async () => {
|
||||
// Mock API failure
|
||||
server.use(
|
||||
setupMockHandlers(
|
||||
http.get('/api/endpoints/3/kubernetes/helm/test-release', () =>
|
||||
HttpResponse.error()
|
||||
),
|
||||
// Add mock for events endpoint
|
||||
http.get('/api/kubernetes/3/namespaces/default/events', () =>
|
||||
HttpResponse.json([])
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -253,15 +269,9 @@ describe(
|
|||
});
|
||||
|
||||
it('should display additional details when available in helm release', async () => {
|
||||
server.use(
|
||||
setupMockHandlers(
|
||||
http.get('/api/endpoints/3/kubernetes/helm/test-release', () =>
|
||||
HttpResponse.json(completeHelmRelease)
|
||||
),
|
||||
http.get('/api/endpoints/3/kubernetes/helm/test-release/history', () =>
|
||||
HttpResponse.json(helmReleaseHistory)
|
||||
),
|
||||
http.get('/api/kubernetes/3/namespaces/default/events', () =>
|
||||
HttpResponse.json([])
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import { Card } from '@@/Card';
|
|||
import { Alert } from '@@/Alert';
|
||||
|
||||
import { HelmRelease } from '../types';
|
||||
import { useIsSystemNamespace } from '../../namespaces/queries/useIsSystemNamespace';
|
||||
|
||||
import { HelmSummary } from './HelmSummary';
|
||||
import { ReleaseTabs } from './ReleaseDetails/ReleaseTabs';
|
||||
|
@ -37,6 +38,8 @@ export function HelmApplicationView() {
|
|||
revision: selectedRevision,
|
||||
});
|
||||
|
||||
const isSystemNamespace = useIsSystemNamespace(namespace);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader
|
||||
|
@ -63,28 +66,30 @@ export function HelmApplicationView() {
|
|||
/>
|
||||
</div>
|
||||
<Authorized authorizations="K8sApplicationsW">
|
||||
<ChartActions
|
||||
environmentId={environmentId}
|
||||
releaseName={String(name)}
|
||||
namespace={String(namespace)}
|
||||
latestRevision={latestRevision ?? 1}
|
||||
earlistRevision={earlistRevision}
|
||||
selectedRevision={selectedRevision}
|
||||
release={helmReleaseQuery.data}
|
||||
updateRelease={(updatedRelease: HelmRelease) => {
|
||||
queryClient.setQueryData(
|
||||
[
|
||||
environmentId,
|
||||
'helm',
|
||||
'releases',
|
||||
namespace,
|
||||
name,
|
||||
true,
|
||||
],
|
||||
updatedRelease
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{!isSystemNamespace && (
|
||||
<ChartActions
|
||||
environmentId={environmentId}
|
||||
releaseName={String(name)}
|
||||
namespace={String(namespace)}
|
||||
latestRevision={latestRevision ?? 1}
|
||||
earlistRevision={earlistRevision}
|
||||
selectedRevision={selectedRevision}
|
||||
release={helmReleaseQuery.data}
|
||||
updateRelease={(updatedRelease: HelmRelease) => {
|
||||
queryClient.setQueryData(
|
||||
[
|
||||
environmentId,
|
||||
'helm',
|
||||
'releases',
|
||||
namespace,
|
||||
name,
|
||||
true,
|
||||
],
|
||||
updatedRelease
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Authorized>
|
||||
</div>
|
||||
</WidgetTitle>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue