func (*statusContext) processRelations(service *state.Service) (related map[string][]string, subord []string, err error) { // TODO(mue) This way the same relation is read twice (for each service). // Maybe add Relations() to state, read them only once and pass them to each // call of this function. relations, err := service.Relations() if err != nil { return nil, nil, err } var subordSet set.Strings related = make(map[string][]string) for _, relation := range relations { ep, err := relation.Endpoint(service.Name()) if err != nil { return nil, nil, err } relationName := ep.Relation.Name eps, err := relation.RelatedEndpoints(service.Name()) if err != nil { return nil, nil, err } for _, ep := range eps { if ep.Scope == charm.ScopeContainer && !service.IsPrincipal() { subordSet.Add(ep.ServiceName) } related[relationName] = append(related[relationName], ep.ServiceName) } } for relationName, serviceNames := range related { sn := set.NewStrings(serviceNames...) related[relationName] = sn.SortedValues() } return related, subordSet.SortedValues(), nil }
func NewProReqRelation(c *C, s *ConnSuite, scope charm.RelationScope) *ProReqRelation { psvc, err := s.State.AddService("mysql", s.AddTestingCharm(c, "mysql")) c.Assert(err, IsNil) var rsvc *state.Service if scope == charm.ScopeGlobal { rsvc, err = s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress")) } else { rsvc, err = s.State.AddService("logging", s.AddTestingCharm(c, "logging")) } c.Assert(err, IsNil) eps, err := s.State.InferEndpoints([]string{"mysql", rsvc.Name()}) c.Assert(err, IsNil) rel, err := s.State.AddRelation(eps...) c.Assert(err, IsNil) prr := &ProReqRelation{rel: rel, psvc: psvc, rsvc: rsvc} prr.pu0, prr.pru0 = addRU(c, psvc, rel, nil) prr.pu1, prr.pru1 = addRU(c, psvc, rel, nil) if scope == charm.ScopeGlobal { prr.ru0, prr.rru0 = addRU(c, rsvc, rel, nil) prr.ru1, prr.rru1 = addRU(c, rsvc, rel, nil) } else { prr.ru0, prr.rru0 = addRU(c, rsvc, rel, prr.pu0) prr.ru1, prr.rru1 = addRU(c, rsvc, rel, prr.pu1) } return prr }
// serviceSetSettingsYAML updates the settings for the given service, // taking the configuration from a YAML string. func serviceSetSettingsYAML(service *state.Service, settings string) error { ch, _, err := service.Charm() if err != nil { return err } changes, err := ch.Config().ParseSettingsYAML([]byte(settings), service.Name()) if err != nil { return err } return service.UpdateConfigSettings(changes) }
// startService creates a new data value for tracking details of the // service and starts watching the service for exposure changes. func (fw *Firewaller) startService(service *state.Service) error { serviced := &serviceData{ fw: fw, service: service, exposed: service.IsExposed(), unitds: make(map[string]*unitData), } fw.serviceds[service.Name()] = serviced go serviced.watchLoop(serviced.exposed) return nil }
func (context *statusContext) processService(service *state.Service) (status serviceStatus) { url, _ := service.CharmURL() status.Charm = url.String() status.Exposed = service.IsExposed() status.Life = processLife(service) var err error status.Relations, status.SubordinateTo, err = context.processRelations(service) if err != nil { status.Err = err return } if service.IsPrincipal() { status.Units = context.processUnits(context.units[service.Name()]) } return status }
// AddUnits starts n units of the given service and allocates machines // to them as necessary. func (conn *Conn) AddUnits(svc *state.Service, n int) ([]*state.Unit, error) { units := make([]*state.Unit, n) // TODO what do we do if we fail half-way through this process? for i := 0; i < n; i++ { policy := conn.Environ.AssignmentPolicy() unit, err := svc.AddUnit() if err != nil { return nil, fmt.Errorf("cannot add unit %d/%d to service %q: %v", i+1, n, svc.Name(), err) } if err := conn.State.AssignUnit(unit, policy); err != nil { return nil, err } units[i] = unit } return units, nil }
func assertOneRelation(c *C, srv *state.Service, relId int, endpoints ...state.Endpoint) { rels, err := srv.Relations() c.Assert(err, IsNil) c.Assert(rels, HasLen, 1) rel := rels[0] c.Assert(rel.Id(), Equals, relId) name := srv.Name() expectEp := endpoints[0] ep, err := rel.Endpoint(name) c.Assert(err, IsNil) c.Assert(ep, DeepEquals, expectEp) if len(endpoints) == 2 { expectEp = endpoints[1] } eps, err := rel.RelatedEndpoints(name) c.Assert(err, IsNil) c.Assert(eps, DeepEquals, []state.Endpoint{expectEp}) }
// AddUnits starts n units of the given service and allocates machines // to them as necessary. func (conn *Conn) AddUnits(svc *state.Service, n int, machineIdSpec string) ([]*state.Unit, error) { units := make([]*state.Unit, n) // Hard code for now till we implement a different approach. policy := state.AssignCleanEmpty // TODO what do we do if we fail half-way through this process? for i := 0; i < n; i++ { unit, err := svc.AddUnit() if err != nil { return nil, fmt.Errorf("cannot add unit %d/%d to service %q: %v", i+1, n, svc.Name(), err) } if machineIdSpec != "" { if n != 1 { return nil, fmt.Errorf("cannot add multiple units of service %q to a single machine", svc.Name()) } // machineIdSpec may be an existing machine or container, eg 3/lxc/2 // or a new container on a machine, eg lxc:3 mid := machineIdSpec var containerType instance.ContainerType specParts := strings.Split(machineIdSpec, ":") if len(specParts) > 1 { firstPart := specParts[0] var err error if containerType, err = instance.ParseSupportedContainerType(firstPart); err == nil { mid = strings.Join(specParts[1:], "/") } else { mid = machineIdSpec } } if !names.IsMachine(mid) { return nil, fmt.Errorf("invalid force machine id %q", mid) } var err error var m *state.Machine // If a container is to be used, create it. if containerType != "" { params := state.AddMachineParams{ Series: unit.Series(), ParentId: mid, ContainerType: containerType, Jobs: []state.MachineJob{state.JobHostUnits}, } m, err = conn.State.AddMachineWithConstraints(¶ms) } else { m, err = conn.State.Machine(mid) } if err != nil { return nil, fmt.Errorf("cannot assign unit %q to machine: %v", unit.Name(), err) } err = unit.AssignToMachine(m) if err != nil { return nil, err } } else if err := conn.State.AssignUnit(unit, policy); err != nil { return nil, err } units[i] = unit } return units, nil }