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

     1  // Copyright 2015-2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package singular
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/clock"
    10  	"github.com/juju/errors"
    11  	"gopkg.in/juju/names.v2"
    12  	"gopkg.in/juju/worker.v1"
    13  	"gopkg.in/juju/worker.v1/dependency"
    14  
    15  	"github.com/juju/juju/api/base"
    16  	"github.com/juju/juju/cmd/jujud/agent/engine"
    17  )
    18  
    19  // ManifoldConfig holds the information necessary to run a FlagWorker in
    20  // a dependency.Engine.
    21  type ManifoldConfig struct {
    22  	ClockName     string
    23  	APICallerName string
    24  	Duration      time.Duration
    25  	Claimant      names.MachineTag
    26  	Entity        names.Tag
    27  
    28  	NewFacade func(base.APICaller, names.MachineTag, names.Tag) (Facade, error)
    29  	NewWorker func(FlagConfig) (worker.Worker, error)
    30  }
    31  
    32  // start is a method on ManifoldConfig because it's more readable than a closure.
    33  func (config ManifoldConfig) start(context dependency.Context) (worker.Worker, error) {
    34  	var clock clock.Clock
    35  	if err := context.Get(config.ClockName, &clock); err != nil {
    36  		return nil, errors.Trace(err)
    37  	}
    38  	var apiCaller base.APICaller
    39  	if err := context.Get(config.APICallerName, &apiCaller); err != nil {
    40  		return nil, errors.Trace(err)
    41  	}
    42  
    43  	facade, err := config.NewFacade(apiCaller, config.Claimant, config.Entity)
    44  	if err != nil {
    45  		return nil, errors.Trace(err)
    46  	}
    47  	flag, err := config.NewWorker(FlagConfig{
    48  		Clock:    clock,
    49  		Facade:   facade,
    50  		Duration: config.Duration,
    51  	})
    52  	if err != nil {
    53  		return nil, errors.Trace(err)
    54  	}
    55  	return wrappedWorker{flag}, nil
    56  }
    57  
    58  // wrappedWorker wraps a flag worker, translating ErrRefresh into
    59  // dependency.ErrBounce.
    60  type wrappedWorker struct {
    61  	worker.Worker
    62  }
    63  
    64  // Wait is part of the worker.Worker interface.
    65  func (w wrappedWorker) Wait() error {
    66  	err := w.Worker.Wait()
    67  	if err == ErrRefresh {
    68  		err = dependency.ErrBounce
    69  	}
    70  	return err
    71  }
    72  
    73  // Manifold returns a dependency.Manifold that will run a FlagWorker and
    74  // expose it to clients as a engine.Flag resource.
    75  func Manifold(config ManifoldConfig) dependency.Manifold {
    76  	return dependency.Manifold{
    77  		Inputs: []string{
    78  			config.ClockName,
    79  			config.APICallerName,
    80  		},
    81  		Start: config.start,
    82  		Output: func(in worker.Worker, out interface{}) error {
    83  			if w, ok := in.(wrappedWorker); ok {
    84  				in = w.Worker
    85  			}
    86  			return engine.FlagOutput(in, out)
    87  		},
    88  	}
    89  }