github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/uniter/manifold.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package uniter
     5  
     6  import (
     7  	"github.com/juju/clock"
     8  	"github.com/juju/errors"
     9  	"gopkg.in/juju/names.v2"
    10  	"gopkg.in/juju/worker.v1"
    11  	"gopkg.in/juju/worker.v1/dependency"
    12  
    13  	"github.com/juju/juju/agent"
    14  	"github.com/juju/juju/api"
    15  	"github.com/juju/juju/api/uniter"
    16  	"github.com/juju/juju/apiserver/params"
    17  	"github.com/juju/juju/core/leadership"
    18  	"github.com/juju/juju/core/machinelock"
    19  	"github.com/juju/juju/worker/fortress"
    20  	"github.com/juju/juju/worker/uniter/operation"
    21  	"github.com/juju/juju/worker/uniter/resolver"
    22  )
    23  
    24  // ManifoldConfig defines the names of the manifolds on which a
    25  // Manifold will depend.
    26  type ManifoldConfig struct {
    27  	AgentName             string
    28  	APICallerName         string
    29  	MachineLock           machinelock.Lock
    30  	Clock                 clock.Clock
    31  	LeadershipTrackerName string
    32  	CharmDirName          string
    33  	HookRetryStrategyName string
    34  	TranslateResolverErr  func(error) error
    35  }
    36  
    37  // Manifold returns a dependency manifold that runs a uniter worker,
    38  // using the resource names defined in the supplied config.
    39  func Manifold(config ManifoldConfig) dependency.Manifold {
    40  	return dependency.Manifold{
    41  		Inputs: []string{
    42  			config.AgentName,
    43  			config.APICallerName,
    44  			config.LeadershipTrackerName,
    45  			config.CharmDirName,
    46  			config.HookRetryStrategyName,
    47  		},
    48  		Start: func(context dependency.Context) (worker.Worker, error) {
    49  			if config.Clock == nil {
    50  				return nil, errors.NotValidf("missing Clock")
    51  			}
    52  			if config.MachineLock == nil {
    53  				return nil, errors.NotValidf("missing MachineLock")
    54  			}
    55  
    56  			// Collect all required resources.
    57  			var agent agent.Agent
    58  			if err := context.Get(config.AgentName, &agent); err != nil {
    59  				return nil, err
    60  			}
    61  			var apiConn api.Connection
    62  			if err := context.Get(config.APICallerName, &apiConn); err != nil {
    63  				// TODO(fwereade): absence of an APICaller shouldn't be the end of
    64  				// the world -- we ought to return a type that can at least run the
    65  				// leader-deposed hook -- but that's not done yet.
    66  				return nil, err
    67  			}
    68  			var leadershipTracker leadership.Tracker
    69  			if err := context.Get(config.LeadershipTrackerName, &leadershipTracker); err != nil {
    70  				return nil, err
    71  			}
    72  			var charmDirGuard fortress.Guard
    73  			if err := context.Get(config.CharmDirName, &charmDirGuard); err != nil {
    74  				return nil, err
    75  			}
    76  
    77  			var hookRetryStrategy params.RetryStrategy
    78  			if err := context.Get(config.HookRetryStrategyName, &hookRetryStrategy); err != nil {
    79  				return nil, err
    80  			}
    81  
    82  			downloader := api.NewCharmDownloader(apiConn)
    83  
    84  			manifoldConfig := config
    85  			// Configure and start the uniter.
    86  			agentConfig := agent.CurrentConfig()
    87  			tag := agentConfig.Tag()
    88  			unitTag, ok := tag.(names.UnitTag)
    89  			if !ok {
    90  				return nil, errors.Errorf("expected a unit tag, got %v", tag)
    91  			}
    92  			uniterFacade := uniter.NewState(apiConn, unitTag)
    93  			uniter, err := NewUniter(&UniterParams{
    94  				UniterFacade:         uniterFacade,
    95  				UnitTag:              unitTag,
    96  				LeadershipTracker:    leadershipTracker,
    97  				DataDir:              agentConfig.DataDir(),
    98  				Downloader:           downloader,
    99  				MachineLock:          manifoldConfig.MachineLock,
   100  				CharmDirGuard:        charmDirGuard,
   101  				UpdateStatusSignal:   NewUpdateStatusTimer(),
   102  				HookRetryStrategy:    hookRetryStrategy,
   103  				NewOperationExecutor: operation.NewExecutor,
   104  				TranslateResolverErr: config.TranslateResolverErr,
   105  				Clock:                manifoldConfig.Clock,
   106  			})
   107  			if err != nil {
   108  				return nil, errors.Trace(err)
   109  			}
   110  			return uniter, nil
   111  		},
   112  	}
   113  }
   114  
   115  // TranslateFortressErrors turns errors returned by dependent
   116  // manifolds due to fortress lockdown (i.e. model migration) into an
   117  // error which causes the resolver loop to be restarted. When this
   118  // happens the uniter is about to be shut down anyway.
   119  func TranslateFortressErrors(err error) error {
   120  	if fortress.IsFortressError(err) {
   121  		return resolver.ErrRestart
   122  	}
   123  	return err
   124  }