diff --git a/apiserver/facades/client/action/action_test.go b/apiserver/facades/client/action/action_test.go index 67b26627444..d314498f5eb 100644 --- a/apiserver/facades/client/action/action_test.go +++ b/apiserver/facades/client/action/action_test.go @@ -4,48 +4,12 @@ package action_test import ( - "context" - "encoding/json" - - "github.com/juju/names/v5" - jc "github.com/juju/testing/checkers" - "github.com/juju/worker/v4/workertest" - "go.uber.org/mock/gomock" + "github.com/juju/testing" gc "gopkg.in/check.v1" - - "github.com/juju/juju/apiserver/common" - "github.com/juju/juju/apiserver/facades/client/action" - apiservertesting "github.com/juju/juju/apiserver/testing" - "github.com/juju/juju/core/actions" - charmtesting "github.com/juju/juju/core/charm/testing" - "github.com/juju/juju/core/watcher/watchertest" - applicationerrors "github.com/juju/juju/domain/application/errors" - blockcommanderrors "github.com/juju/juju/domain/blockcommand/errors" - internalcharm "github.com/juju/juju/internal/charm" - "github.com/juju/juju/internal/testing/factory" - jujutesting "github.com/juju/juju/juju/testing" - "github.com/juju/juju/rpc/params" - "github.com/juju/juju/state" ) type baseSuite struct { - jujutesting.ApiServerSuite - - action *action.ActionAPI - authorizer apiservertesting.FakeAuthorizer - resources *common.Resources - - charm *state.Charm - machine0 *state.Machine - machine1 *state.Machine - dummy *state.Application - wordpress *state.Application - mysql *state.Application - wordpressUnit *state.Unit - mysqlUnit *state.Unit - - blockCommandService *action.MockBlockCommandService - applicationService *action.MockApplicationService + testing.IsolationSuite } type actionSuite struct { @@ -54,447 +18,12 @@ type actionSuite struct { var _ = gc.Suite(&actionSuite{}) -func (s *actionSuite) TestActions(c *gc.C) { - defer s.setupMocks(c).Finish() - - arg := params.Actions{ - Actions: []params.Action{ - {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, - {Receiver: s.mysqlUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, - {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{"foo": 1, "bar": "please"}}, - {Receiver: s.mysqlUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{"baz": true}}, - }} - - r, err := s.action.EnqueueOperation(context.Background(), arg) - c.Assert(err, jc.ErrorIsNil) - c.Assert(r.Actions, gc.HasLen, len(arg.Actions)) - - // There's only one operation created. - operations, err := s.ControllerModel(c).AllOperations() - c.Assert(err, jc.ErrorIsNil) - c.Assert(operations, gc.HasLen, 1) - c.Assert(operations[0].Summary(), gc.Equals, "fakeaction run on unit-wordpress-0,unit-mysql-0,unit-wordpress-0,unit-mysql-0") - - emptyActionTag := names.ActionTag{} - for i, got := range r.Actions { - c.Assert(got.Error, gc.Equals, (*params.Error)(nil), gc.Commentf("action %d, %v", i, got.Error)) - c.Assert(got.Action, gc.NotNil) - - c.Logf("check index %d (%s: %s)", i, got.Action.Tag, arg.Actions[i].Name) - c.Assert(got.Action, gc.Not(gc.Equals), (*params.Action)(nil)) - c.Assert(got.Action.Tag, gc.Not(gc.Equals), emptyActionTag) - c.Assert(got.Action.Name, gc.Equals, arg.Actions[i].Name) - c.Assert(got.Action.Receiver, gc.Equals, arg.Actions[i].Receiver) - c.Assert(got.Action.Parameters, gc.DeepEquals, arg.Actions[i].Parameters) - c.Assert(got.Status, gc.Equals, params.ActionPending) - c.Assert(got.Message, gc.Equals, "") - c.Assert(got.Output, gc.IsNil) - } -} - -func (s *actionSuite) TestCancel(c *gc.C) { - defer s.setupMocks(c).Finish() - - // Make sure no Actions already exist on wordpress Unit. - actions, err := s.wordpressUnit.Actions() - c.Assert(err, jc.ErrorIsNil) - c.Assert(actions, gc.HasLen, 0) - - // Make sure no Actions already exist on mysql Unit. - actions, err = s.mysqlUnit.Actions() - c.Assert(err, jc.ErrorIsNil) - c.Assert(actions, gc.HasLen, 0) - - // Add Actions. - tests := params.Actions{ - Actions: []params.Action{{ - Receiver: s.wordpressUnit.Tag().String(), - Name: "fakeaction", - }, { - Receiver: s.wordpressUnit.Tag().String(), - Name: "fakeaction", - }, { - Receiver: s.mysqlUnit.Tag().String(), - Name: "fakeaction", - }, { - Receiver: s.mysqlUnit.Tag().String(), - Name: "fakeaction", - }}, - } - - results, err := s.action.EnqueueOperation(context.Background(), tests) - c.Assert(err, jc.ErrorIsNil) - c.Assert(results.Actions, gc.HasLen, 4) - for _, res := range results.Actions { - c.Assert(res.Error, gc.IsNil) - } - - // blocking changes should have no effect - s.blockCommandService.EXPECT().GetBlockSwitchedOn(gomock.Any(), gomock.Any()).Return("Cancel", nil).AnyTimes() - - // Cancel Some. - arg := params.Entities{ - Entities: []params.Entity{ - // "wp-two" - {Tag: results.Actions[1].Action.Tag}, - // "my-one" - {Tag: results.Actions[2].Action.Tag}, - }} - cancelled, err := s.action.Cancel(context.Background(), arg) - c.Assert(err, jc.ErrorIsNil) - c.Assert(cancelled.Results, gc.HasLen, 2) - - // Assert the Actions are all in the expected state. - operations, err := s.action.ListOperations(context.Background(), params.OperationQueryArgs{ - Units: []string{ - s.wordpressUnit.Name(), - s.mysqlUnit.Name(), - }, - }) - c.Assert(err, jc.ErrorIsNil) - c.Assert(operations.Results, gc.HasLen, 1) - - resultActions := operations.Results[0].Actions - c.Assert(resultActions, gc.HasLen, 4) - c.Assert(resultActions[0].Action.Name, gc.Equals, "fakeaction") - c.Assert(resultActions[0].Status, gc.Equals, params.ActionPending) - c.Assert(resultActions[1].Action.Name, gc.Equals, "fakeaction") - c.Assert(resultActions[1].Status, gc.Equals, params.ActionCancelled) - c.Assert(resultActions[2].Action.Name, gc.Equals, "fakeaction") - c.Assert(resultActions[2].Status, gc.Equals, params.ActionCancelled) - c.Assert(resultActions[3].Action.Name, gc.Equals, "fakeaction") - c.Assert(resultActions[3].Status, gc.Equals, params.ActionPending) -} - -func (s *actionSuite) TestAbort(c *gc.C) { - defer s.setupMocks(c).Finish() - - // Make sure no Actions already exist on wordpress Unit. - actions, err := s.wordpressUnit.Actions() - c.Assert(err, jc.ErrorIsNil) - c.Assert(actions, gc.HasLen, 0) - - // Add Actions. - tests := params.Actions{ - Actions: []params.Action{{ - Receiver: s.wordpressUnit.Tag().String(), - Name: "fakeaction", - }}, - } - - results, err := s.action.EnqueueOperation(context.Background(), tests) - c.Assert(err, jc.ErrorIsNil) - c.Assert(results.Actions, gc.HasLen, 1) - c.Assert(results.Actions[0].Error, gc.IsNil) - - actions, err = s.wordpressUnit.Actions() - c.Assert(err, jc.ErrorIsNil) - c.Assert(actions, gc.HasLen, 1) - - _, err = actions[0].Begin() - c.Assert(err, jc.ErrorIsNil) - - // blocking changes should have no effect - s.blockCommandService.EXPECT().GetBlockSwitchedOn(gomock.Any(), gomock.Any()).Return("Cancel", nil).AnyTimes() - - // Cancel Some. - arg := params.Entities{ - Entities: []params.Entity{ - // "wp-one" - {Tag: results.Actions[0].Action.Tag}, - }} - cancelled, err := s.action.Cancel(context.Background(), arg) - c.Assert(err, jc.ErrorIsNil) - c.Assert(cancelled.Results, gc.HasLen, 1) - c.Assert(cancelled.Results[0].Action.Name, gc.Equals, "fakeaction") - c.Assert(cancelled.Results[0].Status, gc.Equals, params.ActionAborting) - - // Assert the Actions are all in the expected state. - operations, err := s.action.ListOperations(context.Background(), params.OperationQueryArgs{ - Units: []string{s.wordpressUnit.Name()}, - }) - c.Assert(err, jc.ErrorIsNil) - c.Assert(operations.Results, gc.HasLen, 1) - - wpActions := operations.Results[0].Actions - c.Assert(wpActions, gc.HasLen, 1) - c.Assert(wpActions[0].Action.Name, gc.Equals, "fakeaction") - c.Assert(wpActions[0].Status, gc.Equals, params.ActionAborting) -} - -func (s *actionSuite) TestApplicationsCharmsActions(c *gc.C) { - defer s.setupMocks(c).Finish() - - s.blockCommandService.EXPECT().GetBlockSwitchedOn(gomock.Any(), gomock.Any()).Return("", blockcommanderrors.NotFound).AnyTimes() - - charmID := charmtesting.GenCharmID(c) - - s.applicationService.EXPECT().GetCharmIDByApplicationName(gomock.Any(), "dummy").Return(charmID, nil) - s.applicationService.EXPECT().GetCharmActions(gomock.Any(), charmID).Return(internalcharm.Actions{ - ActionSpecs: map[string]internalcharm.ActionSpec{ - "snapshot": { - Description: "Take a snapshot of the database.", - Params: map[string]interface{}{ - "type": "object", - "title": "snapshot", - "description": "Take a snapshot of the database.", - "additionalProperties": true, - "properties": map[string]interface{}{ - "outfile": map[string]interface{}{ - "description": "The file to write out to.", - "type": "string", - "default": "foo.bz2", - }, - }, - }, - }, - }, - }, nil) - - s.applicationService.EXPECT().GetCharmIDByApplicationName(gomock.Any(), "wordpress").Return(charmID, nil) - s.applicationService.EXPECT().GetCharmActions(gomock.Any(), charmID).Return(internalcharm.Actions{ - ActionSpecs: map[string]internalcharm.ActionSpec{ - "fakeaction": { - Description: "No description", - Params: map[string]interface{}{ - "type": "object", - "title": "fakeaction", - "description": "No description", - "additionalProperties": true, - "properties": map[string]interface{}{}, - }, - }, - }, - }, nil) - - s.applicationService.EXPECT().GetCharmIDByApplicationName(gomock.Any(), "nonsense").Return(charmID, applicationerrors.ApplicationNotFound) - - actionSchemas := map[string]map[string]interface{}{ - "snapshot": { - "type": "object", - "title": "snapshot", - "description": "Take a snapshot of the database.", - "additionalProperties": true, - "properties": map[string]interface{}{ - "outfile": map[string]interface{}{ - "description": "The file to write out to.", - "type": "string", - "default": "foo.bz2", - }, - }, - }, - "fakeaction": { - "type": "object", - "title": "fakeaction", - "description": "No description", - "additionalProperties": true, - "properties": map[string]interface{}{}, - }, - } - tests := []struct { - applicationNames []string - expectedResults params.ApplicationsCharmActionsResults - }{{ - applicationNames: []string{"dummy"}, - expectedResults: params.ApplicationsCharmActionsResults{ - Results: []params.ApplicationCharmActionsResult{ - { - ApplicationTag: names.NewApplicationTag("dummy").String(), - Actions: map[string]params.ActionSpec{ - "snapshot": { - Description: "Take a snapshot of the database.", - Params: actionSchemas["snapshot"], - }, - }, - }, - }, - }, - }, { - applicationNames: []string{"wordpress"}, - expectedResults: params.ApplicationsCharmActionsResults{ - Results: []params.ApplicationCharmActionsResult{ - { - ApplicationTag: names.NewApplicationTag("wordpress").String(), - Actions: map[string]params.ActionSpec{ - "fakeaction": { - Description: "No description", - Params: actionSchemas["fakeaction"], - }, - }, - }, - }, - }, - }, { - applicationNames: []string{"nonsense"}, - expectedResults: params.ApplicationsCharmActionsResults{ - Results: []params.ApplicationCharmActionsResult{ - { - ApplicationTag: names.NewApplicationTag("nonsense").String(), - Error: ¶ms.Error{ - Message: `application "nonsense" not found`, - Code: "not found", - }, - }, - }, - }, - }} - - for i, t := range tests { - c.Logf("test %d: applications: %#v", i, t.applicationNames) - - svcTags := params.Entities{ - Entities: make([]params.Entity, len(t.applicationNames)), - } - - for j, app := range t.applicationNames { - svcTag := names.NewApplicationTag(app) - svcTags.Entities[j] = params.Entity{Tag: svcTag.String()} - } - - results, err := s.action.ApplicationsCharmsActions(context.Background(), svcTags) - c.Assert(err, jc.ErrorIsNil) - c.Check(results.Results, jc.DeepEquals, t.expectedResults.Results) - } -} - -func (s *actionSuite) TestWatchActionProgress(c *gc.C) { - defer s.setupMocks(c).Finish() - - s.blockCommandService.EXPECT().GetBlockSwitchedOn(gomock.Any(), gomock.Any()).Return("", blockcommanderrors.NotFound).AnyTimes() - - unit, err := s.ControllerModel(c).State().Unit("mysql/0") - c.Assert(err, jc.ErrorIsNil) - assertReadyToTest(c, unit) - - operationID, err := s.ControllerModel(c).EnqueueOperation("a test", 1) - c.Assert(err, jc.ErrorIsNil) - added, err := s.ControllerModel(c).AddAction(unit, operationID, "fakeaction", nil, nil, nil) - c.Assert(err, jc.ErrorIsNil) - - w, err := s.action.WatchActionsProgress( - context.Background(), - params.Entities{Entities: []params.Entity{{Tag: "action-2"}}}, - ) - c.Assert(err, jc.ErrorIsNil) - c.Assert(w.Results, gc.HasLen, 1) - c.Assert(w.Results[0].Error, gc.IsNil) - c.Assert(w.Results[0].Changes, gc.HasLen, 0) - - // Verify the resource was registered and stop when done - c.Assert(s.resources.Count(), gc.Equals, 1) - resource := s.resources.Get("1") - defer workertest.CleanKill(c, resource) - - // Check that the Watch has consumed the initial event - wc := watchertest.NewStringsWatcherC(c, resource.(state.StringsWatcher)) - wc.AssertNoChange() - - // Log a message and check the watcher result. - added, err = added.Begin() - c.Assert(err, jc.ErrorIsNil) - err = added.Log("hello") - c.Assert(err, jc.ErrorIsNil) - - a, err := s.ControllerModel(c).Action("2") - c.Assert(err, jc.ErrorIsNil) - logged := a.Messages() - c.Assert(logged, gc.HasLen, 1) - expected, err := json.Marshal(actions.ActionMessage{ - Message: logged[0].Message(), - Timestamp: logged[0].Timestamp(), - }) - c.Assert(err, jc.ErrorIsNil) - - wc.AssertChange(string(expected)) - wc.AssertNoChange() -} - -func (s *baseSuite) setupMocks(c *gc.C) *gomock.Controller { - ctrl := gomock.NewController(c) - - s.blockCommandService = action.NewMockBlockCommandService(ctrl) - s.applicationService = action.NewMockApplicationService(ctrl) - - s.authorizer = apiservertesting.FakeAuthorizer{ - Tag: jujutesting.AdminUser, - } - s.resources = common.NewResources() - s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() }) - - var err error - s.action, err = action.NewActionAPI( - s.ControllerModel(c).State(), - s.resources, - s.authorizer, - action.FakeLeadership{}, - s.applicationService, - s.blockCommandService, - ) - c.Assert(err, jc.ErrorIsNil) - - f, release := s.NewFactory(c, s.ControllerModelUUID()) - defer release() - - s.charm = f.MakeCharm(c, &factory.CharmParams{ - Name: "wordpress", - }) - - s.dummy = f.MakeApplication(c, &factory.ApplicationParams{ - Name: "dummy", - Charm: f.MakeCharm(c, &factory.CharmParams{ - Name: "dummy", - }), - }) - s.wordpress = f.MakeApplication(c, &factory.ApplicationParams{ - Name: "wordpress", - Charm: s.charm, - }) - s.machine0 = f.MakeMachine(c, &factory.MachineParams{ - Base: state.UbuntuBase("12.10"), - Jobs: []state.MachineJob{state.JobHostUnits, state.JobManageModel}, - }) - s.wordpressUnit = f.MakeUnit(c, &factory.UnitParams{ - Application: s.wordpress, - Machine: s.machine0, - }) - - mysqlCharm := f.MakeCharm(c, &factory.CharmParams{ - Name: "mysql", - }) - s.mysql = f.MakeApplication(c, &factory.ApplicationParams{ - Name: "mysql", - Charm: mysqlCharm, - }) - s.machine1 = f.MakeMachine(c, &factory.MachineParams{ - Base: state.UbuntuBase("12.10"), - Jobs: []state.MachineJob{state.JobHostUnits}, - }) - s.mysqlUnit = f.MakeUnit(c, &factory.UnitParams{ - Application: s.mysql, - Machine: s.machine1, - }) - - return ctrl -} - -func assertReadyToTest(c *gc.C, receiver state.ActionReceiver) { - // make sure there are no actions on the receiver already. - actions, err := receiver.Actions() - c.Assert(err, jc.ErrorIsNil) - c.Assert(actions, gc.HasLen, 0) - - // make sure there are no actions pending already. - actions, err = receiver.PendingActions() - c.Assert(err, jc.ErrorIsNil) - c.Assert(actions, gc.HasLen, 0) - - // make sure there are no actions running already. - actions, err = receiver.RunningActions() - c.Assert(err, jc.ErrorIsNil) - c.Assert(actions, gc.HasLen, 0) - - // make sure there are no actions completed already. - actions, err = receiver.CompletedActions() - c.Assert(err, jc.ErrorIsNil) - c.Assert(actions, gc.HasLen, 0) +func (s *actionSuite) TestStub(c *gc.C) { + c.Skip(`This suite is missing tests for the following scenarios: +- Enqueueing an action against multiple units, verifying persisted receivers/params/status etc. +- Enqueueing actions and cancelling a subset, verifying actions in the cancelled state. +- Beginning an action and then cancelling, verifying the aborting status. +- Ensuring the ApplicationsCharmsActions returns the correct result for input app tags. +- Enqueueing and watching an action, observing its action messages as it progresses. +`) } diff --git a/apiserver/facades/client/action/operation_test.go b/apiserver/facades/client/action/operation_test.go index a262c2d9069..cc7b1453390 100644 --- a/apiserver/facades/client/action/operation_test.go +++ b/apiserver/facades/client/action/operation_test.go @@ -5,7 +5,6 @@ package action_test import ( "context" - "strconv" "time" "github.com/juju/errors" @@ -27,329 +26,16 @@ type operationSuite struct { var _ = gc.Suite(&operationSuite{}) -func (s *operationSuite) setupOperations(c *gc.C) { - parallel := true - executionGroup := "group" - arg := params.Actions{ - Actions: []params.Action{ - {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}, - Parallel: ¶llel, ExecutionGroup: &executionGroup}, - {Receiver: s.mysqlUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, - {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, - {Receiver: s.mysqlUnit.Tag().String(), Name: "anotherfakeaction", Parameters: map[string]interface{}{}}, - }} - - r, err := s.action.EnqueueOperation(context.Background(), arg) - c.Assert(err, jc.ErrorIsNil) - c.Assert(r.Actions, gc.HasLen, len(arg.Actions)) - - // There's only one operation created. - ops, err := s.ControllerModel(c).AllOperations() - c.Assert(err, jc.ErrorIsNil) - c.Assert(ops, gc.HasLen, 1) - operationID, err := strconv.Atoi(ops[0].Id()) - c.Assert(err, jc.ErrorIsNil) - - a, err := s.ControllerModel(c).Action(strconv.Itoa(operationID + 1)) - c.Assert(err, jc.ErrorIsNil) - c.Assert(a.Parallel(), jc.IsTrue) - c.Assert(a.ExecutionGroup(), gc.Equals, "group") - _, err = a.Begin() - c.Assert(err, jc.ErrorIsNil) - a, err = s.ControllerModel(c).Action(strconv.Itoa(operationID + 2)) - c.Assert(err, jc.ErrorIsNil) - _, err = a.Finish(state.ActionResults{Status: state.ActionCompleted}) - c.Assert(err, jc.ErrorIsNil) -} - -func (s *operationSuite) TestListOperationsStatusFilter(c *gc.C) { - defer s.setupMocks(c).Finish() - - s.setupOperations(c) - // Set up a non running operation. - arg := params.Actions{ - Actions: []params.Action{ - {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, - }} - _, err := s.action.EnqueueOperation(context.Background(), arg) - c.Assert(err, jc.ErrorIsNil) - - operations, err := s.action.ListOperations(context.Background(), params.OperationQueryArgs{ - Status: []string{"running"}, - }) - c.Assert(err, jc.ErrorIsNil) - c.Assert(operations.Truncated, jc.IsFalse) - c.Assert(operations.Results, gc.HasLen, 1) - result := operations.Results[0] - c.Assert(result.Actions, gc.HasLen, 4) - c.Assert(result.Actions[0].Action, gc.NotNil) - if result.Enqueued.IsZero() { - c.Fatal("enqueued time not set") - } - if result.Started.IsZero() { - c.Fatal("started time not set") - } - c.Assert(result.Status, gc.Equals, "running") - - action := result.Actions[0].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") - c.Assert(action.Tag, gc.Equals, "action-2") - c.Assert(result.Actions[0].Status, gc.Equals, "running") - action = result.Actions[1].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") - c.Assert(action.Tag, gc.Equals, "action-3") - c.Assert(result.Actions[1].Status, gc.Equals, "completed") - action = result.Actions[2].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") - c.Assert(action.Tag, gc.Equals, "action-4") - c.Assert(result.Actions[2].Status, gc.Equals, "pending") - action = result.Actions[3].Action - c.Assert(action.Name, gc.Equals, "anotherfakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") - c.Assert(action.Tag, gc.Equals, "action-5") - c.Assert(result.Actions[3].Status, gc.Equals, "pending") -} - -func (s *operationSuite) TestListOperationsNameFilter(c *gc.C) { - defer s.setupMocks(c).Finish() - - s.setupOperations(c) - // Set up a second operation. - arg := params.Actions{ - Actions: []params.Action{ - {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, - }} - _, err := s.action.EnqueueOperation(context.Background(), arg) - c.Assert(err, jc.ErrorIsNil) - - operations, err := s.action.ListOperations(context.Background(), params.OperationQueryArgs{ - ActionNames: []string{"anotherfakeaction"}, - }) - c.Assert(err, jc.ErrorIsNil) - c.Assert(operations.Results, gc.HasLen, 1) - result := operations.Results[0] - c.Assert(result.Actions, gc.HasLen, 1) - c.Assert(result.Actions[0].Action, gc.NotNil) - if result.Enqueued.IsZero() { - c.Fatal("enqueued time not set") - } - if result.Started.IsZero() { - c.Fatal("started time not set") - } - c.Assert(result.Status, gc.Equals, "running") - action := result.Actions[0].Action - c.Assert(action.Name, gc.Equals, "anotherfakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") - c.Assert(action.Tag, gc.Equals, "action-5") - c.Assert(result.Actions[0].Status, gc.Equals, "pending") -} - -func (s *operationSuite) TestListOperationsAppFilter(c *gc.C) { - defer s.setupMocks(c).Finish() - - s.setupOperations(c) - // Set up a second operation for a different app. - arg := params.Actions{ - Actions: []params.Action{ - {Receiver: s.mysqlUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, - }} - _, err := s.action.EnqueueOperation(context.Background(), arg) - c.Assert(err, jc.ErrorIsNil) - - operations, err := s.action.ListOperations(context.Background(), params.OperationQueryArgs{ - Applications: []string{"wordpress"}, - }) - c.Assert(err, jc.ErrorIsNil) - c.Assert(operations.Results, gc.HasLen, 1) - result := operations.Results[0] - - c.Assert(result.Actions, gc.HasLen, 2) - c.Assert(result.Actions[0].Action, gc.NotNil) - if result.Enqueued.IsZero() { - c.Fatal("enqueued time not set") - } - if result.Started.IsZero() { - c.Fatal("started time not set") - } - c.Assert(result.Status, gc.Equals, "running") - action := result.Actions[0].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") - c.Assert(action.Tag, gc.Equals, "action-2") - c.Assert(result.Actions[0].Status, gc.Equals, "running") - action = result.Actions[1].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") - c.Assert(action.Tag, gc.Equals, "action-4") - c.Assert(result.Actions[1].Status, gc.Equals, "pending") -} - -func (s *operationSuite) TestListOperationsUnitFilter(c *gc.C) { - defer s.setupMocks(c).Finish() - - s.setupOperations(c) - // Set up an operation with a pending action. - arg := params.Actions{ - Actions: []params.Action{ - {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, - }} - _, err := s.action.EnqueueOperation(context.Background(), arg) - c.Assert(err, jc.ErrorIsNil) - - operations, err := s.action.ListOperations(context.Background(), params.OperationQueryArgs{ - Units: []string{"wordpress/0"}, - Status: []string{"pending"}, - }) - c.Assert(err, jc.ErrorIsNil) - c.Assert(operations.Results, gc.HasLen, 1) - result := operations.Results[0] - - c.Assert(result.Actions, gc.HasLen, 1) - c.Assert(result.Actions[0].Action, gc.NotNil) - if result.Enqueued.IsZero() { - c.Fatal("enqueued time not set") - } - c.Assert(result.Status, gc.Equals, "pending") - action := result.Actions[0].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") - c.Assert(action.Tag, gc.Equals, "action-7") - c.Assert(result.Actions[0].Status, gc.Equals, "pending") -} - -func (s *operationSuite) TestListOperationsMachineFilter(c *gc.C) { - defer s.setupMocks(c).Finish() - - s.setupOperations(c) - // Set up an operation with a pending action. - arg := params.Actions{ - Actions: []params.Action{ - {Receiver: s.machine0.Tag().String(), Name: "juju-exec", Parameters: map[string]interface{}{ - "command": "ls", - "timeout": 1, - }}, - }} - _, err := s.action.EnqueueOperation(context.Background(), arg) - c.Assert(err, jc.ErrorIsNil) - - operations, err := s.action.ListOperations(context.Background(), params.OperationQueryArgs{ - Machines: []string{"0"}, - Status: []string{"pending"}, - }) - c.Assert(err, jc.ErrorIsNil) - c.Assert(operations.Results, gc.HasLen, 1) - result := operations.Results[0] - - c.Assert(result.Actions, gc.HasLen, 1) - c.Assert(result.Actions[0].Action, gc.NotNil) - if result.Enqueued.IsZero() { - c.Fatal("enqueued time not set") - } - c.Assert(result.Status, gc.Equals, "pending") - action := result.Actions[0].Action - c.Assert(action.Name, gc.Equals, "juju-exec") - c.Assert(action.Receiver, gc.Equals, "machine-0") - c.Assert(action.Tag, gc.Equals, "action-7") - c.Assert(result.Actions[0].Status, gc.Equals, "pending") -} - -func (s *operationSuite) TestListOperationsAppAndUnitFilter(c *gc.C) { - defer s.setupMocks(c).Finish() - - s.setupOperations(c) - // Set up an operation with a pending action. - arg := params.Actions{ - Actions: []params.Action{ - {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, - }} - _, err := s.action.EnqueueOperation(context.Background(), arg) - c.Assert(err, jc.ErrorIsNil) - - operations, err := s.action.ListOperations(context.Background(), params.OperationQueryArgs{ - Applications: []string{"mysql"}, - Units: []string{"wordpress/0"}, - Status: []string{"running"}, - }) - c.Assert(err, jc.ErrorIsNil) - c.Assert(operations.Results, gc.HasLen, 1) - c.Log(pretty.Sprint(operations.Results)) - result := operations.Results[0] - - c.Assert(result.Actions, gc.HasLen, 4) - c.Assert(result.Actions[0].Action, gc.NotNil) - if result.Enqueued.IsZero() { - c.Fatal("enqueued time not set") - } - if result.Started.IsZero() { - c.Fatal("started time not set") - } - - action := result.Actions[0].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") - c.Assert(action.Tag, gc.Equals, "action-2") - c.Assert(result.Actions[0].Status, gc.Equals, "running") - action = result.Actions[1].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") - c.Assert(action.Tag, gc.Equals, "action-3") - c.Assert(result.Actions[1].Status, gc.Equals, "completed") - action = result.Actions[2].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") - c.Assert(action.Tag, gc.Equals, "action-4") - c.Assert(result.Actions[2].Status, gc.Equals, "pending") - action = result.Actions[3].Action - c.Assert(action.Name, gc.Equals, "anotherfakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") - c.Assert(action.Tag, gc.Equals, "action-5") - c.Assert(result.Actions[3].Status, gc.Equals, "pending") -} - -func (s *operationSuite) TestOperations(c *gc.C) { - defer s.setupMocks(c).Finish() - - s.setupOperations(c) - operations, err := s.action.Operations(context.Background(), params.Entities{ - Entities: []params.Entity{{Tag: "operation-1"}}, - }) - c.Assert(err, jc.ErrorIsNil) - c.Assert(operations.Truncated, jc.IsFalse) - c.Assert(operations.Results, gc.HasLen, 1) - result := operations.Results[0] - c.Assert(result.Actions, gc.HasLen, 4) - c.Assert(result.Actions[0].Action, gc.NotNil) - if result.Enqueued.IsZero() { - c.Fatal("enqueued time not set") - } - if result.Started.IsZero() { - c.Fatal("started time not set") - } - c.Assert(result.Status, gc.Equals, "running") - - action := result.Actions[0].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") - c.Assert(action.Tag, gc.Equals, "action-2") - c.Assert(result.Actions[0].Status, gc.Equals, "running") - action = result.Actions[1].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") - c.Assert(action.Tag, gc.Equals, "action-3") - c.Assert(result.Actions[1].Status, gc.Equals, "completed") - action = result.Actions[2].Action - c.Assert(action.Name, gc.Equals, "fakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") - c.Assert(action.Tag, gc.Equals, "action-4") - c.Assert(result.Actions[2].Status, gc.Equals, "pending") - action = result.Actions[3].Action - c.Assert(action.Name, gc.Equals, "anotherfakeaction") - c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") - c.Assert(action.Tag, gc.Equals, "action-5") - c.Assert(result.Actions[3].Status, gc.Equals, "pending") +func (s *operationSuite) TestStub(c *gc.C) { + c.Skip(`This suite is missing tests for the following scenarios: +- ListOperations querying by status. +- ListOperations querying by action names. +- ListOperations querying by application names. +- ListOperations querying by unit names. +- ListOperations querying by machines. +- ListOperations querying with multiple filters - result is union. +- Operations based on input entity tags. +`) } type enqueueSuite struct {