github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/jujud/agent/model/manifolds.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package model
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/clock"
    10  	"github.com/juju/utils/voyeur"
    11  	"gopkg.in/juju/names.v2"
    12  	"gopkg.in/juju/worker.v1"
    13  	"gopkg.in/juju/worker.v1/dependency"
    14  
    15  	coreagent "github.com/juju/juju/agent"
    16  	"github.com/juju/juju/api"
    17  	"github.com/juju/juju/api/base"
    18  	caasfirewallerapi "github.com/juju/juju/api/caasfirewaller"
    19  	caasunitprovisionerapi "github.com/juju/juju/api/caasunitprovisioner"
    20  	"github.com/juju/juju/apiserver/params"
    21  	"github.com/juju/juju/caas"
    22  	"github.com/juju/juju/cmd/jujud/agent/engine"
    23  	"github.com/juju/juju/core/life"
    24  	"github.com/juju/juju/environs"
    25  	"github.com/juju/juju/worker/actionpruner"
    26  	"github.com/juju/juju/worker/agent"
    27  	"github.com/juju/juju/worker/apicaller"
    28  	"github.com/juju/juju/worker/apiconfigwatcher"
    29  	"github.com/juju/juju/worker/applicationscaler"
    30  	"github.com/juju/juju/worker/caasbroker"
    31  	"github.com/juju/juju/worker/caasfirewaller"
    32  	"github.com/juju/juju/worker/caasmodelupgrader"
    33  	"github.com/juju/juju/worker/caasoperatorprovisioner"
    34  	"github.com/juju/juju/worker/caasunitprovisioner"
    35  	"github.com/juju/juju/worker/charmrevision"
    36  	"github.com/juju/juju/worker/charmrevision/charmrevisionmanifold"
    37  	"github.com/juju/juju/worker/cleaner"
    38  	"github.com/juju/juju/worker/common"
    39  	"github.com/juju/juju/worker/credentialvalidator"
    40  	"github.com/juju/juju/worker/environ"
    41  	"github.com/juju/juju/worker/firewaller"
    42  	"github.com/juju/juju/worker/fortress"
    43  	"github.com/juju/juju/worker/gate"
    44  	"github.com/juju/juju/worker/instancepoller"
    45  	"github.com/juju/juju/worker/lifeflag"
    46  	"github.com/juju/juju/worker/logforwarder"
    47  	"github.com/juju/juju/worker/logforwarder/sinks"
    48  	"github.com/juju/juju/worker/machineundertaker"
    49  	"github.com/juju/juju/worker/metricworker"
    50  	"github.com/juju/juju/worker/migrationflag"
    51  	"github.com/juju/juju/worker/migrationmaster"
    52  	"github.com/juju/juju/worker/modelupgrader"
    53  	"github.com/juju/juju/worker/provisioner"
    54  	"github.com/juju/juju/worker/pruner"
    55  	"github.com/juju/juju/worker/remoterelations"
    56  	"github.com/juju/juju/worker/singular"
    57  	"github.com/juju/juju/worker/statushistorypruner"
    58  	"github.com/juju/juju/worker/storageprovisioner"
    59  	"github.com/juju/juju/worker/undertaker"
    60  	"github.com/juju/juju/worker/unitassigner"
    61  )
    62  
    63  // ManifoldsConfig holds the dependencies and configuration options for a
    64  // model agent: that is, for the set of interdependent workers that observe
    65  // and manipulate a single model.
    66  type ManifoldsConfig struct {
    67  	// Agent identifies, and exposes configuration for, the controller
    68  	// machine running these manifolds and the model the manifolds
    69  	// should administer.
    70  	//
    71  	// You should almost certainly set this value to one created by
    72  	// model.WrapAgent.
    73  	Agent coreagent.Agent
    74  
    75  	// AgentConfigChanged will be set whenever the agent's api config
    76  	// is updated
    77  	AgentConfigChanged *voyeur.Value
    78  
    79  	// Clock supplies timing services to any manifolds that need them.
    80  	// Only a few workers have been converted to use them fo far.
    81  	Clock clock.Clock
    82  
    83  	// InstPollerAggregationDelay is the delay before sending a batch of
    84  	// requests in the instancepoller.Worker's aggregate loop.
    85  	InstPollerAggregationDelay time.Duration
    86  
    87  	// RunFlagDuration defines for how long this controller will ask
    88  	// for model administration rights; most of the workers controlled
    89  	// by this agent will only be started when the run flag is known
    90  	// to be held.
    91  	RunFlagDuration time.Duration
    92  
    93  	// CharmRevisionUpdateInterval determines how often the charm-
    94  	// revision worker will check for new revisions of known charms.
    95  	CharmRevisionUpdateInterval time.Duration
    96  
    97  	// StatusHistoryPruner* values control status-history pruning
    98  	// behaviour.
    99  	StatusHistoryPrunerInterval time.Duration
   100  
   101  	// ActionPrunerInterval controls the rate at which the action pruner
   102  	// worker is run.
   103  	ActionPrunerInterval time.Duration
   104  
   105  	// NewEnvironFunc is a function opens a provider "environment"
   106  	// (typically environs.New).
   107  	NewEnvironFunc environs.NewEnvironFunc
   108  
   109  	// NewContainerBrokerFunc is a function opens a CAAS provider.
   110  	NewContainerBrokerFunc caas.NewContainerBrokerFunc
   111  
   112  	// NewMigrationMaster is called to create a new migrationmaster
   113  	// worker.
   114  	NewMigrationMaster func(migrationmaster.Config) (worker.Worker, error)
   115  }
   116  
   117  // commonManifolds returns a set of interdependent dependency manifolds that will
   118  // run together to administer a model, as configured. These manifolds are used
   119  // by both IAAS and CAAS models.
   120  func commonManifolds(config ManifoldsConfig) dependency.Manifolds {
   121  	agentConfig := config.Agent.CurrentConfig()
   122  	machineTag := agentConfig.Tag().(names.MachineTag)
   123  	modelTag := agentConfig.Model()
   124  	result := dependency.Manifolds{
   125  		// The first group are foundational; the agent and clock
   126  		// which wrap those supplied in config, and the api-caller
   127  		// through which everything else communicates with the
   128  		// controller.
   129  		agentName: agent.Manifold(config.Agent),
   130  		clockName: clockManifold(config.Clock),
   131  		apiConfigWatcherName: apiconfigwatcher.Manifold(apiconfigwatcher.ManifoldConfig{
   132  			AgentName:          agentName,
   133  			AgentConfigChanged: config.AgentConfigChanged,
   134  		}),
   135  		apiCallerName: apicaller.Manifold(apicaller.ManifoldConfig{
   136  			AgentName:     agentName,
   137  			APIOpen:       api.Open,
   138  			NewConnection: apicaller.OnlyConnect,
   139  			Filter:        apiConnectFilter,
   140  		}),
   141  
   142  		// All other manifolds should depend on at least one of these
   143  		// three, which handle all the tasks that are safe and sane
   144  		// to run in *all* controller machines.
   145  		notDeadFlagName: lifeflag.Manifold(lifeflag.ManifoldConfig{
   146  			APICallerName: apiCallerName,
   147  			Entity:        modelTag,
   148  			Result:        life.IsNotDead,
   149  			Filter:        LifeFilter,
   150  
   151  			NewFacade: lifeflag.NewFacade,
   152  			NewWorker: lifeflag.NewWorker,
   153  		}),
   154  		notAliveFlagName: lifeflag.Manifold(lifeflag.ManifoldConfig{
   155  			APICallerName: apiCallerName,
   156  			Entity:        modelTag,
   157  			Result:        life.IsNotAlive,
   158  			Filter:        LifeFilter,
   159  
   160  			NewFacade: lifeflag.NewFacade,
   161  			NewWorker: lifeflag.NewWorker,
   162  		}),
   163  		isResponsibleFlagName: singular.Manifold(singular.ManifoldConfig{
   164  			ClockName:     clockName,
   165  			APICallerName: apiCallerName,
   166  			Duration:      config.RunFlagDuration,
   167  			Claimant:      machineTag,
   168  			Entity:        modelTag,
   169  
   170  			NewFacade: singular.NewFacade,
   171  			NewWorker: singular.NewWorker,
   172  		}),
   173  		// This flag runs on all models, and
   174  		// indicates if model's cloud credential is valid.
   175  		validCredentialFlagName: credentialvalidator.Manifold(credentialvalidator.ManifoldConfig{
   176  			APICallerName: apiCallerName,
   177  			NewFacade:     credentialvalidator.NewFacade,
   178  			NewWorker:     credentialvalidator.NewWorker,
   179  		}),
   180  
   181  		// The migration workers collaborate to run migrations;
   182  		// and to create a mechanism for running other workers
   183  		// so they can't accidentally interfere with a migration
   184  		// in progress. Such a manifold should (1) depend on the
   185  		// migration-inactive flag, to know when to start or die;
   186  		// and (2) occupy the migration-fortress, so as to avoid
   187  		// possible interference with the minion (which will not
   188  		// take action until it's gained sole control of the
   189  		// fortress).
   190  		//
   191  		// Note that the fortress and flag will only exist while
   192  		// the model is not dead, and not upgrading; this frees
   193  		// their dependencies from model-lifetime/upgrade concerns.
   194  		migrationFortressName: ifNotUpgrading(ifNotDead(fortress.Manifold())),
   195  		migrationInactiveFlagName: ifNotUpgrading(ifNotDead(migrationflag.Manifold(migrationflag.ManifoldConfig{
   196  			APICallerName: apiCallerName,
   197  			Check:         migrationflag.IsTerminal,
   198  			NewFacade:     migrationflag.NewFacade,
   199  			NewWorker:     migrationflag.NewWorker,
   200  		}))),
   201  		migrationMasterName: ifNotUpgrading(ifNotDead(migrationmaster.Manifold(migrationmaster.ManifoldConfig{
   202  			AgentName:     agentName,
   203  			APICallerName: apiCallerName,
   204  			FortressName:  migrationFortressName,
   205  			Clock:         config.Clock,
   206  			NewFacade:     migrationmaster.NewFacade,
   207  			NewWorker:     config.NewMigrationMaster,
   208  		}))),
   209  
   210  		// Everything else should be wrapped in ifResponsible,
   211  		// ifNotAlive, ifNotDead, or ifNotMigrating (which also
   212  		// implies NotDead), to ensure that only a single
   213  		// controller is attempting to administer this model at
   214  		// any one time.
   215  		//
   216  		// NOTE: not perfectly reliable at this stage? i.e. a
   217  		// worker that ignores its stop signal for "too long"
   218  		// might continue to take admin actions after the window
   219  		// of responsibility closes. This *is* a pre-existing
   220  		// problem, but demands some thought/care: e.g. should
   221  		// we make sure the apiserver also closes any
   222  		// connections that lose responsibility..? can we make
   223  		// sure all possible environ operations are either time-
   224  		// bounded or interruptible? etc
   225  		//
   226  		// On the other hand, all workers *should* be written in
   227  		// the expectation of dealing with sucky infrastructure
   228  		// running things in parallel unexpectedly, just because
   229  		// the universe hates us and will engineer matters such
   230  		// that it happens sometimes, even when we try to avoid
   231  		// it.
   232  
   233  		charmRevisionUpdaterName: ifNotMigrating(charmrevisionmanifold.Manifold(charmrevisionmanifold.ManifoldConfig{
   234  			APICallerName: apiCallerName,
   235  			ClockName:     clockName,
   236  			Period:        config.CharmRevisionUpdateInterval,
   237  
   238  			NewFacade: charmrevisionmanifold.NewAPIFacade,
   239  			NewWorker: charmrevision.NewWorker,
   240  		})),
   241  		remoteRelationsName: ifNotMigrating(remoterelations.Manifold(remoterelations.ManifoldConfig{
   242  			AgentName:                agentName,
   243  			APICallerName:            apiCallerName,
   244  			NewControllerConnection:  apicaller.NewExternalControllerConnection,
   245  			NewRemoteRelationsFacade: remoterelations.NewRemoteRelationsFacade,
   246  			NewWorker:                remoterelations.NewWorker,
   247  		})),
   248  		stateCleanerName: ifNotMigrating(cleaner.Manifold(cleaner.ManifoldConfig{
   249  			APICallerName: apiCallerName,
   250  			ClockName:     clockName,
   251  		})),
   252  		statusHistoryPrunerName: ifNotMigrating(pruner.Manifold(pruner.ManifoldConfig{
   253  			APICallerName: apiCallerName,
   254  			EnvironName:   environTrackerName,
   255  			ClockName:     clockName,
   256  			NewWorker:     statushistorypruner.New,
   257  			NewFacade:     statushistorypruner.NewFacade,
   258  			PruneInterval: config.StatusHistoryPrunerInterval,
   259  		})),
   260  		actionPrunerName: ifNotMigrating(pruner.Manifold(pruner.ManifoldConfig{
   261  			APICallerName: apiCallerName,
   262  			EnvironName:   environTrackerName,
   263  			ClockName:     clockName,
   264  			NewWorker:     actionpruner.New,
   265  			NewFacade:     actionpruner.NewFacade,
   266  			PruneInterval: config.ActionPrunerInterval,
   267  		})),
   268  		logForwarderName: ifNotDead(logforwarder.Manifold(logforwarder.ManifoldConfig{
   269  			APICallerName: apiCallerName,
   270  			Sinks: []logforwarder.LogSinkSpec{{
   271  				Name:   "juju-log-forward",
   272  				OpenFn: sinks.OpenSyslog,
   273  			}},
   274  		})),
   275  		// The model upgrader runs on all controller agents, and
   276  		// unlocks the gate when the model is up-to-date. The
   277  		// environ tracker will be supplied only to the leader,
   278  		// which is the agent that will run the upgrade steps;
   279  		// the other controller agents will wait for it to complete
   280  		// running those steps before allowing logins to the model.
   281  		modelUpgradeGateName: gate.Manifold(),
   282  		modelUpgradedFlagName: gate.FlagManifold(gate.FlagManifoldConfig{
   283  			GateName:  modelUpgradeGateName,
   284  			NewWorker: gate.NewFlagWorker,
   285  		}),
   286  	}
   287  	return result
   288  }
   289  
   290  // IAASManifolds returns a set of interdependent dependency manifolds that will
   291  // run together to administer an IAAS model, as configured.
   292  func IAASManifolds(config ManifoldsConfig) dependency.Manifolds {
   293  	agentConfig := config.Agent.CurrentConfig()
   294  	controllerTag := agentConfig.Controller()
   295  	modelTag := agentConfig.Model()
   296  	manifolds := dependency.Manifolds{
   297  		// The environ tracker could/should be used by several other
   298  		// workers (firewaller, provisioners, address-cleaner?).
   299  		environTrackerName: ifCredentialValid(ifResponsible(environ.Manifold(environ.ManifoldConfig{
   300  			APICallerName:  apiCallerName,
   301  			NewEnvironFunc: config.NewEnvironFunc,
   302  		}))),
   303  
   304  		// Everything else should be wrapped in ifResponsible,
   305  		// ifNotAlive, ifNotDead, or ifNotMigrating (which also
   306  		// implies NotDead), to ensure that only a single
   307  		// controller is attempting to administer this model at
   308  		// any one time.
   309  		//
   310  		// NOTE: not perfectly reliable at this stage? i.e. a
   311  		// worker that ignores its stop signal for "too long"
   312  		// might continue to take admin actions after the window
   313  		// of responsibility closes. This *is* a pre-existing
   314  		// problem, but demands some thought/care: e.g. should
   315  		// we make sure the apiserver also closes any
   316  		// connections that lose responsibility..? can we make
   317  		// sure all possible environ operations are either time-
   318  		// bounded or interruptible? etc
   319  		//
   320  		// On the other hand, all workers *should* be written in
   321  		// the expectation of dealing with sucky infrastructure
   322  		// running things in parallel unexpectedly, just because
   323  		// the universe hates us and will engineer matters such
   324  		// that it happens sometimes, even when we try to avoid
   325  		// it.
   326  
   327  		// The undertaker is currently the only ifNotAlive worker.
   328  		undertakerName: ifNotUpgrading(ifNotAlive(ifCredentialValid(undertaker.Manifold(undertaker.ManifoldConfig{
   329  			APICallerName:      apiCallerName,
   330  			CloudDestroyerName: environTrackerName,
   331  
   332  			NewFacade:                    undertaker.NewFacade,
   333  			NewWorker:                    undertaker.NewWorker,
   334  			NewCredentialValidatorFacade: common.NewCredentialInvalidatorFacade,
   335  		})))),
   336  
   337  		// All the rest depend on ifNotMigrating.
   338  		computeProvisionerName: ifNotMigrating(ifCredentialValid(provisioner.Manifold(provisioner.ManifoldConfig{
   339  			AgentName:                    agentName,
   340  			APICallerName:                apiCallerName,
   341  			EnvironName:                  environTrackerName,
   342  			NewProvisionerFunc:           provisioner.NewEnvironProvisioner,
   343  			NewCredentialValidatorFacade: common.NewCredentialInvalidatorFacade,
   344  		}))),
   345  		storageProvisionerName: ifNotMigrating(ifCredentialValid(storageprovisioner.ModelManifold(storageprovisioner.ModelManifoldConfig{
   346  			APICallerName:                apiCallerName,
   347  			ClockName:                    clockName,
   348  			StorageRegistryName:          environTrackerName,
   349  			Model:                        modelTag,
   350  			NewCredentialValidatorFacade: common.NewCredentialInvalidatorFacade,
   351  			NewWorker:                    storageprovisioner.NewStorageProvisioner,
   352  		}))),
   353  		firewallerName: ifNotMigrating(ifCredentialValid(firewaller.Manifold(firewaller.ManifoldConfig{
   354  			AgentName:               agentName,
   355  			APICallerName:           apiCallerName,
   356  			EnvironName:             environTrackerName,
   357  			NewControllerConnection: apicaller.NewExternalControllerConnection,
   358  
   359  			NewFirewallerWorker:          firewaller.NewWorker,
   360  			NewFirewallerFacade:          firewaller.NewFirewallerFacade,
   361  			NewRemoteRelationsFacade:     firewaller.NewRemoteRelationsFacade,
   362  			NewCredentialValidatorFacade: common.NewCredentialInvalidatorFacade,
   363  		}))),
   364  		unitAssignerName: ifNotMigrating(unitassigner.Manifold(unitassigner.ManifoldConfig{
   365  			APICallerName: apiCallerName,
   366  		})),
   367  		applicationScalerName: ifNotMigrating(applicationscaler.Manifold(applicationscaler.ManifoldConfig{
   368  			APICallerName: apiCallerName,
   369  			NewFacade:     applicationscaler.NewFacade,
   370  			NewWorker:     applicationscaler.New,
   371  		})),
   372  		instancePollerName: ifNotMigrating(ifCredentialValid(instancepoller.Manifold(instancepoller.ManifoldConfig{
   373  			APICallerName:                apiCallerName,
   374  			EnvironName:                  environTrackerName,
   375  			ClockName:                    clockName,
   376  			Delay:                        config.InstPollerAggregationDelay,
   377  			NewCredentialValidatorFacade: common.NewCredentialInvalidatorFacade,
   378  		}))),
   379  		metricWorkerName: ifNotMigrating(metricworker.Manifold(metricworker.ManifoldConfig{
   380  			APICallerName: apiCallerName,
   381  		})),
   382  		machineUndertakerName: ifNotMigrating(ifCredentialValid(machineundertaker.Manifold(machineundertaker.ManifoldConfig{
   383  			APICallerName:                apiCallerName,
   384  			EnvironName:                  environTrackerName,
   385  			NewWorker:                    machineundertaker.NewWorker,
   386  			NewCredentialValidatorFacade: common.NewCredentialInvalidatorFacade,
   387  		}))),
   388  		modelUpgraderName: ifCredentialValid(modelupgrader.Manifold(modelupgrader.ManifoldConfig{
   389  			APICallerName:                apiCallerName,
   390  			EnvironName:                  environTrackerName,
   391  			GateName:                     modelUpgradeGateName,
   392  			ControllerTag:                controllerTag,
   393  			ModelTag:                     modelTag,
   394  			NewFacade:                    modelupgrader.NewFacade,
   395  			NewWorker:                    modelupgrader.NewWorker,
   396  			NewCredentialValidatorFacade: common.NewCredentialInvalidatorFacade,
   397  		})),
   398  	}
   399  	result := commonManifolds(config)
   400  	for name, manifold := range manifolds {
   401  		result[name] = manifold
   402  	}
   403  	return result
   404  }
   405  
   406  // CAASManifolds returns a set of interdependent dependency manifolds that will
   407  // run together to administer a CAAS model, as configured.
   408  func CAASManifolds(config ManifoldsConfig) dependency.Manifolds {
   409  	agentConfig := config.Agent.CurrentConfig()
   410  	modelTag := agentConfig.Model()
   411  	manifolds := dependency.Manifolds{
   412  		// The undertaker is currently the only ifNotAlive worker.
   413  		undertakerName: ifNotUpgrading(ifNotAlive(ifCredentialValid(undertaker.Manifold(undertaker.ManifoldConfig{
   414  			APICallerName:      apiCallerName,
   415  			CloudDestroyerName: caasBrokerTrackerName,
   416  
   417  			NewFacade:                    undertaker.NewFacade,
   418  			NewWorker:                    undertaker.NewWorker,
   419  			NewCredentialValidatorFacade: common.NewCredentialInvalidatorFacade,
   420  		})))),
   421  
   422  		caasBrokerTrackerName: ifResponsible(caasbroker.Manifold(caasbroker.ManifoldConfig{
   423  			APICallerName:          apiCallerName,
   424  			NewContainerBrokerFunc: config.NewContainerBrokerFunc,
   425  		})),
   426  		caasFirewallerName: ifNotMigrating(caasfirewaller.Manifold(
   427  			caasfirewaller.ManifoldConfig{
   428  				APICallerName:  apiCallerName,
   429  				BrokerName:     caasBrokerTrackerName,
   430  				ControllerUUID: agentConfig.Controller().Id(),
   431  				ModelUUID:      agentConfig.Model().Id(),
   432  				NewClient: func(caller base.APICaller) caasfirewaller.Client {
   433  					return caasfirewallerapi.NewClient(caller)
   434  				},
   435  				NewWorker: caasfirewaller.NewWorker,
   436  			},
   437  		)),
   438  		caasOperatorProvisionerName: ifNotMigrating(caasoperatorprovisioner.Manifold(
   439  			caasoperatorprovisioner.ManifoldConfig{
   440  				AgentName:     agentName,
   441  				APICallerName: apiCallerName,
   442  				BrokerName:    caasBrokerTrackerName,
   443  				NewWorker:     caasoperatorprovisioner.NewProvisionerWorker,
   444  			},
   445  		)),
   446  		caasUnitProvisionerName: ifNotMigrating(caasunitprovisioner.Manifold(
   447  			caasunitprovisioner.ManifoldConfig{
   448  				APICallerName: apiCallerName,
   449  				BrokerName:    caasBrokerTrackerName,
   450  				NewClient: func(caller base.APICaller) caasunitprovisioner.Client {
   451  					return caasunitprovisionerapi.NewClient(caller)
   452  				},
   453  				NewWorker: caasunitprovisioner.NewWorker,
   454  			},
   455  		)),
   456  		modelUpgraderName: caasmodelupgrader.Manifold(caasmodelupgrader.ManifoldConfig{
   457  			APICallerName: apiCallerName,
   458  			GateName:      modelUpgradeGateName,
   459  			ModelTag:      modelTag,
   460  			NewFacade:     caasmodelupgrader.NewFacade,
   461  			NewWorker:     caasmodelupgrader.NewWorker,
   462  		}),
   463  		caasStorageProvisionerName: ifNotMigrating(ifCredentialValid(storageprovisioner.ModelManifold(storageprovisioner.ModelManifoldConfig{
   464  			APICallerName:                apiCallerName,
   465  			ClockName:                    clockName,
   466  			StorageRegistryName:          caasBrokerTrackerName,
   467  			Model:                        modelTag,
   468  			NewCredentialValidatorFacade: common.NewCredentialInvalidatorFacade,
   469  			NewWorker:                    storageprovisioner.NewCaasWorker,
   470  		}))),
   471  	}
   472  	result := commonManifolds(config)
   473  	for name, manifold := range manifolds {
   474  		result[name] = manifold
   475  	}
   476  	return result
   477  }
   478  
   479  // clockManifold expresses a Clock as a ValueWorker manifold.
   480  func clockManifold(clock clock.Clock) dependency.Manifold {
   481  	return dependency.Manifold{
   482  		Start: func(_ dependency.Context) (worker.Worker, error) {
   483  			return engine.NewValueWorker(clock)
   484  		},
   485  		Output: engine.ValueWorkerOutput,
   486  	}
   487  }
   488  
   489  func apiConnectFilter(err error) error {
   490  	// If the model is no longer there, then convert to ErrRemoved so
   491  	// that the dependency engine for the model is stopped.
   492  	// See http://pad.lv/1614809
   493  	if params.IsCodeModelNotFound(err) {
   494  		return ErrRemoved
   495  	}
   496  	return err
   497  }
   498  
   499  var (
   500  	// ifResponsible wraps a manifold such that it only runs if the
   501  	// responsibility flag is set.
   502  	ifResponsible = engine.Housing{
   503  		Flags: []string{
   504  			isResponsibleFlagName,
   505  		},
   506  	}.Decorate
   507  
   508  	// ifNotAlive wraps a manifold such that it only runs if the
   509  	// responsibility flag is set and the model is Dying or Dead.
   510  	ifNotAlive = engine.Housing{
   511  		Flags: []string{
   512  			isResponsibleFlagName,
   513  			notAliveFlagName,
   514  		},
   515  	}.Decorate
   516  
   517  	// ifNotDead wraps a manifold such that it only runs if the
   518  	// responsibility flag is set and the model is Alive or Dying.
   519  	ifNotDead = engine.Housing{
   520  		Flags: []string{
   521  			isResponsibleFlagName,
   522  			notDeadFlagName,
   523  		},
   524  	}.Decorate
   525  
   526  	// ifNotMigrating wraps a manifold such that it only runs if the
   527  	// migration-inactive flag is set; and then runs workers only
   528  	// within Visits to the migration fortress. To avoid redundancy,
   529  	// it takes advantage of the fact that those migration manifolds
   530  	// themselves depend on ifNotDead, and eschews repeating those
   531  	// dependencies.
   532  	ifNotMigrating = engine.Housing{
   533  		Flags: []string{
   534  			migrationInactiveFlagName,
   535  		},
   536  		Occupy: migrationFortressName,
   537  	}.Decorate
   538  
   539  	// ifNotUpgrading wraps a manifold such that it only runs after
   540  	// the model upgrade worker has completed.
   541  	ifNotUpgrading = engine.Housing{
   542  		Flags: []string{
   543  			modelUpgradedFlagName,
   544  		},
   545  	}.Decorate
   546  
   547  	// ifCredentialValid wraps a manifold such that it only runs if
   548  	// the model has a valid credential.
   549  	ifCredentialValid = engine.Housing{
   550  		Flags: []string{
   551  			validCredentialFlagName,
   552  		},
   553  	}.Decorate
   554  )
   555  
   556  const (
   557  	agentName            = "agent"
   558  	clockName            = "clock"
   559  	apiConfigWatcherName = "api-config-watcher"
   560  	apiCallerName        = "api-caller"
   561  
   562  	isResponsibleFlagName = "is-responsible-flag"
   563  	notDeadFlagName       = "not-dead-flag"
   564  	notAliveFlagName      = "not-alive-flag"
   565  
   566  	migrationFortressName     = "migration-fortress"
   567  	migrationInactiveFlagName = "migration-inactive-flag"
   568  	migrationMasterName       = "migration-master"
   569  
   570  	modelUpgradeGateName  = "model-upgrade-gate"
   571  	modelUpgradedFlagName = "model-upgraded-flag"
   572  	modelUpgraderName     = "model-upgrader"
   573  
   574  	environTrackerName       = "environ-tracker"
   575  	undertakerName           = "undertaker"
   576  	computeProvisionerName   = "compute-provisioner"
   577  	storageProvisionerName   = "storage-provisioner"
   578  	firewallerName           = "firewaller"
   579  	unitAssignerName         = "unit-assigner"
   580  	applicationScalerName    = "application-scaler"
   581  	instancePollerName       = "instance-poller"
   582  	charmRevisionUpdaterName = "charm-revision-updater"
   583  	metricWorkerName         = "metric-worker"
   584  	stateCleanerName         = "state-cleaner"
   585  	statusHistoryPrunerName  = "status-history-pruner"
   586  	actionPrunerName         = "action-pruner"
   587  	machineUndertakerName    = "machine-undertaker"
   588  	remoteRelationsName      = "remote-relations"
   589  	logForwarderName         = "log-forwarder"
   590  
   591  	caasFirewallerName          = "caas-firewaller"
   592  	caasOperatorProvisionerName = "caas-operator-provisioner"
   593  	caasUnitProvisionerName     = "caas-unit-provisioner"
   594  	caasStorageProvisionerName  = "caas-storage-provisioner"
   595  	caasBrokerTrackerName       = "caas-broker-tracker"
   596  
   597  	validCredentialFlagName = "valid-credential-flag"
   598  )