github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/container_inspect_linux_test.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "fmt" 21 "strings" 22 "testing" 23 24 "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" 25 "github.com/containerd/nerdctl/pkg/testutil" 26 "github.com/docker/go-connections/nat" 27 "gotest.tools/v3/assert" 28 ) 29 30 func TestContainerInspectContainsPortConfig(t *testing.T) { 31 testContainer := testutil.Identifier(t) 32 33 base := testutil.NewBase(t) 34 defer base.Cmd("rm", "-f", testContainer).Run() 35 36 base.Cmd("run", "-d", "--name", testContainer, "-p", "8080:80", testutil.NginxAlpineImage).AssertOK() 37 inspect := base.InspectContainer(testContainer) 38 inspect80TCP := (*inspect.NetworkSettings.Ports)["80/tcp"] 39 expected := nat.PortBinding{ 40 HostIP: "0.0.0.0", 41 HostPort: "8080", 42 } 43 assert.Equal(base.T, expected, inspect80TCP[0]) 44 } 45 46 func TestContainerInspectContainsMounts(t *testing.T) { 47 testContainer := testutil.Identifier(t) 48 49 base := testutil.NewBase(t) 50 51 testVolume := testutil.Identifier(t) 52 53 defer base.Cmd("volume", "rm", "-f", testVolume).Run() 54 base.Cmd("volume", "create", "--label", "tag=testVolume", testVolume).AssertOK() 55 inspectVolume := base.InspectVolume(testVolume) 56 namedVolumeSource := inspectVolume.Mountpoint 57 58 defer base.Cmd("rm", "-f", testContainer).Run() 59 base.Cmd("run", "-d", "--privileged", 60 "--name", testContainer, 61 "--network", "none", 62 "-v", "/anony-vol", 63 "--tmpfs", "/app1:size=64m", 64 "--mount", "type=bind,src=/tmp,dst=/app2,ro", 65 "--mount", fmt.Sprintf("type=volume,src=%s,dst=/app3,readonly=false", testVolume), 66 testutil.NginxAlpineImage).AssertOK() 67 68 inspect := base.InspectContainer(testContainer) 69 70 // convert array to map to get by key of Destination 71 actual := make(map[string]dockercompat.MountPoint) 72 for i := range inspect.Mounts { 73 actual[inspect.Mounts[i].Destination] = inspect.Mounts[i] 74 } 75 76 const localDriver = "local" 77 78 expected := []struct { 79 dest string 80 mountPoint dockercompat.MountPoint 81 }{ 82 // anonymous volume 83 { 84 dest: "/anony-vol", 85 mountPoint: dockercompat.MountPoint{ 86 Type: "volume", 87 Name: "", 88 Source: "", // source of anonymous volume is a generated path, so here will not check it. 89 Destination: "/anony-vol", 90 Driver: localDriver, 91 RW: true, 92 }, 93 }, 94 95 // bind 96 { 97 dest: "/app2", 98 mountPoint: dockercompat.MountPoint{ 99 Type: "bind", 100 Name: "", 101 Source: "/tmp", 102 Destination: "/app2", 103 Driver: "", 104 RW: false, 105 }, 106 }, 107 108 // named volume 109 { 110 dest: "/app3", 111 mountPoint: dockercompat.MountPoint{ 112 Type: "volume", 113 Name: testVolume, 114 Source: namedVolumeSource, 115 Destination: "/app3", 116 Driver: localDriver, 117 RW: true, 118 }, 119 }, 120 } 121 122 for i := range expected { 123 testCase := expected[i] 124 t.Logf("test volume[dest=%q]", testCase.dest) 125 126 mountPoint, ok := actual[testCase.dest] 127 assert.Assert(base.T, ok) 128 129 assert.Equal(base.T, testCase.mountPoint.Type, mountPoint.Type) 130 assert.Equal(base.T, testCase.mountPoint.Driver, mountPoint.Driver) 131 assert.Equal(base.T, testCase.mountPoint.RW, mountPoint.RW) 132 assert.Equal(base.T, testCase.mountPoint.Destination, mountPoint.Destination) 133 134 if testCase.mountPoint.Source != "" { 135 assert.Equal(base.T, testCase.mountPoint.Source, mountPoint.Source) 136 } 137 if testCase.mountPoint.Name != "" { 138 assert.Equal(base.T, testCase.mountPoint.Name, mountPoint.Name) 139 } 140 } 141 } 142 143 func TestContainerInspectContainsLabel(t *testing.T) { 144 t.Parallel() 145 testContainer := testutil.Identifier(t) 146 147 base := testutil.NewBase(t) 148 defer base.Cmd("rm", "-f", testContainer).Run() 149 150 base.Cmd("run", "-d", "--name", testContainer, "--label", "foo=foo", "--label", "bar=bar", testutil.NginxAlpineImage).AssertOK() 151 base.EnsureContainerStarted(testContainer) 152 inspect := base.InspectContainer(testContainer) 153 lbs := inspect.Config.Labels 154 155 assert.Equal(base.T, "foo", lbs["foo"]) 156 assert.Equal(base.T, "bar", lbs["bar"]) 157 } 158 159 func TestContainerInspectState(t *testing.T) { 160 t.Parallel() 161 testContainer := testutil.Identifier(t) 162 base := testutil.NewBase(t) 163 164 type testCase struct { 165 name, containerName, cmd string 166 want dockercompat.ContainerState 167 } 168 // nerdctl: run error produces a nil Task, so the Status is empty because Status comes from Task. 169 // docker : run error gives => `Status=created` as in docker there is no a separation between container and Task. 170 errStatus := "" 171 if base.Target == testutil.Docker { 172 errStatus = "created" 173 } 174 testCases := []testCase{ 175 { 176 name: "inspect State with error", 177 containerName: fmt.Sprintf("%s-fail", testContainer), 178 cmd: "aa", 179 want: dockercompat.ContainerState{ 180 Error: "executable file not found in $PATH", 181 Status: errStatus, 182 }, 183 }, 184 { 185 name: "inspect State without error", 186 containerName: fmt.Sprintf("%s-success", testContainer), 187 cmd: "ls", 188 want: dockercompat.ContainerState{ 189 Error: "", 190 Status: "exited", 191 }, 192 }, 193 } 194 195 for _, tc := range testCases { 196 tc := tc 197 t.Run(tc.name, func(t *testing.T) { 198 defer base.Cmd("rm", "-f", tc.containerName).Run() 199 if tc.want.Error != "" { 200 base.Cmd("run", "--name", tc.containerName, testutil.AlpineImage, tc.cmd).AssertFail() 201 } else { 202 base.Cmd("run", "--name", tc.containerName, testutil.AlpineImage, tc.cmd).AssertOK() 203 } 204 inspect := base.InspectContainer(tc.containerName) 205 assert.Assert(t, strings.Contains(inspect.State.Error, tc.want.Error), fmt.Sprintf("expected: %s, actual: %s", tc.want.Error, inspect.State.Error)) 206 assert.Equal(base.T, inspect.State.Status, tc.want.Status) 207 }) 208 } 209 210 }