github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/worker/apicaller/manifold.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package apicaller
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  
     9  	"github.com/juju/juju/agent"
    10  	"github.com/juju/juju/api/base"
    11  	"github.com/juju/juju/worker"
    12  	"github.com/juju/juju/worker/dependency"
    13  	"github.com/juju/juju/worker/gate"
    14  )
    15  
    16  // ManifoldConfig defines the names of the manifolds on which a Manifold will depend.
    17  type ManifoldConfig struct {
    18  	AgentName       string
    19  	APIInfoGateName string
    20  }
    21  
    22  // Manifold returns a manifold whose worker wraps an API connection made on behalf of
    23  // the dependency identified by AgentName.
    24  func Manifold(config ManifoldConfig) dependency.Manifold {
    25  	return dependency.Manifold{
    26  		Inputs: []string{
    27  			config.AgentName,
    28  			config.APIInfoGateName,
    29  		},
    30  		Output: outputFunc,
    31  		Start:  startFunc(config),
    32  	}
    33  }
    34  
    35  // startFunc returns a StartFunc that creates a worker based on the manifolds
    36  // named in the supplied config.
    37  func startFunc(config ManifoldConfig) dependency.StartFunc {
    38  	return func(getResource dependency.GetResourceFunc) (worker.Worker, error) {
    39  
    40  		// Get dependencies and open a connection.
    41  		var gate gate.Unlocker
    42  		if err := getResource(config.APIInfoGateName, &gate); err != nil {
    43  			return nil, err
    44  		}
    45  		var a agent.Agent
    46  		if err := getResource(config.AgentName, &a); err != nil {
    47  			return nil, err
    48  		}
    49  		conn, err := openConnection(a)
    50  		if err != nil {
    51  			return nil, errors.Annotate(err, "cannot open api")
    52  		}
    53  
    54  		// Add the environment uuid to agent config if not present.
    55  		currentConfig := a.CurrentConfig()
    56  		if currentConfig.Environment().Id() == "" {
    57  			err := a.ChangeConfig(func(setter agent.ConfigSetter) error {
    58  				environTag, err := conn.EnvironTag()
    59  				if err != nil {
    60  					return errors.Annotate(err, "no environment uuid set on api")
    61  				}
    62  				return setter.Migrate(agent.MigrateParams{
    63  					Environment: environTag,
    64  				})
    65  			})
    66  			if err != nil {
    67  				logger.Warningf("unable to save environment uuid: %v", err)
    68  				// Not really fatal, just annoying.
    69  			}
    70  		}
    71  
    72  		// Now we know the agent config has been fixed up, notify everyone
    73  		// else who might depend upon its stability/correctness.
    74  		gate.Unlock()
    75  
    76  		// Return the worker.
    77  		return newApiConnWorker(conn)
    78  	}
    79  }
    80  
    81  // outputFunc extracts a base.APICaller from a *apiConnWorker.
    82  func outputFunc(in worker.Worker, out interface{}) error {
    83  	inWorker, _ := in.(*apiConnWorker)
    84  	outPointer, _ := out.(*base.APICaller)
    85  	if inWorker == nil || outPointer == nil {
    86  		return errors.Errorf("expected %T->%T; got %T->%T", inWorker, outPointer, in, out)
    87  	}
    88  	*outPointer = inWorker.conn
    89  	return nil
    90  }