Monorepo for Tangled
tangled.org
1package microvm
2
3import (
4 "crypto/sha256"
5 "database/sql"
6 "encoding/hex"
7 "encoding/json"
8 "errors"
9 "fmt"
10 "time"
11
12 "tangled.org/core/spindle/db"
13)
14
15const nixosToplevelCacheSchemaVersion = 1
16
17type nixosToplevelCacheRecord struct {
18 ConfigKey string `json:"config_key"`
19 Toplevel string `json:"toplevel"`
20 UpdatedAt time.Time `json:"updated_at"`
21}
22
23type nixosToplevelCacheStore struct {
24 db *db.DB
25}
26
27func newNixOSToplevelCacheStore(d *db.DB) nixosToplevelCacheStore {
28 return nixosToplevelCacheStore{db: d}
29}
30
31func (s nixosToplevelCacheStore) Lookup(configKey string) (nixosToplevelCacheRecord, bool, error) {
32 if s.db == nil {
33 return nixosToplevelCacheRecord{}, false, nil
34 }
35 r, err := s.db.GetNixOSToplevelCacheRecord(configKey)
36 if err != nil {
37 if errors.Is(err, sql.ErrNoRows) {
38 return nixosToplevelCacheRecord{}, false, nil
39 }
40 return nixosToplevelCacheRecord{}, false, err
41 }
42 return nixosToplevelCacheRecord{
43 ConfigKey: r.ConfigKey,
44 Toplevel: r.Toplevel,
45 UpdatedAt: r.UpdatedAt,
46 }, true, nil
47}
48
49func (s nixosToplevelCacheStore) Commit(configKey, toplevel string) error {
50 if configKey == "" {
51 return fmt.Errorf("config key is empty")
52 }
53 if toplevel == "" {
54 return fmt.Errorf("config toplevel is empty")
55 }
56 if s.db == nil {
57 return nil
58 }
59 return s.db.SaveNixOSToplevelCacheRecord(configKey, toplevel)
60}
61
62func BaseConfigHash(imageSpec ImageSpec) (string, error) {
63 if imageSpec.BaseConfigHash == "" {
64 return "", fmt.Errorf("microvm image spec missing baseConfigHash")
65 }
66 return imageSpec.BaseConfigHash, nil
67}
68
69func userConfigHash(cfg manifestConfig) string {
70 data, _ := json.Marshal(cfg)
71 sum := sha256.Sum256(data)
72 return hex.EncodeToString(sum[:])
73}
74
75func buildConfigKey(imageSpec ImageSpec, cfg manifestConfig) (string, error) {
76 baseHash, err := BaseConfigHash(imageSpec)
77 if err != nil {
78 return "", err
79 }
80 payload := struct {
81 Schema int `json:"schema"`
82 BaseConfig string `json:"base_config"`
83 UserConfig string `json:"user_config"`
84 }{
85 Schema: nixosToplevelCacheSchemaVersion,
86 BaseConfig: baseHash,
87 UserConfig: userConfigHash(cfg),
88 }
89 data, _ := json.Marshal(payload)
90 sum := sha256.Sum256(data)
91 return hex.EncodeToString(sum[:]), nil
92}
93
94func BuildConfigKey(imageSpec ImageSpec, userConfigJSON string) (string, error) {
95 var cfg manifestConfig
96 if err := json.Unmarshal([]byte(userConfigJSON), &cfg); err != nil {
97 return "", err
98 }
99 return buildConfigKey(imageSpec, cfg)
100}