control: Move serves into a separate components
This commit is contained in:
parent
6f409be8b2
commit
845e927117
12 changed files with 210 additions and 127 deletions
|
|
@ -39,7 +39,7 @@ func (upc updateprefixconfig) Run(context wisski_distillery.Context) error {
|
|||
}
|
||||
|
||||
ddis := dis.Control()
|
||||
target := ddis.ResolverConfigPath()
|
||||
target := dis.Resolver().ConfigPath()
|
||||
|
||||
// print the configuration
|
||||
config, err := dis.Core.Environment.Create(target, environment.DefaultFilePerm)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/instances"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/core"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
|
||||
)
|
||||
|
|
@ -14,9 +13,9 @@ import (
|
|||
type Control struct {
|
||||
component.ComponentBase
|
||||
|
||||
Instances *instances.Instances
|
||||
Servables []component.Servable
|
||||
|
||||
ResolverFile string
|
||||
ResolverFile string // TODO: this shouldn't be needed!
|
||||
}
|
||||
|
||||
func (control Control) Name() string {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/instances"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/config"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
||||
|
|
@ -16,7 +17,17 @@ import (
|
|||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func (control *Control) info(io stream.IOStream) (http.Handler, error) {
|
||||
type Info struct {
|
||||
component.ComponentBase
|
||||
|
||||
Instances *instances.Instances
|
||||
}
|
||||
|
||||
func (Info) Name() string { return "control-info" }
|
||||
|
||||
func (*Info) Routes() []string { return []string{"/dis/"} }
|
||||
|
||||
func (info *Info) Handler(route string, io stream.IOStream) (http.Handler, error) {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// handle everything under /dis/!
|
||||
|
|
@ -29,7 +40,7 @@ func (control *Control) info(io stream.IOStream) (http.Handler, error) {
|
|||
})
|
||||
|
||||
// static stuff
|
||||
static, err := control.disStatic()
|
||||
static, err := info.disStatic()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -37,22 +48,22 @@ func (control *Control) info(io stream.IOStream) (http.Handler, error) {
|
|||
|
||||
// render everything
|
||||
mux.Handle("/dis/index", httpx.HTMLHandler[disIndex]{
|
||||
Handler: control.disIndex,
|
||||
Handler: info.disIndex,
|
||||
Template: indexTemplate,
|
||||
})
|
||||
|
||||
mux.Handle("/dis/instance/", httpx.HTMLHandler[disInstance]{
|
||||
Handler: control.disInstance,
|
||||
Handler: info.disInstance,
|
||||
Template: instanceTemplate,
|
||||
})
|
||||
|
||||
// api -- for future usage
|
||||
mux.Handle("/dis/api/v1/instance/get/", httpx.JSON(control.getinstance))
|
||||
mux.Handle("/dis/api/v1/instance/all", httpx.JSON(control.allinstances))
|
||||
mux.Handle("/dis/api/v1/instance/get/", httpx.JSON(info.getinstance))
|
||||
mux.Handle("/dis/api/v1/instance/all", httpx.JSON(info.allinstances))
|
||||
|
||||
// ensure that everyone is logged in!
|
||||
return httpx.BasicAuth(mux, "WissKI Distillery Admin", func(user, pass string) bool {
|
||||
return user == control.Config.DisAdminUser && pass == control.Config.DisAdminPassword
|
||||
return user == info.Config.DisAdminUser && pass == info.Config.DisAdminPassword
|
||||
}), nil
|
||||
}
|
||||
|
||||
|
|
@ -71,12 +82,12 @@ type disIndex struct {
|
|||
Backups []models.Snapshot
|
||||
}
|
||||
|
||||
func (dis *Control) disIndex(r *http.Request) (idx disIndex, err error) {
|
||||
func (info *Info) disIndex(r *http.Request) (idx disIndex, err error) {
|
||||
var group errgroup.Group
|
||||
|
||||
group.Go(func() error {
|
||||
// load instances
|
||||
idx.Instances, err = dis.allinstances(r)
|
||||
idx.Instances, err = info.allinstances(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -96,12 +107,12 @@ func (dis *Control) disIndex(r *http.Request) (idx disIndex, err error) {
|
|||
|
||||
// get the log entries
|
||||
group.Go(func() (err error) {
|
||||
idx.Backups, err = dis.Instances.SnapshotLogFor("")
|
||||
idx.Backups, err = info.Instances.SnapshotLogFor("")
|
||||
return
|
||||
})
|
||||
|
||||
// get the static properties
|
||||
idx.Config = dis.Config
|
||||
idx.Config = info.Config
|
||||
|
||||
// current time
|
||||
idx.Time = time.Now().UTC()
|
||||
|
|
@ -120,13 +131,13 @@ type disInstance struct {
|
|||
Info instances.WissKIInfo
|
||||
}
|
||||
|
||||
func (dis *Control) disInstance(r *http.Request) (is disInstance, err error) {
|
||||
func (info *Info) disInstance(r *http.Request) (is disInstance, err error) {
|
||||
// find the slug as the last component of path!
|
||||
slug := strings.TrimSuffix(r.URL.Path, "/")
|
||||
slug = slug[strings.LastIndex(slug, "/")+1:]
|
||||
|
||||
// find the instance itself!
|
||||
instance, err := dis.Instances.WissKI(slug)
|
||||
instance, err := info.Instances.WissKI(slug)
|
||||
if err == instances.ErrWissKINotFound {
|
||||
return is, httpx.ErrNotFound
|
||||
}
|
||||
|
|
@ -150,7 +161,7 @@ func (dis *Control) disInstance(r *http.Request) (is disInstance, err error) {
|
|||
//go:embed html/static
|
||||
var htmlStaticFS embed.FS
|
||||
|
||||
func (*Control) disStatic() (http.Handler, error) {
|
||||
func (*Info) disStatic() (http.Handler, error) {
|
||||
fs, err := fs.Sub(htmlStaticFS, "html/static")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -167,29 +178,29 @@ var indexTemplate = template.Must(template.New("index.html").Parse(indexTemplate
|
|||
var instanceTemplateString string
|
||||
var instanceTemplate = template.Must(template.New("instance.html").Parse(instanceTemplateString))
|
||||
|
||||
func (dis *Control) getinstance(r *http.Request) (info instances.WissKIInfo, err error) {
|
||||
func (info *Info) getinstance(r *http.Request) (iinfo instances.WissKIInfo, err error) {
|
||||
// find the slug as the last component of path!
|
||||
slug := strings.TrimSuffix(r.URL.Path, "/")
|
||||
slug = slug[strings.LastIndex(slug, "/")+1:]
|
||||
|
||||
// load the wisski instance!
|
||||
wisski, err := dis.Instances.WissKI(strings.TrimSuffix(slug, "/"))
|
||||
wisski, err := info.Instances.WissKI(strings.TrimSuffix(slug, "/"))
|
||||
if err == instances.ErrWissKINotFound {
|
||||
return info, httpx.ErrNotFound
|
||||
return iinfo, httpx.ErrNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return info, err
|
||||
return iinfo, err
|
||||
}
|
||||
|
||||
// get info about it!
|
||||
return wisski.Info(false)
|
||||
}
|
||||
|
||||
func (dis *Control) allinstances(*http.Request) (infos []instances.WissKIInfo, err error) {
|
||||
func (info *Info) allinstances(*http.Request) (infos []instances.WissKIInfo, err error) {
|
||||
var errgroup errgroup.Group
|
||||
|
||||
// list all the instances
|
||||
all, err := dis.Instances.All()
|
||||
all, err := info.Instances.All()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -6,14 +6,30 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/instances"
|
||||
"github.com/tkw1536/goprogram/stream"
|
||||
)
|
||||
|
||||
// self returns the handler for the self overrides
|
||||
func (control Control) self(io stream.IOStream) (redirect Redirect, err error) {
|
||||
// SelfHandler implements serving the '/' route
|
||||
type SelfHandler struct {
|
||||
component.ComponentBase
|
||||
|
||||
Instances *instances.Instances
|
||||
}
|
||||
|
||||
func (SelfHandler) Name() string { return "control-self" }
|
||||
|
||||
func (*SelfHandler) Routes() []string { return []string{"/"} }
|
||||
|
||||
func (sh *SelfHandler) Handler(route string, io stream.IOStream) (http.Handler, error) {
|
||||
// create a redirect
|
||||
var redirect Redirect
|
||||
var err error
|
||||
|
||||
// open the overrides file
|
||||
overrides, err := control.Environment.Open(control.Config.SelfOverridesFile)
|
||||
io.Printf("loading overrides from %q\n", control.Config.SelfOverridesFile)
|
||||
overrides, err := sh.Environment.Open(sh.Config.SelfOverridesFile)
|
||||
io.Printf("loading overrides from %q\n", sh.Config.SelfOverridesFile)
|
||||
if err != nil {
|
||||
return redirect, err
|
||||
}
|
||||
|
|
@ -21,18 +37,18 @@ func (control Control) self(io stream.IOStream) (redirect Redirect, err error) {
|
|||
|
||||
// decode the overrides file
|
||||
if err := json.NewDecoder(overrides).Decode(&redirect.Overrides); err != nil {
|
||||
return redirect, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if redirect.Overrides == nil {
|
||||
redirect.Overrides = make(map[string]string)
|
||||
}
|
||||
redirect.Overrides[""] = control.Config.SelfRedirect.String()
|
||||
redirect.Overrides[""] = sh.Config.SelfRedirect.String()
|
||||
|
||||
// create a redirect server
|
||||
redirect.Fallback, err = control.selfFallback()
|
||||
redirect.Fallback, err = sh.selfFallback()
|
||||
if err != nil {
|
||||
return redirect, err
|
||||
return nil, err
|
||||
}
|
||||
redirect.Absolute = false
|
||||
redirect.Permanent = false
|
||||
|
|
@ -41,22 +57,22 @@ func (control Control) self(io stream.IOStream) (redirect Redirect, err error) {
|
|||
return redirect, nil
|
||||
}
|
||||
|
||||
func (control *Control) selfFallback() (http.Handler, error) {
|
||||
return http.HandlerFunc(control.serveFallback), nil
|
||||
func (sh *SelfHandler) selfFallback() (http.Handler, error) {
|
||||
return http.HandlerFunc(sh.serveFallback), nil
|
||||
}
|
||||
|
||||
var notFoundText = []byte("not found")
|
||||
|
||||
func (control *Control) serveFallback(w http.ResponseWriter, r *http.Request) {
|
||||
func (sh *SelfHandler) serveFallback(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
slug := control.Config.SlugFromHost(r.Host)
|
||||
slug := sh.Config.SlugFromHost(r.Host)
|
||||
if slug == "" {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write(notFoundText)
|
||||
return
|
||||
}
|
||||
|
||||
if ok, _ := control.Instances.Has(slug); !ok {
|
||||
if ok, _ := sh.Instances.Has(slug); !ok {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
fmt.Fprintf(w, "WissKI %q not found\n", slug)
|
||||
return
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
package control
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/FAU-CDI/wdresolve"
|
||||
"github.com/FAU-CDI/wdresolve/resolvers"
|
||||
"github.com/tkw1536/goprogram/stream"
|
||||
)
|
||||
|
||||
func (control Control) ResolverConfigPath() string {
|
||||
return filepath.Join(control.Path(), control.ResolverFile)
|
||||
}
|
||||
|
||||
func (control Control) resolver(io stream.IOStream) (p wdresolve.ResolveHandler, err error) {
|
||||
p.TrustXForwardedProto = true
|
||||
|
||||
fallback := &resolvers.Regexp{
|
||||
Data: map[string]string{},
|
||||
}
|
||||
|
||||
// handle the default domain name!
|
||||
domainName := control.Config.DefaultDomain
|
||||
if domainName != "" {
|
||||
fallback.Data[fmt.Sprintf("^https?://(.*)\\.%s", regexp.QuoteMeta(domainName))] = fmt.Sprintf("https://$1.%s", domainName)
|
||||
io.Printf("registering default domain %s\n", domainName)
|
||||
}
|
||||
|
||||
// handle the extra domains!
|
||||
for _, domain := range control.Config.SelfExtraDomains {
|
||||
fallback.Data[fmt.Sprintf("^https?://(.*)\\.%s", regexp.QuoteMeta(domain))] = fmt.Sprintf("https://$1.%s", domainName)
|
||||
io.Printf("registering legacy domain %s\n", domain)
|
||||
}
|
||||
|
||||
// open the prefix file
|
||||
prefixFile := control.ResolverConfigPath()
|
||||
fs, err := control.Environment.Open(prefixFile)
|
||||
io.Println("loading prefixes from ", prefixFile)
|
||||
if err != nil {
|
||||
return p, err
|
||||
}
|
||||
defer fs.Close()
|
||||
|
||||
// read the prefixes
|
||||
// TODO: Do we want to load these without a file?
|
||||
prefixes, err := resolvers.ReadPrefixes(fs)
|
||||
if err != nil {
|
||||
return p, err
|
||||
}
|
||||
|
||||
// and use that as the resolver!
|
||||
p.Resolver = resolvers.InOrder{
|
||||
prefixes,
|
||||
fallback,
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
|
@ -7,33 +7,21 @@ import (
|
|||
)
|
||||
|
||||
// Server returns an http.Mux that implements the main server instance
|
||||
func (control Control) Server(io stream.IOStream) (http.Handler, error) {
|
||||
// self server
|
||||
self, err := control.self(io)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resolver, err := control.resolver(io)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info, err := control.info(io)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// resolver
|
||||
|
||||
// Logging messages are directed to io.
|
||||
func (control *Control) Server(io stream.IOStream) (*http.ServeMux, error) {
|
||||
// create a new mux
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/", self)
|
||||
|
||||
mux.Handle("/go/", resolver)
|
||||
mux.Handle("/wisski/get/", resolver)
|
||||
|
||||
// TODO: Fix me!
|
||||
mux.Handle("/dis/", info)
|
||||
|
||||
// add all the servable routes!
|
||||
for _, s := range control.Servables {
|
||||
for _, route := range s.Routes() {
|
||||
io.Printf("mounting %s\n", route)
|
||||
handler, err := s.Handler(route, io)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mux.Handle(route, handler)
|
||||
}
|
||||
}
|
||||
return mux, nil
|
||||
}
|
||||
|
|
|
|||
84
internal/component/resolver/resolver.go
Normal file
84
internal/component/resolver/resolver.go
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package resolver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/FAU-CDI/wdresolve"
|
||||
"github.com/FAU-CDI/wdresolve/resolvers"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/control"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/lazy"
|
||||
"github.com/tkw1536/goprogram/stream"
|
||||
)
|
||||
|
||||
type Resolver struct {
|
||||
component.ComponentBase
|
||||
|
||||
Control *control.Control
|
||||
ResolverFile string
|
||||
|
||||
handler lazy.Lazy[wdresolve.ResolveHandler]
|
||||
}
|
||||
|
||||
func (Resolver) Name() string { return "resolver" }
|
||||
|
||||
func (resolver *Resolver) Routes() []string { return []string{"/go/", "/wisski/get/"} }
|
||||
|
||||
func (resolver *Resolver) Handler(route string, io stream.IOStream) (http.Handler, error) {
|
||||
var err error
|
||||
return resolver.handler.Get(func() (p wdresolve.ResolveHandler) {
|
||||
p.TrustXForwardedProto = true
|
||||
|
||||
fallback := &resolvers.Regexp{
|
||||
Data: map[string]string{},
|
||||
}
|
||||
|
||||
// handle the default domain name!
|
||||
domainName := resolver.Config.DefaultDomain
|
||||
if domainName != "" {
|
||||
fallback.Data[fmt.Sprintf("^https?://(.*)\\.%s", regexp.QuoteMeta(domainName))] = fmt.Sprintf("https://$1.%s", domainName)
|
||||
io.Printf("registering default domain %s\n", domainName)
|
||||
}
|
||||
|
||||
// handle the extra domains!
|
||||
for _, domain := range resolver.Config.SelfExtraDomains {
|
||||
fallback.Data[fmt.Sprintf("^https?://(.*)\\.%s", regexp.QuoteMeta(domain))] = fmt.Sprintf("https://$1.%s", domainName)
|
||||
io.Printf("registering legacy domain %s\n", domain)
|
||||
}
|
||||
|
||||
configPath := resolver.ConfigPath()
|
||||
{
|
||||
// load the prefix path!
|
||||
var fs fs.File
|
||||
fs, err = resolver.Environment.Open(configPath)
|
||||
io.Println("loading prefixes from ", configPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer fs.Close()
|
||||
|
||||
// read the file
|
||||
var prefixes resolvers.Prefix
|
||||
prefixes, err = resolvers.ReadPrefixes(fs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// and use that as the resolver!
|
||||
p.Resolver = resolvers.InOrder{
|
||||
prefixes,
|
||||
fallback,
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
}), err
|
||||
}
|
||||
|
||||
func (resolver *Resolver) ConfigPath() string {
|
||||
return filepath.Join(resolver.Control.Path(), resolver.ResolverFile)
|
||||
}
|
||||
18
internal/component/server.go
Normal file
18
internal/component/server.go
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package component
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/tkw1536/goprogram/stream"
|
||||
)
|
||||
|
||||
// Servable implements a component with a Serve method
|
||||
type Servable interface {
|
||||
Component
|
||||
|
||||
// Routes returns the routes served by this servable
|
||||
Routes() []string
|
||||
|
||||
// Handler returns the handler for the requested route
|
||||
Handler(route string, io stream.IOStream) (http.Handler, error)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Package config provides the distillery configuration
|
||||
// Package config contains distillery configuration
|
||||
package config
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package config
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// This file contains domain related derived configuration values.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/control"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/instances"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/resolver"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/snapshots"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/sql"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/ssh"
|
||||
|
|
@ -49,7 +50,7 @@ func (dis *Distillery) cWeb(thread int32) *web.Web {
|
|||
func (dis *Distillery) cControl(thread int32) *control.Control {
|
||||
return component.InitComponent(&dis.pool, thread, dis.Core, func(control *control.Control, thread int32) {
|
||||
control.ResolverFile = core.PrefixConfig
|
||||
control.Instances = dis.cInstances(thread)
|
||||
control.Servables = dis.cServables(thread)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -89,6 +90,13 @@ func (dis *Distillery) cSnapshotManager(thread int32) *snapshots.Manager {
|
|||
})
|
||||
}
|
||||
|
||||
func (dis *Distillery) cResolver(thread int32) *resolver.Resolver {
|
||||
return component.InitComponent(&dis.pool, thread, dis.Core, func(resolver *resolver.Resolver, thread int32) {
|
||||
resolver.Control = dis.cControl(thread)
|
||||
resolver.ResolverFile = core.PrefixConfig
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// ALL COMPONENTS
|
||||
//
|
||||
|
|
@ -96,7 +104,6 @@ func (dis *Distillery) cSnapshotManager(thread int32) *snapshots.Manager {
|
|||
func (dis *Distillery) cComponents(thread int32) []component.Component {
|
||||
return []component.Component{
|
||||
dis.cWeb(thread),
|
||||
dis.cControl(thread),
|
||||
dis.cSSH(thread),
|
||||
dis.cTriplestore(thread),
|
||||
dis.cSQL(thread),
|
||||
|
|
@ -110,6 +117,16 @@ func (dis *Distillery) cComponents(thread int32) []component.Component {
|
|||
c(dis, thread, func(pbs *snapshots.Pathbuilders, thread int32) {
|
||||
pbs.Instances = dis.cInstances(thread)
|
||||
}),
|
||||
|
||||
// Control server
|
||||
dis.cControl(thread),
|
||||
c(dis, thread, func(sh *control.SelfHandler, thread int32) {
|
||||
sh.Instances = dis.cInstances(thread)
|
||||
}),
|
||||
dis.cResolver(thread),
|
||||
c(dis, thread, func(info *control.Info, thread int32) {
|
||||
info.Instances = dis.cInstances(thread)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,6 +154,10 @@ func (dis *Distillery) cSnapshotable(thread int32) []component.Snapshotable {
|
|||
return getComponentSubtype[component.Snapshotable](dis, thread)
|
||||
}
|
||||
|
||||
func (dis *Distillery) cServables(thread int32) []component.Servable {
|
||||
return getComponentSubtype[component.Servable](dis, thread)
|
||||
}
|
||||
|
||||
func getComponentSubtype[C component.Component](dis *Distillery, thread int32) (components []C) {
|
||||
all := dis.cComponents(thread)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/control"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/instances"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/resolver"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/snapshots"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/sql"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/ssh"
|
||||
|
|
@ -49,6 +50,9 @@ func (dis *Distillery) Context() context.Context {
|
|||
func (dis *Distillery) Control() *control.Control {
|
||||
return dis.cControl(dis.thread())
|
||||
}
|
||||
func (dis *Distillery) Resolver() *resolver.Resolver {
|
||||
return dis.cResolver(dis.thread())
|
||||
}
|
||||
func (dis *Distillery) SSH() *ssh.SSH {
|
||||
return dis.cSSH(dis.thread())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue