diff --git a/api/schema/imageBuilder.yaml b/api/schema/imageBuilder.yaml index 543b9420..9477a18a 100644 --- a/api/schema/imageBuilder.yaml +++ b/api/schema/imageBuilder.yaml @@ -1077,6 +1077,11 @@ components: description: | List of custom repositories including all the repository details needed in order to recreate the repositories. + snapshot_date: + type: string + description: | + Importing the snapshot date will not yet be supported. It is exported for informative reasons. + The format is YYYY-MM-DD. BlueprintMetadata: required: - parent_id diff --git a/src/Components/Blueprints/ImportBlueprintModal.tsx b/src/Components/Blueprints/ImportBlueprintModal.tsx index 345733d0..b3d2e561 100644 --- a/src/Components/Blueprints/ImportBlueprintModal.tsx +++ b/src/Components/Blueprints/ImportBlueprintModal.tsx @@ -21,12 +21,15 @@ import { parse } from 'toml'; import { mapOnPremToHosted } from './helpers/onPremToHostedBlueprintMapper'; +import { + ApiRepositoryRequest, + useBulkImportRepositoriesMutation, +} from '../../store/contentSourcesApi'; import { useAppDispatch } from '../../store/hooks'; import { BlueprintExportResponse } from '../../store/imageBuilderApi'; 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>; @@ -53,7 +56,7 @@ 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 [importRepositories] = useBulkImportRepositoriesMutation(); const handleFileInputChange = ( _event: React.ChangeEvent | React.DragEvent, @@ -65,6 +68,61 @@ export const ImportBlueprintModal: React.FunctionComponent< setIsInvalidFormat(false); }; + async function handleRepositoryImport( + blueprintExportedResponse: BlueprintExportResponse + ) { + if (blueprintExportedResponse.content_sources) { + const customRepositories: ApiRepositoryRequest[] = + blueprintExportedResponse.content_sources.map( + (item) => item as ApiRepositoryRequest + ); + + try { + const result = await importRepositories({ + body: customRepositories, + }).unwrap(); + dispatch( + importCustomRepositories( + blueprintExportedResponse.customizations.custom_repositories || [] + ) + ); + + if (Array.isArray(result)) { + const importedRepositoryNames: string[] = []; + result.forEach((repository) => { + if (repository.warnings?.length === 0 && repository.url) { + importedRepositoryNames.push(repository.url); + return; + } + dispatch( + addNotification({ + variant: 'warning', + title: 'Failed to import custom repositories', + description: JSON.stringify(repository.warnings), + }) + ); + }); + if (importedRepositoryNames.length !== 0) { + dispatch( + addNotification({ + variant: 'info', + title: 'Successfully imported custom repositories', + description: importedRepositoryNames.join(', '), + }) + ); + } + } + } catch { + dispatch( + addNotification({ + variant: 'danger', + title: 'Custom repositories import failed', + }) + ); + } + } + } + React.useEffect(() => { if (filename && fileContent) { try { @@ -96,14 +154,8 @@ export const ImportBlueprintModal: React.FunctionComponent< ); 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 || []) - ); - }; + handleRepositoryImport(blueprintExportedResponse); + } setIsOnPrem(false); setImportedBlueprint(importBlueprintState); } catch { diff --git a/src/store/contentSourcesApi.ts b/src/store/contentSourcesApi.ts index faf9f142..511a4b6c 100644 --- a/src/store/contentSourcesApi.ts +++ b/src/store/contentSourcesApi.ts @@ -441,113 +441,117 @@ export type ApiRepositoryRequestRead = { }; export type ApiRepositoryImportResponse = { /** Content Type (rpm) of the repository */ - content_type?: string; + content_type?: string | undefined; /** Architecture to restrict client usage to */ - distribution_arch?: string; + distribution_arch?: string | undefined; /** Versions to restrict client usage to */ - distribution_versions?: string[]; + distribution_versions?: string[] | undefined; /** Number of consecutive failed introspections */ - failed_introspections_count?: number; + failed_introspections_count?: number | undefined; /** GPG key for repository */ - gpg_key?: string; + gpg_key?: string | undefined; /** Label used to configure the yum repository on clients */ - label?: string; + label?: string | undefined; /** Error of last attempted introspection */ - last_introspection_error?: string; + last_introspection_error?: string | undefined; /** Status of last introspection */ - last_introspection_status?: string; + last_introspection_status?: string | undefined; /** Timestamp of last attempted introspection */ - last_introspection_time?: string; - last_snapshot?: ApiSnapshotResponse; - last_snapshot_task?: ApiTaskInfoResponse; + last_introspection_time?: string | undefined; + last_snapshot?: ApiSnapshotResponse | undefined; + last_snapshot_task?: ApiTaskInfoResponse | undefined; /** UUID of the last snapshot task */ - last_snapshot_task_uuid?: string; + last_snapshot_task_uuid?: string | undefined; /** UUID of the last dao.Snapshot */ - last_snapshot_uuid?: string; + last_snapshot_uuid?: string | undefined; /** Timestamp of last successful introspection */ - last_success_introspection_time?: string; + last_success_introspection_time?: string | undefined; /** Timestamp of last introspection that had updates */ - last_update_introspection_time?: string; + last_update_introspection_time?: string | undefined; /** Latest URL for the snapshot distribution */ - latest_snapshot_url?: string; + latest_snapshot_url?: string | undefined; /** Verify packages */ - metadata_verification?: boolean; + metadata_verification?: boolean | undefined; /** Disable modularity filtering on this repository */ - module_hotfixes?: boolean; + module_hotfixes?: boolean | undefined; /** Name of the remote yum repository */ - name?: string; + name?: string | undefined; /** Origin of the repository */ - origin?: string; + origin?: string | undefined; /** Number of packages last read in the repository */ - package_count?: number; + package_count?: number | undefined; /** Enable snapshotting and hosting of this repository */ - snapshot?: boolean; + snapshot?: boolean | undefined; /** Combined status of last introspection and snapshot of repository (Valid, Invalid, Unavailable, Pending) */ - status?: string; + status?: string | undefined; /** URL of the remote yum repository */ - url?: string; + url?: string | undefined; /** Warnings to alert user of mismatched fields if there is an existing repo with the same URL */ - warnings?: { - [key: string]: any; - }[]; + warnings?: + | { + [key: string]: any; + }[] + | undefined; }; export type ApiRepositoryImportResponseRead = { /** Account ID of the owner */ - account_id?: string; + account_id?: string | undefined; /** Content Type (rpm) of the repository */ - content_type?: string; + content_type?: string | undefined; /** Architecture to restrict client usage to */ - distribution_arch?: string; + distribution_arch?: string | undefined; /** Versions to restrict client usage to */ - distribution_versions?: string[]; + distribution_versions?: string[] | undefined; /** Number of consecutive failed introspections */ - failed_introspections_count?: number; + failed_introspections_count?: number | undefined; /** GPG key for repository */ - gpg_key?: string; + gpg_key?: string | undefined; /** Label used to configure the yum repository on clients */ - label?: string; + label?: string | undefined; /** Error of last attempted introspection */ - last_introspection_error?: string; + last_introspection_error?: string | undefined; /** Status of last introspection */ - last_introspection_status?: string; + last_introspection_status?: string | undefined; /** Timestamp of last attempted introspection */ - last_introspection_time?: string; - last_snapshot?: ApiSnapshotResponse; - last_snapshot_task?: ApiTaskInfoResponse; + last_introspection_time?: string | undefined; + last_snapshot?: ApiSnapshotResponse | undefined; + last_snapshot_task?: ApiTaskInfoResponse | undefined; /** UUID of the last snapshot task */ - last_snapshot_task_uuid?: string; + last_snapshot_task_uuid?: string | undefined; /** UUID of the last dao.Snapshot */ - last_snapshot_uuid?: string; + last_snapshot_uuid?: string | undefined; /** Timestamp of last successful introspection */ - last_success_introspection_time?: string; + last_success_introspection_time?: string | undefined; /** Timestamp of last introspection that had updates */ - last_update_introspection_time?: string; + last_update_introspection_time?: string | undefined; /** Latest URL for the snapshot distribution */ - latest_snapshot_url?: string; + latest_snapshot_url?: string | undefined; /** Verify packages */ - metadata_verification?: boolean; + metadata_verification?: boolean | undefined; /** Disable modularity filtering on this repository */ - module_hotfixes?: boolean; + module_hotfixes?: boolean | undefined; /** Name of the remote yum repository */ - name?: string; + name?: string | undefined; /** Organization ID of the owner */ - org_id?: string; + org_id?: string | undefined; /** Origin of the repository */ - origin?: string; + origin?: string | undefined; /** Number of packages last read in the repository */ - package_count?: number; + package_count?: number | undefined; /** Enable snapshotting and hosting of this repository */ - snapshot?: boolean; + snapshot?: boolean | undefined; /** Combined status of last introspection and snapshot of repository (Valid, Invalid, Unavailable, Pending) */ - status?: string; + status?: string | undefined; /** URL of the remote yum repository */ - url?: string; + url?: string | undefined; /** UUID of the object */ - uuid?: string; + uuid?: string | undefined; /** Warnings to alert user of mismatched fields if there is an existing repo with the same URL */ - warnings?: { - [key: string]: any; - }[]; + warnings?: + | { + [key: string]: any; + }[] + | undefined; }; export type ApiRepositoryRpm = { /** The architecture of the rpm */ diff --git a/src/store/imageBuilderApi.ts b/src/store/imageBuilderApi.ts index 39319704..1990658c 100644 --- a/src/store/imageBuilderApi.ts +++ b/src/store/imageBuilderApi.ts @@ -771,6 +771,10 @@ export type BlueprintExportResponse = { to recreate the repositories. */ content_sources?: object[] | undefined; + /** Importing the snapshot date will not yet be supported. It is exported for informative reasons. + The format is YYYY-MM-DD. + */ + snapshot_date?: string | undefined; }; export type ComposeResponse = { id: string; diff --git a/src/store/wizardSlice.ts b/src/store/wizardSlice.ts index 41553d62..4728eb6c 100644 --- a/src/store/wizardSlice.ts +++ b/src/store/wizardSlice.ts @@ -1,7 +1,7 @@ import { PayloadAction, createSlice } from '@reduxjs/toolkit'; import { v4 as uuidv4 } from 'uuid'; -import type { ApiRepositoryImportResponseRead, ApiRepositoryRequest, ApiRepositoryResponseRead } from './contentSourcesApi'; +import type { ApiRepositoryResponseRead } from './contentSourcesApi'; import type { CustomRepository, Distributions, @@ -671,8 +671,8 @@ export const wizardSlice = createSlice({ ) => { state.repositories.customRepositories = [ ...state.repositories.customRepositories, - ...action.payload - ] + ...action.payload, + ]; }, changeCustomRepositories: ( state,