src: add custom repositories import feature
This allows sharing blueprints cross organizations even with custom repositories.
This commit is contained in:
parent
2bee0ef49b
commit
e805c65f81
5 changed files with 158 additions and 3 deletions
|
|
@ -16,6 +16,7 @@ const config: ConfigFile = {
|
|||
'searchPackageGroup',
|
||||
'listFeatures',
|
||||
'listSnapshotsByDate',
|
||||
'bulkImportRepositories',
|
||||
],
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -23,9 +23,10 @@ import { mapOnPremToHosted } from './helpers/onPremToHostedBlueprintMapper';
|
|||
|
||||
import { useAppDispatch } from '../../store/hooks';
|
||||
import { BlueprintExportResponse } from '../../store/imageBuilderApi';
|
||||
import { wizardState } from '../../store/wizardSlice';
|
||||
import { importCustomRepositories, wizardState } from '../../store/wizardSlice';
|
||||
import { resolveRelPath } from '../../Utilities/path';
|
||||
import { mapExportRequestToState } from '../CreateImageWizard/utilities/requestMapper';
|
||||
import { ApiRepositoryRequest, useBulkImportRepositoriesMutation } from '../../store/contentSourcesApi';
|
||||
|
||||
interface ImportBlueprintModalProps {
|
||||
setShowImportModal: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
|
|
@ -52,6 +53,8 @@ export const ImportBlueprintModal: React.FunctionComponent<
|
|||
const [isRejected, setIsRejected] = React.useState(false);
|
||||
const [isOnPrem, setIsOnPrem] = React.useState(false);
|
||||
const dispatch = useAppDispatch();
|
||||
const [importRepositories, repositoriesResult] = useBulkImportRepositoriesMutation();
|
||||
|
||||
const handleFileInputChange = (
|
||||
_event: React.ChangeEvent<HTMLInputElement> | React.DragEvent<HTMLElement>,
|
||||
file: File
|
||||
|
|
@ -61,6 +64,7 @@ export const ImportBlueprintModal: React.FunctionComponent<
|
|||
setIsRejected(false);
|
||||
setIsInvalidFormat(false);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (filename && fileContent) {
|
||||
try {
|
||||
|
|
@ -84,11 +88,22 @@ export const ImportBlueprintModal: React.FunctionComponent<
|
|||
distribution: blueprintFromFile.distribution,
|
||||
customizations: blueprintFromFile.customizations,
|
||||
metadata: blueprintFromFile.metadata,
|
||||
content_sources: blueprintFromFile.content_sources,
|
||||
};
|
||||
const importBlueprintState = mapExportRequestToState(
|
||||
blueprintExportedResponse,
|
||||
blueprintFromFile.image_requests || []
|
||||
);
|
||||
|
||||
if (blueprintExportedResponse.content_sources) {
|
||||
const customRepositories: ApiRepositoryRequest[] = blueprintExportedResponse.content_sources.map(item => item as ApiRepositoryRequest);
|
||||
const result = importRepositories({
|
||||
body: customRepositories,
|
||||
});
|
||||
dispatch(
|
||||
importCustomRepositories(blueprintExportedResponse.customizations.custom_repositories || [])
|
||||
);
|
||||
};
|
||||
setIsOnPrem(false);
|
||||
setImportedBlueprint(importBlueprintState);
|
||||
} catch {
|
||||
|
|
@ -114,6 +129,7 @@ export const ImportBlueprintModal: React.FunctionComponent<
|
|||
}
|
||||
}
|
||||
}, [filename, fileContent]);
|
||||
|
||||
const handleClear = () => {
|
||||
setFilename('');
|
||||
setFileContent('');
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ import {
|
|||
selectSnapshotDate,
|
||||
selectUseLatest,
|
||||
selectFirstBootScript,
|
||||
selectMetadata,
|
||||
initialState,
|
||||
selectTimezone,
|
||||
selectNtpServers,
|
||||
|
|
@ -83,6 +82,7 @@ import {
|
|||
selectKeyboard,
|
||||
selectHostname,
|
||||
selectUsers,
|
||||
selectMetadata,
|
||||
} from '../../../store/wizardSlice';
|
||||
import { FileSystemConfigurationType } from '../steps/FileSystem';
|
||||
import {
|
||||
|
|
@ -370,6 +370,7 @@ export const mapExportRequestToState = (
|
|||
customizations: request.customizations,
|
||||
image_requests: image_requests,
|
||||
};
|
||||
|
||||
return {
|
||||
wizardMode,
|
||||
metadata: {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@ const injectedRtkApi = api.injectEndpoints({
|
|||
body: queryArg.apiRepositoryRequest,
|
||||
}),
|
||||
}),
|
||||
bulkImportRepositories: build.mutation<
|
||||
BulkImportRepositoriesApiResponse,
|
||||
BulkImportRepositoriesApiArg
|
||||
>({
|
||||
query: (queryArg) => ({
|
||||
url: `/repositories/bulk_import/`,
|
||||
method: "POST",
|
||||
body: queryArg.body,
|
||||
}),
|
||||
}),
|
||||
listRepositoriesRpms: build.query<
|
||||
ListRepositoriesRpmsApiResponse,
|
||||
ListRepositoriesRpmsApiArg
|
||||
|
|
@ -129,6 +139,12 @@ export type CreateRepositoryApiArg = {
|
|||
/** request body */
|
||||
apiRepositoryRequest: ApiRepositoryRequest;
|
||||
};
|
||||
export type BulkImportRepositoriesApiResponse =
|
||||
/** status 201 Created */ ApiRepositoryImportResponseRead[];
|
||||
export type BulkImportRepositoriesApiArg = {
|
||||
/** request body */
|
||||
body: ApiRepositoryRequest[];
|
||||
};
|
||||
export type ListRepositoriesRpmsApiResponse =
|
||||
/** status 200 OK */ ApiRepositoryRpmCollectionResponse;
|
||||
export type ListRepositoriesRpmsApiArg = {
|
||||
|
|
@ -423,6 +439,116 @@ export type ApiRepositoryRequestRead = {
|
|||
/** URL of the remote yum repository */
|
||||
url?: string | undefined;
|
||||
};
|
||||
export type ApiRepositoryImportResponse = {
|
||||
/** Content Type (rpm) of the repository */
|
||||
content_type?: string;
|
||||
/** Architecture to restrict client usage to */
|
||||
distribution_arch?: string;
|
||||
/** Versions to restrict client usage to */
|
||||
distribution_versions?: string[];
|
||||
/** Number of consecutive failed introspections */
|
||||
failed_introspections_count?: number;
|
||||
/** GPG key for repository */
|
||||
gpg_key?: string;
|
||||
/** Label used to configure the yum repository on clients */
|
||||
label?: string;
|
||||
/** Error of last attempted introspection */
|
||||
last_introspection_error?: string;
|
||||
/** Status of last introspection */
|
||||
last_introspection_status?: string;
|
||||
/** Timestamp of last attempted introspection */
|
||||
last_introspection_time?: string;
|
||||
last_snapshot?: ApiSnapshotResponse;
|
||||
last_snapshot_task?: ApiTaskInfoResponse;
|
||||
/** UUID of the last snapshot task */
|
||||
last_snapshot_task_uuid?: string;
|
||||
/** UUID of the last dao.Snapshot */
|
||||
last_snapshot_uuid?: string;
|
||||
/** Timestamp of last successful introspection */
|
||||
last_success_introspection_time?: string;
|
||||
/** Timestamp of last introspection that had updates */
|
||||
last_update_introspection_time?: string;
|
||||
/** Latest URL for the snapshot distribution */
|
||||
latest_snapshot_url?: string;
|
||||
/** Verify packages */
|
||||
metadata_verification?: boolean;
|
||||
/** Disable modularity filtering on this repository */
|
||||
module_hotfixes?: boolean;
|
||||
/** Name of the remote yum repository */
|
||||
name?: string;
|
||||
/** Origin of the repository */
|
||||
origin?: string;
|
||||
/** Number of packages last read in the repository */
|
||||
package_count?: number;
|
||||
/** Enable snapshotting and hosting of this repository */
|
||||
snapshot?: boolean;
|
||||
/** Combined status of last introspection and snapshot of repository (Valid, Invalid, Unavailable, Pending) */
|
||||
status?: string;
|
||||
/** URL of the remote yum repository */
|
||||
url?: string;
|
||||
/** Warnings to alert user of mismatched fields if there is an existing repo with the same URL */
|
||||
warnings?: {
|
||||
[key: string]: any;
|
||||
}[];
|
||||
};
|
||||
export type ApiRepositoryImportResponseRead = {
|
||||
/** Account ID of the owner */
|
||||
account_id?: string;
|
||||
/** Content Type (rpm) of the repository */
|
||||
content_type?: string;
|
||||
/** Architecture to restrict client usage to */
|
||||
distribution_arch?: string;
|
||||
/** Versions to restrict client usage to */
|
||||
distribution_versions?: string[];
|
||||
/** Number of consecutive failed introspections */
|
||||
failed_introspections_count?: number;
|
||||
/** GPG key for repository */
|
||||
gpg_key?: string;
|
||||
/** Label used to configure the yum repository on clients */
|
||||
label?: string;
|
||||
/** Error of last attempted introspection */
|
||||
last_introspection_error?: string;
|
||||
/** Status of last introspection */
|
||||
last_introspection_status?: string;
|
||||
/** Timestamp of last attempted introspection */
|
||||
last_introspection_time?: string;
|
||||
last_snapshot?: ApiSnapshotResponse;
|
||||
last_snapshot_task?: ApiTaskInfoResponse;
|
||||
/** UUID of the last snapshot task */
|
||||
last_snapshot_task_uuid?: string;
|
||||
/** UUID of the last dao.Snapshot */
|
||||
last_snapshot_uuid?: string;
|
||||
/** Timestamp of last successful introspection */
|
||||
last_success_introspection_time?: string;
|
||||
/** Timestamp of last introspection that had updates */
|
||||
last_update_introspection_time?: string;
|
||||
/** Latest URL for the snapshot distribution */
|
||||
latest_snapshot_url?: string;
|
||||
/** Verify packages */
|
||||
metadata_verification?: boolean;
|
||||
/** Disable modularity filtering on this repository */
|
||||
module_hotfixes?: boolean;
|
||||
/** Name of the remote yum repository */
|
||||
name?: string;
|
||||
/** Organization ID of the owner */
|
||||
org_id?: string;
|
||||
/** Origin of the repository */
|
||||
origin?: string;
|
||||
/** Number of packages last read in the repository */
|
||||
package_count?: number;
|
||||
/** Enable snapshotting and hosting of this repository */
|
||||
snapshot?: boolean;
|
||||
/** Combined status of last introspection and snapshot of repository (Valid, Invalid, Unavailable, Pending) */
|
||||
status?: string;
|
||||
/** URL of the remote yum repository */
|
||||
url?: string;
|
||||
/** UUID of the object */
|
||||
uuid?: string;
|
||||
/** Warnings to alert user of mismatched fields if there is an existing repo with the same URL */
|
||||
warnings?: {
|
||||
[key: string]: any;
|
||||
}[];
|
||||
};
|
||||
export type ApiRepositoryRpm = {
|
||||
/** The architecture of the rpm */
|
||||
arch?: string | undefined;
|
||||
|
|
@ -475,6 +601,7 @@ export const {
|
|||
useSearchPackageGroupMutation,
|
||||
useListRepositoriesQuery,
|
||||
useCreateRepositoryMutation,
|
||||
useBulkImportRepositoriesMutation,
|
||||
useListRepositoriesRpmsQuery,
|
||||
useSearchRpmMutation,
|
||||
useListSnapshotsByDateMutation,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import type { ApiRepositoryResponseRead } from './contentSourcesApi';
|
||||
import type { ApiRepositoryImportResponseRead, ApiRepositoryRequest, ApiRepositoryResponseRead } from './contentSourcesApi';
|
||||
import type {
|
||||
CustomRepository,
|
||||
Distributions,
|
||||
|
|
@ -665,6 +665,15 @@ export const wizardSlice = createSlice({
|
|||
changeSnapshotDate: (state, action: PayloadAction<string>) => {
|
||||
state.snapshotting.snapshotDate = action.payload;
|
||||
},
|
||||
importCustomRepositories: (
|
||||
state,
|
||||
action: PayloadAction<CustomRepository[]>
|
||||
) => {
|
||||
state.repositories.customRepositories = [
|
||||
...state.repositories.customRepositories,
|
||||
...action.payload
|
||||
]
|
||||
},
|
||||
changeCustomRepositories: (
|
||||
state,
|
||||
action: PayloadAction<CustomRepository[]>
|
||||
|
|
@ -867,6 +876,7 @@ export const {
|
|||
changeUseLatest,
|
||||
changeSnapshotDate,
|
||||
changeCustomRepositories,
|
||||
importCustomRepositories,
|
||||
changePayloadRepositories,
|
||||
addRecommendedRepository,
|
||||
removeRecommendedRepository,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue