github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/worker/uniter/operation/factory.go (about)

     1  // Copyright 2014-2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package operation
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names"
     9  	corecharm "gopkg.in/juju/charm.v5"
    10  
    11  	"github.com/juju/juju/worker/uniter/charm"
    12  	"github.com/juju/juju/worker/uniter/hook"
    13  	"github.com/juju/juju/worker/uniter/runner"
    14  )
    15  
    16  // FactoryParams holds all the necessary parameters for a new operation factory.
    17  type FactoryParams struct {
    18  	Deployer       charm.Deployer
    19  	RunnerFactory  runner.Factory
    20  	Callbacks      Callbacks
    21  	StorageUpdater StorageUpdater
    22  	Abort          <-chan struct{}
    23  	MetricSender   apiMetricSender
    24  	MetricSpoolDir string
    25  }
    26  
    27  // NewFactory returns a Factory that creates Operations backed by the supplied
    28  // parameters.
    29  func NewFactory(params FactoryParams) Factory {
    30  	return &factory{
    31  		config: params,
    32  	}
    33  }
    34  
    35  type factory struct {
    36  	config FactoryParams
    37  }
    38  
    39  // newResolved wraps the supplied operation such that it will clear the uniter
    40  // resolve flag before executing.
    41  func (f *factory) newResolved(wrapped Operation) (Operation, error) {
    42  	if wrapped == nil {
    43  		return nil, errors.New("operation required")
    44  	}
    45  	return &resolvedOperation{
    46  		Operation: wrapped,
    47  		callbacks: f.config.Callbacks,
    48  	}, nil
    49  }
    50  
    51  // newDeploy is the common code for creating arbitrary deploy operations.
    52  func (f *factory) newDeploy(kind Kind, charmURL *corecharm.URL, revert, resolved bool) (Operation, error) {
    53  	if charmURL == nil {
    54  		return nil, errors.New("charm url required")
    55  	} else if kind != Install && kind != Upgrade {
    56  		return nil, errors.Errorf("unknown deploy kind: %s", kind)
    57  	}
    58  	return &deploy{
    59  		kind:      kind,
    60  		charmURL:  charmURL,
    61  		revert:    revert,
    62  		resolved:  resolved,
    63  		callbacks: f.config.Callbacks,
    64  		deployer:  f.config.Deployer,
    65  		abort:     f.config.Abort,
    66  	}, nil
    67  }
    68  
    69  // NewInstall is part of the Factory interface.
    70  func (f *factory) NewInstall(charmURL *corecharm.URL) (Operation, error) {
    71  	return f.newDeploy(Install, charmURL, false, false)
    72  }
    73  
    74  // NewUpgrade is part of the Factory interface.
    75  func (f *factory) NewUpgrade(charmURL *corecharm.URL) (Operation, error) {
    76  	return f.newDeploy(Upgrade, charmURL, false, false)
    77  }
    78  
    79  // NewRevertUpgrade is part of the Factory interface.
    80  func (f *factory) NewRevertUpgrade(charmURL *corecharm.URL) (Operation, error) {
    81  	charmOp, err := f.newDeploy(Upgrade, charmURL, true, false)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	return f.newResolved(charmOp)
    86  }
    87  
    88  // NewResolvedUpgrade is part of the Factory interface.
    89  func (f *factory) NewResolvedUpgrade(charmURL *corecharm.URL) (Operation, error) {
    90  	charmOp, err := f.newDeploy(Upgrade, charmURL, false, true)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  	return f.newResolved(charmOp)
    95  }
    96  
    97  // NewRunHook is part of the Factory interface.
    98  func (f *factory) NewRunHook(hookInfo hook.Info) (Operation, error) {
    99  	if err := hookInfo.Validate(); err != nil {
   100  		return nil, err
   101  	}
   102  	return &runHook{
   103  		info:          hookInfo,
   104  		callbacks:     f.config.Callbacks,
   105  		runnerFactory: f.config.RunnerFactory,
   106  	}, nil
   107  }
   108  
   109  // NewRetryHook is part of the Factory interface.
   110  func (f *factory) NewRetryHook(hookInfo hook.Info) (Operation, error) {
   111  	hookOp, err := f.NewRunHook(hookInfo)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	return f.newResolved(hookOp)
   116  }
   117  
   118  // NewSkipHook is part of the Factory interface.
   119  func (f *factory) NewSkipHook(hookInfo hook.Info) (Operation, error) {
   120  	hookOp, err := f.NewRunHook(hookInfo)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	return f.newResolved(&skipOperation{hookOp})
   125  }
   126  
   127  // NewAction is part of the Factory interface.
   128  func (f *factory) NewAction(actionId string) (Operation, error) {
   129  	if !names.IsValidAction(actionId) {
   130  		return nil, errors.Errorf("invalid action id %q", actionId)
   131  	}
   132  	return &runAction{
   133  		actionId:      actionId,
   134  		callbacks:     f.config.Callbacks,
   135  		runnerFactory: f.config.RunnerFactory,
   136  	}, nil
   137  }
   138  
   139  // NewCommands is part of the Factory interface.
   140  func (f *factory) NewCommands(args CommandArgs, sendResponse CommandResponseFunc) (Operation, error) {
   141  	if args.Commands == "" {
   142  		return nil, errors.New("commands required")
   143  	} else if sendResponse == nil {
   144  		return nil, errors.New("response sender required")
   145  	}
   146  	if args.RemoteUnitName != "" {
   147  		if args.RelationId == -1 {
   148  			return nil, errors.New("remote unit not valid without relation")
   149  		} else if !names.IsValidUnit(args.RemoteUnitName) {
   150  			return nil, errors.Errorf("invalid remote unit name %q", args.RemoteUnitName)
   151  		}
   152  	}
   153  	return &runCommands{
   154  		args:          args,
   155  		sendResponse:  sendResponse,
   156  		callbacks:     f.config.Callbacks,
   157  		runnerFactory: f.config.RunnerFactory,
   158  	}, nil
   159  }
   160  
   161  // NewUpdateRelations is part of the Factory interface.
   162  func (f *factory) NewUpdateRelations(ids []int) (Operation, error) {
   163  	return &updateRelations{
   164  		ids:       ids,
   165  		callbacks: f.config.Callbacks,
   166  	}, nil
   167  }
   168  
   169  // NewUpdateStorage is part of the Factory interface.
   170  func (f *factory) NewUpdateStorage(tags []names.StorageTag) (Operation, error) {
   171  	return &updateStorage{
   172  		tags:           tags,
   173  		storageUpdater: f.config.StorageUpdater,
   174  	}, nil
   175  }
   176  
   177  // NewResignLeadership is part of the Factory interface.
   178  func (f *factory) NewResignLeadership() (Operation, error) {
   179  	return &resignLeadership{}, nil
   180  }
   181  
   182  // NewAcceptLeadership is part of the Factory interface.
   183  func (f *factory) NewAcceptLeadership() (Operation, error) {
   184  	return &acceptLeadership{}, nil
   185  }
   186  
   187  // NewSendMetrics is part of the Factory interface.
   188  func (f *factory) NewSendMetrics() (Operation, error) {
   189  	return &sendMetrics{
   190  		sender:   f.config.MetricSender,
   191  		spoolDir: f.config.MetricSpoolDir,
   192  	}, nil
   193  }