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
+13
-6
@@ -237,15 +237,22 @@ func printProblems(w io.Writer, ps []client.Problem) {
|
||||
}
|
||||
}
|
||||
|
||||
// printCheck prints named-checkconf's errors and warnings, but not its
|
||||
// routine "loaded serial" lines.
|
||||
func printCheck(w io.Writer, ms []client.CheckMessage) {
|
||||
for _, m := range ms {
|
||||
if m.Error {
|
||||
obj := ""
|
||||
if m.Object != "" {
|
||||
obj = " [" + m.Object + "]"
|
||||
}
|
||||
fmt.Fprintf(w, " named-checkconf: %s%s\n", m.Text, obj)
|
||||
if !m.Error && (strings.HasPrefix(m.Text, "loaded serial") || m.Text == "OK") {
|
||||
continue
|
||||
}
|
||||
obj := ""
|
||||
if m.Object != "" {
|
||||
obj = " [" + m.Object + "]"
|
||||
}
|
||||
label := "named-checkconf"
|
||||
if !m.Error {
|
||||
label += " warning"
|
||||
}
|
||||
fmt.Fprintf(w, " %s: %s%s\n", label, m.Text, obj)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"go.yaml.in/yaml/v3"
|
||||
@@ -102,3 +106,40 @@ func TestListValue(t *testing.T) {
|
||||
t.Errorf("listValue = %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestListQueries runs list commands against a fake server and checks the
|
||||
// filters they send: flags bound to variables shared between subcommands
|
||||
// must not leak defaults (zone create's --type primary once hid every
|
||||
// non-primary zone from 'zone list').
|
||||
func TestListQueries(t *testing.T) {
|
||||
var got string
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
got = r.URL.Path + "?" + r.URL.RawQuery
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte("[]"))
|
||||
}))
|
||||
defer srv.Close()
|
||||
t.Setenv("JARL_CLI_CONFIG", filepath.Join(t.TempDir(), "cli.yaml"))
|
||||
for _, tc := range []struct {
|
||||
args []string
|
||||
want string
|
||||
}{
|
||||
{[]string{"zone", "list"}, "/api/v1/zones?"},
|
||||
{[]string{"zone", "list", "--type", "hint"}, "/api/v1/zones?type=hint"},
|
||||
{[]string{"zone", "list", "--view", "internal"}, "/api/v1/zones?view=internal"},
|
||||
{[]string{"changeset", "list"}, "/api/v1/changesets?status=open"},
|
||||
{[]string{"option", "list", "--all"}, "/api/v1/options?"},
|
||||
} {
|
||||
got = ""
|
||||
root := rootCmd()
|
||||
root.SetArgs(append(tc.args, "--server", srv.URL, "--token", "jarl_test_token", "-o", "json"))
|
||||
root.SetOut(io.Discard)
|
||||
if err := root.Execute(); err != nil {
|
||||
t.Errorf("%v: %v", tc.args, err)
|
||||
continue
|
||||
}
|
||||
if got != tc.want {
|
||||
t.Errorf("%v sent %q, want %q", tc.args, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -18,6 +18,9 @@ import (
|
||||
func zoneCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{Use: "zone", Aliases: []string{"zones"}, Short: "Manage zones"}
|
||||
var view, typ string
|
||||
// list has its own type filter: create's --type defaults to "primary"
|
||||
// and would otherwise leak into list through the shared variable.
|
||||
var listType string
|
||||
|
||||
list := &cobra.Command{
|
||||
Use: "list",
|
||||
@@ -28,7 +31,7 @@ func zoneCmd() *cobra.Command {
|
||||
return err
|
||||
}
|
||||
var zones []api.Zone
|
||||
if err := c.Get(ctx(), "/zones", q("view", view, "type", typ), &zones); err != nil {
|
||||
if err := c.Get(ctx(), "/zones", q("view", view, "type", listType), &zones); err != nil {
|
||||
return err
|
||||
}
|
||||
return output(zones, func(w io.Writer) {
|
||||
@@ -44,7 +47,7 @@ func zoneCmd() *cobra.Command {
|
||||
},
|
||||
}
|
||||
list.Flags().StringVar(&view, "view", "", "only zones in this view")
|
||||
list.Flags().StringVar(&typ, "type", "", "only zones of this type")
|
||||
list.Flags().StringVar(&listType, "type", "", "only zones of this type")
|
||||
|
||||
show := &cobra.Command{
|
||||
Use: "show ZONE",
|
||||
|
||||
+11
-6
@@ -88,13 +88,18 @@ func printResult(res *engine.Result) {
|
||||
printProblems(res.Problems)
|
||||
}
|
||||
for _, m := range res.Check {
|
||||
if m.Error {
|
||||
obj := ""
|
||||
if m.Object != "" {
|
||||
obj = " [" + m.Object + "]"
|
||||
}
|
||||
fmt.Printf(" named-checkconf: %s%s\n", m.Text, obj)
|
||||
if !m.Error && (strings.HasPrefix(m.Text, "loaded serial") || m.Text == "OK") {
|
||||
continue
|
||||
}
|
||||
obj := ""
|
||||
if m.Object != "" {
|
||||
obj = " [" + m.Object + "]"
|
||||
}
|
||||
label := "named-checkconf"
|
||||
if !m.Error {
|
||||
label += " warning"
|
||||
}
|
||||
fmt.Printf(" %s: %s%s\n", label, m.Text, obj)
|
||||
}
|
||||
for _, w := range res.Warnings {
|
||||
fmt.Println("warning:", w)
|
||||
|
||||
Reference in new issue
Block a user