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

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package upgradesteps
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/agent"
    11  	"github.com/juju/juju/api"
    12  	apiagent "github.com/juju/juju/api/agent"
    13  	apimachiner "github.com/juju/juju/api/machiner"
    14  	"github.com/juju/juju/state"
    15  	"github.com/juju/juju/worker"
    16  	"github.com/juju/juju/worker/dependency"
    17  	"github.com/juju/juju/worker/gate"
    18  )
    19  
    20  // ManifoldConfig defines the names of the manifolds on which a
    21  // Manifold will depend.
    22  type ManifoldConfig struct {
    23  	AgentName            string
    24  	APICallerName        string
    25  	UpgradeStepsGateName string
    26  	OpenStateForUpgrade  func() (*state.State, error)
    27  	PreUpgradeSteps      func(*state.State, agent.Config, bool, bool) error
    28  }
    29  
    30  // Manifold returns a dependency manifold that runs an upgrader
    31  // worker, using the resource names defined in the supplied config.
    32  func Manifold(config ManifoldConfig) dependency.Manifold {
    33  	return dependency.Manifold{
    34  		Inputs: []string{
    35  			config.AgentName,
    36  			config.APICallerName,
    37  			config.UpgradeStepsGateName,
    38  		},
    39  		Start: func(context dependency.Context) (worker.Worker, error) {
    40  			// Sanity checks
    41  			if config.OpenStateForUpgrade == nil {
    42  				return nil, errors.New("missing OpenStateForUpgrade in config")
    43  			}
    44  			if config.PreUpgradeSteps == nil {
    45  				return nil, errors.New("missing PreUpgradeSteps in config")
    46  			}
    47  
    48  			// Get machine agent.
    49  			var agent agent.Agent
    50  			if err := context.Get(config.AgentName, &agent); err != nil {
    51  				return nil, err
    52  			}
    53  
    54  			// Grab the tag and ensure that it's for a machine.
    55  			tag, ok := agent.CurrentConfig().Tag().(names.MachineTag)
    56  			if !ok {
    57  				return nil, errors.New("agent's tag is not a machine tag")
    58  			}
    59  
    60  			// Get API connection.
    61  			// TODO(fwereade): can we make the worker use an
    62  			// APICaller instead? should be able to depend on
    63  			// the Engine to abort us when conn is closed...
    64  			var apiConn api.Connection
    65  			if err := context.Get(config.APICallerName, &apiConn); err != nil {
    66  				return nil, err
    67  			}
    68  
    69  			// Get the machine agent's jobs.
    70  			// TODO(fwereade): use appropriate facade!
    71  			agentFacade := apiagent.NewState(apiConn)
    72  			entity, err := agentFacade.Entity(tag)
    73  			if err != nil {
    74  				return nil, err
    75  			}
    76  			jobs := entity.Jobs()
    77  
    78  			// Get machine instance for setting status on.
    79  			// TODO(fwereade): use appropriate facade!
    80  			machinerFacade := apimachiner.NewState(apiConn)
    81  			machine, err := machinerFacade.Machine(tag)
    82  			if err != nil {
    83  				return nil, err
    84  			}
    85  
    86  			// Get upgradesteps completed lock.
    87  			var upgradeStepsLock gate.Lock
    88  			if err := context.Get(config.UpgradeStepsGateName, &upgradeStepsLock); err != nil {
    89  				return nil, err
    90  			}
    91  
    92  			return NewWorker(
    93  				upgradeStepsLock,
    94  				agent,
    95  				apiConn,
    96  				jobs,
    97  				config.OpenStateForUpgrade,
    98  				config.PreUpgradeSteps,
    99  				machine,
   100  			)
   101  		},
   102  	}
   103  }