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