aboutsummaryrefslogtreecommitdiff
path: root/pkg/api/handlers/compat
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api/handlers/compat')
-rw-r--r--pkg/api/handlers/compat/containers.go48
-rw-r--r--pkg/api/handlers/compat/containers_archive.go40
-rw-r--r--pkg/api/handlers/compat/containers_create.go474
-rw-r--r--pkg/api/handlers/compat/containers_stats.go12
-rw-r--r--pkg/api/handlers/compat/events.go2
-rw-r--r--pkg/api/handlers/compat/exec.go6
-rw-r--r--pkg/api/handlers/compat/images.go4
-rw-r--r--pkg/api/handlers/compat/images_build.go192
-rw-r--r--pkg/api/handlers/compat/images_prune.go4
-rw-r--r--pkg/api/handlers/compat/images_remove.go5
-rw-r--r--pkg/api/handlers/compat/info.go141
-rw-r--r--pkg/api/handlers/compat/networks.go4
-rw-r--r--pkg/api/handlers/compat/secrets.go16
-rw-r--r--pkg/api/handlers/compat/swagger.go67
-rw-r--r--pkg/api/handlers/compat/version.go9
-rw-r--r--pkg/api/handlers/compat/volumes.go8
16 files changed, 731 insertions, 301 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 1c339730e..616f0a138 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -254,7 +254,7 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
- if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
+ if sig == 0 || sig == syscall.SIGKILL {
opts := entities.WaitOptions{
Condition: []define.ContainerStatus{define.ContainerStateExited, define.ContainerStateStopped},
Interval: time.Millisecond * 250,
@@ -341,8 +341,8 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error
for idx, portMapping := range portMappings {
ports[idx] = types.Port{
IP: portMapping.HostIP,
- PrivatePort: uint16(portMapping.ContainerPort),
- PublicPort: uint16(portMapping.HostPort),
+ PrivatePort: portMapping.ContainerPort,
+ PublicPort: portMapping.HostPort,
Type: portMapping.Protocol,
}
}
@@ -369,26 +369,28 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error
return nil, err
}
- return &handlers.Container{Container: types.Container{
- ID: l.ID(),
- Names: []string{fmt.Sprintf("/%s", l.Name())},
- Image: imageName,
- ImageID: "sha256:" + imageID,
- Command: strings.Join(l.Command(), " "),
- Created: l.CreatedTime().Unix(),
- Ports: ports,
- SizeRw: sizeRW,
- SizeRootFs: sizeRootFs,
- Labels: l.Labels(),
- State: stateStr,
- Status: status,
- HostConfig: struct {
- NetworkMode string `json:",omitempty"`
- }{
- "host"},
- NetworkSettings: &networkSettings,
- Mounts: mounts,
- },
+ return &handlers.Container{
+ Container: types.Container{
+ ID: l.ID(),
+ Names: []string{fmt.Sprintf("/%s", l.Name())},
+ Image: imageName,
+ ImageID: "sha256:" + imageID,
+ Command: strings.Join(l.Command(), " "),
+ Created: l.CreatedTime().Unix(),
+ Ports: ports,
+ SizeRw: sizeRW,
+ SizeRootFs: sizeRootFs,
+ Labels: l.Labels(),
+ State: stateStr,
+ Status: status,
+ HostConfig: struct {
+ NetworkMode string `json:",omitempty"`
+ }{
+ "host",
+ },
+ NetworkSettings: &networkSettings,
+ Mounts: mounts,
+ },
ContainerCreateConfig: types.ContainerCreateConfig{},
}, nil
}
diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index 45b13818b..77fbbe38a 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"net/http"
"os"
+ "strings"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
@@ -94,11 +95,10 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De
func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
query := struct {
- Path string `schema:"path"`
- Chown bool `schema:"copyUIDGID"`
- Rename string `schema:"rename"`
- // TODO handle params below
- NoOverwriteDirNonDir bool `schema:"noOverwriteDirNonDir"`
+ Path string `schema:"path"`
+ Chown bool `schema:"copyUIDGID"`
+ Rename string `schema:"rename"`
+ NoOverwriteDirNonDir bool `schema:"noOverwriteDirNonDir"`
}{
Chown: utils.IsLibpodRequest(r), // backward compatibility
}
@@ -112,7 +112,7 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder,
var rename map[string]string
if query.Rename != "" {
if err := json.Unmarshal([]byte(query.Rename), &rename); err != nil {
- utils.Error(w, http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
+ utils.Error(w, http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query field 'rename'"))
return
}
}
@@ -120,15 +120,25 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder,
containerName := utils.GetName(r)
containerEngine := abi.ContainerEngine{Libpod: runtime}
- copyOptions := entities.CopyOptions{Chown: query.Chown, Rename: rename}
- copyFunc, err := containerEngine.ContainerCopyFromArchive(r.Context(), containerName, query.Path, r.Body, copyOptions)
- if errors.Cause(err) == define.ErrNoSuchCtr || os.IsNotExist(err) {
- // 404 is returned for an absent container and path. The
- // clients must deal with it accordingly.
- utils.Error(w, http.StatusNotFound, errors.Wrap(err, "the container doesn't exists"))
- return
- } else if err != nil {
- utils.Error(w, http.StatusInternalServerError, err)
+ copyFunc, err := containerEngine.ContainerCopyFromArchive(r.Context(), containerName, query.Path, r.Body,
+ entities.CopyOptions{
+ Chown: query.Chown,
+ NoOverwriteDirNonDir: query.NoOverwriteDirNonDir,
+ Rename: rename,
+ })
+ if err != nil {
+ switch {
+ case errors.Cause(err) == define.ErrNoSuchCtr || os.IsNotExist(err):
+ // 404 is returned for an absent container and path. The
+ // clients must deal with it accordingly.
+ utils.Error(w, http.StatusNotFound, errors.Wrap(err, "the container doesn't exists"))
+ case strings.Contains(err.Error(), "copier: put: error creating file"):
+ // Not the best test but need to break this out for compatibility
+ // See vendor/github.com/containers/buildah/copier/copier.go:1585
+ utils.Error(w, http.StatusBadRequest, err)
+ default:
+ utils.Error(w, http.StatusInternalServerError, err)
+ }
return
}
diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go
index cd592a975..67ec52047 100644
--- a/pkg/api/handlers/compat/containers_create.go
+++ b/pkg/api/handlers/compat/containers_create.go
@@ -2,18 +2,29 @@ package compat
import (
"encoding/json"
+ "fmt"
+ "net"
"net/http"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
- "github.com/containers/podman/v4/cmd/podman/common"
+ "github.com/containers/common/libnetwork/types"
+ "github.com/containers/common/pkg/cgroups"
+ "github.com/containers/common/pkg/config"
"github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/api/handlers"
"github.com/containers/podman/v4/pkg/api/handlers/utils"
api "github.com/containers/podman/v4/pkg/api/types"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/domain/infra/abi"
+ "github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/specgenutil"
"github.com/containers/storage"
+ "github.com/docker/docker/api/types/mount"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
@@ -70,7 +81,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
}
// Take body structure and convert to cliopts
- cliOpts, args, err := common.ContainerCreateToContainerCLIOpts(body, rtc)
+ cliOpts, args, err := cliOpts(body, rtc)
if err != nil {
utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "make cli opts()"))
return
@@ -107,3 +118,462 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
}
utils.WriteResponse(w, http.StatusCreated, createResponse)
}
+
+func stringMaptoArray(m map[string]string) []string {
+ a := make([]string, 0, len(m))
+ for k, v := range m {
+ a = append(a, fmt.Sprintf("%s=%s", k, v))
+ }
+ return a
+}
+
+// cliOpts converts a compat input struct to cliopts
+func cliOpts(cc handlers.CreateContainerConfig, rtc *config.Config) (*entities.ContainerCreateOptions, []string, error) {
+ var (
+ capAdd []string
+ cappDrop []string
+ entrypoint *string
+ init bool
+ specPorts []types.PortMapping
+ )
+
+ if cc.HostConfig.Init != nil {
+ init = *cc.HostConfig.Init
+ }
+
+ // Iterate devices and convert to CLI expected string
+ devices := make([]string, 0, len(cc.HostConfig.Devices))
+ for _, dev := range cc.HostConfig.Devices {
+ devices = append(devices, fmt.Sprintf("%s:%s:%s", dev.PathOnHost, dev.PathInContainer, dev.CgroupPermissions))
+ }
+
+ // iterate blkreaddevicebps
+ readBps := make([]string, 0, len(cc.HostConfig.BlkioDeviceReadBps))
+ for _, dev := range cc.HostConfig.BlkioDeviceReadBps {
+ readBps = append(readBps, dev.String())
+ }
+
+ // iterate blkreaddeviceiops
+ readIops := make([]string, 0, len(cc.HostConfig.BlkioDeviceReadIOps))
+ for _, dev := range cc.HostConfig.BlkioDeviceReadIOps {
+ readIops = append(readIops, dev.String())
+ }
+
+ // iterate blkwritedevicebps
+ writeBps := make([]string, 0, len(cc.HostConfig.BlkioDeviceWriteBps))
+ for _, dev := range cc.HostConfig.BlkioDeviceWriteBps {
+ writeBps = append(writeBps, dev.String())
+ }
+
+ // iterate blkwritedeviceiops
+ writeIops := make([]string, 0, len(cc.HostConfig.BlkioDeviceWriteIOps))
+ for _, dev := range cc.HostConfig.BlkioDeviceWriteIOps {
+ writeIops = append(writeIops, dev.String())
+ }
+
+ // entrypoint
+ // can be a string or slice. if it is a slice, we need to
+ // marshall it to json; otherwise it should just be the string
+ // value
+ if len(cc.Config.Entrypoint) > 0 {
+ entrypoint = &cc.Config.Entrypoint[0]
+ if len(cc.Config.Entrypoint) > 1 {
+ b, err := json.Marshal(cc.Config.Entrypoint)
+ if err != nil {
+ return nil, nil, err
+ }
+ jsonString := string(b)
+ entrypoint = &jsonString
+ }
+ }
+
+ // expose ports
+ expose := make([]string, 0, len(cc.Config.ExposedPorts))
+ for p := range cc.Config.ExposedPorts {
+ expose = append(expose, fmt.Sprintf("%s/%s", p.Port(), p.Proto()))
+ }
+
+ // mounts type=tmpfs/bind,source=...,target=...=,opt=val
+ volSources := make(map[string]bool)
+ volDestinations := make(map[string]bool)
+ mounts := make([]string, 0, len(cc.HostConfig.Mounts))
+ var builder strings.Builder
+ for _, m := range cc.HostConfig.Mounts {
+ addField(&builder, "type", string(m.Type))
+ addField(&builder, "source", m.Source)
+ addField(&builder, "target", m.Target)
+
+ // Store source/dest so we don't add duplicates if a volume is
+ // also mentioned in cc.Volumes.
+ // Which Docker Compose v2.0 does, for unclear reasons...
+ volSources[m.Source] = true
+ volDestinations[m.Target] = true
+
+ if m.ReadOnly {
+ addField(&builder, "ro", "true")
+ }
+ addField(&builder, "consistency", string(m.Consistency))
+ // Map any specialized mount options that intersect between *Options and cli options
+ switch m.Type {
+ case mount.TypeBind:
+ if m.BindOptions != nil {
+ addField(&builder, "bind-propagation", string(m.BindOptions.Propagation))
+ addField(&builder, "bind-nonrecursive", strconv.FormatBool(m.BindOptions.NonRecursive))
+ }
+ case mount.TypeTmpfs:
+ if m.TmpfsOptions != nil {
+ addField(&builder, "tmpfs-size", strconv.FormatInt(m.TmpfsOptions.SizeBytes, 10))
+ addField(&builder, "tmpfs-mode", strconv.FormatUint(uint64(m.TmpfsOptions.Mode), 8))
+ }
+ case mount.TypeVolume:
+ // All current VolumeOpts are handled above
+ // See vendor/github.com/containers/common/pkg/parse/parse.go:ValidateVolumeOpts()
+ }
+ mounts = append(mounts, builder.String())
+ builder.Reset()
+ }
+
+ // dns
+ dns := make([]net.IP, 0, len(cc.HostConfig.DNS))
+ for _, d := range cc.HostConfig.DNS {
+ dns = append(dns, net.ParseIP(d))
+ }
+
+ // publish
+ for port, pbs := range cc.HostConfig.PortBindings {
+ for _, pb := range pbs {
+ var hostport int
+ var err error
+ if pb.HostPort != "" {
+ hostport, err = strconv.Atoi(pb.HostPort)
+ }
+ if err != nil {
+ return nil, nil, err
+ }
+ tmpPort := types.PortMapping{
+ HostIP: pb.HostIP,
+ ContainerPort: uint16(port.Int()),
+ HostPort: uint16(hostport),
+ Range: 0,
+ Protocol: port.Proto(),
+ }
+ specPorts = append(specPorts, tmpPort)
+ }
+ }
+
+ // special case for NetworkMode, the podman default is slirp4netns for
+ // rootless but for better docker compat we want bridge.
+ netmode := string(cc.HostConfig.NetworkMode)
+ if netmode == "" || netmode == "default" {
+ netmode = "bridge"
+ }
+ nsmode, networks, netOpts, err := specgen.ParseNetworkFlag([]string{netmode})
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // network
+ // Note: we cannot emulate compat exactly here. we only allow specifics of networks to be
+ // defined when there is only one network.
+ netInfo := entities.NetOptions{
+ AddHosts: cc.HostConfig.ExtraHosts,
+ DNSOptions: cc.HostConfig.DNSOptions,
+ DNSSearch: cc.HostConfig.DNSSearch,
+ DNSServers: dns,
+ Network: nsmode,
+ PublishPorts: specPorts,
+ NetworkOptions: netOpts,
+ NoHosts: rtc.Containers.NoHosts,
+ }
+
+ // network names
+ switch {
+ case len(cc.NetworkingConfig.EndpointsConfig) > 0:
+ endpointsConfig := cc.NetworkingConfig.EndpointsConfig
+ networks := make(map[string]types.PerNetworkOptions, len(endpointsConfig))
+ for netName, endpoint := range endpointsConfig {
+ netOpts := types.PerNetworkOptions{}
+ if endpoint != nil {
+ netOpts.Aliases = endpoint.Aliases
+
+ // if IP address is provided
+ if len(endpoint.IPAddress) > 0 {
+ staticIP := net.ParseIP(endpoint.IPAddress)
+ if staticIP == nil {
+ return nil, nil, errors.Errorf("failed to parse the ip address %q", endpoint.IPAddress)
+ }
+ netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP)
+ }
+
+ if endpoint.IPAMConfig != nil {
+ // if IPAMConfig.IPv4Address is provided
+ if len(endpoint.IPAMConfig.IPv4Address) > 0 {
+ staticIP := net.ParseIP(endpoint.IPAMConfig.IPv4Address)
+ if staticIP == nil {
+ return nil, nil, errors.Errorf("failed to parse the ipv4 address %q", endpoint.IPAMConfig.IPv4Address)
+ }
+ netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP)
+ }
+ // if IPAMConfig.IPv6Address is provided
+ if len(endpoint.IPAMConfig.IPv6Address) > 0 {
+ staticIP := net.ParseIP(endpoint.IPAMConfig.IPv6Address)
+ if staticIP == nil {
+ return nil, nil, errors.Errorf("failed to parse the ipv6 address %q", endpoint.IPAMConfig.IPv6Address)
+ }
+ netOpts.StaticIPs = append(netOpts.StaticIPs, staticIP)
+ }
+ }
+ // If MAC address is provided
+ if len(endpoint.MacAddress) > 0 {
+ staticMac, err := net.ParseMAC(endpoint.MacAddress)
+ if err != nil {
+ return nil, nil, errors.Errorf("failed to parse the mac address %q", endpoint.MacAddress)
+ }
+ netOpts.StaticMAC = types.HardwareAddr(staticMac)
+ }
+ }
+
+ networks[netName] = netOpts
+ }
+
+ netInfo.Networks = networks
+ case len(cc.HostConfig.NetworkMode) > 0:
+ netInfo.Networks = networks
+ }
+
+ parsedTmp := make([]string, 0, len(cc.HostConfig.Tmpfs))
+ for path, options := range cc.HostConfig.Tmpfs {
+ finalString := path
+ if options != "" {
+ finalString += ":" + options
+ }
+ parsedTmp = append(parsedTmp, finalString)
+ }
+
+ // Note: several options here are marked as "don't need". this is based
+ // on speculation by Matt and I. We think that these come into play later
+ // like with start. We believe this is just a difference in podman/compat
+ cliOpts := entities.ContainerCreateOptions{
+ // Attach: nil, // don't need?
+ Authfile: "",
+ CapAdd: append(capAdd, cc.HostConfig.CapAdd...),
+ CapDrop: append(cappDrop, cc.HostConfig.CapDrop...),
+ CgroupParent: cc.HostConfig.CgroupParent,
+ CIDFile: cc.HostConfig.ContainerIDFile,
+ CPUPeriod: uint64(cc.HostConfig.CPUPeriod),
+ CPUQuota: cc.HostConfig.CPUQuota,
+ CPURTPeriod: uint64(cc.HostConfig.CPURealtimePeriod),
+ CPURTRuntime: cc.HostConfig.CPURealtimeRuntime,
+ CPUShares: uint64(cc.HostConfig.CPUShares),
+ // CPUS: 0, // don't need?
+ CPUSetCPUs: cc.HostConfig.CpusetCpus,
+ CPUSetMems: cc.HostConfig.CpusetMems,
+ // Detach: false, // don't need
+ // DetachKeys: "", // don't need
+ Devices: devices,
+ DeviceCgroupRule: nil,
+ DeviceReadBPs: readBps,
+ DeviceReadIOPs: readIops,
+ DeviceWriteBPs: writeBps,
+ DeviceWriteIOPs: writeIops,
+ Entrypoint: entrypoint,
+ Env: cc.Config.Env,
+ Expose: expose,
+ GroupAdd: cc.HostConfig.GroupAdd,
+ Hostname: cc.Config.Hostname,
+ ImageVolume: "bind",
+ Init: init,
+ Interactive: cc.Config.OpenStdin,
+ IPC: string(cc.HostConfig.IpcMode),
+ Label: stringMaptoArray(cc.Config.Labels),
+ LogDriver: cc.HostConfig.LogConfig.Type,
+ LogOptions: stringMaptoArray(cc.HostConfig.LogConfig.Config),
+ Name: cc.Name,
+ OOMScoreAdj: &cc.HostConfig.OomScoreAdj,
+ Arch: "",
+ OS: "",
+ Variant: "",
+ PID: string(cc.HostConfig.PidMode),
+ PIDsLimit: cc.HostConfig.PidsLimit,
+ Privileged: cc.HostConfig.Privileged,
+ PublishAll: cc.HostConfig.PublishAllPorts,
+ Quiet: false,
+ ReadOnly: cc.HostConfig.ReadonlyRootfs,
+ ReadOnlyTmpFS: true, // podman default
+ Rm: cc.HostConfig.AutoRemove,
+ SecurityOpt: cc.HostConfig.SecurityOpt,
+ StopSignal: cc.Config.StopSignal,
+ StorageOpts: stringMaptoArray(cc.HostConfig.StorageOpt),
+ Sysctl: stringMaptoArray(cc.HostConfig.Sysctls),
+ Systemd: "true", // podman default
+ TmpFS: parsedTmp,
+ TTY: cc.Config.Tty,
+ UnsetEnv: cc.UnsetEnv,
+ UnsetEnvAll: cc.UnsetEnvAll,
+ User: cc.Config.User,
+ UserNS: string(cc.HostConfig.UsernsMode),
+ UTS: string(cc.HostConfig.UTSMode),
+ Mount: mounts,
+ VolumesFrom: cc.HostConfig.VolumesFrom,
+ Workdir: cc.Config.WorkingDir,
+ Net: &netInfo,
+ HealthInterval: define.DefaultHealthCheckInterval,
+ HealthRetries: define.DefaultHealthCheckRetries,
+ HealthTimeout: define.DefaultHealthCheckTimeout,
+ HealthStartPeriod: define.DefaultHealthCheckStartPeriod,
+ }
+ if !rootless.IsRootless() {
+ var ulimits []string
+ if len(cc.HostConfig.Ulimits) > 0 {
+ for _, ul := range cc.HostConfig.Ulimits {
+ ulimits = append(ulimits, ul.String())
+ }
+ cliOpts.Ulimit = ulimits
+ }
+ }
+ if cc.HostConfig.Resources.NanoCPUs > 0 {
+ if cliOpts.CPUPeriod != 0 || cliOpts.CPUQuota != 0 {
+ return nil, nil, errors.Errorf("NanoCpus conflicts with CpuPeriod and CpuQuota")
+ }
+ cliOpts.CPUPeriod = 100000
+ cliOpts.CPUQuota = cc.HostConfig.Resources.NanoCPUs / 10000
+ }
+
+ // volumes
+ for _, vol := range cc.HostConfig.Binds {
+ cliOpts.Volume = append(cliOpts.Volume, vol)
+ // Extract the destination so we don't add duplicate mounts in
+ // the volumes phase.
+ splitVol := specgen.SplitVolumeString(vol)
+ switch len(splitVol) {
+ case 1:
+ volDestinations[vol] = true
+ default:
+ volSources[splitVol[0]] = true
+ volDestinations[splitVol[1]] = true
+ }
+ }
+ // Anonymous volumes are added differently from other volumes, in their
+ // own special field, for reasons known only to Docker. Still use the
+ // format of `-v` so we can just append them in there.
+ // Unfortunately, these may be duplicates of existing mounts in Binds.
+ // So... We need to catch that.
+ // This also handles volumes duplicated between cc.HostConfig.Mounts and
+ // cc.Volumes, as seen in compose v2.0.
+ for vol := range cc.Volumes {
+ if _, ok := volDestinations[filepath.Clean(vol)]; ok {
+ continue
+ }
+ cliOpts.Volume = append(cliOpts.Volume, vol)
+ }
+ // Make mount points for compat volumes
+ for vol := range volSources {
+ // This might be a named volume.
+ // Assume it is if it's not an absolute path.
+ if !filepath.IsAbs(vol) {
+ continue
+ }
+ // If volume already exists, there is nothing to do
+ if _, err := os.Stat(vol); err == nil {
+ continue
+ }
+ if err := os.MkdirAll(vol, 0o755); err != nil {
+ if !os.IsExist(err) {
+ return nil, nil, errors.Wrapf(err, "error making volume mountpoint for volume %s", vol)
+ }
+ }
+ }
+ if len(cc.HostConfig.BlkioWeightDevice) > 0 {
+ devices := make([]string, 0, len(cc.HostConfig.BlkioWeightDevice))
+ for _, d := range cc.HostConfig.BlkioWeightDevice {
+ devices = append(devices, d.String())
+ }
+ cliOpts.BlkIOWeightDevice = devices
+ }
+ if cc.HostConfig.BlkioWeight > 0 {
+ cliOpts.BlkIOWeight = strconv.Itoa(int(cc.HostConfig.BlkioWeight))
+ }
+
+ if cc.HostConfig.Memory > 0 {
+ cliOpts.Memory = strconv.Itoa(int(cc.HostConfig.Memory))
+ }
+
+ if cc.HostConfig.MemoryReservation > 0 {
+ cliOpts.MemoryReservation = strconv.Itoa(int(cc.HostConfig.MemoryReservation))
+ }
+
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ if err != nil {
+ return nil, nil, err
+ }
+ if cc.HostConfig.MemorySwap > 0 && (!rootless.IsRootless() || (rootless.IsRootless() && cgroupsv2)) {
+ cliOpts.MemorySwap = strconv.Itoa(int(cc.HostConfig.MemorySwap))
+ }
+
+ if cc.Config.StopTimeout != nil {
+ cliOpts.StopTimeout = uint(*cc.Config.StopTimeout)
+ }
+
+ if cc.HostConfig.ShmSize > 0 {
+ cliOpts.ShmSize = strconv.Itoa(int(cc.HostConfig.ShmSize))
+ }
+
+ if len(cc.HostConfig.RestartPolicy.Name) > 0 {
+ policy := cc.HostConfig.RestartPolicy.Name
+ // only add restart count on failure
+ if cc.HostConfig.RestartPolicy.IsOnFailure() {
+ policy += fmt.Sprintf(":%d", cc.HostConfig.RestartPolicy.MaximumRetryCount)
+ }
+ cliOpts.Restart = policy
+ }
+
+ if cc.HostConfig.MemorySwappiness != nil && (!rootless.IsRootless() || rootless.IsRootless() && cgroupsv2 && rtc.Engine.CgroupManager == "systemd") {
+ cliOpts.MemorySwappiness = *cc.HostConfig.MemorySwappiness
+ } else {
+ cliOpts.MemorySwappiness = -1
+ }
+ if cc.HostConfig.OomKillDisable != nil {
+ cliOpts.OOMKillDisable = *cc.HostConfig.OomKillDisable
+ }
+ if cc.Config.Healthcheck != nil {
+ finCmd := ""
+ for _, str := range cc.Config.Healthcheck.Test {
+ finCmd = finCmd + str + " "
+ }
+ if len(finCmd) > 1 {
+ finCmd = finCmd[:len(finCmd)-1]
+ }
+ cliOpts.HealthCmd = finCmd
+ if cc.Config.Healthcheck.Interval > 0 {
+ cliOpts.HealthInterval = cc.Config.Healthcheck.Interval.String()
+ }
+ if cc.Config.Healthcheck.Retries > 0 {
+ cliOpts.HealthRetries = uint(cc.Config.Healthcheck.Retries)
+ }
+ if cc.Config.Healthcheck.StartPeriod > 0 {
+ cliOpts.HealthStartPeriod = cc.Config.Healthcheck.StartPeriod.String()
+ }
+ if cc.Config.Healthcheck.Timeout > 0 {
+ cliOpts.HealthTimeout = cc.Config.Healthcheck.Timeout.String()
+ }
+ }
+
+ // specgen assumes the image name is arg[0]
+ cmd := []string{cc.Config.Image}
+ cmd = append(cmd, cc.Config.Cmd...)
+ return &cliOpts, cmd, nil
+}
+
+// addField is a helper function to populate mount options
+func addField(b *strings.Builder, name, value string) {
+ if value == "" {
+ return
+ }
+
+ if b.Len() > 0 {
+ b.WriteRune(',')
+ }
+ b.WriteString(name)
+ b.WriteRune('=')
+ b.WriteString(value)
+}
diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go
index 77b16b03e..6855e369b 100644
--- a/pkg/api/handlers/compat/containers_stats.go
+++ b/pkg/api/handlers/compat/containers_stats.go
@@ -44,18 +44,6 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
return
}
- // If the container isn't running, then let's not bother and return
- // immediately.
- state, err := ctnr.State()
- if err != nil {
- utils.InternalServerError(w, err)
- return
- }
- if state != define.ContainerStateRunning {
- utils.Error(w, http.StatusConflict, define.ErrCtrStateInvalid)
- return
- }
-
stats, err := ctnr.GetContainerStats(nil)
if err != nil {
utils.InternalServerError(w, errors.Wrapf(err, "failed to obtain Container %s stats", name))
diff --git a/pkg/api/handlers/compat/events.go b/pkg/api/handlers/compat/events.go
index 03b3d54bc..6bcb7bd32 100644
--- a/pkg/api/handlers/compat/events.go
+++ b/pkg/api/handlers/compat/events.go
@@ -63,7 +63,7 @@ func GetEvents(w http.ResponseWriter, r *http.Request) {
errorChannel <- runtime.Events(r.Context(), readOpts)
}()
- var flush = func() {}
+ flush := func() {}
if flusher, ok := w.(http.Flusher); ok {
flush = flusher.Flush
}
diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go
index def16d1b5..a8b45c685 100644
--- a/pkg/api/handlers/compat/exec.go
+++ b/pkg/api/handlers/compat/exec.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/podman/v4/pkg/api/handlers/utils"
"github.com/containers/podman/v4/pkg/api/server/idle"
api "github.com/containers/podman/v4/pkg/api/types"
+ "github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/specgenutil"
"github.com/gorilla/mux"
"github.com/pkg/errors"
@@ -93,10 +94,7 @@ func ExecCreateHandler(w http.ResponseWriter, r *http.Request) {
return
}
- resp := new(handlers.ExecCreateResponse)
- resp.ID = sessID
-
- utils.WriteResponse(w, http.StatusCreated, resp)
+ utils.WriteResponse(w, http.StatusCreated, entities.IDResponse{ID: sessID})
}
// ExecInspectHandler inspects a given exec session.
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index a690cdd40..76a28fadf 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -165,7 +165,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "CommitFailure"))
return
}
- utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: commitImage.ID()}) // nolint
+ utils.WriteResponse(w, http.StatusCreated, entities.IDResponse{ID: commitImage.ID()}) // nolint
}
func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
@@ -460,8 +460,6 @@ func GetImages(w http.ResponseWriter, r *http.Request) {
}
func LoadImages(w http.ResponseWriter, r *http.Request) {
- // TODO this is basically wrong
- // TODO ... improve these ^ messages to something useful
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index 318688222..7e599f4d3 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -70,67 +70,70 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
}()
query := struct {
- AddHosts string `schema:"extrahosts"`
- AdditionalCapabilities string `schema:"addcaps"`
- AllPlatforms bool `schema:"allplatforms"`
- Annotations string `schema:"annotations"`
- AppArmor string `schema:"apparmor"`
- BuildArgs string `schema:"buildargs"`
- CacheFrom string `schema:"cachefrom"`
- CgroupParent string `schema:"cgroupparent"` // nolint
- Compression uint64 `schema:"compression"`
- ConfigureNetwork string `schema:"networkmode"`
- CpuPeriod uint64 `schema:"cpuperiod"` // nolint
- CpuQuota int64 `schema:"cpuquota"` // nolint
- CpuSetCpus string `schema:"cpusetcpus"` // nolint
- CpuSetMems string `schema:"cpusetmems"` // nolint
- CpuShares uint64 `schema:"cpushares"` // nolint
- DNSOptions string `schema:"dnsoptions"`
- DNSSearch string `schema:"dnssearch"`
- DNSServers string `schema:"dnsservers"`
- Devices string `schema:"devices"`
- Dockerfile string `schema:"dockerfile"`
- DropCapabilities string `schema:"dropcaps"`
- Envs []string `schema:"setenv"`
- Excludes string `schema:"excludes"`
- ForceRm bool `schema:"forcerm"`
- From string `schema:"from"`
- HTTPProxy bool `schema:"httpproxy"`
- IdentityLabel bool `schema:"identitylabel"`
- Ignore bool `schema:"ignore"`
- Isolation string `schema:"isolation"`
- Jobs int `schema:"jobs"` // nolint
- LabelOpts string `schema:"labelopts"`
- Labels string `schema:"labels"`
- Layers bool `schema:"layers"`
- LogRusage bool `schema:"rusage"`
- Manifest string `schema:"manifest"`
- MemSwap int64 `schema:"memswap"`
- Memory int64 `schema:"memory"`
- NamespaceOptions string `schema:"nsoptions"`
- NoCache bool `schema:"nocache"`
- OSFeatures []string `schema:"osfeature"`
- OSVersion string `schema:"osversion"`
- OutputFormat string `schema:"outputformat"`
- Platform []string `schema:"platform"`
- Pull bool `schema:"pull"`
- PullPolicy string `schema:"pullpolicy"`
- Quiet bool `schema:"q"`
- Registry string `schema:"registry"`
- Rm bool `schema:"rm"`
- RusageLogFile string `schema:"rusagelogfile"`
- Remote string `schema:"remote"`
- Seccomp string `schema:"seccomp"`
- Secrets string `schema:"secrets"`
- SecurityOpt string `schema:"securityopt"`
- ShmSize int `schema:"shmsize"`
- Squash bool `schema:"squash"`
- TLSVerify bool `schema:"tlsVerify"`
- Tags []string `schema:"t"`
- Target string `schema:"target"`
- Timestamp int64 `schema:"timestamp"`
- Ulimits string `schema:"ulimits"`
- UnsetEnvs []string `schema:"unsetenv"`
+ AddHosts string `schema:"extrahosts"`
+ AdditionalCapabilities string `schema:"addcaps"`
+ AdditionalBuildContexts string `schema:"additionalbuildcontexts"`
+ AllPlatforms bool `schema:"allplatforms"`
+ Annotations string `schema:"annotations"`
+ AppArmor string `schema:"apparmor"`
+ BuildArgs string `schema:"buildargs"`
+ CacheFrom string `schema:"cachefrom"`
+ CgroupParent string `schema:"cgroupparent"` // nolint
+ Compression uint64 `schema:"compression"`
+ ConfigureNetwork string `schema:"networkmode"`
+ CPPFlags string `schema:"cppflags"`
+ CpuPeriod uint64 `schema:"cpuperiod"` // nolint
+ CpuQuota int64 `schema:"cpuquota"` // nolint
+ CpuSetCpus string `schema:"cpusetcpus"` // nolint
+ CpuSetMems string `schema:"cpusetmems"` // nolint
+ CpuShares uint64 `schema:"cpushares"` // nolint
+ DNSOptions string `schema:"dnsoptions"`
+ DNSSearch string `schema:"dnssearch"`
+ DNSServers string `schema:"dnsservers"`
+ Devices string `schema:"devices"`
+ Dockerfile string `schema:"dockerfile"`
+ DropCapabilities string `schema:"dropcaps"`
+ Envs []string `schema:"setenv"`
+ Excludes string `schema:"excludes"`
+ ForceRm bool `schema:"forcerm"`
+ From string `schema:"from"`
+ HTTPProxy bool `schema:"httpproxy"`
+ IdentityLabel bool `schema:"identitylabel"`
+ Ignore bool `schema:"ignore"`
+ Isolation string `schema:"isolation"`
+ Jobs int `schema:"jobs"` // nolint
+ LabelOpts string `schema:"labelopts"`
+ Labels string `schema:"labels"`
+ Layers bool `schema:"layers"`
+ LogRusage bool `schema:"rusage"`
+ Manifest string `schema:"manifest"`
+ MemSwap int64 `schema:"memswap"`
+ Memory int64 `schema:"memory"`
+ NamespaceOptions string `schema:"nsoptions"`
+ NoCache bool `schema:"nocache"`
+ OmitHistory bool `schema:"omithistory"`
+ OSFeatures []string `schema:"osfeature"`
+ OSVersion string `schema:"osversion"`
+ OutputFormat string `schema:"outputformat"`
+ Platform []string `schema:"platform"`
+ Pull bool `schema:"pull"`
+ PullPolicy string `schema:"pullpolicy"`
+ Quiet bool `schema:"q"`
+ Registry string `schema:"registry"`
+ Rm bool `schema:"rm"`
+ RusageLogFile string `schema:"rusagelogfile"`
+ Remote string `schema:"remote"`
+ Seccomp string `schema:"seccomp"`
+ Secrets string `schema:"secrets"`
+ SecurityOpt string `schema:"securityopt"`
+ ShmSize int `schema:"shmsize"`
+ Squash bool `schema:"squash"`
+ TLSVerify bool `schema:"tlsVerify"`
+ Tags []string `schema:"t"`
+ Target string `schema:"target"`
+ Timestamp int64 `schema:"timestamp"`
+ Ulimits string `schema:"ulimits"`
+ UnsetEnvs []string `schema:"unsetenv"`
}{
Dockerfile: "Dockerfile",
IdentityLabel: true,
@@ -170,7 +173,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
// convert addcaps formats
containerFiles := []string{}
- // Tells if query paramemter `dockerfile` is set or not.
+ // Tells if query parameter `dockerfile` is set or not.
dockerFileSet := false
if utils.IsLibpodRequest(r) && query.Remote != "" {
// The context directory could be a URL. Try to handle that.
@@ -374,6 +377,14 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
additionalTags = append(additionalTags, possiblyNormalizedTag)
}
+ var additionalBuildContexts = map[string]*buildahDefine.AdditionalBuildContext{}
+ if _, found := r.URL.Query()["additionalbuildcontexts"]; found {
+ if err := json.Unmarshal([]byte(query.AdditionalBuildContexts), &additionalBuildContexts); err != nil {
+ utils.BadRequest(w, "additionalbuildcontexts", query.AdditionalBuildContexts, err)
+ return
+ }
+ }
+
var buildArgs = map[string]string{}
if _, found := r.URL.Query()["buildargs"]; found {
if err := json.Unmarshal([]byte(query.BuildArgs), &buildArgs); err != nil {
@@ -399,6 +410,15 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
}
}
+ // convert cppflags formats
+ var cppflags = []string{}
+ if _, found := r.URL.Query()["cppflags"]; found {
+ if err := json.Unmarshal([]byte(query.CPPFlags), &cppflags); err != nil {
+ utils.BadRequest(w, "cppflags", query.CPPFlags, err)
+ return
+ }
+ }
+
// convert nsoptions formats
nsoptions := buildah.NamespaceOptions{}
if _, found := r.URL.Query()["nsoptions"]; found {
@@ -552,11 +572,13 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
buildOptions := buildahDefine.BuildOptions{
- AddCapabilities: addCaps,
- AdditionalTags: additionalTags,
- Annotations: annotations,
- Args: buildArgs,
- AllPlatforms: query.AllPlatforms,
+ AddCapabilities: addCaps,
+ AdditionalBuildContexts: additionalBuildContexts,
+ AdditionalTags: additionalTags,
+ Annotations: annotations,
+ CPPFlags: cppflags,
+ Args: buildArgs,
+ AllPlatforms: query.AllPlatforms,
CommonBuildOpts: &buildah.CommonBuildOptions{
AddHost: addhosts,
ApparmorProfile: apparmor,
@@ -574,6 +596,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
LabelOpts: labelOpts,
Memory: query.Memory,
MemorySwap: query.MemSwap,
+ OmitHistory: query.OmitHistory,
SeccompProfilePath: seccomp,
ShmSize: strconv.Itoa(query.ShmSize),
Ulimit: ulimits,
@@ -605,7 +628,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
Output: output,
OutputFormat: format,
PullPolicy: pullPolicy,
- PullPushRetryDelay: time.Duration(2 * time.Second),
+ PullPushRetryDelay: 2 * time.Second,
Quiet: query.Quiet,
Registry: registry,
RemoveIntermediateCtrs: query.Rm,
@@ -674,15 +697,17 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(body)
enc.SetEscapeHTML(true)
+ var stepErrors []string
for {
- m := struct {
+ type BuildResponse struct {
Stream string `json:"stream,omitempty"`
Error *jsonmessage.JSONError `json:"errorDetail,omitempty"`
// NOTE: `error` is being deprecated check https://github.com/moby/moby/blob/master/pkg/jsonmessage/jsonmessage.go#L148
ErrorMessage string `json:"error,omitempty"` // deprecate this slowly
Aux json.RawMessage `json:"aux,omitempty"`
- }{}
+ }
+ m := BuildResponse{}
select {
case e := <-stdout.Chan():
@@ -698,12 +723,27 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
}
flush()
case e := <-auxout.Chan():
- m.Stream = string(e)
- if err := enc.Encode(m); err != nil {
- stderr.Write([]byte(err.Error()))
+ if !query.Quiet {
+ m.Stream = string(e)
+ if err := enc.Encode(m); err != nil {
+ stderr.Write([]byte(err.Error()))
+ }
+ flush()
+ } else {
+ stepErrors = append(stepErrors, string(e))
}
- flush()
case e := <-stderr.Chan():
+ // Docker-API Compat parity : Build failed so
+ // output all step errors irrespective of quiet
+ // flag.
+ for _, stepError := range stepErrors {
+ t := BuildResponse{}
+ t.Stream = stepError
+ if err := enc.Encode(t); err != nil {
+ stderr.Write([]byte(err.Error()))
+ }
+ flush()
+ }
m.ErrorMessage = string(e)
m.Error = &jsonmessage.JSONError{
Message: m.ErrorMessage,
@@ -776,7 +816,7 @@ func extractTarFile(r *http.Request) (string, error) {
}
path := filepath.Join(anchorDir, "tarBall")
- tarBall, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
+ tarBall, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600)
if err != nil {
return "", err
}
@@ -790,7 +830,7 @@ func extractTarFile(r *http.Request) (string, error) {
}
buildDir := filepath.Join(anchorDir, "build")
- err = os.Mkdir(buildDir, 0700)
+ err = os.Mkdir(buildDir, 0o700)
if err != nil {
return "", err
}
diff --git a/pkg/api/handlers/compat/images_prune.go b/pkg/api/handlers/compat/images_prune.go
index 46524fcff..02cadbbbe 100644
--- a/pkg/api/handlers/compat/images_prune.go
+++ b/pkg/api/handlers/compat/images_prune.go
@@ -17,9 +17,7 @@ import (
)
func PruneImages(w http.ResponseWriter, r *http.Request) {
- var (
- filters []string
- )
+ var filters []string
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
diff --git a/pkg/api/handlers/compat/images_remove.go b/pkg/api/handlers/compat/images_remove.go
index f45b38c66..35bcb36aa 100644
--- a/pkg/api/handlers/compat/images_remove.go
+++ b/pkg/api/handlers/compat/images_remove.go
@@ -52,7 +52,10 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) {
utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name))
return
}
-
+ if errors.Cause(err) == storage.ErrImageUsedByContainer {
+ utils.Error(w, http.StatusConflict, errors.Wrapf(err, "image %s is in use", name))
+ return
+ }
utils.Error(w, http.StatusInternalServerError, err)
return
}
diff --git a/pkg/api/handlers/compat/info.go b/pkg/api/handlers/compat/info.go
index 6286fdaee..85547570a 100644
--- a/pkg/api/handlers/compat/info.go
+++ b/pkg/api/handlers/compat/info.go
@@ -53,75 +53,76 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
// FIXME: Need to expose if runtime supports Checkpointing
// liveRestoreEnabled := criu.CheckForCriu() && configInfo.RuntimeSupportsCheckpoint()
- info := &handlers.Info{Info: docker.Info{
- Architecture: goRuntime.GOARCH,
- BridgeNfIP6tables: !sysInfo.BridgeNFCallIP6TablesDisabled,
- BridgeNfIptables: !sysInfo.BridgeNFCallIPTablesDisabled,
- CPUCfsPeriod: sysInfo.CPUCfsPeriod,
- CPUCfsQuota: sysInfo.CPUCfsQuota,
- CPUSet: sysInfo.Cpuset,
- CPUShares: sysInfo.CPUShares,
- CgroupDriver: configInfo.Engine.CgroupManager,
- ClusterAdvertise: "",
- ClusterStore: "",
- ContainerdCommit: docker.Commit{},
- Containers: infoData.Store.ContainerStore.Number,
- ContainersPaused: stateInfo[define.ContainerStatePaused],
- ContainersRunning: stateInfo[define.ContainerStateRunning],
- ContainersStopped: stateInfo[define.ContainerStateStopped] + stateInfo[define.ContainerStateExited],
- Debug: log.IsLevelEnabled(log.DebugLevel),
- DefaultRuntime: configInfo.Engine.OCIRuntime,
- DockerRootDir: infoData.Store.GraphRoot,
- Driver: infoData.Store.GraphDriverName,
- DriverStatus: getGraphStatus(infoData.Store.GraphStatus),
- ExperimentalBuild: true,
- GenericResources: nil,
- HTTPProxy: getEnv("http_proxy"),
- HTTPSProxy: getEnv("https_proxy"),
- ID: uuid.New().String(),
- IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled,
- Images: infoData.Store.ImageStore.Number,
- IndexServerAddress: "",
- InitBinary: "",
- InitCommit: docker.Commit{},
- Isolation: "",
- KernelMemoryTCP: false,
- KernelVersion: infoData.Host.Kernel,
- Labels: nil,
- LiveRestoreEnabled: false,
- LoggingDriver: "",
- MemTotal: infoData.Host.MemTotal,
- MemoryLimit: sysInfo.MemoryLimit,
- NCPU: goRuntime.NumCPU(),
- NEventsListener: 0,
- NFd: getFdCount(),
- NGoroutines: goRuntime.NumGoroutine(),
- Name: infoData.Host.Hostname,
- NoProxy: getEnv("no_proxy"),
- OSType: goRuntime.GOOS,
- OSVersion: infoData.Host.Distribution.Version,
- OomKillDisable: sysInfo.OomKillDisable,
- OperatingSystem: infoData.Host.Distribution.Distribution,
- PidsLimit: sysInfo.PidsLimit,
- Plugins: docker.PluginsInfo{
- Volume: infoData.Plugins.Volume,
- Network: infoData.Plugins.Network,
- Log: infoData.Plugins.Log,
+ info := &handlers.Info{
+ Info: docker.Info{
+ Architecture: goRuntime.GOARCH,
+ BridgeNfIP6tables: !sysInfo.BridgeNFCallIP6TablesDisabled,
+ BridgeNfIptables: !sysInfo.BridgeNFCallIPTablesDisabled,
+ CPUCfsPeriod: sysInfo.CPUCfsPeriod,
+ CPUCfsQuota: sysInfo.CPUCfsQuota,
+ CPUSet: sysInfo.Cpuset,
+ CPUShares: sysInfo.CPUShares,
+ CgroupDriver: configInfo.Engine.CgroupManager,
+ ClusterAdvertise: "",
+ ClusterStore: "",
+ ContainerdCommit: docker.Commit{},
+ Containers: infoData.Store.ContainerStore.Number,
+ ContainersPaused: stateInfo[define.ContainerStatePaused],
+ ContainersRunning: stateInfo[define.ContainerStateRunning],
+ ContainersStopped: stateInfo[define.ContainerStateStopped] + stateInfo[define.ContainerStateExited],
+ Debug: log.IsLevelEnabled(log.DebugLevel),
+ DefaultRuntime: configInfo.Engine.OCIRuntime,
+ DockerRootDir: infoData.Store.GraphRoot,
+ Driver: infoData.Store.GraphDriverName,
+ DriverStatus: getGraphStatus(infoData.Store.GraphStatus),
+ ExperimentalBuild: true,
+ GenericResources: nil,
+ HTTPProxy: getEnv("http_proxy"),
+ HTTPSProxy: getEnv("https_proxy"),
+ ID: uuid.New().String(),
+ IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled,
+ Images: infoData.Store.ImageStore.Number,
+ IndexServerAddress: "",
+ InitBinary: "",
+ InitCommit: docker.Commit{},
+ Isolation: "",
+ KernelMemoryTCP: false,
+ KernelVersion: infoData.Host.Kernel,
+ Labels: nil,
+ LiveRestoreEnabled: false,
+ LoggingDriver: "",
+ MemTotal: infoData.Host.MemTotal,
+ MemoryLimit: sysInfo.MemoryLimit,
+ NCPU: goRuntime.NumCPU(),
+ NEventsListener: 0,
+ NFd: getFdCount(),
+ NGoroutines: goRuntime.NumGoroutine(),
+ Name: infoData.Host.Hostname,
+ NoProxy: getEnv("no_proxy"),
+ OSType: goRuntime.GOOS,
+ OSVersion: infoData.Host.Distribution.Version,
+ OomKillDisable: sysInfo.OomKillDisable,
+ OperatingSystem: infoData.Host.Distribution.Distribution,
+ PidsLimit: sysInfo.PidsLimit,
+ Plugins: docker.PluginsInfo{
+ Volume: infoData.Plugins.Volume,
+ Network: infoData.Plugins.Network,
+ Log: infoData.Plugins.Log,
+ },
+ ProductLicense: "Apache-2.0",
+ RegistryConfig: getServiceConfig(runtime),
+ RuncCommit: docker.Commit{},
+ Runtimes: getRuntimes(configInfo),
+ SecurityOptions: getSecOpts(sysInfo),
+ ServerVersion: versionInfo.Version,
+ SwapLimit: sysInfo.SwapLimit,
+ Swarm: swarm.Info{
+ LocalNodeState: swarm.LocalNodeStateInactive,
+ },
+ SystemStatus: nil,
+ SystemTime: time.Now().Format(time.RFC3339Nano),
+ Warnings: []string{},
},
- ProductLicense: "Apache-2.0",
- RegistryConfig: getServiceConfig(runtime),
- RuncCommit: docker.Commit{},
- Runtimes: getRuntimes(configInfo),
- SecurityOptions: getSecOpts(sysInfo),
- ServerVersion: versionInfo.Version,
- SwapLimit: sysInfo.SwapLimit,
- Swarm: swarm.Info{
- LocalNodeState: swarm.LocalNodeStateInactive,
- },
- SystemStatus: nil,
- SystemTime: time.Now().Format(time.RFC3339Nano),
- Warnings: []string{},
- },
BuildahVersion: infoData.Host.BuildahVersion,
CPURealtimePeriod: sysInfo.CPURealtimePeriod,
CPURealtimeRuntime: sysInfo.CPURealtimeRuntime,
@@ -186,7 +187,7 @@ func getSecOpts(sysInfo *sysinfo.SysInfo) []string {
}
func getRuntimes(configInfo *config.Config) map[string]docker.Runtime {
- var runtimes = map[string]docker.Runtime{}
+ runtimes := map[string]docker.Runtime{}
for name, paths := range configInfo.Engine.OCIRuntimes {
runtimes[name] = docker.Runtime{
Path: paths[0],
@@ -206,7 +207,7 @@ func getFdCount() (count int) {
// Just ignoring Container errors here...
func getContainersState(r *libpod.Runtime) map[define.ContainerStatus]int {
- var states = map[define.ContainerStatus]int{}
+ states := map[define.ContainerStatus]int{}
ctnrs, err := r.GetAllContainers()
if err == nil {
for _, ctnr := range ctnrs {
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index 89d914e0a..6fdd5c6a7 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -298,9 +298,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
func Connect(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
- var (
- netConnect types.NetworkConnect
- )
+ var netConnect types.NetworkConnect
if err := json.NewDecoder(r.Body).Decode(&netConnect); err != nil {
utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
diff --git a/pkg/api/handlers/compat/secrets.go b/pkg/api/handlers/compat/secrets.go
index 0c2306dc8..5031bf76b 100644
--- a/pkg/api/handlers/compat/secrets.go
+++ b/pkg/api/handlers/compat/secrets.go
@@ -16,9 +16,7 @@ import (
)
func ListSecrets(w http.ResponseWriter, r *http.Request) {
- var (
- runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
- )
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filtersMap, err := util.PrepareFilters(r)
if err != nil {
utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
@@ -51,9 +49,7 @@ func ListSecrets(w http.ResponseWriter, r *http.Request) {
}
func InspectSecret(w http.ResponseWriter, r *http.Request) {
- var (
- runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
- )
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
names := []string{name}
ic := abi.ContainerEngine{Libpod: runtime}
@@ -84,9 +80,7 @@ func InspectSecret(w http.ResponseWriter, r *http.Request) {
}
func RemoveSecret(w http.ResponseWriter, r *http.Request) {
- var (
- runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
- )
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
opts := entities.SecretRmOptions{}
name := utils.GetName(r)
@@ -104,9 +98,7 @@ func RemoveSecret(w http.ResponseWriter, r *http.Request) {
}
func CreateSecret(w http.ResponseWriter, r *http.Request) {
- var (
- runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
- )
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
opts := entities.SecretCreateOptions{}
createParams := struct {
*entities.SecretCreateRequest
diff --git a/pkg/api/handlers/compat/swagger.go b/pkg/api/handlers/compat/swagger.go
deleted file mode 100644
index 86527da6e..000000000
--- a/pkg/api/handlers/compat/swagger.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package compat
-
-import (
- "github.com/containers/podman/v4/pkg/domain/entities"
- "github.com/docker/docker/api/types"
-)
-
-// Create container
-// swagger:response ContainerCreateResponse
-type swagCtrCreateResponse struct {
- // in:body
- Body struct {
- entities.ContainerCreateResponse
- }
-}
-
-// Wait container
-// swagger:response ContainerWaitResponse
-type swagCtrWaitResponse struct {
- // in:body
- Body struct {
- // container exit code
- StatusCode int
- Error struct {
- Message string
- }
- }
-}
-
-// Network inspect
-// swagger:response CompatNetworkInspect
-type swagCompatNetworkInspect struct {
- // in:body
- Body types.NetworkResource
-}
-
-// Network list
-// swagger:response CompatNetworkList
-type swagCompatNetworkList struct {
- // in:body
- Body []types.NetworkResource
-}
-
-// Network create
-// swagger:model NetworkCreateRequest
-type NetworkCreateRequest struct {
- types.NetworkCreateRequest
-}
-
-// Network create
-// swagger:response CompatNetworkCreate
-type swagCompatNetworkCreateResponse struct {
- // in:body
- Body struct{ types.NetworkCreate }
-}
-
-// Network disconnect
-// swagger:model NetworkCompatConnectRequest
-type swagCompatNetworkConnectRequest struct {
- types.NetworkConnect
-}
-
-// Network disconnect
-// swagger:model NetworkCompatDisconnectRequest
-type swagCompatNetworkDisconnectRequest struct {
- types.NetworkDisconnect
-}
diff --git a/pkg/api/handlers/compat/version.go b/pkg/api/handlers/compat/version.go
index b113fbc90..cfc3468c2 100644
--- a/pkg/api/handlers/compat/version.go
+++ b/pkg/api/handlers/compat/version.go
@@ -57,13 +57,15 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) {
Version: conmon.Version,
Details: map[string]string{
"Package": conmon.Package,
- }},
+ },
+ },
{
Name: fmt.Sprintf("OCI Runtime (%s)", oci.Name),
Version: oci.Version,
Details: map[string]string{
"Package": oci.Package,
- }},
+ },
+ },
}
components = append(components, additional...)
}
@@ -89,5 +91,6 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) {
MinAPIVersion: fmt.Sprintf("%d.%d", minVersion.Major, minVersion.Minor),
Os: components[0].Details["Os"],
Version: components[0].Version,
- }})
+ },
+ })
}
diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go
index c8e4339b0..ff0a7af02 100644
--- a/pkg/api/handlers/compat/volumes.go
+++ b/pkg/api/handlers/compat/volumes.go
@@ -180,9 +180,7 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
}
func InspectVolume(w http.ResponseWriter, r *http.Request) {
- var (
- runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
- )
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
vol, err := runtime.GetVolume(name)
if err != nil {
@@ -263,9 +261,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
}
func PruneVolumes(w http.ResponseWriter, r *http.Request) {
- var (
- runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
- )
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
filterMap, err := util.PrepareFilters(r)
if err != nil {
utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))