Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build images with cockpit (HMS-5417) #2787

Merged
merged 10 commits into from
Jan 30, 2025
10 changes: 5 additions & 5 deletions src/Components/Blueprints/BuildImagesButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ import { addNotification } from '@redhat-cloud-services/frontend-components-noti
import { skipToken } from '@reduxjs/toolkit/query';

import { targetOptions } from '../../constants';
import { useGetBlueprintQuery } from '../../store/backendApi';
import { selectSelectedBlueprintId } from '../../store/BlueprintSlice';
import { useAppDispatch, useAppSelector } from '../../store/hooks';
import {
ImageTypes,
useGetBlueprintQuery,
useComposeBlueprintMutation,
} from '../../store/imageBuilderApi';
} from '../../store/backendApi';
import { selectSelectedBlueprintId } from '../../store/BlueprintSlice';
import { useAppDispatch, useAppSelector } from '../../store/hooks';
import { ImageTypes } from '../../store/imageBuilderApi';

type BuildImagesButtonPropTypes = {
// default children is 'Build images'
Expand Down
123 changes: 120 additions & 3 deletions src/Components/Blueprints/helpers/onPremToHostedBlueprintMapper.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
BlueprintExportResponse,
Container,
CreateBlueprintRequest,
Directory,
Distributions,
Fdo,
Expand All @@ -20,7 +21,7 @@
description?: string;
packages?: PackagesOnPrem[];
groups?: GroupsPackagesOnPrem[];
distro: Distributions;
distro?: Distributions;
customizations?: CustomizationsOnPrem;
containers?: Container[];
};
Expand Down Expand Up @@ -85,7 +86,7 @@

export type GroupOnPrem = {
name: string;
gid: number;
gid: number | undefined;
};

export type SshKeyOnPrem = {
Expand Down Expand Up @@ -115,7 +116,7 @@
return {
name: blueprint.name,
description: blueprint.description || '',
distribution: blueprint.distro,
distribution: blueprint.distro!,
customizations: {
...blueprint.customizations,
containers: blueprint.containers,
Expand Down Expand Up @@ -176,3 +177,119 @@
},
};
};

export const mapHostedToOnPrem = (
blueprint: CreateBlueprintRequest
): BlueprintOnPrem => {
const result: BlueprintOnPrem = {
name: blueprint.name,
customizations: {},
};

if (blueprint.customizations?.packages) {

Check warning on line 189 in src/Components/Blueprints/helpers/onPremToHostedBlueprintMapper.tsx

View workflow job for this annotation

GitHub Actions / dev-check

Unnecessary optional chain on a non-nullish value
result.packages = blueprint.customizations.packages.map((pkg) => {
return {
name: pkg,
version: '*',
};
});
}

if (blueprint.customizations?.containers) {

Check warning on line 198 in src/Components/Blueprints/helpers/onPremToHostedBlueprintMapper.tsx

View workflow job for this annotation

GitHub Actions / dev-check

Unnecessary optional chain on a non-nullish value
result.containers = blueprint.customizations.containers;
}

if (blueprint.customizations?.directories) {

Check warning on line 202 in src/Components/Blueprints/helpers/onPremToHostedBlueprintMapper.tsx

View workflow job for this annotation

GitHub Actions / dev-check

Unnecessary optional chain on a non-nullish value
result.customizations!.directories = blueprint.customizations.directories;
}

if (blueprint.customizations?.files) {

Check warning on line 206 in src/Components/Blueprints/helpers/onPremToHostedBlueprintMapper.tsx

View workflow job for this annotation

GitHub Actions / dev-check

Unnecessary optional chain on a non-nullish value
result.customizations!.files = blueprint.customizations.files;
}

if (blueprint.customizations?.openscap) {

Check warning on line 210 in src/Components/Blueprints/helpers/onPremToHostedBlueprintMapper.tsx

View workflow job for this annotation

GitHub Actions / dev-check

Unnecessary optional chain on a non-nullish value
result.customizations!.openscap = blueprint.customizations.openscap;
}

if (blueprint.customizations?.filesystem) {

Check warning on line 214 in src/Components/Blueprints/helpers/onPremToHostedBlueprintMapper.tsx

View workflow job for this annotation

GitHub Actions / dev-check

Unnecessary optional chain on a non-nullish value
result.customizations!.filesystem = blueprint.customizations.filesystem.map(
(fs) => {
return {
mountpoint: fs.mountpoint,
minsize: fs.min_size,
};
}
);
}

if (blueprint.customizations?.users) {

Check warning on line 225 in src/Components/Blueprints/helpers/onPremToHostedBlueprintMapper.tsx

View workflow job for this annotation

GitHub Actions / dev-check

Unnecessary optional chain on a non-nullish value
result.customizations!.user = blueprint.customizations.users.map((u) => {
return {
name: u.name,
key: u.ssh_key || '',
};
});
}

if (blueprint.customizations?.services) {

Check warning on line 234 in src/Components/Blueprints/helpers/onPremToHostedBlueprintMapper.tsx

View workflow job for this annotation

GitHub Actions / dev-check

Unnecessary optional chain on a non-nullish value
result.customizations!.services = blueprint.customizations.services;
}

if (blueprint.customizations?.hostname) {
result.customizations!.hostname = blueprint.customizations.hostname;
}

if (blueprint.customizations?.kernel) {
result.customizations!.kernel = blueprint.customizations.kernel;
}

if (blueprint.customizations?.groups) {
result.customizations!.groups = blueprint.customizations.groups.map((g) => {
return {
name: g.name,
gid: g.gid,
};
});
}

if (blueprint.customizations?.timezone) {
result.customizations!.timezone = blueprint.customizations.timezone;
}

if (blueprint.customizations?.locale) {
result.customizations!.locale = blueprint.customizations.locale;
}

if (blueprint.customizations?.firewall) {
result.customizations!.firewall = blueprint.customizations.firewall;
}

if (blueprint.customizations?.installation_device) {
result.customizations!.installation_device =
blueprint.customizations.installation_device;
}

if (blueprint.customizations?.fdo) {
result.customizations!.fdo = blueprint.customizations.fdo;
}

if (blueprint.customizations?.ignition) {
result.customizations!.ignition = blueprint.customizations.ignition;
}

if (blueprint.customizations?.partitioning_mode) {
result.customizations!.partitioning_mode =
blueprint.customizations.partitioning_mode;
}

if (blueprint.customizations?.fips) {
result.customizations!.fips =
blueprint.customizations.fips?.enabled || false;
}

if (blueprint.customizations?.installer) {
result.customizations!.installer = blueprint.customizations.installer;
}

return result;
};
35 changes: 34 additions & 1 deletion src/Components/ImagesTable/ImageDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import { ExternalLinkAltIcon } from '@patternfly/react-icons';

import ClonesTable from './ClonesTable';

import { useGetComposeStatusQuery } from '../../store/backendApi';
import { extractProvisioningList } from '../../store/helpers';
import {
ComposesResponseItem,
GcpUploadRequestOptions,
useGetComposeStatusQuery,
} from '../../store/imageBuilderApi';
import { useGetSourceListQuery } from '../../store/provisioningApi';
import {
Expand Down Expand Up @@ -478,3 +478,36 @@ export const AwsS3Details = ({ compose }: AwsS3DetailsPropTypes) => {
</>
);
};

type LocalDetailsPropTypes = {
compose: ComposesResponseItem;
};

export const LocalDetails = ({ compose }: LocalDetailsPropTypes) => {
return (
<>
<div className="pf-v5-u-font-weight-bold pf-v5-u-pb-md">
Build Information
</div>
<DescriptionList isHorizontal isCompact className=" pf-v5-u-pl-xl">
<DescriptionListGroup>
<DescriptionListTerm>UUID</DescriptionListTerm>
<DescriptionListDescription>
<ClipboardCopy
hoverTip="Copy"
clickTip="Copied"
variant="inline-compact"
ouiaId="other-targets-uuid"
>
{compose.id}
</ClipboardCopy>
</DescriptionListDescription>
<DescriptionListTerm>Architecture</DescriptionListTerm>
<DescriptionListDescription>
{compose.request.image_requests[0].architecture}
</DescriptionListDescription>
</DescriptionListGroup>
</DescriptionList>
</>
);
};
46 changes: 38 additions & 8 deletions src/Components/ImagesTable/ImagesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,18 @@ import {
AwsS3Details,
AzureDetails,
GcpDetails,
LocalDetails,
OciDetails,
} from './ImageDetails';
import ImagesTableToolbar from './ImagesTableToolbar';
import { AwsS3Instance, CloudInstance, OciInstance } from './Instance';
import {
AwsS3Instance,
CloudInstance,
OciInstance,
LocalInstance,
} from './Instance';
import Release from './Release';
import { ExpiringStatus, CloudStatus } from './Status';
import { ExpiringStatus, CloudStatus, LocalStatus } from './Status';
import { AwsTarget, Target } from './Target';

import {
Expand All @@ -49,7 +55,12 @@ import {
SEARCH_INPUT,
STATUS_POLLING_INTERVAL,
} from '../../constants';
import { useGetBlueprintsQuery } from '../../store/backendApi';
import {
useGetComposeStatusQuery,
useGetComposesQuery,
useGetBlueprintsQuery,
useGetBlueprintComposesQuery,
} from '../../store/backendApi';
import {
selectBlueprintSearchInput,
selectBlueprintVersionFilter,
Expand All @@ -66,9 +77,6 @@ import {
ComposeStatus,
GetBlueprintComposesApiArg,
GetBlueprintsApiArg,
useGetBlueprintComposesQuery,
useGetComposesQuery,
useGetComposeStatusQuery,
} from '../../store/imageBuilderApi';
import { resolveRelPath } from '../../Utilities/path';
import {
Expand Down Expand Up @@ -298,9 +306,9 @@ const ImagesTableRow = ({ compose, rowIndex }: ImagesTableRowPropTypes) => {
}
}, [setPollingInterval, composeStatus]);

const type = compose.request.image_requests[0].upload_request.type;
const type = compose.request?.image_requests[0]?.upload_request?.type;

switch (type) {
switch (type as string) {
case 'aws':
return (
<AwsRow
Expand All @@ -317,6 +325,8 @@ const ImagesTableRow = ({ compose, rowIndex }: ImagesTableRowPropTypes) => {
return <OciRow compose={compose} rowIndex={rowIndex} />;
case 'aws.s3':
return <AwsS3Row compose={compose} rowIndex={rowIndex} />;
case 'local':
return <LocalRow compose={compose} rowIndex={rowIndex} />;
}
};

Expand Down Expand Up @@ -458,6 +468,26 @@ const AwsRow = ({ compose, composeStatus, rowIndex }: AwsRowPropTypes) => {
);
};

type LocalRowPropTypes = {
compose: ComposesResponseItem;
rowIndex: number;
};

const LocalRow = ({ compose, rowIndex }: LocalRowPropTypes) => {
const details = <LocalDetails compose={compose} />;
const instance = <LocalInstance compose={compose} />;
const status = <LocalStatus compose={compose} />;
return (
<Row
compose={compose}
rowIndex={rowIndex}
details={details}
instance={instance}
status={status}
/>
);
};

type RowPropTypes = {
compose: ComposesResponseItem;
rowIndex: number;
Expand Down
30 changes: 29 additions & 1 deletion src/Components/ImagesTable/Instance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
SEARCH_INPUT,
} from '../../constants';
import { useGetBlueprintsQuery } from '../../store/backendApi';
import { useGetComposeStatusQuery } from '../../store/backendApi';
import {
selectSelectedBlueprintId,
selectBlueprintSearchInput,
Expand All @@ -37,7 +38,6 @@ import {
ComposesResponseItem,
ComposeStatus,
ImageTypes,
useGetComposeStatusQuery,
} from '../../store/imageBuilderApi';
import {
isAwsUploadRequestOptions,
Expand Down Expand Up @@ -403,3 +403,31 @@ export const AwsS3Instance = ({
);
}
};

type LocalInstancePropTypes = {
compose: ComposesResponseItem;
};

export const LocalInstance = ({ compose }: LocalInstancePropTypes) => {
const { data: composeStatus, isSuccess } = useGetComposeStatusQuery({
composeId: compose.id,
});
if (!isSuccess) {
return <Skeleton />;
}

// Hacky to define the type here, but local upload is not available in
// the image builder api, only in the composer api.
type LocalUploadStatusOptions = {
filename: string;
};
const status = composeStatus?.image_status.status;
const options = composeStatus?.image_status.upload_status
?.options as unknown as LocalUploadStatusOptions;

if (status !== 'success') {
return <></>;
}

return <div>Filepath to disk: {options.filename}</div>;
};
Loading
Loading