github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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/utils/clock" 14 "gopkg.in/juju/names.v2" 15 16 "github.com/juju/juju/agent" 17 "github.com/juju/juju/api/base" 18 "github.com/juju/juju/api/meterstatus" 19 "github.com/juju/juju/worker" 20 "github.com/juju/juju/worker/dependency" 21 ) 22 23 var ( 24 logger = loggo.GetLogger("juju.worker.meterstatus") 25 ) 26 27 // ManifoldConfig identifies the resource names upon which the status manifold depends. 28 type ManifoldConfig struct { 29 AgentName string 30 APICallerName string 31 MachineLockName string 32 Clock clock.Clock 33 34 NewHookRunner func(names.UnitTag, string, agent.Config, clock.Clock) 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 }, 48 Start: func(context dependency.Context) (worker.Worker, error) { 49 if config.Clock == nil { 50 return nil, errors.NotValidf("missing Clock") 51 } 52 if config.MachineLockName == "" { 53 return nil, errors.NotValidf("missing MachineLockName") 54 } 55 return newStatusWorker(config, context) 56 }, 57 } 58 } 59 60 func newStatusWorker(config ManifoldConfig, context dependency.Context) (worker.Worker, error) { 61 var agent agent.Agent 62 if err := context.Get(config.AgentName, &agent); 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, config.MachineLockName, agentConfig, config.Clock) 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: config.Clock, 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 }