Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions libs/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -967,12 +967,12 @@
"This device uses package-based OS management. System image configuration is not available for this device.": "This device uses package-based OS management. System image configuration is not available for this device.",
"System image is managed by Software Catalog": "System image is managed by Software Catalog",
"Must be a reference to a bootable container image (such as \"quay.io/<my-org>/my-rhel-with-fc-agent:<version>\"). If you do not want to manage your OS from Edge management, leave this field empty.": "Must be a reference to a bootable container image (such as \"quay.io/<my-org>/my-rhel-with-fc-agent:<version>\"). If you do not want to manage your OS from Edge management, leave this field empty.",
"Use basic configurations": "Use basic configurations",
"Advanced configurations": "Advanced configurations",
"Update policies": "Update policies",
"Update policies allow you to control when updates should be downloaded and applied.": "Update policies allow you to control when updates should be downloaded and applied.",
"Default update policy": "Default update policy",
"The device will download and apply updates as soon as they are available.": "The device will download and apply updates as soon as they are available.",
"Choose how updates are delivered to this device.": "Choose how updates are delivered to this device.",
"Update behavior": "Update behavior",
"Immediate updates": "Immediate updates",
"Devices receive updates as soon as they are available.": "Devices receive updates as soon as they are available.",
"Customize maintenance window and scheduling": "Customize maintenance window and scheduling",
"Set maintenance windows to control when updates are downloaded and applied.": "Set maintenance windows to control when updates are downloaded and applied.",
"Device alias": "Device alias",
"Device labels": "Device labels",
"Unnamed": "Unnamed",
Expand Down Expand Up @@ -1098,12 +1098,16 @@
"Device selector": "Device selector",
"Rollout policy": "Rollout policy",
"Disruption budget": "Disruption budget",
"Set rollout policies": "Set rollout policies",
"Rollout policies allow you to control the order of updates for the fleet devices.": "Rollout policies allow you to control the order of updates for the fleet devices.",
"Customize updates": "Customize updates",
"Maintenance windows": "Maintenance windows",
"Set rollout order": "Set rollout order",
"Rollout order controls in what sequence fleet devices are updated.": "Rollout order controls in what sequence fleet devices are updated.",
"Set disruption budget": "Set disruption budget",
"Disruption budget allows you to limit the number of similar devices that may be updating simultaneously.": "Disruption budget allows you to limit the number of similar devices that may be updating simultaneously.",
"Set update policies": "Set update policies",
"All the devices that are part of this fleet will receive updates as soon as they are available.": "All the devices that are part of this fleet will receive updates as soon as they are available.",
"Set maintenance windows": "Set maintenance windows",
"Maintenance windows control when devices may download and install updates.": "Maintenance windows control when devices may download and install updates.",
"Choose how updates are delivered to devices in this fleet.": "Choose how updates are delivered to devices in this fleet.",
"Set rollout order, disruption budget, or maintenance windows.": "Set rollout order, disruption budget, or maintenance windows.",
"Group devices by label keys": "Group devices by label keys",
"The disruption budget will be applied to all group combinations independently.": "The disruption budget will be applied to all group combinations independently.",
"Add label key": "Add label key",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {

import { type Device } from '@flightctl/types';
import { getUpdatePolicyValues } from '../../Fleet/CreateFleet/fleetSpecUtils';
import { type EditDeviceFormValues } from './../../../types/deviceSpec';
import { type EditDeviceFormValues, UpdateMode } from './../../../types/deviceSpec';
import { getErrorMessage } from '../../../utils/error';
import { fromAPILabel } from '../../../utils/labels';
import { getEditDisabledReason } from '../../../utils/devices';
Expand Down Expand Up @@ -111,11 +111,8 @@ const EditDeviceWizard = () => {
applications: getApplicationValues(device.spec),
systemdUnits: getSystemdUnitsValues(device.spec),
registerMicroShift,
updatePolicy: {
...updatePolicyValues,
isAdvanced: true,
},
useBasicUpdateConfig: !updatePolicyValues.isAdvanced,
updatePolicy: updatePolicyValues,
updateMode: updatePolicyValues.isCustomized ? UpdateMode.Customized : UpdateMode.Default,
}}
validationSchema={getValidationSchema(t)}
validateOnMount
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import * as React from 'react';
import { Alert, Title } from '@patternfly/react-core';
import { FormGroup, Stack, StackItem, Title } from '@patternfly/react-core';
import { type FormikErrors, useFormikContext } from 'formik';

import { useTranslation } from '../../../../hooks/useTranslation';
import UpdateStepUpdatePolicy from '../../../Fleet/CreateFleet/steps/UpdateStepUpdatePolicy';
import { CustomizedUpdatesSectionBody } from '../../../Fleet/CreateFleet/steps/UpdatePolicyStep';

import FlightCtlForm from '../../../form/FlightCtlForm';
import { type DeviceSpecConfigFormValues } from '../../../../types/deviceSpec';
import { FormGroupWithHelperText } from '../../../common/WithHelperText';
import CheckboxField from '../../../form/CheckboxField';
import { type DeviceSpecConfigFormValues, UpdateMode } from '../../../../types/deviceSpec';
import RadioField from '../../../form/RadioField';
import { DefaultHelperText } from '../../../form/FieldHelperText';

export const deviceUpdatePolicyStepId = 'update-policy';

Expand All @@ -18,27 +19,44 @@ const UpdatePolicyStep = ({ isReadOnly }: { isReadOnly?: boolean }) => {
const { t } = useTranslation();

const {
values: { useBasicUpdateConfig },
values: { updateMode },
} = useFormikContext<DeviceSpecConfigFormValues>();

return (
<FlightCtlForm>
<CheckboxField name="useBasicUpdateConfig" label={t('Use basic configurations')} isDisabled={isReadOnly} />
{!useBasicUpdateConfig ? (
<>
<Title headingLevel="h3">{t('Advanced configurations')}</Title>
<FormGroupWithHelperText
label={t('Update policies')}
content={t('Update policies allow you to control when updates should be downloaded and applied.')}
>
<UpdateStepUpdatePolicy isReadOnly={isReadOnly} />
</FormGroupWithHelperText>
</>
) : (
<Alert isInline variant="info" title={t('Default update policy')}>
{t('The device will download and apply updates as soon as they are available.')}
</Alert>
)}
<Stack hasGutter>
<StackItem>
<Title headingLevel="h2" size="xl">
{t('Updates')}
</Title>
<DefaultHelperText helperText={t('Choose how updates are delivered to this device.')} />
</StackItem>
<StackItem>
<FormGroup label={t('Update behavior')} role="radiogroup" isStack>
<RadioField
id="device-update-defaults"
name="updateMode"
label={t('Immediate updates')}
description={t('Devices receive updates as soon as they are available.')}
checkedValue={UpdateMode.Default}
isDisabled={isReadOnly}
/>
<RadioField
id="device-update-customized"
name="updateMode"
label={t('Customize maintenance window and scheduling')}
description={t('Set maintenance windows to control when updates are downloaded and applied.')}
checkedValue={UpdateMode.Customized}
isDisabled={isReadOnly}
body={
<CustomizedUpdatesSectionBody updateMode={updateMode} isFleet={false}>
<UpdateStepUpdatePolicy isReadOnly={isReadOnly} />
</CustomizedUpdatesSectionBody>
}
/>
</FormGroup>
</StackItem>
</Stack>
</FlightCtlForm>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import LabelsView from '../../../common/LabelsView';
export const ReviewUpdateRolloutPolicy = ({ rolloutPolicy }: { rolloutPolicy: RolloutPolicyForm }) => {
const { t } = useTranslation();

return rolloutPolicy.isAdvanced
return rolloutPolicy.isCustomized
? t('{{ count }} batches have been defined', { count: rolloutPolicy.batches.length })
: '-';
};

export const ReviewUpdateDisruptionBudget = ({ disruptionBudget }: { disruptionBudget: DisruptionBudgetForm }) => {
const { t } = useTranslation();
if (!disruptionBudget.isAdvanced) {
if (!disruptionBudget.isCustomized) {
return '-';
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '../../form/validations';
import { getDeviceLabelPatches, getStringListPatches, getUpdatePolicyPatches } from '../../../utils/patch';
import { type Device, type PatchRequest } from '@flightctl/types';
import { type EditDeviceFormValues, type UpdatePolicyForm } from './../../../types/deviceSpec';
import { type EditDeviceFormValues, UpdateMode, type UpdatePolicyForm } from './../../../types/deviceSpec';
import {
ACMCrdConfig,
ACMImportConfig,
Expand All @@ -30,8 +30,7 @@ export const getValidationSchema = (t: TFunction) =>
labels: validLabelsSchema(t),
configTemplates: validConfigTemplatesSchema(t),
applications: validApplicationsSchema(t),
updatePolicy:
!values.useBasicUpdateConfig && values.updatePolicy.isAdvanced ? validUpdatePolicySchema(t) : Yup.object(),
updatePolicy: values.updateMode === UpdateMode.Customized ? validUpdatePolicySchema(t) : Yup.object(),
}),
);

Expand Down Expand Up @@ -78,7 +77,7 @@ export const getDevicePatches = (currentDevice: Device, updatedDevice: EditDevic
// Updates
const updatesPatches = getUpdatePolicyPatches('/spec/updatePolicy', currentDevice.spec?.updatePolicy, {
...updatedDevice.updatePolicy,
isAdvanced: !updatedDevice.useBasicUpdateConfig,
isCustomized: updatedDevice.updateMode === UpdateMode.Customized,
} as Required<UpdatePolicyForm>);
allPatches = allPatches.concat(updatesPatches);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const getRolloutPolicyValues = (fleetSpec?: FleetSpec): RolloutPolicyForm
// If the policy does not specify the timeout, we set the backend's default as the field is required in the UI
const updateTimeout = fleetSpec?.rolloutPolicy?.defaultUpdateTimeout || `${DEFAULT_BACKEND_UPDATE_TIMEOUT_MINUTES}m`;
return {
isAdvanced: batches.length > 0,
isCustomized: batches.length > 0,
batches: batches.length ? batches : [getEmptyInitializedBatch()],
updateTimeout: timeUtils.durationToMinutes(updateTimeout),
};
Expand All @@ -50,7 +50,7 @@ export const getDisruptionBudgetValues = (fleetSpec?: FleetSpec) => {
const budget = fleetSpec?.rolloutPolicy?.disruptionBudget || {};
const groupLabels = budget.groupBy || [];
return {
isAdvanced: Boolean(groupLabels.length > 0 || budget.minAvailable || budget.maxUnavailable),
isCustomized: Boolean(groupLabels.length > 0 || budget.minAvailable || budget.maxUnavailable),
groupBy: groupLabels,
minAvailable: budget.minAvailable,
maxUnavailable: budget.maxUnavailable,
Expand All @@ -72,7 +72,7 @@ export const getUpdatePolicyValues = (updateSpec?: DeviceUpdatePolicySpec): Upda
: updateSpec?.updateSchedule?.startGraceDuration;

return {
isAdvanced: Boolean(updateSpec?.downloadSchedule?.at || updateSpec?.updateSchedule?.at),
isCustomized: Boolean(updateSpec?.downloadSchedule?.at || updateSpec?.updateSchedule?.at),
downloadAndInstallDiffer: !isEqual,
downloadStartsAt,
downloadEndsAt: timeUtils.getEndTime(downloadStartsAt, downloadStartGraceDuration),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { useFormikContext } from 'formik';

import { useTranslation } from '../../../../hooks/useTranslation';
import { type FleetFormValues } from '../../../../types/deviceSpec';
import { type FleetFormValues, UpdateMode } from '../../../../types/deviceSpec';
import LabelsView from '../../../common/LabelsView';
import { toAPILabel } from '../../../../utils/labels';
import RepositorySourceList from '../../../Repository/RepositoryDetails/RepositorySourceList';
Expand Down Expand Up @@ -88,17 +88,17 @@ const ReviewStep = ({ error }: { error?: unknown }) => {
</DescriptionListDescription>
</DescriptionListGroup>
)}
{!values.useBasicUpdateConfig && (
{values.updateMode === UpdateMode.Customized && (
<>
{values.rolloutPolicy.isAdvanced && (
{values.rolloutPolicy.isCustomized && (
<DescriptionListGroup>
<DescriptionListTerm>{t('Rollout policy')}</DescriptionListTerm>
<DescriptionListDescription>
<ReviewUpdateRolloutPolicy rolloutPolicy={values.rolloutPolicy} />
</DescriptionListDescription>
</DescriptionListGroup>
)}
{values.disruptionBudget.isAdvanced && (
{values.disruptionBudget.isCustomized && (
<DescriptionListGroup>
<DescriptionListTerm>{t('Disruption budget')}</DescriptionListTerm>
<DescriptionListDescription>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.fctl-update-policy--advanced .pf-v6-c-check {
/* Prevents Patternfly from moving these checkboxes too high relative to the center of their label */
--pf-v6-c-check__input--TranslateY: 0.7rem;
.fctl-update-policy--customize-options {
padding-inline-start: var(--pf-t--global--spacer--md);
border-inline-start: var(--pf-t--global--border--width--control--default) solid
var(--pf-t--global--border--color--default);
}
Loading
Loading