mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-27 19:43:34 +00:00
chore(images): simplifies ListImages service, server, and client to only list Docker images and not directly access containerd
This commit is contained in:
@@ -379,6 +379,49 @@ func (s *Server) InspectRemoteImage(
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListImages returns a list of all images matching the filter and indicates whether Docker is using the containerd
|
||||
// image store.
|
||||
func (s *Server) ListImages(ctx context.Context, req *pb.ListImagesRequest) (*pb.ListImagesResponse, error) {
|
||||
var opts image.ListOptions
|
||||
if len(req.Options) > 0 {
|
||||
if err := json.Unmarshal(req.Options, &opts); err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "unmarshal options: %v", err)
|
||||
}
|
||||
|
||||
// Handle filters separately because they implement custom JSON unmarshalling.
|
||||
var raw map[string]json.RawMessage
|
||||
if err := json.Unmarshal(req.Options, &raw); err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "unmarshal options to raw map: %v", err)
|
||||
}
|
||||
|
||||
if filtersBytes, ok := raw["Filters"]; ok {
|
||||
args, err := filters.FromJSON(string(filtersBytes))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "unmarshal filters: %v", err)
|
||||
}
|
||||
opts.Filters = args
|
||||
}
|
||||
}
|
||||
|
||||
images, err := s.service.ListImages(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
machineImages := pb.MachineImages{
|
||||
ContainerdStore: images.ContainerdStore,
|
||||
}
|
||||
if len(images.Images) > 0 {
|
||||
if machineImages.Images, err = json.Marshal(images.Images); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "marshal Docker images: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.ListImagesResponse{
|
||||
Messages: []*pb.MachineImages{&machineImages},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CreateVolume creates a new volume with the given options.
|
||||
func (s *Server) CreateVolume(ctx context.Context, req *pb.CreateVolumeRequest) (*pb.CreateVolumeResponse, error) {
|
||||
var opts volume.CreateOptions
|
||||
@@ -447,53 +490,6 @@ func (s *Server) ListVolumes(ctx context.Context, req *pb.ListVolumesRequest) (*
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListImages lists images present in the Docker and containerd image stores.
|
||||
func (s *Server) ListImages(ctx context.Context, req *pb.ListImagesRequest) (*pb.ListImagesResponse, error) {
|
||||
var opts image.ListOptions
|
||||
if len(req.Options) > 0 {
|
||||
if err := json.Unmarshal(req.Options, &opts); err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "unmarshal options: %v", err)
|
||||
}
|
||||
|
||||
// Handle filters separately because they implement custom JSON unmarshalling.
|
||||
var raw map[string]json.RawMessage
|
||||
if err := json.Unmarshal(req.Options, &raw); err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "unmarshal options to raw map: %v", err)
|
||||
}
|
||||
|
||||
if filtersBytes, ok := raw["Filters"]; ok {
|
||||
args, err := filters.FromJSON(string(filtersBytes))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "unmarshal filters: %v", err)
|
||||
}
|
||||
opts.Filters = args
|
||||
}
|
||||
}
|
||||
|
||||
images, err := s.service.ListImages(ctx, opts)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
machineImages := pb.MachineImages{
|
||||
DockerContainerdStore: images.DockerContainerdStore,
|
||||
}
|
||||
if len(images.DockerImages) > 0 {
|
||||
if machineImages.DockerImages, err = json.Marshal(images.DockerImages); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "marshal Docker images: %v", err)
|
||||
}
|
||||
}
|
||||
if len(images.ContainerdImages) > 0 {
|
||||
if machineImages.ContainerdImages, err = json.Marshal(images.ContainerdImages); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "marshal containerd images: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.ListImagesResponse{
|
||||
Messages: []*pb.MachineImages{&machineImages},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RemoveVolume removes a volume with the given ID.
|
||||
func (s *Server) RemoveVolume(ctx context.Context, req *pb.RemoveVolumeRequest) (*emptypb.Empty, error) {
|
||||
if err := s.client.VolumeRemove(ctx, req.Id, req.Force); err != nil {
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/psviderski/uncloud/internal/containerd"
|
||||
"github.com/psviderski/uncloud/pkg/api"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -25,18 +24,15 @@ import (
|
||||
type Service struct {
|
||||
// Client is a Docker client for managing Docker resources.
|
||||
Client *client.Client
|
||||
// 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, containerdClient *containerd.Client, db *sqlx.DB) *Service {
|
||||
func NewService(client *client.Client, db *sqlx.DB) *Service {
|
||||
return &Service{
|
||||
Client: client,
|
||||
containerd: containerdClient,
|
||||
db: db,
|
||||
Client: client,
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,47 +120,33 @@ func (s *Service) IsContainerdImageStoreEnabled(ctx context.Context) (bool, erro
|
||||
}
|
||||
|
||||
type Images struct {
|
||||
// DockerImages lists images from the Docker internal image store.
|
||||
// It may be empty if Docker uses the containerd image store.
|
||||
DockerImages []image.Summary
|
||||
// ContainerdImages lists images from the containerd image store.
|
||||
ContainerdImages []image.Summary
|
||||
// DockerContainerdStore indicates whether Docker is using the containerd image store.
|
||||
DockerContainerdStore bool
|
||||
// Images is a list of images present in the Docker image store (either internal or containerd).
|
||||
Images []image.Summary
|
||||
// ContainerdStore indicates whether Docker is using the containerd image store.
|
||||
ContainerdStore bool
|
||||
}
|
||||
|
||||
// ListImages lists images present in the Docker and containerd image stores.
|
||||
// If Docker uses the containerd image store, only images from containerd are listed, as the internal Docker image
|
||||
// store is not accessible in this case. Otherwise, images from both stores are listed.
|
||||
// ListImages lists Docker images with the given options and indicates whether Docker is using the containerd
|
||||
// image store. It always includes image manifests in the response if the store is containerd.
|
||||
func (s *Service) ListImages(ctx context.Context, opts image.ListOptions) (Images, error) {
|
||||
var images Images
|
||||
var imagesResp Images
|
||||
|
||||
// Always include the image manifests in the response.
|
||||
opts.Manifests = true
|
||||
// List images from Docker.
|
||||
dockerImages, err := s.Client.ImageList(ctx, opts)
|
||||
images, err := s.Client.ImageList(ctx, opts)
|
||||
if err != nil {
|
||||
return images, status.Errorf(codes.Internal, "list Docker images: %v", err)
|
||||
return imagesResp, status.Errorf(codes.Internal, "list images: %v", err)
|
||||
}
|
||||
|
||||
isContainerdStore, err := s.IsContainerdImageStoreEnabled(ctx)
|
||||
if err != nil {
|
||||
return images, status.Errorf(codes.Internal, "check if Docker uses containerd image store: %v", err)
|
||||
return imagesResp, status.Errorf(codes.Internal, "check if Docker uses containerd image store: %v", err)
|
||||
}
|
||||
|
||||
if isContainerdStore {
|
||||
// Docker uses the containerd image store, hence the images listed from Docker are just references to images
|
||||
// in containerd. The internal Docker image store is not accessible in this case.
|
||||
images = Images{
|
||||
ContainerdImages: dockerImages,
|
||||
DockerContainerdStore: true,
|
||||
}
|
||||
} else {
|
||||
images = Images{
|
||||
DockerImages: dockerImages,
|
||||
// TODO: List images from containerd directly. ContainerdImages: containerdImages,
|
||||
}
|
||||
imagesResp = Images{
|
||||
Images: images,
|
||||
ContainerdStore: isContainerdStore,
|
||||
}
|
||||
|
||||
return images, nil
|
||||
return imagesResp, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user