fix: enable more linters (#121)

This commit is contained in:
Julian Sommer
2026-04-09 14:36:22 +10:00
committed by GitHub
parent 26e590716e
commit 7449090c86
12 changed files with 94 additions and 83 deletions
+3
View File
@@ -22,6 +22,7 @@ linters:
- errname # checks that sentinel errors are prefixed with Err, error types suffixed with Error
- exptostd # detects golang.org/x/exp/ functions replaceable by stdlib
- fatcontext # detects nested contexts in loops
- forcetypeassert # flags unchecked type assertions that can panic
- gocheckcompilerdirectives # validates go compiler directive comments (//go:)
- goprintffuncname # checks that printf-like functions are named with f at the end
- gosec # inspects source code for security problems
@@ -29,11 +30,13 @@ linters:
- ineffassign # detects assignments to existing variables that are not used
- makezero # finds slice declarations with non-zero initial length followed by append
- mirror # catches wrong mirror patterns in bytes/strings usage
- musttag # checks structs passed to marshal/unmarshal have proper tags
- modernize # modernizes code to use newer Go idioms (go fix analyzers)
- nakedret # finds naked returns in functions
- nilerr # catches code that returns nil even after checking err != nil
- nilnesserr # catches returning a different nil error variable after err != nil check
- nolintlint # reports ill-formed or insufficient nolint directives
- nosprintfhostport # flags fmt.Sprintf host:port — use net.JoinHostPort for IPv6 safety
- predeclared # catches shadowing of Go builtins (len, cap, error, etc.)
- reassign # checks that package variables are not reassigned
- recvcheck # checks for receiver type consistency (pointer vs value)
+1 -1
View File
@@ -1792,7 +1792,7 @@ func runAccountCreate(cmd *cobra.Command, args []string) {
endpointHost = h
}
}
endpointURL := fmt.Sprintf("https://%s:9999", endpointHost)
endpointURL := "https://" + net.JoinHostPort(endpointHost, "9999")
credPath := filepath.Join(homeDir, ".aws", "credentials")
configPath := filepath.Join(homeDir, ".aws", "config")
+1 -1
View File
@@ -843,7 +843,7 @@ func SetupAWSCredentials(accessKey, secretKey, region, certPath, bindIP string)
if err := UpdateAWSINIFile(configPath, configSection, map[string]string{
"region": region,
"endpoint_url": fmt.Sprintf("https://%s:9999", endpointHost),
"endpoint_url": "https://" + net.JoinHostPort(endpointHost, "9999"),
"ca_bundle": certPath,
"output": "json",
}); err != nil {
+42 -42
View File
@@ -55,80 +55,80 @@ type BootstrapConfig struct {
// Config holds all configuration for the application
type Config struct {
// Node config
Node string `mapstructure:"node"`
Host string `mapstructure:"host"` // Unique hostname or IP of this node
Region string `mapstructure:"region"`
AZ string `mapstructure:"az"`
DataDir string `mapstructure:"data_dir"`
Services []string `mapstructure:"services"` // Which services this node runs locally
Node string `json:"Node" mapstructure:"node"`
Host string `json:"Host" mapstructure:"host"` // Unique hostname or IP of this node
Region string `json:"Region" mapstructure:"region"`
AZ string `json:"AZ" mapstructure:"az"`
DataDir string `json:"DataDir" mapstructure:"data_dir"`
Services []string `json:"Services" mapstructure:"services"` // Which services this node runs locally
Daemon DaemonConfig `mapstructure:"daemon"`
NATS NATSConfig `mapstructure:"nats"`
Predastore PredastoreConfig `mapstructure:"predastore"`
Viperblock ViperblockConfig `mapstructure:"viperblock"`
AWSGW AWSGWConfig `mapstructure:"awsgw"`
VPCD VPCDConfig `mapstructure:"vpcd"`
Daemon DaemonConfig `json:"Daemon" mapstructure:"daemon"`
NATS NATSConfig `json:"NATS" mapstructure:"nats"`
Predastore PredastoreConfig `json:"Predastore" mapstructure:"predastore"`
Viperblock ViperblockConfig `json:"Viperblock" mapstructure:"viperblock"`
AWSGW AWSGWConfig `json:"AWSGW" mapstructure:"awsgw"`
VPCD VPCDConfig `json:"VPCD" mapstructure:"vpcd"`
BaseDir string `mapstructure:"base_dir"`
WalDir string `mapstructure:"wal_dir"`
BaseDir string `json:"BaseDir" mapstructure:"base_dir"`
WalDir string `json:"WalDir" mapstructure:"wal_dir"`
}
type AWSGWConfig struct {
Host string `mapstructure:"host"`
TLSKey string `mapstructure:"tlskey"`
TLSCert string `mapstructure:"tlscert"`
Config string `mapstructure:"config"`
Host string `json:"Host" mapstructure:"host"`
TLSKey string `json:"TLSKey" mapstructure:"tlskey"`
TLSCert string `json:"TLSCert" mapstructure:"tlscert"`
Config string `json:"Config" mapstructure:"config"`
Debug bool `mapstructure:"debug"`
ExpectedNodes int `mapstructure:"expected_nodes"` // TODO: Replace with root cluster config
Debug bool `json:"Debug" mapstructure:"debug"`
ExpectedNodes int `json:"ExpectedNodes" mapstructure:"expected_nodes"` // TODO: Replace with root cluster config
}
type ViperblockConfig struct {
ShardWAL *bool `mapstructure:"shardwal"` // Enable sharded WAL (default false when nil)
ShardWAL *bool `json:"ShardWAL" mapstructure:"shardwal"` // Enable sharded WAL (default false when nil)
}
// VPCDConfig holds the VPC daemon (vpcd) configuration.
type VPCDConfig struct {
OVNNBAddr string `mapstructure:"ovn_nb_addr"` // OVN Northbound DB address (e.g., "tcp:127.0.0.1:6641")
OVNSBAddr string `mapstructure:"ovn_sb_addr"` // OVN Southbound DB address (e.g., "tcp:127.0.0.1:6642")
ExternalInterface string `mapstructure:"external_interface"` // WAN NIC name (e.g., "eth1", "enp0s3") — the physical NIC on the WAN bridge
WanBridge string `mapstructure:"wan_bridge"` // OVS bridge for WAN traffic (default "br-wan", maps to OVN "external" network)
BridgeMode string `mapstructure:"bridge_mode"` // "direct" or "macvlan" (auto-detected if empty)
OVNNBAddr string `json:"OVNNBAddr" mapstructure:"ovn_nb_addr"` // OVN Northbound DB address (e.g., "tcp:127.0.0.1:6641")
OVNSBAddr string `json:"OVNSBAddr" mapstructure:"ovn_sb_addr"` // OVN Southbound DB address (e.g., "tcp:127.0.0.1:6642")
ExternalInterface string `json:"ExternalInterface" mapstructure:"external_interface"` // WAN NIC name (e.g., "eth1", "enp0s3") — the physical NIC on the WAN bridge
WanBridge string `json:"WanBridge" mapstructure:"wan_bridge"` // OVS bridge for WAN traffic (default "br-wan", maps to OVN "external" network)
BridgeMode string `json:"BridgeMode" mapstructure:"bridge_mode"` // "direct" or "macvlan" (auto-detected if empty)
}
type PredastoreConfig struct {
Host string `mapstructure:"host"`
Bucket string `mapstructure:"bucket"`
Region string `mapstructure:"region"`
AccessKey string `mapstructure:"accesskey"`
SecretKey string `mapstructure:"secretkey"`
BaseDir string `mapstructure:"base_dir"`
NodeID int `mapstructure:"node_id"`
Host string `json:"Host" mapstructure:"host"`
Bucket string `json:"Bucket" mapstructure:"bucket"`
Region string `json:"Region" mapstructure:"region"`
AccessKey string `json:"AccessKey" mapstructure:"accesskey"`
SecretKey string `json:"SecretKey" mapstructure:"secretkey"`
BaseDir string `json:"BaseDir" mapstructure:"base_dir"`
NodeID int `json:"NodeID" mapstructure:"node_id"`
}
// DaemonConfig holds the daemon configuration
type DaemonConfig struct {
Host string `mapstructure:"host"`
TLSKey string `mapstructure:"tlskey"`
TLSCert string `mapstructure:"tlscert"`
DevNetworking bool `mapstructure:"dev_networking"` // VPC instances get both TAP + hostfwd for SSH dev access
Host string `json:"Host" mapstructure:"host"`
TLSKey string `json:"TLSKey" mapstructure:"tlskey"`
TLSCert string `json:"TLSCert" mapstructure:"tlscert"`
DevNetworking bool `json:"DevNetworking" mapstructure:"dev_networking"` // VPC instances get both TAP + hostfwd for SSH dev access
}
// NATSConfig holds the NATS configuration
type NATSConfig struct {
Host string `mapstructure:"host"`
ACL NATSACL `mapstructure:"acl"`
Sub NATSSub `mapstructure:"sub"`
Host string `json:"Host" mapstructure:"host"`
ACL NATSACL `json:"ACL" mapstructure:"acl"`
Sub NATSSub `json:"Sub" mapstructure:"sub"`
}
// NATSACL holds the NATS ACL configuration
type NATSACL struct {
Token string `mapstructure:"token"`
Token string `json:"Token" mapstructure:"token"`
}
// NATSSub holds the NATS subscription configuration
type NATSSub struct {
Subject string `mapstructure:"subject"`
Subject string `json:"Subject" mapstructure:"subject"`
}
// NodeBaseDir returns the BaseDir for the current node, or "" if the config
+3 -2
View File
@@ -7,6 +7,7 @@ import (
"log/slog"
"net"
"net/http"
"strconv"
"sync"
"time"
@@ -202,7 +203,7 @@ func (d *Daemon) queryNATSRole() string {
if !d.config.HasService("nats") {
return ""
}
url := fmt.Sprintf("http://%s:%d/varz", d.daemonIP(), natsMonitorPort)
url := "http://" + net.JoinHostPort(d.daemonIP(), strconv.Itoa(natsMonitorPort)) + "/varz"
return fetchNATSRole(url, roleHTTPClient)
}
@@ -212,7 +213,7 @@ func (d *Daemon) queryPredastoreRole() string {
if !d.config.HasService("predastore") {
return ""
}
url := fmt.Sprintf("https://%s:%d/status", d.daemonIP(), predastoreDBPort)
url := "https://" + net.JoinHostPort(d.daemonIP(), strconv.Itoa(predastoreDBPort)) + "/status"
return fetchPredastoreRole(url, roleTLSHTTPClient)
}
+4 -2
View File
@@ -6,7 +6,9 @@ import (
"encoding/json"
"fmt"
"log/slog"
"net"
"net/http"
"strconv"
"sync"
"time"
@@ -117,7 +119,7 @@ func queryDBNodeStatus(ctx context.Context, out *DBNodeStatus, host string, port
}
// Query /health
healthURL := fmt.Sprintf("https://%s:%d/health", queryHost, port)
healthURL := "https://" + net.JoinHostPort(queryHost, strconv.Itoa(port)) + "/health"
req, err := http.NewRequestWithContext(ctx, http.MethodGet, healthURL, nil)
if err != nil {
return
@@ -131,7 +133,7 @@ func queryDBNodeStatus(ctx context.Context, out *DBNodeStatus, host string, port
out.Healthy = resp.StatusCode == http.StatusOK
// Query /status
statusURL := fmt.Sprintf("https://%s:%d/status", queryHost, port)
statusURL := "https://" + net.JoinHostPort(queryHost, strconv.Itoa(port)) + "/status"
req, err = http.NewRequestWithContext(ctx, http.MethodGet, statusURL, nil)
if err != nil {
return
@@ -22,6 +22,7 @@ import (
"os"
"path/filepath"
"slices"
"strconv"
"strings"
"sync"
"testing"
@@ -252,7 +253,7 @@ func waitForServer(timeout time.Duration) bool {
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
resp, err := client.Get(fmt.Sprintf("https://%s:%d/", testHost, testPort))
resp, err := client.Get("https://" + net.JoinHostPort(testHost, strconv.Itoa(testPort)) + "/")
if err == nil {
resp.Body.Close()
// Give a bit more time for config to load
@@ -273,7 +274,7 @@ func createS3Client(accessKey, secretKey string) *s3.S3 {
sess := session.Must(session.NewSession(&aws.Config{
Region: aws.String(testRegion),
Endpoint: aws.String(fmt.Sprintf("https://%s:%d", testHost, testPort)),
Endpoint: aws.String("https://" + net.JoinHostPort(testHost, strconv.Itoa(testPort))),
Credentials: credentials.NewStaticCredentials(accessKey, secretKey, ""),
S3ForcePathStyle: aws.Bool(true),
DisableSSL: aws.Bool(false),
@@ -318,7 +318,8 @@ func TestNewReverseProxy_StripsPrefixAndSetsHost(t *testing.T) {
defer backend.Close()
// Use the test server's TLS transport.
transport := backend.Client().Transport.(*http.Transport)
transport, ok := backend.Client().Transport.(*http.Transport)
require.True(t, ok, "expected *http.Transport")
// Point the proxy at the test server instead of the real backend.
backendAddr := backend.Listener.Addr().String()
+2 -2
View File
@@ -4,10 +4,10 @@ import (
"bufio"
"bytes"
"crypto/tls"
"fmt"
"io"
"net"
"net/http"
"strconv"
"strings"
"time"
)
@@ -81,7 +81,7 @@ func (ln *tlsSplitListener) redirectHTTP(conn net.Conn, firstByte byte) {
return
}
target := fmt.Sprintf("https://%s:%d%s", host, ln.port, req.URL.RequestURI())
target := "https://" + net.JoinHostPort(host, strconv.Itoa(ln.port)) + req.URL.RequestURI()
resp := &http.Response{
StatusCode: http.StatusMovedPermanently,
ProtoMajor: 1,
+3 -1
View File
@@ -95,7 +95,9 @@ func TestTopologyHandler_VPCDelete(t *testing.T) {
t.Fatalf("request vpc.delete: %v", err)
}
var result struct{ Success bool }
var result struct {
Success bool `json:"Success"`
}
_ = json.Unmarshal(resp.Data, &result)
if !result.Success {
t.Fatal("vpc.delete failed")
+28 -28
View File
@@ -3,19 +3,19 @@ package types
import "sync"
type EBSRequests struct {
Requests []EBSRequest `mapstructure:"ebs_requests"`
Requests []EBSRequest `json:"Requests" mapstructure:"ebs_requests"`
Mu sync.Mutex `json:"-"`
}
type EBSRequest struct {
Name string
VolType string
Boot bool
EFI bool
CloudInit bool
DeleteOnTermination bool
NBDURI string // NBD URI - socket path (nbd:unix:/path.sock) or TCP (nbd://host:port)
DeviceName string // AWS API device name (e.g. /dev/sdf) for hot-plugged volumes
Name string `json:"Name"`
VolType string `json:"VolType"`
Boot bool `json:"Boot"`
EFI bool `json:"EFI"`
CloudInit bool `json:"CloudInit"`
DeleteOnTermination bool `json:"DeleteOnTermination"`
NBDURI string `json:"NBDURI"` // NBD URI - socket path (nbd:unix:/path.sock) or TCP (nbd://host:port)
DeviceName string `json:"DeviceName"` // AWS API device name (e.g. /dev/sdf) for hot-plugged volumes
}
// NBDTransport defines the transport type for NBD connections
@@ -29,44 +29,44 @@ const (
)
type EBSMountResponse struct {
URI string
Mounted bool
Error string
URI string `json:"URI"`
Mounted bool `json:"Mounted"`
Error string `json:"Error"`
}
type EBSUnMountResponse struct {
Volume string
Mounted bool
Error string
Volume string `json:"Volume"`
Mounted bool `json:"Mounted"`
Error string `json:"Error"`
}
type EBSSyncRequest struct {
Volume string
Volume string `json:"Volume"`
}
type EBSSyncResponse struct {
Volume string
Synced bool
Error string
Volume string `json:"Volume"`
Synced bool `json:"Synced"`
Error string `json:"Error"`
}
type EBSDeleteRequest struct {
Volume string
Volume string `json:"Volume"`
}
type EBSDeleteResponse struct {
Volume string
Success bool
Error string
Volume string `json:"Volume"`
Success bool `json:"Success"`
Error string `json:"Error"`
}
type EBSSnapshotRequest struct {
Volume string
SnapshotID string
Volume string `json:"Volume"`
SnapshotID string `json:"SnapshotID"`
}
type EBSSnapshotResponse struct {
SnapshotID string
Success bool
Error string
SnapshotID string `json:"SnapshotID"`
Success bool `json:"Success"`
Error string `json:"Error"`
}
+2 -1
View File
@@ -3,6 +3,7 @@ package utils
import (
"errors"
"fmt"
"net"
"path/filepath"
"strconv"
"strings"
@@ -69,7 +70,7 @@ func FormatNBDSocketURI(socketPath string) string {
// FormatNBDTCPURI formats a host:port as an NBD URI for QEMU.
// Returns format: nbd://host:port
func FormatNBDTCPURI(host string, port int) string {
return fmt.Sprintf("nbd://%s:%d", host, port)
return "nbd://" + net.JoinHostPort(host, strconv.Itoa(port))
}
// ParseNBDURI parses an NBD URI into its components for QMP blockdev-add.