mirror of
https://github.com/fosrl/newt.git
synced 2026-02-08 14:06:40 +00:00
167 lines
5.0 KiB
Go
167 lines
5.0 KiB
Go
package docker
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/docker/docker/api/types/container"
|
|
"github.com/docker/docker/client"
|
|
"github.com/fosrl/newt/logger"
|
|
)
|
|
|
|
// Container represents a Docker container
|
|
type Container struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Image string `json:"image"`
|
|
State string `json:"state"`
|
|
Status string `json:"status"`
|
|
Ports []Port `json:"ports"`
|
|
Labels map[string]string `json:"labels"`
|
|
Created int64 `json:"created"`
|
|
Networks map[string]Network `json:"networks"`
|
|
}
|
|
|
|
// Port represents a port mapping for a Docker container
|
|
type Port struct {
|
|
PrivatePort int `json:"privatePort"`
|
|
PublicPort int `json:"publicPort,omitempty"`
|
|
Type string `json:"type"`
|
|
IP string `json:"ip,omitempty"`
|
|
}
|
|
|
|
// Network represents network information for a Docker container
|
|
type Network struct {
|
|
NetworkID string `json:"networkId"`
|
|
EndpointID string `json:"endpointId"`
|
|
Gateway string `json:"gateway,omitempty"`
|
|
IPAddress string `json:"ipAddress,omitempty"`
|
|
IPPrefixLen int `json:"ipPrefixLen,omitempty"`
|
|
IPv6Gateway string `json:"ipv6Gateway,omitempty"`
|
|
GlobalIPv6Address string `json:"globalIPv6Address,omitempty"`
|
|
GlobalIPv6PrefixLen int `json:"globalIPv6PrefixLen,omitempty"`
|
|
MacAddress string `json:"macAddress,omitempty"`
|
|
Aliases []string `json:"aliases,omitempty"`
|
|
DNSNames []string `json:"dnsNames,omitempty"`
|
|
}
|
|
|
|
// CheckSocket checks if Docker socket is available
|
|
func CheckSocket(socketPath string) bool {
|
|
// Use the provided socket path or default to standard location
|
|
if socketPath == "" {
|
|
socketPath = "/var/run/docker.sock"
|
|
}
|
|
|
|
// Try to create a connection to the Docker socket
|
|
conn, err := net.Dial("unix", socketPath)
|
|
if err != nil {
|
|
logger.Debug("Docker socket not available at %s: %v", socketPath, err)
|
|
return false
|
|
}
|
|
defer conn.Close()
|
|
|
|
logger.Debug("Docker socket is available at %s", socketPath)
|
|
return true
|
|
}
|
|
|
|
// ListContainers lists all Docker containers with their network information
|
|
func ListContainers(socketPath string) ([]Container, error) {
|
|
// Use the provided socket path or default to standard location
|
|
if socketPath == "" {
|
|
socketPath = "/var/run/docker.sock"
|
|
}
|
|
|
|
// Create a new Docker client
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
|
|
// Create client with custom socket path
|
|
cli, err := client.NewClientWithOpts(
|
|
client.WithHost("unix://"+socketPath),
|
|
client.WithAPIVersionNegotiation(),
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create Docker client: %v", err)
|
|
}
|
|
defer cli.Close()
|
|
|
|
// List containers
|
|
containers, err := cli.ContainerList(ctx, container.ListOptions{All: true})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list containers: %v", err)
|
|
}
|
|
|
|
var dockerContainers []Container
|
|
for _, c := range containers {
|
|
// Convert ports
|
|
var ports []Port
|
|
for _, port := range c.Ports {
|
|
dockerPort := Port{
|
|
PrivatePort: int(port.PrivatePort),
|
|
Type: port.Type,
|
|
}
|
|
if port.PublicPort != 0 {
|
|
dockerPort.PublicPort = int(port.PublicPort)
|
|
}
|
|
if port.IP != "" {
|
|
dockerPort.IP = port.IP
|
|
}
|
|
ports = append(ports, dockerPort)
|
|
}
|
|
|
|
// Get container name (remove leading slash)
|
|
name := ""
|
|
if len(c.Names) > 0 {
|
|
name = strings.TrimPrefix(c.Names[0], "/")
|
|
}
|
|
|
|
// Get network information by inspecting the container
|
|
networks := make(map[string]Network)
|
|
|
|
// Inspect container to get detailed network information
|
|
containerInfo, err := cli.ContainerInspect(ctx, c.ID)
|
|
if err != nil {
|
|
logger.Debug("Failed to inspect container %s for network info: %v", c.ID[:12], err)
|
|
// Continue without network info if inspection fails
|
|
} else {
|
|
// Extract network information from inspection
|
|
if containerInfo.NetworkSettings != nil && containerInfo.NetworkSettings.Networks != nil {
|
|
for networkName, endpoint := range containerInfo.NetworkSettings.Networks {
|
|
dockerNetwork := Network{
|
|
NetworkID: endpoint.NetworkID,
|
|
EndpointID: endpoint.EndpointID,
|
|
Gateway: endpoint.Gateway,
|
|
IPAddress: endpoint.IPAddress,
|
|
IPPrefixLen: endpoint.IPPrefixLen,
|
|
IPv6Gateway: endpoint.IPv6Gateway,
|
|
GlobalIPv6Address: endpoint.GlobalIPv6Address,
|
|
GlobalIPv6PrefixLen: endpoint.GlobalIPv6PrefixLen,
|
|
MacAddress: endpoint.MacAddress,
|
|
Aliases: endpoint.Aliases,
|
|
DNSNames: endpoint.DNSNames,
|
|
}
|
|
networks[networkName] = dockerNetwork
|
|
}
|
|
}
|
|
}
|
|
|
|
dockerContainer := Container{
|
|
ID: c.ID[:12], // Show short ID like docker ps
|
|
Name: name,
|
|
Image: c.Image,
|
|
State: c.State,
|
|
Status: c.Status,
|
|
Ports: ports,
|
|
Labels: c.Labels,
|
|
Created: c.Created,
|
|
Networks: networks,
|
|
}
|
|
dockerContainers = append(dockerContainers, dockerContainer)
|
|
}
|
|
|
|
return dockerContainers, nil
|
|
}
|