Launch: implement guidance for AWS (HMS-9002)

This commit adds launch modal for guiding users through launching an AWS
instance from their image. As the launch service will be decommissioned,
the flag shall be turned on, the code will later be cleaned up and the
Provisioning wizard removed.
This commit is contained in:
Anna Vítová 2025-08-11 16:06:21 +02:00
parent 54e413f459
commit 1e162433bc
2 changed files with 123 additions and 4 deletions

View file

@ -54,7 +54,9 @@ import {
isOciUploadStatus,
} from '../../store/typeGuards';
import { resolveRelPath } from '../../Utilities/path';
import { useFlag } from '../../Utilities/useGetEnvironment';
import useProvisioningPermissions from '../../Utilities/useProvisioningPermissions';
import { AWSLaunchModal } from '../Launch/AWSLaunchModal';
type CloudInstancePropTypes = {
compose: ComposesResponseItem;
@ -97,6 +99,7 @@ const ProvisioningLink = ({
compose,
composeStatus,
}: ProvisioningLinkPropTypes) => {
const launchEofFlag = useFlag('image-builder.launcheof');
const [userData, setUserData] = useState<ChromeUser | void>(undefined);
const { analytics, auth } = useChrome();
@ -111,7 +114,7 @@ const ProvisioningLink = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const [wizardOpen, setWizardOpen] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(false);
const [exposedScalprumModule, error] = useLoadModule(
{
scope: 'provisioning',
@ -182,7 +185,7 @@ const ProvisioningLink = ({
account_id: userData?.identity.internal?.account_id || 'Not found',
});
setWizardOpen(true);
setIsModalOpen(true);
}}
>
Launch
@ -202,6 +205,10 @@ const ProvisioningLink = ({
</Popover>
);
const handleModalToggle = (_event: KeyboardEvent | React.MouseEvent) => {
setIsModalOpen(!isModalOpen);
};
return (
<>
<Suspense fallback='loading...'>
@ -209,7 +216,15 @@ const ProvisioningLink = ({
compose.blueprint_version !== selectedBlueprintVersion
? buttonWithTooltip
: btn}
{wizardOpen && (
{launchEofFlag && isModalOpen && provider === 'aws' && (
<AWSLaunchModal
isOpen={isModalOpen}
handleModalToggle={handleModalToggle}
compose={compose}
composeStatus={composeStatus}
/>
)}
{!launchEofFlag && isModalOpen && (
<Modal
isOpen
appendTo={appendTo}
@ -218,7 +233,7 @@ const ProvisioningLink = ({
>
<ProvisioningWizard
hasAccess={permissions[provider]}
onClose={() => setWizardOpen(false)}
onClose={() => setIsModalOpen(false)}
image={{
name: compose.image_name || compose.id,
id: compose.id,

View file

@ -0,0 +1,104 @@
import React from 'react';
import {
Button,
List,
ListComponent,
ListItem,
Modal,
ModalBody,
ModalFooter,
ModalHeader,
ModalVariant,
OrderType,
} from '@patternfly/react-core';
import { ExternalLinkAltIcon } from '@patternfly/react-icons';
import {
ComposesResponseItem,
ComposeStatus,
} from '../../store/imageBuilderApi';
import { isAwsUploadRequestOptions } from '../../store/typeGuards';
type LaunchProps = {
isOpen: boolean;
handleModalToggle: (event: KeyboardEvent | React.MouseEvent) => void;
compose: ComposesResponseItem;
composeStatus: ComposeStatus | undefined;
};
export const AWSLaunchModal = ({
isOpen,
handleModalToggle,
compose,
composeStatus,
}: LaunchProps) => {
const options = compose.request.image_requests[0].upload_request.options;
if (!isAwsUploadRequestOptions(options)) {
throw TypeError(
`Error: options must be of type AwsUploadRequestOptions, not ${typeof options}.`,
);
}
const amiId =
composeStatus?.image_status.status === 'success' &&
composeStatus.image_status.upload_status?.options &&
'ami' in composeStatus.image_status.upload_status.options
? composeStatus.image_status.upload_status.options.ami
: '';
return (
<Modal
isOpen={isOpen}
onClose={handleModalToggle}
variant={ModalVariant.large}
aria-label='Open launch guide modal'
>
<ModalHeader
title={'Launch with Amazon Web Services'}
labelId='modal-title'
description={compose.image_name}
/>
<ModalBody id='modal-box-body-basic'>
<List component={ListComponent.ol} type={OrderType.number}>
<ListItem>
Navigate to the{' '}
<Button
component='a'
target='_blank'
variant='link'
icon={<ExternalLinkAltIcon />}
iconPosition='right'
href={`https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#ImageDetails:imageId=${amiId}`}
className='pf-v6-u-pl-0'
>
Images detail page
</Button>{' '}
located on your AWS console.
</ListItem>
<ListItem>
Copy the image to make it a permanent copy in your account.
<br />
Shared with Account{' '}
<span className='pf-v6-u-font-weight-bold'>
{options.share_with_accounts?.[0]}
</span>
<br />
AMI ID: <span className='pf-v6-u-font-weight-bold'>{amiId}</span>
</ListItem>
<ListItem>Launch image as an instance.</ListItem>
<ListItem>
Connect to it via SSH using the following username:{' '}
<span className='pf-v6-u-font-weight-bold'>ec2-user</span>
</ListItem>
</List>
</ModalBody>
<ModalFooter>
<Button key='close' variant='primary' onClick={handleModalToggle}>
Close
</Button>
</ModalFooter>
</Modal>
);
};