1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-25 08:19:40 +02:00

chore(fdo): remove FDO code EE-7235 (#11981)

This commit is contained in:
andres-portainer 2024-06-28 08:42:16 -03:00 committed by GitHub
parent 1a3db327c7
commit 19fa40286a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 3 additions and 2609 deletions

View file

@ -15,7 +15,6 @@ import { EnvironmentStatus } from '../types';
import { columns } from './columns';
import { EnvironmentListItem } from './types';
import { ImportFdoDeviceButton } from './ImportFdoDeviceButton';
const tableKey = 'environments';
const settingsStore = createPersistedStore(tableKey, 'Name');
@ -83,8 +82,6 @@ export function EnvironmentsDatatable({
Remove
</Button>
<ImportFdoDeviceButton />
{isBE && (
<AddButton
color="secondary"

View file

@ -1,32 +0,0 @@
import { AddButton } from '@@/buttons';
import { useSettings } from '../../settings/queries';
import {
FeatureFlag,
useFeatureFlag,
} from '../../feature-flags/useFeatureFlag';
export function ImportFdoDeviceButton() {
const flagEnabledQuery = useFeatureFlag(FeatureFlag.FDO);
const isFDOEnabledQuery = useSettings(
(settings) => settings.fdoConfiguration.enabled,
flagEnabledQuery.data
);
if (!isFDOEnabledQuery.data || !flagEnabledQuery.data) {
return null;
}
return (
<div className="ml-[5px]">
<AddButton
color="secondary"
to="portainer.endpoints.importDevice"
data-cy="import-fdo-device-button"
>
Import FDO device
</AddButton>
</div>
);
}

View file

@ -1,8 +1,6 @@
import { usePublicSettings } from '../settings/queries';
export enum FeatureFlag {
FDO = 'fdo',
}
export enum FeatureFlag {}
export function useFeatureFlag(
flag: FeatureFlag,

View file

@ -1,45 +0,0 @@
import { List } from 'lucide-react';
import { Datatable } from '@@/datatables';
import { createPersistedStore } from '@@/datatables/types';
import { useTableState } from '@@/datatables/useTableState';
import { columns } from './columns';
import { FDOProfilesDatatableActions } from './FDOProfilesDatatableActions';
import { useFDOProfiles } from './useFDOProfiles';
const storageKey = 'fdoProfiles';
const settingsStore = createPersistedStore(storageKey, 'name');
export interface FDOProfilesDatatableProps {
isFDOEnabled: boolean;
}
export function FDOProfilesDatatable({
isFDOEnabled,
}: FDOProfilesDatatableProps) {
const tableState = useTableState(settingsStore, storageKey);
const { isLoading, profiles } = useFDOProfiles();
return (
<Datatable
columns={columns}
dataset={profiles}
settingsManager={tableState}
title="Device Profiles"
titleIcon={List}
disableSelect={!isFDOEnabled}
getRowId={(row) => row.id.toString()}
isLoading={isLoading}
renderTableActions={(selectedItems) => (
<FDOProfilesDatatableActions
isFDOEnabled={isFDOEnabled}
selectedItems={selectedItems}
/>
)}
data-cy="fdo-profiles-datatable"
/>
);
}

View file

@ -1,108 +0,0 @@
import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from '@uirouter/react';
import { PlusCircle } from 'lucide-react';
import { Profile } from '@/portainer/hostmanagement/fdo/model';
import * as notifications from '@/portainer/services/notifications';
import {
deleteProfile,
duplicateProfile,
} from '@/portainer/hostmanagement/fdo/fdo.service';
import { confirm } from '@@/modals/confirm';
import { Link } from '@@/Link';
import { Button } from '@@/buttons';
import { DeleteButton } from '@@/buttons/DeleteButton';
interface Props {
isFDOEnabled: boolean;
selectedItems: Profile[];
}
export function FDOProfilesDatatableActions({
isFDOEnabled,
selectedItems,
}: Props) {
const router = useRouter();
const queryClient = useQueryClient();
return (
<>
<Link
to="portainer.endpoints.profile"
className="space-left"
data-cy="fdo-add-profile-link"
>
<Button
disabled={!isFDOEnabled}
icon={PlusCircle}
data-cy="fdo-add-profile-button"
>
Add Profile
</Button>
</Link>
<Button
disabled={!isFDOEnabled || selectedItems.length !== 1}
data-cy="fdo-duplicate-profile-button"
onClick={() => onDuplicateProfileClick()}
icon={PlusCircle}
>
Duplicate
</Button>
<DeleteButton
disabled={!isFDOEnabled || selectedItems.length === 0}
onConfirmed={() => onDeleteProfileClick()}
confirmMessage="This action will delete the selected profile(s). Continue?"
data-cy="fdo-remove-profile-button"
/>
</>
);
async function onDuplicateProfileClick() {
const confirmed = await confirm({
title: 'Are you sure ?',
message: 'This action will duplicate the selected profile. Continue?',
});
if (!confirmed) {
return;
}
try {
const profile = selectedItems[0];
const newProfile = await duplicateProfile(profile.id);
notifications.success('Profile successfully duplicated', profile.name);
router.stateService.go('portainer.endpoints.profile.edit', {
id: newProfile.id,
});
} catch (err) {
notifications.error(
'Failure',
err as Error,
'Unable to duplicate profile'
);
}
}
async function onDeleteProfileClick() {
await Promise.all(
selectedItems.map(async (profile) => {
try {
await deleteProfile(profile.id);
notifications.success('Profile successfully removed', profile.name);
} catch (err) {
notifications.error(
'Failure',
err as Error,
'Unable to remove profile'
);
}
})
);
await queryClient.invalidateQueries(['fdo_profiles']);
}
}

View file

@ -1,12 +0,0 @@
import { isoDateFromTimestamp } from '@/portainer/filters/filters';
import { columnHelper } from './helper';
export const created = columnHelper.accessor('dateCreated', {
header: 'Created',
id: 'created',
cell: ({ getValue }) => {
const value = getValue();
return isoDateFromTimestamp(value);
},
});

View file

@ -1,5 +0,0 @@
import { createColumnHelper } from '@tanstack/react-table';
import { Profile } from '@/portainer/hostmanagement/fdo/model';
export const columnHelper = createColumnHelper<Profile>();

View file

@ -1,14 +0,0 @@
import { Profile } from '@/portainer/hostmanagement/fdo/model';
import { buildNameColumn } from '@@/datatables/buildNameColumn';
import { created } from './created';
export const columns = [
buildNameColumn<Profile>(
'name',
'portainer.endpoints.profile.edit',
'fdo-profiles-name'
),
created,
];

View file

@ -1 +0,0 @@
export { FDOProfilesDatatable } from './FDOProfilesDatatable';

View file

@ -1,30 +0,0 @@
import { useEffect, useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';
import PortainerError from '@/portainer/error';
import * as notifications from '@/portainer/services/notifications';
import { getProfiles } from '@/portainer/hostmanagement/fdo/fdo.service';
export function useFDOProfiles() {
const { isLoading, data, isError, error } = useQuery(['fdo_profiles'], () =>
getProfiles()
);
useEffect(() => {
if (isError) {
notifications.error(
'Failure',
error as Error,
'Failed retrieving FDO profiles'
);
}
}, [isError, error]);
const profiles = useMemo(() => data || [], [data]);
return {
isLoading,
profiles,
error: isError ? (error as PortainerError) : undefined,
};
}

View file

@ -1,3 +0,0 @@
.fdo-table {
margin-top: 3em;
}

View file

@ -1,212 +0,0 @@
import { useEffect, useState } from 'react';
import { Formik, Field, Form } from 'formik';
import { FlaskConical, Laptop } from 'lucide-react';
import { FDOConfiguration } from '@/portainer/hostmanagement/fdo/model';
import {
FeatureFlag,
useFeatureFlag,
} from '@/react/portainer/feature-flags/useFeatureFlag';
import { Switch } from '@@/form-components/SwitchField/Switch';
import { FormControl } from '@@/form-components/FormControl';
import { FormSectionTitle } from '@@/form-components/FormSectionTitle';
import { Widget, WidgetBody, WidgetTitle } from '@@/Widget';
import { LoadingButton } from '@@/buttons/LoadingButton';
import { TextTip } from '@@/Tip/TextTip';
import { Input } from '@@/form-components/Input';
import { FDOProfilesDatatable } from '../FDOProfilesDatatable';
import styles from './SettingsFDO.module.css';
import { validationSchema } from './SettingsFDO.validation';
export interface Settings {
fdoConfiguration: FDOConfiguration;
EnableEdgeComputeFeatures: boolean;
}
interface Props {
settings: Settings;
onSubmit(values: FDOConfiguration): void;
}
export function SettingsFDO({ settings, onSubmit }: Props) {
const flagEnabledQuery = useFeatureFlag(FeatureFlag.FDO);
if (!flagEnabledQuery.data) {
return (
<Widget>
<Widget.Body>
<TextTip color="blue" icon={FlaskConical}>
Since FDO is still an experimental feature that requires additional
infrastructure, it has been temporarily hidden in the UI.
</TextTip>
</Widget.Body>
</Widget>
);
}
return <SettingsFDOForm settings={settings} onSubmit={onSubmit} />;
}
export function SettingsFDOForm({ settings, onSubmit }: Props) {
const fdoConfiguration = settings ? settings.fdoConfiguration : null;
const initialFDOEnabled = fdoConfiguration ? fdoConfiguration.enabled : false;
const [isFDOEnabled, setIsFDOEnabled] = useState(initialFDOEnabled);
useEffect(() => {
setIsFDOEnabled(settings?.fdoConfiguration?.enabled);
}, [settings]);
const initialValues = {
enabled: initialFDOEnabled,
ownerURL: fdoConfiguration ? fdoConfiguration.ownerURL : '',
ownerUsername: fdoConfiguration ? fdoConfiguration.ownerUsername : '',
ownerPassword: fdoConfiguration ? fdoConfiguration.ownerPassword : '',
};
const edgeComputeFeaturesEnabled = settings
? settings.EnableEdgeComputeFeatures
: false;
return (
<div className="row">
<Widget>
<WidgetTitle icon={Laptop} title="FDO" />
<WidgetBody>
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
enableReinitialize
validationSchema={() => validationSchema()}
validateOnChange
validateOnMount
>
{({
values,
errors,
handleSubmit,
setFieldValue,
isSubmitting,
isValid,
dirty,
}) => (
<Form className="form-horizontal" onSubmit={handleSubmit}>
<FormControl
inputId="edge_enableFDO"
label="Enable FDO Management Service"
size="small"
errors={errors.enabled}
>
<Switch
id="edge_enableFDO"
data-cy="edge-enableFDO-switch"
name="edge_enableFDO"
className="space-right"
disabled={!edgeComputeFeaturesEnabled}
checked={edgeComputeFeaturesEnabled && values.enabled}
onChange={(e) => onChangedEnabled(e, setFieldValue)}
/>
</FormControl>
<TextTip color="blue" className="mb-2">
When enabled, this will allow Portainer to interact with FDO
Services.
</TextTip>
{edgeComputeFeaturesEnabled && values.enabled && (
<>
<hr />
<FormControl
inputId="owner_url"
label="Owner Service Server"
errors={errors.ownerURL}
>
<Field
as={Input}
name="ownerURL"
id="owner_url"
placeholder="http://127.0.0.1:8042"
value={values.ownerURL}
data-cy="fdo-serverInput"
/>
</FormControl>
<FormControl
inputId="owner_username"
label="Owner Service Username"
errors={errors.ownerUsername}
>
<Field
as={Input}
name="ownerUsername"
id="owner_username"
placeholder="username"
value={values.ownerUsername}
data-cy="fdo-usernameInput"
/>
</FormControl>
<FormControl
inputId="owner_password"
label="Owner Service Password"
errors={errors.ownerPassword}
>
<Field
as={Input}
type="password"
name="ownerPassword"
id="owner_password"
placeholder="password"
value={values.ownerPassword}
data-cy="fdo-passwordInput"
/>
</FormControl>
</>
)}
<div className="form-group mt-5">
<div className="col-sm-12">
<LoadingButton
disabled={!isValid || !dirty}
data-cy="settings-fdoButton"
isLoading={isSubmitting}
loadingText="Saving settings..."
>
Save settings
</LoadingButton>
</div>
</div>
</Form>
)}
</Formik>
{edgeComputeFeaturesEnabled && isFDOEnabled && (
<div className={styles.fdoTable}>
<FormSectionTitle>Device Profiles</FormSectionTitle>
<TextTip color="blue" className="mb-2">
Add, Edit and Manage the list of device profiles available
during FDO device setup
</TextTip>
<FDOProfilesDatatable isFDOEnabled={initialFDOEnabled} />
</div>
)}
</WidgetBody>
</Widget>
</div>
);
async function onChangedEnabled(
e: boolean,
setFieldValue: (
field: string,
value: unknown,
shouldValidate?: boolean
) => void
) {
setIsFDOEnabled(e);
setFieldValue('enabled', e);
}
}

View file

@ -1,18 +0,0 @@
import { object, string } from 'yup';
export function validationSchema() {
return object().shape({
ownerURL: string().when('enabled', {
is: true,
then: string().required('Field is required'),
}),
ownerUsername: string().when('enabled', {
is: true,
then: string().required('Field is required'),
}),
ownerPassword: string().when('enabled', {
is: true,
then: string().required('Field is required'),
}),
});
}

View file

@ -1 +0,0 @@
export { SettingsFDO } from './SettingsFDO';

View file

@ -253,7 +253,7 @@ export function SettingsOpenAMT({ settings, onSubmit }: Props) {
<div className="col-sm-12">
<LoadingButton
disabled={!isValid || !dirty}
data-cy="settings-fdoButton"
data-cy="settings-OpenAMTButton"
isLoading={isSubmitting}
loadingText="Saving settings..."
>

View file

@ -1,12 +1,5 @@
import { TeamId } from '@/react/portainer/users/teams/types';
export interface FDOConfiguration {
enabled: boolean;
ownerURL: string;
ownerUsername: string;
ownerPassword: string;
}
export interface TLSConfiguration {
TLS: boolean;
TLSSkipVerify: boolean;
@ -119,7 +112,6 @@ export interface Settings {
LDAPSettings: LDAPSettings;
OAuthSettings: OAuthSettings;
openAMTConfiguration: OpenAMTConfiguration;
fdoConfiguration: FDOConfiguration;
FeatureFlagSettings: { [key: Feature]: boolean };
SnapshotInterval: string;
TemplatesURL: string;
@ -201,8 +193,6 @@ export interface PublicSettingsResponse {
KubeconfigExpiry: string;
/** Whether team sync is enabled */
TeamSync: boolean;
/** Whether FDO is enabled */
IsFDOEnabled: boolean;
/** Whether AMT is enabled */
IsAMTEnabled: boolean;
/** Whether to hide default registry (only on BE) */