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

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package caasoperator
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/clock"
    10  	"github.com/juju/errors"
    11  	"gopkg.in/juju/names.v2"
    12  	"gopkg.in/juju/worker.v1"
    13  	"gopkg.in/juju/worker.v1/dependency"
    14  
    15  	"github.com/juju/juju/agent"
    16  	"github.com/juju/juju/api/base"
    17  	apileadership "github.com/juju/juju/api/leadership"
    18  	apiuniter "github.com/juju/juju/api/uniter"
    19  	"github.com/juju/juju/apiserver/params"
    20  	coreleadership "github.com/juju/juju/core/leadership"
    21  	"github.com/juju/juju/core/machinelock"
    22  	"github.com/juju/juju/worker/fortress"
    23  	"github.com/juju/juju/worker/leadership"
    24  	"github.com/juju/juju/worker/uniter"
    25  	"github.com/juju/juju/worker/uniter/operation"
    26  )
    27  
    28  // ManifoldConfig defines the names of the manifolds on which a
    29  // Manifold will depend.
    30  type ManifoldConfig struct {
    31  	AgentName     string
    32  	APICallerName string
    33  	ClockName     string
    34  
    35  	MachineLock           machinelock.Lock
    36  	LeadershipGuarantee   time.Duration
    37  	CharmDirName          string
    38  	HookRetryStrategyName string
    39  	TranslateResolverErr  func(error) error
    40  
    41  	NewWorker          func(Config) (worker.Worker, error)
    42  	NewClient          func(base.APICaller) Client
    43  	NewCharmDownloader func(base.APICaller) Downloader
    44  }
    45  
    46  func (config ManifoldConfig) Validate() error {
    47  	if config.AgentName == "" {
    48  		return errors.NotValidf("empty AgentName")
    49  	}
    50  	if config.APICallerName == "" {
    51  		return errors.NotValidf("empty APICallerName")
    52  	}
    53  	if config.ClockName == "" {
    54  		return errors.NotValidf("empty ClockName")
    55  	}
    56  	if config.NewWorker == nil {
    57  		return errors.NotValidf("missing NewWorker")
    58  	}
    59  	if config.NewClient == nil {
    60  		return errors.NotValidf("missing NewClient")
    61  	}
    62  	if config.NewCharmDownloader == nil {
    63  		return errors.NotValidf("missing NewCharmDownloader")
    64  	}
    65  	if config.CharmDirName == "" {
    66  		return errors.NotValidf("missing CharmDirName")
    67  	}
    68  	if config.MachineLock == nil {
    69  		return errors.NotValidf("missing MachineLock")
    70  	}
    71  	if config.HookRetryStrategyName == "" {
    72  		return errors.NotValidf("missing HookRetryStrategyName")
    73  	}
    74  	if config.LeadershipGuarantee == 0 {
    75  		return errors.NotValidf("missing LeadershipGuarantee")
    76  	}
    77  	return nil
    78  }
    79  
    80  // Manifold returns a dependency manifold that runs a caasoperator worker,
    81  // using the resource names defined in the supplied config.
    82  func Manifold(config ManifoldConfig) dependency.Manifold {
    83  	return dependency.Manifold{
    84  		Inputs: []string{
    85  			config.AgentName,
    86  			config.APICallerName,
    87  			config.ClockName,
    88  			config.CharmDirName,
    89  			config.HookRetryStrategyName,
    90  		},
    91  		Start: func(context dependency.Context) (worker.Worker, error) {
    92  			if err := config.Validate(); err != nil {
    93  				return nil, errors.Trace(err)
    94  			}
    95  
    96  			var agent agent.Agent
    97  			if err := context.Get(config.AgentName, &agent); err != nil {
    98  				return nil, errors.Trace(err)
    99  			}
   100  
   101  			var apiCaller base.APICaller
   102  			if err := context.Get(config.APICallerName, &apiCaller); err != nil {
   103  				return nil, errors.Trace(err)
   104  			}
   105  			client := config.NewClient(apiCaller)
   106  			downloader := config.NewCharmDownloader(apiCaller)
   107  
   108  			var clock clock.Clock
   109  			if err := context.Get(config.ClockName, &clock); err != nil {
   110  				return nil, errors.Trace(err)
   111  			}
   112  
   113  			model, err := client.Model()
   114  			if err != nil {
   115  				return nil, errors.Trace(err)
   116  			}
   117  
   118  			var charmDirGuard fortress.Guard
   119  			if err := context.Get(config.CharmDirName, &charmDirGuard); err != nil {
   120  				return nil, err
   121  			}
   122  
   123  			var hookRetryStrategy params.RetryStrategy
   124  			if err := context.Get(config.HookRetryStrategyName, &hookRetryStrategy); err != nil {
   125  				return nil, err
   126  			}
   127  
   128  			// Configure and start the caasoperator worker.
   129  			agentConfig := agent.CurrentConfig()
   130  			tag := agentConfig.Tag()
   131  			applicationTag, ok := tag.(names.ApplicationTag)
   132  			if !ok {
   133  				return nil, errors.Errorf("expected an application tag, got %v", tag)
   134  			}
   135  			newUniterFunc := func(unitTag names.UnitTag) *apiuniter.State {
   136  				return apiuniter.NewState(apiCaller, unitTag)
   137  			}
   138  			leadershipTrackerFunc := func(unitTag names.UnitTag) coreleadership.Tracker {
   139  				claimer := apileadership.NewClient(apiCaller)
   140  				return leadership.NewTracker(unitTag, claimer, clock, config.LeadershipGuarantee)
   141  			}
   142  			w, err := config.NewWorker(Config{
   143  				ModelUUID:          agentConfig.Model().Id(),
   144  				ModelName:          model.Name,
   145  				Application:        applicationTag.Id(),
   146  				CharmGetter:        client,
   147  				Clock:              clock,
   148  				PodSpecSetter:      client,
   149  				DataDir:            agentConfig.DataDir(),
   150  				Downloader:         downloader,
   151  				StatusSetter:       client,
   152  				UnitGetter:         client,
   153  				UnitRemover:        client,
   154  				ApplicationWatcher: client,
   155  				VersionSetter:      client,
   156  				StartUniterFunc:    uniter.StartUniter,
   157  
   158  				LeadershipTrackerFunc: leadershipTrackerFunc,
   159  				UniterFacadeFunc:      newUniterFunc,
   160  				UniterParams: &uniter.UniterParams{
   161  					NewOperationExecutor: operation.NewExecutor,
   162  					DataDir:              agentConfig.DataDir(),
   163  					Clock:                clock,
   164  					MachineLock:          config.MachineLock,
   165  					CharmDirGuard:        charmDirGuard,
   166  					UpdateStatusSignal:   uniter.NewUpdateStatusTimer(),
   167  					HookRetryStrategy:    hookRetryStrategy,
   168  					TranslateResolverErr: config.TranslateResolverErr,
   169  				},
   170  			})
   171  			if err != nil {
   172  				return nil, errors.Trace(err)
   173  			}
   174  			return w, nil
   175  		},
   176  	}
   177  }