Refactor components
This commit is contained in:
parent
17011a277f
commit
487ce09979
7 changed files with 117 additions and 63 deletions
|
|
@ -34,6 +34,10 @@ type Component interface {
|
|||
// Context returns a new InstallationContext to be used during installation from the command line.
|
||||
// Typically this should just pass through the parent, but might perform other tasks.
|
||||
Context(parent InstallationContext) InstallationContext
|
||||
|
||||
// Base() returns a reference to a base component
|
||||
// This is implemented by an embedding on ComponentBase
|
||||
Base() *ComponentBase
|
||||
}
|
||||
|
||||
// ComponentBase implements base functionality for a component
|
||||
|
|
@ -43,6 +47,11 @@ type ComponentBase struct {
|
|||
Config *config.Config // Config is the configuration of the underlying distillery
|
||||
}
|
||||
|
||||
// Base returns a reference to the ComponentBase
|
||||
func (cb *ComponentBase) Base() *ComponentBase {
|
||||
return cb
|
||||
}
|
||||
|
||||
// Path returns the path to this component
|
||||
func (cb ComponentBase) Path() string {
|
||||
return cb.Dir
|
||||
|
|
|
|||
118
env/component.go
vendored
118
env/component.go
vendored
|
|
@ -2,6 +2,8 @@ package env
|
|||
|
||||
import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/component"
|
||||
|
|
@ -14,9 +16,63 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/component/web"
|
||||
)
|
||||
|
||||
// Stacks returns the Stacks of this distillery
|
||||
// components holds the various components of the distillery
|
||||
// It is inlined into the [Distillery] struct, and initialized using [makeComponent].
|
||||
type components struct {
|
||||
// m protects the fields below
|
||||
m sync.Mutex
|
||||
|
||||
// each component is only initialized once
|
||||
web *web.Web
|
||||
self *self.Self
|
||||
resolver *resolver.Resolver
|
||||
dis *dis.Dis
|
||||
ssh *ssh.SSH
|
||||
ts *triplestore.Triplestore
|
||||
sql *sql.SQL
|
||||
}
|
||||
|
||||
// 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 *C, init func(C)) C {
|
||||
dis.components.m.Lock()
|
||||
defer dis.components.m.Unlock()
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
// if the component is non-nil, then it has already been initialized
|
||||
if !reflect.ValueOf(*field).IsNil() {
|
||||
return *field
|
||||
}
|
||||
|
||||
// create a new element, and call the initializer (if requested)
|
||||
*field = reflect.New(typC.Elem()).Interface().(C)
|
||||
if init != nil {
|
||||
init(*field)
|
||||
}
|
||||
|
||||
// apply the base configuration
|
||||
base := (*field).Base()
|
||||
base.Config = dis.Config
|
||||
base.Dir = filepath.Join(dis.Config.DeployRoot, "core", (*field).Name())
|
||||
|
||||
// and eventually return it
|
||||
return *field
|
||||
}
|
||||
|
||||
// Components returns all components of the distillery
|
||||
func (dis *Distillery) Components() []component.Component {
|
||||
// TODO: Do we want to cache these components?
|
||||
return []component.Component{
|
||||
dis.Web(),
|
||||
dis.Self(),
|
||||
|
|
@ -28,63 +84,43 @@ func (dis *Distillery) Components() []component.Component {
|
|||
}
|
||||
}
|
||||
|
||||
// Web returns the web component belonging to this distillery
|
||||
func (dis *Distillery) Web() (web web.Web) {
|
||||
dis.makeComponent(web, &web.ComponentBase)
|
||||
return
|
||||
func (dis *Distillery) Web() *web.Web {
|
||||
return makeComponent(dis, &dis.components.web, nil)
|
||||
}
|
||||
|
||||
// Self returns the self component belonging to this distillery
|
||||
func (dis *Distillery) Self() (self self.Self) {
|
||||
dis.makeComponent(self, &self.ComponentBase)
|
||||
return
|
||||
func (dis *Distillery) Self() *self.Self {
|
||||
return makeComponent(dis, &dis.components.self, nil)
|
||||
}
|
||||
|
||||
// Resolver returns the resolver component belonging to this distillery
|
||||
func (dis *Distillery) Resolver() (resolver resolver.Resolver) {
|
||||
func (dis *Distillery) Resolver() *resolver.Resolver {
|
||||
return makeComponent(dis, &dis.components.resolver, func(resolver *resolver.Resolver) {
|
||||
resolver.ConfigName = "prefix.cfg" // TODO: Move into core?
|
||||
resolver.Executable = dis.CurrentExecutable()
|
||||
|
||||
dis.makeComponent(resolver, &resolver.ComponentBase)
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
// Dis returns the dis component belonging to this distillery
|
||||
func (dis *Distillery) Dis() (ddis dis.Dis) {
|
||||
ddis.Executable = dis.CurrentExecutable()
|
||||
|
||||
dis.makeComponent(ddis, &ddis.ComponentBase)
|
||||
return
|
||||
func (d *Distillery) Dis() *dis.Dis {
|
||||
return makeComponent(d, &d.components.dis, func(ddis *dis.Dis) {
|
||||
ddis.Executable = d.CurrentExecutable()
|
||||
})
|
||||
}
|
||||
|
||||
// SSH returns the SSH component belonging to this distillery
|
||||
func (dis *Distillery) SSH() (ssh ssh.SSH) {
|
||||
dis.makeComponent(ssh, &ssh.ComponentBase)
|
||||
return
|
||||
func (dis *Distillery) SSH() *ssh.SSH {
|
||||
return makeComponent(dis, &dis.components.ssh, nil)
|
||||
}
|
||||
|
||||
// SQL returns the SQL component belonging to this distillery
|
||||
func (dis *Distillery) SQL() (sql sql.SQL) {
|
||||
func (dis *Distillery) SQL() *sql.SQL {
|
||||
return makeComponent(dis, &dis.components.sql, func(sql *sql.SQL) {
|
||||
sql.ServerURL = dis.Upstream.SQL
|
||||
sql.PollContext = dis.Context()
|
||||
sql.PollInterval = time.Second
|
||||
|
||||
dis.makeComponent(sql, &sql.ComponentBase)
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
// Triplestore returns the TriplestoreComponent belonging to this distillery
|
||||
func (dis *Distillery) Triplestore() (ts triplestore.Triplestore) {
|
||||
func (dis *Distillery) Triplestore() *triplestore.Triplestore {
|
||||
return makeComponent(dis, &dis.components.ts, func(ts *triplestore.Triplestore) {
|
||||
ts.BaseURL = "http://" + dis.Upstream.Triplestore
|
||||
ts.PollContext = dis.Context()
|
||||
ts.PollInterval = time.Second
|
||||
|
||||
dis.makeComponent(ts, &ts.ComponentBase)
|
||||
return
|
||||
}
|
||||
|
||||
// makeComponent updates the baseComponent belonging to component
|
||||
func (dis *Distillery) makeComponent(component component.Component, base *component.ComponentBase) {
|
||||
base.Config = dis.Config
|
||||
base.Dir = filepath.Join(dis.Config.DeployRoot, "core", component.Name())
|
||||
})
|
||||
}
|
||||
|
|
|
|||
17
env/distillery.go
vendored
17
env/distillery.go
vendored
|
|
@ -10,10 +10,21 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/fsx"
|
||||
)
|
||||
|
||||
// Distillery represents a running instance for the distillery
|
||||
// Distillery represents an interface to the running distillery.
|
||||
type Distillery struct {
|
||||
// Config holds the configuration of the distillery.
|
||||
// It is read directly from a configuration file.
|
||||
Config *config.Config
|
||||
Upstream Upstream // TODO: not sure this belongs here
|
||||
|
||||
// Upstream holds information to connect to the various running
|
||||
// distillery components.
|
||||
//
|
||||
// NOTE(twiesing): This is intended to eventually allow full remote management of the distillery.
|
||||
// But for now this will just hold upstream configuration.
|
||||
Upstream Upstream
|
||||
|
||||
// components hold references to the various components of the distillery.
|
||||
components
|
||||
}
|
||||
|
||||
// Upstream are the upstream urls connecting to the various external components.
|
||||
|
|
@ -23,7 +34,7 @@ type Upstream struct {
|
|||
}
|
||||
|
||||
// Context returns a new Context belonging to this distillery
|
||||
func (dis Distillery) Context() context.Context {
|
||||
func (dis *Distillery) Context() context.Context {
|
||||
return context.Background()
|
||||
}
|
||||
|
||||
|
|
|
|||
2
env/runtime.go
vendored
2
env/runtime.go
vendored
|
|
@ -3,6 +3,6 @@ package env
|
|||
import "path/filepath"
|
||||
|
||||
// RuntimeDir returns the path to the runtime directory
|
||||
func (dis Distillery) RuntimeDir() string {
|
||||
func (dis *Distillery) RuntimeDir() string {
|
||||
return filepath.Join(dis.Config.DeployRoot, "runtime")
|
||||
}
|
||||
|
|
|
|||
12
env/snapshot.go
vendored
12
env/snapshot.go
vendored
|
|
@ -16,25 +16,25 @@ import (
|
|||
)
|
||||
|
||||
// SnapshotsDir returns the path that contains all snapshot related data.
|
||||
func (dis Distillery) SnapshotsDir() string {
|
||||
func (dis *Distillery) SnapshotsDir() string {
|
||||
return filepath.Join(dis.Config.DeployRoot, "snapshots")
|
||||
}
|
||||
|
||||
// SnapshotsStagingPath returns the path to the directory containing a temporary staging area for snapshots.
|
||||
// Use NewSnapshotStagingDir to generate a new staging area.
|
||||
func (dis Distillery) SnapshotsStagingPath() string {
|
||||
func (dis *Distillery) SnapshotsStagingPath() string {
|
||||
return filepath.Join(dis.SnapshotsDir(), "staging")
|
||||
}
|
||||
|
||||
// SnapshotsArchivePath 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 Distillery) SnapshotsArchivePath() string {
|
||||
func (dis *Distillery) SnapshotsArchivePath() string {
|
||||
return filepath.Join(dis.SnapshotsDir(), "archives")
|
||||
}
|
||||
|
||||
// NewSnapshotArchivePath returns the path to a new archive with the provided prefix.
|
||||
// The path is guaranteed to not exist.
|
||||
func (dis Distillery) NewSnapshotArchivePath(prefix string) (path string) {
|
||||
func (dis *Distillery) NewSnapshotArchivePath(prefix string) (path string) {
|
||||
// TODO: Consider moving these into a subdirectory with the provided prefix.
|
||||
for path == "" || fsx.Exists(path) {
|
||||
name := dis.newSnapshotName(prefix) + ".tar.gz"
|
||||
|
|
@ -45,7 +45,7 @@ func (dis Distillery) NewSnapshotArchivePath(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 (Distillery) newSnapshotName(prefix string) string {
|
||||
func (*Distillery) newSnapshotName(prefix string) string {
|
||||
suffix, _ := password.Password(64) // silently ignore any errors!
|
||||
if prefix == "" {
|
||||
prefix = "backup"
|
||||
|
|
@ -57,7 +57,7 @@ func (Distillery) newSnapshotName(prefix string) string {
|
|||
|
||||
// NewSnapshotStagingDir returns the path to a new snapshot directory.
|
||||
// The directory is guaranteed to have been freshly created.
|
||||
func (dis Distillery) NewSnapshotStagingDir(prefix string) (path string, err error) {
|
||||
func (dis *Distillery) NewSnapshotStagingDir(prefix string) (path string, err error) {
|
||||
for path == "" || os.IsExist(err) {
|
||||
path = filepath.Join(dis.SnapshotsStagingPath(), dis.newSnapshotName(prefix))
|
||||
err = os.Mkdir(path, os.ModeDir)
|
||||
|
|
|
|||
|
|
@ -48,8 +48,6 @@ var ErrCopyNoDirectory = errors.New("dst is not a directory")
|
|||
//
|
||||
// onCopy, when not nil, is called for each file or directory being copied.
|
||||
func CopyDirectory(dst, src string, onCopy func(dst, src string)) error {
|
||||
// TODO: Allow copying in parallel? Maybe with a mutex?
|
||||
|
||||
// sanity checks
|
||||
if SameFile(src, dst) {
|
||||
return ErrCopySameFile
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Package hostname provides hostname
|
||||
// Package hostname provides the hostname.
|
||||
package hostname
|
||||
|
||||
import (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue