summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/networks.go2
-rw-r--r--pkg/api/server/server.go4
-rw-r--r--pkg/domain/filters/volumes.go23
-rw-r--r--pkg/domain/infra/abi/system.go2
-rw-r--r--pkg/ps/ps.go8
-rw-r--r--pkg/spec/createconfig.go9
-rw-r--r--pkg/specgen/generate/oci.go20
-rw-r--r--pkg/specgen/generate/ports.go112
-rw-r--r--pkg/specgen/specgen.go3
-rw-r--r--pkg/systemd/generate/common.go5
-rw-r--r--pkg/systemd/generate/common_test.go9
-rw-r--r--pkg/systemd/generate/containers.go2
-rw-r--r--pkg/systemd/generate/containers_test.go2
-rw-r--r--pkg/terminal/console_unix.go8
-rw-r--r--pkg/terminal/console_windows.go37
15 files changed, 204 insertions, 42 deletions
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index 0f1eca5e5..7209255d7 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -285,7 +285,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
return
}
if !exists {
- utils.Error(w, "network not found", http.StatusNotFound, err)
+ utils.Error(w, "network not found", http.StatusNotFound, network.ErrNetworkNotFound)
return
}
if err := network.RemoveNetwork(config, name); err != nil {
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index bd6a99b96..5b2f8bea2 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -173,6 +173,10 @@ func (s *APIServer) Serve() error {
}()
}
+ // Before we start serving, ensure umask is properly set for container
+ // creation.
+ _ = syscall.Umask(0022)
+
go func() {
err := s.Server.Serve(s.Listener)
if err != nil && err != http.ErrServerClosed {
diff --git a/pkg/domain/filters/volumes.go b/pkg/domain/filters/volumes.go
index f97c3f570..b1b5e6319 100644
--- a/pkg/domain/filters/volumes.go
+++ b/pkg/domain/filters/volumes.go
@@ -61,6 +61,29 @@ func GenerateVolumeFilters(filters map[string][]string) ([]libpod.VolumeFilter,
}
return false
})
+ case "dangling":
+ danglingVal := val
+ invert := false
+ switch strings.ToLower(danglingVal) {
+ case "true", "1":
+ // Do nothing
+ case "false", "0":
+ // Dangling=false requires that we
+ // invert the result of IsDangling.
+ invert = true
+ default:
+ return nil, errors.Errorf("%q is not a valid value for the \"dangling\" filter - must be true or false", danglingVal)
+ }
+ vf = append(vf, func(v *libpod.Volume) bool {
+ dangling, err := v.IsDangling()
+ if err != nil {
+ return false
+ }
+ if invert {
+ return !dangling
+ }
+ return dangling
+ })
default:
return nil, errors.Errorf("%q is in an invalid volume filter", filter)
}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 90002326e..0511289ab 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -330,7 +330,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
if err != nil {
return nil, err
}
- inUse, err := v.VolumesInUse()
+ inUse, err := v.VolumeInUse()
if err != nil {
return nil, err
}
diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go
index b07eb7f9a..cbac2cb06 100644
--- a/pkg/ps/ps.go
+++ b/pkg/ps/ps.go
@@ -145,11 +145,15 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
}
return nil
})
-
if batchErr != nil {
return entities.ListContainer{}, batchErr
}
+ portMappings, err := ctr.PortMappings()
+ if err != nil {
+ return entities.ListContainer{}, err
+ }
+
ps := entities.ListContainer{
Command: conConfig.Command,
Created: conConfig.CreatedTime.Unix(),
@@ -165,7 +169,7 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
Names: []string{conConfig.Name},
Pid: pid,
Pod: conConfig.Pod,
- Ports: conConfig.PortMappings,
+ Ports: portMappings,
Size: size,
StartedAt: startedTime.Unix(),
State: conState.String(),
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index e19c582b5..a04afa00f 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -287,10 +287,11 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l
options = append(options, libpod.WithCommand(c.UserCommand))
}
- // Add entrypoint unconditionally
- // If it's empty it's because it was explicitly set to "" or the image
- // does not have one
- options = append(options, libpod.WithEntrypoint(c.Entrypoint))
+ // Add entrypoint if it was set
+ // If it's empty it's because it was explicitly set to ""
+ if c.Entrypoint != nil {
+ options = append(options, libpod.WithEntrypoint(c.Entrypoint))
+ }
// TODO: MNT, USER, CGROUP
options = append(options, libpod.WithStopSignal(c.StopSignal))
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index 1c34f622b..badb34999 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -52,10 +52,14 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) error {
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err != nil {
logrus.Warnf("failed to return RLIMIT_NOFILE ulimit %q", err)
}
- current = rlimit.Cur
- max = rlimit.Max
+ if rlimit.Cur < current {
+ current = rlimit.Cur
+ }
+ if rlimit.Max < max {
+ max = rlimit.Max
+ }
}
- g.AddProcessRlimits("RLIMIT_NOFILE", current, max)
+ g.AddProcessRlimits("RLIMIT_NOFILE", max, current)
}
if !nprocSet {
max := kernelMax
@@ -65,10 +69,14 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) error {
if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err != nil {
logrus.Warnf("failed to return RLIMIT_NPROC ulimit %q", err)
}
- current = rlimit.Cur
- max = rlimit.Max
+ if rlimit.Cur < current {
+ current = rlimit.Cur
+ }
+ if rlimit.Max < max {
+ max = rlimit.Max
+ }
}
- g.AddProcessRlimits("RLIMIT_NPROC", current, max)
+ g.AddProcessRlimits("RLIMIT_NPROC", max, current)
}
return nil
diff --git a/pkg/specgen/generate/ports.go b/pkg/specgen/generate/ports.go
index 91c8e68d1..5c06d3bc3 100644
--- a/pkg/specgen/generate/ports.go
+++ b/pkg/specgen/generate/ports.go
@@ -43,6 +43,8 @@ func parsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping,
containerPortValidate[proto] = make(map[string]map[uint16]uint16)
}
+ postAssignHostPort := false
+
// Iterate through all port mappings, generating OCICNI PortMapping
// structs and validating there is no overlap.
for _, port := range portMappings {
@@ -71,9 +73,6 @@ func parsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping,
return nil, nil, nil, errors.Errorf("container port number must be non-0")
}
hostPort := port.HostPort
- if hostPort == 0 {
- hostPort = containerPort
- }
if uint32(len-1)+uint32(containerPort) > 65535 {
return nil, nil, nil, errors.Errorf("container port range exceeds maximum allowable port number")
}
@@ -105,26 +104,42 @@ func parsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping,
cPort := containerPort + index
hPort := hostPort + index
- if cPort == 0 || hPort == 0 {
- return nil, nil, nil, errors.Errorf("host and container ports cannot be 0")
- }
-
- testCPort := ctrPortMap[cPort]
- if testCPort != 0 && testCPort != hPort {
- // This is an attempt to redefine a port
- return nil, nil, nil, errors.Errorf("conflicting port mappings for container port %d (protocol %s)", cPort, p)
+ if cPort == 0 {
+ return nil, nil, nil, errors.Errorf("container port cannot be 0")
}
- ctrPortMap[cPort] = hPort
- testHPort := hostPortMap[hPort]
- if testHPort != 0 && testHPort != cPort {
- return nil, nil, nil, errors.Errorf("conflicting port mappings for host port %d (protocol %s)", hPort, p)
- }
- hostPortMap[hPort] = cPort
-
- // If we have an exact duplicate, just continue
- if testCPort == hPort && testHPort == cPort {
- continue
+ // Host port is allowed to be 0. If it is, we
+ // select a random port on the host.
+ // This will happen *after* all other ports are
+ // placed, to ensure we don't accidentally
+ // select a port that a later mapping wanted.
+ if hPort == 0 {
+ // If we already have a host port
+ // assigned to their container port -
+ // just use that.
+ if ctrPortMap[cPort] != 0 {
+ hPort = ctrPortMap[cPort]
+ } else {
+ postAssignHostPort = true
+ }
+ } else {
+ testCPort := ctrPortMap[cPort]
+ if testCPort != 0 && testCPort != hPort {
+ // This is an attempt to redefine a port
+ return nil, nil, nil, errors.Errorf("conflicting port mappings for container port %d (protocol %s)", cPort, p)
+ }
+ ctrPortMap[cPort] = hPort
+
+ testHPort := hostPortMap[hPort]
+ if testHPort != 0 && testHPort != cPort {
+ return nil, nil, nil, errors.Errorf("conflicting port mappings for host port %d (protocol %s)", hPort, p)
+ }
+ hostPortMap[hPort] = cPort
+
+ // If we have an exact duplicate, just continue
+ if testCPort == hPort && testHPort == cPort {
+ continue
+ }
}
// We appear to be clear. Make an OCICNI port
@@ -142,6 +157,61 @@ func parsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping,
}
}
+ // Handle any 0 host ports now by setting random container ports.
+ if postAssignHostPort {
+ remadeMappings := make([]ocicni.PortMapping, 0, len(finalMappings))
+
+ // Iterate over all
+ for _, p := range finalMappings {
+ if p.HostPort != 0 {
+ remadeMappings = append(remadeMappings, p)
+ continue
+ }
+
+ hostIPMap := hostPortValidate[p.Protocol]
+ ctrIPMap := containerPortValidate[p.Protocol]
+
+ hostPortMap, ok := hostIPMap[p.HostIP]
+ if !ok {
+ hostPortMap = make(map[uint16]uint16)
+ hostIPMap[p.HostIP] = hostPortMap
+ }
+ ctrPortMap, ok := ctrIPMap[p.HostIP]
+ if !ok {
+ ctrPortMap = make(map[uint16]uint16)
+ ctrIPMap[p.HostIP] = ctrPortMap
+ }
+
+ // See if container port has been used elsewhere
+ if ctrPortMap[uint16(p.ContainerPort)] != 0 {
+ // Duplicate definition. Let's not bother
+ // including it.
+ continue
+ }
+
+ // Max retries to ensure we don't loop forever.
+ for i := 0; i < 15; i++ {
+ candidate, err := getRandomPort()
+ if err != nil {
+ return nil, nil, nil, errors.Wrapf(err, "error getting candidate host port for container port %d", p.ContainerPort)
+ }
+
+ if hostPortMap[uint16(candidate)] == 0 {
+ logrus.Debugf("Successfully assigned container port %d to host port %d (IP %s Protocol %s)", p.ContainerPort, candidate, p.HostIP, p.Protocol)
+ hostPortMap[uint16(candidate)] = uint16(p.ContainerPort)
+ ctrPortMap[uint16(p.ContainerPort)] = uint16(candidate)
+ p.HostPort = int32(candidate)
+ break
+ }
+ }
+ if p.HostPort == 0 {
+ return nil, nil, nil, errors.Errorf("could not find open host port to map container port %d to", p.ContainerPort)
+ }
+ remadeMappings = append(remadeMappings, p)
+ }
+ return remadeMappings, containerPortValidate, hostPortValidate, nil
+ }
+
return finalMappings, containerPortValidate, hostPortValidate, nil
}
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index 3d5bf03e5..361f09379 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -435,7 +435,8 @@ type PortMapping struct {
ContainerPort uint16 `json:"container_port"`
// HostPort is the port number that will be forwarded from the host into
// the container.
- // If omitted, will be assumed to be identical to
+ // If omitted, a random port on the host (guaranteed to be over 1024)
+ // will be assigned.
HostPort uint16 `json:"host_port,omitempty"`
// Range is the number of ports that will be forwarded, starting at
// HostPort and ContainerPort and counting up.
diff --git a/pkg/systemd/generate/common.go b/pkg/systemd/generate/common.go
index fe56dc874..d6d18a810 100644
--- a/pkg/systemd/generate/common.go
+++ b/pkg/systemd/generate/common.go
@@ -1,6 +1,8 @@
package generate
import (
+ "strings"
+
"github.com/pkg/errors"
)
@@ -44,6 +46,9 @@ func filterPodFlags(command []string) []string {
i++
continue
}
+ if strings.HasPrefix(s, "--pod=") || strings.HasPrefix(s, "--pod-id-file=") {
+ continue
+ }
processed = append(processed, s)
}
return processed
diff --git a/pkg/systemd/generate/common_test.go b/pkg/systemd/generate/common_test.go
index f53bb7828..389c30f59 100644
--- a/pkg/systemd/generate/common_test.go
+++ b/pkg/systemd/generate/common_test.go
@@ -1,6 +1,7 @@
package generate
import (
+ "strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -14,12 +15,16 @@ func TestFilterPodFlags(t *testing.T) {
{[]string{"podman", "pod", "create"}},
{[]string{"podman", "pod", "create", "--name", "foo"}},
{[]string{"podman", "pod", "create", "--pod-id-file", "foo"}},
+ {[]string{"podman", "pod", "create", "--pod-id-file=foo"}},
{[]string{"podman", "run", "--pod", "foo"}},
+ {[]string{"podman", "run", "--pod=foo"}},
}
for _, test := range tests {
processed := filterPodFlags(test.input)
- assert.NotContains(t, processed, "--pod-id-file")
- assert.NotContains(t, processed, "--pod")
+ for _, s := range processed {
+ assert.False(t, strings.HasPrefix(s, "--pod-id-file"))
+ assert.False(t, strings.HasPrefix(s, "--pod"))
+ }
}
}
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go
index bf6cb81b8..333f8ef88 100644
--- a/pkg/systemd/generate/containers.go
+++ b/pkg/systemd/generate/containers.go
@@ -69,8 +69,6 @@ type containerInfo struct {
const containerTemplate = headerTemplate + `
{{- if .BoundToServices}}
-RefuseManualStart=yes
-RefuseManualStop=yes
BindsTo={{- range $index, $value := .BoundToServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}}
After={{- range $index, $value := .BoundToServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}}
{{- end}}
diff --git a/pkg/systemd/generate/containers_test.go b/pkg/systemd/generate/containers_test.go
index 80f0996a1..e108251ea 100644
--- a/pkg/systemd/generate/containers_test.go
+++ b/pkg/systemd/generate/containers_test.go
@@ -88,8 +88,6 @@ Description=Podman container-foobar.service
Documentation=man:podman-generate-systemd(1)
Wants=network.target
After=network-online.target
-RefuseManualStart=yes
-RefuseManualStop=yes
BindsTo=a.service b.service c.service pod.service
After=a.service b.service c.service pod.service
diff --git a/pkg/terminal/console_unix.go b/pkg/terminal/console_unix.go
new file mode 100644
index 000000000..6eee6aa2f
--- /dev/null
+++ b/pkg/terminal/console_unix.go
@@ -0,0 +1,8 @@
+// +build !windows
+
+package terminal
+
+// SetConsole for non-windows environments is a no-op
+func SetConsole() error {
+ return nil
+}
diff --git a/pkg/terminal/console_windows.go b/pkg/terminal/console_windows.go
new file mode 100644
index 000000000..c7691857c
--- /dev/null
+++ b/pkg/terminal/console_windows.go
@@ -0,0 +1,37 @@
+// +build windows
+
+package terminal
+
+import (
+ "github.com/sirupsen/logrus"
+ "golang.org/x/sys/windows"
+)
+
+// SetConsole switches the windows terminal mode to be able to handle colors, etc
+func SetConsole() error {
+ if err := setConsoleMode(windows.Stdout, windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err != nil {
+ return err
+ }
+ if err := setConsoleMode(windows.Stderr, windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err != nil {
+ return err
+ }
+ if err := setConsoleMode(windows.Stdin, windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err != nil {
+ return err
+ }
+ return nil
+}
+
+func setConsoleMode(handle windows.Handle, flags uint32) error {
+ var mode uint32
+ err := windows.GetConsoleMode(handle, &mode)
+ if err != nil {
+ return err
+ }
+ if err := windows.SetConsoleMode(handle, mode|flags); err != nil {
+ // In similar code, it is not considered an error if we cannot set the
+ // console mode. Following same line of thinking here.
+ logrus.WithError(err).Error("Failed to set console mode for cli")
+ }
+
+ return nil
+}