/
load.go
96 lines (80 loc) · 2.62 KB
/
load.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright 2018 GRAIL, Inc. All rights reserved.
// Use of this source code is governed by the Apache-2.0
// license that can be found in the LICENSE file.
package config
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/grailbio/base/security/ticket"
"v.io/v23/naming"
"v.io/v23/security/access"
"v.io/x/lib/vlog"
"v.io/x/ref/lib/vdl/build"
"v.io/x/ref/lib/vdl/compile"
"v.io/x/ref/lib/vdl/vdlutil"
)
const configSuffix = ".vdlconfig"
type ticketConfig struct {
Kind string
Ticket ticket.Ticket
Perms access.Permissions
Controls map[ticket.Control]bool
}
type Config map[string]ticketConfig
// Load returns a map with the tickets from a directory where the key is the
// path of the ticket.
func Load(dir string) (map[string]ticketConfig, error) {
all := Config{}
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
// The prefix we want for a path like 'config/docker/rwc.vdlconfig' is
// 'docker/rwc' where 'config' is the dir variable. For this example dirPart
// will be 'docker' and filePart will be 'rwc'.
dirPart := strings.TrimLeft(strings.TrimPrefix(filepath.Dir(path), dir), "/")
filePart := strings.TrimSuffix(filepath.Base(path), configSuffix)
prefix := naming.Join(dirPart, filePart)
vlog.VI(1).Infof("walk: %q prefix %q", path, prefix)
if !strings.HasSuffix(path, configSuffix) {
return nil
}
f, err := os.Open(path)
if err != nil {
return fmt.Errorf("bad path %q: %+v", path, err)
}
errors := vdlutil.Errors{}
warnings := vdlutil.Errors{}
packages := build.TransitivePackagesForConfig(path, f, build.Opts{}, &errors, &warnings)
env := compile.NewEnv(100)
for _, p := range packages {
vlog.VI(1).Infof("building package: %+v", p.Path)
build.BuildPackage(p, env)
if env.Errors.NumErrors() != 0 {
return fmt.Errorf("errors building %s:\n%+v", p.Path, env.Errors)
}
}
f.Seek(0, 0)
config := ticket.Config{}
build.BuildConfigValue(path, f, nil, env, &config)
if env.Errors != nil && env.Errors.NumErrors() > 0 {
return env.Errors.ToError()
}
for name, t := range config.Tickets {
perms := config.Permissions
if t.Permissions != nil {
perms = t.Permissions
}
// TODO(noah): Remove this check after PagerDutyId and TicketId controls are supported.
if _, ok := t.Controls[ticket.ControlRationale]; len(t.Controls) != 0 && (len(t.Controls) != 1 || !ok) {
return fmt.Errorf("only rationale control is supported: %+v", t.Controls)
}
all[naming.Join(prefix, name)] = ticketConfig{
Ticket: t.Ticket,
Perms: perms,
Controls: t.Controls,
}
}
return nil
})
return all, err
}