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