func (s *ImportSuite) TestStreamCharmsTools(c *gc.C) { model := description.NewModel(description.ModelArgs{ Owner: names.NewUserTag("me"), }) model.AddService(description.ServiceArgs{ Tag: names.NewServiceTag("magic"), CharmURL: "local:trusty/magic", }) model.AddService(description.ServiceArgs{ Tag: names.NewServiceTag("magic"), CharmURL: "cs:trusty/postgresql-42", }) uploader := &fakeUploader{charms: make(map[string]string)} config := migration.UploadBinariesConfig{ State: &fakeStateStorage{}, Model: model, Target: &fakeAPIConnection{}, GetCharmUploader: func(api.Connection) migration.CharmUploader { return uploader }, GetToolsUploader: func(target api.Connection) migration.ToolsUploader { return &noOpUploader{} }, GetStateStorage: func(migration.UploadBackend) storage.Storage { return &fakeCharmsStorage{} }, GetCharmStoragePath: func(_ migration.UploadBackend, u *charm.URL) (string, error) { return "/path/for/" + u.String(), nil }, } err := migration.UploadBinaries(config) c.Assert(err, jc.ErrorIsNil) c.Assert(uploader.charms, jc.DeepEquals, map[string]string{ "local:trusty/magic": "fake file at /path/for/local:trusty/magic", "cs:trusty/postgresql-42": "fake file at /path/for/cs:trusty/postgresql-42", }) }
// Rescale requests that all supplied service names be rescaled to // their minimum configured sizes. It returns the first error it // encounters. func (api *API) Rescale(services []string) error { args := params.Entities{ Entities: make([]params.Entity, len(services)), } for i, service := range services { if !names.IsValidService(service) { return errors.NotValidf("service name %q", service) } tag := names.NewServiceTag(service) args.Entities[i].Tag = tag.String() } var results params.ErrorResults err := api.caller.FacadeCall("Rescale", args, &results) if err != nil { return errors.Trace(err) } for _, result := range results.Results { if result.Error != nil { if err == nil { err = result.Error } else { logger.Errorf("additional rescale error: %v", err) } } } return errors.Trace(err) }
func (s *settingsSuite) TestWriteSettings(c *gc.C) { numWriteSettingCalls := 0 writeSettings := func(serviceId string, settings map[string]string) error { numWriteSettingCalls++ c.Check(serviceId, gc.Equals, StubServiceNm) return nil } numIsLeaderCalls := 0 isLeader := func(serviceId, unitId string) (bool, error) { numIsLeaderCalls++ c.Check(serviceId, gc.Equals, StubServiceNm) c.Check(unitId, gc.Equals, StubUnitNm) return true, nil } accessor := NewLeadershipSettingsAccessor(&stubAuthorizer{}, nil, nil, writeSettings, isLeader) results, err := accessor.Merge(params.MergeLeadershipSettingsBulkParams{ []params.MergeLeadershipSettingsParam{ { ServiceTag: names.NewServiceTag(StubServiceNm).String(), Settings: map[string]string{"baz": "biz"}, }, }, }) c.Assert(err, gc.IsNil) c.Assert(results.Results, gc.HasLen, 1) c.Check(results.Results[0].Error, gc.IsNil) c.Check(numWriteSettingCalls, gc.Equals, 1) c.Check(numIsLeaderCalls, gc.Equals, 1) }
func (*FacadeSuite) TestWatchSuccess(c *gc.C) { caller := apiCaller(c, func(_ string, _, results interface{}) error { typed, ok := results.(*params.NotifyWatchResults) c.Assert(ok, jc.IsTrue) *typed = params.NotifyWatchResults{ Results: []params.NotifyWatchResult{{ NotifyWatcherId: "123", }}, } return nil }) expectWatcher := &struct{ watcher.NotifyWatcher }{} newWatcher := func(apiCaller base.APICaller, result params.NotifyWatchResult) watcher.NotifyWatcher { c.Check(apiCaller, gc.NotNil) // uncomparable c.Check(result, jc.DeepEquals, params.NotifyWatchResult{ NotifyWatcherId: "123", }) return expectWatcher } facade := lifeflag.NewFacade(caller, newWatcher) watcher, err := facade.Watch(names.NewServiceTag("blah")) c.Check(err, jc.ErrorIsNil) c.Check(watcher, gc.Equals, expectWatcher) }
func (*ScaryConnectSuite) TestEntityUnknownLife(c *gc.C) { // "random" failure case stub := &testing.Stub{} expectConn := &mockConn{stub: stub} apiOpen := func(info *api.Info, opts api.DialOpts) (api.Connection, error) { return expectConn, nil } entity := names.NewServiceTag("omg") connect := func() (api.Connection, error) { return apicaller.ScaryConnect(&mockAgent{ stub: stub, model: coretesting.ModelTag, entity: entity, }, apiOpen) } conn, err := lifeTest(c, stub, apiagent.Life("zombie"), connect) c.Check(conn, gc.IsNil) c.Check(err, gc.ErrorMatches, `unknown life value "zombie"`) stub.CheckCalls(c, []testing.StubCall{{ FuncName: "Life", Args: []interface{}{entity}, }, { FuncName: "Close", }}) }
func (s *leadershipSuite) TestClaimLeadershipTranslation(c *gc.C) { var ldrMgr stubLeadershipManager ldrMgr.ClaimLeadershipFn = func(sid, uid string, duration time.Duration) error { c.Check(sid, gc.Equals, StubServiceNm) c.Check(uid, gc.Equals, StubUnitNm) expectDuration := time.Duration(299.9 * float64(time.Second)) checkDurationEquals(c, duration, expectDuration) return nil } ldrSvc := &leadershipService{LeadershipManager: &ldrMgr, authorizer: &stubAuthorizer{}} results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ Params: []params.ClaimLeadershipParams{ { ServiceTag: names.NewServiceTag(StubServiceNm).String(), UnitTag: names.NewUnitTag(StubUnitNm).String(), DurationSeconds: 299.9, }, }, }) c.Check(err, jc.ErrorIsNil) c.Assert(results.Results, gc.HasLen, 1) c.Check(results.Results[0].Error, gc.IsNil) }
// prepareClaimLeadership creates a single set of params in // preperation for making a bulk call. func (c *client) prepareClaimLeadership(serviceId, unitId string, duration time.Duration) params.ClaimLeadershipParams { return params.ClaimLeadershipParams{ names.NewServiceTag(serviceId).String(), names.NewUnitTag(unitId).String(), duration.Seconds(), } }
func testEntityFine(c *gc.C, life apiagent.Life) { stub := &testing.Stub{} expectConn := &mockConn{stub: stub} apiOpen := func(info *api.Info, opts api.DialOpts) (api.Connection, error) { // no apiOpen stub calls necessary in this suite; covered // by RetrySuite, just an extra complication here. return expectConn, nil } // to make the point that this code should be entity-agnostic, // use an entity that doesn't correspond to an agent at all. entity := names.NewServiceTag("omg") connect := func() (api.Connection, error) { return apicaller.ScaryConnect(&mockAgent{ stub: stub, model: coretesting.ModelTag, entity: entity, }, apiOpen) } conn, err := lifeTest(c, stub, apiagent.Alive, connect) c.Check(conn, gc.Equals, expectConn) c.Check(err, jc.ErrorIsNil) stub.CheckCalls(c, []testing.StubCall{{ FuncName: "Life", Args: []interface{}{entity}, }, { FuncName: "SetPassword", Args: []interface{}{entity, "new"}, }}) }
// NewAddPendingResourcesArgs returns the arguments for the // AddPendingResources API endpoint. func NewAddPendingResourcesArgs(serviceID string, chID charmstore.CharmID, csMac *macaroon.Macaroon, resources []charmresource.Resource) (AddPendingResourcesArgs, error) { var args AddPendingResourcesArgs if !names.IsValidService(serviceID) { return args, errors.Errorf("invalid service %q", serviceID) } tag := names.NewServiceTag(serviceID).String() var apiResources []CharmResource for _, res := range resources { if err := res.Validate(); err != nil { return args, errors.Trace(err) } apiRes := CharmResource2API(res) apiResources = append(apiResources, apiRes) } args.Tag = tag args.Resources = apiResources if chID.URL != nil { args.URL = chID.URL.String() args.Channel = string(chID.Channel) args.CharmStoreMacaroon = csMac } return args, nil }
func (s *leadershipSuite) TestClaimLeadershipDeniedError(c *gc.C) { var ldrMgr stubLeadershipManager ldrMgr.ClaimLeadershipFn = func(sid, uid string, duration time.Duration) error { c.Check(sid, gc.Equals, StubServiceNm) c.Check(uid, gc.Equals, StubUnitNm) expectDuration := time.Duration(5.001 * float64(time.Second)) checkDurationEquals(c, duration, expectDuration) return errors.Annotatef(leadership.ErrClaimDenied, "obfuscated") } ldrSvc := &leadershipService{LeadershipManager: &ldrMgr, authorizer: &stubAuthorizer{}} results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ Params: []params.ClaimLeadershipParams{ { ServiceTag: names.NewServiceTag(StubServiceNm).String(), UnitTag: names.NewUnitTag(StubUnitNm).String(), DurationSeconds: 5.001, }, }, }) c.Check(err, jc.ErrorIsNil) c.Assert(results.Results, gc.HasLen, 1) c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeLeadershipClaimDenied) }
func checkChangePassword(c *gc.C, errs ...error) (*testing.Stub, error) { // We prepend the unauth/success pair that triggers password // change, and consume them in apiOpen below... errUnauth := ¶ms.Error{Code: params.CodeUnauthorized} allErrs := append([]error{errUnauth, nil}, errs...) stub := &testing.Stub{} stub.SetErrors(allErrs...) expectConn := &mockConn{stub: stub} apiOpen := func(info *api.Info, opts api.DialOpts) (api.Connection, error) { // ...but we *don't* record the calls themselves; they // are tested plenty elsewhere, and hiding them makes // client code simpler. if err := stub.NextErr(); err != nil { return nil, err } return expectConn, nil } entity := names.NewServiceTag("omg") connect := func() (api.Connection, error) { return apicaller.ScaryConnect(&mockAgent{ stub: stub, model: coretesting.ModelTag, entity: entity, }, apiOpen) } conn, err := lifeTest(c, stub, apiagent.Alive, connect) c.Check(conn, gc.IsNil) return stub, err }
func (*ScaryConnectSuite) TestEntityDenied(c *gc.C) { // permanent failure case stub := &testing.Stub{} stub.SetErrors(apiagent.ErrDenied) expectConn := &mockConn{stub: stub} apiOpen := func(info *api.Info, opts api.DialOpts) (api.Connection, error) { return expectConn, nil } entity := names.NewServiceTag("omg") connect := func() (api.Connection, error) { return apicaller.ScaryConnect(&mockAgent{ stub: stub, model: coretesting.ModelTag, entity: entity, }, apiOpen) } conn, err := lifeTest(c, stub, apiagent.Dead, connect) c.Check(conn, gc.IsNil) c.Check(err, gc.Equals, apicaller.ErrConnectImpossible) stub.CheckCalls(c, []testing.StubCall{{ FuncName: "Life", Args: []interface{}{entity}, }, { FuncName: "Close", }}) }
func (s *agentAuthenticatorSuite) TestNotSupportedTag(c *gc.C) { srv := newServer(c, s.State) defer srv.Stop() authenticator, err := apiserver.ServerAuthenticatorForTag(srv, names.NewServiceTag("not-support")) c.Assert(err, gc.ErrorMatches, "unexpected login entity tag: invalid request") c.Assert(authenticator, gc.IsNil) }
func (s *DefinedSuite) TestInit(c *gc.C) { tests := []struct { should string args []string expectedSvc names.ServiceTag expectedOutputSchema bool expectedErr string }{{ should: "fail with missing service name", args: []string{}, expectedErr: "no service name specified", }, { should: "fail with invalid service name", args: []string{invalidServiceId}, expectedErr: "invalid service name \"" + invalidServiceId + "\"", }, { should: "fail with too many args", args: []string{"two", "things"}, expectedErr: "unrecognized args: \\[\"things\"\\]", }, { should: "init properly with valid service name", args: []string{validServiceId}, expectedSvc: names.NewServiceTag(validServiceId), }, { should: "init properly with valid service name and --schema", args: []string{"--schema", validServiceId}, expectedOutputSchema: true, expectedSvc: names.NewServiceTag(validServiceId), }} for i, t := range tests { for _, modelFlag := range s.modelFlags { c.Logf("test %d should %s: juju actions defined %s", i, t.should, strings.Join(t.args, " ")) s.wrappedCommand, s.command = action.NewDefinedCommand(s.store) args := append([]string{modelFlag, "admin"}, t.args...) err := testing.InitCommand(s.wrappedCommand, args) if t.expectedErr == "" { c.Check(s.command.ServiceTag(), gc.Equals, t.expectedSvc) c.Check(s.command.FullSchema(), gc.Equals, t.expectedOutputSchema) } else { c.Check(err, gc.ErrorMatches, t.expectedErr) } } } }
func (s *rsyslogSuite) TestUpgraderAPIRefusesNonUnitNonMachineAgent(c *gc.C) { anAuthorizer := s.authorizer anAuthorizer.Tag = names.NewServiceTag("hadoop") anUpgrader, err := rsyslog.NewRsyslogAPI(s.State, s.resources, anAuthorizer) c.Check(err, gc.NotNil) c.Check(anUpgrader, gc.IsNil) c.Assert(err, gc.ErrorMatches, "permission denied") }
func (s *volumeSuite) TestCreateVolumeItemNoUnit(c *gc.C) { s.storageInstance.owner = names.NewServiceTag("test-service") found := storage.CreateVolumeItem(s.api, s.volumeTag.String(), nil) c.Assert(found.Error, gc.IsNil) c.Assert(found.Error, gc.IsNil) expected, err := storage.ConvertStateVolumeToParams(s.api, s.volume) c.Assert(err, jc.ErrorIsNil) c.Assert(found.Volume, gc.DeepEquals, expected) }
func (s *commonSuite) TestAuthFuncForTagKind(c *gc.C) { // TODO(dimitern): This list of all supported tags and kinds needs // to live in juju/names. uuid, err := utils.NewUUID() c.Assert(err, jc.ErrorIsNil) allTags := []names.Tag{ nil, // invalid tag names.NewActionTag(uuid.String()), names.NewCharmTag("cs:precise/missing"), names.NewModelTag(uuid.String()), names.NewFilesystemTag("20/20"), names.NewLocalUserTag("user"), names.NewMachineTag("42"), names.NewNetworkTag("public"), names.NewRelationTag("wordpress:mysql mysql:db"), names.NewServiceTag("wordpress"), names.NewSpaceTag("apps"), names.NewStorageTag("foo/42"), names.NewUnitTag("wordpress/5"), names.NewUserTag("joe"), names.NewVolumeTag("80/20"), } for i, allowedTag := range allTags { c.Logf("test #%d: allowedTag: %v", i, allowedTag) var allowedKind string if allowedTag != nil { allowedKind = allowedTag.Kind() } getAuthFunc := common.AuthFuncForTagKind(allowedKind) authFunc, err := getAuthFunc() if allowedKind == "" { c.Check(err, gc.ErrorMatches, "tag kind cannot be empty") c.Check(authFunc, gc.IsNil) continue } else if !c.Check(err, jc.ErrorIsNil) { continue } for j, givenTag := range allTags { c.Logf("test #%d.%d: givenTag: %v", i, j, givenTag) var givenKind string if givenTag != nil { givenKind = givenTag.Kind() } if allowedKind == givenKind { c.Check(authFunc(givenTag), jc.IsTrue) } else { c.Check(authFunc(givenTag), jc.IsFalse) } } } }
func (*FacadeSuite) TestWatchNoResultsError(c *gc.C) { caller := apiCaller(c, func(_ string, _, _ interface{}) error { return nil }) facade := lifeflag.NewFacade(caller, nil) watcher, err := facade.Watch(names.NewServiceTag("blah")) c.Check(err, gc.ErrorMatches, "expected 1 Watch result, got 0") c.Check(watcher, gc.IsNil) }
func (*FacadeSuite) TestLifeNoResultsError(c *gc.C) { caller := apiCaller(c, func(_ string, _, _ interface{}) error { return nil }) facade := lifeflag.NewFacade(caller, nil) result, err := facade.Life(names.NewServiceTag("blah")) c.Check(err, gc.ErrorMatches, "expected 1 Life result, got 0") c.Check(result, gc.Equals, life.Value("")) }
func (*FacadeSuite) TestLifeCallError(c *gc.C) { caller := apiCaller(c, func(_ string, _, _ interface{}) error { return errors.New("crunch belch") }) facade := lifeflag.NewFacade(caller, nil) result, err := facade.Life(names.NewServiceTag("blah")) c.Check(err, gc.ErrorMatches, "crunch belch") c.Check(result, gc.Equals, life.Value("")) }
func (*FacadeSuite) TestWatchCallError(c *gc.C) { caller := apiCaller(c, func(_ string, _, _ interface{}) error { return errors.New("crunch belch") }) facade := lifeflag.NewFacade(caller, nil) watcher, err := facade.Watch(names.NewServiceTag("blah")) c.Check(err, gc.ErrorMatches, "crunch belch") c.Check(watcher, gc.IsNil) }
// BlockUntilLeadershipReleased is part of the leadership.Claimer interface. func (c *client) BlockUntilLeadershipReleased(serviceId string) error { const friendlyErrMsg = "error blocking on leadership release" var result params.ErrorResult err := c.FacadeCall("BlockUntilLeadershipReleased", names.NewServiceTag(serviceId), &result) if err != nil { return errors.Annotate(err, friendlyErrMsg) } else if result.Error != nil { return errors.Annotate(result.Error, friendlyErrMsg) } return nil }
func (s *leadershipSuite) TestBlockUntilLeadershipReleasedErrors(c *gc.C) { authorizer := &stubAuthorizer{ AuthUnitAgentFn: func() bool { return false }, } ldrSvc := &leadershipService{LeadershipManager: nil, authorizer: authorizer} result, err := ldrSvc.BlockUntilLeadershipReleased(names.NewServiceTag(StubServiceNm)) // Overall function call should succeed, but operations should // fail with a permissions issue. c.Check(err, jc.ErrorIsNil) c.Check(result.Error, jc.Satisfies, params.IsCodeUnauthorized) }
func (s *ImportSuite) TestUploadBinariesTools(c *gc.C) { // Create a model that has three different tools versions: // one for a machine, one for a container, and one for a unit agent. // We don't care about the actual validity of the model (it isn't). model := description.NewModel(description.ModelArgs{ Owner: names.NewUserTag("me"), }) machine := model.AddMachine(description.MachineArgs{ Id: names.NewMachineTag("0"), }) machine.SetTools(description.AgentToolsArgs{ Version: version.MustParseBinary("2.0.1-trusty-amd64"), }) container := machine.AddContainer(description.MachineArgs{ Id: names.NewMachineTag("0/lxc/0"), }) container.SetTools(description.AgentToolsArgs{ Version: version.MustParseBinary("2.0.5-trusty-amd64"), }) service := model.AddService(description.ServiceArgs{ Tag: names.NewServiceTag("magic"), CharmURL: "local:trusty/magic", }) unit := service.AddUnit(description.UnitArgs{ Tag: names.NewUnitTag("magic/0"), }) unit.SetTools(description.AgentToolsArgs{ Version: version.MustParseBinary("2.0.3-trusty-amd64"), }) uploader := &fakeUploader{tools: make(map[version.Binary]string)} config := migration.UploadBinariesConfig{ State: &fakeStateStorage{}, Model: model, Target: &fakeAPIConnection{}, GetCharmUploader: func(api.Connection) migration.CharmUploader { return &noOpUploader{} }, GetToolsUploader: func(target api.Connection) migration.ToolsUploader { return uploader }, GetStateStorage: func(migration.UploadBackend) storage.Storage { return &fakeCharmsStorage{} }, GetCharmStoragePath: func(migration.UploadBackend, *charm.URL) (string, error) { return "", nil }, } err := migration.UploadBinaries(config) c.Assert(err, jc.ErrorIsNil) c.Assert(uploader.tools, jc.DeepEquals, map[version.Binary]string{ version.MustParseBinary("2.0.1-trusty-amd64"): "fake tools 2.0.1-trusty-amd64", version.MustParseBinary("2.0.3-trusty-amd64"): "fake tools 2.0.3-trusty-amd64", version.MustParseBinary("2.0.5-trusty-amd64"): "fake tools 2.0.5-trusty-amd64", }) }
func (s *WatcherSuite) SetUpTest(c *gc.C) { s.BaseSuite.SetUpTest(c) s.st = mockState{ unit: mockUnit{ tag: names.NewUnitTag("mysql/0"), life: params.Alive, service: mockService{ tag: names.NewServiceTag("mysql"), life: params.Alive, curl: charm.MustParseURL("cs:trusty/mysql"), serviceWatcher: mockNotifyWatcher{changes: make(chan struct{}, 1)}, leaderSettingsWatcher: mockNotifyWatcher{ changes: make(chan struct{}, 1), }, relationsWatcher: mockStringsWatcher{ changes: make(chan []string, 1), }, }, unitWatcher: mockNotifyWatcher{changes: make(chan struct{}, 1)}, addressesWatcher: mockNotifyWatcher{changes: make(chan struct{}, 1)}, configSettingsWatcher: mockNotifyWatcher{changes: make(chan struct{}, 1)}, storageWatcher: mockStringsWatcher{changes: make(chan []string, 1)}, actionWatcher: mockStringsWatcher{changes: make(chan []string, 1)}, }, relations: make(map[names.RelationTag]*mockRelation), storageAttachment: make(map[params.StorageAttachmentId]params.StorageAttachment), relationUnitsWatchers: make(map[names.RelationTag]*mockRelationUnitsWatcher), storageAttachmentWatchers: make(map[names.StorageTag]*mockStorageAttachmentWatcher), } s.leadership = mockLeadershipTracker{ claimTicket: mockTicket{make(chan struct{}, 1), true}, leaderTicket: mockTicket{make(chan struct{}, 1), true}, minionTicket: mockTicket{make(chan struct{}, 1), true}, } s.clock = testing.NewClock(time.Now()) statusTicker := func() <-chan time.Time { return s.clock.After(statusTickDuration) } w, err := remotestate.NewWatcher(remotestate.WatcherConfig{ State: &s.st, LeadershipTracker: &s.leadership, UnitTag: s.st.unit.tag, UpdateStatusChannel: statusTicker, }) c.Assert(err, jc.ErrorIsNil) s.watcher = w }
func (s *leadershipSuite) TestBlockUntilLeadershipReleasedTranslation(c *gc.C) { var ldrMgr stubLeadershipManager ldrMgr.BlockUntilLeadershipReleasedFn = func(sid string) error { c.Check(sid, gc.Equals, StubServiceNm) return nil } ldrSvc := &leadershipService{LeadershipManager: &ldrMgr, authorizer: &stubAuthorizer{}} result, err := ldrSvc.BlockUntilLeadershipReleased(names.NewServiceTag(StubServiceNm)) c.Check(err, jc.ErrorIsNil) c.Check(result.Error, gc.IsNil) }
// Service returns the service. func (u *Unit) Service() (*Service, error) { serviceTag := names.NewServiceTag(u.ServiceName()) service := &Service{ st: u.st, tag: serviceTag, } // Call Refresh() immediately to get the up-to-date // life and other needed locally cached fields. err := service.Refresh() if err != nil { return nil, err } return service, nil }
func (s *leadershipSuite) TestBlockUntilLeadershipReleasedTranslation(c *gc.C) { claimer := &stubClaimer{ BlockUntilLeadershipReleasedFn: func(sid string) error { c.Check(sid, gc.Equals, StubServiceNm) return nil }, } ldrSvc := newLeadershipService(c, claimer, nil) result, err := ldrSvc.BlockUntilLeadershipReleased(names.NewServiceTag(StubServiceNm)) c.Check(err, jc.ErrorIsNil) c.Check(result.Error, gc.IsNil) }
// MoveServiceUnitSeqToSequence moves information from unitSeq value // in the services documents and puts it into a new document in the // sequence collection. // The move happens in 3 stages: // Insert: We insert the new sequence documents based on the values // in the service collection. Any existing documents with the id we ignore // Update: We update all the sequence documents with the correct UnitSeq. // this phase overwrites any existing sequence documents that existed and // were ignored during the install phase // Unset: The last phase is to remove the unitseq from the service collection. func MoveServiceUnitSeqToSequence(st *State) error { unitSeqDocs := []struct { Name string `bson:"name"` UnitSeq int `bson:"unitseq"` }{} servicesCollection, closer := st.getCollection(servicesC) defer closer() err := servicesCollection.Find(nil).All(&unitSeqDocs) if err != nil { return errors.Trace(err) } insertOps := make([]txn.Op, len(unitSeqDocs)) updateOps := make([]txn.Op, len(unitSeqDocs)) unsetOps := make([]txn.Op, len(unitSeqDocs)) for i, svc := range unitSeqDocs { tag := names.NewServiceTag(svc.Name) insertOps[i] = txn.Op{ C: sequenceC, Id: st.docID(tag.String()), Insert: sequenceDoc{ Name: tag.String(), EnvUUID: st.EnvironUUID(), Counter: svc.UnitSeq, }, } updateOps[i] = txn.Op{ C: sequenceC, Id: st.docID(tag.String()), Update: bson.M{ "$set": bson.M{ "name": tag.String(), "env-uuid": st.EnvironUUID(), "counter": svc.UnitSeq, }, }, } unsetOps[i] = txn.Op{ C: servicesC, Id: st.docID(svc.Name), Update: bson.M{ "$unset": bson.M{ "unitseq": 0}, }, } } ops := append(insertOps, updateOps...) ops = append(ops, unsetOps...) return st.runRawTransaction(ops) }
func (s *leadershipSuite) TestClaimLeadershipDurationTooLong(c *gc.C) { ldrSvc := &leadershipService{authorizer: &stubAuthorizer{}} results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{ Params: []params.ClaimLeadershipParams{ { ServiceTag: names.NewServiceTag(StubServiceNm).String(), UnitTag: names.NewUnitTag(StubUnitNm).String(), DurationSeconds: 300.1, }, }, }) c.Check(err, jc.ErrorIsNil) c.Assert(results.Results, gc.HasLen, 1) c.Check(results.Results[0].Error, gc.ErrorMatches, "invalid duration") }