github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/containerbroker/manifold.go (about)

     1  // Copyright 2019 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package containerbroker
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/worker/v3"
     9  	"github.com/juju/worker/v3/dependency"
    10  
    11  	"github.com/juju/juju/agent"
    12  	"github.com/juju/juju/api/agent/provisioner"
    13  	"github.com/juju/juju/api/base"
    14  	"github.com/juju/juju/container/broker"
    15  	"github.com/juju/juju/core/machinelock"
    16  	"github.com/juju/juju/environs"
    17  )
    18  
    19  // ManifoldConfig describes the resources used by a Tracker.
    20  type ManifoldConfig struct {
    21  	AgentName     string
    22  	APICallerName string
    23  	MachineLock   machinelock.Lock
    24  	NewBrokerFunc func(broker.Config) (environs.InstanceBroker, error)
    25  	NewTracker    func(Config) (worker.Worker, error)
    26  }
    27  
    28  // Validate validates the manifold configuration.
    29  func (config ManifoldConfig) Validate() error {
    30  	if config.AgentName == "" {
    31  		return errors.NotValidf("empty AgentName")
    32  	}
    33  	if config.APICallerName == "" {
    34  		return errors.NotValidf("empty APICallerName")
    35  	}
    36  	if config.MachineLock == nil {
    37  		return errors.NotValidf("nil MachineLock")
    38  	}
    39  	if config.NewBrokerFunc == nil {
    40  		return errors.NotValidf("nil NewBrokerFunc")
    41  	}
    42  	if config.NewTracker == nil {
    43  		return errors.NotValidf("nil NewTracker")
    44  	}
    45  	return nil
    46  }
    47  
    48  // Manifold returns a Manifold that encapsulates a *Tracker and exposes it as
    49  // an Broker resource.
    50  func Manifold(config ManifoldConfig) dependency.Manifold {
    51  	return dependency.Manifold{
    52  		Inputs: []string{
    53  			config.AgentName,
    54  			config.APICallerName,
    55  		},
    56  		Output: manifoldOutput,
    57  		Start: func(context dependency.Context) (worker.Worker, error) {
    58  			if err := config.Validate(); err != nil {
    59  				return nil, errors.Trace(err)
    60  			}
    61  
    62  			var agent agent.Agent
    63  			if err := context.Get(config.AgentName, &agent); err != nil {
    64  				return nil, errors.Trace(err)
    65  			}
    66  			var apiCaller base.APICaller
    67  			if err := context.Get(config.APICallerName, &apiCaller); err != nil {
    68  				return nil, errors.Trace(err)
    69  			}
    70  			w, err := config.NewTracker(Config{
    71  				APICaller:     apiCaller,
    72  				AgentConfig:   agent.CurrentConfig(),
    73  				MachineLock:   config.MachineLock,
    74  				NewBrokerFunc: config.NewBrokerFunc,
    75  				NewStateFunc: func(apiCaller base.APICaller) State {
    76  					return provisioner.NewState(apiCaller)
    77  				},
    78  			})
    79  			if err != nil {
    80  				return nil, errors.Trace(err)
    81  			}
    82  			return w, nil
    83  		},
    84  	}
    85  }
    86  
    87  // manifoldOutput extracts an environs.Environ resource from a *Tracker.
    88  func manifoldOutput(in worker.Worker, out interface{}) error {
    89  	inTracker, ok := in.(*Tracker)
    90  	if !ok {
    91  		return errors.Errorf("expected *broker.Tracker, got %T", in)
    92  	}
    93  	switch result := out.(type) {
    94  	case *environs.InstanceBroker:
    95  		*result = inTracker.Broker()
    96  	default:
    97  		return errors.Errorf("expected *environs.InstanceBroker got %T", out)
    98  	}
    99  	return nil
   100  }