github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/jujud/agent/agent.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 /* 5 agent contains jujud's machine agent. 6 */ 7 package agent 8 9 import ( 10 "sync" 11 12 "github.com/juju/cmd" 13 "github.com/juju/errors" 14 "github.com/juju/gnuflag" 15 "gopkg.in/juju/names.v2" 16 17 "github.com/juju/juju/agent" 18 "github.com/juju/juju/cmd/jujud/util" 19 ) 20 21 // AgentConf is a terribly confused interface. 22 // 23 // Parts of it are a mixin for cmd.Command implementations; others are a mixin 24 // for agent.Agent implementations; others bridge the two. We should be aiming 25 // to separate the cmd responsibilities from the agent responsibilities. 26 type AgentConf interface { 27 28 // AddFlags injects common agent flags into f. 29 AddFlags(f *gnuflag.FlagSet) 30 31 // CheckArgs reports whether the given args are valid for this agent. 32 CheckArgs(args []string) error 33 34 // DataDir returns the directory where this agent should store its data. 35 DataDir() string 36 37 // ReadConfig reads the agent's config from its config file. 38 ReadConfig(tag string) error 39 40 // CurrentConfig returns the agent config for this agent. 41 CurrentConfig() agent.Config 42 43 // ChangeConfig modifies this configuration using the given mutator. 44 ChangeConfig(change agent.ConfigMutator) error 45 } 46 47 // NewAgentConf returns a new value that satisfies AgentConf 48 func NewAgentConf(dataDir string) AgentConf { 49 return &agentConf{dataDir: dataDir} 50 } 51 52 // agentConf handles command-line flags shared by all agents. 53 type agentConf struct { 54 dataDir string 55 mu sync.Mutex 56 _config agent.ConfigSetterWriter 57 } 58 59 // AddFlags injects common agent flags into f. 60 func (c *agentConf) AddFlags(f *gnuflag.FlagSet) { 61 // TODO(dimitern) 2014-02-19 bug 1282025 62 // We need to pass a config location here instead and 63 // use it to locate the conf and the infer the data-dir 64 // from there instead of passing it like that. 65 f.StringVar(&c.dataDir, "data-dir", util.DataDir, "directory for juju data") 66 } 67 68 // CheckArgs reports whether the given args are valid for this agent. 69 func (c *agentConf) CheckArgs(args []string) error { 70 if c.dataDir == "" { 71 return util.RequiredError("data-dir") 72 } 73 return cmd.CheckEmpty(args) 74 } 75 76 // DataDir returns the directory where this agent should store its data. 77 func (c *agentConf) DataDir() string { 78 return c.dataDir 79 } 80 81 // ReadConfig reads the agent's config from its config file. 82 func (c *agentConf) ReadConfig(tag string) error { 83 t, err := names.ParseTag(tag) 84 if err != nil { 85 return err 86 } 87 c.mu.Lock() 88 defer c.mu.Unlock() 89 conf, err := agent.ReadConfig(agent.ConfigPath(c.dataDir, t)) 90 if err != nil { 91 return err 92 } 93 c._config = conf 94 return nil 95 } 96 97 // ChangeConfig modifies this configuration using the given mutator. 98 func (ch *agentConf) ChangeConfig(change agent.ConfigMutator) error { 99 ch.mu.Lock() 100 defer ch.mu.Unlock() 101 if err := change(ch._config); err != nil { 102 return errors.Trace(err) 103 } 104 if err := ch._config.Write(); err != nil { 105 return errors.Annotate(err, "cannot write agent configuration") 106 } 107 return nil 108 } 109 110 // CurrentConfig returns the agent config for this agent. 111 func (ch *agentConf) CurrentConfig() agent.Config { 112 ch.mu.Lock() 113 defer ch.mu.Unlock() 114 return ch._config.Clone() 115 }