...
1 package packagelock
2
3 import (
4 _ "embed"
5 "fmt"
6 "os"
7 "path/filepath"
8 "sort"
9
10 "cuelang.org/go/cue"
11 "cuelang.org/go/cue/cuecontext"
12 "cuelang.org/go/encoding/gocode/gocodec"
13 "cuelang.org/go/encoding/yaml"
14
15 "edge-infra.dev/pkg/edge/yamlfmt"
16 "edge-infra.dev/pkg/lib/build/bazel"
17 )
18
19 var (
20 Packagelock = "packagelock"
21
22 rulesFile []byte
23 )
24
25 type Version struct {
26 Digest string `json:"digest" yaml:"digest"`
27 Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"`
28 }
29
30 type LockPackage struct {
31 Name string `json:"name" yaml:"name"`
32 Versions []Version `json:"versions,omitempty" yaml:"versions,omitempty"`
33 }
34
35 type Packages []LockPackage
36
37 func (p Packages) Sort() {
38 sort.Slice(p, func(i, j int) bool { return p[i].Name < p[j].Name })
39 }
40
41 type PackageLock struct {
42 Packages Packages `json:"packages" yaml:"packages"`
43 }
44
45 type Rules struct {
46 codec *gocodec.Codec
47 ruleValue cue.Value
48 }
49
50 func NewRules() (Rules, error) {
51 c := cuecontext.New()
52 ruleValue := c.CompileBytes(rulesFile)
53 if ruleValue.Err() != nil {
54 return Rules{}, ruleValue.Err()
55 }
56
57 codec := gocodec.New(c, nil)
58
59 return Rules{codec: codec, ruleValue: ruleValue}, nil
60 }
61
62 func (plr Rules) ParsePackageLock(path string) (PackageLock, error) {
63 pl := &PackageLock{}
64
65 if bazel.IsBazelRun() {
66 if !filepath.IsAbs(path) {
67 path = filepath.Join(os.Getenv(bazel.BuildWorkspaceDir), path)
68 }
69 }
70
71 plReader, err := os.Open(path)
72 if err != nil {
73 return PackageLock{}, fmt.Errorf("failed to open file, err: %w", err)
74 }
75
76 plCueFile, err := yaml.Extract(path, plReader)
77 if err != nil {
78 return PackageLock{}, fmt.Errorf("failed to extract yaml, err: %w", err)
79 }
80 plReader.Close()
81
82 plCueValue, err := plr.codec.Decode(plCueFile)
83 if err != nil {
84 return PackageLock{}, err
85 }
86
87 err = plr.codec.Encode(plCueValue, pl)
88 if err != nil {
89 return PackageLock{}, err
90 }
91
92 err = plr.codec.Validate(plr.ruleValue, pl)
93
94 if err != nil {
95 return PackageLock{}, err
96 }
97
98 return *pl, nil
99 }
100
101 func (plr Rules) MarshalPackageLockYAML(pl PackageLock) ([]byte, error) {
102 pl.Packages.Sort()
103 plValue, err := plr.codec.Decode(pl)
104 if err != nil {
105 return nil, err
106 }
107
108 err = plr.codec.Validate(plr.ruleValue, plValue)
109 if err != nil {
110 return nil, err
111 }
112 plBytes, err := yaml.Encode(plValue)
113 if err != nil {
114 return nil, err
115 }
116
117 formatter := yamlfmt.NewByteFormatter()
118 formattedBytes, err := formatter.FormatBytes(plBytes)
119 if err != nil {
120 return nil, err
121 }
122
123 return formattedBytes, nil
124 }
125
View as plain text