From b4dcd3ead9e9ab442637cad4c47712d2606237f2 Mon Sep 17 00:00:00 2001 From: Julian Sommer <115516918+juliansommer@users.noreply.github.com> Date: Thu, 19 Feb 2026 14:40:16 +1000 Subject: [PATCH] gofix: modernize codebase with go fix analyzers Apply safe modernizations across the codebase: - minmax: replace if/else clamping with min/max builtins - fmtappendf: replace []byte(fmt.Sprintf) with fmt.Appendf - forvar: remove redundant loop variable re-declarations - inline: rename reflect.Ptr to reflect.Pointer - mapsloop: replace explicit map loops with maps package - omitzero: remove ineffective omitempty on time.Time fields - rangeint: replace 3-clause for loops with range-over-int - slicescontains: replace manual loops with slices.Contains --- hive/awsec2query/parser.go | 10 ++++----- hive/config/config.go | 8 ++----- hive/daemon/daemon.go | 22 +++++++------------ hive/daemon/daemon_handlers_test.go | 2 +- hive/daemon/health.go | 2 +- hive/daemon/health_test.go | 2 +- hive/formation/formation.go | 9 +++----- hive/formation/helpers.go | 8 ++----- .../ec2/instance/StopInstances_test.go | 1 - .../ec2/instance/TerminateInstances_test.go | 1 - hive/handlers/ec2/snapshot/service_impl.go | 5 ++--- hive/vm/vm.go | 4 ++-- 12 files changed, 27 insertions(+), 47 deletions(-) diff --git a/hive/awsec2query/parser.go b/hive/awsec2query/parser.go index 13ebc89d1..15fb91935 100644 --- a/hive/awsec2query/parser.go +++ b/hive/awsec2query/parser.go @@ -33,7 +33,7 @@ func QueryParamsToStruct(params map[string]string, out any) error { v := reflect.ValueOf(out) // Must be a pointer to a struct - if v.Kind() != reflect.Ptr { + if v.Kind() != reflect.Pointer { return fmt.Errorf("out must be a pointer to a struct") } @@ -86,7 +86,7 @@ func setStructFields(v reflect.Value, params map[string]string, prefix string) e } // Handle pointer to struct (nested structs) - if field.Kind() == reflect.Ptr && field.Type().Elem().Kind() == reflect.Struct { + if field.Kind() == reflect.Pointer && field.Type().Elem().Kind() == reflect.Struct { for _, queryKey := range queryKeys { // Check if there are any params with this prefix hasParams := false @@ -122,7 +122,7 @@ func setStructFields(v reflect.Value, params map[string]string, prefix string) e } // Handle pointer to slice - if field.Kind() == reflect.Ptr && field.Type().Elem().Kind() == reflect.Slice { + if field.Kind() == reflect.Pointer && field.Type().Elem().Kind() == reflect.Slice { for _, queryKey := range queryKeys { sliceField := reflect.New(field.Type().Elem()).Elem() if err := setSliceField(sliceField, params, queryKey); err != nil { @@ -161,7 +161,7 @@ func setFieldValue(field reflect.Value, value string) error { case reflect.String: field.SetString(value) - case reflect.Ptr: + case reflect.Pointer: // Handle pointer types if field.IsNil() { field.Set(reflect.New(field.Type().Elem())) @@ -229,7 +229,7 @@ func setSliceField(field reflect.Value, params map[string]string, prefix string) if val, ok := params[indexPrefix]; ok { elem.SetString(val) } - case reflect.Ptr: + case reflect.Pointer: // Handle pointer to string if elemType.Elem().Kind() == reflect.String { if val, ok := params[indexPrefix]; ok { diff --git a/hive/config/config.go b/hive/config/config.go index 957ee5fb0..478a9c1fc 100644 --- a/hive/config/config.go +++ b/hive/config/config.go @@ -5,6 +5,7 @@ import ( "fmt" "log/slog" "os" + "slices" "sync" "github.com/nats-io/nats.go" @@ -70,12 +71,7 @@ func (c Config) HasService(name string) bool { if len(services) == 0 { services = AllServices } - for _, s := range services { - if s == name { - return true - } - } - return false + return slices.Contains(services, name) } // GetServices returns the configured service list, defaulting to AllServices. diff --git a/hive/daemon/daemon.go b/hive/daemon/daemon.go index 7577d46e8..e096a0aa7 100644 --- a/hive/daemon/daemon.go +++ b/hive/daemon/daemon.go @@ -255,9 +255,8 @@ func (rm *ResourceManager) GetAvailableInstanceTypeInfos(showCapacity bool) []*e // Use the minimum of CPU slots and Memory slots count := min(countMem, countVCPU) - if count < 0 { - count = 0 - } + // ensure non negative + count = max(count, 0) if showCapacity { // Add to the list as many times as it can fit @@ -298,9 +297,9 @@ func (rm *ResourceManager) GetResourceStats() (totalVCPU int, totalMemGB float64 countVCPU := remainingVCPU / int(vCPUs) countMem := int(remainingMem / memGB) count := min(countMem, countVCPU) - if count < 0 { - count = 0 - } + + // ensure non negative + count = max(count, 0) name := "" if it.InstanceType != nil { name = *it.InstanceType @@ -2024,16 +2023,11 @@ func (rm *ResourceManager) canAllocate(instanceType *ec2.InstanceTypeInfo, count // Take the minimum of CPU-limited and memory-limited counts allocatableCount := min(countByMem, countByCPU) - // Cap at requested count - if allocatableCount > count { - allocatableCount = count - } + allocatableCount = min(allocatableCount, count) - // Ensure non-negative - if allocatableCount < 0 { - allocatableCount = 0 - } + // ensure non negative + allocatableCount = max(allocatableCount, 0) return allocatableCount } diff --git a/hive/daemon/daemon_handlers_test.go b/hive/daemon/daemon_handlers_test.go index 3b9687a36..48a0596ac 100644 --- a/hive/daemon/daemon_handlers_test.go +++ b/hive/daemon/daemon_handlers_test.go @@ -647,7 +647,7 @@ func TestRespondWithVolumeAttachment(t *testing.T) { sub, err := daemon.natsConn.Subscribe("test.volume.attach", func(msg *nats.Msg) { respondWithError := func(errCode string) { - msg.Respond([]byte(fmt.Sprintf(`{"Code":"%s"}`, errCode))) + msg.Respond(fmt.Appendf(nil, `{"Code":"%s"}`, errCode)) } daemon.respondWithVolumeAttachment(msg, respondWithError, "vol-123", "i-456", "/dev/sdf", "attached") }) diff --git a/hive/daemon/health.go b/hive/daemon/health.go index d085b8869..0844507e7 100644 --- a/hive/daemon/health.go +++ b/hive/daemon/health.go @@ -212,7 +212,7 @@ func (d *Daemon) maybeRestartInstance(instance *vm.VM) { // Calculate exponential backoff delay := restartBackoffBase - for i := 0; i < restartCount; i++ { + for range restartCount { delay *= 2 if delay > restartBackoffMax { delay = restartBackoffMax diff --git a/hive/daemon/health_test.go b/hive/daemon/health_test.go index 8b57c2e02..e810951d7 100644 --- a/hive/daemon/health_test.go +++ b/hive/daemon/health_test.go @@ -190,7 +190,7 @@ func TestRestartBackoff_Exponential(t *testing.T) { for i, want := range expected { delay := restartBackoffBase - for j := 0; j < i; j++ { + for range i { delay *= 2 if delay > restartBackoffMax { delay = restartBackoffMax diff --git a/hive/formation/formation.go b/hive/formation/formation.go index 24b527036..78c42c725 100644 --- a/hive/formation/formation.go +++ b/hive/formation/formation.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "log/slog" + "maps" "net" "net/http" "sync" @@ -147,9 +148,7 @@ func (fs *FormationServer) Nodes() map[string]NodeInfo { fs.mu.RLock() defer fs.mu.RUnlock() out := make(map[string]NodeInfo, len(fs.nodes)) - for k, v := range fs.nodes { - out[k] = v - } + maps.Copy(out, fs.nodes) return out } @@ -235,9 +234,7 @@ func (fs *FormationServer) handleStatus(w http.ResponseWriter, r *http.Request) // Only expose full data when formation is complete if fs.isComplete() { resp.Nodes = make(map[string]NodeInfo, len(fs.nodes)) - for k, v := range fs.nodes { - resp.Nodes[k] = v - } + maps.Copy(resp.Nodes, fs.nodes) resp.Credentials = fs.credentials resp.CACert = fs.caCert resp.CAKey = fs.caKey diff --git a/hive/formation/helpers.go b/hive/formation/helpers.go index 788218c5a..7be64b566 100644 --- a/hive/formation/helpers.go +++ b/hive/formation/helpers.go @@ -1,6 +1,7 @@ package formation import ( + "slices" "sort" "github.com/mulgadc/hive/hive/admin" @@ -12,12 +13,7 @@ func hasService(services []string, name string) bool { if len(services) == 0 { return true // backward compat: empty = all services } - for _, s := range services { - if s == name { - return true - } - } - return false + return slices.Contains(services, name) } // BuildClusterRoutes returns a sorted list of "IP:4248" NATS cluster routes diff --git a/hive/gateway/ec2/instance/StopInstances_test.go b/hive/gateway/ec2/instance/StopInstances_test.go index b217d4a1a..007d4983f 100644 --- a/hive/gateway/ec2/instance/StopInstances_test.go +++ b/hive/gateway/ec2/instance/StopInstances_test.go @@ -54,7 +54,6 @@ func TestStopInstances_MultipleInstances(t *testing.T) { ids := []string{"i-001", "i-002"} for _, id := range ids { - id := id nc.Subscribe("ec2.cmd."+id, func(msg *nats.Msg) { msg.Respond([]byte(`{"return":{}}`)) }) diff --git a/hive/gateway/ec2/instance/TerminateInstances_test.go b/hive/gateway/ec2/instance/TerminateInstances_test.go index 83b7f31be..ada962794 100644 --- a/hive/gateway/ec2/instance/TerminateInstances_test.go +++ b/hive/gateway/ec2/instance/TerminateInstances_test.go @@ -54,7 +54,6 @@ func TestTerminateInstances_MultipleInstances(t *testing.T) { ids := []string{"i-001", "i-002", "i-003"} for _, id := range ids { - id := id nc.Subscribe("ec2.cmd."+id, func(msg *nats.Msg) { msg.Respond([]byte(`{"return":{}}`)) }) diff --git a/hive/handlers/ec2/snapshot/service_impl.go b/hive/handlers/ec2/snapshot/service_impl.go index 7c0a6cee5..96175d4f4 100644 --- a/hive/handlers/ec2/snapshot/service_impl.go +++ b/hive/handlers/ec2/snapshot/service_impl.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "log/slog" + "maps" "strings" "sync" "time" @@ -491,9 +492,7 @@ func (s *SnapshotServiceImpl) CopySnapshot(input *ec2.CopySnapshotInput) (*ec2.C newCfg.Description = *input.Description } - for k, v := range sourceCfg.Tags { - newCfg.Tags[k] = v - } + maps.Copy(newCfg.Tags, sourceCfg.Tags) // Track the volume→snapshot dependency in KV before persisting to S3. if err := s.addSnapshotRef(sourceCfg.VolumeID, newSnapshotID); err != nil { diff --git a/hive/vm/vm.go b/hive/vm/vm.go index f4abaaa2b..be9d272ff 100644 --- a/hive/vm/vm.go +++ b/hive/vm/vm.go @@ -18,10 +18,10 @@ import ( // InstanceHealthState tracks crash detection and auto-restart metadata for a VM. type InstanceHealthState struct { CrashCount int `json:"crash_count"` - LastCrashTime time.Time `json:"last_crash_time,omitempty"` + LastCrashTime time.Time `json:"last_crash_time"` LastCrashReason string `json:"last_crash_reason,omitempty"` RestartCount int `json:"restart_count"` - FirstCrashTime time.Time `json:"first_crash_time,omitempty"` + FirstCrashTime time.Time `json:"first_crash_time"` } type VM struct {