mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 17:11:30 +00:00
fix: enable more linters (#121)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user