Skip to content

Commit

Permalink
Invalidate imageCache if the pinned image from config exists
Browse files Browse the repository at this point in the history
Signed-off-by: roman-kiselenko <roman.kiselenko.dev@gmail.com>
  • Loading branch information
roman-kiselenko committed Apr 10, 2024
1 parent f63de87 commit 53da2c8
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 29 deletions.
24 changes: 24 additions & 0 deletions internal/storage/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ type ImageServer interface {
// CandidatesForPotentiallyShortImageName resolves an image name into a set of fully-qualified image names (domain/repo/image:tag|@digest).
// It will only return an empty slice if err != nil.
CandidatesForPotentiallyShortImageName(systemContext *types.SystemContext, imageName string) ([]RegistryImageReference, error)

// UpdateImageCache invalidate imageCache if the pinned image from config exists;
// this method doesn't change the Pinned attribute, only removes the image item.
UpdateImageCache(configPinnedImage []string) error
}

func parseImageNames(image *storage.Image) (someName *RegistryImageReference, tags []reference.NamedTagged, digests []reference.Canonical, err error) {
Expand Down Expand Up @@ -897,6 +901,26 @@ func (st nativeStorageTransport) ResolveReference(ref types.ImageReference) (typ
return istorage.ResolveReference(ref)
}

// UpdateImageCache invalidate imageCache if the pinned image from config exists;
// this method doesn't change the Pinned attribute, only removes the image item.
func (svc *imageService) UpdateImageCache(configPinnedImage []string) error {
images, err := svc.store.Images()
if err != nil {
return err
}
for i := range images {
img := &images[i]
for _, name := range img.Names {
if FilterPinnedImage(name, CompileRegexpsForPinnedImages(configPinnedImage)) {
svc.imageCacheLock.Lock()
delete(svc.imageCache, img.ID)
svc.imageCacheLock.Unlock()
}
}
}
return nil
}

// FilterPinnedImage checks if the given image needs to be pinned
// and excluded from kubelet's image GC.
func FilterPinnedImage(image string, pinnedImages []*regexp.Regexp) bool {
Expand Down
55 changes: 33 additions & 22 deletions pkg/config/reload.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@ import (
)

// Reload reloads the configuration for the single crio.conf and the drop-in
// configuration directory.
func (c *Config) Reload() error {
// configuration directory. Returns updated Config struct.
func (c *Config) Reload() (*Config, error) {
logrus.Infof("Reloading configuration")

// Reload the config
newConfig, err := DefaultConfig()
if err != nil {
return errors.New("unable to create default config")
return nil, fmt.Errorf("unable to create default config: %w", err)
}

if _, err := os.Stat(c.singleConfigPath); !os.IsNotExist(err) {
logrus.Infof("Updating config from file %s", c.singleConfigPath)
if err := newConfig.UpdateFromFile(c.singleConfigPath); err != nil {
return err
return newConfig, err
}
} else {
logrus.Infof("Skipping not-existing config file %q", c.singleConfigPath)
Expand All @@ -35,45 +35,49 @@ func (c *Config) Reload() error {
if _, err := os.Stat(c.dropInConfigDir); !os.IsNotExist(err) {
logrus.Infof("Updating config from path %s", c.dropInConfigDir)
if err := newConfig.UpdateFromPath(c.dropInConfigDir); err != nil {
return err
return newConfig, err
}
} else {
logrus.Infof("Skipping not-existing config path %q", c.dropInConfigDir)
}

// Reload all available options
if err := c.ReloadLogLevel(newConfig); err != nil {
return err
return newConfig, err
}
if err := c.ReloadLogFilter(newConfig); err != nil {
return err
return newConfig, err
}
if err := c.ReloadPauseImage(newConfig); err != nil {
return err
return newConfig, err
}
c.ReloadPinnedImages(newConfig)
if err := c.ReloadRegistries(); err != nil {
return err
return newConfig, err
}
c.ReloadDecryptionKeyConfig(newConfig)
if err := c.ReloadSeccompProfile(newConfig); err != nil {
return err
return newConfig, err
}
if err := c.ReloadAppArmorProfile(newConfig); err != nil {
return err
return newConfig, err
}
if err := c.ReloadBlockIOConfig(newConfig); err != nil {
return err
return newConfig, err
}
if err := c.ReloadRdtConfig(newConfig); err != nil {
return err
return newConfig, err
}
if err := c.ReloadRuntimes(newConfig); err != nil {
return err
return newConfig, err
}

cdi.GetRegistry(cdi.WithSpecDirs(newConfig.CDISpecDirs...))
return newConfig, nil
}

return nil
// IsPinnedImagesUpdated return the state of pinned image updates
func (c *Config) IsPinnedImagesUpdated(newConfig *Config) bool {
return c.ReloadPinnedImages(newConfig)
}

// logConfig logs a config set operation as with info verbosity. Please always
Expand Down Expand Up @@ -143,17 +147,24 @@ func (c *Config) ReloadPauseImage(newConfig *Config) error {
}

// ReloadPinnedImages updates the PinnedImages with the provided `newConfig`.
func (c *Config) ReloadPinnedImages(newConfig *Config) {
func (c *Config) ReloadPinnedImages(newConfig *Config) bool {
updatedPinnedImages := make([]string, len(newConfig.PinnedImages))
updatedPinnedImageList := false

for i, image := range newConfig.PinnedImages {
if i < len(c.PinnedImages) && image == c.PinnedImages[i] {
updatedPinnedImages[i] = c.PinnedImages[i]
} else {
updatedPinnedImages[i] = image
continue
}
updatedPinnedImages[i] = image
updatedPinnedImageList = true
}

if updatedPinnedImageList {
logrus.Infof("Updated new pinned images: %+v", updatedPinnedImages)
c.PinnedImages = updatedPinnedImages
}
logrus.Infof("Updated new pinned images: %+v", updatedPinnedImages)
c.PinnedImages = updatedPinnedImages

return updatedPinnedImageList
}

// ReloadRegistries reloads the registry configuration from the Configs
Expand Down
18 changes: 12 additions & 6 deletions pkg/config/reload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ var _ = t.Describe("Config", func() {
Expect(sut.UpdateFromFile(filePath)).To(Succeed())

// When
err := sut.Reload()
cfg, err := sut.Reload()

// Then
Expect(cfg).ToNot(BeNil())
Expect(err).ToNot(HaveOccurred())
})

Expand All @@ -49,9 +50,10 @@ var _ = t.Describe("Config", func() {
)

// When
err := sut.Reload()
cfg, err := sut.Reload()

// Then
Expect(cfg).ToNot(BeNil())
Expect(err).To(HaveOccurred())
})

Expand All @@ -63,9 +65,10 @@ var _ = t.Describe("Config", func() {
)

// When
err := sut.Reload()
cfg, err := sut.Reload()

// Then
Expect(cfg).ToNot(BeNil())
Expect(err).To(HaveOccurred())
})

Expand All @@ -77,9 +80,10 @@ var _ = t.Describe("Config", func() {
)

// When
err := sut.Reload()
cfg, err := sut.Reload()

// Then
Expect(cfg).ToNot(BeNil())
Expect(err).ToNot(HaveOccurred())
})
})
Expand Down Expand Up @@ -427,15 +431,17 @@ var _ = t.Describe("Config", func() {
sut.PinnedImages = []string{"image1", "image4", "image3"}
newConfig := &config.Config{}
newConfig.PinnedImages = []string{"image5"}
sut.ReloadPinnedImages(newConfig)
ok := sut.ReloadPinnedImages(newConfig)
Expect(ok).To(BeTrue())
Expect(sut.PinnedImages).To(Equal([]string{"image5"}))
})

It("should not update PinnedImages if they are the same as newConfig's PinnedImages", func() {
sut.PinnedImages = []string{"image1", "image2", "image3"}
newConfig := &config.Config{}
newConfig.PinnedImages = []string{"image1", "image2", "image3"}
sut.ReloadPinnedImages(newConfig)
ok := sut.ReloadPinnedImages(newConfig)
Expect(ok).To(BeFalse())
Expect(sut.PinnedImages).To(Equal([]string{"image1", "image2", "image3"}))
})
})
Expand Down
9 changes: 8 additions & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,10 +573,17 @@ func (s *Server) startReloadWatcher(ctx context.Context) {
for {
// Block until the signal is received
<-ch
if err := s.config.Reload(); err != nil {
newConfig, err := s.config.Reload()
if err != nil {
logrus.Errorf("Unable to reload configuration: %v", err)
continue
}
if s.config.IsPinnedImagesUpdated(newConfig) {
if err := s.StorageImageServer().UpdateImageCache(s.config.PinnedImages); err != nil {
logrus.Errorf("Unable to update pinned images: %v", err)
continue
}
}
}
}()

Expand Down
14 changes: 14 additions & 0 deletions test/mocks/criostorage/criostorage.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions test/reload_config.bats
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,13 @@ EOF
#then
wait_for_log '"updating runtime configuration"'
}

@test "reload config should update 'pinned_images'" {
# given
printf '[crio.image]\npinned_images = [""]\n' > "$CRIO_CONFIG_DIR"/00-default
printf '[crio.image]\npinned_images = ["quay.io/crio/hello-wasm:latest"]\n' > "$CRIO_CONFIG_DIR"/01-overwrite
# when
reload_crio
#then
wait_for_log 'Updated new pinned images'
}

0 comments on commit 53da2c8

Please sign in to comment.