Skip to content

Commit

Permalink
Use a containerd plugin for side-loading images (#502)
Browse files Browse the repository at this point in the history
* containerd sideload images

* add regctl under tools/
  • Loading branch information
neoaggelos authored Jun 17, 2024
1 parent 2e29d06 commit be814f6
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
From d6a1e25e517a981b90bb6e0df66b63c72bc61f45 Mon Sep 17 00:00:00 2001
From: Angelos Kolaitis <[email protected]>
Date: Sun, 16 Jun 2024 16:58:03 +0300
Subject: [PATCH] side-load images plugin

---
cmd/containerd/builtins_custom.go | 6 ++
custom_plugins/sideload.go | 134 ++++++++++++++++++++++++++++++
2 files changed, 140 insertions(+)
create mode 100644 cmd/containerd/builtins_custom.go
create mode 100644 custom_plugins/sideload.go

diff --git a/cmd/containerd/builtins_custom.go b/cmd/containerd/builtins_custom.go
new file mode 100644
index 000000000..581e42364
--- /dev/null
+++ b/cmd/containerd/builtins_custom.go
@@ -0,0 +1,6 @@
+package main
+
+// register custom containerd plugins here
+import (
+ _ "github.com/containerd/containerd/custom_plugins"
+)
diff --git a/custom_plugins/sideload.go b/custom_plugins/sideload.go
new file mode 100644
index 000000000..4f2680a32
--- /dev/null
+++ b/custom_plugins/sideload.go
@@ -0,0 +1,134 @@
+package custom_plugins
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/containerd/containerd"
+ "github.com/containerd/containerd/log"
+ "github.com/containerd/containerd/platforms"
+ "github.com/containerd/containerd/plugin"
+)
+
+const pluginName = "sideload-images"
+
+var logger = log.L.WithField("plugin", pluginName)
+
+type Config struct {
+ // Disabled is a toggle option to completely disable this plugin.
+ Disabled bool `toml:"enabled"`
+
+ // Interval configures how frequently the plugin will look for new images found
+ // in the sources. If set to zero, images are only loaded during initial start.
+ Interval time.Duration `toml:"interval"`
+
+ // Sources is a list of paths to look for .tar images.
+ // For example, `/var/snap/k8s/common/images`
+ Sources []string `toml:"sources"`
+
+ // Namespace the images will be loaded into, e.g. "k8s.io"
+ Namespace string `toml:"namespace"`
+}
+
+func (c *Config) SetDefaults() {
+ if c.Namespace == "" {
+ c.Namespace = "k8s.io"
+ }
+ if len(c.Sources) == 0 {
+ snapCommon := os.Getenv("SNAP_COMMON")
+ if snapCommon == "" {
+ snapCommon = "/var/snap/k8s/common"
+ }
+ c.Sources = []string{filepath.Join(snapCommon, "images")}
+ }
+}
+
+func init() {
+ c := &Config{}
+ plugin.Register(&plugin.Registration{
+ Type: plugin.ServicePlugin,
+ ID: pluginName,
+ Config: c,
+ InitFn: func(ic *plugin.InitContext) (interface{}, error) {
+ config := ic.Config.(*Config)
+ config.SetDefaults()
+
+ logger.Debugf("Loaded config %#v", config)
+
+ if config.Disabled {
+ return nil, fmt.Errorf("plugin disabled through config: %w", plugin.ErrSkipPlugin)
+ }
+ if len(config.Sources) == 0 {
+ return nil, fmt.Errorf("no sources configured: %w", plugin.ErrSkipPlugin)
+ }
+
+ go func() {
+ // get a containerd client
+ var (
+ cl *containerd.Client
+ err error
+ )
+ for cl == nil {
+ select {
+ case <-ic.Context.Done():
+ return
+ default:
+ }
+
+ cl, err = containerd.New(ic.Address, containerd.WithDefaultNamespace(config.Namespace), containerd.WithTimeout(2*time.Second))
+ if err != nil {
+ logger.Info("Failed to create containerd client")
+ }
+ }
+
+ for {
+ nextDir:
+ for _, dir := range c.Sources {
+ logger := logger.WithField("dir", dir)
+ logger.Debug("Looking for images")
+ files, err := filepath.Glob(filepath.Join(dir, "*.tar"))
+ if err != nil {
+ logger.WithError(err).Warn("Failed to look for images")
+ continue nextDir
+ }
+
+ nextFile:
+ for _, file := range files {
+ logger := logger.WithField("file", file)
+ r, err := os.Open(file)
+ if err != nil {
+ logger.WithError(err).Warn("Failed to open file")
+ continue nextFile
+ }
+ images, err := cl.Import(ic.Context, r, containerd.WithImportPlatform(platforms.Default()))
+ if err != nil {
+ logger.WithError(err).Error("Failed to import images")
+ } else {
+ logger.Infof("Imported %d images", len(images))
+ os.Rename(file, file+".loaded")
+ }
+ if closeErr := r.Close(); closeErr != nil {
+ logger.WithError(closeErr).Error("Failed to close reader")
+ }
+ }
+ }
+
+ // retry after interval, finish if interval is zero
+ if c.Interval == 0 {
+ logger.Info("Plugin terminating")
+ return
+ }
+ select {
+ case <-ic.Context.Done():
+ return
+ case <-time.After(c.Interval):
+ }
+ }
+ }()
+
+ return nil, nil
+ },
+ })
+}
--
2.34.1

1 change: 1 addition & 0 deletions src/k8s/tools/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
2 changes: 2 additions & 0 deletions src/k8s/tools/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0o
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
8 changes: 8 additions & 0 deletions src/k8s/tools/regctl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash -eu

# Run regctl
TOOLS_DIR="$(realpath `dirname "${0}"`)"
(
cd "${TOOLS_DIR}"
go run github.com/regclient/regclient/cmd/regctl "${@}"
)
1 change: 1 addition & 0 deletions src/k8s/tools/tools.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package main

import (
_ "github.com/regclient/regclient/cmd/regctl"
_ "github.com/regclient/regclient/cmd/regsync"
)

0 comments on commit be814f6

Please sign in to comment.