Migrates:
- TestAPIErrorJSON
- TestContainerAPIInvalidPortSyntax
- TestContainerAPIRestartPolicyInvalidPolicyName
- TestContainerAPIRestartPolicyRetryMismatch
- TestContainerAPIRestartPolicyNegativeRetryCount
- TestContainerAPIRestartPolicyDefaultRetryCount
- TestCreateWithTooLowMemoryLimit
Co-authored-by: Sameer Gupta <sameergupta4873@gmail.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -644,105 +644,6 @@ func (s *DockerAPISuite) TestContainerAPIVerifyHeader(c *testing.T) {
|
| 644 | 644 |
_ = body.Close() |
| 645 | 645 |
} |
| 646 | 646 |
|
| 647 |
-// Issue 14230. daemon should return 500 for invalid port syntax |
|
| 648 |
-func (s *DockerAPISuite) TestContainerAPIInvalidPortSyntax(c *testing.T) {
|
|
| 649 |
- config := `{
|
|
| 650 |
- "Image": "busybox", |
|
| 651 |
- "HostConfig": {
|
|
| 652 |
- "NetworkMode": "default", |
|
| 653 |
- "PortBindings": {
|
|
| 654 |
- "19039;1230": [ |
|
| 655 |
- {}
|
|
| 656 |
- ] |
|
| 657 |
- } |
|
| 658 |
- } |
|
| 659 |
- }` |
|
| 660 |
- |
|
| 661 |
- res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) |
|
| 662 |
- assert.NilError(c, err) |
|
| 663 |
- assert.Equal(c, res.StatusCode, http.StatusBadRequest) |
|
| 664 |
- |
|
| 665 |
- b, err := request.ReadBody(body) |
|
| 666 |
- assert.NilError(c, err) |
|
| 667 |
- assert.Assert(c, is.Contains(string(b[:]), "invalid port")) |
|
| 668 |
-} |
|
| 669 |
- |
|
| 670 |
-func (s *DockerAPISuite) TestContainerAPIRestartPolicyInvalidPolicyName(c *testing.T) {
|
|
| 671 |
- config := `{
|
|
| 672 |
- "Image": "busybox", |
|
| 673 |
- "HostConfig": {
|
|
| 674 |
- "RestartPolicy": {
|
|
| 675 |
- "Name": "something", |
|
| 676 |
- "MaximumRetryCount": 0 |
|
| 677 |
- } |
|
| 678 |
- } |
|
| 679 |
- }` |
|
| 680 |
- |
|
| 681 |
- res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) |
|
| 682 |
- assert.NilError(c, err) |
|
| 683 |
- assert.Equal(c, res.StatusCode, http.StatusBadRequest) |
|
| 684 |
- |
|
| 685 |
- b, err := request.ReadBody(body) |
|
| 686 |
- assert.NilError(c, err) |
|
| 687 |
- assert.Assert(c, is.Contains(string(b[:]), "invalid restart policy")) |
|
| 688 |
-} |
|
| 689 |
- |
|
| 690 |
-func (s *DockerAPISuite) TestContainerAPIRestartPolicyRetryMismatch(c *testing.T) {
|
|
| 691 |
- config := `{
|
|
| 692 |
- "Image": "busybox", |
|
| 693 |
- "HostConfig": {
|
|
| 694 |
- "RestartPolicy": {
|
|
| 695 |
- "Name": "always", |
|
| 696 |
- "MaximumRetryCount": 2 |
|
| 697 |
- } |
|
| 698 |
- } |
|
| 699 |
- }` |
|
| 700 |
- |
|
| 701 |
- res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) |
|
| 702 |
- assert.NilError(c, err) |
|
| 703 |
- assert.Equal(c, res.StatusCode, http.StatusBadRequest) |
|
| 704 |
- |
|
| 705 |
- b, err := request.ReadBody(body) |
|
| 706 |
- assert.NilError(c, err) |
|
| 707 |
- assert.Assert(c, is.Contains(string(b[:]), "invalid restart policy: maximum retry count can only be used with 'on-failure'")) |
|
| 708 |
-} |
|
| 709 |
- |
|
| 710 |
-func (s *DockerAPISuite) TestContainerAPIRestartPolicyNegativeRetryCount(c *testing.T) {
|
|
| 711 |
- config := `{
|
|
| 712 |
- "Image": "busybox", |
|
| 713 |
- "HostConfig": {
|
|
| 714 |
- "RestartPolicy": {
|
|
| 715 |
- "Name": "on-failure", |
|
| 716 |
- "MaximumRetryCount": -2 |
|
| 717 |
- } |
|
| 718 |
- } |
|
| 719 |
- }` |
|
| 720 |
- |
|
| 721 |
- res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) |
|
| 722 |
- assert.NilError(c, err) |
|
| 723 |
- assert.Equal(c, res.StatusCode, http.StatusBadRequest) |
|
| 724 |
- |
|
| 725 |
- b, err := request.ReadBody(body) |
|
| 726 |
- assert.NilError(c, err) |
|
| 727 |
- assert.Assert(c, is.Contains(string(b[:]), "maximum retry count cannot be negative")) |
|
| 728 |
-} |
|
| 729 |
- |
|
| 730 |
-func (s *DockerAPISuite) TestContainerAPIRestartPolicyDefaultRetryCount(c *testing.T) {
|
|
| 731 |
- config := `{
|
|
| 732 |
- "Image": "busybox", |
|
| 733 |
- "HostConfig": {
|
|
| 734 |
- "RestartPolicy": {
|
|
| 735 |
- "Name": "on-failure", |
|
| 736 |
- "MaximumRetryCount": 0 |
|
| 737 |
- } |
|
| 738 |
- } |
|
| 739 |
- }` |
|
| 740 |
- |
|
| 741 |
- res, _, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) |
|
| 742 |
- assert.NilError(c, err) |
|
| 743 |
- assert.Equal(c, res.StatusCode, http.StatusCreated) |
|
| 744 |
-} |
|
| 745 |
- |
|
| 746 | 647 |
// Issue 7941 - test to make sure a "null" in JSON is just ignored. |
| 747 | 648 |
// W/o this fix a null in JSON would be parsed into a string var as "null" |
| 748 | 649 |
func (s *DockerAPISuite) TestContainerAPIPostCreateNull(c *testing.T) {
|
| ... | ... |
@@ -789,26 +690,6 @@ func (s *DockerAPISuite) TestContainerAPIPostCreateNull(c *testing.T) {
|
| 789 | 789 |
assert.Equal(c, outMemorySwap, "0") |
| 790 | 790 |
} |
| 791 | 791 |
|
| 792 |
-func (s *DockerAPISuite) TestCreateWithTooLowMemoryLimit(c *testing.T) {
|
|
| 793 |
- // TODO Windows: Port once memory is supported |
|
| 794 |
- testRequires(c, DaemonIsLinux) |
|
| 795 |
- config := `{
|
|
| 796 |
- "Image": "busybox", |
|
| 797 |
- "HostConfig": {
|
|
| 798 |
- "CpuShares": 100, |
|
| 799 |
- "Memory": 524287 |
|
| 800 |
- } |
|
| 801 |
- }` |
|
| 802 |
- |
|
| 803 |
- res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) |
|
| 804 |
- assert.NilError(c, err) |
|
| 805 |
- b, err2 := request.ReadBody(body) |
|
| 806 |
- assert.NilError(c, err2) |
|
| 807 |
- |
|
| 808 |
- assert.Equal(c, res.StatusCode, http.StatusBadRequest) |
|
| 809 |
- assert.Assert(c, is.Contains(string(b), "Minimum memory limit allowed is 6MB")) |
|
| 810 |
-} |
|
| 811 |
- |
|
| 812 | 792 |
func (s *DockerAPISuite) TestContainerAPIKill(c *testing.T) {
|
| 813 | 793 |
const name = "test-api-kill" |
| 814 | 794 |
runSleepingContainer(c, "-i", "--name", name) |
| ... | ... |
@@ -8,7 +8,6 @@ import ( |
| 8 | 8 |
"github.com/moby/moby/v2/internal/testutil" |
| 9 | 9 |
"github.com/moby/moby/v2/internal/testutil/request" |
| 10 | 10 |
"gotest.tools/v3/assert" |
| 11 |
- is "gotest.tools/v3/assert/cmp" |
|
| 12 | 11 |
) |
| 13 | 12 |
|
| 14 | 13 |
type DockerAPISuite struct {
|
| ... | ... |
@@ -40,13 +39,3 @@ func (s *DockerAPISuite) TestAPIGetEnabledCORS(c *testing.T) {
|
| 40 | 40 |
// assert.Equal(c, res.Header.Get("Access-Control-Allow-Origin"), "*")
|
| 41 | 41 |
// assert.Equal(c, res.Header.Get("Access-Control-Allow-Headers"), "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth")
|
| 42 | 42 |
} |
| 43 |
- |
|
| 44 |
-func (s *DockerAPISuite) TestAPIErrorJSON(c *testing.T) {
|
|
| 45 |
- httpResp, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.JSONBody(struct{}{}))
|
|
| 46 |
- assert.NilError(c, err) |
|
| 47 |
- assert.Equal(c, httpResp.StatusCode, http.StatusBadRequest) |
|
| 48 |
- assert.Assert(c, is.Contains(httpResp.Header.Get("Content-Type"), "application/json"))
|
|
| 49 |
- b, err := request.ReadBody(body) |
|
| 50 |
- assert.NilError(c, err) |
|
| 51 |
- assert.Check(c, is.Contains(getErrorMessage(c, b), "config cannot be empty")) |
|
| 52 |
-} |
| ... | ... |
@@ -4,6 +4,7 @@ import ( |
| 4 | 4 |
"bufio" |
| 5 | 5 |
"context" |
| 6 | 6 |
"fmt" |
| 7 |
+ "net/http" |
|
| 7 | 8 |
"strconv" |
| 8 | 9 |
"strings" |
| 9 | 10 |
"testing" |
| ... | ... |
@@ -11,6 +12,7 @@ import ( |
| 11 | 11 |
|
| 12 | 12 |
containerd "github.com/containerd/containerd/v2/client" |
| 13 | 13 |
cerrdefs "github.com/containerd/errdefs" |
| 14 |
+ "github.com/moby/moby/api/types/common" |
|
| 14 | 15 |
"github.com/moby/moby/api/types/container" |
| 15 | 16 |
"github.com/moby/moby/api/types/network" |
| 16 | 17 |
"github.com/moby/moby/api/types/versions" |
| ... | ... |
@@ -20,6 +22,7 @@ import ( |
| 20 | 20 |
testContainer "github.com/moby/moby/v2/integration/internal/container" |
| 21 | 21 |
net "github.com/moby/moby/v2/integration/internal/network" |
| 22 | 22 |
"github.com/moby/moby/v2/internal/testutil" |
| 23 |
+ "github.com/moby/moby/v2/internal/testutil/request" |
|
| 23 | 24 |
ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
| 24 | 25 |
"gotest.tools/v3/assert" |
| 25 | 26 |
is "gotest.tools/v3/assert/cmp" |
| ... | ... |
@@ -658,6 +661,79 @@ func TestCreateInvalidHostConfig(t *testing.T) {
|
| 658 | 658 |
} |
| 659 | 659 |
} |
| 660 | 660 |
|
| 661 |
+func TestCreateValidation(t *testing.T) {
|
|
| 662 |
+ tests := []struct {
|
|
| 663 |
+ name string |
|
| 664 |
+ body string |
|
| 665 |
+ skipOn string |
|
| 666 |
+ expStatus int |
|
| 667 |
+ expError string |
|
| 668 |
+ }{
|
|
| 669 |
+ {
|
|
| 670 |
+ name: "empty body", |
|
| 671 |
+ body: ``, |
|
| 672 |
+ expStatus: http.StatusBadRequest, |
|
| 673 |
+ expError: `invalid JSON: EOF`, // TODO(thaJeztah): this could use a nicer error message. |
|
| 674 |
+ }, |
|
| 675 |
+ {
|
|
| 676 |
+ name: "empty config", |
|
| 677 |
+ body: `{}`,
|
|
| 678 |
+ expStatus: http.StatusBadRequest, |
|
| 679 |
+ expError: `config cannot be empty in order to create a container`, |
|
| 680 |
+ }, |
|
| 681 |
+ {
|
|
| 682 |
+ name: "invalid port syntax", // issue https://github.com/moby/moby/issues/14230 for invalid port syntax |
|
| 683 |
+ body: `{"Image": "busybox", "HostConfig": {"NetworkMode": "default", "PortBindings": {"19039;1230": [{}]}}}`,
|
|
| 684 |
+ expStatus: http.StatusBadRequest, |
|
| 685 |
+ expError: `invalid JSON: invalid port '19039;1230': invalid syntax`, |
|
| 686 |
+ }, |
|
| 687 |
+ {
|
|
| 688 |
+ name: "invalid memory-limit: value too low", |
|
| 689 |
+ body: `{"Image": "busybox", "HostConfig": {"CpuShares": 100, "Memory": 524287}}`,
|
|
| 690 |
+ skipOn: "windows", // TODO Windows: Port once memory is supported |
|
| 691 |
+ expStatus: http.StatusBadRequest, |
|
| 692 |
+ expError: `Minimum memory limit allowed is 6MB`, |
|
| 693 |
+ }, |
|
| 694 |
+ {
|
|
| 695 |
+ name: "invalid restart policy name", |
|
| 696 |
+ body: `{"Image": "busybox", "HostConfig": {"RestartPolicy": {"Name": "something", "MaximumRetryCount": 0}}}`,
|
|
| 697 |
+ expStatus: http.StatusBadRequest, |
|
| 698 |
+ expError: `invalid restart policy: unknown policy 'something'`, |
|
| 699 |
+ }, |
|
| 700 |
+ {
|
|
| 701 |
+ name: "invalid restart policy: retry not allowed", |
|
| 702 |
+ body: `{"Image": "busybox", "HostConfig": {"RestartPolicy": {"Name": "always", "MaximumRetryCount": 2}}}`,
|
|
| 703 |
+ expStatus: http.StatusBadRequest, |
|
| 704 |
+ expError: `invalid restart policy: maximum retry count can only be used with 'on-failure'`, |
|
| 705 |
+ }, |
|
| 706 |
+ {
|
|
| 707 |
+ name: "invalid restart policy: retry negative", |
|
| 708 |
+ body: `{"Image": "busybox", "HostConfig": {"RestartPolicy": {"Name": "on-failure", "MaximumRetryCount": -2}}}`,
|
|
| 709 |
+ expStatus: http.StatusBadRequest, |
|
| 710 |
+ expError: `invalid restart policy: maximum retry count cannot be negative`, |
|
| 711 |
+ }, |
|
| 712 |
+ {
|
|
| 713 |
+ name: "restart policy: default retry count", |
|
| 714 |
+ body: `{"Image": "busybox", "HostConfig": {"RestartPolicy": {"Name": "on-failure", "MaximumRetryCount": 0}}}`,
|
|
| 715 |
+ expStatus: http.StatusCreated, |
|
| 716 |
+ }, |
|
| 717 |
+ } |
|
| 718 |
+ for _, tc := range tests {
|
|
| 719 |
+ t.Run(tc.name, func(t *testing.T) {
|
|
| 720 |
+ skip.If(t, testEnv.DaemonInfo.OSType == tc.skipOn) |
|
| 721 |
+ res, _, err := request.Post(testutil.GetContext(t), "/containers/create", request.RawString(tc.body), request.JSON) |
|
| 722 |
+ assert.NilError(t, err) |
|
| 723 |
+ assert.Equal(t, res.StatusCode, tc.expStatus) |
|
| 724 |
+ |
|
| 725 |
+ if tc.expError != "" {
|
|
| 726 |
+ var respErr common.ErrorResponse |
|
| 727 |
+ assert.NilError(t, request.ReadJSONResponse(res, &respErr)) |
|
| 728 |
+ assert.ErrorContains(t, respErr, tc.expError) |
|
| 729 |
+ } |
|
| 730 |
+ }) |
|
| 731 |
+ } |
|
| 732 |
+} |
|
| 733 |
+ |
|
| 661 | 734 |
func TestCreateWithMultipleEndpointSettings(t *testing.T) {
|
| 662 | 735 |
ctx := setupTest(t) |
| 663 | 736 |
|