diff --git a/cmd/backup.go b/cmd/backup.go index ce2e600..3250baf 100644 --- a/cmd/backup.go +++ b/cmd/backup.go @@ -53,7 +53,7 @@ func (bk backupC) Run(context wisski_distillery.Context) error { if !bk.StagingOnly { // regular mode: create a temporary staging directory logging.LogMessage(context.IOStream, "Creating new snapshot staging directory") - sPath, err = dis.Snapshots().NewStagingDir("") + sPath, err = dis.SnapshotManager().NewStagingDir("") if err != nil { return errSnapshotFailed.Wrap(err) } @@ -65,7 +65,7 @@ func (bk backupC) Run(context wisski_distillery.Context) error { // staging mode: use dest as a destination sPath = bk.Positionals.Dest if sPath == "" { - sPath, err = dis.Snapshots().NewStagingDir("") + sPath, err = dis.SnapshotManager().NewStagingDir("") if err != nil { return errSnapshotFailed.Wrap(err) } @@ -100,7 +100,7 @@ func (bk backupC) Run(context wisski_distillery.Context) error { // create the archive path archivePath := bk.Positionals.Dest if archivePath == "" { - archivePath = dis.Snapshots().NewArchivePath("") + archivePath = dis.SnapshotManager().NewArchivePath("") } // and write everything into it! diff --git a/cmd/snapshot.go b/cmd/snapshot.go index dce8816..0ff0b8b 100644 --- a/cmd/snapshot.go +++ b/cmd/snapshot.go @@ -4,8 +4,8 @@ import ( "io/fs" wisski_distillery "github.com/FAU-CDI/wisski-distillery" + "github.com/FAU-CDI/wisski-distillery/internal/component/snapshots" "github.com/FAU-CDI/wisski-distillery/internal/core" - "github.com/FAU-CDI/wisski-distillery/internal/wisski" "github.com/FAU-CDI/wisski-distillery/pkg/environment" "github.com/FAU-CDI/wisski-distillery/pkg/logging" "github.com/FAU-CDI/wisski-distillery/pkg/targz" @@ -55,7 +55,7 @@ func (bi snapshot) Run(context wisski_distillery.Context) error { if !bi.StagingOnly { // regular mode: create a temporary staging directory logging.LogMessage(context.IOStream, "Creating new snapshot staging directory") - sPath, err = dis.Snapshots().NewStagingDir(instance.Slug) + sPath, err = dis.SnapshotManager().NewStagingDir(instance.Slug) if err != nil { return errSnapshotFailed.Wrap(err) } @@ -67,7 +67,7 @@ func (bi snapshot) Run(context wisski_distillery.Context) error { // staging mode: use dest as a destination sPath = bi.Positionals.Dest if sPath == "" { - sPath, err = dis.Snapshots().NewStagingDir(instance.Slug) + sPath, err = dis.SnapshotManager().NewStagingDir(instance.Slug) if err != nil { return errSnapshotFailed.Wrap(err) } @@ -87,7 +87,7 @@ func (bi snapshot) Run(context wisski_distillery.Context) error { // take a snapshot into the staging area! logging.LogOperation(func() error { - sreport := dis.Snapshot(instance, context.IOStream, wisski.SnapshotDescription{ + sreport := dis.SnapshotManager().NewSnapshot(instance, context.IOStream, snapshots.SnapshotDescription{ Dest: sPath, Keepalive: bi.Keepalive, }) @@ -107,7 +107,7 @@ func (bi snapshot) Run(context wisski_distillery.Context) error { // create the archive path archivePath := bi.Positionals.Dest if archivePath == "" { - archivePath = dis.Snapshots().NewArchivePath(instance.Slug) + archivePath = dis.SnapshotManager().NewArchivePath(instance.Slug) } // and write everything into it! diff --git a/cmd/system_update.go b/cmd/system_update.go index 0b8ffbe..057df73 100644 --- a/cmd/system_update.go +++ b/cmd/system_update.go @@ -70,8 +70,8 @@ func (si systemupdate) Run(context wisski_distillery.Context) error { for _, d := range []string{ dis.Config.DeployRoot, dis.Instances().Path(), - dis.Snapshots().StagingPath(), - dis.Snapshots().ArchivePath(), + dis.SnapshotManager().StagingPath(), + dis.SnapshotManager().ArchivePath(), } { context.Println(d) if err := dis.Core.Environment.MkdirAll(d, environment.DefaultDirPerm); err != nil { diff --git a/internal/backup/backup.go b/internal/backup/backup.go index 509a6bc..6542ddd 100644 --- a/internal/backup/backup.go +++ b/internal/backup/backup.go @@ -9,7 +9,8 @@ import ( "github.com/FAU-CDI/wisski-distillery/internal/component" "github.com/FAU-CDI/wisski-distillery/internal/component/instances" - "github.com/FAU-CDI/wisski-distillery/internal/wisski" + "github.com/FAU-CDI/wisski-distillery/internal/component/snapshots" + "github.com/FAU-CDI/wisski-distillery/internal/dis" "github.com/FAU-CDI/wisski-distillery/pkg/environment" "github.com/FAU-CDI/wisski-distillery/pkg/logging" "github.com/tkw1536/goprogram/status" @@ -18,7 +19,7 @@ import ( ) // New create a new Backup -func New(io stream.IOStream, dis *wisski.Distillery, description Description) (backup Backup) { +func New(io stream.IOStream, dis *dis.Distillery, description Description) (backup Backup) { backup.Description = description // catch anything critical that happened during the snapshot @@ -38,7 +39,7 @@ func New(io stream.IOStream, dis *wisski.Distillery, description Description) (b return } -func (backup *Backup) run(ios stream.IOStream, dis *wisski.Distillery) { +func (backup *Backup) run(ios stream.IOStream, dis *dis.Distillery) { // // MANIFEST // @@ -120,27 +121,27 @@ func (backup *Backup) run(ios stream.IOStream, dis *wisski.Distillery) { } // re-use the backup of the snapshots - backup.InstanceSnapshots = status.Group[instances.WissKI, wisski.Snapshot]{ + backup.InstanceSnapshots = status.Group[instances.WissKI, snapshots.Snapshot]{ PrefixString: func(item instances.WissKI, index int) string { return fmt.Sprintf("[snapshot %s]: ", item.Slug) }, PrefixAlign: true, - Handler: func(instance instances.WissKI, index int, writer io.Writer) wisski.Snapshot { + Handler: func(instance instances.WissKI, index int, writer io.Writer) snapshots.Snapshot { dir := filepath.Join(instancesBackupDir, instance.Slug) if err := dis.Core.Environment.Mkdir(dir, environment.DefaultDirPerm); err != nil { - return wisski.Snapshot{ + return snapshots.Snapshot{ ErrPanic: err, } } manifest <- dir - return dis.Snapshot(instance, stream.NewIOStream(writer, writer, nil, 0), wisski.SnapshotDescription{ + return dis.SnapshotManager().NewSnapshot(instance, stream.NewIOStream(writer, writer, nil, 0), snapshots.SnapshotDescription{ Dest: dir, }) }, - ResultString: func(res wisski.Snapshot, item instances.WissKI, index int) string { + ResultString: func(res snapshots.Snapshot, item instances.WissKI, index int) string { return "done" }, WaitString: status.DefaultWaitString[instances.WissKI], @@ -154,7 +155,7 @@ func (backup *Backup) run(ios stream.IOStream, dis *wisski.Distillery) { <-manifestDone // sort the instances manifest - slices.SortFunc(backup.InstanceSnapshots, func(a, b wisski.Snapshot) bool { + slices.SortFunc(backup.InstanceSnapshots, func(a, b snapshots.Snapshot) bool { return a.Instance.Slug < b.Instance.Slug }) } diff --git a/internal/backup/report.go b/internal/backup/report.go index dd3bac2..a19ab91 100644 --- a/internal/backup/report.go +++ b/internal/backup/report.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "github.com/FAU-CDI/wisski-distillery/internal/wisski" + "github.com/FAU-CDI/wisski-distillery/internal/component/snapshots" "github.com/FAU-CDI/wisski-distillery/pkg/countwriter" "github.com/FAU-CDI/wisski-distillery/pkg/environment" "github.com/FAU-CDI/wisski-distillery/pkg/logging" @@ -42,7 +42,7 @@ type Backup struct { // Snapshots containing instances InstanceListErr error - InstanceSnapshots []wisski.Snapshot + InstanceSnapshots []snapshots.Snapshot // List of files included Manifest []string diff --git a/internal/wisski/snapshot.go b/internal/component/snapshots/snapshot_make.go similarity index 88% rename from internal/wisski/snapshot.go rename to internal/component/snapshots/snapshot_make.go index 3cb9222..6eda8a8 100644 --- a/internal/wisski/snapshot.go +++ b/internal/component/snapshots/snapshot_make.go @@ -1,4 +1,4 @@ -package wisski +package snapshots import ( "encoding/json" @@ -109,7 +109,7 @@ func (snapshot Snapshot) Report(w io.Writer) (int, error) { } // Snapshot creates a new snapshot of this instance into dest -func (dis *Distillery) Snapshot(instance instances.WissKI, io stream.IOStream, desc SnapshotDescription) (snapshot Snapshot) { +func (snapshots *Manager) NewSnapshot(instance instances.WissKI, io stream.IOStream, desc SnapshotDescription) (snapshot Snapshot) { // setup the snapshot snapshot.Description = desc snapshot.Instance = instance.Instance @@ -123,8 +123,8 @@ func (dis *Distillery) Snapshot(instance instances.WissKI, io stream.IOStream, d logging.LogOperation(func() error { snapshot.StartTime = time.Now().UTC() - snapshot.makeBlackbox(io, dis, instance) - snapshot.makeWhitebox(io, dis, instance) + snapshot.makeBlackbox(io, snapshots, instance) + snapshot.makeWhitebox(io, snapshots, instance) snapshot.EndTime = time.Now().UTC() return nil @@ -136,7 +136,7 @@ func (dis *Distillery) Snapshot(instance instances.WissKI, io stream.IOStream, d // makeBlackbox runs the blackbox backup of the system. // It pauses the Instance, if a consistent state is required. -func (snapshot *Snapshot) makeBlackbox(io stream.IOStream, dis *Distillery, instance instances.WissKI) { +func (snapshot *Snapshot) makeBlackbox(io stream.IOStream, snapshots *Manager, instance instances.WissKI) { stack := instance.Barrel() og := opgroup.NewOpGroup[string](4) @@ -166,7 +166,7 @@ func (snapshot *Snapshot) makeBlackbox(io stream.IOStream, dis *Distillery, inst fmt.Fprintln(line, bkPath) files <- bkPath - info, err := dis.Core.Environment.Create(bkPath, environment.DefaultFilePerm) + info, err := snapshots.Core.Environment.Create(bkPath, environment.DefaultFilePerm) if err != nil { return err } @@ -188,7 +188,7 @@ func (snapshot *Snapshot) makeBlackbox(io stream.IOStream, dis *Distillery, inst // copy over whatever is in the base directory defer fmt.Fprintln(line, "done") - return fsx.CopyDirectory(dis.Core.Environment, fsPath, instance.FilesystemBase, func(dst, src string) { + return fsx.CopyDirectory(snapshots.Core.Environment, fsPath, instance.FilesystemBase, func(dst, src string) { fmt.Fprintln(line, dst) files <- dst }) @@ -205,14 +205,14 @@ func (snapshot *Snapshot) makeBlackbox(io stream.IOStream, dis *Distillery, inst fmt.Fprintln(line, tsPath) files <- tsPath - nquads, err := dis.Core.Environment.Create(tsPath, environment.DefaultFilePerm) + nquads, err := snapshots.Core.Environment.Create(tsPath, environment.DefaultFilePerm) if err != nil { return err } defer nquads.Close() // directly store the result - _, err = dis.Triplestore().Snapshot(nquads, instance.GraphDBRepository) + _, err = snapshots.TS.Snapshot(nquads, instance.GraphDBRepository) return err }, &snapshot.ErrTriplestore) @@ -226,14 +226,14 @@ func (snapshot *Snapshot) makeBlackbox(io stream.IOStream, dis *Distillery, inst fmt.Fprintln(line, sqlPath) files <- sqlPath - sql, err := dis.Core.Environment.Create(sqlPath, environment.DefaultFilePerm) + sql, err := snapshots.Core.Environment.Create(sqlPath, environment.DefaultFilePerm) if err != nil { return err } defer sql.Close() // directly store the result - return dis.SQL().Snapshot(io, sql, instance.SqlDatabase) + return snapshots.SQL.Snapshot(io, sql, instance.SqlDatabase) }, &snapshot.ErrSQL) // wait for the group! @@ -242,7 +242,7 @@ func (snapshot *Snapshot) makeBlackbox(io stream.IOStream, dis *Distillery, inst // makeWhitebox runs the whitebox backup of the system. // The instance should be running during this step. -func (snapshot *Snapshot) makeWhitebox(io stream.IOStream, dis *Distillery, instance instances.WissKI) { +func (snapshot *Snapshot) makeWhitebox(io stream.IOStream, snapshots *Manager, instance instances.WissKI) { og := opgroup.NewOpGroup[string](1) // write pathbuilders @@ -252,7 +252,7 @@ func (snapshot *Snapshot) makeWhitebox(io stream.IOStream, dis *Distillery, inst files <- pbPath // create the directory! - if err := dis.Core.Environment.Mkdir(pbPath, environment.DefaultDirPerm); err != nil { + if err := snapshots.Core.Environment.Mkdir(pbPath, environment.DefaultDirPerm); err != nil { return err } diff --git a/internal/component/snapshots/snapshots.go b/internal/component/snapshots/snapshots.go index 7107b66..bc7e767 100644 --- a/internal/component/snapshots/snapshots.go +++ b/internal/component/snapshots/snapshots.go @@ -6,38 +6,43 @@ import ( "time" "github.com/FAU-CDI/wisski-distillery/internal/component" + "github.com/FAU-CDI/wisski-distillery/internal/component/sql" + "github.com/FAU-CDI/wisski-distillery/internal/component/triplestore" "github.com/FAU-CDI/wisski-distillery/pkg/environment" "github.com/FAU-CDI/wisski-distillery/pkg/fsx" "github.com/FAU-CDI/wisski-distillery/pkg/password" ) -// Snapshots manages snapshots and backups -type Snapshots struct { +// Manager manages snapshots and backups +type Manager struct { component.ComponentBase + + TS *triplestore.Triplestore + SQL *sql.SQL } -func (Snapshots) Name() string { return "snapshots" } +func (Manager) Name() string { return "snapshots" } // Path returns the path that contains all snapshot related data. -func (dis *Snapshots) Path() string { +func (dis *Manager) Path() string { return filepath.Join(dis.Config.DeployRoot, "snapshots") } // StagingPath returns the path to the directory containing a temporary staging area for snapshots. // Use NewSnapshotStagingDir to generate a new staging area. -func (dis *Snapshots) StagingPath() string { +func (dis *Manager) StagingPath() string { return filepath.Join(dis.Path(), "staging") } // ArchivePath returns the path to the directory containing all exported archives. // Use NewSnapshotArchivePath to generate a path to a new archive in this directory. -func (dis *Snapshots) ArchivePath() string { +func (dis *Manager) ArchivePath() string { return filepath.Join(dis.Path(), "archives") } // NewArchivePath returns the path to a new archive with the provided prefix. // The path is guaranteed to not exist. -func (dis *Snapshots) NewArchivePath(prefix string) (path string) { +func (dis *Manager) NewArchivePath(prefix string) (path string) { // TODO: Consider moving these into a subdirectory with the provided prefix. for path == "" || fsx.Exists(dis.Environment, path) { name := dis.newSnapshotName(prefix) + ".tar.gz" @@ -48,7 +53,7 @@ func (dis *Snapshots) NewArchivePath(prefix string) (path string) { // newSnapshot name returns a new basename for a snapshot with the provided prefix. // The name is guaranteed to be unique within this process. -func (*Snapshots) newSnapshotName(prefix string) string { +func (*Manager) newSnapshotName(prefix string) string { suffix, _ := password.Password(64) // silently ignore any errors! if prefix == "" { prefix = "backup" @@ -60,7 +65,7 @@ func (*Snapshots) newSnapshotName(prefix string) string { // NewStagingDir returns the path to a new snapshot directory. // The directory is guaranteed to have been freshly created. -func (dis *Snapshots) NewStagingDir(prefix string) (path string, err error) { +func (dis *Manager) NewStagingDir(prefix string) (path string, err error) { for path == "" || environment.IsExist(err) { path = filepath.Join(dis.StagingPath(), dis.newSnapshotName(prefix)) err = dis.Core.Environment.Mkdir(path, environment.DefaultFilePerm) diff --git a/internal/wisski/backup_prune.go b/internal/dis/backup_prune.go similarity index 94% rename from internal/wisski/backup_prune.go rename to internal/dis/backup_prune.go index 2cfc2a1..c31f7bd 100644 --- a/internal/wisski/backup_prune.go +++ b/internal/dis/backup_prune.go @@ -1,4 +1,4 @@ -package wisski +package dis import ( "path/filepath" @@ -14,7 +14,7 @@ func (dis *Distillery) ShouldPrune(modtime time.Time) bool { // PruneBackups prunes all backups older than the maximum backup age func (dis *Distillery) PruneBackups(io stream.IOStream) error { - sPath := dis.Snapshots().ArchivePath() + sPath := dis.SnapshotManager().ArchivePath() // list all the files entries, err := dis.Core.Environment.ReadDir(sPath) diff --git a/internal/wisski/component.go b/internal/dis/component.go similarity index 94% rename from internal/wisski/component.go rename to internal/dis/component.go index 4368027..c4eab01 100644 --- a/internal/wisski/component.go +++ b/internal/dis/component.go @@ -1,4 +1,4 @@ -package wisski +package dis import ( "time" @@ -30,7 +30,7 @@ type components struct { // other components instances lazy.Lazy[*instances.Instances] - snapshots lazy.Lazy[*snapshots.Snapshots] + snapshots lazy.Lazy[*snapshots.Manager] } // @@ -75,9 +75,10 @@ func (dis *Distillery) Instances() *instances.Instances { }) } -func (dis *Distillery) Snapshots() *snapshots.Snapshots { - return component.Initialize(dis.Core, &dis.components.snapshots, func(snapshots *snapshots.Snapshots) { - +func (dis *Distillery) SnapshotManager() *snapshots.Manager { + return component.Initialize(dis.Core, &dis.components.snapshots, func(snapshots *snapshots.Manager) { + snapshots.SQL = dis.SQL() + snapshots.TS = dis.Triplestore() }) } diff --git a/internal/wisski/distillery.go b/internal/dis/distillery.go similarity index 98% rename from internal/wisski/distillery.go rename to internal/dis/distillery.go index e73ce30..a32a594 100644 --- a/internal/wisski/distillery.go +++ b/internal/dis/distillery.go @@ -1,4 +1,4 @@ -package wisski +package dis import ( "context" diff --git a/internal/wisski/init.go b/internal/dis/init.go similarity index 99% rename from internal/wisski/init.go rename to internal/dis/init.go index d747ae3..4abe8b9 100644 --- a/internal/wisski/init.go +++ b/internal/dis/init.go @@ -1,4 +1,4 @@ -package wisski +package dis import ( "github.com/FAU-CDI/wisski-distillery/internal/component" diff --git a/program.go b/program.go index cae3827..39e21c9 100644 --- a/program.go +++ b/program.go @@ -4,14 +4,14 @@ import ( "os/user" "github.com/FAU-CDI/wisski-distillery/internal/core" - "github.com/FAU-CDI/wisski-distillery/internal/wisski" + "github.com/FAU-CDI/wisski-distillery/internal/dis" "github.com/tkw1536/goprogram" "github.com/tkw1536/goprogram/exit" ) // these define the ggman-specific program types // none of these are strictly needed, they're just around for convenience -type wdcliEnv = *wisski.Distillery +type wdcliEnv = *dis.Distillery type wdcliParameters = core.Params type wdcliRequirements = core.Requirements type wdCliFlags = core.Flags @@ -49,7 +49,7 @@ func NewProgram() Program { }, NewEnvironment: func(params wdcliParameters, context Context) (e wdcliEnv, err error) { - return wisski.NewDistillery(params, context.Args.Flags, context.Description.Requirements) + return dis.NewDistillery(params, context.Args.Flags, context.Description.Requirements) }, } }