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

feat: Added stop/re-run button in experiment dashboard table and right sidebar #4255

Merged
merged 5 commits into from Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion chaoscenter/README.md
Expand Up @@ -45,5 +45,5 @@ helm install my-release bitnami/mongodb --values mongo-values.yml -n <NAMESPACE>
Applying the manifest file will install all the required service account configuration and ChaosCenter in cluster scope.

```shell
kubectl apply -f https://github.com/litmuschaos/litmus/blob/master/mkdocs/docs/3.0.0/litmus-cluster-scope-3.0.0.yaml
kubectl apply -f https://raw.githubusercontent.com/litmuschaos/litmus/master/mkdocs/docs/3.0.0/litmus-cluster-scope-3.0.0.yaml
```
Expand Up @@ -121,6 +121,7 @@ func (c *ChaosExperimentRunHandler) GetExperimentRun(ctx context.Context, projec
{"$project", bson.D{
{"name", 1},
{"is_custom_experiment", 1},
{"experiment_type", 1},
{"revision", bson.D{{
"$filter", bson.D{
{"input", "$revision"},
Expand Down Expand Up @@ -229,10 +230,13 @@ func (c *ChaosExperimentRunHandler) GetExperimentRun(ctx context.Context, projec
}
}

expType := string(wfRun.ExperimentDetails[0].ExperimentType)

expRunResponse = &model.ExperimentRun{
ExperimentName: wfRun.ExperimentDetails[0].ExperimentName,
ExperimentID: wfRun.ExperimentID,
ExperimentRunID: wfRun.ExperimentRunID,
ExperimentType: &expType,
NotifyID: wfRun.NotifyID,
Weightages: weightages,
ExperimentManifest: workflowRunManifest,
Expand Down
15 changes: 0 additions & 15 deletions chaoscenter/web/src/api/core/experiments/stopWorkflow.ts
Expand Up @@ -48,18 +48,3 @@ export function stopExperimentRun(

return [stopExperimentRunMutation, result];
}

export function stopAllExperiments(
options?: GqlAPIMutationRequest<StopAllExperimentResponse, StopAllExperimentRequest>
): GqlAPIMutationResponse<StopAllExperimentResponse, StopAllExperimentRequest> {
const [stopAllExperimentsMutation, result] = useMutation<StopAllExperimentResponse, StopAllExperimentRequest>(
gql`
mutation stopAllExperimentRuns($projectID: ID!) {
stopAllExperimentRuns(projectID: $projectID)
}
`,
options
);

return [stopAllExperimentsMutation, result];
}
@@ -1,17 +1,25 @@
import React from 'react';
import { Color, PopoverProps } from '@harnessio/design-system';
import { useToaster, ButtonVariation, ButtonProps } from '@harnessio/uicore';
import {
useToaster,
ButtonVariation,
ButtonProps,
ConfirmationDialog,
ConfirmationDialogProps,
useToggleOpen
} from '@harnessio/uicore';
import cx from 'classnames';
import { Position } from '@blueprintjs/core';
import { Intent, Position } from '@blueprintjs/core';
import { useHistory } from 'react-router-dom';
import { parse } from 'yaml';
import { useStrings } from '@strings';
import { listExperiment, runChaosExperiment } from '@api/core';
import { listExperiment, runChaosExperiment, stopExperiment, stopExperimentRun } from '@api/core';
import { useRouteWithBaseUrl } from '@hooks';
import type { RefetchExperiments } from '@controllers/ExperimentDashboardV2';
import type { RefetchExperimentRuns, RefetchExperiments } from '@controllers/ExperimentDashboardV2';
import { PermissionGroup, StudioTabs } from '@models';
import RbacButton from '@components/RbacButton';
import { downloadYamlAsFile, getScope, yamlStringify } from '@utils';
import type { InfrastructureType } from '@api/entities';
import css from './ExperimentActionButton.module.scss';

interface ActionButtonProps {
Expand All @@ -24,6 +32,12 @@ interface RunExperimentButtonProps extends ActionButtonProps, Partial<RefetchExp
disabled?: boolean;
}

interface StopExperimentButtonProps extends ActionButtonProps, Partial<RefetchExperiments> {
buttonProps?: ButtonProps;
infrastructureType: InfrastructureType | undefined;
disabled?: boolean;
}

export const RunExperimentButton = ({
experimentID,
tooltipProps,
Expand Down Expand Up @@ -70,13 +84,6 @@ export const RunExperimentButton = ({
withoutCurrentColor
variation={ButtonVariation.ICON}
permission={PermissionGroup.EDITOR}
// permission={{
// resourceScope: scope,
// resource: {
// resourceType: ResourceType.CHAOS_EXPERIMENT
// },
// permission: PermissionIdentifier.EXECUTE_CHAOS_EXPERIMENT
// }}
onClick={() => {
runChaosExperimentMutation({
variables: { projectID: scope.projectID, experimentID: experimentID }
Expand All @@ -88,6 +95,154 @@ export const RunExperimentButton = ({
);
};

export const StopExperimentButton = ({
experimentID,
tooltipProps,
refetchExperiments,
disabled
}: StopExperimentButtonProps): React.ReactElement => {
const scope = getScope();
const { getString } = useStrings();
const { showSuccess, showError } = useToaster();
const {
isOpen: isOpenStopExperimentDialog,
open: openStopExperimentDialog,
close: closeStopExperimentDialog
} = useToggleOpen();

const [stopExperimentMutation] = stopExperiment({
onCompleted: () => {
showSuccess(getString('experimentStopSuccessMessage'));
refetchExperiments?.();
},
onError: err => showError(err.message)
});

const stopExperimentDialogProps: ConfirmationDialogProps = {
isOpen: isOpenStopExperimentDialog,
contentText: getString('stopExperimentDesc'),
titleText: getString('stopExperimentHeading'),
cancelButtonText: getString('cancel'),
confirmButtonText: getString('confirm'),
intent: Intent.DANGER,
buttonIntent: Intent.DANGER,
onClose: (isConfirmed: boolean) => {
if (isConfirmed) {
stopExperimentMutation({
variables: {
projectID: scope.projectID,
experimentID
}
});
}
closeStopExperimentDialog();
}
};

const stopExperimentDialog = <ConfirmationDialog {...stopExperimentDialogProps} />;

return (
<div className={cx(css.actionButtons, css.withBg, css.hoverRed)}>
<div>
<RbacButton
tooltip={getString('stopExpRuns')}
iconProps={{ size: 18 }}
withoutCurrentColor
disabled={disabled}
tooltipProps={{
position: Position.TOP,
usePortal: true,
isDark: true,
...tooltipProps
}}
permission={PermissionGroup.EDITOR}
variation={ButtonVariation.ICON}
icon={'stop'}
onClick={openStopExperimentDialog}
/>
</div>
{stopExperimentDialog}
</div>
);
};

interface StopExperimentRunButtonProps extends ActionButtonProps, Partial<RefetchExperimentRuns> {
experimentRunID?: string;
notifyID?: string;
infrastructureType: InfrastructureType | undefined;
}

export const StopExperimentRunButton = ({
experimentID,
experimentRunID,
tooltipProps,
refetchExperimentRuns
}: StopExperimentRunButtonProps): React.ReactElement => {
const scope = getScope();
const { getString } = useStrings();
const { showSuccess, showError } = useToaster();
const {
isOpen: isOpenStopExperimentRunModal,
open: openStopExperimentRunDialog,
close: closeStopExperimentRunDialog
} = useToggleOpen();

const [stopExperimentRunMutation] = stopExperimentRun({
onCompleted: () => {
showSuccess(getString('experimentStopSuccessMessage'));
refetchExperimentRuns?.();
},
onError: err => showError(err.message)
});

const stopExperimentRunDialogProps: ConfirmationDialogProps = {
isOpen: isOpenStopExperimentRunModal,
contentText: getString('stopExpRunDesc'),
titleText: `${getString('stopExpRun')}?`,
cancelButtonText: getString('cancel'),
confirmButtonText: getString('confirm'),
intent: Intent.DANGER,
buttonIntent: Intent.DANGER,
onClose: (isConfirmed: boolean) => {
if (isConfirmed) {
stopExperimentRunMutation({
variables: {
experimentID,
projectID: scope.projectID,
experimentRunID
}
});
}
closeStopExperimentRunDialog();
}
};

const stopExperimentRunDialog = <ConfirmationDialog {...stopExperimentRunDialogProps} />;

return (
<div className={cx(css.actionButtons, css.withBg, css.hoverRed)}>
<div>
<RbacButton
tooltip={getString('stopExpRun')}
iconProps={{ size: 18 }}
withoutCurrentColor
tooltipProps={{
position: Position.TOP,
usePortal: true,
isDark: true,
...tooltipProps
}}
variation={ButtonVariation.ICON}
icon={'stop'}
permission={PermissionGroup.EDITOR}
onClick={openStopExperimentRunDialog}
/>
</div>
{stopExperimentRunDialog}
</div>
);
};

export const EditExperimentButton = ({ experimentID, tooltipProps }: ActionButtonProps): React.ReactElement => {
const history = useHistory();
const paths = useRouteWithBaseUrl();
Expand Down