From 84974dd71287aa5503fd45070ac695e69193dbc2 Mon Sep 17 00:00:00 2001 From: Tom Wiesing Date: Wed, 21 Sep 2022 12:00:36 +0200 Subject: [PATCH] internal/component: Cleanup unused general code --- internal/component/component.go | 71 ++++++++++--------- internal/component/control/control.go | 9 ++- internal/component/control/resolver.go | 2 +- internal/component/core.go | 12 ++++ internal/component/installable.go | 11 +++ internal/component/instances/instances.go | 5 ++ internal/component/instances/wisski_create.go | 2 +- internal/component/sql/sql.go | 13 +++- internal/component/ssh/ssh.go | 13 +++- internal/component/triplestore/triplestore.go | 12 +++- internal/component/web/web.go | 20 ++++-- internal/wisski/component.go | 49 ++----------- 12 files changed, 127 insertions(+), 92 deletions(-) create mode 100644 internal/component/core.go diff --git a/internal/component/component.go b/internal/component/component.go index 314fe64..5937089 100644 --- a/internal/component/component.go +++ b/internal/component/component.go @@ -2,18 +2,18 @@ package component import ( - "github.com/FAU-CDI/wisski-distillery/internal/config" - "github.com/FAU-CDI/wisski-distillery/pkg/environment" + "reflect" + + "github.com/FAU-CDI/wisski-distillery/pkg/lazy" ) // Component represents a logical subsystem of the distillery. +// Every component must embed [ComponentBase] and should be initialized using [Initialize]. // // By convention these are defined within their corresponding subpackage. // This subpackage also contains all required resources. // Furthermore, a component is typically instantiated using a call on the ["distillery.Distillery"] struct. // -// Each Component should make use of [ComponentBase] for sane defaults. -// // For example, the web.Web component lives in the web package and can be created like: // // var dis Distillery @@ -23,45 +23,46 @@ type Component interface { // It should correspond to the appropriate subpackage. Name() string - // Path returns the path this component is installed at. - // By convention it is /var/www/deploy/internal/core/${Name()} - Path() string - - // Base() returns a reference to a base component - // This is implemented by an embedding on ComponentBase - Base() *ComponentBase + // getBase returns the embedded ComponentBase struct. + getBase() *ComponentBase } -// ComponentBase implements base functionality for a component +// ComponentBase should be embedded into every component type ComponentBase struct { - Core // the core of the associated distillery - Dir string // Dir is the directory this component lives in + Core // the core of the associated distillery } -// Core represents the core of a distillery -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 -} - -// Base returns a reference to the ComponentBase -func (cb *ComponentBase) Base() *ComponentBase { +func (cb *ComponentBase) getBase() *ComponentBase { return cb } -// Path returns the path to this component -func (cb ComponentBase) Path() string { - return cb.Dir -} +// Initialize makes or returns a component based on a lazy. +// +// C is the type of component to initialize. It must be backed by a pointer, or Initialize will panic. +// +// dis is the distillery to initialize components for +// field is a pointer to the appropriate struct field within the distillery components +// init is called with a new non-nil component to initialize it. It may be nil, to indicate no initialization is required. +// +// makeComponent returns the new or existing component instance +func Initialize[C Component](core Core, field *lazy.Lazy[C], init func(C)) C { -// Context passes through the parent context -func (ComponentBase) Context(parent InstallationContext) InstallationContext { - return parent -} + // get the typeof C and make sure that it is a pointer type! + typC := reflect.TypeOf((*C)(nil)).Elem() + if typC.Kind() != reflect.Pointer { + panic("Initialize: C must be backed by a pointer") + } -// MakeStack registers the Installable as a stack -func (cb ComponentBase) MakeStack(env environment.Environment, stack StackWithResources) StackWithResources { - stack.Env = env - stack.Dir = cb.Dir - return stack + // return the field + return field.Get(func() (c C) { + c = reflect.New(typC.Elem()).Interface().(C) + if init != nil { + init(c) + } + + base := c.getBase() + base.Core = core + + return + }) } diff --git a/internal/component/control/control.go b/internal/component/control/control.go index 71fb295..7cb8fbd 100644 --- a/internal/component/control/control.go +++ b/internal/component/control/control.go @@ -2,6 +2,7 @@ package control import ( "embed" + "path/filepath" "github.com/FAU-CDI/wisski-distillery/internal/component" "github.com/FAU-CDI/wisski-distillery/internal/component/instances" @@ -22,11 +23,15 @@ 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()) +} + //go:embed all:control control.env var resources embed.FS -func (control Control) Stack(env environment.Environment) component.StackWithResources { - return control.ComponentBase.MakeStack(env, component.StackWithResources{ +func (control *Control) Stack(env environment.Environment) component.StackWithResources { + return component.MakeStack(control, env, component.StackWithResources{ Resources: resources, ContextPath: "control", EnvPath: "control.env", diff --git a/internal/component/control/resolver.go b/internal/component/control/resolver.go index d16e311..933d008 100644 --- a/internal/component/control/resolver.go +++ b/internal/component/control/resolver.go @@ -11,7 +11,7 @@ import ( ) func (control Control) ResolverConfigPath() string { - return filepath.Join(control.Dir, control.ResolverFile) + return filepath.Join(control.Path(), control.ResolverFile) } func (control Control) resolver(io stream.IOStream) (p wdresolve.ResolveHandler, err error) { diff --git a/internal/component/core.go b/internal/component/core.go new file mode 100644 index 0000000..55bd3a6 --- /dev/null +++ b/internal/component/core.go @@ -0,0 +1,12 @@ +package component + +import ( + "github.com/FAU-CDI/wisski-distillery/internal/config" + "github.com/FAU-CDI/wisski-distillery/pkg/environment" +) + +// Core represents the Core of a WissKI Distillery. +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/installable.go b/internal/component/installable.go index 2e080dd..33762f5 100644 --- a/internal/component/installable.go +++ b/internal/component/installable.go @@ -9,6 +9,10 @@ import ( type Installable interface { Component + // Path returns the path this component is installed at. + // By convention it is /var/www/deploy/internal/core/${Name()} + Path() string + // Stack can be used to gain access to the "docker compose" stack. // // This should internally call [ComponentBase.MakeStack] @@ -19,6 +23,13 @@ type Installable interface { Context(parent InstallationContext) InstallationContext } +// MakeStack registers the Installable as a stack +func MakeStack(component Installable, env environment.Environment, stack StackWithResources) StackWithResources { + stack.Env = env + stack.Dir = component.Path() + return stack +} + // Updatable represents a component with an Update method. type Updatable interface { Component diff --git a/internal/component/instances/instances.go b/internal/component/instances/instances.go index 6948a67..0f67659 100644 --- a/internal/component/instances/instances.go +++ b/internal/component/instances/instances.go @@ -2,6 +2,7 @@ package instances import ( "errors" + "path/filepath" "github.com/FAU-CDI/wisski-distillery/internal/component" "github.com/FAU-CDI/wisski-distillery/internal/component/sql" @@ -24,6 +25,10 @@ func (Instances) Name() string { return "instances" } +func (instances *Instances) Path() string { + return filepath.Join(instances.Core.Config.DeployRoot, instances.Name()) +} + // ErrWissKINotFound is returned when a WissKI is not found var ErrWissKINotFound = errors.New("WissKI not found") diff --git a/internal/component/instances/wisski_create.go b/internal/component/instances/wisski_create.go index af1c75d..c8994b5 100644 --- a/internal/component/instances/wisski_create.go +++ b/internal/component/instances/wisski_create.go @@ -26,7 +26,7 @@ func (instances *Instances) Create(slug string) (wisski WissKI, err error) { } wisski.Instance.Slug = slug - wisski.Instance.FilesystemBase = filepath.Join(instances.Dir, wisski.Domain()) + wisski.Instance.FilesystemBase = filepath.Join(instances.Path(), wisski.Domain()) wisski.Instance.OwnerEmail = "" wisski.Instance.AutoBlindUpdateEnabled = true diff --git a/internal/component/sql/sql.go b/internal/component/sql/sql.go index cf1fdcf..7367fc5 100644 --- a/internal/component/sql/sql.go +++ b/internal/component/sql/sql.go @@ -3,6 +3,7 @@ package sql import ( "context" "embed" + "path/filepath" "time" "github.com/FAU-CDI/wisski-distillery/internal/component" @@ -25,11 +26,19 @@ func (SQL) Name() string { return "sql" } +func (sql SQL) Path() string { + return filepath.Join(sql.Core.Config.DeployRoot, "core", sql.Name()) +} + +func (SQL) Context(parent component.InstallationContext) component.InstallationContext { + return parent +} + //go:embed all:sql var resources embed.FS -func (ssh *SQL) Stack(env environment.Environment) component.StackWithResources { - return ssh.ComponentBase.MakeStack(env, component.StackWithResources{ +func (sql *SQL) Stack(env environment.Environment) component.StackWithResources { + return component.MakeStack(sql, env, component.StackWithResources{ Resources: resources, ContextPath: "sql", diff --git a/internal/component/ssh/ssh.go b/internal/component/ssh/ssh.go index e0ab14a..acd7ca6 100644 --- a/internal/component/ssh/ssh.go +++ b/internal/component/ssh/ssh.go @@ -2,6 +2,7 @@ package ssh import ( "embed" + "path/filepath" "github.com/FAU-CDI/wisski-distillery/internal/component" "github.com/FAU-CDI/wisski-distillery/pkg/environment" @@ -15,11 +16,19 @@ func (SSH) Name() string { return "ssh" } +func (ssh SSH) Path() string { + return filepath.Join(ssh.Core.Config.DeployRoot, "core", ssh.Name()) +} + +func (SSH) Context(parent component.InstallationContext) component.InstallationContext { + return parent +} + //go:embed all:ssh var resources embed.FS -func (ssh SSH) Stack(env environment.Environment) component.StackWithResources { - return ssh.ComponentBase.MakeStack(env, component.StackWithResources{ +func (ssh *SSH) Stack(env environment.Environment) component.StackWithResources { + return component.MakeStack(ssh, env, component.StackWithResources{ Resources: resources, ContextPath: "ssh", }) diff --git a/internal/component/triplestore/triplestore.go b/internal/component/triplestore/triplestore.go index 2538601..57b6e73 100644 --- a/internal/component/triplestore/triplestore.go +++ b/internal/component/triplestore/triplestore.go @@ -23,11 +23,19 @@ func (Triplestore) Name() string { return "triplestore" } +func (ts Triplestore) Path() string { + return filepath.Join(ts.Core.Config.DeployRoot, "core", ts.Name()) +} + +func (Triplestore) Context(parent component.InstallationContext) component.InstallationContext { + return parent +} + //go:embed all:triplestore var resources embed.FS -func (ts Triplestore) Stack(env environment.Environment) component.StackWithResources { - return ts.ComponentBase.MakeStack(env, component.StackWithResources{ +func (ts *Triplestore) Stack(env environment.Environment) component.StackWithResources { + return component.MakeStack(ts, env, component.StackWithResources{ Resources: resources, ContextPath: "triplestore", diff --git a/internal/component/web/web.go b/internal/component/web/web.go index f9fcdb7..54b1680 100644 --- a/internal/component/web/web.go +++ b/internal/component/web/web.go @@ -2,6 +2,8 @@ package web import ( "embed" + "fmt" + "path/filepath" "github.com/FAU-CDI/wisski-distillery/internal/component" "github.com/FAU-CDI/wisski-distillery/pkg/environment" @@ -18,6 +20,16 @@ func (Web) Name() string { return "web" } +func (web Web) Path() string { + res := filepath.Join(web.Core.Config.DeployRoot, "core", web.Name()) + fmt.Println("debug====" + res) + return res +} + +func (Web) Context(parent component.InstallationContext) component.InstallationContext { + return parent +} + func (web Web) Stack(env environment.Environment) component.StackWithResources { if web.Config.HTTPSEnabled() { return web.stackHTTPS(env) @@ -30,8 +42,8 @@ func (web Web) Stack(env environment.Environment) component.StackWithResources { //go:embed web-https.env var httpsResources embed.FS -func (web Web) stackHTTPS(env environment.Environment) component.StackWithResources { - return web.MakeStack(env, component.StackWithResources{ +func (web *Web) stackHTTPS(env environment.Environment) component.StackWithResources { + return component.MakeStack(web, env, component.StackWithResources{ Resources: httpsResources, ContextPath: "web-https", EnvPath: "web-https.env", @@ -46,8 +58,8 @@ func (web Web) stackHTTPS(env environment.Environment) component.StackWithResour //go:embed web-http.env var httpResources embed.FS -func (web Web) stackHTTP(env environment.Environment) component.StackWithResources { - return web.MakeStack(env, component.StackWithResources{ +func (web *Web) stackHTTP(env environment.Environment) component.StackWithResources { + return component.MakeStack(web, env, component.StackWithResources{ Resources: httpResources, ContextPath: "web-http", EnvPath: "web-http.env", diff --git a/internal/wisski/component.go b/internal/wisski/component.go index 3a36653..716af49 100644 --- a/internal/wisski/component.go +++ b/internal/wisski/component.go @@ -1,8 +1,6 @@ package wisski import ( - "path/filepath" - "reflect" "time" "github.com/FAU-CDI/wisski-distillery/internal/component" @@ -33,40 +31,6 @@ type components struct { instances lazy.Lazy[*instances.Instances] } -// makeComponent makes or returns a component inside the [component] struct of the distillery -// -// C is the type of component to initialize. It must be backed by a pointer, or makeComponent will panic. -// -// dis is the distillery to initialize components for -// field is a pointer to the appropriate struct field within the distillery components -// init is called with a new non-nil component to initialize it. It may be nil, to indicate no initialization is required. -// -// makeComponent returns the new or existing component instance -func makeComponent[C component.Component](dis *Distillery, field *lazy.Lazy[C], init func(C)) C { - - // get the typeof C and make sure that it is a pointer type! - typC := reflect.TypeOf((*C)(nil)).Elem() - if typC.Kind() != reflect.Pointer { - panic("makeComponent: C must be backed by a pointer") - } - - // return the field - return field.Get(func() (c C) { - c = reflect.New(typC.Elem()).Interface().(C) - if init != nil { - init(c) - } - - base := c.Base() - base.Core = dis.Core - if base.Dir == "" { - base.Dir = filepath.Join(dis.Config.DeployRoot, "core", c.Name()) - } - - return - }) -} - func (dis *Distillery) Components() []component.Component { return []component.Component{ dis.Web(), @@ -114,22 +78,22 @@ func getComponents[C component.Component](dis *Distillery) (result []C) { } func (dis *Distillery) Web() *web.Web { - return makeComponent(dis, &dis.components.web, nil) + return component.Initialize(dis.Core, &dis.components.web, nil) } func (d *Distillery) Control() *control.Control { - return makeComponent(d, &d.components.control, func(ddis *control.Control) { + return component.Initialize(d.Core, &d.components.control, func(ddis *control.Control) { ddis.ResolverFile = core.PrefixConfig ddis.Instances = d.Instances() }) } func (dis *Distillery) SSH() *ssh.SSH { - return makeComponent(dis, &dis.components.ssh, nil) + return component.Initialize(dis.Core, &dis.components.ssh, nil) } func (dis *Distillery) SQL() *sql.SQL { - return makeComponent(dis, &dis.components.sql, func(sql *sql.SQL) { + return component.Initialize(dis.Core, &dis.components.sql, func(sql *sql.SQL) { sql.ServerURL = dis.Upstream.SQL sql.PollContext = dis.Context() sql.PollInterval = time.Second @@ -137,7 +101,7 @@ func (dis *Distillery) SQL() *sql.SQL { } func (dis *Distillery) Triplestore() *triplestore.Triplestore { - return makeComponent(dis, &dis.components.ts, func(ts *triplestore.Triplestore) { + return component.Initialize(dis.Core, &dis.components.ts, func(ts *triplestore.Triplestore) { ts.BaseURL = "http://" + dis.Upstream.Triplestore ts.PollContext = dis.Context() ts.PollInterval = time.Second @@ -145,8 +109,7 @@ func (dis *Distillery) Triplestore() *triplestore.Triplestore { } func (dis *Distillery) Instances() *instances.Instances { - return makeComponent(dis, &dis.components.instances, func(instances *instances.Instances) { - instances.Dir = filepath.Join(dis.Config.DeployRoot, "instances") + return component.Initialize(dis.Core, &dis.components.instances, func(instances *instances.Instances) { instances.SQL = dis.SQL() instances.TS = dis.Triplestore() })