func (s *runcommandsSuite) SetUpTest(c *gc.C) { s.charmURL = charm.MustParseURL("cs:precise/mysql-2") s.remoteState = remotestate.Snapshot{ CharmURL: s.charmURL, } s.mockRunner = mockRunner{runCommands: func(commands string) (*exec.ExecResponse, error) { return s.runCommands(commands) }} s.callbacks = &mockCallbacks{} s.opFactory = operation.NewFactory(operation.FactoryParams{ Callbacks: s.callbacks, RunnerFactory: &mockRunnerFactory{ newCommandRunner: func(info runnercontext.CommandInfo) (runner.Runner, error) { return &s.mockRunner, nil }, }, }) s.commands = runcommands.NewCommands() s.commandCompleted = nil s.resolver = runcommands.NewCommandsResolver( s.commands, func(id string) { if s.commandCompleted != nil { s.commandCompleted(id) } }, ) }
func (s *RunHookSuite) testPrepareHookError( c *gc.C, newHook newHook, expectClearResolvedFlag, expectSkip bool, ) { callbacks := &PrepareHookCallbacks{ MockPrepareHook: &MockPrepareHook{err: errors.New("pow")}, MockClearResolvedFlag: &MockNoArgs{}, } factory := operation.NewFactory(operation.FactoryParams{ Callbacks: callbacks, }) op, err := newHook(factory, hook.Info{Kind: hooks.ConfigChanged}) c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{}) c.Check(newState, gc.IsNil) c.Check(callbacks.MockClearResolvedFlag.called, gc.Equals, expectClearResolvedFlag) if expectSkip { c.Check(err, gc.Equals, operation.ErrSkipExecute) c.Check(callbacks.MockPrepareHook.gotHook, gc.IsNil) return } c.Check(err, gc.ErrorMatches, "pow") c.Check(callbacks.MockPrepareHook.gotHook, gc.DeepEquals, &hook.Info{ Kind: hooks.ConfigChanged, }) }
func (s *MetricsOperationSuite) TestSendingFails(c *gc.C) { apiSender := newTestAPIMetricSender() factory := operation.NewFactory(operation.FactoryParams{ MetricSender: apiSender, MetricSpoolDir: s.spoolDir, }) sendOperation, err := factory.NewSendMetrics() c.Assert(err, gc.IsNil) _, err = sendOperation.Prepare(operation.State{}) c.Assert(err, jc.ErrorIsNil) select { case apiSender.sendError <- errors.New("something went wrong"): default: c.Fatalf("blocked error channel") } _, err = sendOperation.Execute(operation.State{}) c.Assert(err, jc.ErrorIsNil) c.Assert(apiSender.batches, gc.HasLen, 1) reader, err := metrics.NewJSONMetricReader(s.spoolDir) c.Assert(err, gc.IsNil) batches, err := reader.Read() c.Assert(err, gc.IsNil) c.Assert(batches, gc.HasLen, 1) }
func (s *RunHookSuite) TestPrepareHookCtxError(c *gc.C) { ctx := &MockContext{} ctx.SetErrors(errors.New("ctx prepare error")) callbacks := &PrepareHookCallbacks{ MockPrepareHook: &MockPrepareHook{}, } runnerFactory := &MockRunnerFactory{ MockNewHookRunner: &MockNewHookRunner{ runner: &MockRunner{ context: ctx, }, }, } factory := operation.NewFactory(operation.FactoryParams{ RunnerFactory: runnerFactory, Callbacks: callbacks, }) op, err := factory.NewRunHook(hook.Info{Kind: hooks.ConfigChanged}) c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{}) c.Check(newState, gc.IsNil) c.Assert(err, gc.ErrorMatches, `ctx prepare error`) ctx.CheckCall(c, 0, "Prepare") }
func (s *MetricsOperationSuite) TestSendingGetDuplicate(c *gc.C) { apiSender := newTestAPIMetricSender() factory := operation.NewFactory(operation.FactoryParams{ MetricSender: apiSender, MetricSpoolDir: s.spoolDir, }) sendOperation, err := factory.NewSendMetrics() c.Assert(err, gc.IsNil) _, err = sendOperation.Prepare(operation.State{}) c.Assert(err, jc.ErrorIsNil) apiErr := ¶ms.Error{Message: "already exists", Code: params.CodeAlreadyExists} select { case apiSender.errors <- apiErr: default: c.Fatalf("blocked error channel") } _, err = sendOperation.Execute(operation.State{}) c.Assert(err, jc.ErrorIsNil) c.Assert(apiSender.batches, gc.HasLen, 1) reader, err := metrics.NewJSONMetricReader(s.spoolDir) c.Assert(err, gc.IsNil) batches, err := reader.Read() c.Assert(err, gc.IsNil) c.Assert(batches, gc.HasLen, 0) }
func (s *MetricsOperationSuite) TestMetricSendingSuccess(c *gc.C) { apiSender := newTestAPIMetricSender() factory := operation.NewFactory(operation.FactoryParams{ MetricSender: apiSender, MetricSpoolDir: s.spoolDir, }) sendOperation, err := factory.NewSendMetrics() c.Assert(err, gc.IsNil) _, err = sendOperation.Prepare(operation.State{}) c.Assert(err, jc.ErrorIsNil) _, err = sendOperation.Execute(operation.State{}) c.Assert(err, jc.ErrorIsNil) c.Assert(apiSender.batches, gc.HasLen, 1) reader, err := metrics.NewJSONMetricReader(s.spoolDir) c.Assert(err, gc.IsNil) batches, err := reader.Read() c.Assert(err, gc.IsNil) c.Assert(batches, gc.HasLen, 0) }
func (s *DeploySuite) testNotifyDeployerError( c *gc.C, newDeploy newDeploy, expectNotifyRevert bool, ) { callbacks := &DeployCallbacks{ MockClearResolvedFlag: &MockNoArgs{}, } deployer := &MockDeployer{} expectCall := &MockNoArgs{err: errors.New("snh")} if expectNotifyRevert { deployer.MockNotifyRevert = expectCall } else { deployer.MockNotifyResolved = expectCall } factory := operation.NewFactory(operation.FactoryParams{ Callbacks: callbacks, Deployer: deployer, }) op, err := newDeploy(factory, curl("cs:quantal/hive-23")) c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{}) c.Check(newState, gc.IsNil) c.Check(err, gc.ErrorMatches, "snh") c.Check(expectCall.called, jc.IsTrue) }
func (s *resolverSuite) SetUpTest(c *gc.C) { s.stub = testing.Stub{} s.charmURL = charm.MustParseURL("cs:precise/mysql-2") s.remoteState = remotestate.Snapshot{ CharmModifiedVersion: s.charmModifiedVersion, CharmURL: s.charmURL, } s.opFactory = operation.NewFactory(operation.FactoryParams{}) attachments, err := storage.NewAttachments(&dummyStorageAccessor{}, names.NewUnitTag("u/0"), c.MkDir(), nil) c.Assert(err, jc.ErrorIsNil) s.clearResolved = func() error { return errors.New("unexpected resolved") } s.reportHookError = func(hook.Info) error { return errors.New("unexpected report hook error") } s.resolverConfig = uniter.ResolverConfig{ ClearResolved: func() error { return s.clearResolved() }, ReportHookError: func(info hook.Info) error { return s.reportHookError(info) }, StartRetryHookTimer: func() { s.stub.AddCall("StartRetryHookTimer") }, StopRetryHookTimer: func() { s.stub.AddCall("StopRetryHookTimer") }, ShouldRetryHooks: true, Leadership: leadership.NewResolver(), Actions: uniteractions.NewResolver(), Relations: relation.NewRelationsResolver(&dummyRelations{}), Storage: storage.NewResolver(attachments), Commands: nopResolver{}, } s.resolver = uniter.NewUniterResolver(s.resolverConfig) }
func (s *RunHookSuite) TestPrepareHookCtxCalled(c *gc.C) { ctx := &MockContext{} callbacks := &PrepareHookCallbacks{ MockPrepareHook: &MockPrepareHook{}, MockClearResolvedFlag: &MockNoArgs{}, } runnerFactory := &MockRunnerFactory{ MockNewHookRunner: &MockNewHookRunner{ runner: &MockRunner{ context: ctx, }, }, } factory := operation.NewFactory(operation.FactoryParams{ RunnerFactory: runnerFactory, Callbacks: callbacks, }) op, err := factory.NewRunHook(hook.Info{Kind: hooks.ConfigChanged}) c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{}) c.Check(newState, gc.NotNil) c.Assert(err, jc.ErrorIsNil) ctx.CheckCall(c, 0, "Prepare") }
func (s *RunCommandsSuite) TestPrepareSuccess(c *gc.C) { ctx := &MockContext{} runnerFactory := &MockRunnerFactory{ MockNewCommandRunner: &MockNewCommandRunner{ runner: &MockRunner{ context: ctx, }, }, } factory := operation.NewFactory(operation.FactoryParams{ RunnerFactory: runnerFactory, }) sendResponse := func(*utilexec.ExecResponse, error) { panic("not expected") } op, err := factory.NewCommands(someCommandArgs, sendResponse) c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{}) c.Assert(err, jc.ErrorIsNil) c.Assert(newState, gc.IsNil) c.Assert(*runnerFactory.MockNewCommandRunner.gotInfo, gc.Equals, runner.CommandInfo{ RelationId: 123, RemoteUnitName: "foo/456", ForceRemoteUnit: true, }) ctx.CheckCall(c, 0, "Prepare") }
func (s *DeploySuite) testPrepareStageError(c *gc.C, newDeploy newDeploy) { callbacks := &DeployCallbacks{ MockClearResolvedFlag: &MockNoArgs{}, MockGetArchiveInfo: &MockGetArchiveInfo{info: &MockBundleInfo{}}, } deployer := &MockDeployer{ MockNotifyRevert: &MockNoArgs{}, MockNotifyResolved: &MockNoArgs{}, MockStage: &MockStage{err: errors.New("squish")}, } var abort <-chan struct{} = make(chan struct{}) factory := operation.NewFactory(operation.FactoryParams{ Deployer: deployer, Callbacks: callbacks, Abort: abort, }) op, err := newDeploy(factory, curl("cs:quantal/hive-23")) c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{}) c.Check(newState, gc.IsNil) c.Check(err, gc.ErrorMatches, "squish") c.Check(*deployer.MockStage.gotInfo, gc.Equals, callbacks.MockGetArchiveInfo.info) c.Check(*deployer.MockStage.gotAbort, gc.Equals, abort) }
func (s *RunHookSuite) testCommitSuccess_CollectMetricsTime(c *gc.C, newHook newHook) { callbacks := &CommitHookCallbacks{ MockCommitHook: &MockCommitHook{}, } factory := operation.NewFactory(operation.FactoryParams{ Callbacks: callbacks, }) op, err := newHook(factory, hook.Info{Kind: hooks.CollectMetrics}) c.Assert(err, jc.ErrorIsNil) nowBefore := time.Now().Unix() newState, err := op.Commit(overwriteState) c.Assert(err, jc.ErrorIsNil) nowAfter := time.Now().Unix() nowWritten := newState.CollectMetricsTime c.Logf("%d <= %d <= %d", nowBefore, nowWritten, nowAfter) c.Check(nowBefore <= nowWritten, jc.IsTrue) c.Check(nowWritten <= nowAfter, jc.IsTrue) // Check the other fields match. newState.CollectMetricsTime = 0 c.Check(newState, gc.DeepEquals, &operation.State{ Started: true, Kind: operation.Continue, Step: operation.Pending, UpdateStatusTime: 1234567, }) }
func (s *DeploySuite) testExecuteConflictError(c *gc.C, newDeploy newDeploy) { callbacks := NewDeployCallbacks() deployer := &MockDeployer{ MockNotifyRevert: &MockNoArgs{}, MockNotifyResolved: &MockNoArgs{}, MockStage: &MockStage{}, MockDeploy: &MockNoArgs{err: charm.ErrConflict}, } factory := operation.NewFactory(operation.FactoryParams{ Deployer: deployer, Callbacks: callbacks, }) charmURL := curl("cs:quantal/nyancat-4") op, err := newDeploy(factory, charmURL) c.Assert(err, jc.ErrorIsNil) _, err = op.Prepare(operation.State{}) c.Assert(err, jc.ErrorIsNil) newState, err := op.Execute(operation.State{}) c.Check(newState, gc.IsNil) c.Check(err, gc.ErrorMatches, "cannot deploy charm cs:quantal/nyancat-4") ok := operation.IsDeployConflictError(err) c.Check(ok, jc.IsTrue) c.Check(deployer.MockDeploy.called, jc.IsTrue) }
func (s *RunCommandsSuite) TestNeedsGlobalMachineLock(c *gc.C) { factory := operation.NewFactory(operation.FactoryParams{}) sendResponse := &MockSendResponse{} op, err := factory.NewCommands(someCommandArgs, sendResponse.Call) c.Assert(err, jc.ErrorIsNil) c.Assert(op.NeedsGlobalMachineLock(), jc.IsTrue) }
func (s *UpdateRelationsSuite) TestPrepare(c *gc.C) { factory := operation.NewFactory(operation.FactoryParams{}) op, err := factory.NewUpdateRelations(nil) c.Assert(err, jc.ErrorIsNil) state, err := op.Prepare(operation.State{}) c.Check(err, jc.ErrorIsNil) c.Check(state, gc.IsNil) }
func (s *UpdateRelationsSuite) TestCommit(c *gc.C) { factory := operation.NewFactory(nil, nil, nil, nil, nil) op, err := factory.NewUpdateRelations(nil) c.Assert(err, jc.ErrorIsNil) state, err := op.Commit(operation.State{}) c.Check(err, jc.ErrorIsNil) c.Check(state, gc.IsNil) }
func (s *UpdateStorageSuite) TestPrepare(c *gc.C) { factory := operation.NewFactory(nil, nil, nil, nil, nil) op, err := factory.NewUpdateStorage(nil) c.Assert(err, jc.ErrorIsNil) state, err := op.Prepare(operation.State{}) c.Check(err, jc.ErrorIsNil) c.Check(state, gc.IsNil) }
func (s *UpdateStorageSuite) TestCommit(c *gc.C) { factory := operation.NewFactory(operation.FactoryParams{}) op, err := factory.NewUpdateStorage(nil) c.Assert(err, jc.ErrorIsNil) state, err := op.Commit(operation.State{}) c.Check(err, jc.ErrorIsNil) c.Check(state, gc.IsNil) }
func (s *FactorySuite) SetUpTest(c *gc.C) { s.IsolationSuite.SetUpTest(c) // Yes, this factory will produce useless ops; this suite is just for // verifying that inadequate args to the factory methods will produce // the expected errors; and that the results of same get a string // representation that does not depend on the factory attributes. s.factory = operation.NewFactory(operation.FactoryParams{}) }
func (s *LeaderSuite) TestResignLeadership_Prepare_Leader(c *gc.C) { factory := operation.NewFactory(nil, nil, nil, nil, nil) op, err := factory.NewResignLeadership() c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{Leader: true}) c.Check(newState, gc.IsNil) c.Check(err, jc.ErrorIsNil) }
func (s *RunCommandsSuite) TestCommit(c *gc.C) { factory := operation.NewFactory(operation.FactoryParams{}) sendResponse := func(*utilexec.ExecResponse, error) { panic("not expected") } op, err := factory.NewCommands(someCommandArgs, sendResponse) c.Assert(err, jc.ErrorIsNil) newState, err := op.Commit(operation.State{}) c.Assert(newState, gc.IsNil) c.Assert(err, jc.ErrorIsNil) }
func (s *LeaderSuite) TestResignLeadership_Prepare_NotLeader(c *gc.C) { factory := operation.NewFactory(operation.FactoryParams{}) op, err := factory.NewResignLeadership() c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{}) c.Check(newState, gc.IsNil) c.Check(err, gc.Equals, operation.ErrSkipExecute) }
func (s *DeploySuite) testCommitMetricsError(c *gc.C, newDeploy newDeploy) { callbacks := NewDeployCommitCallbacks(errors.New("glukh")) factory := operation.NewFactory(nil, nil, callbacks, nil, nil) op, err := newDeploy(factory, curl("cs:quantal/x-0")) c.Assert(err, jc.ErrorIsNil) newState, err := op.Commit(operation.State{}) c.Check(err, gc.ErrorMatches, "glukh") c.Check(newState, gc.IsNil) }
func (s *LeaderSuite) TestResignLeadership_Commit_ClearLeader(c *gc.C) { factory := operation.NewFactory(operation.FactoryParams{}) op, err := factory.NewResignLeadership() c.Assert(err, jc.ErrorIsNil) newState, err := op.Commit(operation.State{Leader: true}) c.Check(newState, gc.DeepEquals, &operation.State{}) c.Check(err, jc.ErrorIsNil) }
func (s *LeaderSuite) TestResignLeadership_Commit_PreserveOthers(c *gc.C) { factory := operation.NewFactory(operation.FactoryParams{}) op, err := factory.NewResignLeadership() c.Assert(err, jc.ErrorIsNil) newState, err := op.Commit(overwriteState) c.Check(newState, gc.DeepEquals, &overwriteState) c.Check(err, jc.ErrorIsNil) }
func (s *LeaderSuite) TestAcceptLeadership_Prepare_NotLeader(c *gc.C) { factory := operation.NewFactory(operation.FactoryParams{}) op, err := factory.NewAcceptLeadership() c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{Kind: operation.Continue}) c.Check(newState, gc.IsNil) // *execute* is currently just a no-op -- all the meat happens in commit. c.Check(err, gc.Equals, operation.ErrSkipExecute) }
func (s *LeaderSuite) TestAcceptLeadership_Prepare_BadState(c *gc.C) { factory := operation.NewFactory(operation.FactoryParams{}) op, err := factory.NewAcceptLeadership() c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{}) c.Check(newState, gc.IsNil) // accept is only valid in Continue mode, when we're sure nothing is queued // or in progress. c.Check(err, gc.Equals, operation.ErrCannotAcceptLeadership) }
func (s *LeaderSuite) TestResignLeadership_Commit_All(c *gc.C) { factory := operation.NewFactory(operation.FactoryParams{}) op, err := factory.NewResignLeadership() c.Assert(err, jc.ErrorIsNil) leaderState := overwriteState leaderState.Leader = true newState, err := op.Commit(leaderState) c.Check(newState, gc.DeepEquals, &overwriteState) c.Check(err, jc.ErrorIsNil) }
func (s *DeploySuite) testClearResolvedFlagError(c *gc.C, newDeploy newDeploy) { callbacks := &DeployCallbacks{ MockClearResolvedFlag: &MockNoArgs{err: errors.New("blort")}, } factory := operation.NewFactory(nil, nil, callbacks, nil, nil) op, err := newDeploy(factory, curl("cs:quantal/hive-23")) c.Assert(err, jc.ErrorIsNil) newState, err := op.Prepare(operation.State{}) c.Check(newState, gc.IsNil) c.Check(err, gc.ErrorMatches, "blort") c.Check(callbacks.MockClearResolvedFlag.called, jc.IsTrue) }
func (s *RunActionSuite) TestCommit(c *gc.C) { var stateChangeTests = []struct { description string before operation.State after operation.State }{{ description: "empty state", after: operation.State{ Kind: operation.Continue, Step: operation.Pending, }, }, { description: "preserves only appropriate fields, no hook", before: operation.State{ Kind: operation.Continue, Step: operation.Pending, Started: true, CharmURL: curl("cs:quantal/wordpress-2"), ActionId: &randomActionId, }, after: operation.State{ Kind: operation.Continue, Step: operation.Pending, Started: true, }, }, { description: "preserves only appropriate fields, with hook", before: operation.State{ Kind: operation.Continue, Step: operation.Pending, Started: true, CharmURL: curl("cs:quantal/wordpress-2"), ActionId: &randomActionId, Hook: &hook.Info{Kind: hooks.Install}, }, after: operation.State{ Kind: operation.RunHook, Step: operation.Pending, Hook: &hook.Info{Kind: hooks.Install}, Started: true, }, }} for i, test := range stateChangeTests { c.Logf("test %d: %s", i, test.description) factory := operation.NewFactory(operation.FactoryParams{}) op, err := factory.NewAction(someActionId) c.Assert(err, jc.ErrorIsNil) newState, err := op.Commit(test.before) c.Assert(newState, jc.DeepEquals, &test.after) } }