import React, { useEffect, useMemo } from 'react';
import {
Alert,
Button,
Popover,
Content,
ContentVariants,
FormGroup,
CodeBlock,
CodeBlockCode,
} from '@patternfly/react-core';
import { ExclamationTriangleIcon } from '@patternfly/react-icons';
import ActivationKeyInformation from './../Registration/ActivationKeyInformation';
import {
PackagesTable,
RepositoriesTable,
SnapshotTable,
} from './ReviewStepTables';
import { FSReviewTable } from './ReviewStepTables';
import {
FEDORA_RELEASES,
ON_PREM_RELEASES,
RELEASES,
RHEL_8,
RHEL_8_FULL_SUPPORT,
RHEL_8_MAINTENANCE_SUPPORT,
RHEL_9,
targetOptions,
UNIT_GIB,
} from '../../../../constants';
import {
useListSnapshotsByDateMutation,
useGetTemplateQuery,
} from '../../../../store/contentSourcesApi';
import { useAppSelector } from '../../../../store/hooks';
import { useGetSourceListQuery } from '../../../../store/provisioningApi';
import { useShowActivationKeyQuery } from '../../../../store/rhsmApi';
import {
selectActivationKey,
selectArchitecture,
selectAwsAccountId,
selectAwsShareMethod,
selectAzureShareMethod,
selectAzureSource,
selectAzureResourceGroup,
selectAzureSubscriptionId,
selectAzureTenantId,
selectAwsSourceId,
selectBlueprintDescription,
selectBlueprintName,
selectCustomRepositories,
selectDistribution,
selectGcpAccountType,
selectGcpEmail,
selectGcpShareMethod,
selectPackages,
selectGroups,
selectRegistrationType,
selectFileSystemConfigurationType,
selectRecommendedRepositories,
selectSnapshotDate,
selectUseLatest,
selectPartitions,
selectFirstBootScript,
selectTimezone,
selectNtpServers,
selectLanguages,
selectKeyboard,
selectHostname,
selectKernel,
selectFirewall,
selectServices,
selectUsers,
selectTemplate,
selectRedHatRepositories,
} from '../../../../store/wizardSlice';
import { toMonthAndYear, yyyyMMddFormat } from '../../../../Utilities/time';
import { useGetEnvironment } from '../../../../Utilities/useGetEnvironment';
import {
getConversionFactor,
MinimumSizePopover,
Partition,
} from '../FileSystem/FileSystemTable';
import { MajorReleasesLifecyclesChart } from '../ImageOutput/ReleaseLifecycle';
import OscapProfileInformation from '../Oscap/components/OscapProfileInformation';
import PopoverActivation from '../Registration/components/PopoverActivation';
const ExpirationWarning = () => {
return (
Expires 14 days after creation
);
};
export const ImageOutputList = () => {
const distribution = useAppSelector(selectDistribution);
const arch = useAppSelector(selectArchitecture);
const { isFedoraEnv } = useGetEnvironment();
const releases = isFedoraEnv
? FEDORA_RELEASES
: process.env.IS_ON_PREMISE
? ON_PREM_RELEASES
: RELEASES;
return (
{distribution === RHEL_8 && (
<>
{RELEASES.get(distribution)} will be supported through{' '}
{toMonthAndYear(RHEL_8_FULL_SUPPORT[1])}, with optional ELS support
through {toMonthAndYear(RHEL_8_MAINTENANCE_SUPPORT[1])}. Consider
building an image with {RELEASES.get(RHEL_9)} to extend the support
period.
>
)}
Release
{releases.get(distribution)}
Architecture
{arch}
);
};
export const FSCList = () => {
const fileSystemConfigurationType = useAppSelector(
selectFileSystemConfigurationType
);
const partitions = useAppSelector(selectPartitions);
return (
Configuration type
{fileSystemConfigurationType === 'manual' ? 'Manual' : 'Automatic'}
{fileSystemConfigurationType === 'manual' && (
<>
{' '}
}
>
>
)}
{fileSystemConfigurationType === 'manual' && (
<>
Image size (minimum)
>
)}
);
};
type MinSizeProps = {
partitions: Partition[];
};
export const MinSize = ({ partitions }: MinSizeProps) => {
let minSize = '';
if (partitions) {
let size = 0;
for (const partition of partitions) {
size += Number(partition.min_size) * getConversionFactor(partition.unit);
}
size = Number((size / UNIT_GIB).toFixed(1));
if (size < 1) {
minSize = `Less than 1 GiB`;
} else {
minSize = `${size} GiB`;
}
}
return {minSize} ;
};
export const TargetEnvAWSList = () => {
const { isSuccess } = useGetSourceListQuery({
provider: 'aws',
});
const awsAccountId = useAppSelector(selectAwsAccountId);
const awsShareMethod = useAppSelector(selectAwsShareMethod);
const sourceId = useAppSelector(selectAwsSourceId);
const { source } = useGetSourceListQuery(
{
provider: 'aws',
},
{
selectFromResult: ({ data }) => ({
source: data?.data?.find((source) => source.id === sourceId),
}),
}
);
return (
{targetOptions.aws}
Image type
Red Hat hosted image
Shared to account
{awsAccountId}
{awsShareMethod === 'sources' ? 'Source' : null}
{isSuccess && awsShareMethod === 'sources' ? source?.name : null}
Default region
us-east-1
);
};
export const TargetEnvGCPList = () => {
const accountType = useAppSelector(selectGcpAccountType);
const sharedMethod = useAppSelector(selectGcpShareMethod);
const email = useAppSelector(selectGcpEmail);
return (
{targetOptions.gcp}
Image type
Red Hat hosted image
<>
{sharedMethod === 'withInsights' ? (
<>
Shared with
Red Hat Insights only
>
) : (
<>
Account type
{accountType === 'group'
? 'Google group'
: accountType === 'serviceAccount'
? 'Service account'
: accountType === 'user'
? 'Google account'
: 'Domain'}
{accountType === 'domain' ? 'Domain' : 'Principal'}
{email || accountType}
>
)}
>
);
};
export const TargetEnvAzureList = () => {
const { data: rawAzureSources, isSuccess: isSuccessAzureSources } =
useGetSourceListQuery({ provider: 'azure' });
const shareMethod = useAppSelector(selectAzureShareMethod);
const tenantId = useAppSelector(selectAzureTenantId);
const azureSource = useAppSelector(selectAzureSource);
const azureResourceGroup = useAppSelector(selectAzureResourceGroup);
const subscriptionId = useAppSelector(selectAzureSubscriptionId);
return (
{targetOptions.azure}
Image type
Red Hat hosted image
{shareMethod === 'sources' && isSuccessAzureSources && (
<>
Azure Source
{
rawAzureSources?.data?.find(
(source) => source.id === azureSource
)?.name
}
>
)}
{shareMethod === 'manual' && (
<>
Azure tenant ID
{tenantId}
Subscription ID
{subscriptionId}
>
)}
Resource group
{azureResourceGroup}
);
};
export const TargetEnvOciList = () => {
return (
{targetOptions.oci}
Object Storage URL
The URL for the built image will be ready to copy
);
};
export const TargetEnvOtherList = () => {
return (
<>
Image type
Built image will be available for download
>
);
};
export const ContentList = () => {
const customRepositories = useAppSelector(selectCustomRepositories);
const packages = useAppSelector(selectPackages);
const groups = useAppSelector(selectGroups);
const recommendedRepositories = useAppSelector(selectRecommendedRepositories);
const snapshotDate = useAppSelector(selectSnapshotDate);
const useLatest = useAppSelector(selectUseLatest);
const template = useAppSelector(selectTemplate);
const redHatRepositories = useAppSelector(selectRedHatRepositories);
const customAndRecommendedRepositoryUUIDS = useMemo(
() =>
[
...customRepositories.map(({ id }) => id),
...recommendedRepositories.map(({ uuid }) => uuid),
] as string[],
[customRepositories, recommendedRepositories]
);
const [listSnapshotsByDate, { data, isSuccess, isLoading, isError }] =
useListSnapshotsByDateMutation();
useEffect(() => {
if (!snapshotDate && !useLatest) return;
listSnapshotsByDate({
apiListSnapshotByDateRequest: {
repository_uuids: customAndRecommendedRepositoryUUIDS,
date: useLatest
? yyyyMMddFormat(new Date()) + 'T00:00:00Z'
: snapshotDate,
},
});
}, [
customAndRecommendedRepositoryUUIDS,
listSnapshotsByDate,
snapshotDate,
useLatest,
]);
const duplicatePackages = packages.filter(
(item, index) => packages.indexOf(item) !== index
);
const noRepositoriesSelected =
customAndRecommendedRepositoryUUIDS.length === 0 &&
redHatRepositories.length === 0;
const hasSnapshotDateAfter = data?.data?.some(({ is_after }) => is_after);
const { data: templateData, isLoading: isTemplateLoading } =
useGetTemplateQuery(
{
uuid: template,
},
{ refetchOnMountOrArgChange: true, skip: template === '' }
);
const snapshottingText = useMemo(() => {
switch (true) {
case isLoading || isTemplateLoading:
return '';
case useLatest:
return 'Use latest';
case !!snapshotDate:
return `State as of ${yyyyMMddFormat(new Date(snapshotDate))}`;
case !!template:
return `Use a content template: ${templateData?.name}`;
default:
return '';
}
}, [isLoading, isTemplateLoading, useLatest, snapshotDate, template]);
return (
<>
<>
Repeatable build
}
>
{!useLatest && !isLoading && isSuccess && hasSnapshotDateAfter ? (
) : (
''
)}
>
Custom repositories
{customRepositories?.length + recommendedRepositories.length > 0 ? (
}
>
) : (
0
)}
Additional packages
{packages?.length > 0 || groups?.length > 0 ? (
}
>
) : (
0
)}
{duplicatePackages.length > 0 && (
Some of the packages added to this image belong to multiple added
repositories. We can not guarantee which repository the package will
come from.
)}
>
);
};
export const RegisterLaterList = () => {
return (
Registration type
Register the system later
);
};
export const RegisterSatelliteList = () => {
return (
Register Satellite
Enabled
);
};
export const RegisterNowList = () => {
const activationKey = useAppSelector(selectActivationKey);
const registrationType = useAppSelector(selectRegistrationType);
const { isError } = useShowActivationKeyQuery(
// @ts-ignore type of 'activationKey' might not be strictly compatible with the expected type for 'name'.
{ name: activationKey },
{
skip: !activationKey,
}
);
return (
<>
Registration type
{registrationType?.startsWith('register-now') && (
Register with Red Hat Subscription Manager (RHSM)
)}
{(registrationType === 'register-now-insights' ||
registrationType === 'register-now-rhc') && (
Connect to Red Hat Insights
)}
{registrationType === 'register-now-rhc' && (
Use remote host configuration (rhc) utility
)}
Activation key
{isError && (
Information about the activation key cannot be loaded. Please check
the key was not removed and try again later.
)}
>
);
};
export const DetailsList = () => {
const blueprintName = useAppSelector(selectBlueprintName);
const blueprintDescription = useAppSelector(selectBlueprintDescription);
return (
{blueprintName && (
<>
Blueprint name
{blueprintName}
>
)}
{blueprintDescription && (
<>
Description
{blueprintDescription}
>
)}
);
};
export const OscapList = () => {
return ;
};
export const TimezoneList = () => {
const timezone = useAppSelector(selectTimezone);
const ntpServers = useAppSelector(selectNtpServers);
return (
Timezone
{timezone ? timezone : 'None'}
NTP servers
{ntpServers && ntpServers.length > 0 ? ntpServers.join(', ') : 'None'}
);
};
export const UsersList = () => {
const users = useAppSelector(selectUsers);
return (
{users.map((user) => (
Username
{user.name ? user.name : 'None'}
Password
{user.password || user.hasPassword ? '●'.repeat(8) : 'None'}
SSH key
{user.ssh_key ? user.ssh_key : 'None'}
Administrator
{user.isAdministrator ? 'True' : 'False'}
))}
);
};
export const LocaleList = () => {
const languages = useAppSelector(selectLanguages);
const keyboard = useAppSelector(selectKeyboard);
return (
Languages
{languages && languages.length > 0 ? languages.join(', ') : 'None'}
Keyboard
{keyboard ? keyboard : 'None'}
);
};
export const HostnameList = () => {
const hostname = useAppSelector(selectHostname);
return (
Hostname
{hostname ? hostname : 'None'}
);
};
export const KernelList = () => {
const kernel = useAppSelector(selectKernel);
return (
Name
{kernel.name ? kernel.name : 'None'}
Append
{kernel.append.length > 0 ? (
{kernel.append.join(' ')}
) : (
'None'
)}
);
};
export const FirewallList = () => {
const firewall = useAppSelector(selectFirewall);
return (
Ports
{firewall.ports.length > 0 ? (
{firewall.ports.join(' ')}
) : (
'None'
)}
Disabled services
{firewall.services.disabled.length > 0 ? (
{firewall.services.disabled.join(' ')}
) : (
'None'
)}
Enabled services
{firewall.services.enabled.length > 0 ? (
{firewall.services.enabled.join(' ')}
) : (
'None'
)}
);
};
export const ServicesList = () => {
const services = useAppSelector(selectServices);
return (
Disabled
{services.disabled.length > 0 ? (
{services.disabled.join(' ')}
) : (
'None'
)}
Masked
{services.masked.length > 0 ? (
{services.masked.join(' ')}
) : (
'None'
)}
Enabled
{services.enabled.length > 0 ? (
{services.enabled.join(' ')}
) : (
'None'
)}
);
};
export const FirstBootList = () => {
const isFirstbootEnabled = !!useAppSelector(selectFirstBootScript);
return (
First boot script
{isFirstbootEnabled ? 'Enabled' : 'Disabled'}
);
};