Skip to content

Commit

Permalink
Handle image user and exposed ports in podman play kube
Browse files Browse the repository at this point in the history
Currently if a user runs an image with a user specified or
exposed ports with podman play kube, the fields are ignored.

Fixed: #9609

Signed-off-by: Daniel J Walsh <[email protected]>
  • Loading branch information
rhatdan committed May 26, 2021
1 parent 5b4ffc7 commit de293c9
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 20 deletions.
14 changes: 14 additions & 0 deletions pkg/specgen/generate/kube/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/containers/common/pkg/secrets"
ann "github.com/containers/podman/v3/pkg/annotations"
"github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/specgen/generate"
"github.com/containers/podman/v3/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
Expand Down Expand Up @@ -182,6 +183,19 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
if imageData.Config.WorkingDir != "" {
s.WorkDir = imageData.Config.WorkingDir
}
if s.User == "" {
s.User = imageData.Config.User
}

exposed, err := generate.GenExposedPorts(imageData.Config.ExposedPorts)
if err != nil {
return nil, err
}

for k, v := range s.Expose {
exposed[k] = v
}
s.Expose = exposed
// Pull entrypoint and cmd from image
s.Entrypoint = imageData.Config.Entrypoint
s.Command = imageData.Config.Cmd
Expand Down
49 changes: 29 additions & 20 deletions pkg/specgen/generate/ports.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,31 +268,18 @@ func createPortMappings(ctx context.Context, s *specgen.SpecGenerator, imageData

logrus.Debugf("Adding exposed ports")

// We need to merge s.Expose into image exposed ports
expose := make(map[uint16]string)
for k, v := range s.Expose {
expose[k] = v
}
if imageData != nil {
for imgExpose := range imageData.Config.ExposedPorts {
// Expose format is portNumber[/protocol]
splitExpose := strings.SplitN(imgExpose, "/", 2)
num, err := strconv.Atoi(splitExpose[0])
if err != nil {
return nil, errors.Wrapf(err, "unable to convert image EXPOSE statement %q to port number", imgExpose)
}
if num > 65535 || num < 1 {
return nil, errors.Errorf("%d from image EXPOSE statement %q is not a valid port number", num, imgExpose)
}
// No need to validate protocol, we'll do it below.
if len(splitExpose) == 1 {
expose[uint16(num)] = "tcp"
} else {
expose[uint16(num)] = splitExpose[1]
}
expose, err = GenExposedPorts(imageData.Config.ExposedPorts)
if err != nil {
return nil, err
}
}

// We need to merge s.Expose into image exposed ports
for k, v := range s.Expose {
expose[k] = v
}
// There's been a request to expose some ports. Let's do that.
// Start by figuring out what needs to be exposed.
// This is a map of container port number to protocols to expose.
Expand Down Expand Up @@ -417,3 +404,25 @@ func checkProtocol(protocol string, allowSCTP bool) ([]string, error) {

return finalProto, nil
}

func GenExposedPorts(exposedPorts map[string]struct{}) (map[uint16]string, error) {
expose := make(map[uint16]string)
for imgExpose := range exposedPorts {
// Expose format is portNumber[/protocol]
splitExpose := strings.SplitN(imgExpose, "/", 2)
num, err := strconv.Atoi(splitExpose[0])
if err != nil {
return nil, errors.Wrapf(err, "unable to convert image EXPOSE statement %q to port number", imgExpose)
}
if num > 65535 || num < 1 {
return nil, errors.Errorf("%d from image EXPOSE statement %q is not a valid port number", num, imgExpose)
}
// No need to validate protocol, we'll do it below.
if len(splitExpose) == 1 {
expose[uint16(num)] = "tcp"
} else {
expose[uint16(num)] = splitExpose[1]
}
}
return expose, nil
}
41 changes: 41 additions & 0 deletions test/system/700-play.bats
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,44 @@ RELABEL="system_u:object_r:container_file_t:s0"
fi
run_podman pod rm -f test_pod
}

@test "podman play with user from image" {
TESTDIR=$PODMAN_TMPDIR/testdir
mkdir -p $TESTDIR

testUserYaml="
apiVersion: v1
kind: Pod
metadata:
labels:
app: test
name: test_pod
spec:
containers:
- command:
- id
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: TERM
value: xterm
- name: container
value: podman
image: userimage
name: test
resources: {}
status: {}
"

cat > $PODMAN_TMPDIR/Containerfile << _EOF
from $IMAGE
USER bin
_EOF

echo "$testUserYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
run_podman build -t userimage $PODMAN_TMPDIR
run_podman play kube --start=false $PODMAN_TMPDIR/test.yaml
run_podman inspect --format "{{ .Config.User }}" test_pod-test
is "$output" bin "expect container within pod to run as the bin user"
run_podman pod rm -f test_pod
}

0 comments on commit de293c9

Please sign in to comment.