cmd/hi: fixes and qol (#2649)

This commit is contained in:
Kristoffer Dalby
2025-06-23 13:43:14 +02:00
committed by GitHub
parent ea7376f522
commit afc11e1f0c
31 changed files with 1097 additions and 311 deletions

View File

@@ -10,6 +10,7 @@ import (
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/client"
"github.com/docker/docker/errdefs"
)
// cleanupBeforeTest performs cleanup operations before running tests.
@@ -32,7 +33,7 @@ func cleanupAfterTest(ctx context.Context, cli *client.Client, containerID strin
})
}
// killTestContainers terminates all running test containers.
// killTestContainers terminates and removes all test containers.
func killTestContainers(ctx context.Context) error {
cli, err := createDockerClient()
if err != nil {
@@ -47,28 +48,67 @@ func killTestContainers(ctx context.Context) error {
return fmt.Errorf("failed to list containers: %w", err)
}
killed := 0
removed := 0
for _, cont := range containers {
shouldKill := false
shouldRemove := false
for _, name := range cont.Names {
if strings.Contains(name, "headscale-test-suite") ||
strings.Contains(name, "hs-") ||
strings.Contains(name, "ts-") {
shouldKill = true
strings.Contains(name, "ts-") ||
strings.Contains(name, "derp-") {
shouldRemove = true
break
}
}
if shouldKill {
if err := cli.ContainerKill(ctx, cont.ID, "KILL"); err == nil {
killed++
if shouldRemove {
// First kill the container if it's running
if cont.State == "running" {
_ = cli.ContainerKill(ctx, cont.ID, "KILL")
}
// Then remove the container with retry logic
if removeContainerWithRetry(ctx, cli, cont.ID) {
removed++
}
}
}
if removed > 0 {
fmt.Printf("Removed %d test containers\n", removed)
} else {
fmt.Println("No test containers found to remove")
}
return nil
}
// removeContainerWithRetry attempts to remove a container with exponential backoff retry logic.
func removeContainerWithRetry(ctx context.Context, cli *client.Client, containerID string) bool {
maxRetries := 3
baseDelay := 100 * time.Millisecond
for attempt := 0; attempt < maxRetries; attempt++ {
err := cli.ContainerRemove(ctx, containerID, container.RemoveOptions{
Force: true,
})
if err == nil {
return true
}
// If this is the last attempt, don't wait
if attempt == maxRetries-1 {
break
}
// Wait with exponential backoff
delay := baseDelay * time.Duration(1<<attempt)
time.Sleep(delay)
}
return false
}
// pruneDockerNetworks removes unused Docker networks.
func pruneDockerNetworks(ctx context.Context) error {
cli, err := createDockerClient()
@@ -77,11 +117,17 @@ func pruneDockerNetworks(ctx context.Context) error {
}
defer cli.Close()
_, err = cli.NetworksPrune(ctx, filters.Args{})
report, err := cli.NetworksPrune(ctx, filters.Args{})
if err != nil {
return fmt.Errorf("failed to prune networks: %w", err)
}
if len(report.NetworksDeleted) > 0 {
fmt.Printf("Removed %d unused networks\n", len(report.NetworksDeleted))
} else {
fmt.Println("No unused networks found to remove")
}
return nil
}
@@ -126,6 +172,12 @@ func cleanOldImages(ctx context.Context) error {
}
}
if removed > 0 {
fmt.Printf("Removed %d test images\n", removed)
} else {
fmt.Println("No test images found to remove")
}
return nil
}
@@ -138,7 +190,18 @@ func cleanCacheVolume(ctx context.Context) error {
defer cli.Close()
volumeName := "hs-integration-go-cache"
_ = cli.VolumeRemove(ctx, volumeName, true)
err = cli.VolumeRemove(ctx, volumeName, true)
if err != nil {
if errdefs.IsNotFound(err) {
fmt.Printf("Go module cache volume not found: %s\n", volumeName)
} else if errdefs.IsConflict(err) {
fmt.Printf("Go module cache volume is in use and cannot be removed: %s\n", volumeName)
} else {
fmt.Printf("Failed to remove Go module cache volume %s: %v\n", volumeName, err)
}
} else {
fmt.Printf("Removed Go module cache volume: %s\n", volumeName)
}
return nil
}