// uninstallerManifold defines a simple start function which retrieves // some dependencies, checks if the machine is dead and causes the // agent to uninstall itself if it is. This doubles up on part of the // machiner's functionality but the machiner doesn't run until // upgrades are complete, and the upgrade related workers may not be // able to make API requests if the machine is dead. func uninstallerManifold(config uninstallerManifoldConfig) dependency.Manifold { return dependency.Manifold{ Inputs: []string{ config.AgentName, config.APICallerName, }, Start: func(getResource dependency.GetResourceFunc) (worker.Worker, error) { if config.WriteUninstallFile == nil { return nil, errors.New("WriteUninstallFile not specified") } // Get the agent. var agent agent.Agent if err := getResource(config.AgentName, &agent); err != nil { return nil, err } // Grab the tag and ensure that it's for a machine. tag, ok := agent.CurrentConfig().Tag().(names.MachineTag) if !ok { return nil, errors.New("agent's tag is not a machine tag") } // Get API connection. // // TODO(mjs) - this should really be a base.APICaller to // remove the possibility of the API connection being closed // here. var apiConn api.Connection if err := getResource(config.APICallerName, &apiConn); err != nil { return nil, err } // Check if the machine is dead and set the agent to // uninstall if it is. // // TODO(mjs) - ideally this would be using its own facade. machine, err := apiConn.Agent().Entity(tag) if err != nil { return nil, err } if machine.Life() == params.Dead { if err := config.WriteUninstallFile(); err != nil { return nil, errors.Annotate(err, "writing uninstall agent file") } return nil, worker.ErrTerminateAgent } // All is well - we're done (no actual worker is actually returned). return nil, dependency.ErrUninstall }, } }
// Manifold returns a dependency manifold that runs an upgrader // worker, using the resource names defined in the supplied config. func Manifold(config ManifoldConfig) dependency.Manifold { return dependency.Manifold{ Inputs: []string{ config.AgentName, config.APICallerName, config.UpgradeStepsGateName, }, Start: func(getResource dependency.GetResourceFunc) (worker.Worker, error) { // Sanity checks if config.OpenStateForUpgrade == nil { return nil, errors.New("missing OpenStateForUpgrade in config") } if config.PreUpgradeSteps == nil { return nil, errors.New("missing PreUpgradeSteps in config") } // Get machine agent. var agent agent.Agent if err := getResource(config.AgentName, &agent); err != nil { return nil, err } // Grab the tag and ensure that it's for a machine. tag, ok := agent.CurrentConfig().Tag().(names.MachineTag) if !ok { return nil, errors.New("agent's tag is not a machine tag") } // Get API connection. var apiConn api.Connection if err := getResource(config.APICallerName, &apiConn); err != nil { return nil, err } // Get the machine agent's jobs. entity, err := apiConn.Agent().Entity(tag) if err != nil { return nil, err } jobs := entity.Jobs() // Get machine instance for setting status on. machine, err := apiConn.Machiner().Machine(tag) if err != nil { return nil, err } // Get upgradesteps completed lock. var upgradeStepsLock gate.Lock if err := getResource(config.UpgradeStepsGateName, &upgradeStepsLock); err != nil { return nil, err } return NewWorker( upgradeStepsLock, agent, apiConn, jobs, config.OpenStateForUpgrade, config.PreUpgradeSteps, machine, ) }, } }