github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/jujud/agent/agenttest/agent.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package agenttest 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/juju/cmd" 11 "github.com/juju/replicaset" 12 gitjujutesting "github.com/juju/testing" 13 jc "github.com/juju/testing/checkers" 14 "github.com/juju/utils/arch" 15 "github.com/juju/utils/series" 16 "github.com/juju/version" 17 gc "gopkg.in/check.v1" 18 "gopkg.in/juju/names.v2" 19 "gopkg.in/mgo.v2" 20 21 "github.com/juju/juju/agent" 22 agenttools "github.com/juju/juju/agent/tools" 23 "github.com/juju/juju/apiserver/params" 24 cmdutil "github.com/juju/juju/cmd/jujud/util" 25 "github.com/juju/juju/environs" 26 "github.com/juju/juju/environs/filestorage" 27 envtesting "github.com/juju/juju/environs/testing" 28 envtools "github.com/juju/juju/environs/tools" 29 "github.com/juju/juju/juju/testing" 30 "github.com/juju/juju/mongo" 31 "github.com/juju/juju/mongo/mongotest" 32 "github.com/juju/juju/network" 33 "github.com/juju/juju/state" 34 "github.com/juju/juju/state/stateenvirons" 35 coretesting "github.com/juju/juju/testing" 36 coretools "github.com/juju/juju/tools" 37 jujuversion "github.com/juju/juju/version" 38 "github.com/juju/juju/worker/peergrouper" 39 ) 40 41 type patchingSuite interface { 42 PatchValue(interface{}, interface{}) 43 } 44 45 // InstallFakeEnsureMongo creates a new FakeEnsureMongo, patching 46 // out replicaset.CurrentConfig and cmdutil.EnsureMongoServer. 47 func InstallFakeEnsureMongo(suite patchingSuite) *FakeEnsureMongo { 48 f := &FakeEnsureMongo{ 49 ServiceInstalled: true, 50 } 51 suite.PatchValue(&mongo.IsServiceInstalled, f.IsServiceInstalled) 52 suite.PatchValue(&replicaset.CurrentConfig, f.CurrentConfig) 53 suite.PatchValue(&cmdutil.EnsureMongoServer, f.EnsureMongo) 54 return f 55 } 56 57 // FakeEnsureMongo provides test fakes for the functions used to 58 // initialise MongoDB. 59 type FakeEnsureMongo struct { 60 EnsureCount int 61 InitiateCount int 62 DataDir string 63 OplogSize int 64 Info state.StateServingInfo 65 InitiateParams peergrouper.InitiateMongoParams 66 Err error 67 ServiceInstalled bool 68 } 69 70 func (f *FakeEnsureMongo) IsServiceInstalled() (bool, error) { 71 return f.ServiceInstalled, nil 72 } 73 74 func (f *FakeEnsureMongo) CurrentConfig(*mgo.Session) (*replicaset.Config, error) { 75 // Return a dummy replicaset config that's good enough to 76 // indicate that the replicaset is initiated. 77 return &replicaset.Config{ 78 Members: []replicaset.Member{{}}, 79 }, nil 80 } 81 82 func (f *FakeEnsureMongo) EnsureMongo(args mongo.EnsureServerParams) error { 83 f.EnsureCount++ 84 f.DataDir, f.OplogSize = args.DataDir, args.OplogSize 85 f.Info = state.StateServingInfo{ 86 APIPort: args.APIPort, 87 StatePort: args.StatePort, 88 Cert: args.Cert, 89 PrivateKey: args.PrivateKey, 90 CAPrivateKey: args.CAPrivateKey, 91 SharedSecret: args.SharedSecret, 92 SystemIdentity: args.SystemIdentity, 93 } 94 return f.Err 95 } 96 97 func (f *FakeEnsureMongo) InitiateMongo(p peergrouper.InitiateMongoParams) error { 98 f.InitiateCount++ 99 f.InitiateParams = p 100 return nil 101 } 102 103 // agentSuite is a fixture to be used by agent test suites. 104 type AgentSuite struct { 105 oldRestartDelay time.Duration 106 testing.JujuConnSuite 107 } 108 109 // PrimeAgent writes the configuration file and tools for an agent 110 // with the given entity name. It returns the agent's configuration and the 111 // current tools. 112 func (s *AgentSuite) PrimeAgent(c *gc.C, tag names.Tag, password string) (agent.ConfigSetterWriter, *coretools.Tools) { 113 vers := version.Binary{ 114 Number: jujuversion.Current, 115 Arch: arch.HostArch(), 116 Series: series.HostSeries(), 117 } 118 return s.PrimeAgentVersion(c, tag, password, vers) 119 } 120 121 // PrimeAgentVersion writes the configuration file and tools with version 122 // vers for an agent with the given entity name. It returns the agent's 123 // configuration and the current tools. 124 func (s *AgentSuite) PrimeAgentVersion(c *gc.C, tag names.Tag, password string, vers version.Binary) (agent.ConfigSetterWriter, *coretools.Tools) { 125 c.Logf("priming agent %s", tag.String()) 126 stor, err := filestorage.NewFileStorageWriter(c.MkDir()) 127 c.Assert(err, jc.ErrorIsNil) 128 agentTools := envtesting.PrimeTools(c, stor, s.DataDir(), "released", vers) 129 err = envtools.MergeAndWriteMetadata(stor, "released", "released", coretools.List{agentTools}, envtools.DoNotWriteMirrors) 130 tools1, err := agenttools.ChangeAgentTools(s.DataDir(), tag.String(), vers) 131 c.Assert(err, jc.ErrorIsNil) 132 c.Assert(tools1, gc.DeepEquals, agentTools) 133 134 stateInfo := s.MongoInfo(c) 135 apiInfo := s.APIInfo(c) 136 paths := agent.DefaultPaths 137 paths.DataDir = s.DataDir() 138 paths.MetricsSpoolDir = c.MkDir() 139 conf, err := agent.NewAgentConfig( 140 agent.AgentConfigParams{ 141 Paths: paths, 142 Tag: tag, 143 UpgradedToVersion: vers.Number, 144 Password: password, 145 Nonce: agent.BootstrapNonce, 146 StateAddresses: stateInfo.Addrs, 147 APIAddresses: apiInfo.Addrs, 148 CACert: stateInfo.CACert, 149 Controller: coretesting.ControllerTag, 150 Model: apiInfo.ModelTag, 151 }) 152 c.Assert(err, jc.ErrorIsNil) 153 conf.SetPassword(password) 154 c.Assert(conf.Write(), gc.IsNil) 155 s.primeAPIHostPorts(c) 156 return conf, agentTools 157 } 158 159 // PrimeStateAgent writes the configuration file and tools for 160 // a state agent with the given entity name. It returns the agent's 161 // configuration and the current tools. 162 func (s *AgentSuite) PrimeStateAgent(c *gc.C, tag names.Tag, password string) (agent.ConfigSetterWriter, *coretools.Tools) { 163 vers := version.Binary{ 164 Number: jujuversion.Current, 165 Arch: arch.HostArch(), 166 Series: series.HostSeries(), 167 } 168 return s.PrimeStateAgentVersion(c, tag, password, vers) 169 } 170 171 // PrimeStateAgentVersion writes the configuration file and tools with 172 // version vers for a state agent with the given entity name. It 173 // returns the agent's configuration and the current tools. 174 func (s *AgentSuite) PrimeStateAgentVersion(c *gc.C, tag names.Tag, password string, vers version.Binary) ( 175 agent.ConfigSetterWriter, *coretools.Tools, 176 ) { 177 stor, err := filestorage.NewFileStorageWriter(c.MkDir()) 178 c.Assert(err, jc.ErrorIsNil) 179 agentTools := envtesting.PrimeTools(c, stor, s.DataDir(), "released", vers) 180 tools1, err := agenttools.ChangeAgentTools(s.DataDir(), tag.String(), vers) 181 c.Assert(err, jc.ErrorIsNil) 182 c.Assert(tools1, gc.DeepEquals, agentTools) 183 184 conf := s.WriteStateAgentConfig(c, tag, password, vers, s.State.ModelTag()) 185 s.primeAPIHostPorts(c) 186 return conf, agentTools 187 } 188 189 // WriteStateAgentConfig creates and writes a state agent config. 190 func (s *AgentSuite) WriteStateAgentConfig( 191 c *gc.C, 192 tag names.Tag, 193 password string, 194 vers version.Binary, 195 modelTag names.ModelTag, 196 ) agent.ConfigSetterWriter { 197 stateInfo := s.State.MongoConnectionInfo() 198 apiPort := gitjujutesting.FindTCPPort() 199 apiAddr := []string{fmt.Sprintf("localhost:%d", apiPort)} 200 conf, err := agent.NewStateMachineConfig( 201 agent.AgentConfigParams{ 202 Paths: agent.NewPathsWithDefaults(agent.Paths{DataDir: s.DataDir()}), 203 Tag: tag, 204 UpgradedToVersion: vers.Number, 205 Password: password, 206 Nonce: agent.BootstrapNonce, 207 StateAddresses: stateInfo.Addrs, 208 APIAddresses: apiAddr, 209 CACert: stateInfo.CACert, 210 Controller: s.State.ControllerTag(), 211 Model: modelTag, 212 }, 213 params.StateServingInfo{ 214 Cert: coretesting.ServerCert, 215 PrivateKey: coretesting.ServerKey, 216 CAPrivateKey: coretesting.CAKey, 217 StatePort: gitjujutesting.MgoServer.Port(), 218 APIPort: apiPort, 219 }) 220 c.Assert(err, jc.ErrorIsNil) 221 conf.SetPassword(password) 222 c.Assert(conf.Write(), gc.IsNil) 223 return conf 224 } 225 226 func (s *AgentSuite) primeAPIHostPorts(c *gc.C) { 227 apiInfo := s.APIInfo(c) 228 229 c.Assert(apiInfo.Addrs, gc.HasLen, 1) 230 hostPorts, err := network.ParseHostPorts(apiInfo.Addrs[0]) 231 c.Assert(err, jc.ErrorIsNil) 232 233 err = s.State.SetAPIHostPorts([][]network.HostPort{hostPorts}) 234 c.Assert(err, jc.ErrorIsNil) 235 236 c.Logf("api host ports primed %#v", hostPorts) 237 } 238 239 // InitAgent initialises the given agent command with additional 240 // arguments as provided. 241 func (s *AgentSuite) InitAgent(c *gc.C, a cmd.Command, args ...string) { 242 args = append([]string{"--data-dir", s.DataDir()}, args...) 243 err := coretesting.InitCommand(a, args) 244 c.Assert(err, jc.ErrorIsNil) 245 } 246 247 func (s *AgentSuite) AssertCanOpenState(c *gc.C, tag names.Tag, dataDir string) { 248 config, err := agent.ReadConfig(agent.ConfigPath(dataDir, tag)) 249 c.Assert(err, jc.ErrorIsNil) 250 info, ok := config.MongoInfo() 251 c.Assert(ok, jc.IsTrue) 252 st, err := state.Open(config.Model(), config.Controller(), info, mongotest.DialOpts(), stateenvirons.GetNewPolicyFunc( 253 stateenvirons.GetNewEnvironFunc(environs.New), 254 )) 255 c.Assert(err, jc.ErrorIsNil) 256 st.Close() 257 } 258 259 func (s *AgentSuite) AssertCannotOpenState(c *gc.C, tag names.Tag, dataDir string) { 260 config, err := agent.ReadConfig(agent.ConfigPath(dataDir, tag)) 261 c.Assert(err, jc.ErrorIsNil) 262 _, ok := config.MongoInfo() 263 c.Assert(ok, jc.IsFalse) 264 }