From 25a436ddd925ad23c2c489cb19eae8d00572e4d3 Mon Sep 17 00:00:00 2001 From: Sarthak Jain Date: Thu, 28 Sep 2023 17:17:07 +0530 Subject: [PATCH] Added check to prevent duplicate experiments with same name (#4187) * Added check to prevent duplicate experiments with same name * Added duplicate experiment name check in chaos center * minor fix Signed-off-by: Sarthak Jain --------- Signed-off-by: Sarthak Jain --- .../pkg/chaos_experiment/handler/handler.go | 43 +++++++++++++++---- .../mongodb/chaos_experiment/operations.go | 9 ++++ .../graphql/server/pkg/gitops/service.go | 2 +- .../pkg/chaos-workflow/handler/handler.go | 30 +++++++++++++ 4 files changed, 75 insertions(+), 9 deletions(-) diff --git a/chaoscenter/graphql/server/pkg/chaos_experiment/handler/handler.go b/chaoscenter/graphql/server/pkg/chaos_experiment/handler/handler.go index d8b3f11d4cf..f7243344469 100644 --- a/chaoscenter/graphql/server/pkg/chaos_experiment/handler/handler.go +++ b/chaoscenter/graphql/server/pkg/chaos_experiment/handler/handler.go @@ -105,6 +105,20 @@ func (c *ChaosExperimentHandler) SaveChaosExperiment(ctx context.Context, reques // Updating the existing experiment if wfDetails.ExperimentID == request.ID { logrus.WithFields(logFields).Info("request received to update k8s chaos experiment") + if wfDetails.Name != request.Name { + filterQuery := bson.D{ + {"project_id", request.ID}, + {"name", request.Name}, + {"is_removed", false}, + } + experimentCount, err := c.chaosExperimentOperator.CountChaosExperiments(ctx, filterQuery) + if err != nil { + return "", err + } + if experimentCount > 0 { + return "", errors.New("experiment name should be unique, duplicate experiment found with name: " + request.Name) + } + } err = c.chaosExperimentService.ProcessExperimentUpdate(newRequest, username, wfType, revID, false, projectID, nil) if err != nil { @@ -129,19 +143,18 @@ func (c *ChaosExperimentHandler) CreateChaosExperiment(ctx context.Context, requ var revID = uuid.New().String() - // Check if the workflow_name exists under same project - wfDetails, err := c.chaosExperimentOperator.GetExperiments(bson.D{ - {"name", request.ExperimentName}, + // Check if the experiment_name exists under same project + filterQuery := bson.D{ {"project_id", projectID}, - {"tags", request.Tags}, + {"name", request.ExperimentName}, {"is_removed", false}, - }) + } + experimentCount, err := c.chaosExperimentOperator.CountChaosExperiments(ctx, filterQuery) if err != nil { return nil, err } - - if wfDetails != nil || len(wfDetails) > 0 { - return nil, errors.New("experiment name already exists in this project") + if experimentCount > 0 { + return nil, errors.New("experiment name should be unique, duplicate experiment found with name: " + request.ExperimentName) } newRequest, wfType, err := c.chaosExperimentService.ProcessExperiment(request, projectID, revID) @@ -226,6 +239,20 @@ func (c *ChaosExperimentHandler) UpdateChaosExperiment(ctx context.Context, requ revID = uuid.New().String() ) + // Check if the experiment_name exists under same project + filterQuery := bson.D{ + {"project_id", projectID}, + {"name", request.ExperimentName}, + {"is_removed", false}, + } + experimentCount, err := c.chaosExperimentOperator.CountChaosExperiments(ctx, filterQuery) + if err != nil { + return nil, err + } + if experimentCount > 0 { + return nil, errors.New("experiment name should be unique, duplicate experiment found with name: " + request.ExperimentName) + } + newRequest, wfType, err := c.chaosExperimentService.ProcessExperiment(request, projectID, revID) if err != nil { return nil, err diff --git a/chaoscenter/graphql/server/pkg/database/mongodb/chaos_experiment/operations.go b/chaoscenter/graphql/server/pkg/database/mongodb/chaos_experiment/operations.go index f2956fc788d..65058673a9d 100644 --- a/chaoscenter/graphql/server/pkg/database/mongodb/chaos_experiment/operations.go +++ b/chaoscenter/graphql/server/pkg/database/mongodb/chaos_experiment/operations.go @@ -124,3 +124,12 @@ func (c *Operator) UpdateChaosExperiments(ctx context.Context, query bson.D, upd return nil } + +// CountChaosExperiments returns total number of matched documents +func (c *Operator) CountChaosExperiments(ctx context.Context, query bson.D) (int64, error) { + res, err := mongodb.Operator.CountDocuments(ctx, mongodb.ChaosExperimentCollection, query) + if err != nil { + return 0, err + } + return res, nil +} diff --git a/chaoscenter/graphql/server/pkg/gitops/service.go b/chaoscenter/graphql/server/pkg/gitops/service.go index 77d073aa5f9..ccad77d084e 100644 --- a/chaoscenter/graphql/server/pkg/gitops/service.go +++ b/chaoscenter/graphql/server/pkg/gitops/service.go @@ -597,7 +597,7 @@ func (g *gitOpsService) updateExperiment(data, wfID, file string, config GitConf return errors.New("file name doesn't match experiment name") } - experiment, err := g.chaosExperimentOps.GetExperiments(bson.D{{"experiment_id", wfID}, {"project_id", config.ProjectID}, {"isRemoved", false}}) + experiment, err := g.chaosExperimentOps.GetExperiments(bson.D{{"experiment_id", wfID}, {"project_id", config.ProjectID}, {"is_removed", false}}) if len(experiment) == 0 { return errors.New("No such experiment found : " + wfID) } diff --git a/litmus-portal/graphql-server/pkg/chaos-workflow/handler/handler.go b/litmus-portal/graphql-server/pkg/chaos-workflow/handler/handler.go index 9455063b8f1..caabb7da067 100644 --- a/litmus-portal/graphql-server/pkg/chaos-workflow/handler/handler.go +++ b/litmus-portal/graphql-server/pkg/chaos-workflow/handler/handler.go @@ -5,6 +5,7 @@ import ( "encoding/base64" "encoding/json" "errors" + "fmt" "strconv" "strings" "time" @@ -64,6 +65,21 @@ func NewChaosWorkflowHandler( // CreateChaosWorkflow creates a new chaos workflow func (c *ChaosWorkflowHandler) CreateChaosWorkflow(ctx context.Context, request *model.ChaosWorkFlowRequest, r *store.StateData) (*model.ChaosWorkFlowResponse, error) { + + // Check if the experiment_name exists under same project + expDetails, err := c.chaosWorkflowOperator.GetWorkflow(bson.D{ + {"name", request.WorkflowName}, + {"project_id", request.ProjectID}, + {"is_removed", false}, + }) + if err != nil && err != mongo.ErrNoDocuments { + return nil, err + } + if expDetails.WorkflowID == "" { + log.Errorf("experiment with name %s already exists", request.WorkflowName) + return nil, fmt.Errorf("experiment with name %s already exists", request.WorkflowName) + } + request, wfType, err := c.chaosWorkflowService.ProcessWorkflow(request) if err != nil { log.Error("error processing workflow: ", err) @@ -198,6 +214,20 @@ func (c *ChaosWorkflowHandler) TerminateChaosWorkflow(ctx context.Context, proje } func (c *ChaosWorkflowHandler) UpdateChaosWorkflow(ctx context.Context, request *model.ChaosWorkFlowRequest, r *store.StateData) (*model.ChaosWorkFlowResponse, error) { + // Check if the experiment_name exists under same project + expDetails, err := c.chaosWorkflowOperator.GetWorkflow(bson.D{ + {"name", request.WorkflowName}, + {"project_id", request.ProjectID}, + {"is_removed", false}, + }) + if err != nil && err != mongo.ErrNoDocuments { + return nil, err + } + if expDetails.WorkflowID == "" { + log.Errorf("experiment with name %s already exists", request.WorkflowName) + return nil, fmt.Errorf("experiment with name %s already exists", request.WorkflowName) + } + request, wfType, err := c.chaosWorkflowService.ProcessWorkflow(request) if err != nil { log.Error("error processing workflow update: ", err)