github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/auditconfigupdater/manifold.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package auditconfigupdater
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/worker/v3"
     9  	"github.com/juju/worker/v3/dependency"
    10  
    11  	jujuagent "github.com/juju/juju/agent"
    12  	"github.com/juju/juju/core/auditlog"
    13  	"github.com/juju/juju/worker/common"
    14  	workerstate "github.com/juju/juju/worker/state"
    15  )
    16  
    17  // ManifoldConfig holds the information needed to run an
    18  // auditconfigupdater in a dependency.Engine.
    19  type ManifoldConfig struct {
    20  	AgentName string
    21  	StateName string
    22  	NewWorker func(ConfigSource, auditlog.Config, AuditLogFactory) (worker.Worker, error)
    23  }
    24  
    25  // Validate validates the manifold configuration.
    26  func (config ManifoldConfig) Validate() error {
    27  	if config.AgentName == "" {
    28  		return errors.NotValidf("empty AgentName")
    29  	}
    30  	if config.StateName == "" {
    31  		return errors.NotValidf("empty StateName")
    32  	}
    33  	if config.NewWorker == nil {
    34  		return errors.NotValidf("nil NewWorker")
    35  	}
    36  	return nil
    37  }
    38  
    39  // Manifold returns a dependency.Manifold to run an
    40  // auditconfigupdater.
    41  func Manifold(config ManifoldConfig) dependency.Manifold {
    42  	return dependency.Manifold{
    43  		Inputs: []string{
    44  			config.AgentName,
    45  			config.StateName,
    46  		},
    47  		Start:  config.start,
    48  		Output: output,
    49  	}
    50  }
    51  
    52  func (config ManifoldConfig) start(context dependency.Context) (_ worker.Worker, err error) {
    53  	if err := config.Validate(); err != nil {
    54  		return nil, errors.Trace(err)
    55  	}
    56  
    57  	var agent jujuagent.Agent
    58  	if err := context.Get(config.AgentName, &agent); err != nil {
    59  		return nil, errors.Trace(err)
    60  	}
    61  
    62  	var stTracker workerstate.StateTracker
    63  	if err := context.Get(config.StateName, &stTracker); err != nil {
    64  		return nil, errors.Trace(err)
    65  	}
    66  	statePool, err := stTracker.Use()
    67  	if err != nil {
    68  		return nil, errors.Trace(err)
    69  	}
    70  	defer func() {
    71  		if err != nil {
    72  			_ = stTracker.Done()
    73  		}
    74  	}()
    75  
    76  	logDir := agent.CurrentConfig().LogDir()
    77  
    78  	st, err := statePool.SystemState()
    79  	if err != nil {
    80  		return nil, errors.Trace(err)
    81  	}
    82  
    83  	logFactory := func(cfg auditlog.Config) auditlog.AuditLog {
    84  		return auditlog.NewLogFile(logDir, cfg.MaxSizeMB, cfg.MaxBackups)
    85  	}
    86  	auditConfig, err := initialConfig(st)
    87  	if err != nil {
    88  		return nil, errors.Trace(err)
    89  	}
    90  	if auditConfig.Enabled {
    91  		auditConfig.Target = logFactory(auditConfig)
    92  	}
    93  
    94  	w, err := config.NewWorker(st, auditConfig, logFactory)
    95  	if err != nil {
    96  		return nil, errors.Trace(err)
    97  	}
    98  	return common.NewCleanupWorker(w, func() { _ = stTracker.Done() }), nil
    99  }
   100  
   101  type withCurrentConfig interface {
   102  	CurrentConfig() auditlog.Config
   103  }
   104  
   105  func output(in worker.Worker, out interface{}) error {
   106  	if w, ok := in.(*common.CleanupWorker); ok {
   107  		in = w.Worker
   108  	}
   109  	w, ok := in.(withCurrentConfig)
   110  	if !ok {
   111  		return errors.Errorf("expected worker implementing CurrentConfig(), got %T", in)
   112  	}
   113  	target, ok := out.(*func() auditlog.Config)
   114  	if !ok {
   115  		return errors.Errorf("out should be *func() auditlog.Config; got %T", out)
   116  	}
   117  	*target = w.CurrentConfig
   118  	return nil
   119  }
   120  
   121  func initialConfig(source ConfigSource) (auditlog.Config, error) {
   122  	cfg, err := source.ControllerConfig()
   123  	if err != nil {
   124  		return auditlog.Config{}, errors.Trace(err)
   125  	}
   126  	result := auditlog.Config{
   127  		Enabled:        cfg.AuditingEnabled(),
   128  		CaptureAPIArgs: cfg.AuditLogCaptureArgs(),
   129  		MaxSizeMB:      cfg.AuditLogMaxSizeMB(),
   130  		MaxBackups:     cfg.AuditLogMaxBackups(),
   131  		ExcludeMethods: cfg.AuditLogExcludeMethods(),
   132  	}
   133  	return result, nil
   134  }