func getApp(name string, s cp.Snapshotable) (*App, error) { sp := s.GetSnapshot() app := storeFromSnapshotable(s).NewApp(name, "", "") f, err := sp.GetSnapshot().GetFile(app.dir.Prefix("attrs"), new(cp.JsonCodec)) if err != nil { if cp.IsErrNoEnt(err) { err = errorf(ErrNotFound, `app "%s" not found`, app.Name) } return nil, err } value := f.Value.(map[string]interface{}) app.RepoURL = value["repo-url"].(string) app.Stack = value["stack"].(string) app.DeployType = value["deploy-type"].(string) f, err = app.dir.GetFile(registeredPath, new(cp.StringCodec)) if err != nil { if cp.IsErrNoEnt(err) { err = errorf(ErrNotFound, "registered not found for %s", app.Name) } return nil, err } app.Registered, err = parseTime(f.Value.(string)) if err != nil { return nil, err } return app, nil }
func getProc(app *App, name string, s cp.Snapshotable) (*Proc, error) { p := &Proc{ dir: cp.NewDir(app.dir.Prefix(procsPath, name), s.GetSnapshot()), Name: name, App: app, } port, err := p.dir.GetFile(procsPortPath, new(cp.IntCodec)) if err != nil { if cp.IsErrNoEnt(err) { exists, _, err := s.GetSnapshot().Exists(p.dir.Name) if err != nil { return nil, err } if !exists { return nil, errorf(ErrNotFound, `proc "%s" not found for app %s`, name, app.Name) } return nil, errorf(ErrNotFound, "port not found for %s:%s", app.Name, name) } return nil, err } p.Port = port.Value.(int) controlPort, err := p.dir.GetFile(procsControlPortPath, new(cp.IntCodec)) if err != nil { if IsErrNotFound(err) { p.ControlPort = 0 } else { return nil, err } } else { p.ControlPort = controlPort.Value.(int) } _, err = p.dir.GetFile(procsAttrsPath, &cp.JsonCodec{DecodedVal: &p.Attrs}) if err != nil && !cp.IsErrNoEnt(err) { return nil, err } f, err := p.dir.GetFile(registeredPath, new(cp.StringCodec)) if err != nil { if cp.IsErrNoEnt(err) { err = errorf(ErrNotFound, "registered not found for %s:%s", app.Name, name) } return nil, err } p.Registered, err = parseTime(f.Value.(string)) if err != nil { return nil, err } return p, nil }
// EnvironmentVars returns all set variables for this app as a map. func (a *App) EnvironmentVars() (vars map[string]string, err error) { vars = map[string]string{} sp, err := a.GetSnapshot().FastForward() if err != nil { return vars, err } names, err := sp.Getdir(a.dir.Prefix("env")) if err != nil { if cp.IsErrNoEnt(err) { err = nil } return } a.dir = a.dir.Join(sp) type resp struct { key, val string err error } ch := make(chan resp, len(names)) if err != nil { if cp.IsErrNoEnt(err) { return vars, nil } return } for _, name := range names { go func(name string) { v, err := a.GetEnvironmentVar(name) if err != nil { ch <- resp{err: err} } else { ch <- resp{key: name, val: v} } }(name) } for i := 0; i < len(names); i++ { r := <-ch if r.err != nil { return nil, err } vars[strings.Replace(r.key, "-", "_", -1)] = r.val } return }
// Init sets up expected paths. func (s *Store) Init() (*Store, error) { sp, err := s.GetSnapshot().FastForward() if err != nil { return nil, err } exists, _, err := sp.Exists(nextPortPath) if err != nil { return nil, err } if !exists { sp, err = sp.Set(nextPortPath, strconv.Itoa(startPort)) if err != nil { return nil, err } } v, err := cp.VerifySchema(SchemaVersion, sp) if cp.IsErrNoEnt(err) { sp, err = cp.SetSchemaVersion(SchemaVersion, sp) if err != nil { return nil, err } } else if err != nil { if cp.IsErrSchemaMism(err) { err = fmt.Errorf("%s (%d != %d)", err, SchemaVersion, v) } return nil, err } s.snapshot = sp return s, nil }
// GetProcs returns all registered Procs for the App func (a *App) GetProcs() (procs []*Proc, err error) { sp, err := a.GetSnapshot().FastForward() if err != nil { return } names, err := sp.Getdir(a.dir.Prefix(procsPath)) if err != nil || len(names) == 0 { if cp.IsErrNoEnt(err) { err = nil } return } ch, errch := cp.GetSnapshotables(names, func(name string) (cp.Snapshotable, error) { return getProc(a, name, sp) }) for i := 0; i < len(names); i++ { select { case r := <-ch: procs = append(procs, r.(*Proc)) case err := <-errch: return nil, err } } return }
// Claims returns the list of claimers. func (i *Instance) Claims() (claims []string, err error) { sp, err := i.GetSnapshot().FastForward() if err != nil { return } claims, err = sp.Getdir(i.dir.Prefix("claims")) if cp.IsErrNoEnt(err) { claims = []string{} err = nil } return }
// GetEnvironmentVar returns the value stored for the given key. func (a *App) GetEnvironmentVar(k string) (value string, err error) { k = strings.Replace(k, "_", "-", -1) val, _, err := a.dir.Get("env/" + k) if err != nil { if cp.IsErrNoEnt(err) { err = errorf(ErrNotFound, `"%s" not found in %s's environment`, k, a.Name) } return } value = string(val) return }
func getRevision(app *App, ref string, s cp.Snapshotable) (*Revision, error) { r := &Revision{ dir: cp.NewDir(app.dir.Prefix(revsPath, ref), s.GetSnapshot()), App: app, Ref: ref, } f, err := r.dir.GetFile(archiveURLPath, new(cp.StringCodec)) if err != nil { if cp.IsErrNoEnt(err) { exists, _, err := s.GetSnapshot().Exists(r.dir.Name) if err != nil { return nil, err } if !exists { return nil, errorf(ErrNotFound, `revision "%s" not found for app %s`, ref, app.Name) } return nil, errorf(ErrNotFound, "archive-url not found for %s:%s", app.Name, ref) } return nil, err } r.ArchiveURL = f.Value.(string) f, err = r.dir.GetFile(registeredPath, new(cp.StringCodec)) if err != nil { if cp.IsErrNoEnt(err) { err = errorf(ErrNotFound, "registered not found for %s:%s", app.Name, ref) } return nil, err } r.Registered, err = parseTime(f.Value.(string)) if err != nil { return nil, err } return r, nil }
func (i *Instance) getRestarts() (InsRestarts, *cp.File, error) { var restarts InsRestarts f, err := i.dir.GetFile(restartsPath, new(cp.ListIntCodec)) if err == nil { fields := f.Value.([]int) restarts.Fail = fields[restartFailField] restarts.OOM = fields[restartOOMField] } else if !cp.IsErrNoEnt(err) { return restarts, nil, err } return restarts, f, nil }
func getEnv(app *App, ref string, s cp.Snapshotable) (*Env, error) { e := &Env{ dir: cp.NewDir(app.dir.Prefix(envsPath, ref), s.GetSnapshot()), App: app, Ref: ref, } _, err := e.dir.GetFile(varsPath, &cp.JsonCodec{DecodedVal: &e.Vars}) if err != nil { if cp.IsErrNoEnt(err) { exists, _, err := s.GetSnapshot().Exists(e.dir.Name) if err != nil { return nil, err } if !exists { return nil, errorf(ErrNotFound, `env "%s" not found for app %s`, ref, app.Name) } return nil, errorf(ErrNotFound, "vars not found for %s#%s", app.Name, ref) } return nil, err } f, err := e.dir.GetFile(registeredPath, new(cp.StringCodec)) if err != nil { if cp.IsErrNoEnt(err) { err = errorf(ErrNotFound, `registered not found for %s`, ref) } return nil, err } e.Registered, err = parseTime(f.Value.(string)) if err != nil { return nil, err } return e, nil }
func getTag(a *App, name string, s cp.Snapshotable) (*Tag, error) { t := &Tag{} c := &cp.JsonCodec{DecodedVal: t} f, err := s.GetSnapshot().GetFile(a.dir.Prefix(tagsPath, name), c) if err != nil { if cp.IsErrNoEnt(err) { err = errorf(ErrNotFound, `tag "%s" not found`, name) } return nil, err } t.file = f t.App = a return t, nil }
func getRunner(addr string, s cp.Snapshotable) (*Runner, error) { sp := s.GetSnapshot() f, err := sp.GetFile(runnerPath(addr), new(cp.ListCodec)) if err != nil { if cp.IsErrNoEnt(err) { err = errorf(ErrNotFound, "runner '%s' not found", addr) } return nil, err } data := f.Value.([]string) insIDStr := data[0] insID, err := parseInstanceID(insIDStr) if err != nil { return nil, err } return storeFromSnapshotable(sp).NewRunner(addr, insID), nil }
func getHook(app *App, name string, s cp.Snapshotable) (*Hook, error) { c := new(cp.JsonCodec) c.DecodedVal = &Hook{} f, err := s.GetSnapshot().GetFile(app.dir.Prefix(hooksPath, name), c) if err != nil { if cp.IsErrNoEnt(err) { err = errorf(ErrNotFound, `hook not found for "%s"`, name) } return nil, err } h, ok := f.Value.(*Hook) if !ok { return nil, errors.New("retrieved file is not a hook") } h.file = f h.App = app return h, nil }
func getInstance(id int64, s cp.Snapshotable) (*Instance, error) { i := &Instance{ ID: id, Status: InsStatusPending, dir: cp.NewDir(instancePath(id), s.GetSnapshot()), } exists, _, err := s.GetSnapshot().Exists(i.dir.Name) if err != nil { return nil, err } if !exists { return nil, errorf(ErrNotFound, `instance '%d' not found`, id) } f, err := i.dir.GetFile(startPath, new(cp.ListCodec)) if cp.IsErrNoEnt(err) { // Ignore } else if err != nil { return nil, err } else { fields := f.Value.([]string) if len(fields) > 0 { // IP i.Status = InsStatusClaimed i.IP = fields[0] } if len(fields) > 1 { // Port i.Status = InsStatusRunning i.Port, err = strconv.Atoi(fields[1]) if err != nil { return nil, errorf(ErrInvalidPort, "invalid port: "+fields[1]) } } if len(fields) > 2 { // Hostname i.Host = fields[2] } if len(fields) > 3 { // TelePort i.TelePort, err = strconv.Atoi(fields[3]) if err != nil { return nil, errorf(ErrInvalidPort, "invalid teleport: "+fields[3]) } } } statusStr, _, err := i.dir.Get(statusPath) if cp.IsErrNoEnt(err) { err = nil } else if err == nil { i.Status = InsStatus(statusStr) } else { return nil, err } if i.Status == InsStatusRunning { _, _, err := i.dir.Get(stopPath) if err == nil { i.Status = InsStatusStopping } else if !cp.IsErrNoEnt(err) { return nil, err } } f, err = i.dir.GetFile(objectPath, new(cp.ListCodec)) if err != nil { return nil, errorf(ErrNotFound, "object file not found for instance %d", id) } fields := f.Value.([]string) if len(fields) < 3 { return nil, errorf(ErrInvalidFile, "object file for %d has %d instead %d fields", id, len(fields), 3) } i.AppName = fields[0] i.RevisionName = fields[1] i.ProcessName = fields[2] i.Env = fields[3] i.Restarts, _, err = i.getRestarts() if err != nil { return nil, err } f, err = i.dir.GetFile(registeredPath, new(cp.StringCodec)) if err != nil { return nil, err } i.Registered, err = parseTime(f.Value.(string)) if err != nil { return nil, err } f, err = i.claimDir().GetFile(i.IP, new(cp.StringCodec)) if err != nil { if cp.IsErrNoEnt(err) { return i, nil } return nil, err } i.Claimed, err = parseTime(f.Value.(string)) if err != nil { return nil, err } return i, nil }