github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/leadership/manifold.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package leadership
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/juju/errors"
    11  	"github.com/juju/utils/clock"
    12  	"gopkg.in/juju/names.v2"
    13  
    14  	"github.com/juju/juju/agent"
    15  	"github.com/juju/juju/api/base"
    16  	"github.com/juju/juju/api/leadership"
    17  	coreleadership "github.com/juju/juju/core/leadership"
    18  	"github.com/juju/juju/worker"
    19  	"github.com/juju/juju/worker/dependency"
    20  )
    21  
    22  // ManifoldConfig defines the names of the manifolds on which a Manifold will depend.
    23  type ManifoldConfig struct {
    24  	AgentName           string
    25  	APICallerName       string
    26  	Clock               clock.Clock
    27  	LeadershipGuarantee time.Duration
    28  }
    29  
    30  // Manifold returns a manifold whose worker wraps a Tracker working on behalf of
    31  // the dependency identified by AgentName.
    32  func Manifold(config ManifoldConfig) dependency.Manifold {
    33  	return dependency.Manifold{
    34  		Inputs: []string{
    35  			config.AgentName,
    36  			config.APICallerName,
    37  		},
    38  		Start:  startFunc(config),
    39  		Output: outputFunc,
    40  	}
    41  }
    42  
    43  // startFunc returns a StartFunc that creates a worker based on the manifolds
    44  // named in the supplied config.
    45  func startFunc(config ManifoldConfig) dependency.StartFunc {
    46  	return func(context dependency.Context) (worker.Worker, error) {
    47  		if config.Clock == nil {
    48  			return nil, errors.NotValidf("missing Clock")
    49  		}
    50  		var agent agent.Agent
    51  		if err := context.Get(config.AgentName, &agent); err != nil {
    52  			return nil, err
    53  		}
    54  		var apiCaller base.APICaller
    55  		if err := context.Get(config.APICallerName, &apiCaller); err != nil {
    56  			return nil, err
    57  		}
    58  		return NewManifoldWorker(agent, apiCaller, config.Clock, config.LeadershipGuarantee)
    59  	}
    60  }
    61  
    62  // NewManifoldWorker wraps NewTracker for the convenience of startFunc. It
    63  // exists primarily to be patched out via NewManifoldWorker for ease of testing,
    64  // and is not itself directly tested. It would almost certainly be better to
    65  // pass the constructor dependencies in as explicit manifold config.
    66  var NewManifoldWorker = func(agent agent.Agent, apiCaller base.APICaller, clock clock.Clock, guarantee time.Duration) (worker.Worker, error) {
    67  	tag := agent.CurrentConfig().Tag()
    68  	unitTag, ok := tag.(names.UnitTag)
    69  	if !ok {
    70  		return nil, fmt.Errorf("expected a unit tag; got %q", tag)
    71  	}
    72  	claimer := leadership.NewClient(apiCaller)
    73  	return NewTracker(unitTag, claimer, clock, guarantee), nil
    74  }
    75  
    76  // outputFunc extracts the coreleadership.Tracker from a *Tracker passed in as a Worker.
    77  func outputFunc(in worker.Worker, out interface{}) error {
    78  	inWorker, _ := in.(*Tracker)
    79  	if inWorker == nil {
    80  		return errors.Errorf("expected *Tracker input; got %T", in)
    81  	}
    82  	outPointer, _ := out.(*coreleadership.Tracker)
    83  	if outPointer == nil {
    84  		return errors.Errorf("expected *leadership.Tracker output; got %T", out)
    85  	}
    86  	*outPointer = inWorker
    87  	return nil
    88  }