podman should assign a host port to -p when omitted

If the user does not provide a host port when adding -p to create/run, podman should inject an available random port.

podman run -p 80 .... podman should assign a random port to the host and expose the container port 80 to it

Signed-off-by: baude <bbaude@redhat.com>

Closes: #703
Approved by: rhatdan
This commit is contained in:
baude 2018-04-30 15:22:50 -05:00 committed by Atomic Bot
parent e98ad5751d
commit 970eaf0033
2 changed files with 47 additions and 12 deletions

View file

@ -371,26 +371,47 @@ func exposedPorts(c *cli.Context, imageExposedPorts map[string]struct{}) (map[na
if err != nil {
return nil, err
}
l, err := net.Listen("tcp", ":0")
rp, err := getRandomPort()
if err != nil {
return nil, errors.Wrapf(err, "unable to get free port")
return nil, err
}
defer l.Close()
_, randomPort, err := net.SplitHostPort(l.Addr().String())
if err != nil {
return nil, errors.Wrapf(err, "unable to determine free port")
}
rp, err := strconv.Atoi(randomPort)
if err != nil {
return nil, errors.Wrapf(err, "unable to convert random port to int")
}
logrus.Debug(fmt.Sprintf("Using random host port %s with container port %d", randomPort, p.Int()))
logrus.Debug(fmt.Sprintf("Using random host port %d with container port %d", rp, p.Int()))
portBindings[p] = CreatePortBinding(rp, "")
}
}
// We need to see if any host ports are not populated and if so, we need to assign a
// random port to them.
for k, pb := range portBindings {
if pb[0].HostPort == "" {
hostPort, err := getRandomPort()
if err != nil {
return nil, err
}
logrus.Debug(fmt.Sprintf("Using random host port %d with container port %s", hostPort, k.Port()))
pb[0].HostPort = strconv.Itoa(hostPort)
}
}
return portBindings, nil
}
func getRandomPort() (int, error) {
l, err := net.Listen("tcp", ":0")
if err != nil {
return 0, errors.Wrapf(err, "unable to get free port")
}
defer l.Close()
_, randomPort, err := net.SplitHostPort(l.Addr().String())
if err != nil {
return 0, errors.Wrapf(err, "unable to determine free port")
}
rp, err := strconv.Atoi(randomPort)
if err != nil {
return 0, errors.Wrapf(err, "unable to convert random port to int")
}
return rp, nil
}
// Parses CLI options related to container creation into a config which can be
// parsed into an OCI runtime spec
func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*createConfig, error) {

View file

@ -77,4 +77,18 @@ var _ = Describe("Podman rmi", func() {
Expect(results.ExitCode()).To(Equal(0))
Expect(results.OutputToString()).To(ContainSubstring(": 80,"))
})
It("podman run network expose duplicate host port results in error", func() {
session := podmanTest.Podman([]string{"run", "-dt", "-p", "80", ALPINE, "/bin/sh"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
inspect := podmanTest.Podman([]string{"inspect", "-l"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
containerConfig := inspect.InspectContainerToJSON()
Expect(containerConfig[0].NetworkSettings.Ports[0].HostPort).ToNot(Equal("80"))
})
})