summaryrefslogtreecommitdiff
path: root/pkg/specgenutil
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/specgenutil')
-rw-r--r--pkg/specgenutil/ports_test.go57
-rw-r--r--pkg/specgenutil/specgen.go4
-rw-r--r--pkg/specgenutil/specgenutil_test.go77
-rw-r--r--pkg/specgenutil/util.go1
-rw-r--r--pkg/specgenutil/util_test.go146
-rw-r--r--pkg/specgenutil/volumes.go21
-rw-r--r--pkg/specgenutil/volumes_test.go68
7 files changed, 364 insertions, 10 deletions
diff --git a/pkg/specgenutil/ports_test.go b/pkg/specgenutil/ports_test.go
new file mode 100644
index 000000000..3f62c619c
--- /dev/null
+++ b/pkg/specgenutil/ports_test.go
@@ -0,0 +1,57 @@
+package specgenutil
+
+import "testing"
+
+func Test_verifyExpose(t *testing.T) {
+ type args struct {
+ expose []string
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "single port with tcp",
+ args: args{
+ expose: []string{"53/tcp"},
+ },
+ wantErr: false,
+ },
+ {
+ name: "single port with udp",
+ args: args{
+ expose: []string{"53/udp"},
+ },
+ wantErr: false,
+ },
+ {
+ name: "good port range",
+ args: args{
+ expose: []string{"100-133"},
+ },
+ wantErr: false,
+ },
+ {
+ name: "high to low should fail",
+ args: args{
+ expose: []string{"100-99"},
+ },
+ wantErr: true,
+ },
+ {
+ name: "range with protocol",
+ args: args{
+ expose: []string{"53/tcp-55/tcp"},
+ },
+ wantErr: false,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if err := verifyExpose(tt.args.expose); (err != nil) != tt.wantErr {
+ t.Errorf("verifyExpose() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ })
+ }
+}
diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go
index 00de99817..f0dfcac1a 100644
--- a/pkg/specgenutil/specgen.go
+++ b/pkg/specgenutil/specgen.go
@@ -136,7 +136,7 @@ func LimitToSwap(memory *specs.LinuxMemory, swap string, ml int64) {
}
}
-func getMemoryLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) (*specs.LinuxMemory, error) {
+func getMemoryLimits(c *entities.ContainerCreateOptions) (*specs.LinuxMemory, error) {
var err error
memory := &specs.LinuxMemory{}
hasLimits := false
@@ -497,7 +497,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
}
if s.ResourceLimits.Memory == nil || (len(c.Memory) != 0 || len(c.MemoryReservation) != 0 || len(c.MemorySwap) != 0 || c.MemorySwappiness != 0) {
- s.ResourceLimits.Memory, err = getMemoryLimits(s, c)
+ s.ResourceLimits.Memory, err = getMemoryLimits(c)
if err != nil {
return err
}
diff --git a/pkg/specgenutil/specgenutil_test.go b/pkg/specgenutil/specgenutil_test.go
new file mode 100644
index 000000000..5867b0ae0
--- /dev/null
+++ b/pkg/specgenutil/specgenutil_test.go
@@ -0,0 +1,77 @@
+//go:build linux
+// +build linux
+
+package specgenutil
+
+import (
+ "testing"
+
+ "github.com/containers/common/pkg/machine"
+ "github.com/containers/podman/v4/pkg/domain/entities"
+ "github.com/containers/podman/v4/pkg/specgen"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestWinPath(t *testing.T) {
+ const (
+ fail = false
+ pass = true
+ )
+ tests := []struct {
+ vol string
+ source string
+ dest string
+ isN bool
+ outcome bool
+ mach string
+ }{
+ {`C:\Foo:/blah`, "/mnt/c/Foo", "/blah", false, pass, "wsl"},
+ {`C:\Foo:/blah`, "/mnt/c/Foo", "/blah", false, fail, ""},
+ {`\\?\C:\Foo:/blah`, "/mnt/c/Foo", "/blah", false, pass, "wsl"},
+ {`/c/bar:/blah`, "/mnt/c/bar", "/blah", false, pass, "wsl"},
+ {`/c/bar:/blah`, "/c/bar", "/blah", false, pass, ""},
+ {`/test/this:/blah`, "/test/this", "/blah", false, pass, "wsl"},
+ {`c:/bar/something:/other`, "/mnt/c/bar/something", "/other", false, pass, "wsl"},
+ {`c:/foo:ro`, "c", "/foo", true, pass, ""},
+ {`\\computer\loc:/dest`, "", "", false, fail, "wsl"},
+ {`\\.\drive\loc:/target`, "/mnt/wsl/drive/loc", "/target", false, pass, "wsl"},
+ }
+
+ f := func(vol string, mach string) (*specgen.SpecGenerator, error) {
+ machine := machine.GetMachineMarker()
+ oldEnable, oldType := machine.Enabled, machine.Type
+ machine.Enabled, machine.Type = len(mach) > 0, mach
+ sg := specgen.NewSpecGenerator("nothing", false)
+ err := FillOutSpecGen(sg, &entities.ContainerCreateOptions{
+ ImageVolume: "ignore",
+ Volume: []string{vol}}, []string{},
+ )
+ machine.Enabled, machine.Type = oldEnable, oldType
+ return sg, err
+ }
+
+ for _, test := range tests {
+ msg := "Checking: " + test.vol
+ sg, err := f(test.vol, test.mach)
+ if test.outcome == fail {
+ assert.NotNil(t, err, msg)
+ continue
+ }
+ if !assert.Nil(t, err, msg) {
+ continue
+ }
+ if test.isN {
+ if !assert.Equal(t, 1, len(sg.Volumes), msg) {
+ continue
+ }
+ assert.Equal(t, test.source, sg.Volumes[0].Name, msg)
+ assert.Equal(t, test.dest, sg.Volumes[0].Dest, msg)
+ } else {
+ if !assert.Equal(t, 1, len(sg.Mounts), msg) {
+ continue
+ }
+ assert.Equal(t, test.source, sg.Mounts[0].Source, msg)
+ assert.Equal(t, test.dest, sg.Mounts[0].Destination, msg)
+ }
+ }
+}
diff --git a/pkg/specgenutil/util.go b/pkg/specgenutil/util.go
index 80d31398b..fa2e90457 100644
--- a/pkg/specgenutil/util.go
+++ b/pkg/specgenutil/util.go
@@ -281,6 +281,7 @@ func CreateExitCommandArgs(storageConfig storageTypes.StoreOptions, config *conf
"--tmpdir", config.Engine.TmpDir,
"--network-config-dir", config.Network.NetworkConfigDir,
"--network-backend", config.Network.NetworkBackend,
+ "--volumepath", config.Engine.VolumePath,
}
if config.Engine.OCIRuntime != "" {
command = append(command, []string{"--runtime", config.Engine.OCIRuntime}...)
diff --git a/pkg/specgenutil/util_test.go b/pkg/specgenutil/util_test.go
new file mode 100644
index 000000000..79d60d335
--- /dev/null
+++ b/pkg/specgenutil/util_test.go
@@ -0,0 +1,146 @@
+package specgenutil
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestCreateExpose(t *testing.T) {
+ single := make(map[uint16]string, 0)
+ single[99] = "tcp"
+
+ simpleRange := make(map[uint16]string, 0)
+ simpleRange[99] = "tcp"
+ simpleRange[100] = "tcp"
+
+ simpleRangeUDP := make(map[uint16]string, 0)
+ simpleRangeUDP[99] = "udp"
+ simpleRangeUDP[100] = "udp"
+ type args struct {
+ expose []string
+ }
+ tests := []struct {
+ name string
+ args args
+ want map[uint16]string
+ wantErr bool
+ }{
+ {
+ name: "single port",
+ args: args{
+ expose: []string{"99"},
+ },
+ want: single,
+ wantErr: false,
+ },
+ {
+ name: "simple range tcp",
+ args: args{
+ expose: []string{"99-100"},
+ },
+ want: simpleRange,
+ wantErr: false,
+ },
+ {
+ name: "simple range udp",
+ args: args{
+ expose: []string{"99-100/udp"},
+ },
+ want: simpleRangeUDP,
+ wantErr: false,
+ },
+ {
+ name: "range inverted should fail",
+ args: args{
+ expose: []string{"100-99"},
+ },
+ want: nil,
+ wantErr: true,
+ },
+ {
+ name: "specifying protocol twice should fail",
+ args: args{
+ expose: []string{"99/tcp-100/tcp"},
+ },
+ want: nil,
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := CreateExpose(tt.args.expose)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("CreateExpose() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("CreateExpose() got = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_parseAndValidatePort(t *testing.T) {
+ type args struct {
+ port string
+ }
+ tests := []struct {
+ name string
+ args args
+ want uint16
+ wantErr bool
+ }{
+ {
+ name: "0 should fail",
+ args: args{
+ port: "0",
+ },
+ want: 0,
+ wantErr: true,
+ },
+ {
+ name: "over 65535 should fail",
+ args: args{
+ port: "66666",
+ },
+ want: 0,
+ wantErr: true,
+ },
+ {
+ name: "",
+ args: args{
+ port: "99",
+ },
+ want: 99,
+ wantErr: false,
+ },
+ {
+ name: "negative values should fail",
+ args: args{
+ port: "-1",
+ },
+ want: 0,
+ wantErr: true,
+ },
+ {
+ name: "protocol should fail",
+ args: args{
+ port: "99/tcp",
+ },
+ want: 0,
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := parseAndValidatePort(tt.args.port)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("parseAndValidatePort() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if got != tt.want {
+ t.Errorf("parseAndValidatePort() got = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/pkg/specgenutil/volumes.go b/pkg/specgenutil/volumes.go
index 95ce420f8..50d745380 100644
--- a/pkg/specgenutil/volumes.go
+++ b/pkg/specgenutil/volumes.go
@@ -3,7 +3,7 @@ package specgenutil
import (
"encoding/csv"
"fmt"
- "path/filepath"
+ "path"
"strings"
"github.com/containers/common/pkg/parse"
@@ -123,7 +123,7 @@ func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bo
finalMounts := make([]spec.Mount, 0, len(unifiedMounts))
for _, mount := range unifiedMounts {
if mount.Type == define.TypeBind {
- absSrc, err := filepath.Abs(mount.Source)
+ absSrc, err := specgen.ConvertWinMountPath(mount.Source)
if err != nil {
return nil, nil, nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source)
}
@@ -334,7 +334,7 @@ func getBindMount(args []string) (spec.Mount, error) {
if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil {
return newMount, err
}
- newMount.Destination = filepath.Clean(kv[1])
+ newMount.Destination = unixPathClean(kv[1])
setDest = true
case "relabel":
if setRelabel {
@@ -456,7 +456,7 @@ func getTmpfsMount(args []string) (spec.Mount, error) {
if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil {
return newMount, err
}
- newMount.Destination = filepath.Clean(kv[1])
+ newMount.Destination = unixPathClean(kv[1])
setDest = true
case "U", "chown":
if setOwnership {
@@ -507,7 +507,7 @@ func getDevptsMount(args []string) (spec.Mount, error) {
if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil {
return newMount, err
}
- newMount.Destination = filepath.Clean(kv[1])
+ newMount.Destination = unixPathClean(kv[1])
setDest = true
default:
return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0])
@@ -572,7 +572,7 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) {
if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil {
return nil, err
}
- newVolume.Dest = filepath.Clean(kv[1])
+ newVolume.Dest = unixPathClean(kv[1])
setDest = true
case "U", "chown":
if setOwnership {
@@ -624,7 +624,7 @@ func getImageVolume(args []string) (*specgen.ImageVolume, error) {
if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil {
return nil, err
}
- newVolume.Destination = filepath.Clean(kv[1])
+ newVolume.Destination = unixPathClean(kv[1])
case "rw", "readwrite":
switch kv[1] {
case "true":
@@ -670,7 +670,7 @@ func getTmpfsMounts(tmpfsFlag []string) (map[string]spec.Mount, error) {
}
mount := spec.Mount{
- Destination: filepath.Clean(destPath),
+ Destination: unixPathClean(destPath),
Type: define.TypeTmpfs,
Options: options,
Source: define.TypeTmpfs,
@@ -700,3 +700,8 @@ func validChownFlag(flag string) (bool, error) {
return true, nil
}
+
+// Use path instead of filepath to preserve Unix style paths on Windows
+func unixPathClean(p string) string {
+ return path.Clean(p)
+}
diff --git a/pkg/specgenutil/volumes_test.go b/pkg/specgenutil/volumes_test.go
new file mode 100644
index 000000000..fc6caf83c
--- /dev/null
+++ b/pkg/specgenutil/volumes_test.go
@@ -0,0 +1,68 @@
+package specgenutil
+
+import "testing"
+
+func Test_validChownFlag(t *testing.T) {
+ type args struct {
+ flag string
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ wantErr bool
+ }{
+ {
+ name: "U true",
+ args: args{
+ flag: "U=true",
+ },
+ want: true,
+ wantErr: false,
+ },
+ {
+ name: "U true case doesnt matter",
+ args: args{
+ flag: "u=True",
+ },
+ want: true,
+ wantErr: false,
+ },
+ {
+ name: "U is false",
+ args: args{
+ flag: "U=false",
+ },
+ want: false,
+ wantErr: false,
+ },
+ {
+ name: "chown should also work",
+ args: args{
+ flag: "chown=true",
+ },
+ want: true,
+ wantErr: false,
+ },
+ {
+ name: "garbage value should fail",
+ args: args{
+ flag: "U=foobar",
+ },
+ want: false,
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := validChownFlag(tt.args.flag)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("validChownFlag() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if got != tt.want {
+ t.Errorf("validChownFlag() got = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}