diff --git a/cmd/purge.go b/cmd/purge.go index cea26a0..70714e9 100644 --- a/cmd/purge.go +++ b/cmd/purge.go @@ -71,7 +71,7 @@ func (p purge) Run(context wisski_distillery.Context) error { // remove the filesystem logging.LogMessage(context.IOStream, "Removing from filesystem %s", instance.FilesystemBase) - if err := dis.Core.Environment.RemoveAll(instance.FilesystemBase); err != nil { + if err := dis.Still.Environment.RemoveAll(instance.FilesystemBase); err != nil { context.EPrintln(err) } diff --git a/cmd/server.go b/cmd/server.go index dea3dd0..56bfc63 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -41,7 +41,7 @@ func (s server) Run(context wisski_distillery.Context) error { context.Printf("Listening on %s\n", s.Bind) // make a new listener - listener, err := dis.Core.Environment.Listen("tcp", s.Bind) + listener, err := dis.Still.Environment.Listen("tcp", s.Bind) if err != nil { return errServerListen.Wrap(err) } diff --git a/cmd/system_update.go b/cmd/system_update.go index 80acaf9..99613c1 100644 --- a/cmd/system_update.go +++ b/cmd/system_update.go @@ -74,7 +74,7 @@ func (si systemupdate) Run(context wisski_distillery.Context) error { dis.Exporter().ArchivePath(), } { context.Println(d) - if err := dis.Core.Environment.MkdirAll(d, environment.DefaultDirPerm); err != nil { + if err := dis.Still.Environment.MkdirAll(d, environment.DefaultDirPerm); err != nil { return errBoostrapFailedToCreateDirectory.WithMessageF(d, err) } } @@ -166,7 +166,7 @@ func (si systemupdate) mustExec(context wisski_distillery.Context, workdir strin if workdir == "" { workdir = context.Environment.Config.DeployRoot } - code := dis.Core.Environment.Exec(context.IOStream, workdir, exe, argv...) + code := dis.Still.Environment.Exec(context.IOStream, workdir, exe, argv...) if code != 0 { err := errMustExecFailed.WithMessageF(code) err.ExitCode = exit.ExitCode(code) diff --git a/internal/component/component.go b/internal/component/component.go index 4be5a39..783e33a 100644 --- a/internal/component/component.go +++ b/internal/component/component.go @@ -10,20 +10,11 @@ package component // // Components are initialized using a [Pool]. type Component interface { - // Name returns the name of this component. - // It should correspond to the appropriate subpackage. + // Name returns the name of this component + // Name should be implemented by the [ComponentBase] struct. Name() string - // getBase returns the embedded ComponentBase struct. - getBase() *ComponentBase -} - -// ComponentBase should be embedded into every component -type ComponentBase struct { - Core // the underlying stillage of the distillery -} - -//lint:ignore U1000 used to implement the private methods of [Component] -func (cb *ComponentBase) getBase() *ComponentBase { - return cb + // getComponentBase returns the underlying ComponentBase object of this Component. + // It is used internally during initialization + getComponentBase() *ComponentBase } diff --git a/internal/component/control/control.go b/internal/component/control/control.go index 87fdcbb..a832f6f 100644 --- a/internal/component/control/control.go +++ b/internal/component/control/control.go @@ -16,12 +16,8 @@ type Control struct { Servables []component.Servable } -func (control Control) Name() string { - return "dis" // TODO: Rename this to control! -} - func (control Control) Path() string { - return filepath.Join(control.Core.Config.DeployRoot, "core", control.Name()) + return filepath.Join(control.Still.Config.DeployRoot, "core", "dis") } //go:embed all:control control.env diff --git a/internal/component/core.go b/internal/component/core.go deleted file mode 100644 index e0319da..0000000 --- a/internal/component/core.go +++ /dev/null @@ -1,11 +0,0 @@ -package component - -import ( - "github.com/FAU-CDI/wisski-distillery/internal/config" - "github.com/FAU-CDI/wisski-distillery/pkg/environment" -) - -type Core struct { - Environment environment.Environment // environment to use for reading / writing to and from the distillery - Config *config.Config // the configuration of the distillery -} diff --git a/internal/component/exporter/exporter.go b/internal/component/exporter/exporter.go index 547fe4a..69dec72 100644 --- a/internal/component/exporter/exporter.go +++ b/internal/component/exporter/exporter.go @@ -27,8 +27,6 @@ type Exporter struct { Backupable []component.Backupable } -func (Exporter) Name() string { return "snapshots" } - // Path returns the path that contains all snapshot related data. func (dis *Exporter) Path() string { return filepath.Join(dis.Config.DeployRoot, "snapshots") @@ -74,7 +72,7 @@ func (*Exporter) newSnapshotName(prefix string) string { func (dis *Exporter) 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) + err = dis.Still.Environment.Mkdir(path, environment.DefaultFilePerm) } if err != nil { path = "" diff --git a/internal/component/exporter/extras_bookkeeping.go b/internal/component/exporter/extras_bookkeeping.go index 16bebc5..edf5de0 100644 --- a/internal/component/exporter/extras_bookkeeping.go +++ b/internal/component/exporter/extras_bookkeeping.go @@ -12,8 +12,6 @@ type Bookkeeping struct { component.ComponentBase } -func (Bookkeeping) Name() string { return "bookkeeping" } - // SnapshotNeedsRunning returns if this Snapshotable requires a running instance. func (Bookkeeping) SnapshotNeedsRunning() bool { return false } diff --git a/internal/component/exporter/extras_config.go b/internal/component/exporter/extras_config.go index cde4791..f2bb26d 100644 --- a/internal/component/exporter/extras_config.go +++ b/internal/component/exporter/extras_config.go @@ -11,8 +11,6 @@ type Config struct { component.ComponentBase } -func (Config) Name() string { return "config" } - func (*Config) BackupName() string { return "config" } diff --git a/internal/component/exporter/extras_filesystem.go b/internal/component/exporter/extras_filesystem.go index 4812641..ffec88b 100644 --- a/internal/component/exporter/extras_filesystem.go +++ b/internal/component/exporter/extras_filesystem.go @@ -10,8 +10,6 @@ type Filesystem struct { component.ComponentBase } -func (Filesystem) Name() string { return "filesystem" } - // SnapshotNeedsRunning returns if this Snapshotable requires a running instance. func (Filesystem) SnapshotNeedsRunning() bool { return false } diff --git a/internal/component/exporter/extras_pathbuilders.go b/internal/component/exporter/extras_pathbuilders.go index 0a7862f..4cab5b6 100644 --- a/internal/component/exporter/extras_pathbuilders.go +++ b/internal/component/exporter/extras_pathbuilders.go @@ -13,8 +13,6 @@ type Pathbuilders struct { Instances *instances.Instances } -func (Pathbuilders) Name() string { return "pathbuilders" } - func (Pathbuilders) SnapshotNeedsRunning() bool { return true } func (Pathbuilders) SnapshotName() string { return "pathbuilders" } diff --git a/internal/component/exporter/logger/logger.go b/internal/component/exporter/logger/logger.go index 5efa16a..3eb71ae 100644 --- a/internal/component/exporter/logger/logger.go +++ b/internal/component/exporter/logger/logger.go @@ -15,8 +15,6 @@ type Logger struct { SQL *sql.SQL } -func (*Logger) Name() string { return "snapshots-log" } - // For retrieves (and prunes) the ExportLog. // Slug determines if entries for Backups (empty slug) // or a specific Instance (non-empty slug) are returned. @@ -48,7 +46,7 @@ func (log *Logger) Log() ([]models.Export, error) { // partition out the exports that have been deleted! parts := collection.Partition(exports, func(s models.Export) bool { - _, err := log.Core.Environment.Stat(s.Path) + _, err := log.Still.Environment.Stat(s.Path) return !environment.IsNotExist(err) }) diff --git a/internal/component/exporter/prune.go b/internal/component/exporter/prune.go index 211ca3b..673eb7b 100644 --- a/internal/component/exporter/prune.go +++ b/internal/component/exporter/prune.go @@ -18,7 +18,7 @@ func (exporter *Exporter) PruneExports(io stream.IOStream) error { sPath := exporter.ArchivePath() // list all the files - entries, err := exporter.Core.Environment.ReadDir(sPath) + entries, err := exporter.Still.Environment.ReadDir(sPath) if err != nil { return err } @@ -44,7 +44,7 @@ func (exporter *Exporter) PruneExports(io stream.IOStream) error { path := filepath.Join(sPath, entry.Name()) io.Printf("Removing %s cause it is older than %d days", path, exporter.Config.MaxBackupAge) - if err := exporter.Core.Environment.Remove(path); err != nil { + if err := exporter.Still.Environment.Remove(path); err != nil { return err } } diff --git a/internal/component/home/home.go b/internal/component/home/home.go index d607d57..533fa7c 100644 --- a/internal/component/home/home.go +++ b/internal/component/home/home.go @@ -24,8 +24,6 @@ type Home struct { homeBytes lazy.Lazy[[]byte] } -func (*Home) Name() string { return "home" } - func (*Home) Routes() []string { return []string{"/"} } func (home *Home) Handler(route string, context context.Context, io stream.IOStream) (http.Handler, error) { diff --git a/internal/component/info/info.go b/internal/component/info/info.go index bd07a0f..beed7e2 100644 --- a/internal/component/info/info.go +++ b/internal/component/info/info.go @@ -21,8 +21,6 @@ type Info struct { SnapshotsLog *logger.Logger } -func (Info) Name() string { return "control-info" } - func (*Info) Routes() []string { return []string{"/dis/"} } func (info *Info) Handler(route string, context context.Context, io stream.IOStream) (http.Handler, error) { diff --git a/internal/component/instances/instances.go b/internal/component/instances/instances.go index d058703..9bfd53c 100644 --- a/internal/component/instances/instances.go +++ b/internal/component/instances/instances.go @@ -27,12 +27,8 @@ type Instances struct { ExporterLog *logger.Logger } -func (Instances) Name() string { - return "instances" -} - func (instances *Instances) Path() string { - return filepath.Join(instances.Core.Config.DeployRoot, instances.Name()) + return filepath.Join(instances.Still.Config.DeployRoot, "instances") } // ErrWissKINotFound is returned when a WissKI is not found @@ -45,7 +41,7 @@ var errSQL = exit.Error{ // use uses the non-nil wisski instance with this instances func (instances *Instances) use(wisski *wisski.WissKI) { - wisski.Core = instances.Core + wisski.Core = instances.Still wisski.SQL = instances.SQL wisski.TS = instances.TS wisski.Meta = instances.Meta diff --git a/internal/component/instances/runtime.go b/internal/component/instances/runtime.go index ee6010e..554db5c 100644 --- a/internal/component/instances/runtime.go +++ b/internal/component/instances/runtime.go @@ -20,7 +20,7 @@ var runtimeResources embed.FS // Update installs or updates runtime components needed by this component. func (instances *Instances) Update(stream stream.IOStream) error { - err := unpack.InstallDir(instances.Core.Environment, instances.Config.RuntimeDir(), "runtime", runtimeResources, func(dst, src string) { + err := unpack.InstallDir(instances.Still.Environment, instances.Config.RuntimeDir(), "runtime", runtimeResources, func(dst, src string) { stream.Printf("[copy] %s\n", dst) }) if err != nil { diff --git a/internal/component/meta/meta.go b/internal/component/meta/meta.go index b43098a..694ed6e 100644 --- a/internal/component/meta/meta.go +++ b/internal/component/meta/meta.go @@ -17,8 +17,6 @@ type Meta struct { sc map[string]*Storage } -func (*Meta) Name() string { return "metadata" } - // Storage returns a Storage for the instance with the given slug. // When slug is nil, returns a global storage. func (meta *Meta) Storage(slug string) *Storage { diff --git a/internal/component/pool.go b/internal/component/pool.go index 3ea1fcc..80f16dd 100644 --- a/internal/component/pool.go +++ b/internal/component/pool.go @@ -7,14 +7,16 @@ import ( ) type ComponentPool struct { - pool lazy.Pool[Component, Core] + pool lazy.Pool[Component, Still] poolInit sync.Once } func (pool *ComponentPool) init() { pool.poolInit.Do(func() { - pool.pool.Init = func(component Component, core Core) Component { - component.getBase().Core = core + pool.pool.Init = func(component Component, core Still) Component { + base := component.getComponentBase() + base.Still = core + base.name = nameOf(component) return component } }) @@ -23,7 +25,7 @@ func (pool *ComponentPool) init() { type ComponentPoolContext = *lazy.PoolContext[Component] type ComponentAllFunc = func(context ComponentPoolContext) []Component -func (pool *ComponentPool) All(core Core, init func(context ComponentPoolContext) []Component) []Component { +func (pool *ComponentPool) All(core Still, init func(context ComponentPoolContext) []Component) []Component { pool.init() return pool.pool.All(core, init) } @@ -43,7 +45,7 @@ func (pool *ComponentPool) All(core Core, init func(context ComponentPoolContext // Furthermore, the init function may not cause other components to be initialized. // // The init function may be nil, indicating that no additional initialization is required. -func MakeComponent[C Component](context ComponentPoolContext, core Core, init func(component C)) C { +func MakeComponent[C Component](context ComponentPoolContext, core Still, init func(component C)) C { return lazy.Make(context, init) } @@ -51,16 +53,16 @@ func MakeComponent[C Component](context ComponentPoolContext, core Core, init fu // // All should be the function of the core that initializes all components. // All should only make calls to [InitComponent]. -func ExportComponents[C Component](pool *ComponentPool, core Core, All ComponentAllFunc) []C { +func ExportComponents[C Component](pool *ComponentPool, core Still, All ComponentAllFunc) []C { pool.init() - return lazy.ExportComponents[Component, Core, C](&pool.pool, core, All) + return lazy.ExportComponents[Component, Still, C](&pool.pool, core, All) } // ExportComponent exports the first component that is a C from the pool. // // All should be the function of the core that initializes all components. // All should only make calls to [InitComponent]. -func ExportComponent[C Component](pool *ComponentPool, core Core, All ComponentAllFunc) C { +func ExportComponent[C Component](pool *ComponentPool, core Still, All ComponentAllFunc) C { pool.init() - return lazy.ExportComponent[Component, Core, C](&pool.pool, core, All) + return lazy.ExportComponent[Component, Still, C](&pool.pool, core, All) } diff --git a/internal/component/resolver/resolver.go b/internal/component/resolver/resolver.go index bedef61..a3cc13c 100644 --- a/internal/component/resolver/resolver.go +++ b/internal/component/resolver/resolver.go @@ -26,8 +26,6 @@ type Resolver struct { handler lazy.Lazy[wdresolve.ResolveHandler] // handler } -func (*Resolver) Name() string { return "resolver" } - func (resolver *Resolver) Routes() []string { return []string{"/go/", "/wisski/get/"} } func (resolver *Resolver) Handler(route string, context context.Context, io stream.IOStream) (http.Handler, error) { diff --git a/internal/component/sql/connect.go b/internal/component/sql/connect.go index 7f99ae1..7d63f82 100644 --- a/internal/component/sql/connect.go +++ b/internal/component/sql/connect.go @@ -133,7 +133,7 @@ func (sql *SQL) network() string { // this seems like a bit of a hack, but it works for now. name = fmt.Sprintf("sql-network-%d", atomic.AddUint64(&proxyNameCounter, 1)) mysqldriver.RegisterDialContext(name, func(ctx context.Context, addr string) (net.Conn, error) { - return sql.Core.Environment.DialContext(ctx, network, addr) + return sql.Still.Environment.DialContext(ctx, network, addr) }) return }) diff --git a/internal/component/sql/sql.go b/internal/component/sql/sql.go index acbcbf4..270bc69 100644 --- a/internal/component/sql/sql.go +++ b/internal/component/sql/sql.go @@ -22,12 +22,8 @@ type SQL struct { lazyNetwork lazy.Lazy[string] } -func (*SQL) Name() string { - return "sql" -} - func (sql *SQL) Path() string { - return filepath.Join(sql.Core.Config.DeployRoot, "core", sql.Name()) + return filepath.Join(sql.Still.Config.DeployRoot, "core", "sql") } func (*SQL) Context(parent component.InstallationContext) component.InstallationContext { diff --git a/internal/component/ssh/ssh.go b/internal/component/ssh/ssh.go index 0c07a0b..f2fbbe1 100644 --- a/internal/component/ssh/ssh.go +++ b/internal/component/ssh/ssh.go @@ -12,15 +12,11 @@ type SSH struct { component.ComponentBase } -func (SSH) Name() string { - return "ssh" +func (ssh *SSH) Path() string { + return filepath.Join(ssh.Still.Config.DeployRoot, "core", "ssh") } -func (ssh SSH) Path() string { - return filepath.Join(ssh.Core.Config.DeployRoot, "core", ssh.Name()) -} - -func (SSH) Context(parent component.InstallationContext) component.InstallationContext { +func (*SSH) Context(parent component.InstallationContext) component.InstallationContext { return parent } diff --git a/internal/component/static/static.go b/internal/component/static/static.go index 2555298..c643bfd 100644 --- a/internal/component/static/static.go +++ b/internal/component/static/static.go @@ -15,8 +15,6 @@ type Static struct { component.ComponentBase } -func (*Static) Name() string { return "static" } - func (*Static) Routes() []string { return []string{"/static/"} } //go:embed dist diff --git a/internal/component/still.go b/internal/component/still.go new file mode 100644 index 0000000..edfa56c --- /dev/null +++ b/internal/component/still.go @@ -0,0 +1,36 @@ +package component + +import ( + "reflect" + "strings" + + "github.com/FAU-CDI/wisski-distillery/internal/config" + "github.com/FAU-CDI/wisski-distillery/pkg/environment" +) + +// ComponentBase is embedded into every Component +type ComponentBase struct { + name string // name is the name of this component + Still // the underlying still of the distillery +} + +//lint:ignore U1000 used to implement the private methods of [Component] +func (cb *ComponentBase) getComponentBase() *ComponentBase { + return cb +} + +func (cb ComponentBase) Name() string { + return cb.name +} + +// nameOf returns the name of the given component +func nameOf(component Component) string { + return strings.ToLower(reflect.TypeOf(component).Elem().Name()) +} + +// Still represents the central part of a distillery. +// It is used inside the main distillery struct, as well as every component via [ComponentBase]. +type Still struct { + Environment environment.Environment // environment to use for reading / writing to and from the distillery + Config *config.Config // the configuration of the distillery +} diff --git a/internal/component/triplestore/triplestore.go b/internal/component/triplestore/triplestore.go index bb52708..435ff27 100644 --- a/internal/component/triplestore/triplestore.go +++ b/internal/component/triplestore/triplestore.go @@ -19,12 +19,8 @@ type Triplestore struct { PollInterval time.Duration // duration to wait for during wait } -func (Triplestore) Name() string { - return "triplestore" -} - -func (ts Triplestore) Path() string { - return filepath.Join(ts.Core.Config.DeployRoot, "core", ts.Name()) +func (ts *Triplestore) Path() string { + return filepath.Join(ts.Still.Config.DeployRoot, "core", "triplestore") } func (Triplestore) Context(parent component.InstallationContext) component.InstallationContext { diff --git a/internal/component/web/web.go b/internal/component/web/web.go index 32754c0..ccb9abb 100644 --- a/internal/component/web/web.go +++ b/internal/component/web/web.go @@ -15,16 +15,11 @@ type Web struct { component.ComponentBase } -func (Web) Name() string { - return "web" +func (web *Web) Path() string { + return filepath.Join(web.Still.Config.DeployRoot, "core", "web") } -func (web Web) Path() string { - res := filepath.Join(web.Core.Config.DeployRoot, "core", web.Name()) - return res -} - -func (Web) Context(parent component.InstallationContext) component.InstallationContext { +func (*Web) Context(parent component.InstallationContext) component.InstallationContext { return parent } diff --git a/internal/dis/component.go b/internal/dis/component.go index 408f1c6..34822aa 100644 --- a/internal/dis/component.go +++ b/internal/dis/component.go @@ -70,11 +70,11 @@ type initFunc = func(dis *Distillery, context component.ComponentPoolContext) co // manual initializes a component from the provided distillery. func manual[C component.Component](init func(component C)) initFunc { return func(dis *Distillery, context component.ComponentPoolContext) component.Component { - return component.MakeComponent(context, dis.Core, init) + return component.MakeComponent(context, dis.Still, init) } } // use is like r, but does not provided additional initialization func auto[C component.Component](dis *Distillery, context component.ComponentPoolContext) component.Component { - return component.MakeComponent[C](context, dis.Core, nil) + return component.MakeComponent[C](context, dis.Still, nil) } diff --git a/internal/dis/distillery.go b/internal/dis/distillery.go index c3b7870..d658f73 100644 --- a/internal/dis/distillery.go +++ b/internal/dis/distillery.go @@ -19,7 +19,7 @@ import ( // It is the main structure used to interact with different components. type Distillery struct { // core holds the core of the distillery - component.Core + component.Still // internal context for the distillery context context.Context @@ -54,7 +54,7 @@ func (dis *Distillery) Context() context.Context { func e[C component.Component](dis *Distillery) C { return component.ExportComponent[C]( &dis.pool, - dis.Core, + dis.Still, dis.register, ) } @@ -62,7 +62,7 @@ func e[C component.Component](dis *Distillery) C { func ea[C component.Component](dis *Distillery) []C { return component.ExportComponents[C]( &dis.pool, - dis.Core, + dis.Still, dis.register, ) } diff --git a/internal/dis/init.go b/internal/dis/init.go index 97febf2..18fdacc 100644 --- a/internal/dis/init.go +++ b/internal/dis/init.go @@ -22,7 +22,7 @@ var errOpenConfig = exit.Error{ func NewDistillery(params cli.Params, flags cli.Flags, req cli.Requirements) (dis *Distillery, err error) { dis = &Distillery{ context: params.Context, - Core: component.Core{ + Still: component.Still{ Environment: environment.Native{}, }, Upstream: Upstream{ @@ -38,7 +38,7 @@ func NewDistillery(params cli.Params, flags cli.Flags, req cli.Requirements) (di if flags.InternalInDocker { dis.Upstream.SQL = "sql:3306" dis.Upstream.Triplestore = "triplestore:7200" - params.ConfigPath = dis.Core.Environment.GetEnv("CONFIG_PATH") + params.ConfigPath = dis.Still.Environment.GetEnv("CONFIG_PATH") } // if we don't need to load the config, there is nothing to do @@ -56,7 +56,7 @@ func NewDistillery(params cli.Params, flags cli.Flags, req cli.Requirements) (di } // open the config file! - f, err := dis.Core.Environment.Open(params.ConfigPath) + f, err := dis.Still.Environment.Open(params.ConfigPath) if err != nil { return nil, errOpenConfig.WithMessageF(err) } @@ -66,6 +66,6 @@ func NewDistillery(params cli.Params, flags cli.Flags, req cli.Requirements) (di dis.Config = &config.Config{ ConfigPath: cfg, } - err = dis.Config.Unmarshal(dis.Core.Environment, f) + err = dis.Config.Unmarshal(dis.Still.Environment, f) return } diff --git a/internal/wisski/wisski.go b/internal/wisski/wisski.go index e6ed089..cf1f78c 100644 --- a/internal/wisski/wisski.go +++ b/internal/wisski/wisski.go @@ -20,7 +20,7 @@ type WissKI struct { DrupalPassword string // references to components! - Core component.Core + Core component.Still Meta *meta.Meta TS *triplestore.Triplestore SQL *sql.SQL