Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 129 additions & 2 deletions pkg/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@ package container

import (
"context"
"encoding/json"
"fmt"
"path/filepath"
"strconv"
"strings"
"time"

"github.com/containers/libpod/v2/pkg/annotations"
"github.com/containers/storage/pkg/stringid"
"github.com/cri-o/cri-o/internal/lib"
"github.com/cri-o/cri-o/internal/lib/sandbox"
oci "github.com/cri-o/cri-o/internal/oci"
"github.com/cri-o/cri-o/internal/storage"
"github.com/cri-o/cri-o/utils"
rspec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -62,6 +72,19 @@ type Container interface {
// SelinuxLabel returns the container's SelinuxLabel
// it takes the sandbox's label, which it falls back upon
SelinuxLabel(string) ([]string, error)

// spec functions

// returns the spec
Spec() *generate.Generator

// SpecAddMount adds a mount to the container's spec
// it takes the rspec mount object
// if there is already a mount at the path specified, it removes it.
SpecAddMount(rspec.Mount)

// SpecAddAnnotations adds annotations to the spec.
SpecAddAnnotations(sandbox *sandbox.Sandbox, containerVolume []oci.ContainerVolume, mountPoint, configStopSignal string, imageResult *storage.ImageResult, isSystemd, systemdHasCollectMode bool) error
}

// container is the hidden default type behind the Container interface
Expand All @@ -72,13 +95,117 @@ type container struct {
id string
name string
privileged bool
spec generate.Generator
}

// New creates a new, empty Sandbox instance
func New(ctx context.Context) Container {
func New(ctx context.Context) (Container, error) {
spec, err := generate.New("linux")
if err != nil {
return nil, err
}
return &container{
ctx: ctx,
ctx: ctx,
spec: spec,
}, nil
}

// SpecAddMount adds a specified mount to the spec
func (c *container) SpecAddMount(r rspec.Mount) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we have two docstrings for SpecAddMount. I think one is enough

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Perhaps s/SpecAddMount/AddMount/?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's similar comments over other functions in the file, I think I we should either remove all of them or keep all of them.

c.spec.RemoveMount(r.Destination)
c.spec.AddMount(r)
}

// SpecAddAnnotation adds all annotations to the spec
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

func (c *container) SpecAddAnnotations(sb *sandbox.Sandbox, containerVolumes []oci.ContainerVolume, mountPoint, configStopSignal string, imageResult *storage.ImageResult, isSystemd, systemdHasCollectMode bool) (err error) {
// Copied from k8s.io/kubernetes/pkg/kubelet/kuberuntime/labels.go
const podTerminationGracePeriodLabel = "io.kubernetes.pod.terminationGracePeriod"

kubeAnnotations := c.Config().GetAnnotations()
created := time.Now()
labels := c.Config().GetLabels()

image, err := c.Image()
if err != nil {
return err
}
logPath, err := c.LogPath(sb.LogDir())
if err != nil {
return err
}
c.spec.AddAnnotation(annotations.Image, image)
c.spec.AddAnnotation(annotations.ImageName, imageResult.Name)
c.spec.AddAnnotation(annotations.ImageRef, imageResult.ID)
c.spec.AddAnnotation(annotations.Name, c.Name())
c.spec.AddAnnotation(annotations.ContainerID, c.ID())
c.spec.AddAnnotation(annotations.SandboxID, sb.ID())
c.spec.AddAnnotation(annotations.SandboxName, sb.Name())
c.spec.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer)
c.spec.AddAnnotation(annotations.LogPath, logPath)
c.spec.AddAnnotation(annotations.TTY, strconv.FormatBool(c.Config().Tty))
c.spec.AddAnnotation(annotations.Stdin, strconv.FormatBool(c.Config().Stdin))
c.spec.AddAnnotation(annotations.StdinOnce, strconv.FormatBool(c.Config().StdinOnce))
c.spec.AddAnnotation(annotations.ResolvPath, sb.ResolvPath())
c.spec.AddAnnotation(annotations.ContainerManager, lib.ContainerManagerCRIO)
c.spec.AddAnnotation(annotations.MountPoint, mountPoint)
c.spec.AddAnnotation(annotations.SeccompProfilePath, c.Config().GetLinux().GetSecurityContext().GetSeccompProfilePath())
c.spec.AddAnnotation(annotations.Created, created.Format(time.RFC3339Nano))

metadataJSON, err := json.Marshal(c.Config().GetMetadata())
if err != nil {
return err
}
c.spec.AddAnnotation(annotations.Metadata, string(metadataJSON))

labelsJSON, err := json.Marshal(labels)
if err != nil {
return err
}
c.spec.AddAnnotation(annotations.Labels, string(labelsJSON))

volumesJSON, err := json.Marshal(containerVolumes)
if err != nil {
return err
}
c.spec.AddAnnotation(annotations.Volumes, string(volumesJSON))

kubeAnnotationsJSON, err := json.Marshal(kubeAnnotations)
if err != nil {
return err
}
c.spec.AddAnnotation(annotations.Annotations, string(kubeAnnotationsJSON))

for k, v := range kubeAnnotations {
c.spec.AddAnnotation(k, v)
}
for k, v := range labels {
c.spec.AddAnnotation(k, v)
}
for idx, ip := range sb.IPs() {
c.spec.AddAnnotation(fmt.Sprintf("%s.%d", annotations.IP, idx), ip)
}

if isSystemd {
if t, ok := kubeAnnotations[podTerminationGracePeriodLabel]; ok {
// currently only supported by systemd, see
// https://github.com/opencontainers/runc/pull/2224
c.spec.AddAnnotation("org.systemd.property.TimeoutStopUSec", "uint64 "+t+"000000") // sec to usec
}
if systemdHasCollectMode {
c.spec.AddAnnotation("org.systemd.property.CollectMode", "'inactive-or-failed'")
}
}

if configStopSignal != "" {
// this key is defined in image-spec conversion document at https://github.com/opencontainers/image-spec/pull/492/files#diff-8aafbe2c3690162540381b8cdb157112R57
c.spec.AddAnnotation("org.opencontainers.image.stopSignal", configStopSignal)
}

return nil
}

func (c *container) Spec() *generate.Generator {
return &c.spec
}

// SetConfig sets the configuration to the container and validates it
Expand Down
6 changes: 5 additions & 1 deletion pkg/container/container_setnameandid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,13 @@ var _ = t.Describe("Container:SetNameAndID", func() {
It("should fail with config nil", func() {
// Given
// When
err := container.New(context.Background()).SetNameAndID()
container, err := container.New(context.Background())
Expect(err).To(BeNil())

err = container.SetNameAndID()

// Then
Expect(container).ToNot(BeNil())
Expect(err).NotTo(BeNil())
})
})
Expand Down
121 changes: 121 additions & 0 deletions pkg/container/container_test.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,141 @@
package container_test

import (
"encoding/json"
"strconv"
"time"

"github.com/containers/libpod/v2/pkg/annotations"
"github.com/cri-o/cri-o/internal/lib"
"github.com/cri-o/cri-o/internal/lib/sandbox"
oci "github.com/cri-o/cri-o/internal/oci"
"github.com/cri-o/cri-o/internal/storage"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
rspec "github.com/opencontainers/runtime-spec/specs-go"
pb "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
"k8s.io/kubernetes/pkg/kubelet/dockershim/network/hostport"
)

var _ = t.Describe("Container", func() {
var config *pb.ContainerConfig
var sboxConfig *pb.PodSandboxConfig
const defaultMounts = 6
BeforeEach(func() {
config = &pb.ContainerConfig{
Metadata: &pb.ContainerMetadata{Name: "name"},
}
sboxConfig = &pb.PodSandboxConfig{}
})
t.Describe("SpecAddMount", func() {
It("should add the mount to the spec", func() {
sut.SpecAddMount(rspec.Mount{
Destination: "test",
Type: "test",
Source: "test",
Options: []string{"test"},
})
Expect(len(sut.Spec().Mounts())).To(Equal(defaultMounts + 1))
})
It("should add only one copy to the spec", func() {
sut.SpecAddMount(rspec.Mount{
Destination: "test",
Type: "test",
Source: "test",
Options: []string{"test"},
})
sut.SpecAddMount(rspec.Mount{
Destination: "test",
Type: "test",
Source: "test",
Options: []string{"test"},
})
Expect(len(sut.Spec().Mounts())).To(Equal(defaultMounts + 1))
})
})
t.Describe("Spec", func() {
It("should return the spec", func() {
Expect(sut.Spec()).ToNot(Equal(nil))
})
})
t.Describe("SpecAddAnnotations", func() {
It("should set the spec annotations", func() {
// Given
sandboxConfig := &pb.PodSandboxConfig{
Metadata: &pb.PodSandboxMetadata{Name: "name"},
}
containerConfig := &pb.ContainerConfig{
Metadata: &pb.ContainerMetadata{Name: "name"},
Linux: &pb.LinuxContainerConfig{
SecurityContext: &pb.LinuxContainerSecurityContext{
Privileged: true,
},
},
Image: &pb.ImageSpec{
Image: "img",
},
}
err := sut.SetConfig(containerConfig, sandboxConfig)
Expect(err).To(BeNil())
currentTime := time.Now()
volumes := []oci.ContainerVolume{}
imageResult := storage.ImageResult{}
mountPoint := "test"
configStopSignal := "test"

sb, err := sandbox.New("sandboxID", "", "", "", "test",
make(map[string]string), make(map[string]string), "", "",
&pb.PodSandboxMetadata{}, "", "", false, "", "", "",
[]*hostport.PortMapping{}, false, currentTime, "")
Expect(err).To(BeNil())

image, err := sut.Image()
Expect(err).To(BeNil())

logpath, err := sut.LogPath(sb.LogDir())
Expect(err).To(BeNil())

metadataJSON, err := json.Marshal(sut.Config().GetMetadata())
Expect(err).To(BeNil())

labelsJSON, err := json.Marshal(sut.Config().GetLabels())
Expect(err).To(BeNil())

volumesJSON, err := json.Marshal(volumes)
Expect(err).To(BeNil())

kubeAnnotationsJSON, err := json.Marshal(sut.Config().GetAnnotations())
Expect(err).To(BeNil())

Expect(currentTime).ToNot(BeNil())
Expect(sb).ToNot(BeNil())

err = sut.SpecAddAnnotations(sb, volumes, mountPoint, configStopSignal, &imageResult, false, false)
Expect(err).To(BeNil())

Expect(sut.Spec().Config.Annotations[annotations.Image]).To(Equal(image))
Expect(sut.Spec().Config.Annotations[annotations.ImageName]).To(Equal(imageResult.Name))
Expect(sut.Spec().Config.Annotations[annotations.ImageRef]).To(Equal(imageResult.ID))
Expect(sut.Spec().Config.Annotations[annotations.Name]).To(Equal(sut.Name()))
Expect(sut.Spec().Config.Annotations[annotations.ContainerID]).To(Equal(sut.ID()))
Expect(sut.Spec().Config.Annotations[annotations.SandboxID]).To(Equal(sb.ID()))
Expect(sut.Spec().Config.Annotations[annotations.SandboxName]).To(Equal(sb.Name()))
Expect(sut.Spec().Config.Annotations[annotations.ContainerType]).To(Equal(annotations.ContainerTypeContainer))
Expect(sut.Spec().Config.Annotations[annotations.LogPath]).To(Equal(logpath))
Expect(sut.Spec().Config.Annotations[annotations.TTY]).To(Equal(strconv.FormatBool(sut.Config().Tty)))
Expect(sut.Spec().Config.Annotations[annotations.Stdin]).To(Equal(strconv.FormatBool(sut.Config().Stdin)))
Expect(sut.Spec().Config.Annotations[annotations.StdinOnce]).To(Equal(strconv.FormatBool(sut.Config().StdinOnce)))
Expect(sut.Spec().Config.Annotations[annotations.ResolvPath]).To(Equal(sb.ResolvPath()))
Expect(sut.Spec().Config.Annotations[annotations.ContainerManager]).To(Equal(lib.ContainerManagerCRIO))
Expect(sut.Spec().Config.Annotations[annotations.MountPoint]).To(Equal(mountPoint))
Expect(sut.Spec().Config.Annotations[annotations.SeccompProfilePath]).To(Equal(sut.Config().GetLinux().GetSecurityContext().GetSeccompProfilePath()))
Expect(sut.Spec().Config.Annotations[annotations.Created]).ToNot(BeNil())
Expect(sut.Spec().Config.Annotations[annotations.Metadata]).To(Equal(string(metadataJSON)))
Expect(sut.Spec().Config.Annotations[annotations.Labels]).To(Equal(string(labelsJSON)))
Expect(sut.Spec().Config.Annotations[annotations.Volumes]).To(Equal(string(volumesJSON)))
Expect(sut.Spec().Config.Annotations[annotations.Annotations]).To(Equal(string(kubeAnnotationsJSON)))
})
})
t.Describe("FipsDisable", func() {
It("should be true when set to true", func() {
// Given
Expand Down
4 changes: 3 additions & 1 deletion pkg/container/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,7 @@ var _ = AfterSuite(func() {
})

var _ = BeforeEach(func() {
sut = container.New(context.Background())
var err error
sut, err = container.New(context.Background())
Expect(err).To(BeNil())
})
6 changes: 5 additions & 1 deletion server/container_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,11 @@ func (s *Server) CreateContainer(ctx context.Context, req *pb.CreateContainerReq
return nil, fmt.Errorf("CreateContainer failed as the sandbox was stopped: %v", sbID)
}

ctr := container.New(ctx)
ctr, err := container.New(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to create container")
}

if err := ctr.SetConfig(req.GetConfig(), req.GetSandboxConfig()); err != nil {
return nil, errors.Wrap(err, "setting container config")
}
Expand Down
Loading