-
Notifications
You must be signed in to change notification settings - Fork 69
Expand file tree
/
Copy pathgen.go
More file actions
153 lines (134 loc) · 3.53 KB
/
Copy pathgen.go
File metadata and controls
153 lines (134 loc) · 3.53 KB
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//go:build ignore
package main
import (
"bytes"
"fmt"
"go/format"
"os"
"path/filepath"
"text/template"
"github.com/semihalev/zlog/v2"
)
// middleware list order very important, handlers call via this order.
var middlewareList = []string{
"recovery",
"metrics",
"dnstap",
"accesslist",
"ratelimit",
"reflex",
"edns",
"accesslog",
"chaos",
"hostsfile",
"views",
"blocklist",
// rpz sits after blocklist (blocklist wins on overlap; RPZ PASSTHRU
// exempts from RPZ, not from the blocklist) and ahead of the cache, so
// policy applies to every client query, hits included, and a reload
// takes effect immediately.
"rpz",
"as112",
"kubernetes",
"dns64",
"cache",
"failover",
"resolver",
"forwarder",
}
const codeTemplate = `// Code generated by gen.go DO NOT EDIT.
// Package defaults holds SDNS's default middleware chain, in its default
// order.
//
// It is a package rather than an init in main so that everything which
// needs the real chain can ask for it: the binary, the benchmarks, a
// harness. When this lived in main it could not be imported, so each of
// those kept a list of its own — and they drifted, which is worse than
// duplication because a benchmark that quietly measures five handlers
// fewer than production still reports a number.
package defaults
import (
"github.com/semihalev/sdns/config"
"github.com/semihalev/sdns/middleware"
{{range .Imports}}
"{{.}}"
{{- end}}
)
type entry struct {
name string
ctor middleware.Constructor
}
var chain = []entry{
{{range .Middleware}} {"{{.}}", func(cfg *config.Config) middleware.Handler { return {{.}}.New(cfg) }},
{{end -}}
}
// Register registers the default chain, in order.
func Register() { RegisterUpTo("") }
// RegisterUpTo registers the chain up to but not including name; an empty
// name registers all of it.
//
// It exists for the harnesses that replace the tail — a benchmark
// standing a stub in for the resolver — so that what runs ahead of the
// stub is the real chain rather than a hand-kept approximation of it.
func RegisterUpTo(stop string) {
for _, e := range chain {
if e.name == stop {
return
}
middleware.Register(e.name, e.ctor)
}
}
`
func main() {
if err := generate(); err != nil {
zlog.Fatal("Generation failed", "error", err.Error())
}
}
func generate() error {
// Validate middleware directories
var imports []string
for _, name := range middlewareList {
dir := filepath.Join(middlewareDir, name)
stat, err := os.Stat(dir)
if err != nil {
return fmt.Errorf("checking middleware %s: %w", name, err)
}
if !stat.IsDir() {
return fmt.Errorf("%s is not a directory", dir)
}
imports = append(imports, filepath.Join(prefixDir, middlewareDir, name))
}
// Generate code using template
tmpl, err := template.New("code").Parse(codeTemplate)
if err != nil {
return fmt.Errorf("parsing template: %w", err)
}
var buf bytes.Buffer
err = tmpl.Execute(&buf, struct {
Imports []string
Middleware []string
}{
Imports: imports,
Middleware: middlewareList,
})
if err != nil {
return fmt.Errorf("executing template: %w", err)
}
// Format the generated code
formatted, err := format.Source(buf.Bytes())
if err != nil {
return fmt.Errorf("formatting code: %w", err)
}
// Write to file
err = os.WriteFile(filename, formatted, 0644)
if err != nil {
return fmt.Errorf("writing file: %w", err)
}
fmt.Printf("Generated %s successfully\n", filename)
return nil
}
const (
filename = "middleware/defaults/defaults.go"
prefixDir = "github.com/semihalev/sdns"
middlewareDir = "middleware"
)