// getJoinedRelations finds out what relations the unit is *really* part of, // working around the fact that pre-1.19 (1.18.1?) unit agents don't write a // state dir for a relation until a remote unit joins. func (u *Uniter) getJoinedRelations() (map[int]*uniter.Relation, error) { var joinedRelationTags []string for { var err error joinedRelationTags, err = u.unit.JoinedRelations() if err == nil { break } if params.IsCodeNotImplemented(err) { logger.Infof("waiting for state server to be upgraded") select { case <-u.tomb.Dying(): return nil, tomb.ErrDying case <-time.After(15 * time.Second): continue } } return nil, err } joinedRelations := make(map[int]*uniter.Relation) for _, tag := range joinedRelationTags { relation, err := u.st.Relation(tag) if err != nil { return nil, err } joinedRelations[relation.Id()] = relation } return joinedRelations, nil }
// init reconciles the local relation state dirs with the remote state of // the corresponding relations. It's only expected to be called while a // *relations is being created. func (r *relations) init() error { joinedRelationTags, err := r.unit.JoinedRelations() if err != nil { return errors.Trace(err) } joinedRelations := make(map[int]*uniter.Relation) for _, tag := range joinedRelationTags { relation, err := r.st.Relation(tag) if err != nil { return errors.Trace(err) } joinedRelations[relation.Id()] = relation } knownDirs, err := relation.ReadAllStateDirs(r.relationsDir) if err != nil { return errors.Trace(err) } for id, dir := range knownDirs { if rel, ok := joinedRelations[id]; ok { if err := r.add(rel, dir); err != nil { return errors.Trace(err) } } else if err := dir.Remove(); err != nil { return errors.Trace(err) } } for id, rel := range joinedRelations { if _, ok := knownDirs[id]; ok { continue } dir, err := relation.ReadStateDir(r.relationsDir, id) if err != nil { return errors.Trace(err) } if err := r.add(rel, dir); err != nil { return errors.Trace(err) } } return nil }