Fix zone list filtering and BIND warning display; add a views guide
- jarl zone list showed only primary zones. zone create binds its --type flag (default "primary") to the same variable as list's --type, so the default leaked into the list filter and hid hint, secondary and forward zones. list now has its own variable. TestListQueries runs list commands against a fake server and checks the filters they send. - named-checkconf/named-checkzone messages are classified by the tool's exit code: on success, everything printed is a warning. Warnings such as 'both "recursion no;" and "allow-recursion" active' were shown as errors. The CLI, jarld check and the web UI now label them as warnings and skip the routine "loaded serial" lines. - The zone_outside_view error points at --adopt-zones. - docs/views.md: step-by-step split DNS for a server that has no views yet, tested on a copy of a stock Ubuntu 26.04 setup. Linked from the README, concepts and validation docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3c73afe0e1
commit
0795a1001e
13 files changed
+261
-26
No files matched your search
+15
-2
@@ -141,7 +141,20 @@ func (t *Tools) CheckConfig(ctx context.Context, path string, loadZones bool) (*
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Result{OK: code == 0, Messages: ParseOutput(out), Output: out}, nil
|
||||
return newResult(out, code), nil
|
||||
}
|
||||
|
||||
// newResult builds a checker result. The exit code is authoritative: when
|
||||
// the checker succeeded, whatever it printed is a warning, even if the text
|
||||
// doesn't say so (e.g. 'both "recursion no;" and "allow-recursion" active').
|
||||
func newResult(out string, code int) *Result {
|
||||
r := &Result{OK: code == 0, Messages: ParseOutput(out), Output: out}
|
||||
if r.OK {
|
||||
for i := range r.Messages {
|
||||
r.Messages[i].Error = false
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// CheckZone runs named-checkzone on a zone file with the same strictness
|
||||
@@ -152,7 +165,7 @@ func (t *Tools) CheckZone(ctx context.Context, zone, file string) (*Result, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Result{OK: code == 0, Messages: ParseOutput(out), Output: out}, nil
|
||||
return newResult(out, code), nil
|
||||
}
|
||||
|
||||
// DumpZone loads a zone file and prints it in canonical form (used by the
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package bind
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestResultClassification(t *testing.T) {
|
||||
// named-checkconf exited 0: everything it printed is a warning.
|
||||
ok := newResult(`both "recursion no;" and "allow-recursion" active for view external
|
||||
zone example.com/IN/internal: loaded serial 1
|
||||
`, 0)
|
||||
if !ok.OK || len(ok.Messages) != 2 || ok.Messages[0].Error || ok.Messages[1].Error {
|
||||
t.Errorf("exit 0: %+v", ok)
|
||||
}
|
||||
// Non-zero exit: real problems stay errors.
|
||||
bad := newResult(`/etc/bind/jarl/named.conf:12: unknown option 'recursoin'
|
||||
`, 1)
|
||||
if bad.OK || len(bad.Messages) != 1 || !bad.Messages[0].Error || bad.Messages[0].Line != 12 {
|
||||
t.Errorf("exit 1: %+v", bad)
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ func (c *checker) checkZones() {
|
||||
continue
|
||||
}
|
||||
if hasViews && z.ViewID == 0 {
|
||||
c.zoneProblem(z, Error, "zone_outside_view", "when views are used, every zone must be inside a view (named requires this); move the zone into a view")
|
||||
c.zoneProblem(z, Error, "zone_outside_view", "when views are used, every zone must be inside a view (named requires this); move the zone into a view, or create the first view with adopt_zones (jarl view create NAME --adopt-zones) to move all zones at once")
|
||||
}
|
||||
if err := dnsname.CheckZoneName(z.Name); err != nil {
|
||||
c.zoneProblem(z, Error, "zone_name_invalid", "invalid zone name: %v", err)
|
||||
|
||||
@@ -193,11 +193,13 @@ export function problemsList(problems) {
|
||||
}));
|
||||
}
|
||||
|
||||
// checkList shows named-checkconf's errors and warnings (not its routine
|
||||
// "loaded serial" lines).
|
||||
export function checkList(msgs) {
|
||||
const errs = (msgs || []).filter((m) => m.error);
|
||||
if (!errs.length) return null;
|
||||
return h("ul", { class: "problems" }, errs.map((m) =>
|
||||
h("li", { class: "error" }, h("strong", null, "named-checkconf: "), m.text, m.object ? h("span", { class: "where" }, m.object) : null)));
|
||||
const shown = (msgs || []).filter((m) => m.error || !(m.text.startsWith("loaded serial") || m.text === "OK"));
|
||||
if (!shown.length) return null;
|
||||
return h("ul", { class: "problems" }, shown.map((m) =>
|
||||
h("li", { class: m.error ? "error" : "warning" }, h("strong", null, m.error ? "named-checkconf: " : "named-checkconf warning: "), m.text, m.object ? h("span", { class: "where" }, m.object) : null)));
|
||||
}
|
||||
|
||||
export function diffView(text) {
|
||||
|
||||
Reference in new issue
Block a user