Skip to content

Commit

Permalink
Merge pull request containerd#9124 from dmcgowan/cri-image-store-no-c…
Browse files Browse the repository at this point in the history
…lient

Update CRI image store to not use containerd client
  • Loading branch information
AkihiroSuda committed Sep 21, 2023
2 parents b101cad + 9e819fb commit 3ebe5d1
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 23 deletions.
3 changes: 2 additions & 1 deletion pkg/cri/sbserver/images/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
imagestore "github.com/containerd/containerd/pkg/cri/store/image"
snapshotstore "github.com/containerd/containerd/pkg/cri/store/snapshot"
"github.com/containerd/containerd/pkg/kmutex"
"github.com/containerd/containerd/platforms"
docker "github.com/distribution/reference"
imagedigest "github.com/opencontainers/go-digest"
)
Expand All @@ -52,7 +53,7 @@ func NewService(config criconfig.Config, imageFSPath string, client *containerd.
svc := CRIImageService{
config: config,
client: client,
imageStore: imagestore.NewStore(client),
imageStore: imagestore.NewStore(client.ImageService(), client.ContentStore(), platforms.Default()),
imageFSPath: imageFSPath,
snapshotStore: snapshotstore.NewStore(),
unpackDuplicationSuppressor: kmutex.New(),
Expand Down
3 changes: 2 additions & 1 deletion pkg/cri/sbserver/images/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
criconfig "github.com/containerd/containerd/pkg/cri/config"
imagestore "github.com/containerd/containerd/pkg/cri/store/image"
snapshotstore "github.com/containerd/containerd/pkg/cri/store/snapshot"
"github.com/containerd/containerd/platforms"
"github.com/stretchr/testify/assert"
)

Expand All @@ -42,7 +43,7 @@ func newTestCRIService() *CRIImageService {
return &CRIImageService{
config: testConfig,
imageFSPath: testImageFSPath,
imageStore: imagestore.NewStore(nil),
imageStore: imagestore.NewStore(nil, nil, platforms.Default()),
snapshotStore: snapshotstore.NewStore(),
}
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/cri/server/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/containerd/containerd/pkg/cri/nri"
"github.com/containerd/containerd/pkg/cri/streaming"
"github.com/containerd/containerd/pkg/kmutex"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
cni "github.com/containerd/go-cni"
"google.golang.org/grpc"
Expand Down Expand Up @@ -128,7 +129,7 @@ func NewCRIService(config criconfig.Config, client *containerd.Client, nri *nri.
os: osinterface.RealOS{},
sandboxStore: sandboxstore.NewStore(labels),
containerStore: containerstore.NewStore(labels),
imageStore: imagestore.NewStore(client),
imageStore: imagestore.NewStore(client.ImageService(), client.ContentStore(), platforms.Default()),
snapshotStore: snapshotstore.NewStore(),
sandboxNameIndex: registrar.NewRegistrar(),
containerNameIndex: registrar.NewRegistrar(),
Expand Down
3 changes: 2 additions & 1 deletion pkg/cri/server/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"testing"

"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/platforms"
"github.com/containerd/go-cni"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -45,7 +46,7 @@ func newTestCRIService() *criService {
imageFSPath: testImageFSPath,
os: ostesting.NewFakeOS(),
sandboxStore: sandboxstore.NewStore(labels),
imageStore: imagestore.NewStore(nil),
imageStore: imagestore.NewStore(nil, nil, platforms.Default()),
snapshotStore: snapshotstore.NewStore(),
sandboxNameIndex: registrar.NewRegistrar(),
containerStore: containerstore.NewStore(labels),
Expand Down
8 changes: 6 additions & 2 deletions pkg/cri/store/image/fake_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@

package image

import "fmt"
import (
"fmt"

"github.com/containerd/containerd/platforms"
)

// NewFakeStore returns an image store with predefined images.
// Update is not allowed for this fake store.
func NewFakeStore(images []Image) (*Store, error) {
s := NewStore(nil)
s := NewStore(nil, nil, platforms.Default())
for _, i := range images {
for _, ref := range i.References {
s.refCache[ref] = i.ID
Expand Down
62 changes: 45 additions & 17 deletions pkg/cri/store/image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,20 @@ package image

import (
"context"
"encoding/json"
"fmt"
"sync"

"github.com/containerd/containerd"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/images/usage"
"github.com/containerd/containerd/pkg/cri/labels"
"github.com/containerd/containerd/pkg/cri/util"
"github.com/containerd/containerd/platforms"
docker "github.com/distribution/reference"

"github.com/opencontainers/go-digest"
imagedigest "github.com/opencontainers/go-digest"
"github.com/opencontainers/go-digest/digestset"
imageidentity "github.com/opencontainers/image-spec/identity"
Expand All @@ -50,22 +55,39 @@ type Image struct {
Pinned bool
}

// InfoProvider provides both content and info about content
type InfoProvider interface {
content.Provider
Info(ctx context.Context, dgst digest.Digest) (content.Info, error)
}

// Store stores all images.
type Store struct {
lock sync.RWMutex
// refCache is a containerd image reference to image id cache.
refCache map[string]string
// client is the containerd client.
client *containerd.Client

// images is the local image store
images images.Store

// content provider
provider InfoProvider

// platform represents the currently supported platform for images
// TODO: Make this store multi-platform
platform platforms.MatchComparer

// store is the internal image store indexed by image id.
store *store
}

// NewStore creates an image store.
func NewStore(client *containerd.Client) *Store {
func NewStore(img images.Store, provider InfoProvider, platform platforms.MatchComparer) *Store {
return &Store{
refCache: make(map[string]string),
client: client,
images: img,
provider: provider,
platform: platform,
store: &store{
images: make(map[string]Image),
digestSet: digestset.NewSet(),
Expand All @@ -77,13 +99,15 @@ func NewStore(client *containerd.Client) *Store {
func (s *Store) Update(ctx context.Context, ref string) error {
s.lock.Lock()
defer s.lock.Unlock()
i, err := s.client.GetImage(ctx, ref)

i, err := s.images.Get(ctx, ref)
if err != nil && !errdefs.IsNotFound(err) {
return fmt.Errorf("get image from containerd: %w", err)
}

var img *Image
if err == nil {
img, err = getImage(ctx, i)
img, err = s.getImage(ctx, i)
if err != nil {
return fmt.Errorf("get image info from containerd: %w", err)
}
Expand Down Expand Up @@ -116,36 +140,40 @@ func (s *Store) update(ref string, img *Image) error {
return s.store.add(*img)
}

// getImage gets image information from containerd.
func getImage(ctx context.Context, i containerd.Image) (*Image, error) {
// Get image information.
diffIDs, err := i.RootFS(ctx)
// getImage gets image information from containerd for current platform.
func (s *Store) getImage(ctx context.Context, i images.Image) (*Image, error) {
diffIDs, err := i.RootFS(ctx, s.provider, s.platform)
if err != nil {
return nil, fmt.Errorf("get image diffIDs: %w", err)
}
chainID := imageidentity.ChainID(diffIDs)

size, err := i.Size(ctx)
size, err := usage.CalculateImageUsage(ctx, i, s.provider, usage.WithManifestLimit(s.platform, 1), usage.WithManifestUsage())
if err != nil {
return nil, fmt.Errorf("get image compressed resource size: %w", err)
}

desc, err := i.Config(ctx)
desc, err := i.Config(ctx, s.provider, s.platform)
if err != nil {
return nil, fmt.Errorf("get image config descriptor: %w", err)
}
id := desc.Digest.String()

spec, err := i.Spec(ctx)
blob, err := content.ReadBlob(ctx, s.provider, desc)
if err != nil {
return nil, fmt.Errorf("failed to get OCI image spec: %w", err)
return nil, fmt.Errorf("read image config from content store: %w", err)
}

var spec imagespec.Image
if err := json.Unmarshal(blob, &spec); err != nil {
return nil, fmt.Errorf("unmarshal image config %s: %w", blob, err)
}

pinned := i.Labels()[labels.PinnedImageLabelKey] == labels.PinnedImageLabelValue
pinned := i.Labels[labels.PinnedImageLabelKey] == labels.PinnedImageLabelValue

return &Image{
ID: id,
References: []string{i.Name()},
References: []string{i.Name},
ChainID: chainID.String(),
Size: size,
ImageSpec: spec,
Expand Down

0 comments on commit 3ebe5d1

Please sign in to comment.