Skip to content

Commit

Permalink
implement kwasm lockfile support to avoid unnecessary restarts
Browse files Browse the repository at this point in the history
  • Loading branch information
phyrog committed Sep 29, 2023
1 parent 73cc3d8 commit a8c876a
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 11 deletions.
22 changes: 17 additions & 5 deletions cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,33 @@ var installCmd = &cobra.Command{
slog.Error(err.Error())
return
}
anythingChanged := false
for _, file := range files {
binPath, err := shim.Install(&config, file.Name())
fileName := file.Name()
runtimeName := shim.RuntimeName(fileName)

binPath, changed, err := shim.Install(&config, fileName)
if err != nil {
slog.Error(err.Error())
slog.Error("failed to install shim", "shim", runtimeName, "error", err)
return
}
slog.Info("shim installed", "shim", shim.RuntimeName(file.Name()), "path", binPath)
anythingChanged = anythingChanged || changed
slog.Info("shim installed", "shim", runtimeName, "path", binPath, "new-version", changed)

configPath, err := containerd.WriteConfig(&config, binPath)
if err != nil {
slog.Error(err.Error())
slog.Error("failed to write containerd config", "shim", runtimeName, "path", configPath, "error", err)
return
}
slog.Info("shim configured", "shim", shim.RuntimeName(file.Name()), "path", configPath)
slog.Info("shim configured", "shim", runtimeName, "path", configPath)
}

if !anythingChanged {
slog.Info("nothing changed, nothing more to do")
return
}

slog.Info("restarting containerd")
err = containerd.RestartRuntime()
if err != nil {
slog.Error("failed to restart containerd", "error", err)
Expand Down
32 changes: 26 additions & 6 deletions pkg/shim/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,52 @@
package shim

import (
"crypto/sha256"
"io"
"os"
"path"

"github.com/kwasm/kwasm-node-installer/pkg/config"
"github.com/kwasm/kwasm-node-installer/pkg/state"
)

func Install(config *config.Config, shimName string) (string, error) {
func Install(config *config.Config, shimName string) (string, bool, error) {
shimPath := config.AssetPath(shimName)
srcFile, err := os.OpenFile(shimPath, os.O_RDONLY, 0000)
if err != nil {
return "", err
return "", false, err
}
dstFilePath := path.Join(config.Kwasm.Path, "bin", shimName)
dstFilePathHost := config.PathWithHost(dstFilePath)

err = os.MkdirAll(path.Dir(dstFilePathHost), 0755)
if err != nil {
return dstFilePath, err
return dstFilePath, false, err
}

dstFile, err := os.OpenFile(dstFilePathHost, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
return "", err
return "", false, err
}
_, err = io.Copy(dstFile, srcFile)

return dstFilePath, err
st, err := state.Get(config)
if err != nil {
return "", false, err
}
shimSha256 := sha256.New()

_, err = io.Copy(io.MultiWriter(dstFile, shimSha256), srcFile)
runtimeName := RuntimeName(shimName)
changed := st.ShimChanged(runtimeName, shimSha256.Sum(nil), dstFilePath)
if changed {
st.UpdateShim(runtimeName, state.Shim{
Path: dstFilePath,
Sha256: shimSha256.Sum(nil),
})
if err := st.Write(); err != nil {
return "", false, err
}
}

return dstFilePath, changed, err
}
38 changes: 38 additions & 0 deletions pkg/state/shim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package state

import (
"encoding/hex"
"encoding/json"
)

type Shim struct {
Sha256 []byte
Path string
}

func (s *Shim) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Sha256 string `json:"sha256"`
Path string `json:"path"`
}{
Sha256: hex.EncodeToString(s.Sha256),
Path: s.Path,
})
}

func (s *Shim) UnmarshalJSON(data []byte) error {
aux := &struct {
Sha256 string `json:"sha256"`
Path string `json:"path"`
}{}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
s.Path = aux.Path
sha256, err := hex.DecodeString(aux.Sha256)
if err != nil {
return err
}
s.Sha256 = sha256
return nil
}
62 changes: 62 additions & 0 deletions pkg/state/state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package state

import (
"bytes"
"encoding/json"
"errors"
"log/slog"
"os"
"path"

"github.com/kwasm/kwasm-node-installer/pkg/config"
)

type state struct {
Shims map[string]*Shim `json:"shims"`
config *config.Config
}

func Get(config *config.Config) (*state, error) {
out := state{
Shims: make(map[string]*Shim),
config: config,
}
content, err := os.ReadFile(filePath(config))
if err == nil {
err := json.Unmarshal(content, &out)
return &out, err
}
if !errors.Is(err, os.ErrNotExist) {
return nil, err
}

return &out, nil
}

func (l *state) ShimChanged(shimName string, sha256 []byte, path string) bool {
shim, ok := l.Shims[shimName]
if !ok {
return true
}

return !bytes.Equal(shim.Sha256, sha256) || shim.Path != path
}

func (l *state) UpdateShim(shimName string, shim Shim) {
l.Shims[shimName] = &shim
}

func (l *state) Write() error {
out, err := json.MarshalIndent(l, "", " ")
if err != nil {
return err
}

slog.Info("writing lock file", "content", string(out))

return os.WriteFile(filePath(l.config), out, 0644)
}

func filePath(config *config.Config) string {
return config.PathWithHost(path.Join(config.Kwasm.Path, "kwasm-lock.json"))
}

0 comments on commit a8c876a

Please sign in to comment.