diff --git a/internal/catalogue/shares.go b/internal/catalogue/shares.go index 87b56f3a..2ee52e89 100644 --- a/internal/catalogue/shares.go +++ b/internal/catalogue/shares.go @@ -29,9 +29,11 @@ const MountsSeat = "node-mounts" func nfsServerVerbs() []Verb { return []Verb{ {Name: "exports", Description: "Every share this machine exports: its name, its path, read-write or " + - "read-only, the owner every client is mapped to (uid and gid), the clients it is exported to (the " + - "private network's range), and whether the kernel holds it now. Also the exports found that are " + - "not the mesh's: a dataset's sharenfs property, a line in /etc/exports.", + "read-only, the owner every client is mapped to (uid and gid), each node it is exported to with that " + + "node's private address and access (only the nodes the server grants it to and that ask for it), " + + "what is granted and not asked for or asked for and not granted, and whether the kernel holds it " + + "now. Also the exports found that are not the mesh's: a dataset's sharenfs property, a line in " + + "/etc/exports.", Input: schema(map[string]string{}, nil), Replaces: []string{"exportfs -v", "cat /etc/exports", "zfs get sharenfs"}}, {Name: "clients", Description: "Which machines have mounted which share now, as the NFS server " + @@ -39,11 +41,12 @@ func nfsServerVerbs() []Verb { Input: schema(map[string]string{}, nil), Replaces: []string{"ss -tn sport = :2049", "cat /proc/fs/nfsd/clients/*/info"}}, {Name: "test", Description: "Whether this machine exports one share for the mesh now, and whether its " + - "NFS service is up; with an address, also whether that address is inside the private network's " + - "range the share is exported to. What a machine mounting the share asks before it mounts.", + "NFS service is up; with an address, also whether the share is exported to that address: a node's " + + "own private address, when the server grants it the share and the node asks for it. What a machine " + + "mounting the share asks before it mounts.", Input: schema(map[string]string{ "share": "the share, by its name", - "address": "a client's address on the private network (optional)", + "address": "a node's private address, to ask whether the share is exported to it (optional)", }, []string{"share"}), Replaces: []string{"showmount -e"}}, {Name: "reload", Description: "Have the kernel read this machine's export files again now (exportfs " + diff --git a/internal/catalogue/shares_test.go b/internal/catalogue/shares_test.go index 5fbe0f10..6fd5b05d 100644 --- a/internal/catalogue/shares_test.go +++ b/internal/catalogue/shares_test.go @@ -159,3 +159,21 @@ func TestReloadSaysWhatItDoes(t *testing.T) { } } } + +// A share is exported to each node the server grants it to and that asks for it, at that node's own +// address (novox/hq ADR 0263 rule 5) — never to the private network's whole range. The verbs that +// describe the export say so, and do not promise the range. +func TestTheExportVerbsDescribePerNodeAddresses(t *testing.T) { + s, _ := SeatNamed(NFSServerSeat) + for _, v := range s.Serves { + if v.Name != "exports" && v.Name != "test" { + continue + } + if strings.Contains(v.Description, "private network's range") { + t.Errorf("%s still describes the export as the private network's range: %s", v.Name, v.Description) + } + if !strings.Contains(v.Description, "address") { + t.Errorf("%s does not say the export is to each node's address: %s", v.Name, v.Description) + } + } +}