mirror of
https://github.com/containers/podman.git
synced 2025-06-21 09:28:09 +08:00
Merge pull request #19781 from mtrmac/api-handlers-types-no-impl
Remove a dependency on libimage from pkg/api/handlers
This commit is contained in:
@ -1,12 +1,14 @@
|
|||||||
package compat
|
package compat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/containers/buildah"
|
"github.com/containers/buildah"
|
||||||
"github.com/containers/common/libimage"
|
"github.com/containers/common/libimage"
|
||||||
@ -24,7 +26,10 @@ import (
|
|||||||
"github.com/containers/podman/v4/pkg/util"
|
"github.com/containers/podman/v4/pkg/util"
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
"github.com/docker/distribution/registry/api/errcode"
|
"github.com/docker/distribution/registry/api/errcode"
|
||||||
|
docker "github.com/docker/docker/api/types"
|
||||||
|
dockerContainer "github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/pkg/jsonmessage"
|
"github.com/docker/docker/pkg/jsonmessage"
|
||||||
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -418,7 +423,7 @@ func GetImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s: %s", name, errMsg))
|
utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s: %s", name, errMsg))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inspect, err := handlers.ImageDataToImageInspect(r.Context(), newImage)
|
inspect, err := imageDataToImageInspect(r.Context(), newImage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to convert ImageData to ImageInspect '%s': %w", name, err))
|
utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to convert ImageData to ImageInspect '%s': %w", name, err))
|
||||||
return
|
return
|
||||||
@ -426,6 +431,99 @@ func GetImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
utils.WriteResponse(w, http.StatusOK, inspect)
|
utils.WriteResponse(w, http.StatusOK, inspect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func imageDataToImageInspect(ctx context.Context, l *libimage.Image) (*handlers.ImageInspect, error) {
|
||||||
|
options := &libimage.InspectOptions{WithParent: true, WithSize: true}
|
||||||
|
info, err := l.Inspect(ctx, options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ports, err := portsToPortSet(info.Config.ExposedPorts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: many fields in Config still need wiring
|
||||||
|
config := dockerContainer.Config{
|
||||||
|
User: info.User,
|
||||||
|
ExposedPorts: ports,
|
||||||
|
Env: info.Config.Env,
|
||||||
|
Cmd: info.Config.Cmd,
|
||||||
|
Volumes: info.Config.Volumes,
|
||||||
|
WorkingDir: info.Config.WorkingDir,
|
||||||
|
Entrypoint: info.Config.Entrypoint,
|
||||||
|
Labels: info.Labels,
|
||||||
|
StopSignal: info.Config.StopSignal,
|
||||||
|
}
|
||||||
|
|
||||||
|
rootfs := docker.RootFS{}
|
||||||
|
if info.RootFS != nil {
|
||||||
|
rootfs.Type = info.RootFS.Type
|
||||||
|
rootfs.Layers = make([]string, 0, len(info.RootFS.Layers))
|
||||||
|
for _, layer := range info.RootFS.Layers {
|
||||||
|
rootfs.Layers = append(rootfs.Layers, string(layer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
graphDriver := docker.GraphDriverData{
|
||||||
|
Name: info.GraphDriver.Name,
|
||||||
|
Data: info.GraphDriver.Data,
|
||||||
|
}
|
||||||
|
// Add in basic ContainerConfig to satisfy docker-compose
|
||||||
|
cc := new(dockerContainer.Config)
|
||||||
|
cc.Hostname = info.ID[0:11] // short ID is the hostname
|
||||||
|
cc.Volumes = info.Config.Volumes
|
||||||
|
|
||||||
|
dockerImageInspect := docker.ImageInspect{
|
||||||
|
Architecture: info.Architecture,
|
||||||
|
Author: info.Author,
|
||||||
|
Comment: info.Comment,
|
||||||
|
Config: &config,
|
||||||
|
ContainerConfig: cc,
|
||||||
|
Created: l.Created().Format(time.RFC3339Nano),
|
||||||
|
DockerVersion: info.Version,
|
||||||
|
GraphDriver: graphDriver,
|
||||||
|
ID: "sha256:" + l.ID(),
|
||||||
|
Metadata: docker.ImageMetadata{},
|
||||||
|
Os: info.Os,
|
||||||
|
OsVersion: info.Version,
|
||||||
|
Parent: info.Parent,
|
||||||
|
RepoDigests: info.RepoDigests,
|
||||||
|
RepoTags: info.RepoTags,
|
||||||
|
RootFS: rootfs,
|
||||||
|
Size: info.Size,
|
||||||
|
Variant: "",
|
||||||
|
VirtualSize: info.VirtualSize,
|
||||||
|
}
|
||||||
|
return &handlers.ImageInspect{ImageInspect: dockerImageInspect}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// portsToPortSet converts libpod's exposed ports to docker's structs
|
||||||
|
func portsToPortSet(input map[string]struct{}) (nat.PortSet, error) {
|
||||||
|
ports := make(nat.PortSet)
|
||||||
|
for k := range input {
|
||||||
|
proto, port := nat.SplitProtoPort(k)
|
||||||
|
switch proto {
|
||||||
|
// See the OCI image spec for details:
|
||||||
|
// https://github.com/opencontainers/image-spec/blob/e562b04403929d582d449ae5386ff79dd7961a11/config.md#properties
|
||||||
|
case "tcp", "":
|
||||||
|
p, err := nat.NewPort("tcp", port)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to create tcp port from %s: %w", k, err)
|
||||||
|
}
|
||||||
|
ports[p] = struct{}{}
|
||||||
|
case "udp":
|
||||||
|
p, err := nat.NewPort("udp", port)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to create tcp port from %s: %w", k, err)
|
||||||
|
}
|
||||||
|
ports[p] = struct{}{}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid port proto %q in %q", proto, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ports, nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetImages(w http.ResponseWriter, r *http.Request) {
|
func GetImages(w http.ResponseWriter, r *http.Request) {
|
||||||
decoder := utils.GetDecoder(r)
|
decoder := utils.GetDecoder(r)
|
||||||
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
|
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
|
||||||
|
@ -1,16 +1,10 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containers/common/libimage"
|
|
||||||
"github.com/containers/podman/v4/pkg/domain/entities"
|
"github.com/containers/podman/v4/pkg/domain/entities"
|
||||||
docker "github.com/docker/docker/api/types"
|
docker "github.com/docker/docker/api/types"
|
||||||
dockerContainer "github.com/docker/docker/api/types/container"
|
dockerContainer "github.com/docker/docker/api/types/container"
|
||||||
dockerNetwork "github.com/docker/docker/api/types/network"
|
dockerNetwork "github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/go-connections/nat"
|
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -167,96 +161,3 @@ type ExecStartConfig struct {
|
|||||||
Height uint16 `json:"h"`
|
Height uint16 `json:"h"`
|
||||||
Width uint16 `json:"w"`
|
Width uint16 `json:"w"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ImageDataToImageInspect(ctx context.Context, l *libimage.Image) (*ImageInspect, error) {
|
|
||||||
options := &libimage.InspectOptions{WithParent: true, WithSize: true}
|
|
||||||
info, err := l.Inspect(ctx, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ports, err := portsToPortSet(info.Config.ExposedPorts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: many fields in Config still need wiring
|
|
||||||
config := dockerContainer.Config{
|
|
||||||
User: info.User,
|
|
||||||
ExposedPorts: ports,
|
|
||||||
Env: info.Config.Env,
|
|
||||||
Cmd: info.Config.Cmd,
|
|
||||||
Volumes: info.Config.Volumes,
|
|
||||||
WorkingDir: info.Config.WorkingDir,
|
|
||||||
Entrypoint: info.Config.Entrypoint,
|
|
||||||
Labels: info.Labels,
|
|
||||||
StopSignal: info.Config.StopSignal,
|
|
||||||
}
|
|
||||||
|
|
||||||
rootfs := docker.RootFS{}
|
|
||||||
if info.RootFS != nil {
|
|
||||||
rootfs.Type = info.RootFS.Type
|
|
||||||
rootfs.Layers = make([]string, 0, len(info.RootFS.Layers))
|
|
||||||
for _, layer := range info.RootFS.Layers {
|
|
||||||
rootfs.Layers = append(rootfs.Layers, string(layer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graphDriver := docker.GraphDriverData{
|
|
||||||
Name: info.GraphDriver.Name,
|
|
||||||
Data: info.GraphDriver.Data,
|
|
||||||
}
|
|
||||||
// Add in basic ContainerConfig to satisfy docker-compose
|
|
||||||
cc := new(dockerContainer.Config)
|
|
||||||
cc.Hostname = info.ID[0:11] // short ID is the hostname
|
|
||||||
cc.Volumes = info.Config.Volumes
|
|
||||||
|
|
||||||
dockerImageInspect := docker.ImageInspect{
|
|
||||||
Architecture: info.Architecture,
|
|
||||||
Author: info.Author,
|
|
||||||
Comment: info.Comment,
|
|
||||||
Config: &config,
|
|
||||||
ContainerConfig: cc,
|
|
||||||
Created: l.Created().Format(time.RFC3339Nano),
|
|
||||||
DockerVersion: info.Version,
|
|
||||||
GraphDriver: graphDriver,
|
|
||||||
ID: "sha256:" + l.ID(),
|
|
||||||
Metadata: docker.ImageMetadata{},
|
|
||||||
Os: info.Os,
|
|
||||||
OsVersion: info.Version,
|
|
||||||
Parent: info.Parent,
|
|
||||||
RepoDigests: info.RepoDigests,
|
|
||||||
RepoTags: info.RepoTags,
|
|
||||||
RootFS: rootfs,
|
|
||||||
Size: info.Size,
|
|
||||||
Variant: "",
|
|
||||||
VirtualSize: info.VirtualSize,
|
|
||||||
}
|
|
||||||
return &ImageInspect{dockerImageInspect}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// portsToPortSet converts libpod's exposed ports to docker's structs
|
|
||||||
func portsToPortSet(input map[string]struct{}) (nat.PortSet, error) {
|
|
||||||
ports := make(nat.PortSet)
|
|
||||||
for k := range input {
|
|
||||||
proto, port := nat.SplitProtoPort(k)
|
|
||||||
switch proto {
|
|
||||||
// See the OCI image spec for details:
|
|
||||||
// https://github.com/opencontainers/image-spec/blob/e562b04403929d582d449ae5386ff79dd7961a11/config.md#properties
|
|
||||||
case "tcp", "":
|
|
||||||
p, err := nat.NewPort("tcp", port)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to create tcp port from %s: %w", k, err)
|
|
||||||
}
|
|
||||||
ports[p] = struct{}{}
|
|
||||||
case "udp":
|
|
||||||
p, err := nat.NewPort("udp", port)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to create tcp port from %s: %w", k, err)
|
|
||||||
}
|
|
||||||
ports[p] = struct{}{}
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("invalid port proto %q in %q", proto, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ports, nil
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user