Skip to content

Commit 92876fb

Browse files
authored
Avoid reuploading unchanged files (#352)
1 parent e6fb861 commit 92876fb

File tree

4 files changed

+64
-6
lines changed

4 files changed

+64
-6
lines changed

go.sum

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
471471
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
472472
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
473473
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
474-
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
475474
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
476475
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
477476
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=

phase/upload_binaries.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package phase
22

33
import (
4+
"fmt"
5+
"os"
6+
47
"github.com/k0sproject/k0sctl/pkg/apis/k0sctl.k0sproject.io/v1beta1"
58
"github.com/k0sproject/k0sctl/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster"
69
"github.com/k0sproject/rig/exec"
@@ -38,15 +41,28 @@ func (p *UploadBinaries) Run() error {
3841
}
3942

4043
func (p *UploadBinaries) uploadBinary(h *cluster.Host) error {
41-
log.Infof("%s: uploading k0s binary from %s", h, h.UploadBinaryPath)
42-
if err := h.Upload(h.UploadBinaryPath, h.Configurer.K0sBinaryPath(), exec.Sudo(h)); err != nil {
43-
return err
44+
stat, err := os.Stat(h.UploadBinaryPath)
45+
if err != nil {
46+
return fmt.Errorf("failed to stat %s: %w", h.UploadBinaryPath, err)
47+
}
48+
if h.FileChanged(h.UploadBinaryPath, h.Configurer.K0sBinaryPath()) {
49+
log.Infof("%s: uploading k0s binary from %s", h, h.UploadBinaryPath)
50+
if err := h.Upload(h.UploadBinaryPath, h.Configurer.K0sBinaryPath(), exec.Sudo(h)); err != nil {
51+
return err
52+
}
53+
} else {
54+
log.Infof("%s: k0s binary %s already exists on the target and hasn't been changed, skipping upload", h, h.UploadBinaryPath)
4455
}
4556

4657
if err := h.Configurer.Chmod(h, h.Configurer.K0sBinaryPath(), "0700", exec.Sudo(h)); err != nil {
4758
return err
4859
}
4960

61+
log.Debugf("%s: touching %s", h, h.Configurer.K0sBinaryPath())
62+
if err := h.Configurer.Touch(h, h.Configurer.K0sBinaryPath(), stat.ModTime(), exec.Sudo(h)); err != nil {
63+
return fmt.Errorf("failed to touch %s: %w", h.Configurer.K0sBinaryPath(), err)
64+
}
65+
5066
h.Metadata.K0sBinaryVersion = p.Config.Spec.K0s.Version
5167

5268
return nil

phase/uploadfiles.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package phase
22

33
import (
44
"fmt"
5+
"os"
56
"path"
67

78
"github.com/alessio/shellescape"
@@ -107,8 +108,12 @@ func (p *UploadFiles) uploadFile(h *cluster.Host, f *cluster.UploadFile) error {
107108
return err
108109
}
109110

110-
if err := h.Upload(path.Join(f.Base, s.Path), dest, exec.Sudo(h)); err != nil {
111-
return err
111+
if h.FileChanged(src, dest) {
112+
if err := h.Upload(path.Join(f.Base, s.Path), dest, exec.Sudo(h)); err != nil {
113+
return err
114+
}
115+
} else {
116+
log.Infof("%s: file already exists and hasn't been changed, skipping upload", h)
112117
}
113118

114119
if owner != "" {
@@ -121,6 +126,14 @@ func (p *UploadFiles) uploadFile(h *cluster.Host, f *cluster.UploadFile) error {
121126
if err := h.Configurer.Chmod(h, dest, s.PermMode, exec.Sudo(h)); err != nil {
122127
return err
123128
}
129+
stat, err := os.Stat(src)
130+
if err != nil {
131+
return fmt.Errorf("failed to stat %s: %s", src, err)
132+
}
133+
log.Debugf("%s: touching %s", h, dest)
134+
if err := h.Configurer.Touch(h, dest, stat.ModTime(), exec.Sudo(h)); err != nil {
135+
return fmt.Errorf("failed to touch %s: %w", dest, err)
136+
}
124137
}
125138

126139
return nil

pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cluster
33
import (
44
"encoding/json"
55
"fmt"
6+
gos "os"
67
"regexp"
78
"strconv"
89
"strings"
@@ -112,6 +113,8 @@ type configurer interface {
112113
TempFile(os.Host) (string, error)
113114
UpdateServiceEnvironment(os.Host, string, map[string]string) error
114115
CleanupServiceEnvironment(os.Host, string) error
116+
Stat(os.Host, string, ...exec.Option) (*os.FileInfo, error)
117+
Touch(os.Host, string, time.Time, ...exec.Option) error
115118
}
116119

117120
// HostMetadata resolved metadata for host
@@ -494,3 +497,30 @@ func (h *Host) WaitKubeAPIReady(port int) error {
494497
// thus we need to accept both 200 and 401 as valid statuses when checking kube api
495498
return h.WaitHTTPStatus(fmt.Sprintf("https://localhost:%d/version", port), 200, 401)
496499
}
500+
501+
// FileChanged returns true when a remote file has different size or mtime compared to local
502+
// or if an error occurs
503+
func (h *Host) FileChanged(lpath, rpath string) bool {
504+
lstat, err := gos.Stat(lpath)
505+
if err != nil {
506+
log.Debugf("%s: local stat failed: %s", h, err)
507+
return true
508+
}
509+
rstat, err := h.Configurer.Stat(h, rpath, exec.Sudo(h))
510+
if err != nil {
511+
log.Debugf("%s: remote stat failed: %s", h, err)
512+
return true
513+
}
514+
515+
if lstat.Size() != rstat.Size() {
516+
log.Debugf("%s: file sizes for %s differ (%d vs %d)", h, lpath, lstat.Size(), rstat.Size())
517+
return true
518+
}
519+
520+
if !lstat.ModTime().Equal(rstat.ModTime()) {
521+
log.Debugf("%s: file modtimes for %s differ (%s vs %s)", h, lpath, lstat.ModTime(), rstat.ModTime())
522+
return true
523+
}
524+
525+
return false
526+
}

0 commit comments

Comments
 (0)