Merge pull request #9124 from dmcgowan/cri-image-store-no-client
Update CRI image store to not use containerd client
This commit is contained in:
commit
3ebe5d1c56
@ -27,6 +27,7 @@ import (
|
|||||||
imagestore "github.com/containerd/containerd/pkg/cri/store/image"
|
imagestore "github.com/containerd/containerd/pkg/cri/store/image"
|
||||||
snapshotstore "github.com/containerd/containerd/pkg/cri/store/snapshot"
|
snapshotstore "github.com/containerd/containerd/pkg/cri/store/snapshot"
|
||||||
"github.com/containerd/containerd/pkg/kmutex"
|
"github.com/containerd/containerd/pkg/kmutex"
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
docker "github.com/distribution/reference"
|
docker "github.com/distribution/reference"
|
||||||
imagedigest "github.com/opencontainers/go-digest"
|
imagedigest "github.com/opencontainers/go-digest"
|
||||||
)
|
)
|
||||||
@ -52,7 +53,7 @@ func NewService(config criconfig.Config, imageFSPath string, client *containerd.
|
|||||||
svc := CRIImageService{
|
svc := CRIImageService{
|
||||||
config: config,
|
config: config,
|
||||||
client: client,
|
client: client,
|
||||||
imageStore: imagestore.NewStore(client),
|
imageStore: imagestore.NewStore(client.ImageService(), client.ContentStore(), platforms.Default()),
|
||||||
imageFSPath: imageFSPath,
|
imageFSPath: imageFSPath,
|
||||||
snapshotStore: snapshotstore.NewStore(),
|
snapshotStore: snapshotstore.NewStore(),
|
||||||
unpackDuplicationSuppressor: kmutex.New(),
|
unpackDuplicationSuppressor: kmutex.New(),
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
criconfig "github.com/containerd/containerd/pkg/cri/config"
|
criconfig "github.com/containerd/containerd/pkg/cri/config"
|
||||||
imagestore "github.com/containerd/containerd/pkg/cri/store/image"
|
imagestore "github.com/containerd/containerd/pkg/cri/store/image"
|
||||||
snapshotstore "github.com/containerd/containerd/pkg/cri/store/snapshot"
|
snapshotstore "github.com/containerd/containerd/pkg/cri/store/snapshot"
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ func newTestCRIService() *CRIImageService {
|
|||||||
return &CRIImageService{
|
return &CRIImageService{
|
||||||
config: testConfig,
|
config: testConfig,
|
||||||
imageFSPath: testImageFSPath,
|
imageFSPath: testImageFSPath,
|
||||||
imageStore: imagestore.NewStore(nil),
|
imageStore: imagestore.NewStore(nil, nil, platforms.Default()),
|
||||||
snapshotStore: snapshotstore.NewStore(),
|
snapshotStore: snapshotstore.NewStore(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ import (
|
|||||||
"github.com/containerd/containerd/pkg/cri/nri"
|
"github.com/containerd/containerd/pkg/cri/nri"
|
||||||
"github.com/containerd/containerd/pkg/cri/streaming"
|
"github.com/containerd/containerd/pkg/cri/streaming"
|
||||||
"github.com/containerd/containerd/pkg/kmutex"
|
"github.com/containerd/containerd/pkg/kmutex"
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
cni "github.com/containerd/go-cni"
|
cni "github.com/containerd/go-cni"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
@ -128,7 +129,7 @@ func NewCRIService(config criconfig.Config, client *containerd.Client, nri *nri.
|
|||||||
os: osinterface.RealOS{},
|
os: osinterface.RealOS{},
|
||||||
sandboxStore: sandboxstore.NewStore(labels),
|
sandboxStore: sandboxstore.NewStore(labels),
|
||||||
containerStore: containerstore.NewStore(labels),
|
containerStore: containerstore.NewStore(labels),
|
||||||
imageStore: imagestore.NewStore(client),
|
imageStore: imagestore.NewStore(client.ImageService(), client.ContentStore(), platforms.Default()),
|
||||||
snapshotStore: snapshotstore.NewStore(),
|
snapshotStore: snapshotstore.NewStore(),
|
||||||
sandboxNameIndex: registrar.NewRegistrar(),
|
sandboxNameIndex: registrar.NewRegistrar(),
|
||||||
containerNameIndex: registrar.NewRegistrar(),
|
containerNameIndex: registrar.NewRegistrar(),
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/containerd/go-cni"
|
"github.com/containerd/go-cni"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -45,7 +46,7 @@ func newTestCRIService() *criService {
|
|||||||
imageFSPath: testImageFSPath,
|
imageFSPath: testImageFSPath,
|
||||||
os: ostesting.NewFakeOS(),
|
os: ostesting.NewFakeOS(),
|
||||||
sandboxStore: sandboxstore.NewStore(labels),
|
sandboxStore: sandboxstore.NewStore(labels),
|
||||||
imageStore: imagestore.NewStore(nil),
|
imageStore: imagestore.NewStore(nil, nil, platforms.Default()),
|
||||||
snapshotStore: snapshotstore.NewStore(),
|
snapshotStore: snapshotstore.NewStore(),
|
||||||
sandboxNameIndex: registrar.NewRegistrar(),
|
sandboxNameIndex: registrar.NewRegistrar(),
|
||||||
containerStore: containerstore.NewStore(labels),
|
containerStore: containerstore.NewStore(labels),
|
||||||
|
@ -16,12 +16,16 @@
|
|||||||
|
|
||||||
package image
|
package image
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
|
)
|
||||||
|
|
||||||
// NewFakeStore returns an image store with predefined images.
|
// NewFakeStore returns an image store with predefined images.
|
||||||
// Update is not allowed for this fake store.
|
// Update is not allowed for this fake store.
|
||||||
func NewFakeStore(images []Image) (*Store, error) {
|
func NewFakeStore(images []Image) (*Store, error) {
|
||||||
s := NewStore(nil)
|
s := NewStore(nil, nil, platforms.Default())
|
||||||
for _, i := range images {
|
for _, i := range images {
|
||||||
for _, ref := range i.References {
|
for _, ref := range i.References {
|
||||||
s.refCache[ref] = i.ID
|
s.refCache[ref] = i.ID
|
||||||
|
@ -18,15 +18,20 @@ package image
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"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/labels"
|
||||||
"github.com/containerd/containerd/pkg/cri/util"
|
"github.com/containerd/containerd/pkg/cri/util"
|
||||||
|
"github.com/containerd/containerd/platforms"
|
||||||
docker "github.com/distribution/reference"
|
docker "github.com/distribution/reference"
|
||||||
|
|
||||||
|
"github.com/opencontainers/go-digest"
|
||||||
imagedigest "github.com/opencontainers/go-digest"
|
imagedigest "github.com/opencontainers/go-digest"
|
||||||
"github.com/opencontainers/go-digest/digestset"
|
"github.com/opencontainers/go-digest/digestset"
|
||||||
imageidentity "github.com/opencontainers/image-spec/identity"
|
imageidentity "github.com/opencontainers/image-spec/identity"
|
||||||
@ -50,22 +55,39 @@ type Image struct {
|
|||||||
Pinned bool
|
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.
|
// Store stores all images.
|
||||||
type Store struct {
|
type Store struct {
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
// refCache is a containerd image reference to image id cache.
|
// refCache is a containerd image reference to image id cache.
|
||||||
refCache map[string]string
|
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 is the internal image store indexed by image id.
|
||||||
store *store
|
store *store
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStore creates an image 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{
|
return &Store{
|
||||||
refCache: make(map[string]string),
|
refCache: make(map[string]string),
|
||||||
client: client,
|
images: img,
|
||||||
|
provider: provider,
|
||||||
|
platform: platform,
|
||||||
store: &store{
|
store: &store{
|
||||||
images: make(map[string]Image),
|
images: make(map[string]Image),
|
||||||
digestSet: digestset.NewSet(),
|
digestSet: digestset.NewSet(),
|
||||||
@ -77,13 +99,15 @@ func NewStore(client *containerd.Client) *Store {
|
|||||||
func (s *Store) Update(ctx context.Context, ref string) error {
|
func (s *Store) Update(ctx context.Context, ref string) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
i, err := s.client.GetImage(ctx, ref)
|
|
||||||
|
i, err := s.images.Get(ctx, ref)
|
||||||
if err != nil && !errdefs.IsNotFound(err) {
|
if err != nil && !errdefs.IsNotFound(err) {
|
||||||
return fmt.Errorf("get image from containerd: %w", err)
|
return fmt.Errorf("get image from containerd: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var img *Image
|
var img *Image
|
||||||
if err == nil {
|
if err == nil {
|
||||||
img, err = getImage(ctx, i)
|
img, err = s.getImage(ctx, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get image info from containerd: %w", err)
|
return fmt.Errorf("get image info from containerd: %w", err)
|
||||||
}
|
}
|
||||||
@ -116,36 +140,40 @@ func (s *Store) update(ref string, img *Image) error {
|
|||||||
return s.store.add(*img)
|
return s.store.add(*img)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getImage gets image information from containerd.
|
// getImage gets image information from containerd for current platform.
|
||||||
func getImage(ctx context.Context, i containerd.Image) (*Image, error) {
|
func (s *Store) getImage(ctx context.Context, i images.Image) (*Image, error) {
|
||||||
// Get image information.
|
diffIDs, err := i.RootFS(ctx, s.provider, s.platform)
|
||||||
diffIDs, err := i.RootFS(ctx)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get image diffIDs: %w", err)
|
return nil, fmt.Errorf("get image diffIDs: %w", err)
|
||||||
}
|
}
|
||||||
chainID := imageidentity.ChainID(diffIDs)
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get image compressed resource size: %w", err)
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get image config descriptor: %w", err)
|
return nil, fmt.Errorf("get image config descriptor: %w", err)
|
||||||
}
|
}
|
||||||
id := desc.Digest.String()
|
id := desc.Digest.String()
|
||||||
|
|
||||||
spec, err := i.Spec(ctx)
|
blob, err := content.ReadBlob(ctx, s.provider, desc)
|
||||||
if err != nil {
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
pinned := i.Labels()[labels.PinnedImageLabelKey] == labels.PinnedImageLabelValue
|
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
|
||||||
|
|
||||||
return &Image{
|
return &Image{
|
||||||
ID: id,
|
ID: id,
|
||||||
References: []string{i.Name()},
|
References: []string{i.Name},
|
||||||
ChainID: chainID.String(),
|
ChainID: chainID.String(),
|
||||||
Size: size,
|
Size: size,
|
||||||
ImageSpec: spec,
|
ImageSpec: spec,
|
||||||
|
Loading…
Reference in New Issue
Block a user