Revamp Libpod state strings for Docker compat

Improve our compatibility with Docker by better handling the
state strings that we print in `podman ps`. Docker capitalizes
all states in `ps` (we do not) - fix this in our PS code. Also,
stop normalizing ContainerStateConfigured to the "Created" state,
and instead make it always be Created, with the existing Created
state becoming Initialized.

I didn't rename the actual states because I'm somewhat reticent
to make such a large change a day before we leave for break. It's
somewhat confusing that ContainerStateConfigured now returns
Created, but internally and externally we're still consistent.

[NO NEW TESTS NEEDED] existing tests should catch anything that
broke.

I also consider this a breaking change. I will flag appropriately
on Github.

Fixes RHBZ#2010432 and RHBZ#2032561

Signed-off-by: Matthew Heon <mheon@redhat.com>
This commit is contained in:
Matthew Heon 2021-12-22 09:35:00 -05:00
parent 8514ebd182
commit 141de86862
8 changed files with 24 additions and 18 deletions

View File

@ -358,13 +358,12 @@ func (l psReporter) State() string {
case "running": case "running":
t := units.HumanDuration(time.Since(time.Unix(l.StartedAt, 0))) t := units.HumanDuration(time.Since(time.Unix(l.StartedAt, 0)))
state = "Up " + t + " ago" state = "Up " + t + " ago"
case "configured":
state = "Created"
case "exited", "stopped": case "exited", "stopped":
t := units.HumanDuration(time.Since(time.Unix(l.ExitedAt, 0))) t := units.HumanDuration(time.Since(time.Unix(l.ExitedAt, 0)))
state = fmt.Sprintf("Exited (%d) %s ago", l.ExitCode, t) state = fmt.Sprintf("Exited (%d) %s ago", l.ExitCode, t)
default: default:
state = l.ListContainer.State // Need to capitalize the first letter to match Docker.
state = strings.Title(l.ListContainer.State)
} }
return state return state
} }

View File

@ -37,16 +37,23 @@ const (
ContainerStateStopping ContainerStatus = iota ContainerStateStopping ContainerStatus = iota
) )
// ContainerStatus returns a string representation for users // ContainerStatus returns a string representation for users of a container
// of a container state // state. All results should match Docker's versions (from `docker ps`) as
// closely as possible, given the different set of states we support.
func (t ContainerStatus) String() string { func (t ContainerStatus) String() string {
switch t { switch t {
case ContainerStateUnknown: case ContainerStateUnknown:
return "unknown" return "unknown"
case ContainerStateConfigured: case ContainerStateConfigured:
return "configured" // The naming here is confusing, but it's necessary for Docker
case ContainerStateCreated: // compatibility - their Created state is our Configured state.
return "created" return "created"
case ContainerStateCreated:
// Docker does not have an equivalent to this state, so give it
// a clear name. Most of the time this is a purely transitory
// state between Configured and Running so we don't expect to
// see it much anyways.
return "initialized"
case ContainerStateRunning: case ContainerStateRunning:
return "running" return "running"
case ContainerStateStopped: case ContainerStateStopped:

View File

@ -156,7 +156,7 @@ podman create -t -i --name myctr $IMAGE ls
# Check configuration before initializing # Check configuration before initializing
t GET libpod/containers/myctr/json 200 \ t GET libpod/containers/myctr/json 200 \
.Id~[0-9a-f]\\{64\\} \ .Id~[0-9a-f]\\{64\\} \
.State.Status="configured" \ .State.Status="created" \
.State.Pid=0 \ .State.Pid=0 \
.ResolvConfPath="" \ .ResolvConfPath="" \
.HostnamePath="" \ .HostnamePath="" \
@ -172,7 +172,7 @@ t POST libpod/containers/myctr/init 204
# Check configuration after initializing # Check configuration after initializing
t GET libpod/containers/myctr/json 200 \ t GET libpod/containers/myctr/json 200 \
.Id~[0-9a-f]\\{64\\} \ .Id~[0-9a-f]\\{64\\} \
.State.Status="created" \ .State.Status="initialized" \
.State.Pid~[0-9]\\{1\,8\\} \ .State.Pid~[0-9]\\{1\,8\\} \
.ResolvConfPath=$userdata_path/resolv.conf \ .ResolvConfPath=$userdata_path/resolv.conf \
.HostnamePath=$userdata_path/hostname \ .HostnamePath=$userdata_path/hostname \

View File

@ -57,7 +57,7 @@ var _ = Describe("Podman init", func() {
result.WaitWithDefaultTimeout() result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0)) Expect(result).Should(Exit(0))
conData := result.InspectContainerToJSON() conData := result.InspectContainerToJSON()
Expect(conData[0].State.Status).To(Equal("created")) Expect(conData[0].State.Status).To(Equal("initialized"))
}) })
It("podman init single container by name", func() { It("podman init single container by name", func() {
@ -72,7 +72,7 @@ var _ = Describe("Podman init", func() {
result.WaitWithDefaultTimeout() result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0)) Expect(result).Should(Exit(0))
conData := result.InspectContainerToJSON() conData := result.InspectContainerToJSON()
Expect(conData[0].State.Status).To(Equal("created")) Expect(conData[0].State.Status).To(Equal("initialized"))
}) })
It("podman init latest container", func() { It("podman init latest container", func() {
@ -87,7 +87,7 @@ var _ = Describe("Podman init", func() {
result.WaitWithDefaultTimeout() result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0)) Expect(result).Should(Exit(0))
conData := result.InspectContainerToJSON() conData := result.InspectContainerToJSON()
Expect(conData[0].State.Status).To(Equal("created")) Expect(conData[0].State.Status).To(Equal("initialized"))
}) })
It("podman init all three containers, one running", func() { It("podman init all three containers, one running", func() {
@ -107,12 +107,12 @@ var _ = Describe("Podman init", func() {
result.WaitWithDefaultTimeout() result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0)) Expect(result).Should(Exit(0))
conData := result.InspectContainerToJSON() conData := result.InspectContainerToJSON()
Expect(conData[0].State.Status).To(Equal("created")) Expect(conData[0].State.Status).To(Equal("initialized"))
result2 := podmanTest.Podman([]string{"inspect", "test2"}) result2 := podmanTest.Podman([]string{"inspect", "test2"})
result2.WaitWithDefaultTimeout() result2.WaitWithDefaultTimeout()
Expect(result2).Should(Exit(0)) Expect(result2).Should(Exit(0))
conData2 := result2.InspectContainerToJSON() conData2 := result2.InspectContainerToJSON()
Expect(conData2[0].State.Status).To(Equal("created")) Expect(conData2[0].State.Status).To(Equal("initialized"))
result3 := podmanTest.Podman([]string{"inspect", "test3"}) result3 := podmanTest.Podman([]string{"inspect", "test3"})
result3.WaitWithDefaultTimeout() result3.WaitWithDefaultTimeout()
Expect(result3).Should(Exit(0)) Expect(result3).Should(Exit(0))

View File

@ -16,7 +16,7 @@ var _ = Describe("Podman pod pause", func() {
podmanTest *PodmanTestIntegration podmanTest *PodmanTestIntegration
) )
pausedState := "paused" pausedState := "Paused"
BeforeEach(func() { BeforeEach(func() {
SkipIfRootlessCgroupsV1("Pause is not supported in cgroups v1") SkipIfRootlessCgroupsV1("Pause is not supported in cgroups v1")

View File

@ -110,7 +110,7 @@ EOF
run_podman ps --external run_podman ps --external
is "${#lines[@]}" "3" "podman ps -a --external sees buildah containers" is "${#lines[@]}" "3" "podman ps -a --external sees buildah containers"
is "${lines[1]}" \ is "${lines[1]}" \
"[0-9a-f]\{12\} \+$IMAGE *buildah .* seconds ago .* storage .* ${PODMAN_TEST_IMAGE_NAME}-working-container" \ "[0-9a-f]\{12\} \+$IMAGE *buildah .* seconds ago .* Storage .* ${PODMAN_TEST_IMAGE_NAME}-working-container" \
"podman ps --external" "podman ps --external"
# 'rm -a' should be a NOP # 'rm -a' should be a NOP

View File

@ -27,7 +27,7 @@ load helpers
is "$output" "paused" "podman inspect .State.Status" is "$output" "paused" "podman inspect .State.Status"
sleep 3 sleep 3
run_podman ps -a --format '{{.ID}} {{.Names}} {{.Status}}' run_podman ps -a --format '{{.ID}} {{.Names}} {{.Status}}'
is "$output" "${cid:0:12} $cname paused" "podman ps on paused container" is "$output" "${cid:0:12} $cname Paused" "podman ps on paused container"
run_podman unpause $cname run_podman unpause $cname
run_podman ps -a --format '{{.ID}} {{.Names}} {{.Status}}' run_podman ps -a --format '{{.ID}} {{.Names}} {{.Status}}'
is "$output" "${cid:0:12} $cname Up .*" "podman ps on resumed container" is "$output" "${cid:0:12} $cname Up .*" "podman ps on resumed container"

View File

@ -223,7 +223,7 @@ EOF
@test "inspect - all container status" { @test "inspect - all container status" {
tests=" tests="
running | running | 0 running | running | 0
created | configured | 0 created | created | 0
done | exited | 0 done | exited | 0
failed | exited | 17 failed | exited | 17
" "