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

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package deployer
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  	"gopkg.in/juju/worker.v1"
    10  	"gopkg.in/juju/worker.v1/dependency"
    11  
    12  	"github.com/juju/juju/agent"
    13  	apiagent "github.com/juju/juju/api/agent"
    14  	"github.com/juju/juju/api/base"
    15  	apideployer "github.com/juju/juju/api/deployer"
    16  	"github.com/juju/juju/cmd/jujud/agent/engine"
    17  	"github.com/juju/juju/state/multiwatcher"
    18  )
    19  
    20  // ManifoldConfig defines the names of the manifolds on which a Manifold will depend.
    21  type ManifoldConfig struct {
    22  	AgentName        string
    23  	APICallerName    string
    24  	NewDeployContext func(st *apideployer.State, agentConfig agent.Config) Context
    25  }
    26  
    27  // Manifold returns a dependency manifold that runs a deployer worker,
    28  // using the resource names defined in the supplied config.
    29  func Manifold(config ManifoldConfig) dependency.Manifold {
    30  	typedConfig := engine.AgentAPIManifoldConfig{
    31  		AgentName:     config.AgentName,
    32  		APICallerName: config.APICallerName,
    33  	}
    34  	return engine.AgentAPIManifold(typedConfig, config.newWorker)
    35  }
    36  
    37  // newWorker trivially wraps NewDeployer for use in a engine.AgentAPIManifold.
    38  //
    39  // It's not tested at the moment, because the scaffolding
    40  // necessary is too unwieldy/distracting to introduce at this point.
    41  func (config ManifoldConfig) newWorker(a agent.Agent, apiCaller base.APICaller) (worker.Worker, error) {
    42  	cfg := a.CurrentConfig()
    43  	// Grab the tag and ensure that it's for a machine.
    44  	tag, ok := cfg.Tag().(names.MachineTag)
    45  	if !ok {
    46  		return nil, errors.New("agent's tag is not a machine tag")
    47  	}
    48  
    49  	// Get the machine agent's jobs.
    50  	// TODO(fwereade): this functionality should be on the
    51  	// deployer facade instead.
    52  	agentFacade, err := apiagent.NewState(apiCaller)
    53  	if err != nil {
    54  		return nil, errors.Trace(err)
    55  	}
    56  	entity, err := agentFacade.Entity(tag)
    57  	if err != nil {
    58  		return nil, errors.Trace(err)
    59  	}
    60  
    61  	var isUnitHoster bool
    62  	for _, job := range entity.Jobs() {
    63  		if job == multiwatcher.JobHostUnits {
    64  			isUnitHoster = true
    65  			break
    66  		}
    67  	}
    68  
    69  	if !isUnitHoster {
    70  		return nil, dependency.ErrUninstall
    71  	}
    72  
    73  	deployerFacade := apideployer.NewState(apiCaller)
    74  	context := config.NewDeployContext(deployerFacade, cfg)
    75  	w, err := NewDeployer(deployerFacade, context)
    76  	if err != nil {
    77  		return nil, errors.Annotate(err, "cannot start unit agent deployer worker")
    78  	}
    79  	return w, nil
    80  }