github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/meterstatus/manifold.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // Package meterstatus provides a worker that executes the meter-status-changed hook 5 // periodically. 6 package meterstatus 7 8 import ( 9 "path" 10 11 "github.com/juju/errors" 12 "github.com/juju/loggo" 13 "github.com/juju/names" 14 "github.com/juju/utils/clock" 15 "github.com/juju/utils/fslock" 16 17 "github.com/juju/juju/agent" 18 "github.com/juju/juju/api/base" 19 "github.com/juju/juju/api/meterstatus" 20 "github.com/juju/juju/worker" 21 "github.com/juju/juju/worker/dependency" 22 ) 23 24 var ( 25 logger = loggo.GetLogger("juju.worker.meterstatus") 26 ) 27 28 // ManifoldConfig identifies the resource names upon which the status manifold depends. 29 type ManifoldConfig struct { 30 AgentName string 31 APICallerName string 32 MachineLockName string 33 34 NewHookRunner func(names.UnitTag, *fslock.Lock, agent.Config) HookRunner 35 NewMeterStatusAPIClient func(base.APICaller, names.UnitTag) meterstatus.MeterStatusClient 36 37 NewConnectedStatusWorker func(ConnectedConfig) (worker.Worker, error) 38 NewIsolatedStatusWorker func(IsolatedConfig) (worker.Worker, error) 39 } 40 41 // Manifold returns a status manifold. 42 func Manifold(config ManifoldConfig) dependency.Manifold { 43 return dependency.Manifold{ 44 Inputs: []string{ 45 config.AgentName, 46 config.APICallerName, 47 config.MachineLockName, 48 }, 49 Start: func(context dependency.Context) (worker.Worker, error) { 50 return newStatusWorker(config, context) 51 }, 52 } 53 } 54 55 func newStatusWorker(config ManifoldConfig, context dependency.Context) (worker.Worker, error) { 56 var agent agent.Agent 57 if err := context.Get(config.AgentName, &agent); err != nil { 58 return nil, err 59 } 60 61 var machineLock *fslock.Lock 62 if err := context.Get(config.MachineLockName, &machineLock); err != nil { 63 return nil, err 64 } 65 66 tag := agent.CurrentConfig().Tag() 67 unitTag, ok := tag.(names.UnitTag) 68 if !ok { 69 return nil, errors.Errorf("expected unit tag, got %v", tag) 70 } 71 72 agentConfig := agent.CurrentConfig() 73 stateFile := NewStateFile(path.Join(agentConfig.DataDir(), "meter-status.yaml")) 74 runner := config.NewHookRunner(unitTag, machineLock, agentConfig) 75 76 // If we don't have a valid APICaller, start a meter status 77 // worker that works without an API connection. 78 var apiCaller base.APICaller 79 err := context.Get(config.APICallerName, &apiCaller) 80 if errors.Cause(err) == dependency.ErrMissing { 81 logger.Tracef("API caller dependency not available, starting isolated meter status worker.") 82 cfg := IsolatedConfig{ 83 Runner: runner, 84 StateFile: stateFile, 85 Clock: clock.WallClock, 86 AmberGracePeriod: defaultAmberGracePeriod, 87 RedGracePeriod: defaultRedGracePeriod, 88 TriggerFactory: GetTriggers, 89 } 90 return config.NewIsolatedStatusWorker(cfg) 91 } else if err != nil { 92 return nil, err 93 } 94 logger.Tracef("Starting connected meter status worker.") 95 status := config.NewMeterStatusAPIClient(apiCaller, unitTag) 96 97 cfg := ConnectedConfig{ 98 Runner: runner, 99 StateFile: stateFile, 100 Status: status, 101 } 102 return config.NewConnectedStatusWorker(cfg) 103 }