22d055869d
If we create a container using the image ID like
771cd5947d5ea4bf8e8f4900dd357dbb67e7b16486c270f8274087d182d457c6, then
a call to container_status will return that same ID for the "Image"
field in ContainerStatusResponse.
This patch matches dockershim behavior and return the first tagged name
if available from the image store.
This is also needed to fix a failure in k8s e2d tests.
Reference:
https://github.com/kubernetes/kubernetes/pull/39298/files#diff-c7dd39479fd733354254e70845075db5R369
Reference:
67a5bf8454/test/e2e/framework/util.go (L1941)
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
138 lines
3.4 KiB
Go
138 lines
3.4 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/docker/distribution/reference"
|
|
"github.com/kubernetes-incubator/cri-o/oci"
|
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
|
"golang.org/x/net/context"
|
|
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
|
)
|
|
|
|
// ContainerStatus returns status of the container.
|
|
func (s *Server) ContainerStatus(ctx context.Context, req *pb.ContainerStatusRequest) (*pb.ContainerStatusResponse, error) {
|
|
logrus.Debugf("ContainerStatusRequest %+v", req)
|
|
c, err := s.getContainerFromRequest(req.ContainerId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err = s.runtime.UpdateStatus(c); err != nil {
|
|
return nil, err
|
|
}
|
|
s.containerStateToDisk(c)
|
|
|
|
containerID := c.ID()
|
|
resp := &pb.ContainerStatusResponse{
|
|
Status: &pb.ContainerStatus{
|
|
Id: containerID,
|
|
Metadata: c.Metadata(),
|
|
Labels: c.Labels(),
|
|
Annotations: c.Annotations(),
|
|
},
|
|
}
|
|
|
|
mounts, err := s.getMounts(containerID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
resp.Status.Mounts = mounts
|
|
|
|
imageName := c.Image().Image
|
|
status, err := s.storageImageServer.ImageStatus(s.imageContext, imageName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO: use status.ID only if no digested names!!!
|
|
// need to modify ImageStatus to split tagged and digested!
|
|
resp.Status.ImageRef = status.ID
|
|
|
|
for _, n := range status.Names {
|
|
r, err := reference.ParseNormalizedNamed(n)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to normalize image name for Image: %v", err)
|
|
}
|
|
if tagged, isTagged := r.(reference.Tagged); isTagged {
|
|
imageName = reference.FamiliarString(tagged)
|
|
break
|
|
}
|
|
}
|
|
resp.Status.Image = &pb.ImageSpec{Image: imageName}
|
|
|
|
cState := s.runtime.ContainerStatus(c)
|
|
rStatus := pb.ContainerState_CONTAINER_UNKNOWN
|
|
|
|
switch cState.Status {
|
|
case oci.ContainerStateCreated:
|
|
rStatus = pb.ContainerState_CONTAINER_CREATED
|
|
created := cState.Created.UnixNano()
|
|
resp.Status.CreatedAt = created
|
|
case oci.ContainerStateRunning:
|
|
rStatus = pb.ContainerState_CONTAINER_RUNNING
|
|
created := cState.Created.UnixNano()
|
|
resp.Status.CreatedAt = created
|
|
started := cState.Started.UnixNano()
|
|
resp.Status.StartedAt = started
|
|
case oci.ContainerStateStopped:
|
|
rStatus = pb.ContainerState_CONTAINER_EXITED
|
|
created := cState.Created.UnixNano()
|
|
resp.Status.CreatedAt = created
|
|
started := cState.Started.UnixNano()
|
|
resp.Status.StartedAt = started
|
|
finished := cState.Finished.UnixNano()
|
|
resp.Status.FinishedAt = finished
|
|
resp.Status.ExitCode = cState.ExitCode
|
|
}
|
|
|
|
resp.Status.State = rStatus
|
|
|
|
logrus.Debugf("ContainerStatusResponse: %+v", resp)
|
|
return resp, nil
|
|
}
|
|
|
|
func (s *Server) getMounts(id string) ([]*pb.Mount, error) {
|
|
config, err := s.store.FromContainerDirectory(id, "config.json")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var m rspec.Spec
|
|
if err = json.Unmarshal(config, &m); err != nil {
|
|
return nil, err
|
|
}
|
|
isRO := func(m rspec.Mount) bool {
|
|
var ro bool
|
|
for _, o := range m.Options {
|
|
if o == "ro" {
|
|
ro = true
|
|
break
|
|
}
|
|
}
|
|
return ro
|
|
}
|
|
isBind := func(m rspec.Mount) bool {
|
|
var bind bool
|
|
for _, o := range m.Options {
|
|
if o == "bind" || o == "rbind" {
|
|
bind = true
|
|
break
|
|
}
|
|
}
|
|
return bind
|
|
}
|
|
mounts := []*pb.Mount{}
|
|
for _, b := range m.Mounts {
|
|
if !isBind(b) {
|
|
continue
|
|
}
|
|
mounts = append(mounts, &pb.Mount{
|
|
ContainerPath: b.Destination,
|
|
HostPath: b.Source,
|
|
Readonly: isRO(b),
|
|
})
|
|
}
|
|
return mounts, nil
|
|
}
|