Skip to content
Merged
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
122 changes: 57 additions & 65 deletions frontend/packages/console-app/src/actions/creators/hpa-factory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useMemo } from 'react';
import i18next from 'i18next';
import type { Action } from '@console/dynamic-plugin-sdk';
import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
import { HorizontalPodAutoscalerModel } from '@console/internal/models';
import type {
Expand All @@ -12,84 +13,23 @@ import type {
import { referenceForModel } from '@console/internal/module/k8s';
import type { ClusterServiceVersionKind } from '@console/operator-lifecycle-manager';
import { ClusterServiceVersionModel } from '@console/operator-lifecycle-manager';
import deleteHPAModal from '@console/shared/src/components/hpa/DeleteHPAModal';
import { LazyDeleteHPAModalOverlay } from '@console/shared/src/components/hpa';
import { isHelmResource } from '@console/shared/src/utils/helm-utils';
import { doesHpaMatch } from '@console/shared/src/utils/hpa-utils';
import { isOperatorBackedService } from '@console/shared/src/utils/operator-utils';
import type { ResourceActionFactory } from './types';

const hpaRoute = (
{ metadata: { name = '', namespace = '' } = {} }: K8sResourceCommon,
kind: K8sKind,
) => `/workload-hpa/ns/${namespace}/${referenceForModel(kind)}/${name}`;

export const HpaActionFactory: ResourceActionFactory = {
AddHorizontalPodAutoScaler: (kind: K8sKind, obj: K8sResourceKind) => ({
id: 'add-hpa',
label: i18next.t('console-app~Add HorizontalPodAutoscaler'),
cta: { href: hpaRoute(obj, kind) },
insertBefore: 'add-pdb',
accessReview: {
group: HorizontalPodAutoscalerModel.apiGroup,
resource: HorizontalPodAutoscalerModel.plural,
namespace: obj.metadata?.namespace,
verb: 'create',
},
}),
EditHorizontalPodAutoScaler: (kind: K8sKind, obj: K8sResourceCommon) => ({
id: 'edit-hpa',
label: i18next.t('console-app~Edit HorizontalPodAutoscaler'),
cta: { href: hpaRoute(obj, kind) },
insertBefore: 'add-pdb',
accessReview: {
group: HorizontalPodAutoscalerModel.apiGroup,
resource: HorizontalPodAutoscalerModel.plural,
namespace: obj.metadata?.namespace,
verb: 'update',
},
}),
DeleteHorizontalPodAutoScaler: (
kind: K8sKind,
obj: K8sResourceCommon,
relatedHPA: HorizontalPodAutoscalerKind,
) => ({
id: 'delete-hpa',
label: i18next.t('console-app~Remove HorizontalPodAutoscaler'),
insertBefore: 'delete-pdb',
cta: () => {
deleteHPAModal({
workload: obj,
hpa: relatedHPA,
});
},
accessReview: {
group: HorizontalPodAutoscalerModel.apiGroup,
resource: HorizontalPodAutoscalerModel.plural,
namespace: obj.metadata?.namespace,
verb: 'delete',
},
}),
};

export const getHpaActions = (
kind: K8sKind,
obj: K8sResourceKind,
relatedHPAs: K8sResourceKind[],
): Action[] => {
if (relatedHPAs.length === 0) return [HpaActionFactory.AddHorizontalPodAutoScaler(kind, obj)];

return [
HpaActionFactory.EditHorizontalPodAutoScaler(kind, obj),
HpaActionFactory.DeleteHorizontalPodAutoScaler(kind, obj, relatedHPAs[0]),
];
};

type DeploymentActionExtraResources = {
hpas: HorizontalPodAutoscalerKind[];
csvs: ClusterServiceVersionKind[];
};

export const useHPAActions = (kindObj: K8sKind, resource: K8sResourceKind) => {
const launchModal = useOverlay();
const namespace = resource?.metadata?.namespace;

const watchedResources = useMemo(
Expand Down Expand Up @@ -121,9 +61,61 @@ export const useHPAActions = (kindObj: K8sKind, resource: K8sResourceKind) => {
[extraResources.csvs.data, resource],
);

const actions = useMemo<Action[]>(() => {
if (!supportsHPA) return [];

if (relatedHPAs.length === 0) {
return [
{
id: 'add-hpa',
label: i18next.t('console-app~Add HorizontalPodAutoscaler'),
cta: { href: hpaRoute(resource, kindObj) },
insertBefore: 'add-pdb',
accessReview: {
group: HorizontalPodAutoscalerModel.apiGroup,
resource: HorizontalPodAutoscalerModel.plural,
namespace: resource.metadata?.namespace,
verb: 'create',
},
},
];
}
return [
{
id: 'edit-hpa',
label: i18next.t('console-app~Edit HorizontalPodAutoscaler'),
cta: { href: hpaRoute(resource, kindObj) },
insertBefore: 'add-pdb',
accessReview: {
group: HorizontalPodAutoscalerModel.apiGroup,
resource: HorizontalPodAutoscalerModel.plural,
namespace: resource.metadata?.namespace,
verb: 'update',
},
},
{
id: 'delete-hpa',
label: i18next.t('console-app~Remove HorizontalPodAutoscaler'),
insertBefore: 'delete-pdb',
cta: () => {
launchModal(LazyDeleteHPAModalOverlay, {
workload: resource,
hpa: relatedHPAs[0],
});
},
accessReview: {
group: HorizontalPodAutoscalerModel.apiGroup,
resource: HorizontalPodAutoscalerModel.plural,
namespace: resource.metadata?.namespace,
verb: 'delete',
},
},
];
}, [kindObj, launchModal, relatedHPAs, resource, supportsHPA]);

const result = useMemo<[Action[], HorizontalPodAutoscalerKind[]]>(() => {
return [supportsHPA ? getHpaActions(kindObj, resource, relatedHPAs) : [], relatedHPAs];
}, [kindObj, relatedHPAs, resource, supportsHPA]);
return [actions, relatedHPAs];
}, [actions, relatedHPAs]);

return result;
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Link } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import type { WatchK8sResource } from '@console/dynamic-plugin-sdk';
import { useAccessReview } from '@console/dynamic-plugin-sdk';
import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import {
getGroupVersionKindForModel,
getReferenceForModel,
Expand All @@ -35,7 +36,7 @@ import { referenceForModel } from '@console/internal/module/k8s';
import type { RootState } from '@console/internal/redux';
import { usePluginInfo } from '@console/plugin-sdk/src/api/usePluginInfo';
import PaneBody from '@console/shared/src/components/layout/PaneBody';
import { consolePluginModal } from '@console/shared/src/components/modals/ConsolePluginModal';
import { LazyConsolePluginModalOverlay } from '@console/shared/src/components/modals';
import {
GreenCheckCircleIcon,
YellowExclamationTriangleIcon,
Expand Down Expand Up @@ -102,6 +103,7 @@ export const ConsolePluginEnabledStatus: FC<ConsolePluginEnabledStatusProps> = (
enabled,
}) => {
const { t } = useTranslation('console-app');
const launchModal = useOverlay();

const {
consoleOperatorConfig,
Expand All @@ -121,7 +123,7 @@ export const ConsolePluginEnabledStatus: FC<ConsolePluginEnabledStatusProps> = (
type="button"
isInline
onClick={() =>
consolePluginModal({
launchModal(LazyConsolePluginModalOverlay, {
consoleOperatorConfig,
pluginName,
trusted: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,20 @@ import { Form } from '@patternfly/react-core';
import { ExclamationTriangleIcon } from '@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon';
import { t_global_icon_color_status_warning_default as warningColor } from '@patternfly/react-tokens';
import { useTranslation } from 'react-i18next';
import type { OverlayComponent } from '@console/dynamic-plugin-sdk/src/app/modal-support/OverlayProvider';
import type { ModalComponentProps } from '@console/internal/components/factory/modal';
import {
createModalLauncher,
ModalBody,
ModalSubmitFooter,
ModalTitle,
ModalWrapper,
} from '@console/internal/components/factory/modal';
import { LoadingInline } from '@console/internal/components/utils/status-box';
import { HorizontalPodAutoscalerModel } from '@console/internal/models';
import type { HorizontalPodAutoscalerKind, K8sResourceCommon } from '@console/internal/module/k8s';
import { k8sKill } from '@console/internal/module/k8s';

type DeleteHPAModalProps = ModalComponentProps & {
hpa: HorizontalPodAutoscalerKind;
workload: K8sResourceCommon;
};

const DeleteHPAModal: FC<DeleteHPAModalProps> = ({ close, hpa, workload }) => {
const DeleteHPAModal: FC<DeleteHPAModalProps> = ({ close, cancel, hpa, workload }) => {
const [submitError, setSubmitError] = useState<string>(null);
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
const { t } = useTranslation();
Expand Down Expand Up @@ -79,11 +75,27 @@ const DeleteHPAModal: FC<DeleteHPAModalProps> = ({ close, hpa, workload }) => {
submitText={t('console-shared~Remove')}
submitDanger
submitDisabled={!!submitError}
cancel={close}
cancel={cancel}
/>
</div>
</Form>
);
};

export default createModalLauncher(DeleteHPAModal);
export const DeleteHPAModalOverlay: OverlayComponent<DeleteHPAModalProps> = (props) => {
return (
<ModalWrapper blocking onClose={props.closeOverlay}>
<DeleteHPAModal
close={props.closeOverlay}
cancel={props.closeOverlay}
hpa={props.hpa}
workload={props.workload}
/>
</ModalWrapper>
);
};

type DeleteHPAModalProps = ModalComponentProps & {
hpa: HorizontalPodAutoscalerKind;
workload: K8sResourceCommon;
};
11 changes: 10 additions & 1 deletion frontend/packages/console-shared/src/components/hpa/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
export { default as deleteHPAModal } from './DeleteHPAModal';
import { lazy } from 'react';

export { DeleteHPAModalOverlay } from './DeleteHPAModal';

// Lazy-loaded OverlayComponent for DeleteHPAModal
export const LazyDeleteHPAModalOverlay = lazy(() =>
import('./DeleteHPAModal' /* webpackChunkName: "delete-hpa-modal" */).then((m) => ({
default: m.DeleteHPAModalOverlay,
})),
);
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useState } from 'react';
import { Form } from '@patternfly/react-core';
import { useTranslation } from 'react-i18next';
import type { OverlayComponent } from '@console/dynamic-plugin-sdk/src/app/modal-support/OverlayProvider';
import type { ModalComponentProps } from '@console/internal/components/factory/modal';
import {
createModalLauncher,
ModalTitle,
ModalBody,
ModalSubmitFooter,
ModalWrapper,
} from '@console/internal/components/factory/modal';
import { ConsoleOperatorConfigModel } from '@console/internal/models';
import type { K8sResourceKind } from '@console/internal/module/k8s';
Expand Down Expand Up @@ -49,19 +50,17 @@ export const ConsolePluginModal = (props: ConsolePluginModalProps) => {
'console-shared~This console plugin provides a custom interface that can be included in the console. Updating the enablement of this console plugin will prompt for the console to be refreshed once it has been updated. Make sure you trust this console plugin before enabling.',
)}
</p>
<Form>
<ConsolePluginRadioInputs
autofocus
name={pluginName}
enabled={enabled}
onChange={setEnabled}
/>
<ConsolePluginWarning
previouslyEnabled={previouslyEnabled}
enabled={enabled}
trusted={trusted}
/>
</Form>
<ConsolePluginRadioInputs
autofocus
name={pluginName}
enabled={enabled}
onChange={setEnabled}
/>
<ConsolePluginWarning
previouslyEnabled={previouslyEnabled}
enabled={enabled}
trusted={trusted}
/>
</ModalBody>
<ModalSubmitFooter
errorMessage={errorMessage}
Expand All @@ -74,13 +73,24 @@ export const ConsolePluginModal = (props: ConsolePluginModalProps) => {
);
};

export const consolePluginModal = createModalLauncher(ConsolePluginModal);
export const ConsolePluginModalOverlay: OverlayComponent<ConsolePluginModalProps> = (props) => {
return (
<ModalWrapper blocking onClose={props.closeOverlay}>
<ConsolePluginModal
close={props.closeOverlay}
cancel={props.closeOverlay}
consoleOperatorConfig={props.consoleOperatorConfig}
csvPluginsCount={props.csvPluginsCount}
pluginName={props.pluginName}
trusted={props.trusted}
/>
</ModalWrapper>
);
};

export type ConsolePluginModalProps = {
consoleOperatorConfig: K8sResourceKind;
csvPluginsCount?: number;
pluginName: string;
trusted: boolean;
cancel?: () => void;
close?: () => void;
};
} & ModalComponentProps;
12 changes: 8 additions & 4 deletions frontend/packages/console-shared/src/components/modals/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
export const consolePluginModal = (props) =>
import('./ConsolePluginModal' /* webpackChunkName: "shared-modals" */).then((m) =>
m.consolePluginModal(props),
);
import { lazy } from 'react';

// Lazy-loaded OverlayComponent for ConsolePluginModal
export const LazyConsolePluginModalOverlay = lazy(() =>
import('./ConsolePluginModal' /* webpackChunkName: "shared-modals" */).then((m) => ({
default: m.ConsolePluginModalOverlay,
})),
);

export const deleteResourceModal = (props) =>
import('./DeleteResourceModal' /* webpackChunkName: "shared-modals" */).then((m) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
useAccessReviewAllowed,
useAccessReview,
} from '@console/dynamic-plugin-sdk';
import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import { getGroupVersionKindForModel } from '@console/dynamic-plugin-sdk/src/lib-core';
import { Conditions, ConditionTypes } from '@console/internal/components/conditions';
import { ResourceEventStream } from '@console/internal/components/events';
Expand Down Expand Up @@ -66,7 +67,7 @@ import { DocumentTitle } from '@console/shared/src/components/document-title/Doc
import { withFallback } from '@console/shared/src/components/error';
import PaneBody from '@console/shared/src/components/layout/PaneBody';
import { ExternalLink } from '@console/shared/src/components/links/ExternalLink';
import { consolePluginModal } from '@console/shared/src/components/modals';
import { LazyConsolePluginModalOverlay } from '@console/shared/src/components/modals';
import { RedExclamationCircleIcon } from '@console/shared/src/components/status/icons';
import { CONSOLE_OPERATOR_CONFIG_NAME } from '@console/shared/src/constants';
import { useActiveNamespace } from '@console/shared/src/hooks/redux-selectors';
Expand Down Expand Up @@ -235,6 +236,7 @@ const ConsolePlugins: FC<ConsolePluginsProps> = ({ csvPlugins, trusted }) => {
};
const [consoleOperatorConfig] = useK8sWatchResource<K8sResourceKind>(console);
const { t } = useTranslation();
const launchModal = useOverlay();
const [canPatchConsoleOperatorConfig] = useAccessReview({
group: ConsoleOperatorConfigModel.apiGroup,
resource: ConsoleOperatorConfigModel.plural,
Expand Down Expand Up @@ -262,8 +264,9 @@ const ConsolePlugins: FC<ConsolePluginsProps> = ({ csvPlugins, trusted }) => {
type="button"
isInline
onClick={() =>
consolePluginModal({
launchModal(LazyConsolePluginModalOverlay, {
consoleOperatorConfig,
csvPluginsCount,
pluginName,
trusted,
})
Expand Down