func (s *watcherSuite) TestStringsWatcherStopsWithPendingSend(c *gc.C) { // Call the Deployer facade's WatchUnits for machine-0. var results params.StringsWatchResults args := params.Entities{Entities: []params.Entity{{Tag: s.rawMachine.Tag().String()}}} err := s.stateAPI.APICall("Deployer", s.stateAPI.BestFacadeVersion("Deployer"), "", "WatchUnits", args, &results) c.Assert(err, jc.ErrorIsNil) c.Assert(results.Results, gc.HasLen, 1) result := results.Results[0] c.Assert(result.Error, gc.IsNil) // Start a StringsWatcher and check the initial event. w := watcher.NewStringsWatcher(s.stateAPI, result) wc := statetesting.NewStringsWatcherC(c, s.State, w) // Create a service, deploy a unit of it on the machine. mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) principal, err := mysql.AddUnit() c.Assert(err, jc.ErrorIsNil) err = principal.AssignToMachine(s.rawMachine) c.Assert(err, jc.ErrorIsNil) // Ensure the initial event is delivered. Then test the watcher // can be stopped cleanly without reading the pending change. s.BackingState.StartSync() statetesting.AssertCanStopWhenSending(c, w) wc.AssertClosed() }
// WatchContainers returns a StringsWatcher that notifies of changes // to the lifecycles of containers of the specified type on the machine. func (m *Machine) WatchContainers(ctype instance.ContainerType) (watcher.StringsWatcher, error) { if string(ctype) == "" { return nil, fmt.Errorf("container type must be specified") } supported := false for _, c := range instance.ContainerTypes { if ctype == c { supported = true break } } if !supported { return nil, fmt.Errorf("unsupported container type %q", ctype) } var results params.StringsWatchResults args := params.WatchContainers{ Params: []params.WatchContainer{ {MachineTag: m.tag.String(), ContainerType: string(ctype)}, }, } err := m.st.facade.FacadeCall("WatchContainers", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, result.Error } w := apiwatcher.NewStringsWatcher(m.st.facade.RawAPICaller(), result) return w, nil }
func (s *watcherSuite) TestWatchUnitsKeepsEvents(c *gc.C) { // Create two services, relate them, and add one unit to each - a // principal and a subordinate. mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging")) eps, err := s.State.InferEndpoints("mysql", "logging") c.Assert(err, jc.ErrorIsNil) rel, err := s.State.AddRelation(eps...) c.Assert(err, jc.ErrorIsNil) principal, err := mysql.AddUnit() c.Assert(err, jc.ErrorIsNil) err = principal.AssignToMachine(s.rawMachine) c.Assert(err, jc.ErrorIsNil) relUnit, err := rel.Unit(principal) c.Assert(err, jc.ErrorIsNil) err = relUnit.EnterScope(nil) c.Assert(err, jc.ErrorIsNil) subordinate, err := s.State.Unit("logging/0") c.Assert(err, jc.ErrorIsNil) // Call the Deployer facade's WatchUnits for machine-0. var results params.StringsWatchResults args := params.Entities{Entities: []params.Entity{{Tag: s.rawMachine.Tag().String()}}} err = s.stateAPI.APICall("Deployer", s.stateAPI.BestFacadeVersion("Deployer"), "", "WatchUnits", args, &results) c.Assert(err, jc.ErrorIsNil) c.Assert(results.Results, gc.HasLen, 1) result := results.Results[0] c.Assert(result.Error, gc.IsNil) // Start a StringsWatcher and check the initial event. w := watcher.NewStringsWatcher(s.stateAPI, result) wc := statetesting.NewStringsWatcherC(c, s.State, w) wc.AssertChange("mysql/0", "logging/0") wc.AssertNoChange() // Now, without reading any changes advance the lifecycle of both // units, inducing an update server-side after each two changes to // ensure they're reported as separate events over the API. err = subordinate.EnsureDead() c.Assert(err, jc.ErrorIsNil) s.BackingState.StartSync() err = subordinate.Remove() c.Assert(err, jc.ErrorIsNil) err = principal.EnsureDead() c.Assert(err, jc.ErrorIsNil) s.BackingState.StartSync() // Expect these changes as 2 separate events, so that // nothing gets lost. wc.AssertChange("logging/0") wc.AssertChange("mysql/0") wc.AssertNoChange() statetesting.AssertStop(c, w) wc.AssertClosed() }
// WatchEnvironMachines returns a StringsWatcher that notifies of // changes to the life cycles of the top level machines in the current // environment. func (st *State) WatchEnvironMachines() (watcher.StringsWatcher, error) { var result params.StringsWatchResult err := st.facade.FacadeCall("WatchEnvironMachines", nil, &result) if err != nil { return nil, err } if err := result.Error; err != nil { return nil, result.Error } w := watcher.NewStringsWatcher(st.facade.RawAPICaller(), result) return w, nil }
// WatchUnitAssignments watches the server for new unit assignments to be // created. func (a API) WatchUnitAssignments() (watcher.StringsWatcher, error) { var result params.StringsWatchResult err := a.facade.FacadeCall("WatchUnitAssignments", nil, &result) if err != nil { return nil, err } if result.Error != nil { return nil, result.Error } w := watcher.NewStringsWatcher(a.facade.RawAPICaller(), result) return w, nil }
// WatchUnitStorageAttachments starts a watcher for changes to storage // attachments related to the unit. The watcher will return the // IDs of the corresponding storage instances. func (sa *StorageAccessor) WatchUnitStorageAttachments(unitTag names.UnitTag) (watcher.StringsWatcher, error) { var results params.StringsWatchResults args := params.Entities{ Entities: []params.Entity{{Tag: unitTag.String()}}, } err := sa.facade.FacadeCall("WatchUnitStorageAttachments", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, result.Error } w := apiwatcher.NewStringsWatcher(sa.facade.RawAPICaller(), result) return w, nil }
// WatchUnits starts a StringsWatcher to watch all units assigned to // the machine. func (m *Machine) WatchUnits() (watcher.StringsWatcher, error) { var results params.StringsWatchResults args := params.Entities{ Entities: []params.Entity{{Tag: m.tag.String()}}, } err := m.st.facade.FacadeCall("WatchUnits", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, result.Error } w := watcher.NewStringsWatcher(m.st.facade.RawAPICaller(), result) return w, nil }
func (st *State) watchStorageEntities(method string) (watcher.StringsWatcher, error) { var results params.StringsWatchResults args := params.Entities{ Entities: []params.Entity{{Tag: st.scope.String()}}, } err := st.facade.FacadeCall(method, args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { panic(errors.Errorf("expected 1 result, got %d", len(results.Results))) } result := results.Results[0] if result.Error != nil { return nil, result.Error } w := apiwatcher.NewStringsWatcher(st.facade.RawAPICaller(), result) return w, nil }
// WatchRelations returns a StringsWatcher that notifies of changes to // the lifecycles of relations involving s. func (s *Service) WatchRelations() (watcher.StringsWatcher, error) { var results params.StringsWatchResults args := params.Entities{ Entities: []params.Entity{{Tag: s.tag.String()}}, } err := s.st.facade.FacadeCall("WatchServiceRelations", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, result.Error } w := apiwatcher.NewStringsWatcher(s.st.facade.RawAPICaller(), result) return w, nil }
// WatchAllContainers returns a StringsWatcher that notifies of changes // to the lifecycles of all containers on the machine. func (m *Machine) WatchAllContainers() (watcher.StringsWatcher, error) { var results params.StringsWatchResults args := params.WatchContainers{ Params: []params.WatchContainer{ {MachineTag: m.tag.String()}, }, } err := m.st.facade.FacadeCall("WatchContainers", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, result.Error } w := apiwatcher.NewStringsWatcher(m.st.facade.RawAPICaller(), result) return w, nil }
// WatchOpenedPorts returns a StringsWatcher that notifies of // changes to the opened ports for the current model. func (st *State) WatchOpenedPorts() (watcher.StringsWatcher, error) { modelTag, ok := st.ModelTag() if !ok { return nil, errors.New("API connection is controller-only (should never happen)") } var results params.StringsWatchResults args := params.Entities{ Entities: []params.Entity{{Tag: modelTag.String()}}, } if err := st.facade.FacadeCall("WatchOpenedPorts", args, &results); err != nil { return nil, err } if len(results.Results) != 1 { return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if err := result.Error; err != nil { return nil, result.Error } w := apiwatcher.NewStringsWatcher(st.facade.RawAPICaller(), result) return w, nil }
func (s *watcherSuite) TestStringsWatcherStopsWithPendingSend(c *gc.C) { // Call the Deployer facade's WatchUnits for machine-0. var results params.StringsWatchResults args := params.Entities{Entities: []params.Entity{{Tag: s.rawMachine.Tag().String()}}} err := s.stateAPI.APICall("Deployer", s.stateAPI.BestFacadeVersion("Deployer"), "", "WatchUnits", args, &results) c.Assert(err, jc.ErrorIsNil) c.Assert(results.Results, gc.HasLen, 1) result := results.Results[0] c.Assert(result.Error, gc.IsNil) // Start a StringsWatcher and check the initial event. w := watcher.NewStringsWatcher(s.stateAPI, result) wc := watchertest.NewStringsWatcherC(c, w, s.BackingState.StartSync) defer wc.AssertStops() // Create a service, deploy a unit of it on the machine. mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) principal, err := mysql.AddUnit() c.Assert(err, jc.ErrorIsNil) err = principal.AssignToMachine(s.rawMachine) c.Assert(err, jc.ErrorIsNil) }
// WatchActionNotifications returns a StringsWatcher for observing the // IDs of Actions added to the Machine. The initial event will contain the // IDs of any Actions pending at the time the Watcher is made. func (c *Client) WatchActionNotifications(agent names.MachineTag) (watcher.StringsWatcher, error) { var results params.StringsWatchResults args := params.Entities{ Entities: []params.Entity{{Tag: agent.String()}}, } err := c.facade.FacadeCall("WatchActionNotifications", args, &results) if err != nil { return nil, errors.Trace(err) } if len(results.Results) != 1 { return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, errors.Trace(result.Error) } w := apiwatcher.NewStringsWatcher(c.facade.RawAPICaller(), result) return w, nil }
// WatchOpenedPorts returns a StringsWatcher that notifies of // changes to the opened ports for the current model. func (st *State) WatchOpenedPorts() (watcher.StringsWatcher, error) { modelTag, err := st.ModelTag() if err != nil { return nil, errors.Annotatef(err, "invalid model tag") } var results params.StringsWatchResults args := params.Entities{ Entities: []params.Entity{{Tag: modelTag.String()}}, } err = st.facade.FacadeCall("WatchOpenedPorts", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if err := result.Error; err != nil { return nil, result.Error } w := apiwatcher.NewStringsWatcher(st.facade.RawAPICaller(), result) return w, nil }