github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/migrationmaster/manifold.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package migrationmaster
     5  
     6  import (
     7  	"github.com/juju/clock"
     8  	"github.com/juju/errors"
     9  	"github.com/juju/worker/v3"
    10  	"github.com/juju/worker/v3/dependency"
    11  
    12  	"github.com/juju/juju/agent"
    13  	"github.com/juju/juju/api"
    14  	"github.com/juju/juju/api/base"
    15  	"github.com/juju/juju/api/client/charms"
    16  	"github.com/juju/juju/api/http"
    17  	"github.com/juju/juju/migration"
    18  	"github.com/juju/juju/worker/fortress"
    19  )
    20  
    21  // logger is here to stop the desire of creating a package level logger.
    22  // Don't do this, instead pass one passed as manifold config.
    23  type logger interface{}
    24  
    25  var _ logger = struct{}{}
    26  
    27  // ManifoldConfig defines the names of the manifolds on which a
    28  // Worker manifold will depend.
    29  type ManifoldConfig struct {
    30  	AgentName     string
    31  	APICallerName string
    32  	FortressName  string
    33  
    34  	Clock     clock.Clock
    35  	NewFacade func(base.APICaller) (Facade, error)
    36  	NewWorker func(Config) (worker.Worker, error)
    37  }
    38  
    39  // Validate is called by start to check for bad configuration.
    40  func (config ManifoldConfig) Validate() error {
    41  	if config.AgentName == "" {
    42  		return errors.NotValidf("empty AgentName")
    43  	}
    44  	if config.APICallerName == "" {
    45  		return errors.NotValidf("empty APICallerName")
    46  	}
    47  	if config.FortressName == "" {
    48  		return errors.NotValidf("empty FortressName")
    49  	}
    50  	if config.NewFacade == nil {
    51  		return errors.NotValidf("nil NewFacade")
    52  	}
    53  	if config.NewWorker == nil {
    54  		return errors.NotValidf("nil NewWorker")
    55  	}
    56  	if config.Clock == nil {
    57  		return errors.NotValidf("nil Clock")
    58  	}
    59  	return nil
    60  }
    61  
    62  // start is a StartFunc for a Worker manifold.
    63  func (config ManifoldConfig) start(context dependency.Context) (worker.Worker, error) {
    64  	if err := config.Validate(); err != nil {
    65  		return nil, errors.Trace(err)
    66  	}
    67  
    68  	var agent agent.Agent
    69  	if err := context.Get(config.AgentName, &agent); err != nil {
    70  		return nil, errors.Trace(err)
    71  	}
    72  	var apiConn api.Connection
    73  	if err := context.Get(config.APICallerName, &apiConn); err != nil {
    74  		return nil, errors.Trace(err)
    75  	}
    76  	var guard fortress.Guard
    77  	if err := context.Get(config.FortressName, &guard); err != nil {
    78  		return nil, errors.Trace(err)
    79  	}
    80  	facade, err := config.NewFacade(apiConn)
    81  	if err != nil {
    82  		return nil, errors.Trace(err)
    83  	}
    84  	charmDownloader, err := charms.NewCharmOpener(apiConn)
    85  	if err != nil {
    86  		return nil, errors.Trace(err)
    87  	}
    88  	toolsDownloader, err := http.NewURIOpener(apiConn)
    89  	if err != nil {
    90  		return nil, errors.Trace(err)
    91  	}
    92  	w, err := config.NewWorker(Config{
    93  		ModelUUID:       agent.CurrentConfig().Model().Id(),
    94  		Facade:          facade,
    95  		Guard:           guard,
    96  		APIOpen:         api.Open,
    97  		UploadBinaries:  migration.UploadBinaries,
    98  		CharmDownloader: charmDownloader,
    99  		ToolsDownloader: toolsDownloader,
   100  		Clock:           config.Clock,
   101  	})
   102  	if err != nil {
   103  		return nil, errors.Trace(err)
   104  	}
   105  	return w, nil
   106  }
   107  
   108  func errorFilter(err error) error {
   109  	switch errors.Cause(err) {
   110  	case ErrMigrated:
   111  		// If the model has migrated, the migrationmaster should no
   112  		// longer be running.
   113  		return dependency.ErrUninstall
   114  	case ErrInactive:
   115  		// If the migration is no longer active, restart the
   116  		// migrationmaster immediately so it can wait for the next
   117  		// attempt.
   118  		return dependency.ErrBounce
   119  	default:
   120  		return err
   121  	}
   122  }
   123  
   124  // Manifold packages a Worker for use in a dependency.Engine.
   125  func Manifold(config ManifoldConfig) dependency.Manifold {
   126  	return dependency.Manifold{
   127  		Inputs: []string{
   128  			config.AgentName,
   129  			config.APICallerName,
   130  			config.FortressName,
   131  		},
   132  		Start:  config.start,
   133  		Filter: errorFilter,
   134  	}
   135  }