Skip to content

Commit

Permalink
feat: support initializing timestamp files
Browse files Browse the repository at this point in the history
  • Loading branch information
suzuki-shunsuke committed Jan 22, 2025
1 parent c4a67f2 commit cc1859f
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 2 deletions.
17 changes: 16 additions & 1 deletion pkg/cli/vacuum/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package vacuum
import (
"errors"
"fmt"
"net/http"

"github.com/aquaproj/aqua/v2/pkg/cli/profile"
"github.com/aquaproj/aqua/v2/pkg/cli/util"
Expand Down Expand Up @@ -35,6 +36,12 @@ func New(r *util.Param) *cli.Command {
Aliases: []string{"v"},
Description: description,
Action: i.action,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "init",
Usage: "Create timestamp files.",
},
},
}
}

Expand All @@ -52,8 +59,16 @@ func (i *command) action(c *cli.Context) error {
return fmt.Errorf("parse the command line arguments: %w", err)
}

if c.Bool("init") {
ctrl := controller.InitializeVacuumInitCommandController(c.Context, param, i.r.Runtime, &http.Client{})
if err := ctrl.Init(c.Context, logE, param); err != nil {
return err //nolint:wrapcheck
}
return nil
}

if param.VacuumDays == 0 {
return errors.New("vacuum is not enabled, please set the AQUA_VACUUM_DAYS environment variable")
return errors.New("vacuum-days is required")
}

ctrl := controller.InitializeVacuumCommandController(c.Context, param, i.r.Runtime)
Expand Down
52 changes: 52 additions & 0 deletions pkg/controller/vacuum/initialize/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package initialize

import (
"context"
"time"

"github.com/aquaproj/aqua/v2/pkg/checksum"
"github.com/aquaproj/aqua/v2/pkg/config"
"github.com/aquaproj/aqua/v2/pkg/config/aqua"
"github.com/aquaproj/aqua/v2/pkg/config/registry"
"github.com/aquaproj/aqua/v2/pkg/runtime"
"github.com/sirupsen/logrus"
"github.com/spf13/afero"
)

type Controller struct {
rootDir string
runtime *runtime.Runtime
fs afero.Fs
vacuum Vacuum
configFinder ConfigFinder
configReader ConfigReader
registryInstaller RegistryInstaller
}

func New(param *config.Param, rt *runtime.Runtime, fs afero.Fs, vc Vacuum, configFinder ConfigFinder, configReader ConfigReader, registryInstaller RegistryInstaller) *Controller {
return &Controller{
rootDir: param.RootDir,
runtime: rt,
fs: fs,
vacuum: vc,
configFinder: configFinder,
configReader: configReader,
registryInstaller: registryInstaller,
}
}

type Vacuum interface {
Create(pkgPath string, timestamp time.Time) error
}

type ConfigReader interface {
Read(logE *logrus.Entry, configFilePath string, cfg *aqua.Config) error
}

type ConfigFinder interface {
Finds(wd, configFilePath string) []string
}

type RegistryInstaller interface {
InstallRegistries(ctx context.Context, logE *logrus.Entry, cfg *aqua.Config, cfgFilePath string, checksums *checksum.Checksums) (map[string]*registry.Config, error)
}
77 changes: 77 additions & 0 deletions pkg/controller/vacuum/initialize/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package initialize

import (
"context"
"fmt"
"time"

"github.com/aquaproj/aqua/v2/pkg/checksum"
"github.com/aquaproj/aqua/v2/pkg/config"
finder "github.com/aquaproj/aqua/v2/pkg/config-finder"
"github.com/aquaproj/aqua/v2/pkg/config/aqua"
"github.com/sirupsen/logrus"
"github.com/suzuki-shunsuke/logrus-error/logerr"
)

func (c *Controller) Init(ctx context.Context, logE *logrus.Entry, param *config.Param) error {
for _, cfgFilePath := range c.configFinder.Finds(param.PWD, param.ConfigFilePath) {
if err := c.create(ctx, logE, cfgFilePath, param); err != nil {
return err
}
}
for _, cfgFilePath := range param.GlobalConfigFilePaths {
if _, err := c.fs.Stat(cfgFilePath); err != nil {
continue
}
if err := c.create(ctx, logE, cfgFilePath, param); err != nil {
return err
}
}
return nil
}

func (c *Controller) create(ctx context.Context, logE *logrus.Entry, cfgFilePath string, param *config.Param) error { //nolint:cyclop
cfg := &aqua.Config{}
if cfgFilePath == "" {
return finder.ErrConfigFileNotFound
}
if err := c.configReader.Read(logE, cfgFilePath, cfg); err != nil {
return err //nolint:wrapcheck
}

var checksums *checksum.Checksums
if cfg.ChecksumEnabled(param.EnforceChecksum, param.Checksum) {
checksums = checksum.New()
checksumFilePath, err := checksum.GetChecksumFilePathFromConfigFilePath(c.fs, cfgFilePath)
if err != nil {
return err //nolint:wrapcheck
}
if err := checksums.ReadFile(c.fs, checksumFilePath); err != nil {
return fmt.Errorf("read a checksum JSON: %w", err)
}
defer func() {
if err := checksums.UpdateFile(c.fs, checksumFilePath); err != nil {
logE.WithError(err).Error("update a checksum file")
}
}()
}

registryContents, err := c.registryInstaller.InstallRegistries(ctx, logE, cfg, cfgFilePath, checksums)
if err != nil {
return err //nolint:wrapcheck
}

pkgs, _ := config.ListPackages(logE, cfg, c.runtime, registryContents)
now := time.Now()
for _, pkg := range pkgs {
pkgPath, err := pkg.PkgPath(c.runtime)
if err != nil {
logerr.WithError(logE, err).Warn("get a package path")
continue
}
if err := c.vacuum.Create(pkgPath, now); err != nil {
logerr.WithError(logE, err).Warn("create a timestamp file")
}
}
return nil
}
58 changes: 58 additions & 0 deletions pkg/controller/wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/aquaproj/aqua/v2/pkg/controller/updateaqua"
"github.com/aquaproj/aqua/v2/pkg/controller/updatechecksum"
cvacuum "github.com/aquaproj/aqua/v2/pkg/controller/vacuum"
"github.com/aquaproj/aqua/v2/pkg/controller/vacuum/initialize"
"github.com/aquaproj/aqua/v2/pkg/controller/which"
"github.com/aquaproj/aqua/v2/pkg/cosign"
"github.com/aquaproj/aqua/v2/pkg/domain"
Expand Down Expand Up @@ -1071,3 +1072,60 @@ func InitializeVacuumCommandController(ctx context.Context, param *config.Param,
)
return &cvacuum.Controller{}
}

func InitializeVacuumInitCommandController(ctx context.Context, param *config.Param, rt *runtime.Runtime, httpClient *http.Client) *initialize.Controller {
wire.Build(
initialize.New,
afero.NewOsFs,
wire.NewSet(
vacuum.New,
wire.Bind(new(initialize.Vacuum), new(*vacuum.Client)),
),
wire.NewSet(
finder.NewConfigFinder,
wire.Bind(new(initialize.ConfigFinder), new(*finder.ConfigFinder)),
),
wire.NewSet(
reader.New,
wire.Bind(new(initialize.ConfigReader), new(*reader.ConfigReader)),
),
wire.NewSet(
registry.New,
wire.Bind(new(initialize.RegistryInstaller), new(*registry.Installer)),
),
wire.NewSet(
github.New,
wire.Bind(new(github.RepositoriesService), new(*github.RepositoriesServiceImpl)),
wire.Bind(new(download.GitHubContentAPI), new(*github.RepositoriesServiceImpl)),
),
wire.NewSet(
download.NewGitHubContentFileDownloader,
wire.Bind(new(registry.GitHubContentFileDownloader), new(*download.GitHubContentFileDownloader)),
),
download.NewHTTPDownloader,
wire.NewSet(
download.NewDownloader,
wire.Bind(new(download.ClientAPI), new(*download.Downloader)),
),
wire.NewSet(
cosign.NewVerifier,
wire.Bind(new(installpackage.CosignVerifier), new(*cosign.Verifier)),
wire.Bind(new(registry.CosignVerifier), new(*cosign.Verifier)),
),
wire.NewSet(
osexec.New,
wire.Bind(new(cosign.Executor), new(*osexec.Executor)),
wire.Bind(new(slsa.CommandExecutor), new(*osexec.Executor)),
),
wire.NewSet(
slsa.New,
wire.Bind(new(installpackage.SLSAVerifier), new(*slsa.Verifier)),
wire.Bind(new(registry.SLSAVerifier), new(*slsa.Verifier)),
),
wire.NewSet(
slsa.NewExecutor,
wire.Bind(new(slsa.Executor), new(*slsa.ExecutorImpl)),
),
)
return &initialize.Controller{}
}
19 changes: 19 additions & 0 deletions pkg/controller/wire_gen.go

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

17 changes: 16 additions & 1 deletion pkg/vacuum/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,25 @@ func (c *Client) Remove(pkgPath string) error {

func (c *Client) Update(pkgPath string, timestamp time.Time) error {
dir := c.dir(pkgPath)
file := filepath.Join(dir, fileName)
return c.update(file, dir, timestamp)
}

func (c *Client) Create(pkgPath string, timestamp time.Time) error {
dir := c.dir(pkgPath)
file := filepath.Join(dir, fileName)
if f, err := afero.Exists(c.fs, file); err != nil {
return fmt.Errorf("check whether a package timestamp file exists: %w", err)
} else if f {
return nil
}
return c.update(file, dir, timestamp)
}

func (c *Client) update(file, dir string, timestamp time.Time) error {
if err := osfile.MkdirAll(c.fs, dir); err != nil {
return fmt.Errorf("create a package metadata directory: %w", err)
}
file := filepath.Join(dir, fileName)
timestampStr := timestamp.Format(time.RFC3339)
if err := afero.WriteFile(c.fs, file, []byte(timestampStr+"\n"), filePermission); err != nil {
return fmt.Errorf("create a package timestamp file: %w", err)
Expand Down

0 comments on commit cc1859f

Please sign in to comment.