220 lines
6.5 KiB
Go
220 lines
6.5 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"time"
|
||
|
|
||
|
"k8s.io/apimachinery/pkg/fields"
|
||
|
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||
|
|
||
|
"github.com/containers/storage"
|
||
|
"github.com/kubernetes-incubator/cri-o/cmd/kpod/docker"
|
||
|
"github.com/kubernetes-incubator/cri-o/oci"
|
||
|
"github.com/kubernetes-incubator/cri-o/pkg/annotations"
|
||
|
"github.com/kubernetes-incubator/cri-o/server"
|
||
|
"github.com/opencontainers/image-spec/specs-go/v1"
|
||
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||
|
"github.com/pkg/errors"
|
||
|
)
|
||
|
|
||
|
type containerData struct {
|
||
|
ID string
|
||
|
Name string
|
||
|
LogPath string
|
||
|
Labels fields.Set
|
||
|
Annotations fields.Set
|
||
|
State *oci.ContainerState
|
||
|
Metadata *pb.ContainerMetadata
|
||
|
BundlePath string
|
||
|
StopSignal string
|
||
|
Type string `json:"type"`
|
||
|
FromImage string `json:"image,omitempty"`
|
||
|
FromImageID string `json:"image-id"`
|
||
|
MountPoint string `json:"mountpoint,omitempty"`
|
||
|
MountLabel string
|
||
|
Mounts []specs.Mount
|
||
|
AppArmorProfile string
|
||
|
ImageAnnotations map[string]string `json:"annotations,omitempty"`
|
||
|
ImageCreatedBy string `json:"created-by,omitempty"`
|
||
|
OCIv1 v1.Image `json:"ociv1,omitempty"`
|
||
|
Docker docker.V2Image `json:"docker,omitempty"`
|
||
|
SizeRw uint `json:"SizeRw,omitempty"`
|
||
|
SizeRootFs uint `json:"SizeRootFs,omitempty"`
|
||
|
Args []string
|
||
|
ResolvConfPath string
|
||
|
HostnamePath string
|
||
|
HostsPath string
|
||
|
GraphDriver driverData
|
||
|
}
|
||
|
|
||
|
type driverData struct {
|
||
|
Name string
|
||
|
Data map[string]string
|
||
|
}
|
||
|
|
||
|
func getContainerData(store storage.Store, name string, size bool) (*containerData, error) {
|
||
|
ctr, err := inspectContainer(store, name)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrapf(err, "error reading build container %q", name)
|
||
|
}
|
||
|
cid, err := openContainer(store, name)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrapf(err, "error reading container image data")
|
||
|
}
|
||
|
config, err := store.FromContainerDirectory(ctr.ID(), "config.json")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
var m specs.Spec
|
||
|
if err = json.Unmarshal(config, &m); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
driverName, err := getDriverName(store)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
topLayer, err := getContainerTopLayerID(store, ctr.ID())
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
driverMetadata, err := getDriverMetadata(store, topLayer)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
data := &containerData{
|
||
|
ID: ctr.ID(),
|
||
|
Name: ctr.Name(),
|
||
|
LogPath: ctr.LogPath(),
|
||
|
Labels: ctr.Labels(),
|
||
|
Annotations: ctr.Annotations(),
|
||
|
State: ctr.State(),
|
||
|
Metadata: ctr.Metadata(),
|
||
|
BundlePath: ctr.BundlePath(),
|
||
|
StopSignal: ctr.GetStopSignal(),
|
||
|
Args: m.Process.Args,
|
||
|
Type: cid.Type,
|
||
|
FromImage: cid.FromImage,
|
||
|
FromImageID: cid.FromImageID,
|
||
|
MountPoint: cid.MountPoint,
|
||
|
ImageAnnotations: cid.ImageAnnotations,
|
||
|
ImageCreatedBy: cid.ImageCreatedBy,
|
||
|
OCIv1: cid.OCIv1,
|
||
|
Docker: cid.Docker,
|
||
|
GraphDriver: driverData{
|
||
|
Name: driverName,
|
||
|
Data: driverMetadata,
|
||
|
},
|
||
|
MountLabel: m.Linux.MountLabel,
|
||
|
Mounts: m.Mounts,
|
||
|
AppArmorProfile: m.Process.ApparmorProfile,
|
||
|
ResolvConfPath: "",
|
||
|
HostnamePath: "",
|
||
|
HostsPath: "",
|
||
|
}
|
||
|
|
||
|
if size {
|
||
|
sizeRootFs, err := getRootFsSize(store, data.ID)
|
||
|
if err != nil {
|
||
|
|
||
|
return nil, errors.Wrapf(err, "error reading size for container %q", name)
|
||
|
}
|
||
|
data.SizeRootFs = uint(sizeRootFs)
|
||
|
sizeRw, err := getContainerRwSize(store, data.ID)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrapf(err, "error reading RWSize for container %q", name)
|
||
|
}
|
||
|
data.SizeRw = uint(sizeRw)
|
||
|
}
|
||
|
|
||
|
return data, nil
|
||
|
}
|
||
|
|
||
|
// Get an oci.Container and update its status
|
||
|
func inspectContainer(store storage.Store, container string) (*oci.Container, error) {
|
||
|
ociCtr, err := getOCIContainer(store, container)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
// call oci.New() to get the runtime
|
||
|
runtime, err := getOCIRuntime(store, container)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
// call runtime.UpdateStatus()
|
||
|
err = runtime.UpdateStatus(ociCtr)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return ociCtr, nil
|
||
|
}
|
||
|
|
||
|
// get an oci.Container instance for a given container ID
|
||
|
func getOCIContainer(store storage.Store, container string) (*oci.Container, error) {
|
||
|
ctr, err := findContainer(store, container)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
config, err := store.FromContainerDirectory(ctr.ID, "config.json")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
var m specs.Spec
|
||
|
if err = json.Unmarshal(config, &m); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
labels := make(map[string]string)
|
||
|
err = json.Unmarshal([]byte(m.Annotations[annotations.Labels]), &labels)
|
||
|
if len(m.Annotations[annotations.Labels]) > 0 && err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
name := ctr.Names[0]
|
||
|
|
||
|
var metadata pb.ContainerMetadata
|
||
|
err = json.Unmarshal([]byte(m.Annotations[annotations.Metadata]), &metadata)
|
||
|
if len(m.Annotations[annotations.Metadata]) > 0 && err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
tty := isTrue(m.Annotations[annotations.TTY])
|
||
|
stdin := isTrue(m.Annotations[annotations.Stdin])
|
||
|
stdinOnce := isTrue(m.Annotations[annotations.StdinOnce])
|
||
|
|
||
|
containerPath, err := store.ContainerRunDirectory(ctr.ID)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
containerDir, err := store.ContainerDirectory(ctr.ID)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
img, _ := m.Annotations[annotations.Image]
|
||
|
|
||
|
kubeAnnotations := make(map[string]string)
|
||
|
err = json.Unmarshal([]byte(m.Annotations[annotations.Annotations]), &kubeAnnotations)
|
||
|
if len(m.Annotations[annotations.Annotations]) > 0 && err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
created := time.Time{}
|
||
|
if len(m.Annotations[annotations.Created]) > 0 {
|
||
|
created, err = time.Parse(time.RFC3339Nano, m.Annotations[annotations.Created])
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// create a new OCI Container. kpod currently doesn't deal with pod sandboxes, so the fields for netns, privileged, and trusted are left empty
|
||
|
return oci.NewContainer(ctr.ID, name, containerPath, m.Annotations[annotations.LogPath], nil, labels, kubeAnnotations, img, &metadata, ctr.ImageID, tty, stdin, stdinOnce, false, false, containerDir, created, m.Annotations["org.opencontainers.image.stopSignal"])
|
||
|
}
|
||
|
|
||
|
func getOCIRuntime(store storage.Store, container string) (*oci.Runtime, error) {
|
||
|
config := server.DefaultConfig()
|
||
|
return oci.New(config.Runtime, config.RuntimeUntrustedWorkload, config.DefaultWorkloadTrust, config.Conmon, config.ConmonEnv, config.CgroupManager)
|
||
|
}
|