96fb47213e
We had a bug in ImageStatus where we weren't returning the default image user if set, thus running all containers as root despite a user being set in the image config. We weren't populating the Username field of ImageStatus. This patch fixes that along with the handling of multiple images based on the registry patch for multiple images. It also fixes ListImages to return Username as well. Signed-off-by: Antonio Murdaca <runcom@redhat.com>
100 lines
2.6 KiB
Go
100 lines
2.6 KiB
Go
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/containers/storage"
|
|
pkgstorage "github.com/kubernetes-incubator/cri-o/pkg/storage"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
"golang.org/x/net/context"
|
|
pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
|
)
|
|
|
|
// ImageStatus returns the status of the image.
|
|
func (s *Server) ImageStatus(ctx context.Context, req *pb.ImageStatusRequest) (resp *pb.ImageStatusResponse, err error) {
|
|
const operation = "image_status"
|
|
defer func() {
|
|
recordOperation(operation, time.Now())
|
|
recordError(operation, err)
|
|
}()
|
|
|
|
logrus.Debugf("ImageStatusRequest: %+v", req)
|
|
image := ""
|
|
img := req.GetImage()
|
|
if img != nil {
|
|
image = img.Image
|
|
}
|
|
if image == "" {
|
|
return nil, fmt.Errorf("no image specified")
|
|
}
|
|
images, err := s.StorageImageServer().ResolveNames(image)
|
|
if err != nil {
|
|
if err == pkgstorage.ErrCannotParseImageID {
|
|
images = append(images, image)
|
|
} else {
|
|
return nil, err
|
|
}
|
|
}
|
|
var (
|
|
notfound bool
|
|
lastErr error
|
|
)
|
|
for _, image := range images {
|
|
status, err := s.StorageImageServer().ImageStatus(s.ImageContext(), image)
|
|
if err != nil {
|
|
if errors.Cause(err) == storage.ErrImageUnknown {
|
|
logrus.Warnf("imageStatus: can't find %s", image)
|
|
notfound = true
|
|
continue
|
|
}
|
|
logrus.Warnf("imageStatus: error getting status from %s: %v", image, err)
|
|
lastErr = err
|
|
continue
|
|
}
|
|
resp = &pb.ImageStatusResponse{
|
|
Image: &pb.Image{
|
|
Id: status.ID,
|
|
RepoTags: status.RepoTags,
|
|
RepoDigests: status.RepoDigests,
|
|
Size_: *status.Size,
|
|
},
|
|
}
|
|
uid, username := getUserFromImage(status.User)
|
|
if uid != nil {
|
|
resp.Image.Uid = &pb.Int64Value{Value: *uid}
|
|
}
|
|
resp.Image.Username = username
|
|
break
|
|
}
|
|
if lastErr != nil && resp == nil {
|
|
return nil, lastErr
|
|
}
|
|
if notfound && resp == nil {
|
|
return &pb.ImageStatusResponse{}, nil
|
|
}
|
|
logrus.Debugf("ImageStatusResponse: %+v", resp)
|
|
return resp, nil
|
|
}
|
|
|
|
// getUserFromImage gets uid or user name of the image user.
|
|
// If user is numeric, it will be treated as uid; or else, it is treated as user name.
|
|
func getUserFromImage(user string) (*int64, string) {
|
|
// return both empty if user is not specified in the image.
|
|
if user == "" {
|
|
return nil, ""
|
|
}
|
|
// split instances where the id may contain user:group
|
|
user = strings.Split(user, ":")[0]
|
|
// user could be either uid or user name. Try to interpret as numeric uid.
|
|
uid, err := strconv.ParseInt(user, 10, 64)
|
|
if err != nil {
|
|
// If user is non numeric, assume it's user name.
|
|
return nil, user
|
|
}
|
|
// If user is a numeric uid.
|
|
return &uid, ""
|
|
}
|