Skip to content

CONSOLE-4580: Refactor PVCActionFactory to hook form. #15078

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
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
21 changes: 21 additions & 0 deletions frontend/packages/console-app/console-extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,27 @@
}
}
},
{
"type": "console.action/resource-provider",
"properties": {
"model": {
"version": "v1",
"kind": "PersistentVolumeClaim"
},
"provider": { "$codeRef": "persistentVolumeClaimsProvider.usePVCActionsProvider" }
}
},
{
"type": "console.action/resource-provider",
"properties": {
"model": {
"version": "v1",
"kind": "VolumeSnapshot",
"group": "snapshot.storage.k8s.io"
},
"provider": { "$codeRef": "volumeSnapshotProvider.useVolumeSnapshotActionsProvider" }
}
},
{
"type": "console.action/resource-provider",
"properties": {
Expand Down
4 changes: 2 additions & 2 deletions frontend/packages/console-app/locales/en/console-app.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,13 @@
"Create snapshot": "Create snapshot",
"PVC is not Bound": "PVC is not Bound",
"Clone PVC": "Clone PVC",
"Restore as new PVC": "Restore as new PVC",
"Volume Snapshot is not Ready": "Volume Snapshot is not Ready",
"Rollback": "Rollback",
"Cancel rollout": "Cancel rollout",
"Are you sure you want to cancel this rollout?": "Are you sure you want to cancel this rollout?",
"Yes, cancel": "Yes, cancel",
"No, don't cancel": "No, don't cancel",
"Restore as new PVC": "Restore as new PVC",
"Volume Snapshot is not Ready": "Volume Snapshot is not Ready",
"Retry rollout": "Retry rollout",
"This action is only enabled when the latest revision of the ReplicationController resource is in a failed state.": "This action is only enabled when the latest revision of the ReplicationController resource is in a failed state.",
"Current default StorageClass": "Current default StorageClass",
Expand Down
2 changes: 2 additions & 0 deletions frontend/packages/console-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
"storageClassProvider": "src/actions/providers/storageclass-provider.ts",
"replicaSetProvider": "src/actions/providers/replicaset-provider.ts",
"replicationControllersProvider": "src/actions/providers/replication-controllers-provider.ts",
"persistentVolumeClaimsProvider": "src/actions/providers/persistent-volume-claim-provider.ts",
"volumeSnapshotProvider": "src/actions/providers/volume-snaphot-provider.ts",
"podProvider": "src/actions/providers/pod-provider.ts",
"perspectiveStateProvider": "src/actions/providers/perspective-state-provider.ts",
"ClusterConfigurationPage": "src/components/cluster-configuration/ClusterConfigurationPage.tsx",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,7 @@ import {
} from '@console/internal/components/modals';
import { resourceObjPath, asAccessReview } from '@console/internal/components/utils';
import { referenceForModel, K8sKind, K8sResourceKind } from '@console/internal/module/k8s';

export type ResourceActionCreator = (
kind: K8sKind,
obj: K8sResourceKind,
relatedResource?: K8sResourceKind,
message?: JSX.Element,
) => Action;

export type ResourceActionFactory = { [name: string]: ResourceActionCreator };
import { ResourceActionFactory } from './types';

export const CommonActionFactory: ResourceActionFactory = {
Delete: (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
JobKind,
referenceFor,
} from '@console/internal/module/k8s';
import { ResourceActionFactory } from './common-factory';
import { ResourceActionFactory } from './types';

const startJob = (obj: CronJobKind): Promise<JobKind> => {
const reqPayload = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
referenceForModel,
} from '@console/internal/module/k8s';
import { resourceLimitsModal } from '../../components/modals/resource-limits';
import { ResourceActionFactory } from './common-factory';
import { ResourceActionFactory } from './types';

const deploymentConfigRollout = (dc: K8sResourceKind): Promise<K8sResourceKind> => {
const req = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import i18next from 'i18next';
import * as _ from 'lodash';
import { Action } from '@console/dynamic-plugin-sdk';
import { K8sResourceKind, K8sKind, referenceFor } from '@console/internal/module/k8s';
import { ResourceActionFactory } from './common-factory';
import { ResourceActionFactory } from './types';

const healthChecksAdded = (resource: K8sResourceKind): boolean => {
const containers = resource?.spec?.template?.spec?.containers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from '@console/operator-lifecycle-manager';
import { deleteHPAModal, isHelmResource, isOperatorBackedService } from '@console/shared';
import { doesHpaMatch } from '@console/shared/src/utils/hpa-utils';
import { ResourceActionFactory } from './common-factory';
import { ResourceActionFactory } from './types';

const hpaRoute = ({ metadata: { name, namespace } }: K8sResourceCommon, kind: K8sKind) =>
`/workload-hpa/ns/${namespace}/${referenceForModel(kind)}/${name}`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import i18next from 'i18next';
import { configureJobParallelismModal } from '@console/internal/components/modals';
import { JobKind, K8sKind } from '@console/internal/module/k8s';
import { ResourceActionFactory } from './common-factory';
import { ResourceActionFactory } from './types';

export const JobActionFactory: ResourceActionFactory = {
ModifyJobParallelism: (kind: K8sKind, obj: JobKind) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { deletePDBModal } from '../../components/pdb/modals';
import { PodDisruptionBudgetKind } from '../../components/pdb/types';
import { getPDBResource } from '../../components/pdb/utils/get-pdb-resources';
import { PodDisruptionBudgetModel } from '../../models';
import { ResourceActionFactory } from './common-factory';
import { ResourceActionFactory } from './types';

const pdbRoute = ({ metadata: { name, namespace } }: K8sResourceCommon, kindObj: K8sKind) =>
`/k8s/ns/${namespace}/${referenceForModel(kindObj)}/form?name=${name}`;
Expand Down
57 changes: 0 additions & 57 deletions frontend/packages/console-app/src/actions/creators/pvc-factory.ts

This file was deleted.

107 changes: 107 additions & 0 deletions frontend/packages/console-app/src/actions/creators/pvc-kit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import * as React from 'react';
import { isEqual } from 'lodash';
import { useTranslation } from 'react-i18next';
import { Action } from '@console/dynamic-plugin-sdk';
import { clonePVCModal, expandPVCModal } from '@console/internal/components/modals';
import deletePVCModal from '@console/internal/components/modals/delete-pvc-modal';
import { asAccessReview } from '@console/internal/components/utils';
import { VolumeSnapshotModel } from '@console/internal/models';
import { PersistentVolumeClaimKind, K8sModel } from '@console/internal/module/k8s';
import { ResourceActionsKit, PVCActionCreator, ResourceActionFactory } from './types';

/**
* A React hook for creating actions related to a PersistentVolumeClaim (PVC).
*
* @param {K8sModel} kind - The K8s model for the PersistentVolumeClaim.
* @param {PersistentVolumeClaimKind} obj - The specific PVC resource instance for which to generate actions.
* @param {PVCActionCreator[]} [actionCreators] - Optional. If provided, the returned `actions` array will contain
* only the specified actions. If omitted, it will contain all PVC actions. In case of invalid `actionCreators`
* returned `actions` are an empty array.
* @returns {ResourceActionsKit} An object containing both the action factory and the generated action(s).
* - `factory`: Contains all possible action creators: `ExpandPVC`, `PVCSnapshot`, `ClonePVC`, `DeletePVC`.
* - `actions`: An array containing the generated `Action` object(s).
*
* @example
* // Getting all actions for PVC resource
* const MyPVCComponent = ({ kind, obj }) => {
* const { actions } = usePVCActionKit(kind, obj);
* return <Kebab actions={actions} />;
* };
*/
export const usePVCActionsKit = (
kind: K8sModel,
obj: PersistentVolumeClaimKind,
filterActions?: PVCActionCreator[],
): ResourceActionsKit => {
const { t } = useTranslation();
const stableFilterActions = React.useRef(null);

if (!isEqual(filterActions, stableFilterActions.current)) {
stableFilterActions.current = filterActions;
}

const factory = React.useMemo<ResourceActionFactory>(
() => ({
ExpandPVC: (_kind: K8sModel, _obj: PersistentVolumeClaimKind) => ({
id: 'expand-pvc',
label: t('console-app~Expand PVC'),
cta: () =>
expandPVCModal({
kind: _kind,
resource: _obj,
}),
accessReview: asAccessReview(_kind, _obj, 'patch'),
}),
PVCSnapshot: (_kind: K8sModel, _obj: PersistentVolumeClaimKind) => ({
id: 'create-snapshot',
label: t('console-app~Create snapshot'),
disabled: _obj?.status?.phase !== 'Bound',
tooltip: _obj?.status?.phase !== 'Bound' ? t('console-app~PVC is not Bound') : '',
cta: {
href: `/k8s/ns/${_obj.metadata.namespace}/${VolumeSnapshotModel.plural}/~new/form?pvc=${_obj.metadata.name}`,
},
accessReview: asAccessReview(_kind, _obj, 'create'),
}),
ClonePVC: (_kind: K8sModel, _obj: PersistentVolumeClaimKind) => ({
id: 'clone-pvc',
label: t('console-app~Clone PVC'),
disabled: _obj?.status?.phase !== 'Bound',
tooltip: _obj?.status?.phase !== 'Bound' ? t('console-app~PVC is not Bound') : '',
cta: () =>
clonePVCModal({
kind: _kind,
resource: _obj,
}),
accessReview: asAccessReview(_kind, _obj, 'create'),
}),
DeletePVC: (_kind: K8sModel, _obj: PersistentVolumeClaimKind) => ({
id: 'delete-pvc',
label: t('public~Delete PersistentVolumeClaim'),
cta: () =>
deletePVCModal({
pvc: _obj,
}),
accessReview: asAccessReview(_kind, _obj, 'delete'),
}),
}),
[t],
);
// filter and initialize requested actions or construct list of all PVCActions
const actions = React.useMemo<Action[]>(() => {
if (stableFilterActions.current) {
return stableFilterActions.current
.map((creator) => factory[creator]?.(kind, obj))
.filter(Boolean);
}
return [
factory.ExpandPVC(kind, obj),
factory.PVCSnapshot(kind, obj),
factory.ClonePVC(kind, obj),
factory.DeletePVC(kind, obj),
];
}, [kind, obj, factory, stableFilterActions]);
return {
factory,
actions,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { rollbackModal } from '@console/internal/components/modals';
import { DeploymentModel } from '@console/internal/models';
import { ReplicaSetKind, K8sKind } from '@console/internal/module/k8s';
import { getOwnerNameByKind } from '@console/shared/src';
import { ResourceActionFactory } from './common-factory';
import { ResourceActionFactory } from './types';

export const ReplicaSetFactory: ResourceActionFactory = {
RollbackDeploymentAction: (kind: K8sKind, obj: ReplicaSetKind): Action => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { asAccessReview } from '@console/internal/components/utils';
import { DeploymentConfigModel } from '@console/internal/models';
import { ReplicationControllerKind, K8sKind, k8sPatch } from '@console/internal/module/k8s';
import { getOwnerNameByKind } from '@console/shared/src';
import { ResourceActionFactory } from './common-factory';
import { ResourceActionFactory } from './types';

const INACTIVE_STATUSES = ['New', 'Pending', 'Running'];

Expand Down
23 changes: 23 additions & 0 deletions frontend/packages/console-app/src/actions/creators/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Action } from '@console/dynamic-plugin-sdk';
import { K8sModel, K8sResourceKind } from '@console/internal/module/k8s';

export type ResourceActionCreator = (
kind: K8sModel,
obj: K8sResourceKind,
relatedResource?: K8sResourceKind,
message?: JSX.Element,
) => Action;

export type ResourceActionFactory = Record<string, ResourceActionCreator>;

export type ResourceActionsKit = {
factory: ResourceActionFactory;
actions: Action[];
};

export enum PVCActionCreator {
ExpandPVC = 'ExpandPVC',
PVCSnapshot = 'PVCSnapshot',
ClonePVC = 'ClonePVC',
DeletePVC = 'DeletePVC',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { restorePVCModal } from '@console/internal/components/modals';
import { asAccessReview } from '@console/internal/components/utils';
import { VolumeSnapshotKind, K8sModel } from '@console/internal/module/k8s';
import { ResourceActionFactory } from './types';

/**
* A React hook for creating actions related to VolumeSnapshots.
*
* @returns {ResourceActionFactory} An object containing the action factory used to generate
* all actions specific to VolumeSnaphots.
*
* @example
* // Getting actions for VolumeSnapshot resources
* const MyVolumeSnapshotComponent = ({ kind, obj }) => {
* const factory = useVolumeSnapshotActionFactory();
* return <Kebab actions={factory.RestorePVC(kind, obj)} />;
* };
*/
export const useVolumeSnapshotActionFactory = (): ResourceActionFactory => {
const { t } = useTranslation();
return React.useMemo(
() => ({
RestorePVC: (kind: K8sModel, obj: VolumeSnapshotKind) => ({
id: 'clone-pvc',
label: t('console-app~Restore as new PVC'),
disabled: !obj?.status?.readyToUse,
tooltip: !obj?.status?.readyToUse ? t('console-app~Volume Snapshot is not Ready') : '',
cta: () =>
restorePVCModal({
kind,
obj,
}),
accessReview: asAccessReview(kind, obj, 'create'),
}),
}),
[t],
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as React from 'react';
import { CommonActionFactory } from '@console/app/src/actions/creators/common-factory';
import { usePVCActionsKit } from '@console/app/src/actions/creators/pvc-kit';
import { Action } from '@console/dynamic-plugin-sdk';
import { referenceFor, PersistentVolumeClaimKind } from '@console/internal/module/k8s';
import { useK8sModel } from '@console/shared/src/hooks/useK8sModel';

export const usePVCActionsProvider = (
resource: PersistentVolumeClaimKind,
): [Action[], boolean, boolean] => {
const [kindObj, inFlight] = useK8sModel(referenceFor(resource));
const { actions: actionsPVC } = usePVCActionsKit(kindObj, resource);

const actions = React.useMemo(
() => [
...actionsPVC,
CommonActionFactory.ModifyLabels(kindObj, resource),
CommonActionFactory.ModifyAnnotations(kindObj, resource),
CommonActionFactory.Edit(kindObj, resource),
],
[kindObj, actionsPVC, resource],
);
return [actions, !inFlight, undefined];
};
Loading