mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 11:03:34 +00:00
chore(images): initialise Docker service with containerd client
This commit is contained in:
@@ -14,6 +14,9 @@ require (
|
||||
github.com/charmbracelet/huh v0.6.0
|
||||
github.com/charmbracelet/lipgloss v1.1.0
|
||||
github.com/compose-spec/compose-go/v2 v2.4.5
|
||||
github.com/containerd/containerd/v2 v2.1.1
|
||||
github.com/containerd/errdefs v1.0.0
|
||||
github.com/containerd/log v0.1.0
|
||||
github.com/containerd/platforms v1.0.0-rc.1
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||
github.com/deckarep/golang-set/v2 v2.8.0
|
||||
@@ -24,6 +27,7 @@ require (
|
||||
github.com/docker/docker v27.4.0-rc.2+incompatible
|
||||
github.com/docker/go-connections v0.5.0
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/goccy/go-yaml v1.17.1
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/go-containerregistry v0.20.2
|
||||
@@ -101,12 +105,9 @@ require (
|
||||
github.com/containerd/console v1.0.4 // indirect
|
||||
github.com/containerd/containerd v1.7.24 // indirect
|
||||
github.com/containerd/containerd/api v1.9.0 // indirect
|
||||
github.com/containerd/containerd/v2 v2.1.1 // indirect
|
||||
github.com/containerd/continuity v0.4.5 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/fifo v1.1.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/plugin v1.0.0 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
|
||||
github.com/containerd/ttrpc v1.2.7 // indirect
|
||||
@@ -127,7 +128,6 @@ require (
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/fatih/color v1.17.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package containerd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/v2/client"
|
||||
)
|
||||
|
||||
// Client is a containerd client for image operations.
|
||||
type Client struct {
|
||||
Client *client.Client
|
||||
}
|
||||
|
||||
// NewClient creates a new containerd client connected to the given socket path.
|
||||
func NewClient(sockPath string) (*Client, error) {
|
||||
if sockPath == "" {
|
||||
return nil, fmt.Errorf("containerd socket path is required")
|
||||
}
|
||||
|
||||
c, err := client.New(
|
||||
sockPath,
|
||||
client.WithDefaultNamespace("moby"),
|
||||
client.WithTimeout(60*time.Second),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{Client: c}, nil
|
||||
}
|
||||
|
||||
// Close closes the containerd client connection.
|
||||
func (c *Client) Close() error {
|
||||
if c.Client != nil {
|
||||
return c.Client.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -63,25 +63,16 @@ type Server struct {
|
||||
waitForNetworkReady func(ctx context.Context) error
|
||||
}
|
||||
|
||||
// ServerOption configures the Docker server.
|
||||
type ServerOption func(*Server)
|
||||
|
||||
// WithNetworkReady sets the network readiness check function.
|
||||
func WithNetworkReady(networkReady func() bool) ServerOption {
|
||||
return func(s *Server) {
|
||||
s.networkReady = networkReady
|
||||
}
|
||||
}
|
||||
|
||||
// WithWaitForNetworkReady sets the network readiness wait function.
|
||||
func WithWaitForNetworkReady(waitForNetworkReady func(ctx context.Context) error) ServerOption {
|
||||
return func(s *Server) {
|
||||
s.waitForNetworkReady = waitForNetworkReady
|
||||
}
|
||||
type ServerOptions struct {
|
||||
// TODO: verify if we still need the network readiness checks as the cluster controller ensures the network
|
||||
// is ready before starting the network API server. It may still be needed when communicating with the local
|
||||
// API server but in this case we should probably fail until the cluster is initialised.
|
||||
NetworkReady func() bool
|
||||
WaitForNetworkReady func(ctx context.Context) error
|
||||
}
|
||||
|
||||
// NewServer creates a new Docker gRPC server with the provided Docker service.
|
||||
func NewServer(service *Service, db *sqlx.DB, internalDNSIP func() netip.Addr, opts ...ServerOption) *Server {
|
||||
func NewServer(service *Service, db *sqlx.DB, internalDNSIP func() netip.Addr, opts ServerOptions) *Server {
|
||||
s := &Server{
|
||||
client: service.Client,
|
||||
service: service,
|
||||
@@ -89,9 +80,8 @@ func NewServer(service *Service, db *sqlx.DB, internalDNSIP func() netip.Addr, o
|
||||
internalDNSIP: internalDNSIP,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(s)
|
||||
}
|
||||
s.networkReady = opts.NetworkReady
|
||||
s.waitForNetworkReady = opts.WaitForNetworkReady
|
||||
|
||||
return s
|
||||
}
|
||||
@@ -731,7 +721,9 @@ func (s *Server) injectConfigs(ctx context.Context, containerID string, configs
|
||||
}
|
||||
|
||||
// Copy the config content directly into the container
|
||||
if err := s.copyContentToContainer(ctx, containerID, config.Content, targetPath, uid, gid, fileMode); err != nil {
|
||||
if err := s.copyContentToContainer(
|
||||
ctx, containerID, config.Content, targetPath, uid, gid, fileMode,
|
||||
); err != nil {
|
||||
return fmt.Errorf("copy config file '%s' to container: %w", config.Name, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,21 +12,27 @@ import (
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/psviderski/uncloud/internal/containerd"
|
||||
"github.com/psviderski/uncloud/pkg/api"
|
||||
)
|
||||
|
||||
// Service provides higher-level Docker operations that extends Docker API with Uncloud-specific data
|
||||
// from the machine database.
|
||||
type Service struct {
|
||||
// Client is a Docker client for managing Docker resources.
|
||||
Client *client.Client
|
||||
db *sqlx.DB
|
||||
// containerd is a containerd client for accessing containerd images.
|
||||
containerd *containerd.Client
|
||||
// db is a connection to the machine database.
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
// NewService creates a new Docker service instance.
|
||||
func NewService(client *client.Client, db *sqlx.DB) *Service {
|
||||
func NewService(client *client.Client, containerdClient *containerd.Client, db *sqlx.DB) *Service {
|
||||
return &Service{
|
||||
Client: client,
|
||||
db: db,
|
||||
Client: client,
|
||||
containerd: containerdClient,
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/go-connections/sockets"
|
||||
"github.com/psviderski/uncloud/internal/containerd"
|
||||
"github.com/psviderski/uncloud/internal/corrosion"
|
||||
"github.com/psviderski/uncloud/internal/docker"
|
||||
"github.com/psviderski/uncloud/internal/fs"
|
||||
@@ -255,7 +256,14 @@ func NewMachine(config *Config) (*Machine, error) {
|
||||
return nil, fmt.Errorf("init machine database: %w", err)
|
||||
}
|
||||
|
||||
dockerService := machinedocker.NewService(config.DockerClient, db)
|
||||
if config.ContainerdSockPath == "" {
|
||||
return nil, errors.New("containerd socket path must be configured")
|
||||
}
|
||||
containerdClient, err := containerd.NewClient(config.ContainerdSockPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create containerd client: %w", err)
|
||||
}
|
||||
dockerService := machinedocker.NewService(config.DockerClient, containerdClient, db)
|
||||
|
||||
// Init a local gRPC proxy server that proxies requests to the local or remote machine API servers.
|
||||
proxyDirector := apiproxy.NewDirector(config.MachineSockPath, constants.MachineAPIPort)
|
||||
@@ -283,9 +291,10 @@ func NewMachine(config *Config) (*Machine, error) {
|
||||
internalDNSIP := func() netip.Addr {
|
||||
return m.IP()
|
||||
}
|
||||
m.dockerServer = machinedocker.NewServer(dockerService, db, internalDNSIP,
|
||||
machinedocker.WithNetworkReady(m.IsNetworkReady),
|
||||
machinedocker.WithWaitForNetworkReady(m.WaitForNetworkReady))
|
||||
m.dockerServer = machinedocker.NewServer(dockerService, db, internalDNSIP, machinedocker.ServerOptions{
|
||||
NetworkReady: m.IsNetworkReady,
|
||||
WaitForNetworkReady: m.WaitForNetworkReady,
|
||||
})
|
||||
caddyServer := caddyconfig.NewServer(caddyconfig.NewService(config.CaddyConfigDir))
|
||||
m.localMachineServer = newGRPCServer(m, c, m.dockerServer, caddyServer)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user