// Manifold returns a status manifold.
432310
func Manifold(config ManifoldConfig) dependency.Manifold {
	return dependency.Manifold{
		Inputs: []string{
			config.AgentName,
			config.APICallerName,
		},
		Start: func(context dependency.Context) (worker.Worker, error) {
			if config.Clock == nil {
				return nil, errors.NotValidf("missing Clock")
			}
			if config.MachineLock == nil {
				return nil, errors.NotValidf("missing MachineLock")
			}
			return newStatusWorker(config, context)
		},
	}
}
1238483
func Manifold(config ManifoldConfig) dependency.Manifold {
	return dependency.Manifold{
		Inputs: []string{
			config.ClockName,
			config.AgentName,
			config.TransportName,
		},
		Start:  config.start,
		Output: raftOutput,
	}
}
133357
func (config ManifoldConfig) Validate() error {
	if config.StateName == "" {
		return errors.NotValidf("empty StateName")
	}
	if config.NewWorker == nil {
		return errors.NotValidf("nil NewWorker")
	}
	return nil
}
707176
func Manifold(config ManifoldConfig) dependency.Manifold {
	manifold := dependency.Manifold{
		Inputs: []string{
			config.APICallerName,
		},
		Output: manifoldOutput,
		Start: func(context dependency.Context) (worker.Worker, error) {
			var apiCaller base.APICaller
			if err := context.Get(config.APICallerName, &apiCaller); err != nil {
				return nil, errors.Trace(err)
			}
			api, err := caasagent.NewClient(apiCaller)
			if err != nil {
				return nil, errors.Trace(err)
			}
			w, err := NewTracker(Config{
				ConfigAPI:              api,
				NewContainerBrokerFunc: config.NewContainerBrokerFunc,
			})
			if err != nil {
				return nil, errors.Trace(err)
			}
			return w, nil
		},
	}
	return manifold
}
909991
func Manifold(config ManifoldConfig) dependency.Manifold {
	inputs := []string{
		config.AgentName,
		config.APICallerName,
	}

	// The machine agent uses these but the application agent doesn't.
	if config.UpgradeStepsGateName != "" {
		inputs = append(inputs, config.UpgradeStepsGateName)
	}
	if config.UpgradeCheckGateName != "" {
		inputs = append(inputs, config.UpgradeCheckGateName)
	}

	return dependency.Manifold{
		Inputs: inputs,
		Start: func(context dependency.Context) (worker.Worker, error) {
			if config.PreviousAgentVersion == version.Zero {
				return nil, errors.New("previous agent version not specified")
			}

			var agent agent.Agent
			if err := context.Get(config.AgentName, &agent); err != nil {
				return nil, err
			}
			currentConfig := agent.CurrentConfig()

			var apiCaller base.APICaller
			if err := context.Get(config.APICallerName, &apiCaller); err != nil {
				return nil, err
			}

			upgraderFacade := upgrader.NewState(apiCaller)
			operatorUpgraderFacade := caasoperatorupgrader.NewClient(apiCaller)

			var upgradeStepsWaiter gate.Waiter
			if config.UpgradeStepsGateName == "" {
				upgradeStepsWaiter = gate.NewLock()
			} else {
				if config.PreviousAgentVersion == version.Zero {
					return nil, errors.New("previous agent version not specified")
				}
				if err := context.Get(config.UpgradeStepsGateName, &upgradeStepsWaiter); err != nil {
					return nil, err
				}
			}

			var initialCheckUnlocker gate.Unlocker
			if config.UpgradeCheckGateName == "" {
				initialCheckUnlocker = gate.NewLock()
			} else {
				if err := context.Get(config.UpgradeCheckGateName, &initialCheckUnlocker); err != nil {
					return nil, err
				}
			}

			return NewUpgrader(Config{
				UpgraderClient:              upgraderFacade,
				CAASOperatorUpgrader:        operatorUpgraderFacade,
				AgentTag:                    currentConfig.Tag(),
				OrigAgentVersion:            config.PreviousAgentVersion,
				UpgradeStepsWaiter:          upgradeStepsWaiter,
				InitialUpgradeCheckComplete: initialCheckUnlocker,
			})
		},
	}
}
739776
func Manifold(cfg ManifoldConfig) dependency.Manifold {
	return dependency.Manifold{
		Inputs: []string{
			cfg.AgentName,
			cfg.APICallerName,
			cfg.EnvironName,
		},
		Start: cfg.start,
	}
}
350655
func Manifold(config ManifoldConfig) dependency.Manifold {
	return dependency.Manifold{
		Inputs: []string{config.APICallerName},
		Start:  config.start,
		Output: engine.FlagOutput,
		Filter: filterErrors,
	}
}
1076371
func (config ManifoldConfig) Validate() error {
	if config.AgentName == "" {
		return errors.NotValidf("empty AgentName")
	}
	if config.APICallerName == "" {
		return errors.NotValidf("empty APICallerName")
	}
	if config.NewControllerConnection == nil {
		return errors.NotValidf("nil NewControllerConnection")
	}
	if config.NewRemoteRelationsFacade == nil {
		return errors.NotValidf("nil NewRemoteRelationsFacade")
	}
	if config.NewWorker == nil {
		return errors.NotValidf("nil NewWorker")
	}
	return nil
}
384905
func (config ManifoldConfig) startFunc() dependency.StartFunc {
	return func(context dependency.Context) (worker.Worker, error) {
		var agent agent.Agent
		if err := context.Get(config.AgentName, &agent); err != nil {
			return nil, err
		}

		conn, err := config.NewConnection(agent, config.APIOpen)
		if errors.Cause(err) == ErrChangedPassword {
			return nil, dependency.ErrBounce
		} else if err != nil {
			cfg := agent.CurrentConfig()
			return nil, errors.Annotatef(err, "[%s] %q cannot open api",
				shortModelUUID(cfg.Model()), cfg.Tag().String())
		}
		return newAPIConnWorker(conn), nil
	}
}
1113176
func (config ManifoldConfig) validate() error {
	if config.APICallerName == "" {
		return errors.NotValidf("empty APICallerName")
	}
	if config.Check == nil {
		return errors.NotValidf("nil Check")
	}
	if config.NewFacade == nil {
		return errors.NotValidf("nil NewFacade")
	}
	if config.NewWorker == nil {
		return errors.NotValidf("nil NewWorker")
	}
	return nil
}
303590
func Manifold(config ManifoldConfig) dependency.Manifold {
	typedConfig := engine.AgentAPIManifoldConfig{
		AgentName:     config.AgentName,
		APICallerName: config.APICallerName,
	}
	manifold := engine.AgentAPIManifold(typedConfig, config.start)
	manifold.Output = config.output
	return manifold
}
857714
func FlagManifold(config FlagManifoldConfig) dependency.Manifold {
	return dependency.Manifold{
		Inputs: []string{config.GateName},
		Start:  config.start,
		Output: engine.FlagOutput,
		Filter: bounceUnlocked,
	}
}
893926
func Manifold(config ManifoldConfig) dependency.Manifold {
	return dependency.Manifold{
		Inputs: []string{
			config.AgentName,
			config.CentralHubName,
			config.StateConfigWatcherName,
		},
		Start: func(context dependency.Context) (worker.Worker, error) {
			if err := config.Validate(); err != nil {
				return nil, err
			}
			// Get the agent.
			var agent coreagent.Agent
			if err := context.Get(config.AgentName, &agent); err != nil {
				config.Logger.Tracef("agent dependency not available")
				return nil, err
			}
			origin := agent.CurrentConfig().Tag().String()

			// Get the hub.
			var hub *pubsub.StructuredHub
			if err := context.Get(config.CentralHubName, &hub); err != nil {
				config.Logger.Tracef("hub dependency not available")
				return nil, err
			}
			// Confirm we're running in a state server by asking the
			// stateconfigwatcher manifold.
			var haveStateConfig bool
			if err := context.Get(config.StateConfigWatcherName, &haveStateConfig); err != nil {
				config.Logger.Tracef("state config watcher not available")
				return nil, err
			}
			if !haveStateConfig {
				config.Logger.Tracef("not a state server, not needed")
				config.Recorder.Disable()
				return nil, dependency.ErrMissing
			}
			config.Recorder.Enable()

			cfg := WorkerConfig{
				Origin:   origin,
				Hub:      hub,
				Recorder: config.Recorder,
				Logger:   config.Logger,
			}
			return config.NewWorker(cfg)
		},
	}
}
113583
func Manifold(config ManifoldConfig) dependency.Manifold {
	inputs := []string{config.ClockName}
	if config.StateName != "" {
		inputs = append(inputs, config.StateName)
	} else {
		inputs = append(inputs, config.LeaseManagerName)
	}
	if config.RaftName != "" {
		inputs = append(inputs, config.RaftName)
	}
	return dependency.Manifold{
		Inputs: inputs,
		Start:  config.start,
	}
}
937655
func commonManifolds(config ManifoldsConfig) dependency.Manifolds {

	// connectFilter exists:
	//  1) to let us retry api connections immediately on password change,
	//     rather than causing the dependency engine to wait for a while;
	//  2) to ensure that certain connection failures correctly trigger
	//     complete agent removal. (It's not safe to let any agent other
	//     than the machine mess around with SetCanUninstall).
	connectFilter := func(err error) error {
		cause := errors.Cause(err)
		if cause == apicaller.ErrConnectImpossible {
			err2 := coreagent.SetCanUninstall(config.Agent)
			if err2 != nil {
				return errors.Trace(err2)
			}
			return jworker.ErrTerminateAgent
		} else if cause == apicaller.ErrChangedPassword {
			return dependency.ErrBounce
		}
		return err
	}

	newExternalControllerWatcherClient := func(apiInfo *api.Info) (
		externalcontrollerupdater.ExternalControllerWatcherClientCloser, error,
	) {
		conn, err := apicaller.NewExternalControllerConnection(apiInfo)
		if err != nil {
			return nil, errors.Trace(err)
		}
		return crosscontroller.NewClient(conn), nil
	}

	agentConfig := config.Agent.CurrentConfig()
	machineTag := agentConfig.Tag().(names.MachineTag)
	controllerTag := agentConfig.Controller()

	leaseFSM := raftlease.NewFSM()

	manifolds := dependency.Manifolds{
		// The agent manifold references the enclosing agent, and is the
		// foundation stone on which most other manifolds ultimately depend.
		agentName: agent.Manifold(config.Agent),

		// The termination worker returns ErrTerminateAgent if a
		// termination signal is received by the process it's running
		// in. It has no inputs and its only output is the error it
		// returns. It depends on the uninstall file having been
		// written *by the manual provider* at install time; it would
		// be Very Wrong Indeed to use SetCanUninstall in conjunction
		// with this code.
		terminationName: terminationworker.Manifold(),

		clockName: clockManifold(config.Clock),

		// Each machine agent has a flag manifold/worker which
		// reports whether or not the agent is a controller.
		isControllerFlagName: isControllerFlagManifold(),

		// The stateconfigwatcher manifold watches the machine agent's
		// configuration and reports if state serving info is
		// present. It will bounce itself if state serving info is
		// added or removed. It is intended as a dependency just for
		// the state manifold.
		stateConfigWatcherName: stateconfigwatcher.Manifold(stateconfigwatcher.ManifoldConfig{
			AgentName:          agentName,
			AgentConfigChanged: config.AgentConfigChanged,
		}),

		// The centralhub manifold watches the state config to make sure it
		// only starts for machines that are api servers. Currently the hub is
		// passed in as config, but when the apiserver and peergrouper are
		// updated to use the dependency engine, the centralhub manifold
		// should also take the agentName so the worker can get the machine ID
		// for the creation of the hub.
		centralHubName: centralhub.Manifold(centralhub.ManifoldConfig{
			StateConfigWatcherName: stateConfigWatcherName,
			Hub:                    config.CentralHub,
		}),

		// The pubsub manifold gets the APIInfo from the agent config,
		// and uses this as a basis to talk to the other API servers.
		// The worker subscribes to the messages sent by the peergrouper
		// that defines the set of machines that are the API servers.
		// All non-local messages that originate from the machine that
		// is running the worker get forwarded to the other API servers.
		// This worker does not run in non-API server machines through
		// the hub dependency, as that is only available if the machine
		// is an API server.
		pubSubName: psworker.Manifold(psworker.ManifoldConfig{
			AgentName:      agentName,
			CentralHubName: centralHubName,
			Clock:          config.Clock,
			Logger:         loggo.GetLogger("juju.worker.pubsub"),
			NewWorker:      psworker.NewWorker,
			Reporter:       config.PubSubReporter,
		}),

		// The presence manifold listens to pubsub messages about the pubsub
		// forwarding connections and api connection and disconnections to
		// establish a view on which agents are "alive".
		presenceName: prworker.Manifold(prworker.ManifoldConfig{
			AgentName:              agentName,
			CentralHubName:         centralHubName,
			StateConfigWatcherName: stateConfigWatcherName,
			Recorder:               config.PresenceRecorder,
			Logger:                 loggo.GetLogger("juju.worker.presence"),
			NewWorker:              prworker.NewWorker,
		}),

		/* TODO(menn0) - this is currently unused, pending further
		 * refactoring in the state package.

			// The controller manifold creates a *state.Controller and
			// makes it available to other manifolds. It pings the MongoDB
			// session regularly and will die if pings fail.
			controllerName: workercontroller.Manifold(workercontroller.ManifoldConfig{
				AgentName:              agentName,
				StateConfigWatcherName: stateConfigWatcherName,
				OpenController:         config.OpenController,
			}),
		*/

		// The state manifold creates a *state.State and makes it
		// available to other manifolds. It pings the mongodb session
		// regularly and will die if pings fail.
		stateName: workerstate.Manifold(workerstate.ManifoldConfig{
			AgentName:              agentName,
			StateConfigWatcherName: stateConfigWatcherName,
			OpenStatePool:          config.OpenStatePool,
			SetStatePool:           config.SetStatePool,
		}),

		// The modelcache manifold creates a cache.Controller and keeps
		// it up to date using an all model watcher. The controller is then
		// used by the apiserver.
		modelCacheName: modelcache.Manifold(modelcache.ManifoldConfig{
			StateName:            stateName,
			Logger:               loggo.GetLogger("juju.worker.modelcache"),
			PrometheusRegisterer: config.PrometheusRegisterer,
			NewWorker:            modelcache.NewWorker,
		}),

		// The api-config-watcher manifold monitors the API server
		// addresses in the agent config and bounces when they
		// change. It's required as part of model migrations.
		apiConfigWatcherName: apiconfigwatcher.Manifold(apiconfigwatcher.ManifoldConfig{
			AgentName:          agentName,
			AgentConfigChanged: config.AgentConfigChanged,
		}),

		// The certificate-watcher manifold monitors the API server
		// certificate in the agent config for changes, and parses
		// and offers the result to other manifolds. This is only
		// run by state servers.
		certificateWatcherName: ifController(apiservercertwatcher.Manifold(apiservercertwatcher.ManifoldConfig{
			AgentName:          agentName,
			AgentConfigChanged: config.AgentConfigChanged,
		})),

		// The api caller is a thin concurrent wrapper around a connection
		// to some API server. It's used by many other manifolds, which all
		// select their own desired facades. It will be interesting to see
		// how this works when we consolidate the agents; might be best to
		// handle the auth changes server-side..?
		apiCallerName: apicaller.Manifold(apicaller.ManifoldConfig{
			AgentName:            agentName,
			APIConfigWatcherName: apiConfigWatcherName,
			APIOpen:              api.Open,
			NewConnection:        apicaller.ScaryConnect,
			Filter:               connectFilter,
		}),

		// The upgrade steps gate is used to coordinate workers which
		// shouldn't do anything until the upgrade-steps worker has
		// finished running any required upgrade steps. The flag of
		// similar name is used to implement the isFullyUpgraded func
		// that keeps upgrade concerns out of unrelated manifolds.
		upgradeStepsGateName: gate.ManifoldEx(config.UpgradeStepsLock),
		upgradeStepsFlagName: gate.FlagManifold(gate.FlagManifoldConfig{
			GateName:  upgradeStepsGateName,
			NewWorker: gate.NewFlagWorker,
		}),

		// The upgrade check gate is used to coordinate workers which
		// shouldn't do anything until the upgrader worker has
		// completed its first check for a new tools version to
		// upgrade to. The flag of similar name is used to implement
		// the isFullyUpgraded func that keeps upgrade concerns out of
		// unrelated manifolds.
		upgradeCheckGateName: gate.ManifoldEx(config.UpgradeCheckLock),
		upgradeCheckFlagName: gate.FlagManifold(gate.FlagManifoldConfig{
			GateName:  upgradeCheckGateName,
			NewWorker: gate.NewFlagWorker,
		}),

		// The upgradesteps worker runs soon after the machine agent
		// starts and runs any steps required to upgrade to the
		// running jujud version. Once upgrade steps have run, the
		// upgradesteps gate is unlocked and the worker exits.
		upgradeStepsName: upgradesteps.Manifold(upgradesteps.ManifoldConfig{
			AgentName:            agentName,
			APICallerName:        apiCallerName,
			UpgradeStepsGateName: upgradeStepsGateName,
			OpenStateForUpgrade:  config.OpenStateForUpgrade,
			PreUpgradeSteps:      config.PreUpgradeSteps,
			NewAgentStatusSetter: config.NewAgentStatusSetter,
		}),

		// The migration workers collaborate to run migrations;
		// and to create a mechanism for running other workers
		// so they can't accidentally interfere with a migration
		// in progress. Such a manifold should (1) depend on the
		// migration-inactive flag, to know when to start or die;
		// and (2) occupy the migration-fortress, so as to avoid
		// possible interference with the minion (which will not
		// take action until it's gained sole control of the
		// fortress).
		//
		// Note that the fortress itself will not be created
		// until the upgrade process is complete; this frees all
		// its dependencies from upgrade concerns.
		migrationFortressName: ifFullyUpgraded(fortress.Manifold()),
		migrationInactiveFlagName: migrationflag.Manifold(migrationflag.ManifoldConfig{
			APICallerName: apiCallerName,
			Check:         migrationflag.IsTerminal,
			NewFacade:     migrationflag.NewFacade,
			NewWorker:     migrationflag.NewWorker,
		}),
		migrationMinionName: migrationminion.Manifold(migrationminion.ManifoldConfig{
			AgentName:         agentName,
			APICallerName:     apiCallerName,
			FortressName:      migrationFortressName,
			APIOpen:           api.Open,
			ValidateMigration: config.ValidateMigration,
			NewFacade:         migrationminion.NewFacade,
			NewWorker:         migrationminion.NewWorker,
		}),

		// We run clock updaters for every controller machine to
		// ensure the lease clock is updated monotonically and at a
		// rate no faster than real time.
		//
		// If the legacy-leases feature flag is set the global clock
		// updater updates the lease clock in the database.  .
		globalClockUpdaterName: ifLegacyLeasesEnabled(globalclockupdater.Manifold(globalclockupdater.ManifoldConfig{
			ClockName:      clockName,
			StateName:      stateName,
			NewWorker:      globalclockupdater.NewWorker,
			UpdateInterval: globalClockUpdaterUpdateInterval,
			BackoffDelay:   globalClockUpdaterBackoffDelay,
			Logger:         loggo.GetLogger("juju.worker.globalclockupdater.mongo"),
		})),
		// We also run another clock updater to feed time updates into
		// the lease FSM.
		leaseClockUpdaterName: globalclockupdater.Manifold(globalclockupdater.ManifoldConfig{
			ClockName:        clockName,
			LeaseManagerName: leaseManagerName,
			RaftName:         raftForwarderName,
			NewWorker:        globalclockupdater.NewWorker,
			UpdateInterval:   globalClockUpdaterUpdateInterval,
			BackoffDelay:     globalClockUpdaterBackoffDelay,
			Logger:           loggo.GetLogger("juju.worker.globalclockupdater.raft"),
		}),

		// Each controller machine runs a singular worker which will
		// attempt to claim responsibility for running certain workers
		// that must not be run concurrently by multiple agents.
		isPrimaryControllerFlagName: ifController(singular.Manifold(singular.ManifoldConfig{
			ClockName:     clockName,
			APICallerName: apiCallerName,
			Duration:      config.ControllerLeaseDuration,
			Claimant:      machineTag,
			Entity:        controllerTag,
			NewFacade:     singular.NewFacade,
			NewWorker:     singular.NewWorker,
		})),

		// The agent-config-updater manifold sets the state serving info from
		// the API connection and writes it to the agent config.
		agentConfigUpdaterName: ifNotMigrating(agentconfigupdater.Manifold(agentconfigupdater.ManifoldConfig{
			AgentName:      agentName,
			APICallerName:  apiCallerName,
			CentralHubName: centralHubName,
			Logger:         loggo.GetLogger("juju.worker.agentconfigupdater"),
		})),

		// The apiworkers manifold starts workers which rely on the
		// machine agent's API connection but have not been converted
		// to work directly under the dependency engine. It waits for
		// upgrades to be finished before starting these workers.
		apiWorkersName: ifNotMigrating(APIWorkersManifold(APIWorkersConfig{
			APICallerName:   apiCallerName,
			StartAPIWorkers: config.StartAPIWorkers,
		})),

		// The logging config updater is a leaf worker that indirectly
		// controls the messages sent via the log sender or rsyslog,
		// according to changes in environment config. We should only need
		// one of these in a consolidated agent.
		loggingConfigUpdaterName: ifNotMigrating(logger.Manifold(logger.ManifoldConfig{
			AgentName:       agentName,
			APICallerName:   apiCallerName,
			UpdateAgentFunc: config.UpdateLoggerConfig,
		})),

		// The diskmanager worker periodically lists block devices on the
		// machine it runs on. This worker will be run on all Juju-managed
		// machines (one per machine agent).
		diskManagerName: ifNotMigrating(diskmanager.Manifold(diskmanager.ManifoldConfig{
			AgentName:     agentName,
			APICallerName: apiCallerName,
		})),

		// The api address updater is a leaf worker that rewrites agent config
		// as the state server addresses change. We should only need one of
		// these in a consolidated agent.
		apiAddressUpdaterName: ifNotMigrating(apiaddressupdater.Manifold(apiaddressupdater.ManifoldConfig{
			AgentName:     agentName,
			APICallerName: apiCallerName,
		})),

		// The machiner Worker will wait for the identified machine to become
		// Dying and make it Dead; or until the machine becomes Dead by other
		// means. This worker needs to be launched after fanconfigurer
		// so that it reports interfaces created by it.
		machinerName: ifNotMigrating(machiner.Manifold(machiner.ManifoldConfig{
			AgentName:         agentName,
			APICallerName:     apiCallerName,
			FanConfigurerName: fanConfigurerName,
		})),

		// The log sender is a leaf worker that sends log messages to some
		// API server, when configured so to do. We should only need one of
		// these in a consolidated agent.
		//
		// NOTE: the LogSource will buffer a large number of messages as an upgrade
		// runs; it currently seems better to fill the buffer and send when stable,
		// optimising for stable controller upgrades rather than up-to-the-moment
		// observable normal-machine upgrades.
		logSenderName: ifNotMigrating(logsender.Manifold(logsender.ManifoldConfig{
			APICallerName: apiCallerName,
			LogSource:     config.LogSource,
		})),

		resumerName: ifNotMigrating(resumer.Manifold(resumer.ManifoldConfig{
			AgentName:     agentName,
			APICallerName: apiCallerName,
			Clock:         config.Clock,
			Interval:      time.Minute,
			NewFacade:     resumer.NewFacade,
			NewWorker:     resumer.NewWorker,
		})),

		identityFileWriterName: ifNotMigrating(identityfilewriter.Manifold(identityfilewriter.ManifoldConfig{
			AgentName:     agentName,
			APICallerName: apiCallerName,
		})),

		machineActionName: ifNotMigrating(machineactions.Manifold(machineactions.ManifoldConfig{
			AgentName:     agentName,
			APICallerName: apiCallerName,
			NewFacade:     machineactions.NewFacade,
			NewWorker:     machineactions.NewMachineActionsWorker,
		})),

		externalControllerUpdaterName: ifNotMigrating(ifPrimaryController(externalcontrollerupdater.Manifold(
			externalcontrollerupdater.ManifoldConfig{
				APICallerName:                      apiCallerName,
				NewExternalControllerWatcherClient: newExternalControllerWatcherClient,
			},
		))),

		logPrunerName: ifNotMigrating(ifPrimaryController(dblogpruner.Manifold(
			dblogpruner.ManifoldConfig{
				ClockName:     clockName,
				StateName:     stateName,
				PruneInterval: config.LogPruneInterval,
				NewWorker:     dblogpruner.NewWorker,
			},
		))),

		txnPrunerName: ifNotMigrating(ifPrimaryController(txnpruner.Manifold(
			txnpruner.ManifoldConfig{
				ClockName:     clockName,
				StateName:     stateName,
				PruneInterval: config.TransactionPruneInterval,
				NewWorker:     txnpruner.New,
			},
		))),

		httpServerArgsName: httpserverargs.Manifold(httpserverargs.ManifoldConfig{
			ClockName:             clockName,
			ControllerPortName:    controllerPortName,
			StateName:             stateName,
			NewStateAuthenticator: httpserverargs.NewStateAuthenticator,
		}),

		// TODO Juju 3.0: the controller port worker is only needed while
		// the controller port is a mutable controller config value.
		// When we hit 3.0 we should make controller-port a required
		// and unmutable value.
		controllerPortName: controllerport.Manifold(controllerport.ManifoldConfig{
			AgentName:               agentName,
			HubName:                 centralHubName,
			StateName:               stateName,
			Logger:                  loggo.GetLogger("juju.worker.controllerport"),
			UpdateControllerAPIPort: config.UpdateControllerAPIPort,
			GetControllerConfig:     controllerport.GetControllerConfig,
			NewWorker:               controllerport.NewWorker,
		}),

		httpServerName: httpserver.Manifold(httpserver.ManifoldConfig{
			CertWatcherName:      certificateWatcherName,
			HubName:              centralHubName,
			StateName:            stateName,
			MuxName:              httpServerArgsName,
			APIServerName:        apiServerName,
			RaftTransportName:    raftTransportName,
			PrometheusRegisterer: config.PrometheusRegisterer,
			AgentName:            config.AgentName,
			Clock:                config.Clock,
			MuxShutdownWait:      config.MuxShutdownWait,
			LogDir:               agentConfig.LogDir(),
			GetControllerConfig:  httpserver.GetControllerConfig,
			NewTLSConfig:         httpserver.NewTLSConfig,
			NewWorker:            httpserver.NewWorkerShim,
		}),

		apiServerName: apiserver.Manifold(apiserver.ManifoldConfig{
			AgentName:              agentName,
			AuthenticatorName:      httpServerArgsName,
			ClockName:              clockName,
			StateName:              stateName,
			ModelCacheName:         modelCacheName,
			MuxName:                httpServerArgsName,
			LeaseManagerName:       leaseManagerName,
			UpgradeGateName:        upgradeStepsGateName,
			RestoreStatusName:      restoreWatcherName,
			AuditConfigUpdaterName: auditConfigUpdaterName,
			// Synthetic dependency - if raft-transport bounces we
			// need to bounce api-server too, otherwise http-server
			// can't shutdown properly.
			RaftTransportName: raftTransportName,

			PrometheusRegisterer:              config.PrometheusRegisterer,
			RegisterIntrospectionHTTPHandlers: config.RegisterIntrospectionHTTPHandlers,
			Hub:                               config.CentralHub,
			Presence:                          config.PresenceRecorder,
			NewWorker:                         apiserver.NewWorker,
			NewMetricsCollector:               apiserver.NewMetricsCollector,
		}),

		modelWorkerManagerName: ifFullyUpgraded(modelworkermanager.Manifold(modelworkermanager.ManifoldConfig{
			StateName:      stateName,
			NewWorker:      modelworkermanager.New,
			NewModelWorker: config.NewModelWorker,
		})),

		peergrouperName: ifFullyUpgraded(peergrouper.Manifold(peergrouper.ManifoldConfig{
			AgentName:          agentName,
			ClockName:          clockName,
			ControllerPortName: controllerPortName,
			StateName:          stateName,
			Hub:                config.CentralHub,
			NewWorker:          peergrouper.New,
		})),

		restoreWatcherName: restorewatcher.Manifold(restorewatcher.ManifoldConfig{
			StateName: stateName,
			NewWorker: restorewatcher.NewWorker,
		}),

		auditConfigUpdaterName: ifController(auditconfigupdater.Manifold(auditconfigupdater.ManifoldConfig{
			AgentName: agentName,
			StateName: stateName,
			NewWorker: auditconfigupdater.New,
		})),

		raftTransportName: ifController(rafttransport.Manifold(rafttransport.ManifoldConfig{
			ClockName:         clockName,
			AgentName:         agentName,
			AuthenticatorName: httpServerArgsName,
			HubName:           centralHubName,
			MuxName:           httpServerArgsName,
			DialConn:          rafttransport.DialConn,
			NewWorker:         rafttransport.NewWorker,
			Path:              "/raft",
		})),

		raftName: ifFullyUpgraded(raft.Manifold(raft.ManifoldConfig{
			ClockName:            clockName,
			AgentName:            agentName,
			TransportName:        raftTransportName,
			FSM:                  leaseFSM,
			Logger:               loggo.GetLogger("juju.worker.raft"),
			PrometheusRegisterer: config.PrometheusRegisterer,
			NewWorker:            raft.NewWorker,
		})),

		raftFlagName: raftflag.Manifold(raftflag.ManifoldConfig{
			RaftName:  raftName,
			NewWorker: raftflag.NewWorker,
		}),

		// The raft clusterer can only run on the raft leader, since
		// it makes configuration updates based on changes in API
		// server details.
		raftClustererName: ifRaftLeader(raftclusterer.Manifold(raftclusterer.ManifoldConfig{
			RaftName:       raftName,
			CentralHubName: centralHubName,
			NewWorker:      raftclusterer.NewWorker,
		})),

		raftBackstopName: raftbackstop.Manifold(raftbackstop.ManifoldConfig{
			RaftName:       raftName,
			CentralHubName: centralHubName,
			AgentName:      agentName,
			Logger:         loggo.GetLogger("juju.worker.raft.raftbackstop"),
			NewWorker:      raftbackstop.NewWorker,
		}),

		// The raft forwarder accepts FSM commands from the hub and
		// applies them to the raft leader.
		raftForwarderName: ifRaftLeader(raftforwarder.Manifold(raftforwarder.ManifoldConfig{
			AgentName:      agentName,
			RaftName:       raftName,
			StateName:      stateName,
			CentralHubName: centralHubName,
			RequestTopic:   leaseRequestTopic,
			Logger:         loggo.GetLogger("juju.worker.raft.raftforwarder"),
			NewWorker:      raftforwarder.NewWorker,
			NewTarget:      raftforwarder.NewTarget,
		})),

		// The global lease manager tracks lease information in the raft
		// cluster rather than in mongo.
		leaseManagerName: ifController(leasemanager.Manifold(leasemanager.ManifoldConfig{
			AgentName:            agentName,
			ClockName:            clockName,
			CentralHubName:       centralHubName,
			StateName:            stateName,
			FSM:                  leaseFSM,
			RequestTopic:         leaseRequestTopic,
			Logger:               loggo.GetLogger("juju.worker.lease.raft"),
			PrometheusRegisterer: config.PrometheusRegisterer,
			NewWorker:            leasemanager.NewWorker,
			NewStore:             leasemanager.NewStore,
		})),

		validCredentialFlagName: credentialvalidator.Manifold(credentialvalidator.ManifoldConfig{
			APICallerName: apiCallerName,
			NewFacade:     credentialvalidator.NewFacade,
			NewWorker:     credentialvalidator.NewWorker,
		}),

		legacyLeasesFlagName: ifController(featureflag.Manifold(featureflag.ManifoldConfig{
			StateName: stateName,
			FlagName:  feature.LegacyLeases,
			Logger:    loggo.GetLogger("juju.worker.legacyleasesenabled"),
			NewWorker: featureflag.NewWorker,
		})),

		certificateUpdaterName: ifFullyUpgraded(certupdater.Manifold(certupdater.ManifoldConfig{
			AgentName:                agentName,
			StateName:                stateName,
			NewWorker:                certupdater.NewCertificateUpdater,
			NewMachineAddressWatcher: certupdater.NewMachineAddressWatcher,
		})),

		fanConfigurerName: ifNotMigrating(fanconfigurer.Manifold(fanconfigurer.ManifoldConfig{
			APICallerName: apiCallerName,
			Clock:         config.Clock,
		})),
	}

	return manifolds
}
316189
func Manifold(config ManifoldConfig) dependency.Manifold {
	return dependency.Manifold{
		Inputs: []string{
			config.AgentName,
			config.APICallerName,
			config.FanConfigurerName,
		},
		Start: func(context dependency.Context) (worker.Worker, error) {
			var agent agent.Agent
			if err := context.Get(config.AgentName, &agent); err != nil {
				return nil, err
			}
			var apiCaller base.APICaller
			if err := context.Get(config.APICallerName, &apiCaller); err != nil {
				return nil, err
			}
			var fanConfigurerReady bool
			if err := context.Get(config.FanConfigurerName, &fanConfigurerReady); err != nil {
				return nil, err
			}
			if !fanConfigurerReady {
				return nil, dependency.ErrMissing
			}
			return newWorker(agent, apiCaller)
		},
	}
}
423605
func manifoldStart(apiCaller base.APICaller) (worker.Worker, error) {
	facade := unitassigner.New(apiCaller)
	worker, err := New(facade)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return worker, nil
}