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