fetch_ml/internal/tracking/factory/loader.go
Jeremie Fraeys 4cdb68907e
refactor(utilities): update supporting modules for scheduler integration
Update utility modules:
- File utilities with secure file operations
- Environment pool with resource tracking
- Error types with scheduler error categories
- Logging with audit context support
- Network/SSH with connection pooling
- Privacy/PII handling with tenant boundaries
- Resource manager with scheduler allocation
- Security monitor with audit integration
- Tracking plugins (MLflow, TensorBoard) with auth
- Crypto signing with tenant keys
- Database init with multi-user support
2026-02-26 12:07:15 -05:00

116 lines
3.1 KiB
Go

package factory
import (
"fmt"
"github.com/jfraeys/fetch_ml/internal/container"
"github.com/jfraeys/fetch_ml/internal/logging"
"github.com/jfraeys/fetch_ml/internal/tracking"
"github.com/jfraeys/fetch_ml/internal/tracking/plugins"
)
// PluginConfig represents the configuration for a single plugin.
type PluginConfig struct {
Settings map[string]any `toml:"settings" yaml:"settings"`
Image string `toml:"image" yaml:"image"`
Mode string `toml:"mode" yaml:"mode"`
LogBasePath string `toml:"log_base_path" yaml:"log_base_path"`
ArtifactPath string `toml:"artifact_path" yaml:"artifact_path"`
Enabled bool `toml:"enabled" yaml:"enabled"`
}
// PluginFactory is a function that creates a Plugin instance.
type PluginFactory func(
logger *logging.Logger,
podman *container.PodmanManager,
cfg PluginConfig,
) (tracking.Plugin, error)
// PluginLoader uses dependency injection to load plugins.
type PluginLoader struct {
logger *logging.Logger
podman *container.PodmanManager
factories map[string]PluginFactory
}
// NewPluginLoader creates a new PluginLoader.
func NewPluginLoader(logger *logging.Logger, podman *container.PodmanManager) *PluginLoader {
loader := &PluginLoader{
logger: logger,
podman: podman,
factories: make(map[string]PluginFactory),
}
// Register default factories
loader.RegisterFactory("mlflow", createMLflowPlugin)
loader.RegisterFactory("tensorboard", createTensorBoardPlugin)
loader.RegisterFactory("wandb", createWandbPlugin)
return loader
}
// RegisterFactory allows external packages to register new plugin types (Marketplace ready).
func (l *PluginLoader) RegisterFactory(name string, factory PluginFactory) {
l.factories[name] = factory
}
// LoadPlugins loads plugins from the provided configuration map and registers them.
func (l *PluginLoader) LoadPlugins(
plugins map[string]PluginConfig,
registry *tracking.Registry,
) error {
for name, pluginCfg := range plugins {
if !pluginCfg.Enabled {
continue
}
factory, ok := l.factories[name]
if !ok {
l.logger.Warn("unknown plugin type", "name", name)
continue
}
plugin, err := factory(l.logger, l.podman, pluginCfg)
if err != nil {
return fmt.Errorf("failed to create plugin %s: %w", name, err)
}
registry.Register(plugin)
l.logger.Info("plugin loaded", "name", name, "mode", pluginCfg.Mode)
}
return nil
}
// Factory Implementations
func createMLflowPlugin(
logger *logging.Logger,
podman *container.PodmanManager,
cfg PluginConfig,
) (tracking.Plugin, error) {
opts := plugins.MLflowOptions{
Image: cfg.Image,
ArtifactBasePath: cfg.ArtifactPath,
}
return plugins.NewMLflowPlugin(logger, podman, opts)
}
func createTensorBoardPlugin(
logger *logging.Logger,
podman *container.PodmanManager,
cfg PluginConfig,
) (tracking.Plugin, error) {
opts := plugins.TensorBoardOptions{
Image: cfg.Image,
LogBasePath: cfg.LogBasePath,
}
return plugins.NewTensorBoardPlugin(logger, podman, opts)
}
func createWandbPlugin(
logger *logging.Logger,
_ *container.PodmanManager,
_ PluginConfig,
) (tracking.Plugin, error) {
return plugins.NewWandbPlugin(), nil
}