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

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package peergrouper
     5  
     6  import (
     7  	"github.com/juju/clock"
     8  	"github.com/juju/errors"
     9  	"gopkg.in/juju/worker.v1"
    10  	"gopkg.in/juju/worker.v1/dependency"
    11  
    12  	"github.com/juju/juju/agent"
    13  	"github.com/juju/juju/state"
    14  	"github.com/juju/juju/worker/common"
    15  	workerstate "github.com/juju/juju/worker/state"
    16  )
    17  
    18  // ManifoldConfig holds the information necessary to run a peergrouper
    19  // in a dependency.Engine.
    20  type ManifoldConfig struct {
    21  	AgentName                string
    22  	ClockName                string
    23  	ControllerPortName       string
    24  	StateName                string
    25  	Hub                      Hub
    26  	NewWorker                func(Config) (worker.Worker, error)
    27  	ControllerSupportsSpaces func(*state.State) (bool, error)
    28  }
    29  
    30  // Validate validates the manifold configuration.
    31  func (config ManifoldConfig) Validate() error {
    32  	if config.AgentName == "" {
    33  		return errors.NotValidf("empty AgentName")
    34  	}
    35  	if config.ClockName == "" {
    36  		return errors.NotValidf("empty ClockName")
    37  	}
    38  	if config.ControllerPortName == "" {
    39  		return errors.NotValidf("empty ControllerPortName")
    40  	}
    41  	if config.StateName == "" {
    42  		return errors.NotValidf("empty StateName")
    43  	}
    44  	if config.Hub == nil {
    45  		return errors.NotValidf("nil Hub")
    46  	}
    47  	if config.ControllerSupportsSpaces == nil {
    48  		return errors.NotValidf("nil ControllerSupportsSpaces")
    49  	}
    50  	if config.NewWorker == nil {
    51  		return errors.NotValidf("nil NewWorker")
    52  	}
    53  	return nil
    54  }
    55  
    56  // Manifold returns a dependency.Manifold that will run a peergrouper.
    57  func Manifold(config ManifoldConfig) dependency.Manifold {
    58  	return dependency.Manifold{
    59  		Inputs: []string{
    60  			config.AgentName,
    61  			config.ClockName,
    62  			config.ControllerPortName,
    63  			config.StateName,
    64  		},
    65  		Start: config.start,
    66  	}
    67  }
    68  
    69  // start is a method on ManifoldConfig because it's more readable than a closure.
    70  func (config ManifoldConfig) start(context dependency.Context) (worker.Worker, error) {
    71  	if err := config.Validate(); err != nil {
    72  		return nil, errors.Trace(err)
    73  	}
    74  
    75  	var agent agent.Agent
    76  	if err := context.Get(config.AgentName, &agent); err != nil {
    77  		return nil, errors.Trace(err)
    78  	}
    79  
    80  	var clock clock.Clock
    81  	if err := context.Get(config.ClockName, &clock); err != nil {
    82  		return nil, errors.Trace(err)
    83  	}
    84  
    85  	// Ensure that the controller-port worker is running.
    86  	if err := context.Get(config.ControllerPortName, nil); err != nil {
    87  		return nil, errors.Trace(err)
    88  	}
    89  
    90  	var stTracker workerstate.StateTracker
    91  	if err := context.Get(config.StateName, &stTracker); err != nil {
    92  		return nil, errors.Trace(err)
    93  	}
    94  	statePool, err := stTracker.Use()
    95  	if err != nil {
    96  		return nil, errors.Trace(err)
    97  	}
    98  
    99  	st := statePool.SystemState()
   100  	mongoSession := st.MongoSession()
   101  	agentConfig := agent.CurrentConfig()
   102  	stateServingInfo, ok := agentConfig.StateServingInfo()
   103  	if !ok {
   104  		return nil, errors.New("state serving info missing from agent config")
   105  	}
   106  
   107  	supportsSpaces, err := config.ControllerSupportsSpaces(st)
   108  	if err != nil {
   109  		return nil, errors.Trace(err)
   110  	}
   111  
   112  	w, err := config.NewWorker(Config{
   113  		State:              StateShim{st},
   114  		MongoSession:       MongoSessionShim{mongoSession},
   115  		APIHostPortsSetter: &CachingAPIHostPortsSetter{APIHostPortsSetter: st},
   116  		Clock:              clock,
   117  		Hub:                config.Hub,
   118  		SupportsSpaces:     supportsSpaces,
   119  		MongoPort:          stateServingInfo.StatePort,
   120  		APIPort:            stateServingInfo.APIPort,
   121  		ControllerAPIPort:  stateServingInfo.ControllerAPIPort,
   122  	})
   123  	if err != nil {
   124  		stTracker.Done()
   125  		return nil, errors.Trace(err)
   126  	}
   127  	return common.NewCleanupWorker(w, func() { stTracker.Done() }), nil
   128  }