// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package command import ( "errors" "fmt" "testing" "github.com/hashicorp/nomad/ci" "github.com/mitchellh/cli" "github.com/stretchr/testify/require" ) func TestEvalDeleteCommand_Run(t *testing.T) { ci.Parallel(t) testCases := []struct { testFn func() name string }{ { testFn: func() { testServer, client, url := testServer(t, false, nil) defer testServer.Shutdown() // Create the UI and command. ui := cli.NewMockUi() cmd := &EvalDeleteCommand{ Meta: Meta{ Ui: ui, flagAddress: url, }, } // Test basic command input validation. require.Equal(t, 1, cmd.Run([]string{"-address=" + url})) require.Contains(t, ui.ErrorWriter.String(), "Error validating command args and flags") ui.ErrorWriter.Reset() ui.OutputWriter.Reset() // Try running the command when the eval broker is not paused. require.Equal(t, 1, cmd.Run([]string{"-address=" + url, "fa3a8c37-eac3-00c7-3410-5ba3f7318fd8"})) require.Contains(t, ui.ErrorWriter.String(), "Eval broker is not paused") ui.ErrorWriter.Reset() ui.OutputWriter.Reset() // Paused the eval broker, then try deleting with an eval that // does not exist. schedulerConfig, _, err := client.Operator().SchedulerGetConfiguration(nil) require.NoError(t, err) require.False(t, schedulerConfig.SchedulerConfig.PauseEvalBroker) schedulerConfig.SchedulerConfig.PauseEvalBroker = true _, _, err = client.Operator().SchedulerSetConfiguration(schedulerConfig.SchedulerConfig, nil) require.NoError(t, err) require.True(t, schedulerConfig.SchedulerConfig.PauseEvalBroker) require.Equal(t, 1, cmd.Run([]string{"-address=" + url, "fa3a8c37-eac3-00c7-3410-5ba3f7318fd8"})) require.Contains(t, ui.ErrorWriter.String(), "eval not found") ui.ErrorWriter.Reset() ui.OutputWriter.Reset() }, name: "failure", }, { testFn: func() { testServer, client, url := testServer(t, false, nil) defer testServer.Shutdown() // Create the UI and command. ui := cli.NewMockUi() cmd := &EvalDeleteCommand{ Meta: Meta{ Ui: ui, flagAddress: url, }, } // Paused the eval broker. schedulerConfig, _, err := client.Operator().SchedulerGetConfiguration(nil) require.NoError(t, err) require.False(t, schedulerConfig.SchedulerConfig.PauseEvalBroker) schedulerConfig.SchedulerConfig.PauseEvalBroker = true _, _, err = client.Operator().SchedulerSetConfiguration(schedulerConfig.SchedulerConfig, nil) require.NoError(t, err) require.True(t, schedulerConfig.SchedulerConfig.PauseEvalBroker) // With the eval broker paused, run a job register several times // to generate evals that will not be acted on. testJob := testJob("eval-delete") evalIDs := make([]string, 3) for i := 0; i < 3; i++ { regResp, _, err := client.Jobs().Register(testJob, nil) require.NoError(t, err) require.NotNil(t, regResp) require.NotEmpty(t, regResp.EvalID) evalIDs[i] = regResp.EvalID } // Ensure we have three evaluations in state. evalList, _, err := client.Evaluations().List(nil) require.NoError(t, err) require.Len(t, evalList, 3) // Attempted to delete one eval using the ID. require.Equal(t, 0, cmd.Run([]string{"-address=" + url, evalIDs[0]})) require.Contains(t, ui.OutputWriter.String(), "Successfully deleted 1 evaluation") ui.ErrorWriter.Reset() ui.OutputWriter.Reset() // We modify the number deleted on each command run, so we // need to reset this in order to check the next command // output. cmd.numDeleted = 0 // Attempted to delete the remaining two evals using a filter // expression. expr := fmt.Sprintf("JobID == %q and Status == \"pending\" ", *testJob.Name) require.Equal(t, 0, cmd.Run([]string{"-address=" + url, "-filter=" + expr})) require.Contains(t, ui.OutputWriter.String(), "Successfully deleted 2 evaluations") ui.ErrorWriter.Reset() ui.OutputWriter.Reset() // Ensure we have zero evaluations in state. evalList, _, err = client.Evaluations().List(nil) require.NoError(t, err) require.Len(t, evalList, 0) }, name: "successful", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { tc.testFn() }) } } func TestEvalDeleteCommand_verifyArgsAndFlags(t *testing.T) { ci.Parallel(t) testCases := []struct { inputEvalDeleteCommand *EvalDeleteCommand inputArgs []string expectedError error name string }{ { inputEvalDeleteCommand: &EvalDeleteCommand{ filter: `Status == "Pending"`, }, inputArgs: []string{"fa3a8c37-eac3-00c7-3410-5ba3f7318fd8"}, expectedError: errors.New("evaluation ID or filter flag required"), name: "arg and flags", }, { inputEvalDeleteCommand: &EvalDeleteCommand{ filter: "", }, inputArgs: []string{}, expectedError: errors.New("evaluation ID or filter flag required"), name: "no arg or flags", }, { inputEvalDeleteCommand: &EvalDeleteCommand{ filter: "", }, inputArgs: []string{"fa3a8c37-eac3-00c7-3410-5ba3f7318fd8", "fa3a8c37-eac3-00c7-3410-5ba3f7318fd9"}, expectedError: errors.New("expected 1 argument, got 2"), name: "multiple args", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { actualError := tc.inputEvalDeleteCommand.verifyArgsAndFlags(tc.inputArgs) require.Equal(t, tc.expectedError, actualError) }) } }