carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package seeds
2
3import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "errors"
8 "fmt"
9 "io"
10 "os"
11
12 "github.com/carlosframework/platform/internal/release"
13)
14
15// LegacyOwnersKey is the operator assignment of legacy route names
16// (seeded-instances spec §6.4, codex 9): which account and app a route
17// filed under the operator account belongs to.
18const LegacyOwnersKey = "control/legacy-route-owners.json"
19
20// legacyOwnersVersion is the only file version this reader understands.
21const legacyOwnersVersion = 1
22
23// LegacyOwner is the account and app a legacy route name is assigned to.
24type LegacyOwner struct {
25 Account string `json:"account"`
26 App string `json:"app"`
27}
28
29// LegacyOwners maps a route name, as filed under the operator account, to
30// the one account and app it belongs to.
31type LegacyOwners struct {
32 V int `json:"v"`
33 Names map[string]LegacyOwner `json:"names"`
34}
35
36// ReadLegacyOwners reads the assignments. It is an authority check, so it
37// fails closed: an absent file is an empty set (nothing is assigned), but a
38// file that is present and unreadable, malformed, of an unknown version or
39// carrying an incomplete entry is an error and no owners, never "no
40// assignment". The etag is "" for an absent file.
41func ReadLegacyOwners(ctx context.Context, s release.Store) (*LegacyOwners, string, error) {
42 body, etag, err := s.Get(ctx, LegacyOwnersKey)
43 if errors.Is(err, os.ErrNotExist) {
44 return &LegacyOwners{V: legacyOwnersVersion, Names: map[string]LegacyOwner{}}, "", nil
45 }
46 if err != nil {
47 return nil, "", fmt.Errorf("seeds: read legacy route owners: %w", err)
48 }
49 dec := json.NewDecoder(bytes.NewReader(body))
50 dec.DisallowUnknownFields()
51 var o LegacyOwners
52 if err := dec.Decode(&o); err != nil {
53 return nil, "", fmt.Errorf("seeds: parse legacy route owners: %w", err)
54 }
55 if _, err := dec.Token(); err != io.EOF {
56 return nil, "", errors.New("seeds: parse legacy route owners: data after the object")
57 }
58 if o.V != legacyOwnersVersion {
59 return nil, "", fmt.Errorf("seeds: legacy route owners: unknown version %d", o.V)
60 }
61 if o.Names == nil {
62 o.Names = map[string]LegacyOwner{}
63 }
64 for name, ow := range o.Names {
65 if name == "" || ow.Account == "" || ow.App == "" {
66 return nil, "", fmt.Errorf("seeds: legacy route owners: incomplete entry %q", name)
67 }
68 }
69 return &o, etag, nil
70}
71
72// Lookup returns the owner assigned to name. A name that is not in the set
73// is not assigned.
74func (o *LegacyOwners) Lookup(name string) (LegacyOwner, bool) {
75 if o == nil {
76 return LegacyOwner{}, false
77 }
78 v, ok := o.Names[name]
79 return v, ok
80}
81