Skip to content

Commit 4108aa9

Browse files
authoredAug 8, 2023
Auto calculate image size on actions (#122)
1 parent 3e9befa commit 4108aa9

File tree

8 files changed

+102
-14
lines changed

8 files changed

+102
-14
lines changed
 

‎go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/hashicorp/go-multierror v1.1.1
1313
github.com/jaypipes/ghw v0.12.0
1414
github.com/joho/godotenv v1.5.1
15-
github.com/kairos-io/kairos-sdk v0.0.11
15+
github.com/kairos-io/kairos-sdk v0.0.12
1616
github.com/labstack/echo/v4 v4.10.2
1717
github.com/mitchellh/mapstructure v1.5.0
1818
github.com/mudler/go-nodepair v0.0.0-20221223092639-ba399a66fdfb

‎go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,8 @@ github.com/kairos-io/kairos-sdk v0.0.10 h1:TUgrGSGP6Z1CPfA4gjmbb+cCaJg1OR18c+LD+
371371
github.com/kairos-io/kairos-sdk v0.0.10/go.mod h1:AK9poWisuhnzri04diXnTG8L7EkOSUArSeeDn2LYFU0=
372372
github.com/kairos-io/kairos-sdk v0.0.11 h1:+EWuO4gWMzBa81s8gbF1L7wOvEjbph1z8UkfUrMyvxc=
373373
github.com/kairos-io/kairos-sdk v0.0.11/go.mod h1:AK9poWisuhnzri04diXnTG8L7EkOSUArSeeDn2LYFU0=
374+
github.com/kairos-io/kairos-sdk v0.0.12 h1:+uibTjjsAh8klupXHWpWse2AKww6p8ROu8Ii28t3k48=
375+
github.com/kairos-io/kairos-sdk v0.0.12/go.mod h1:AK9poWisuhnzri04diXnTG8L7EkOSUArSeeDn2LYFU0=
374376
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o=
375377
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4=
376378
github.com/kendru/darwin/go/depgraph v0.0.0-20221105232959-877d6a81060c h1:eKb4PqwAMhlqwXw0W3atpKaYaPGlXE/Fwh+xpCEYaPk=

‎pkg/config/spec.go

+83-7
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@ package config
1818

1919
import (
2020
"fmt"
21-
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
22-
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions"
21+
"io/fs"
2322
"path/filepath"
2423
"reflect"
2524
"strings"
2625

2726
"github.com/kairos-io/kairos-agent/v2/internal/common"
2827
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
2928
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
29+
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
30+
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions"
3031
"github.com/mitchellh/mapstructure"
3132
"github.com/sanity-io/litter"
3233
"github.com/sirupsen/logrus"
@@ -95,7 +96,19 @@ func NewInstallSpec(cfg *Config) *v1.InstallSpec {
9596
Recovery: recoveryImg,
9697
Passive: passiveImg,
9798
}
98-
// Calculate the partitions sizes automatically based on the images set size
99+
100+
// Get the actual source size to calculate the image size and partitions size
101+
size, err := GetSourceSize(cfg, spec.Active.Source)
102+
if err != nil {
103+
cfg.Logger.Warnf("Failed to infer size for images: %s", err.Error())
104+
} else {
105+
cfg.Logger.Infof("Setting image size to %dMb", size)
106+
spec.Active.Size = uint(size)
107+
spec.Passive.Size = uint(size)
108+
spec.Recovery.Size = uint(size)
109+
}
110+
111+
// Calculate the partitions afterwards so they use the image sizes for the final partition sizes
99112
spec.Partitions = NewInstallElementalPartitions(spec)
100113

101114
return spec
@@ -237,13 +250,26 @@ func NewUpgradeSpec(cfg *Config) (*v1.UpgradeSpec, error) {
237250
}
238251
}
239252

240-
return &v1.UpgradeSpec{
253+
spec := &v1.UpgradeSpec{
241254
Active: active,
242255
Recovery: recovery,
243256
Passive: passive,
244257
Partitions: ep,
245258
State: installState,
246-
}, nil
259+
}
260+
261+
// Get the actual source size to calculate the image size and partitions size
262+
size, err := GetSourceSize(cfg, spec.Active.Source)
263+
if err != nil {
264+
cfg.Logger.Warnf("Failed to infer size for images: %s", err.Error())
265+
} else {
266+
cfg.Logger.Infof("Setting image size to %dMb", size)
267+
// On upgrade only the active or recovery will be upgraded, so we dont need to override passive
268+
spec.Active.Size = uint(size)
269+
spec.Recovery.Size = uint(size)
270+
}
271+
272+
return spec, nil
247273
}
248274

249275
// NewResetSpec returns a ResetSpec struct all based on defaults and current host state
@@ -343,7 +369,7 @@ func NewResetSpec(cfg *Config) (*v1.ResetSpec, error) {
343369
}
344370

345371
activeFile := filepath.Join(ep.State.MountPoint, "cOS", constants.ActiveImgFile)
346-
return &v1.ResetSpec{
372+
spec := &v1.ResetSpec{
347373
Target: target,
348374
Partitions: ep,
349375
Efi: efiExists,
@@ -367,7 +393,19 @@ func NewResetSpec(cfg *Config) (*v1.ResetSpec, error) {
367393
FS: constants.LinuxImgFs,
368394
},
369395
State: installState,
370-
}, nil
396+
}
397+
398+
// Get the actual source size to calculate the image size and partitions size
399+
size, err := GetSourceSize(cfg, spec.Active.Source)
400+
if err != nil {
401+
cfg.Logger.Warnf("Failed to infer size for images: %s", err.Error())
402+
} else {
403+
cfg.Logger.Infof("Setting image size to %dMb", size)
404+
spec.Active.Size = uint(size)
405+
spec.Passive.Size = uint(size)
406+
}
407+
408+
return spec, nil
371409
}
372410

373411
// ReadResetSpecFromConfig will return a proper v1.ResetSpec based on an agent Config
@@ -400,6 +438,44 @@ func ReadInstallSpecFromConfig(c *Config) (*v1.InstallSpec, error) {
400438
return installSpec, nil
401439
}
402440

441+
// GetSourceSize will try to gather the actual size of the source
442+
// Useful to create the exact size of images and by side effect the partition size
443+
// This helps adjust the size to be juuuuust right.
444+
// It can still be manually override from the cloud config by setting all values manually
445+
// But by default it should adjust the sizes properly
446+
func GetSourceSize(config *Config, source *v1.ImageSource) (int64, error) {
447+
var size int64
448+
var err error
449+
450+
switch {
451+
case source.IsDocker():
452+
size, err = config.ImageExtractor.GetOCIImageSize(source.Value(), config.Platform.String())
453+
case source.IsDir():
454+
err = fsutils.WalkDirFs(config.Fs, source.Value(), func(path string, d fs.DirEntry, err error) error {
455+
if err != nil {
456+
return err
457+
}
458+
info, err := d.Info()
459+
if err != nil {
460+
return err
461+
}
462+
size += info.Size()
463+
return nil
464+
})
465+
466+
case source.IsFile():
467+
file, err := config.Fs.Stat(source.Value())
468+
if err == nil {
469+
size = file.Size()
470+
}
471+
}
472+
// Normalize size to Mb before returning and add 100Mb to round the size from bytes to mb+extra files like grub stuff
473+
if size != 0 {
474+
size = (size / 1000 / 1000) + 100
475+
}
476+
return size, err
477+
}
478+
403479
// ReadUpgradeSpecFromConfig will return a proper v1.UpgradeSpec based on an agent Config
404480
func ReadUpgradeSpecFromConfig(c *Config) (*v1.UpgradeSpec, error) {
405481
sp, err := ReadSpecFromCloudConfig(c, "upgrade")

‎pkg/elemental/elemental.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ func (e Elemental) UnmountImage(img *v1.Image) error {
252252

253253
// CreateFileSystemImage creates the image file for config.target
254254
func (e Elemental) CreateFileSystemImage(img *v1.Image) error {
255-
e.config.Logger.Infof("Creating file system image %s", img.File)
255+
e.config.Logger.Infof("Creating file system image %s with size %dMb", img.File, img.Size)
256256
err := fsutils.MkdirAll(e.config.Fs, filepath.Dir(img.File), cnst.DirPerm)
257257
if err != nil {
258258
return err

‎pkg/elemental/elemental_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -387,13 +387,13 @@ var _ = Describe("Elemental", Label("elemental"), func() {
387387
"mkpart", "oem", "ext4", "133120", "264191",
388388
}, {"mkfs.ext4", "-L", "COS_OEM", "/some/device2"}, {
389389
"parted", "--script", "--machine", "--", "/some/device", "unit", "s",
390-
"mkpart", "recovery", "ext4", "264192", "6760447",
390+
"mkpart", "recovery", "ext4", "264192", "468991",
391391
}, {"mkfs.ext4", "-L", "COS_RECOVERY", "/some/device3"}, {
392392
"parted", "--script", "--machine", "--", "/some/device", "unit", "s",
393-
"mkpart", "state", "ext4", "6760448", "19548159",
393+
"mkpart", "state", "ext4", "468992", "673791",
394394
}, {"mkfs.ext4", "-L", "COS_STATE", "/some/device4"}, {
395395
"parted", "--script", "--machine", "--", "/some/device", "unit", "s",
396-
"mkpart", "persistent", "ext4", "19548160", "100%",
396+
"mkpart", "persistent", "ext4", "673792", "100%",
397397
}, {"mkfs.ext4", "-L", "COS_PERSISTENT", "/some/device5"},
398398
}
399399

‎pkg/types/v1/image.go

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
type ImageExtractor interface {
2424
ExtractImage(imageRef, destination, platformRef string) error
25+
GetOCIImageSize(imageRef, platformRef string) (int64, error)
2526
}
2627

2728
type OCIImageExtractor struct{}
@@ -31,3 +32,7 @@ var _ ImageExtractor = OCIImageExtractor{}
3132
func (e OCIImageExtractor) ExtractImage(imageRef, destination, platformRef string) error {
3233
return utils.ExtractOCIImage(imageRef, destination, platformRef)
3334
}
35+
36+
func (e OCIImageExtractor) GetOCIImageSize(imageRef, platformRef string) (int64, error) {
37+
return utils.GetOCIImageSize(imageRef, platformRef)
38+
}

‎pkg/utils/fs/fs.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ limitations under the License.
2020
package fsutils
2121

2222
import (
23+
"errors"
2324
"io/fs"
2425
"os"
2526
"path/filepath"
@@ -198,7 +199,7 @@ func WalkDirFs(fs v1.FS, root string, fn fs.WalkDirFunc) error {
198199
} else {
199200
err = walkDir(fs, root, &statDirEntry{info}, fn)
200201
}
201-
if err == filepath.SkipDir {
202+
if errors.Is(err, filepath.SkipDir) {
202203
return nil
203204
}
204205
return err
@@ -225,7 +226,7 @@ func walkDir(fs v1.FS, path string, d fs.DirEntry, walkDirFn fs.WalkDirFunc) err
225226
for _, d1 := range dirs {
226227
path1 := filepath.Join(path, d1.Name())
227228
if err := walkDir(fs, path1, d1, walkDirFn); err != nil {
228-
if err == filepath.SkipDir {
229+
if errors.Is(err, filepath.SkipDir) {
229230
break
230231
}
231232
return err

‎tests/mocks/extractor_mock.go

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ type FakeImageExtractor struct {
2323
SideEffect func(imageRef, destination, platformRef string) error
2424
}
2525

26+
func (f FakeImageExtractor) GetOCIImageSize(imageRef, platformRef string) (int64, error) {
27+
return 0, nil
28+
}
29+
2630
var _ v1.ImageExtractor = FakeImageExtractor{}
2731

2832
func NewFakeImageExtractor(logger v1.Logger) *FakeImageExtractor {

0 commit comments

Comments
 (0)
Please sign in to comment.