Skip to content

Commit

Permalink
pulp_file: Repositories & Remotes
Browse files Browse the repository at this point in the history
  • Loading branch information
himdel committed Dec 30, 2024
1 parent 7efeeb5 commit 7a73093
Show file tree
Hide file tree
Showing 33 changed files with 1,754 additions and 90 deletions.
9 changes: 9 additions & 0 deletions src/actions/file-remote-create.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { msg } from '@lingui/core/macro';
import { Paths, formatPath } from 'src/paths';
import { Action } from './action';

export const fileRemoteCreateAction = Action({
title: msg`Add remote`,
onClick: (item, { navigate }) =>
navigate(formatPath(Paths.file.remote.edit, { name: '_' })),
});
44 changes: 44 additions & 0 deletions src/actions/file-remote-delete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { msg, t } from '@lingui/core/macro';
import { FileRemoteAPI } from 'src/api';
import { DeleteRemoteModal } from 'src/components';
import {
handleHttpError,
parsePulpIDFromURL,
taskAlert,
waitForTaskUrl,
} from 'src/utilities';
import { Action } from './action';

export const fileRemoteDeleteAction = Action({
title: msg`Delete`,
modal: ({ addAlert, listQuery, setState, state }) =>
state.deleteModalOpen ? (
<DeleteRemoteModal
closeAction={() => setState({ deleteModalOpen: null })}
deleteAction={() =>
deleteRemote(state.deleteModalOpen, { addAlert, setState, listQuery })
}
name={state.deleteModalOpen.name}
/>
) : null,
onClick: (
{ name, id, pulp_href }: { name: string; id?: string; pulp_href?: string },
{ setState },
) =>
setState({
deleteModalOpen: { pulpId: id || parsePulpIDFromURL(pulp_href), name },
}),
});

function deleteRemote({ name, pulpId }, { addAlert, setState, listQuery }) {
return FileRemoteAPI.delete(pulpId)
.then(({ data }) => {
addAlert(taskAlert(data.task, t`Removal started for remote ${name}`));
setState({ deleteModalOpen: null });
return waitForTaskUrl(data.task);
})
.then(() => listQuery())
.catch(
handleHttpError(t`Failed to remove remote ${name}`, () => null, addAlert),
);
}
9 changes: 9 additions & 0 deletions src/actions/file-remote-edit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { msg } from '@lingui/core/macro';
import { Paths, formatPath } from 'src/paths';
import { Action } from './action';

export const fileRemoteEditAction = Action({
title: msg`Edit`,
onClick: ({ name }, { navigate }) =>
navigate(formatPath(Paths.file.remote.edit, { name })),
});
9 changes: 9 additions & 0 deletions src/actions/file-repository-create.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { msg } from '@lingui/core/macro';
import { Paths, formatPath } from 'src/paths';
import { Action } from './action';

export const fileRepositoryCreateAction = Action({
title: msg`Add repository`,
onClick: (item, { navigate }) =>
navigate(formatPath(Paths.file.repository.edit, { name: '_' })),
});
99 changes: 99 additions & 0 deletions src/actions/file-repository-delete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { msg, t } from '@lingui/core/macro';
import { FileDistributionAPI, FileRepositoryAPI } from 'src/api';
import { DeleteRepositoryModal } from 'src/components';
import {
handleHttpError,
parsePulpIDFromURL,
taskAlert,
waitForTaskUrl,
} from 'src/utilities';
import { Action } from './action';

export const fileRepositoryDeleteAction = Action({
title: msg`Delete`,
modal: ({ addAlert, listQuery, setState, state }) =>
state.deleteModalOpen ? (
<DeleteRepositoryModal
closeAction={() => setState({ deleteModalOpen: null })}
deleteAction={() =>
deleteRepository(state.deleteModalOpen, {
addAlert,
listQuery,
setState,
})
}
name={state.deleteModalOpen.name}
/>
) : null,
onClick: (
{ name, id, pulp_href }: { name: string; id?: string; pulp_href?: string },
{ setState },
) =>
setState({
deleteModalOpen: {
pulpId: id || parsePulpIDFromURL(pulp_href),
name,
pulp_href,
},
}),
});

async function deleteRepository(
{ name, pulp_href, pulpId },
{ addAlert, setState, listQuery },
) {
// TODO: handle more pages
const distributionsToDelete = await FileDistributionAPI.list({
repository: pulp_href,
page: 1,
page_size: 100,
})
.then(({ data: { results } }) => results || [])
.catch((e) => {
handleHttpError(
t`Failed to list distributions, removing only the repository.`,
() => null,
addAlert,
)(e);
return [];
});

const deleteRepo = FileRepositoryAPI.delete(pulpId)
.then(({ data }) => {
addAlert(taskAlert(data.task, t`Removal started for repository ${name}`));
return waitForTaskUrl(data.task);
})
.catch(
handleHttpError(
t`Failed to remove repository ${name}`,
() => setState({ deleteModalOpen: null }),
addAlert,
),
);

const deleteDistribution = ({ name, pulp_href }) => {
const distribution_id = parsePulpIDFromURL(pulp_href);
return FileDistributionAPI.delete(distribution_id)
.then(({ data }) => {
addAlert(
taskAlert(data.task, t`Removal started for distribution ${name}`),
);
return waitForTaskUrl(data.task);
})
.catch(
handleHttpError(
t`Failed to remove distribution ${name}`,
() => null,
addAlert,
),
);
};

return Promise.all([
deleteRepo,
...distributionsToDelete.map(deleteDistribution),
]).then(() => {
setState({ deleteModalOpen: null });
listQuery();
});
}
9 changes: 9 additions & 0 deletions src/actions/file-repository-edit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { msg } from '@lingui/core/macro';
import { Paths, formatPath } from 'src/paths';
import { Action } from './action';

export const fileRepositoryEditAction = Action({
title: msg`Edit`,
onClick: ({ name }, { navigate }) =>
navigate(formatPath(Paths.file.repository.edit, { name })),
});
148 changes: 148 additions & 0 deletions src/actions/file-repository-sync.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { msg, t } from '@lingui/core/macro';
import { Button, FormGroup, Modal, Switch } from '@patternfly/react-core';
import { useEffect, useState } from 'react';
import { FileRepositoryAPI } from 'src/api';
import { HelpButton, Spinner } from 'src/components';
import { handleHttpError, parsePulpIDFromURL, taskAlert } from 'src/utilities';
import { Action } from './action';

const SyncModal = ({
closeAction,
syncAction,
name,
}: {
closeAction: () => null;
syncAction: (syncParams) => Promise<void>;
name: string;
}) => {
const [pending, setPending] = useState(false);
const [syncParams, setSyncParams] = useState({
mirror: true,
optimize: true,
});

useEffect(() => {
setPending(false);
setSyncParams({ mirror: true, optimize: true });
}, [name]);

if (!name) {
return null;
}

return (
<Modal
actions={[
<div data-cy='sync-button' key='sync'>
<Button
key='sync'
onClick={() => {
setPending(true);
syncAction(syncParams)
.then(closeAction)
.finally(() => setPending(false));
}}
variant='primary'
isDisabled={pending}
>
{t`Sync`}
{pending && <Spinner size='sm' />}
</Button>
</div>,
<Button key='close' onClick={closeAction} variant='link'>
{t`Close`}
</Button>,
]}
isOpen
onClose={closeAction}
title={t`Sync repository "${name}"`}
variant='medium'
>
<FormGroup
label={t`Mirror`}
labelIcon={
<HelpButton
content={t`If selected, all content that is not present in the remote repository will be removed from the local repository; otherwise, sync will add missing content.`}
/>
}
>
<Switch
isChecked={syncParams.mirror}
onChange={(_event, mirror) =>
setSyncParams({ ...syncParams, mirror })
}
label={t`Content not present in remote repository will be removed from the local repository`}
labelOff={t`Sync will only add missing content`}
/>
</FormGroup>
<br />
<FormGroup
label={t`Optimize`}
labelIcon={
<HelpButton
content={t`Only perform the sync if changes are reported by the remote server. To force a sync to happen, deselect this option.`}
/>
}
>
<Switch
isChecked={syncParams.optimize}
onChange={(_event, optimize) =>
setSyncParams({ ...syncParams, optimize })
}
label={t`Only perform the sync if changes are reported by the remote server.`}
labelOff={t`Force a sync to happen.`}
/>
</FormGroup>
<br />
</Modal>
);
};

export const fileRepositorySyncAction = Action({
title: msg`Sync`,
modal: ({ addAlert, query, setState, state }) =>
state.syncModalOpen ? (
<SyncModal
closeAction={() => setState({ syncModalOpen: null })}
syncAction={(syncParams) =>
syncRepository(state.syncModalOpen, { addAlert, query }, syncParams)
}
name={state.syncModalOpen.name}
/>
) : null,
onClick: ({ name, pulp_href }, { setState }) =>
setState({
syncModalOpen: { name, pulp_href },
}),
visible: (_item, { hasPermission }) =>
hasPermission('file.change_collectionremote'),
disabled: ({ remote, last_sync_task }) => {
if (!remote) {
return t`There are no remotes associated with this repository.`;
}

if (
last_sync_task &&
['running', 'waiting'].includes(last_sync_task.state)
) {
return t`Sync task is already queued.`;
}
},
});

function syncRepository({ name, pulp_href }, { addAlert, query }, syncParams) {
const pulpId = parsePulpIDFromURL(pulp_href);
return FileRepositoryAPI.sync(pulpId, syncParams || { mirror: true })
.then(({ data }) => {
addAlert(taskAlert(data.task, t`Sync started for repository "${name}".`));

query();
})
.catch(
handleHttpError(
t`Failed to sync repository "${name}"`,
() => null,
addAlert,
),
);
}
7 changes: 7 additions & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ export { ansibleRepositoryDeleteAction } from './ansible-repository-delete';
export { ansibleRepositoryEditAction } from './ansible-repository-edit';
export { ansibleRepositorySyncAction } from './ansible-repository-sync';
export { ansibleRepositoryVersionRevertAction } from './ansible-repository-version-revert';
export { fileRemoteCreateAction } from './file-remote-create';
export { fileRemoteDeleteAction } from './file-remote-delete';
export { fileRemoteEditAction } from './file-remote-edit';
export { fileRepositoryCreateAction } from './file-repository-create';
export { fileRepositoryDeleteAction } from './file-repository-delete';
export { fileRepositoryEditAction } from './file-repository-edit';
export { fileRepositorySyncAction } from './file-repository-sync';
35 changes: 34 additions & 1 deletion src/api/ansible-remote.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
import { PulpAPI } from './pulp';
import { type AnsibleRemoteType } from './response-types/ansible-remote';

export class AnsibleRemoteType {
auth_url: string;
ca_cert: string;
client_cert: string;
download_concurrency: number;
name: string;
proxy_url: string;
pulp_href?: string;
rate_limit: number;
requirements_file: string;
tls_validation: boolean;
url: string;
signed_only: boolean;
sync_dependencies?: boolean;

// connect_timeout
// headers
// max_retries
// policy
// pulp_created
// pulp_labels
// pulp_last_updated
// sock_connect_timeout
// sock_read_timeout
// total_timeout

hidden_fields: {
is_set: boolean;
name: string;
}[];

my_permissions?: string[];
}

// simplified version of smartUpdate from execution-environment-registry
function smartUpdate(
Expand Down
Loading

0 comments on commit 7a73093

Please sign in to comment.