package provision import ( "context" "os" "github.com/carlosframework/platform/internal/release" ) type RecordIndex struct { keys map[string][2]string } func IndexRecords(ctx context.Context, s release.Store) (*RecordIndex, error) { known, partial, err := knownAccounts(ctx, s) if err != nil { return nil, err } if partial { return nil, ErrRecordIndexRetry } keys, partial, err := listAppSubtree(ctx, s, known, "instances/") if err != nil { return nil, err } if partial { return nil, ErrRecordIndexRetry } out := &RecordIndex{keys: make(map[string][2]string)} for _, key := range keys { a, p, h, ok := ParseRecordKey(key, known) if !ok { continue } if _, duplicate := out.keys[h]; duplicate { out.keys[h] = [2]string{} } else { out.keys[h] = [2]string{a, p} } } return out, nil } type recordIndexRetry struct{} func (recordIndexRetry) Error() string { return os.ErrDeadlineExceeded.Error() } func (recordIndexRetry) Temporary() bool { return true } var ErrRecordIndexRetry error = recordIndexRetry{} func (i *RecordIndex) Find(ctx context.Context, s release.Store, host string) (*Record, string, error) { names, ok := i.keys[host] if !ok { return nil, "", os.ErrNotExist } account, app := names[0], names[1] if account == "" { return nil, "", os.ErrPermission } rec, etag, err := GetRecordETag(ctx, s, account, app, host) if err != nil { return nil, "", err } if etag == "" || rec.Schema != 1 || !release.ValidAccount(account) || !release.ValidApp(app) { return nil, "", os.ErrPermission } if err := ValidateShape(*rec); err != nil { return nil, "", err } return rec, etag, nil } func FindRecordByHost(ctx context.Context, s release.Store, host string) (*Record, string, error) { index, err := IndexRecords(ctx, s) if err != nil { return nil, "", err } return index.Find(ctx, s, host) }