diff --git a/internal/component/backup.go b/internal/component/backup.go index afb3e0d..82bf9e2 100644 --- a/internal/component/backup.go +++ b/internal/component/backup.go @@ -22,6 +22,20 @@ type Backupable interface { Backup(context StagingContext) error } +// Snapshotable represents a component with a Snapshot method. +type Snapshotable interface { + Component + + // SnapshotNeedsRunning returns if this Snapshotable requires a running instance. + SnapshotNeedsRunning() bool + + // SnapshotName returns a new name to be used as an argument for path. + SnapshotName() string + + // Snapshot snapshots a part of the instance + Snapshot(wisski models.Instance, context StagingContext) error +} + // StagingContext represents a context for [Backupable] and [Snapshotable] type StagingContext interface { // IO returns the input output stream belonging to this backup file @@ -50,20 +64,6 @@ type StagingContext interface { AddFile(path string, op func(file io.Writer) error) error } -// Snapshotable represents a component with a Snapshot method. -type Snapshotable interface { - Component - - // SnapshotNeedsRunning returns if this Snapshotable requires a running instance. - SnapshotNeedsRunning() bool - - // SnapshotName returns a new name to be used as an argument for path. - SnapshotName() string - - // Snapshot snapshots a part of the instance - Snapshot(wisski models.Instance, context StagingContext) error -} - // NewStagingContext returns a new [StagingContext] func NewStagingContext(env environment.Environment, io stream.IOStream, path string, manifest chan<- string) StagingContext { return &stagingContext{ diff --git a/internal/component/component.go b/internal/component/component.go index 783e33a..5010d91 100644 --- a/internal/component/component.go +++ b/internal/component/component.go @@ -1,20 +1,57 @@ // Package component holds the main abstraction for components. package component -// Component represents a logical subsystem of the distillery. -// Every component must embed [ComponentBase] and should be initialized using [Initialize]. +import ( + "reflect" + "strings" + + "github.com/FAU-CDI/wisski-distillery/internal/config" + "github.com/FAU-CDI/wisski-distillery/pkg/environment" +) + +// Components represents a logical subsystem of the distillery. // A Component should be implemented as a pointer to a struct. +// Every component must embed [Base] and should be initialized using [Init] inside a [lazy.Pool]. // // By convention these are defined within their corresponding subpackage. // This subpackage also contains all required resources. -// -// Components are initialized using a [Pool]. type Component interface { // Name returns the name of this component // Name should be implemented by the [ComponentBase] struct. Name() string - // getComponentBase returns the underlying ComponentBase object of this Component. + // getBase returns the underlying ComponentBase object of this Component. // It is used internally during initialization - getComponentBase() *ComponentBase + getBase() *Base +} + +// Base is embedded into every Component +type Base 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 *Base) getBase() *Base { + return cb +} + +// Init initialzes a new componeont Component with the provided still. +// Init is only initended to be used within a lazy.Pool[Component,Still]. +func Init(component Component, core Still) Component { + base := component.getBase() // pointer to a struct + base.Still = core + base.name = strings.ToLower(reflect.TypeOf(component).Elem().Name()) + return component +} + +func (cb Base) Name() string { + return cb.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/control/control.go b/internal/component/control/control.go index a832f6f..28c135c 100644 --- a/internal/component/control/control.go +++ b/internal/component/control/control.go @@ -11,7 +11,7 @@ import ( // Control represents the running control server. type Control struct { - component.ComponentBase + component.Base Servables []component.Servable } diff --git a/internal/component/exporter/exporter.go b/internal/component/exporter/exporter.go index 69dec72..c65d21e 100644 --- a/internal/component/exporter/exporter.go +++ b/internal/component/exporter/exporter.go @@ -17,7 +17,7 @@ import ( // Exporter manages snapshots and backups type Exporter struct { - component.ComponentBase + component.Base SQL *sql.SQL Instances *instances.Instances diff --git a/internal/component/exporter/extras_bookkeeping.go b/internal/component/exporter/extras_bookkeeping.go index edf5de0..2199094 100644 --- a/internal/component/exporter/extras_bookkeeping.go +++ b/internal/component/exporter/extras_bookkeeping.go @@ -9,7 +9,7 @@ import ( ) type Bookkeeping struct { - component.ComponentBase + component.Base } // SnapshotNeedsRunning returns if this Snapshotable requires a running instance. diff --git a/internal/component/exporter/extras_config.go b/internal/component/exporter/extras_config.go index f2bb26d..bd51c60 100644 --- a/internal/component/exporter/extras_config.go +++ b/internal/component/exporter/extras_config.go @@ -8,7 +8,7 @@ import ( // Config implements backing up configuration type Config struct { - component.ComponentBase + component.Base } func (*Config) BackupName() string { diff --git a/internal/component/exporter/extras_filesystem.go b/internal/component/exporter/extras_filesystem.go index ffec88b..1ca0043 100644 --- a/internal/component/exporter/extras_filesystem.go +++ b/internal/component/exporter/extras_filesystem.go @@ -7,7 +7,7 @@ import ( // Filesystem implements snapshotting an instnace filesystem type Filesystem struct { - component.ComponentBase + component.Base } // SnapshotNeedsRunning returns if this Snapshotable requires a running instance. diff --git a/internal/component/exporter/extras_pathbuilders.go b/internal/component/exporter/extras_pathbuilders.go index 4cab5b6..24636ad 100644 --- a/internal/component/exporter/extras_pathbuilders.go +++ b/internal/component/exporter/extras_pathbuilders.go @@ -9,7 +9,7 @@ import ( ) type Pathbuilders struct { - component.ComponentBase + component.Base Instances *instances.Instances } diff --git a/internal/component/exporter/logger/logger.go b/internal/component/exporter/logger/logger.go index 3eb71ae..ca9fafd 100644 --- a/internal/component/exporter/logger/logger.go +++ b/internal/component/exporter/logger/logger.go @@ -10,7 +10,7 @@ import ( // Logger is responsible for logging backups and snapshots type Logger struct { - component.ComponentBase + component.Base SQL *sql.SQL } diff --git a/internal/component/home/home.go b/internal/component/home/home.go index 533fa7c..0ad27bb 100644 --- a/internal/component/home/home.go +++ b/internal/component/home/home.go @@ -13,7 +13,7 @@ import ( ) type Home struct { - component.ComponentBase + component.Base Instances *instances.Instances diff --git a/internal/component/info/info.go b/internal/component/info/info.go index beed7e2..1e61d4c 100644 --- a/internal/component/info/info.go +++ b/internal/component/info/info.go @@ -14,7 +14,7 @@ import ( ) type Info struct { - component.ComponentBase + component.Base Exporter *exporter.Exporter Instances *instances.Instances diff --git a/internal/component/instances/instances.go b/internal/component/instances/instances.go index 9bfd53c..62b79fc 100644 --- a/internal/component/instances/instances.go +++ b/internal/component/instances/instances.go @@ -19,7 +19,7 @@ import ( // Instances manages multiple WissKI Instances. type Instances struct { - component.ComponentBase + component.Base TS *triplestore.Triplestore SQL *sql.SQL diff --git a/internal/component/meta/meta.go b/internal/component/meta/meta.go index 694ed6e..363b582 100644 --- a/internal/component/meta/meta.go +++ b/internal/component/meta/meta.go @@ -9,7 +9,7 @@ import ( // Component meta is responsible for managing metadata per WissKI Instance type Meta struct { - component.ComponentBase + component.Base SQL *sql.SQL diff --git a/internal/component/pool.go b/internal/component/pool.go index 80f16dd..3456fb0 100644 --- a/internal/component/pool.go +++ b/internal/component/pool.go @@ -6,31 +6,27 @@ import ( "github.com/FAU-CDI/wisski-distillery/pkg/lazy" ) -type ComponentPool struct { +// Pool holds a pool of components. +type Pool struct { pool lazy.Pool[Component, Still] poolInit sync.Once } -func (pool *ComponentPool) init() { +func (pool *Pool) init() { pool.poolInit.Do(func() { - pool.pool.Init = func(component Component, core Still) Component { - base := component.getComponentBase() - base.Still = core - base.name = nameOf(component) - return component - } + pool.pool.Init = Init }) } -type ComponentPoolContext = *lazy.PoolContext[Component] -type ComponentAllFunc = func(context ComponentPoolContext) []Component +type PoolContext = *lazy.PoolContext[Component] +type AllFunc = func(context PoolContext) []Component -func (pool *ComponentPool) All(core Still, init func(context ComponentPoolContext) []Component) []Component { +func (pool *Pool) All(core Still, init func(context PoolContext) []Component) []Component { pool.init() return pool.pool.All(core, init) } -// MakeComponent creates or returns a cached component of the given Context. +// Make creates or returns a cached component of the given Context. // // Components are initialized by first calling the init function. // Then all component-like fields of fields are filled with their appropriate components. @@ -45,24 +41,24 @@ func (pool *ComponentPool) All(core Still, init func(context ComponentPoolContex // 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 Still, init func(component C)) C { +func Make[C Component](context PoolContext, core Still, init func(component C)) C { return lazy.Make(context, init) } -// ExportComponents exports all components that are a C from the pool. +// ExportAll exports all components that are 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 ExportComponents[C Component](pool *ComponentPool, core Still, All ComponentAllFunc) []C { +func ExportAll[C Component](pool *Pool, core Still, All AllFunc) []C { pool.init() return lazy.ExportComponents[Component, Still, C](&pool.pool, core, All) } -// ExportComponent exports the first component that is a C from the pool. +// Export 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 Still, All ComponentAllFunc) C { +func Export[C Component](pool *Pool, core Still, All AllFunc) C { pool.init() return lazy.ExportComponent[Component, Still, C](&pool.pool, core, All) } diff --git a/internal/component/provision.go b/internal/component/provision.go index 0054422..eff75fd 100644 --- a/internal/component/provision.go +++ b/internal/component/provision.go @@ -4,7 +4,7 @@ import ( "github.com/FAU-CDI/wisski-distillery/internal/models" ) -// Provisionable represents a component with a Provision and a Purge method. +// Provisionable is a component that can be provisioned type Provisionable interface { Component diff --git a/internal/component/resolver/resolver.go b/internal/component/resolver/resolver.go index a3cc13c..c40d4f9 100644 --- a/internal/component/resolver/resolver.go +++ b/internal/component/resolver/resolver.go @@ -16,7 +16,7 @@ import ( ) type Resolver struct { - component.ComponentBase + component.Base Instances *instances.Instances diff --git a/internal/component/server.go b/internal/component/server.go index 71f6c34..62b4a39 100644 --- a/internal/component/server.go +++ b/internal/component/server.go @@ -7,7 +7,7 @@ import ( "github.com/tkw1536/goprogram/stream" ) -// Servable implements a component with a Serve method +// Servable is a component that is servable type Servable interface { Component diff --git a/internal/component/sql/sql.go b/internal/component/sql/sql.go index 270bc69..d0cee20 100644 --- a/internal/component/sql/sql.go +++ b/internal/component/sql/sql.go @@ -12,7 +12,7 @@ import ( ) type SQL struct { - component.ComponentBase + component.Base ServerURL string // upstream server url diff --git a/internal/component/ssh/ssh.go b/internal/component/ssh/ssh.go index f2fbbe1..9967726 100644 --- a/internal/component/ssh/ssh.go +++ b/internal/component/ssh/ssh.go @@ -9,7 +9,7 @@ import ( ) type SSH struct { - component.ComponentBase + component.Base } func (ssh *SSH) Path() string { diff --git a/internal/component/static/static.go b/internal/component/static/static.go index c643bfd..e54e3c5 100644 --- a/internal/component/static/static.go +++ b/internal/component/static/static.go @@ -12,7 +12,7 @@ import ( ) type Static struct { - component.ComponentBase + component.Base } func (*Static) Routes() []string { return []string{"/static/"} } diff --git a/internal/component/still.go b/internal/component/still.go deleted file mode 100644 index edfa56c..0000000 --- a/internal/component/still.go +++ /dev/null @@ -1,36 +0,0 @@ -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 435ff27..4e396d4 100644 --- a/internal/component/triplestore/triplestore.go +++ b/internal/component/triplestore/triplestore.go @@ -11,7 +11,7 @@ import ( ) type Triplestore struct { - component.ComponentBase + component.Base BaseURL string // upstream server url diff --git a/internal/component/web/web.go b/internal/component/web/web.go index ccb9abb..05b76c1 100644 --- a/internal/component/web/web.go +++ b/internal/component/web/web.go @@ -12,7 +12,7 @@ import ( // // It consists of an nginx docker container and an optional letsencrypt container. type Web struct { - component.ComponentBase + component.Base } func (web *Web) Path() string { diff --git a/internal/dis/component.go b/internal/dis/component.go index 34822aa..73ebcd6 100644 --- a/internal/dis/component.go +++ b/internal/dis/component.go @@ -22,7 +22,7 @@ import ( ) // register returns all components of the distillery -func (dis *Distillery) register(context component.ComponentPoolContext) []component.Component { +func (dis *Distillery) register(context component.PoolContext) []component.Component { return collection.MapSlice([]initFunc{ auto[*web.Web], @@ -65,16 +65,16 @@ func (dis *Distillery) register(context component.ComponentPoolContext) []compon }) } -type initFunc = func(dis *Distillery, context component.ComponentPoolContext) component.Component +type initFunc = func(dis *Distillery, context component.PoolContext) component.Component // 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.Still, init) + return func(dis *Distillery, context component.PoolContext) component.Component { + return component.Make(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.Still, nil) +func auto[C component.Component](dis *Distillery, context component.PoolContext) component.Component { + return component.Make[C](context, dis.Still, nil) } diff --git a/internal/dis/distillery.go b/internal/dis/distillery.go index d658f73..a8803cd 100644 --- a/internal/dis/distillery.go +++ b/internal/dis/distillery.go @@ -32,7 +32,7 @@ type Distillery struct { Upstream Upstream // Pool holds all the components in this pool - pool component.ComponentPool + pool component.Pool } // Upstream contains the configuration for accessing remote configuration. @@ -52,7 +52,7 @@ func (dis *Distillery) Context() context.Context { // e is a convenience function to export a single component func e[C component.Component](dis *Distillery) C { - return component.ExportComponent[C]( + return component.Export[C]( &dis.pool, dis.Still, dis.register, @@ -60,7 +60,7 @@ func e[C component.Component](dis *Distillery) C { } func ea[C component.Component](dis *Distillery) []C { - return component.ExportComponents[C]( + return component.ExportAll[C]( &dis.pool, dis.Still, dis.register, diff --git a/internal/dis/pool.go b/internal/dis/pool.go new file mode 100644 index 0000000..a46b20c --- /dev/null +++ b/internal/dis/pool.go @@ -0,0 +1 @@ +package dis