refactor some code

This commit is contained in:
Graham McIntire 2026-02-11 10:17:01 -06:00
parent 37f411ec55
commit 58d1af4f84
No known key found for this signature in database
12 changed files with 47 additions and 28 deletions

View file

@ -39,6 +39,11 @@ jobs:
- name: Vet
run: go vet ./...
- name: Lint
uses: golangci/golangci-lint-action@v7
with:
version: latest
- name: Test
run: go test -v ./...

1
.gitignore vendored
View file

@ -1,6 +1,7 @@
# Go
towerops-agent
*.test
cover.out
# Database files
*.db

View file

@ -65,7 +65,7 @@ func runSession(ctx context.Context, baseURL, token string) error {
if err != nil {
return fmt.Errorf("connect: %w", err)
}
defer ws.Close()
defer func() { _ = ws.Close() }()
agentID := fmt.Sprintf("agent-%d", time.Now().Unix())
topic := "agent:" + agentID

View file

@ -15,6 +15,7 @@
devShells.default = pkgs.mkShell {
buildInputs = [
pkgs.go
pkgs.golangci-lint
pkgs.protobuf
pkgs.protoc-gen-go
pkgs.git

View file

@ -1,6 +1,7 @@
package main
import (
"context"
"crypto/tls"
"fmt"
"io"
@ -42,7 +43,7 @@ func mikrotikConnect(ip string, port uint32, username, password string, useSSL b
NetDialer: &net.Dialer{Timeout: mikrotikConnTimeout},
Config: &tls.Config{InsecureSkipVerify: true, MinVersion: tls.VersionTLS12},
}
conn, err = dialer.DialContext(nil, "tcp", addr)
conn, err = dialer.DialContext(context.Background(), "tcp", addr)
} else {
conn, err = net.DialTimeout("tcp", addr, mikrotikConnTimeout)
}
@ -55,11 +56,11 @@ func mikrotikConnect(ip string, port uint32, username, password string, useSSL b
// Authenticate
resp, err := c.execute("/login", map[string]string{"name": username, "password": password})
if err != nil {
conn.Close()
_ = conn.Close()
return nil, fmt.Errorf("auth: %w", err)
}
if resp.err != "" {
conn.Close()
_ = conn.Close()
return nil, fmt.Errorf("auth failed: %s", resp.err)
}
@ -85,7 +86,7 @@ func (c *mikrotikClient) execute(command string, args map[string]string) (*mikro
}
func (c *mikrotikClient) close() error {
c.execute("/quit", nil) // best-effort
_, _ = c.execute("/quit", nil) // best-effort
return c.conn.Close()
}
@ -145,7 +146,7 @@ func (c *mikrotikClient) readSentence() ([]string, error) {
var words []string
for {
if tc, ok := c.conn.(net.Conn); ok {
tc.SetReadDeadline(time.Now().Add(mikrotikReadTimeout))
_ = tc.SetReadDeadline(time.Now().Add(mikrotikReadTimeout))
}
word, err := c.readWord()
if err != nil {
@ -268,7 +269,7 @@ func executeMikrotikJob(job *pb.AgentJob, resultCh chan<- *pb.MikrotikResult) {
}
return
}
defer client.close()
defer func() { _ = client.close() }()
var allSentences []*pb.MikrotikSentence
var errorMessage string

11
snmp.go
View file

@ -4,6 +4,7 @@ import (
"fmt"
"log/slog"
"time"
"unicode/utf8"
"github.com/gosnmp/gosnmp"
"github.com/towerops-app/towerops-agent/pb"
@ -22,7 +23,7 @@ func executeSnmpJob(job *pb.AgentJob, resultCh chan<- *pb.SnmpResult) {
slog.Error("snmp connect", "job_id", job.JobId, "device", dev.Ip, "error", err)
return
}
defer conn.Conn.Close()
defer func() { _ = conn.Conn.Close() }()
oidValues := make(map[string]string)
@ -96,7 +97,7 @@ func executeCredentialTest(job *pb.AgentJob, resultCh chan<- *pb.CredentialTestR
}
return
}
defer conn.Conn.Close()
defer func() { _ = conn.Conn.Close() }()
result, err := conn.Get([]string{"1.3.6.1.2.1.1.1.0"})
if err != nil {
@ -221,10 +222,12 @@ func snmpValueToString(pdu gosnmp.SnmpPDU) string {
return fmt.Sprintf("%d", gosnmp.ToBigInt(pdu.Value).Int64())
case gosnmp.OctetString:
b := pdu.Value.([]byte)
// Try UTF-8 first
if !utf8.Valid(b) {
return formatHex(b)
}
// Check for non-printable control chars
for _, c := range b {
if c < 0x20 && c != '\n' && c != '\r' && c != '\t' {
// Non-printable - return hex
return formatHex(b)
}
}

View file

@ -67,6 +67,11 @@ func TestSnmpValueToString(t *testing.T) {
pdu: gosnmp.SnmpPDU{Type: gosnmp.NoSuchObject, Value: nil},
want: "null",
},
{
name: "invalid utf8",
pdu: gosnmp.SnmpPDU{Type: gosnmp.OctetString, Value: []byte{0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x80, 0xFE}},
want: "48:65:6c:6c:6f:80:fe",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

4
ssh.go
View file

@ -23,13 +23,13 @@ func executeMikrotikBackup(ip string, port uint16, username, password string) (s
if err != nil {
return "", fmt.Errorf("ssh dial %s: %w", addr, err)
}
defer conn.Close()
defer func() { _ = conn.Close() }()
session, err := conn.NewSession()
if err != nil {
return "", fmt.Errorf("ssh session: %w", err)
}
defer session.Close()
defer func() { _ = session.Close() }()
output, err := session.CombinedOutput("/export compact")
if err != nil {

View file

@ -18,7 +18,7 @@ func selfUpdate(downloadURL, expectedChecksum string) error {
if err != nil {
return fmt.Errorf("download: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("download failed: status %d", resp.StatusCode)
@ -52,7 +52,7 @@ func selfUpdate(downloadURL, expectedChecksum string) error {
// Replace current binary
if err := os.Rename(tempPath, currentExe); err != nil {
os.Remove(tempPath)
_ = os.Remove(tempPath)
return fmt.Errorf("rename: %w", err)
}
slog.Info("binary replaced", "path", currentExe)

View file

@ -17,7 +17,7 @@ func TestSelfUpdateBadURL(t *testing.T) {
func TestSelfUpdateChecksumMismatch(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("fake binary"))
_, _ = w.Write([]byte("fake binary"))
}))
defer srv.Close()
@ -32,7 +32,7 @@ func TestSelfUpdateChecksumMatch(t *testing.T) {
checksum := fmt.Sprintf("%x", sha256.Sum256(body))
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(body)
_, _ = w.Write(body)
}))
defer srv.Close()

View file

@ -57,7 +57,7 @@ func WSDial(rawURL string) (*WSConn, error) {
// Generate random key for Sec-WebSocket-Key
keyBytes := make([]byte, 16)
if _, err := rand.Read(keyBytes); err != nil {
conn.Close()
_ = conn.Close()
return nil, fmt.Errorf("generate key: %w", err)
}
key := base64.StdEncoding.EncodeToString(keyBytes)
@ -67,7 +67,7 @@ func WSDial(rawURL string) (*WSConn, error) {
path, u.Host, key)
if _, err := conn.Write([]byte(req)); err != nil {
conn.Close()
_ = conn.Close()
return nil, fmt.Errorf("write handshake: %w", err)
}
@ -75,12 +75,12 @@ func WSDial(rawURL string) (*WSConn, error) {
buf := make([]byte, 4096)
n, err := conn.Read(buf)
if err != nil {
conn.Close()
_ = conn.Close()
return nil, fmt.Errorf("read handshake: %w", err)
}
resp := string(buf[:n])
if !strings.Contains(resp, "101") {
conn.Close()
_ = conn.Close()
return nil, fmt.Errorf("handshake failed: %s", strings.SplitN(resp, "\r\n", 2)[0])
}
@ -102,7 +102,7 @@ func (ws *WSConn) ReadMessage() ([]byte, int, error) {
return nil, 0, fmt.Errorf("pong: %w", err)
}
case opClose:
ws.writeFrame(opClose, nil) // best-effort close reply
_ = ws.writeFrame(opClose, nil) // best-effort close reply
return nil, opClose, io.EOF
}
}
@ -115,7 +115,7 @@ func (ws *WSConn) WriteText(data []byte) error {
// Close sends a close frame and closes the underlying connection.
func (ws *WSConn) Close() error {
ws.writeFrame(opClose, nil) // best-effort
_ = ws.writeFrame(opClose, nil) // best-effort
return ws.conn.Close()
}
@ -175,7 +175,7 @@ func (ws *WSConn) writeFrame(opcode int, payload []byte) error {
// Max header: 2 + 8 + 4 (mask) = 14 bytes
header := make([]byte, 2, 14)
header[0] = 0x80 | byte(opcode) // FIN + opcode
header[1] = 0x80 // masked (client must mask)
header[1] = 0x80 // masked (client must mask)
switch {
case length <= 125:
@ -194,7 +194,7 @@ func (ws *WSConn) writeFrame(opcode int, payload []byte) error {
// Generate mask key
maskKey := make([]byte, 4)
rand.Read(maskKey)
_, _ = rand.Read(maskKey)
header = append(header, maskKey...)
// Mask payload

View file

@ -131,6 +131,9 @@ type captureWriter struct {
written []byte
}
func (c *captureWriter) Read(p []byte) (int, error) { return c.Reader.Read(p) }
func (c *captureWriter) Write(p []byte) (int, error) { c.written = append(c.written, p...); return len(p), nil }
func (c *captureWriter) Close() error { return nil }
func (c *captureWriter) Read(p []byte) (int, error) { return c.Reader.Read(p) }
func (c *captureWriter) Write(p []byte) (int, error) {
c.written = append(c.written, p...)
return len(p), nil
}
func (c *captureWriter) Close() error { return nil }