mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-10-12 01:58:46 +02:00
clientinfo: skip unavailable Ubios Mongo discovery
This commit is contained in:
1 parent
9d724869e9
commit
e109c9be33
3 files changed
+75
-2
No files matched your search
@@ -3,8 +3,10 @@ package clientinfo
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -13,9 +15,12 @@ import (
|
|||||||
"github.com/Control-D-Inc/ctrld/internal/router/ubios"
|
"github.com/Control-D-Inc/ctrld/internal/router/ubios"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defaultUbiosMongoPath = "/usr/bin/mongo"
|
||||||
|
|
||||||
// ubiosDiscover provides client discovery functionality on Ubios routers.
|
// ubiosDiscover provides client discovery functionality on Ubios routers.
|
||||||
type ubiosDiscover struct {
|
type ubiosDiscover struct {
|
||||||
hostname sync.Map // mac => hostname
|
hostname sync.Map // mac => hostname
|
||||||
|
mongoPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh reloads unifi devices from database.
|
// refresh reloads unifi devices from database.
|
||||||
@@ -42,7 +47,19 @@ func (u *ubiosDiscover) LookupHostnameByMac(mac string) string {
|
|||||||
|
|
||||||
// refreshDevices updates unifi devices name from local mongodb.
|
// refreshDevices updates unifi devices name from local mongodb.
|
||||||
func (u *ubiosDiscover) refreshDevices() error {
|
func (u *ubiosDiscover) refreshDevices() error {
|
||||||
cmd := exec.Command("/usr/bin/mongo", "localhost:27117/ace", "--quiet", "--eval", `
|
mongoPath := u.mongoExecutable()
|
||||||
|
fi, err := os.Stat(mongoPath)
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("stat mongo executable: %w", err)
|
||||||
|
}
|
||||||
|
if !fi.Mode().IsRegular() || fi.Mode().Perm()&0111 == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(mongoPath, "localhost:27117/ace", "--quiet", "--eval", `
|
||||||
DBQuery.shellBatchSize = 256;
|
DBQuery.shellBatchSize = 256;
|
||||||
db.user.find({name: {$exists: true, $ne: ""}}, {_id:0, mac:1, name:1});`)
|
db.user.find({name: {$exists: true, $ne: ""}}, {_id:0, mac:1, name:1});`)
|
||||||
b, err := cmd.CombinedOutput()
|
b, err := cmd.CombinedOutput()
|
||||||
@@ -52,6 +69,13 @@ func (u *ubiosDiscover) refreshDevices() error {
|
|||||||
return u.storeDevices(bytes.NewReader(b))
|
return u.storeDevices(bytes.NewReader(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *ubiosDiscover) mongoExecutable() string {
|
||||||
|
if u.mongoPath != "" {
|
||||||
|
return u.mongoPath
|
||||||
|
}
|
||||||
|
return defaultUbiosMongoPath
|
||||||
|
}
|
||||||
|
|
||||||
// storeDevices saves unifi devices name for caching.
|
// storeDevices saves unifi devices name for caching.
|
||||||
func (u *ubiosDiscover) storeDevices(r io.Reader) error {
|
func (u *ubiosDiscover) storeDevices(r io.Reader) error {
|
||||||
decoder := json.NewDecoder(r)
|
decoder := json.NewDecoder(r)
|
||||||
|
|||||||
@@ -1,10 +1,32 @@
|
|||||||
package clientinfo
|
package clientinfo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Test_ubiosDiscover_refreshDevices_skipsUnavailableMongo(t *testing.T) {
|
||||||
|
t.Run("missing", func(t *testing.T) {
|
||||||
|
ud := &ubiosDiscover{mongoPath: filepath.Join(t.TempDir(), "mongo")}
|
||||||
|
if err := ud.refreshDevices(); err != nil {
|
||||||
|
t.Fatalf("refreshDevices() error = %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("not executable", func(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), "mongo")
|
||||||
|
if err := os.WriteFile(path, nil, 0600); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ud := &ubiosDiscover{mongoPath: path}
|
||||||
|
if err := ud.refreshDevices(); err != nil {
|
||||||
|
t.Fatalf("refreshDevices() error = %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func Test_ubiosDiscover_storeDevices(t *testing.T) {
|
func Test_ubiosDiscover_storeDevices(t *testing.T) {
|
||||||
ud := &ubiosDiscover{}
|
ud := &ubiosDiscover{}
|
||||||
r := strings.NewReader(`{ "mac": "00:00:00:00:00:01", "name": "device 1" }
|
r := strings.NewReader(`{ "mac": "00:00:00:00:00:01", "name": "device 1" }
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//go:build unix
|
||||||
|
|
||||||
|
package clientinfo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_ubiosDiscover_refreshDevices_usesExecutableMongo(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), "mongo")
|
||||||
|
const script = `#!/bin/sh
|
||||||
|
printf '%s\n' '{"mac":"00:00:00:00:00:01","name":"device 1"}'
|
||||||
|
`
|
||||||
|
if err := os.WriteFile(path, []byte(script), 0700); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ud := &ubiosDiscover{mongoPath: path}
|
||||||
|
if err := ud.refreshDevices(); err != nil {
|
||||||
|
t.Fatalf("refreshDevices() error = %v", err)
|
||||||
|
}
|
||||||
|
if got := ud.LookupHostnameByMac("00:00:00:00:00:01"); got != "device 1" {
|
||||||
|
t.Fatalf("LookupHostnameByMac() = %q, want %q", got, "device 1")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user