github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/facades/client/action/operation_test.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package action_test 5 6 import ( 7 "strconv" 8 "time" 9 10 "github.com/juju/errors" 11 "github.com/juju/names/v5" 12 jc "github.com/juju/testing/checkers" 13 "github.com/kr/pretty" 14 "go.uber.org/mock/gomock" 15 gc "gopkg.in/check.v1" 16 17 facademocks "github.com/juju/juju/apiserver/facade/mocks" 18 "github.com/juju/juju/apiserver/facades/client/action" 19 "github.com/juju/juju/rpc/params" 20 "github.com/juju/juju/state" 21 ) 22 23 type operationSuite struct { 24 baseSuite 25 } 26 27 var _ = gc.Suite(&operationSuite{}) 28 29 func (s *operationSuite) setupOperations(c *gc.C) { 30 parallel := true 31 executionGroup := "group" 32 arg := params.Actions{ 33 Actions: []params.Action{ 34 {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}, 35 Parallel: ¶llel, ExecutionGroup: &executionGroup}, 36 {Receiver: s.mysqlUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, 37 {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, 38 {Receiver: s.mysqlUnit.Tag().String(), Name: "anotherfakeaction", Parameters: map[string]interface{}{}}, 39 }} 40 41 r, err := s.action.EnqueueOperation(arg) 42 c.Assert(err, jc.ErrorIsNil) 43 c.Assert(r.Actions, gc.HasLen, len(arg.Actions)) 44 45 // There's only one operation created. 46 ops, err := s.Model.AllOperations() 47 c.Assert(err, jc.ErrorIsNil) 48 c.Assert(ops, gc.HasLen, 1) 49 operationID, err := strconv.Atoi(ops[0].Id()) 50 c.Assert(err, jc.ErrorIsNil) 51 52 a, err := s.Model.Action(strconv.Itoa(operationID + 1)) 53 c.Assert(err, jc.ErrorIsNil) 54 c.Assert(a.Parallel(), jc.IsTrue) 55 c.Assert(a.ExecutionGroup(), gc.Equals, "group") 56 _, err = a.Begin() 57 c.Assert(err, jc.ErrorIsNil) 58 a, err = s.Model.Action(strconv.Itoa(operationID + 2)) 59 c.Assert(err, jc.ErrorIsNil) 60 _, err = a.Finish(state.ActionResults{Status: state.ActionCompleted}) 61 c.Assert(err, jc.ErrorIsNil) 62 } 63 64 func (s *operationSuite) TestListOperationsStatusFilter(c *gc.C) { 65 s.setupOperations(c) 66 // Set up a non running operation. 67 arg := params.Actions{ 68 Actions: []params.Action{ 69 {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, 70 }} 71 _, err := s.action.EnqueueOperation(arg) 72 c.Assert(err, jc.ErrorIsNil) 73 74 operations, err := s.action.ListOperations(params.OperationQueryArgs{ 75 Status: []string{"running"}, 76 }) 77 c.Assert(err, jc.ErrorIsNil) 78 c.Assert(operations.Truncated, jc.IsFalse) 79 c.Assert(operations.Results, gc.HasLen, 1) 80 result := operations.Results[0] 81 c.Assert(result.Actions, gc.HasLen, 4) 82 c.Assert(result.Actions[0].Action, gc.NotNil) 83 if result.Enqueued.IsZero() { 84 c.Fatal("enqueued time not set") 85 } 86 if result.Started.IsZero() { 87 c.Fatal("started time not set") 88 } 89 c.Assert(result.Status, gc.Equals, "running") 90 91 action := result.Actions[0].Action 92 c.Assert(action.Name, gc.Equals, "fakeaction") 93 c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") 94 c.Assert(action.Tag, gc.Equals, "action-2") 95 c.Assert(result.Actions[0].Status, gc.Equals, "running") 96 action = result.Actions[1].Action 97 c.Assert(action.Name, gc.Equals, "fakeaction") 98 c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") 99 c.Assert(action.Tag, gc.Equals, "action-3") 100 c.Assert(result.Actions[1].Status, gc.Equals, "completed") 101 action = result.Actions[2].Action 102 c.Assert(action.Name, gc.Equals, "fakeaction") 103 c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") 104 c.Assert(action.Tag, gc.Equals, "action-4") 105 c.Assert(result.Actions[2].Status, gc.Equals, "pending") 106 action = result.Actions[3].Action 107 c.Assert(action.Name, gc.Equals, "anotherfakeaction") 108 c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") 109 c.Assert(action.Tag, gc.Equals, "action-5") 110 c.Assert(result.Actions[3].Status, gc.Equals, "pending") 111 } 112 113 func (s *operationSuite) TestListOperationsNameFilter(c *gc.C) { 114 s.setupOperations(c) 115 // Set up a second operation. 116 arg := params.Actions{ 117 Actions: []params.Action{ 118 {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, 119 }} 120 _, err := s.action.EnqueueOperation(arg) 121 c.Assert(err, jc.ErrorIsNil) 122 123 operations, err := s.action.ListOperations(params.OperationQueryArgs{ 124 ActionNames: []string{"anotherfakeaction"}, 125 }) 126 c.Assert(err, jc.ErrorIsNil) 127 c.Assert(operations.Results, gc.HasLen, 1) 128 result := operations.Results[0] 129 c.Assert(result.Actions, gc.HasLen, 1) 130 c.Assert(result.Actions[0].Action, gc.NotNil) 131 if result.Enqueued.IsZero() { 132 c.Fatal("enqueued time not set") 133 } 134 if result.Started.IsZero() { 135 c.Fatal("started time not set") 136 } 137 c.Assert(result.Status, gc.Equals, "running") 138 action := result.Actions[0].Action 139 c.Assert(action.Name, gc.Equals, "anotherfakeaction") 140 c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") 141 c.Assert(action.Tag, gc.Equals, "action-5") 142 c.Assert(result.Actions[0].Status, gc.Equals, "pending") 143 } 144 145 func (s *operationSuite) TestListOperationsAppFilter(c *gc.C) { 146 s.setupOperations(c) 147 // Set up a second operation for a different app. 148 arg := params.Actions{ 149 Actions: []params.Action{ 150 {Receiver: s.mysqlUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, 151 }} 152 _, err := s.action.EnqueueOperation(arg) 153 c.Assert(err, jc.ErrorIsNil) 154 155 operations, err := s.action.ListOperations(params.OperationQueryArgs{ 156 Applications: []string{"wordpress"}, 157 }) 158 c.Assert(err, jc.ErrorIsNil) 159 c.Assert(operations.Results, gc.HasLen, 1) 160 result := operations.Results[0] 161 162 c.Assert(result.Actions, gc.HasLen, 2) 163 c.Assert(result.Actions[0].Action, gc.NotNil) 164 if result.Enqueued.IsZero() { 165 c.Fatal("enqueued time not set") 166 } 167 if result.Started.IsZero() { 168 c.Fatal("started time not set") 169 } 170 c.Assert(result.Status, gc.Equals, "running") 171 action := result.Actions[0].Action 172 c.Assert(action.Name, gc.Equals, "fakeaction") 173 c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") 174 c.Assert(action.Tag, gc.Equals, "action-2") 175 c.Assert(result.Actions[0].Status, gc.Equals, "running") 176 action = result.Actions[1].Action 177 c.Assert(action.Name, gc.Equals, "fakeaction") 178 c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") 179 c.Assert(action.Tag, gc.Equals, "action-4") 180 c.Assert(result.Actions[1].Status, gc.Equals, "pending") 181 } 182 183 func (s *operationSuite) TestListOperationsUnitFilter(c *gc.C) { 184 s.setupOperations(c) 185 // Set up an operation with a pending action. 186 arg := params.Actions{ 187 Actions: []params.Action{ 188 {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, 189 }} 190 _, err := s.action.EnqueueOperation(arg) 191 c.Assert(err, jc.ErrorIsNil) 192 193 operations, err := s.action.ListOperations(params.OperationQueryArgs{ 194 Units: []string{"wordpress/0"}, 195 Status: []string{"pending"}, 196 }) 197 c.Assert(err, jc.ErrorIsNil) 198 c.Assert(operations.Results, gc.HasLen, 1) 199 result := operations.Results[0] 200 201 c.Assert(result.Actions, gc.HasLen, 1) 202 c.Assert(result.Actions[0].Action, gc.NotNil) 203 if result.Enqueued.IsZero() { 204 c.Fatal("enqueued time not set") 205 } 206 c.Assert(result.Status, gc.Equals, "pending") 207 action := result.Actions[0].Action 208 c.Assert(action.Name, gc.Equals, "fakeaction") 209 c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") 210 c.Assert(action.Tag, gc.Equals, "action-7") 211 c.Assert(result.Actions[0].Status, gc.Equals, "pending") 212 } 213 214 func (s *operationSuite) TestListOperationsMachineFilter(c *gc.C) { 215 s.setupOperations(c) 216 // Set up an operation with a pending action. 217 arg := params.Actions{ 218 Actions: []params.Action{ 219 {Receiver: s.machine0.Tag().String(), Name: "juju-exec", Parameters: map[string]interface{}{ 220 "command": "ls", 221 "timeout": 1, 222 }}, 223 }} 224 _, err := s.action.EnqueueOperation(arg) 225 c.Assert(err, jc.ErrorIsNil) 226 227 operations, err := s.action.ListOperations(params.OperationQueryArgs{ 228 Machines: []string{"0"}, 229 Status: []string{"pending"}, 230 }) 231 c.Assert(err, jc.ErrorIsNil) 232 c.Assert(operations.Results, gc.HasLen, 1) 233 result := operations.Results[0] 234 235 c.Assert(result.Actions, gc.HasLen, 1) 236 c.Assert(result.Actions[0].Action, gc.NotNil) 237 if result.Enqueued.IsZero() { 238 c.Fatal("enqueued time not set") 239 } 240 c.Assert(result.Status, gc.Equals, "pending") 241 action := result.Actions[0].Action 242 c.Assert(action.Name, gc.Equals, "juju-exec") 243 c.Assert(action.Receiver, gc.Equals, "machine-0") 244 c.Assert(action.Tag, gc.Equals, "action-7") 245 c.Assert(result.Actions[0].Status, gc.Equals, "pending") 246 } 247 248 func (s *operationSuite) TestListOperationsAppAndUnitFilter(c *gc.C) { 249 s.setupOperations(c) 250 // Set up an operation with a pending action. 251 arg := params.Actions{ 252 Actions: []params.Action{ 253 {Receiver: s.wordpressUnit.Tag().String(), Name: "fakeaction", Parameters: map[string]interface{}{}}, 254 }} 255 _, err := s.action.EnqueueOperation(arg) 256 c.Assert(err, jc.ErrorIsNil) 257 258 operations, err := s.action.ListOperations(params.OperationQueryArgs{ 259 Applications: []string{"mysql"}, 260 Units: []string{"wordpress/0"}, 261 Status: []string{"running"}, 262 }) 263 c.Assert(err, jc.ErrorIsNil) 264 c.Assert(operations.Results, gc.HasLen, 1) 265 c.Log(pretty.Sprint(operations.Results)) 266 result := operations.Results[0] 267 268 c.Assert(result.Actions, gc.HasLen, 4) 269 c.Assert(result.Actions[0].Action, gc.NotNil) 270 if result.Enqueued.IsZero() { 271 c.Fatal("enqueued time not set") 272 } 273 if result.Started.IsZero() { 274 c.Fatal("started time not set") 275 } 276 277 action := result.Actions[0].Action 278 c.Assert(action.Name, gc.Equals, "fakeaction") 279 c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") 280 c.Assert(action.Tag, gc.Equals, "action-2") 281 c.Assert(result.Actions[0].Status, gc.Equals, "running") 282 action = result.Actions[1].Action 283 c.Assert(action.Name, gc.Equals, "fakeaction") 284 c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") 285 c.Assert(action.Tag, gc.Equals, "action-3") 286 c.Assert(result.Actions[1].Status, gc.Equals, "completed") 287 action = result.Actions[2].Action 288 c.Assert(action.Name, gc.Equals, "fakeaction") 289 c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") 290 c.Assert(action.Tag, gc.Equals, "action-4") 291 c.Assert(result.Actions[2].Status, gc.Equals, "pending") 292 action = result.Actions[3].Action 293 c.Assert(action.Name, gc.Equals, "anotherfakeaction") 294 c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") 295 c.Assert(action.Tag, gc.Equals, "action-5") 296 c.Assert(result.Actions[3].Status, gc.Equals, "pending") 297 } 298 299 func (s *operationSuite) TestOperations(c *gc.C) { 300 s.setupOperations(c) 301 operations, err := s.action.Operations(params.Entities{ 302 Entities: []params.Entity{{Tag: "operation-1"}}, 303 }) 304 c.Assert(err, jc.ErrorIsNil) 305 c.Assert(operations.Truncated, jc.IsFalse) 306 c.Assert(operations.Results, gc.HasLen, 1) 307 result := operations.Results[0] 308 c.Assert(result.Actions, gc.HasLen, 4) 309 c.Assert(result.Actions[0].Action, gc.NotNil) 310 if result.Enqueued.IsZero() { 311 c.Fatal("enqueued time not set") 312 } 313 if result.Started.IsZero() { 314 c.Fatal("started time not set") 315 } 316 c.Assert(result.Status, gc.Equals, "running") 317 318 action := result.Actions[0].Action 319 c.Assert(action.Name, gc.Equals, "fakeaction") 320 c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") 321 c.Assert(action.Tag, gc.Equals, "action-2") 322 c.Assert(result.Actions[0].Status, gc.Equals, "running") 323 action = result.Actions[1].Action 324 c.Assert(action.Name, gc.Equals, "fakeaction") 325 c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") 326 c.Assert(action.Tag, gc.Equals, "action-3") 327 c.Assert(result.Actions[1].Status, gc.Equals, "completed") 328 action = result.Actions[2].Action 329 c.Assert(action.Name, gc.Equals, "fakeaction") 330 c.Assert(action.Receiver, gc.Equals, "unit-wordpress-0") 331 c.Assert(action.Tag, gc.Equals, "action-4") 332 c.Assert(result.Actions[2].Status, gc.Equals, "pending") 333 action = result.Actions[3].Action 334 c.Assert(action.Name, gc.Equals, "anotherfakeaction") 335 c.Assert(action.Receiver, gc.Equals, "unit-mysql-0") 336 c.Assert(action.Tag, gc.Equals, "action-5") 337 c.Assert(result.Actions[3].Status, gc.Equals, "pending") 338 } 339 340 type enqueueSuite struct { 341 action.MockBaseSuite 342 343 wordpressAction *action.MockAction 344 mysqlAction *action.MockAction 345 model *action.MockModel 346 347 modelTag names.ModelTag 348 wordpressUnitTag names.UnitTag 349 mysqlUnitTag names.UnitTag 350 executionGroup string 351 } 352 353 var _ = gc.Suite(&enqueueSuite{}) 354 355 func (s *enqueueSuite) SetUpSuite(c *gc.C) { 356 s.modelTag = names.NewModelTag("model-tag") 357 // mysql will be parallel false 358 s.wordpressUnitTag = names.NewUnitTag("wordpress/0") 359 // mysql will be parallel true 360 s.mysqlUnitTag = names.NewUnitTag("mysql/0") 361 s.executionGroup = "testgroup" 362 } 363 364 func (s *enqueueSuite) TestEnqueueOperation(c *gc.C) { 365 ctrl := s.setupMocks(c) 366 defer ctrl.Finish() 367 368 s.model.EXPECT().EnqueueOperation(gomock.Any(), 2).Return("1", nil) 369 s.expectWordpressActionResult() 370 s.expectMysqlActionResult() 371 372 api := s.NewActionAPI(c) 373 374 expectedName := "fakeaction" 375 f := false 376 t := true 377 arg := params.Actions{ 378 Actions: []params.Action{ 379 { 380 Receiver: s.wordpressUnitTag.String(), 381 Name: expectedName, 382 Parameters: map[string]interface{}{}, 383 Parallel: &f, 384 ExecutionGroup: &s.executionGroup, 385 }, { 386 Receiver: s.mysqlUnitTag.String(), 387 Name: expectedName, 388 Parameters: map[string]interface{}{}, 389 Parallel: &t, 390 ExecutionGroup: &s.executionGroup, 391 }, 392 }} 393 394 r, err := api.EnqueueOperation(arg) 395 c.Assert(err, jc.ErrorIsNil) 396 c.Assert(r.Actions, gc.HasLen, len(arg.Actions)) 397 c.Assert(r.Actions[0].Status, gc.Equals, "running") 398 c.Assert(r.Actions[0].Action.Name, gc.Equals, expectedName) 399 c.Assert(r.Actions[0].Action.Tag, gc.Equals, "action-2") 400 c.Assert(r.Actions[1].Status, gc.Equals, "running") 401 c.Assert(r.Actions[1].Action.Name, gc.Equals, expectedName) 402 c.Assert(r.Actions[1].Action.Tag, gc.Equals, "action-3") 403 } 404 405 func (s *enqueueSuite) TestEnqueueOperationFail(c *gc.C) { 406 ctrl := s.setupMocks(c) 407 defer ctrl.Finish() 408 409 expectedName := "fakeaction" 410 s.model.EXPECT().EnqueueOperation(gomock.Any(), 3).Return("1", nil) 411 s.expectWordpressActionResult() 412 s.model.EXPECT().AddAction(gomock.Any(), "1", expectedName, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.NotFoundf("database txn failure")) 413 leaders := map[string]string{ 414 "test": "test/1", 415 } 416 s.Leadership.EXPECT().Leaders().Return(leaders, nil) 417 s.model.EXPECT().FailOperationEnqueuing("1", "error(s) enqueueing action(s): database txn failure not found, could not determine leader for \"mysql\"", 1) 418 419 api := s.NewActionAPI(c) 420 421 f := false 422 arg := params.Actions{ 423 Actions: []params.Action{ 424 { 425 Receiver: s.wordpressUnitTag.String(), 426 Name: expectedName, 427 Parameters: map[string]interface{}{}, 428 Parallel: &f, 429 ExecutionGroup: &s.executionGroup, 430 }, 431 // AddAction failure. 432 {Receiver: s.mysqlUnitTag.String(), Name: expectedName, Parameters: map[string]interface{}{}}, 433 // Leader failure 434 {Receiver: "mysql/leader", Name: expectedName, Parameters: map[string]interface{}{}}, 435 }} 436 437 r, err := api.EnqueueOperation(arg) 438 c.Assert(err, jc.ErrorIsNil) 439 c.Assert(r.Actions, gc.HasLen, len(arg.Actions)) 440 c.Logf("%s", pretty.Sprint(r.Actions)) 441 c.Assert(r.Actions[0].Status, gc.Equals, "running") 442 c.Assert(r.Actions[0].Action.Name, gc.Equals, expectedName) 443 c.Assert(r.Actions[0].Action.Tag, gc.Equals, "action-2") 444 c.Assert(r.Actions[1].Error, jc.Satisfies, params.IsCodeNotFoundOrCodeUnauthorized) 445 c.Assert(r.Actions[2].Error, gc.DeepEquals, ¶ms.Error{Message: "could not determine leader for \"mysql\"", Code: ""}) 446 } 447 448 func (s *enqueueSuite) TestEnqueueOperationLeadership(c *gc.C) { 449 ctrl := s.setupMocks(c) 450 defer ctrl.Finish() 451 452 s.model.EXPECT().EnqueueOperation(gomock.Any(), 2).Return("1", nil) 453 appName, _ := names.UnitApplication(s.mysqlUnitTag.Id()) 454 leaders := map[string]string{ 455 "test": "test/1", 456 appName: s.mysqlUnitTag.Id(), 457 } 458 s.Leadership.EXPECT().Leaders().Return(leaders, nil) 459 s.expectWordpressActionResult() 460 s.expectMysqlActionResult() 461 462 api := s.NewActionAPI(c) 463 464 expectedName := "fakeaction" 465 f := false 466 t := true 467 arg := params.Actions{ 468 Actions: []params.Action{ 469 { 470 Receiver: s.wordpressUnitTag.String(), 471 Name: expectedName, 472 Parameters: map[string]interface{}{}, 473 Parallel: &f, 474 ExecutionGroup: &s.executionGroup, 475 }, { 476 Receiver: "mysql/leader", 477 Name: expectedName, 478 Parameters: map[string]interface{}{}, 479 Parallel: &t, 480 ExecutionGroup: &s.executionGroup, 481 }, 482 }} 483 484 r, err := api.EnqueueOperation(arg) 485 c.Assert(err, jc.ErrorIsNil) 486 c.Assert(r.Actions, gc.HasLen, len(arg.Actions)) 487 c.Assert(r.Actions[0].Status, gc.Equals, "running") 488 c.Assert(r.Actions[0].Action.Name, gc.Equals, expectedName) 489 c.Assert(r.Actions[0].Action.Tag, gc.Equals, "action-2") 490 c.Assert(r.Actions[1].Status, gc.Equals, "running") 491 c.Assert(r.Actions[1].Action.Name, gc.Equals, expectedName) 492 c.Assert(r.Actions[1].Action.Tag, gc.Equals, "action-3") 493 } 494 495 func (s *enqueueSuite) setupMocks(c *gc.C) *gomock.Controller { 496 ctrl := gomock.NewController(c) 497 s.Authorizer = facademocks.NewMockAuthorizer(ctrl) 498 s.Authorizer.EXPECT().HasPermission(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() 499 s.Authorizer.EXPECT().AuthClient().Return(true) 500 501 s.model = action.NewMockModel(ctrl) 502 s.model.EXPECT().ModelTag().Return(s.modelTag).MinTimes(1) 503 504 s.State = action.NewMockState(ctrl) 505 s.State.EXPECT().Model().Return(s.model, nil) 506 507 s.ActionReceiver = action.NewMockActionReceiver(ctrl) 508 s.Leadership = action.NewMockReader(ctrl) 509 510 s.wordpressAction = action.NewMockAction(ctrl) 511 s.mysqlAction = action.NewMockAction(ctrl) 512 513 return ctrl 514 } 515 516 func (s *enqueueSuite) expectWordpressActionResult() { 517 f := false 518 s.model.EXPECT().AddAction(gomock.Any(), "1", "fakeaction", map[string]interface{}{}, &f, &s.executionGroup).Return(s.wordpressAction, nil) 519 s.ActionReceiver.EXPECT().Tag().Return(s.wordpressUnitTag) 520 aExp := s.wordpressAction.EXPECT() 521 aExp.ActionTag().Return(names.NewActionTag("2")) 522 aExp.Status().Return(state.ActionRunning) 523 aExp.Name().Return("fakeaction") 524 aExp.Parameters().Return(map[string]interface{}{}) 525 aExp.Messages().Return(nil) 526 aExp.Results().Return(map[string]interface{}{}, "result") 527 aExp.Started().Return(time.Now()) 528 aExp.Completed().Return(time.Now()) 529 aExp.Enqueued().Return(time.Now()) 530 aExp.Parallel().Return(f) 531 aExp.ExecutionGroup().Return(s.executionGroup) 532 } 533 534 func (s *enqueueSuite) expectMysqlActionResult() { 535 t := true 536 s.model.EXPECT().AddAction(gomock.Any(), "1", "fakeaction", map[string]interface{}{}, &t, &s.executionGroup).Return(s.mysqlAction, nil) 537 s.ActionReceiver.EXPECT().Tag().Return(s.mysqlUnitTag) 538 aExp := s.mysqlAction.EXPECT() 539 aExp.ActionTag().Return(names.NewActionTag("3")) 540 aExp.Status().Return(state.ActionRunning) 541 aExp.Name().Return("fakeaction") 542 aExp.Parameters().Return(map[string]interface{}{}) 543 aExp.Messages().Return(nil) 544 aExp.Results().Return(map[string]interface{}{}, "result") 545 aExp.Started().Return(time.Now()) 546 aExp.Completed().Return(time.Now()) 547 aExp.Enqueued().Return(time.Now()) 548 aExp.Parallel().Return(t) 549 aExp.ExecutionGroup().Return(s.executionGroup) 550 }