github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/state/backups/restore_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // +build !windows 5 6 package backups 7 8 import ( 9 "fmt" 10 "io" 11 "net" 12 "os" 13 "path" 14 "strconv" 15 "strings" 16 17 "github.com/juju/names" 18 "github.com/juju/replicaset" 19 gitjujutesting "github.com/juju/testing" 20 jc "github.com/juju/testing/checkers" 21 gc "gopkg.in/check.v1" 22 "gopkg.in/mgo.v2" 23 "gopkg.in/mgo.v2/bson" 24 25 "github.com/juju/juju/agent" 26 "github.com/juju/juju/apiserver/params" 27 "github.com/juju/juju/mongo" 28 "github.com/juju/juju/state" 29 statetesting "github.com/juju/juju/state/testing" 30 coretesting "github.com/juju/juju/testing" 31 "github.com/juju/juju/utils/ssh" 32 "github.com/juju/juju/version" 33 ) 34 35 var _ = gc.Suite(&RestoreSuite{}) 36 37 type RestoreSuite struct { 38 coretesting.BaseSuite 39 cwd string 40 testFiles []string 41 } 42 43 func (r *RestoreSuite) SetUpSuite(c *gc.C) { 44 r.BaseSuite.SetUpSuite(c) 45 } 46 47 func (r *RestoreSuite) SetUpTest(c *gc.C) { 48 r.cwd = c.MkDir() 49 r.BaseSuite.SetUpTest(c) 50 } 51 52 func (r *RestoreSuite) createTestFiles(c *gc.C) { 53 tarDirE := path.Join(r.cwd, "TarDirectoryEmpty") 54 err := os.Mkdir(tarDirE, os.FileMode(0755)) 55 c.Check(err, jc.ErrorIsNil) 56 57 tarDirP := path.Join(r.cwd, "TarDirectoryPopulated") 58 err = os.Mkdir(tarDirP, os.FileMode(0755)) 59 c.Check(err, jc.ErrorIsNil) 60 61 tarSubFile1 := path.Join(tarDirP, "TarSubFile1") 62 tarSubFile1Handle, err := os.Create(tarSubFile1) 63 c.Check(err, jc.ErrorIsNil) 64 tarSubFile1Handle.WriteString("TarSubFile1") 65 tarSubFile1Handle.Close() 66 67 tarSubDir := path.Join(tarDirP, "TarDirectoryPopulatedSubDirectory") 68 err = os.Mkdir(tarSubDir, os.FileMode(0755)) 69 c.Check(err, jc.ErrorIsNil) 70 71 tarFile1 := path.Join(r.cwd, "TarFile1") 72 tarFile1Handle, err := os.Create(tarFile1) 73 c.Check(err, jc.ErrorIsNil) 74 tarFile1Handle.WriteString("TarFile1") 75 tarFile1Handle.Close() 76 77 tarFile2 := path.Join(r.cwd, "TarFile2") 78 tarFile2Handle, err := os.Create(tarFile2) 79 c.Check(err, jc.ErrorIsNil) 80 tarFile2Handle.WriteString("TarFile2") 81 tarFile2Handle.Close() 82 r.testFiles = []string{tarDirE, tarDirP, tarFile1, tarFile2} 83 } 84 85 func (r *RestoreSuite) ensureAdminUser(c *gc.C, dialInfo *mgo.DialInfo, user, password string) (added bool, err error) { 86 _, portString, err := net.SplitHostPort(dialInfo.Addrs[0]) 87 c.Assert(err, jc.ErrorIsNil) 88 port, err := strconv.Atoi(portString) 89 c.Assert(err, jc.ErrorIsNil) 90 return mongo.EnsureAdminUser(mongo.EnsureAdminUserParams{ 91 DialInfo: dialInfo, 92 Port: port, 93 User: user, 94 Password: password, 95 }) 96 } 97 98 func (r *RestoreSuite) TestReplicasetIsReset(c *gc.C) { 99 server := &gitjujutesting.MgoInstance{Params: []string{"--replSet", "juju"}} 100 err := server.Start(coretesting.Certs) 101 c.Assert(err, jc.ErrorIsNil) 102 defer server.DestroyWithLog() 103 mgoAddr := server.Addr() 104 dialInfo := server.DialInfo() 105 106 var cfg *replicaset.Config 107 dialInfo = server.DialInfo() 108 dialInfo.Addrs = []string{mgoAddr} 109 err = resetReplicaSet(dialInfo, mgoAddr) 110 111 session := server.MustDial() 112 defer session.Close() 113 cfg, err = replicaset.CurrentConfig(session) 114 c.Assert(err, jc.ErrorIsNil) 115 c.Assert(cfg.Members, gc.HasLen, 1) 116 c.Assert(cfg.Members[0].Address, gc.Equals, mgoAddr) 117 } 118 119 type backupConfigTests struct { 120 yamlFile io.Reader 121 expectedError error 122 message string 123 } 124 125 var yamlLines = []string{ 126 "# format 1.18", 127 "bogus: aBogusValue", 128 "tag: aTag", 129 "statepassword: aStatePassword", 130 "oldpassword: anOldPassword", 131 "stateport: 1", 132 "apiport: 2", 133 "cacert: aLengthyCACert", 134 } 135 136 func (r *RestoreSuite) TestSetAgentAddressScript(c *gc.C) { 137 testServerAddresses := []string{ 138 "FirstNewStateServerAddress:30303", 139 "SecondNewStateServerAddress:30304", 140 "ThirdNewStateServerAddress:30305", 141 "FourthNewStateServerAddress:30306", 142 "FiftNewStateServerAddress:30307", 143 "SixtNewStateServerAddress:30308", 144 } 145 for _, address := range testServerAddresses { 146 template := setAgentAddressScript(address) 147 expectedString := fmt.Sprintf("\t\ts/- .*(:[0-9]+)/- %s\\1/\n", address) 148 logger.Infof(fmt.Sprintf("Testing with address %q", address)) 149 c.Assert(strings.Contains(template, expectedString), gc.Equals, true) 150 } 151 } 152 153 var caCertPEM = ` 154 -----BEGIN CERTIFICATE----- 155 MIIBnTCCAUmgAwIBAgIBADALBgkqhkiG9w0BAQUwJjENMAsGA1UEChMEanVqdTEV 156 MBMGA1UEAxMManVqdSB0ZXN0aW5nMB4XDTEyMTExNDE0Mzg1NFoXDTIyMTExNDE0 157 NDM1NFowJjENMAsGA1UEChMEanVqdTEVMBMGA1UEAxMManVqdSB0ZXN0aW5nMFow 158 CwYJKoZIhvcNAQEBA0sAMEgCQQCCOOpn9aWKcKr2GQGtygwD7PdfNe1I9BYiPAqa 159 2I33F5+6PqFdfujUKvoyTJI6XG4Qo/CECaaN9smhyq9DxzMhAgMBAAGjZjBkMA4G 160 A1UdDwEB/wQEAwIABDASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBQQDswP 161 FQGeGMeTzPbHW62EZbbTJzAfBgNVHSMEGDAWgBQQDswPFQGeGMeTzPbHW62EZbbT 162 JzALBgkqhkiG9w0BAQUDQQAqZzN0DqUyEfR8zIanozyD2pp10m9le+ODaKZDDNfH 163 8cB2x26F1iZ8ccq5IC2LtQf1IKJnpTcYlLuDvW6yB96g 164 -----END CERTIFICATE----- 165 ` 166 167 func (r *RestoreSuite) TestNewDialInfo(c *gc.C) { 168 machineTag, err := names.ParseTag("machine-0") 169 c.Assert(err, jc.ErrorIsNil) 170 171 dataDir := path.Join(r.cwd, "dataDir") 172 err = os.Mkdir(dataDir, os.FileMode(0755)) 173 c.Assert(err, jc.ErrorIsNil) 174 175 logDir := path.Join(r.cwd, "logDir") 176 err = os.Mkdir(logDir, os.FileMode(0755)) 177 c.Assert(err, jc.ErrorIsNil) 178 179 configParams := agent.AgentConfigParams{ 180 DataDir: dataDir, 181 LogDir: logDir, 182 UpgradedToVersion: version.Current.Number, 183 Tag: machineTag, 184 Environment: coretesting.EnvironmentTag, 185 Password: "dummyPassword", 186 Nonce: "dummyNonce", 187 StateAddresses: []string{"fakeStateAddress:1234"}, 188 APIAddresses: []string{"fakeAPIAddress:12345"}, 189 CACert: caCertPEM, 190 } 191 statePort := 12345 192 privateAddress := "dummyPrivateAddress" 193 servingInfo := params.StateServingInfo{ 194 APIPort: 1234, 195 StatePort: statePort, 196 Cert: caCertPEM, 197 CAPrivateKey: "a ca key", 198 PrivateKey: "a key", 199 SharedSecret: "a secret", 200 SystemIdentity: "an identity", 201 } 202 203 conf, err := agent.NewStateMachineConfig(configParams, servingInfo) 204 c.Assert(err, jc.ErrorIsNil) 205 206 dialInfo, err := newDialInfo(privateAddress, conf) 207 c.Assert(err, jc.ErrorIsNil) 208 c.Assert(dialInfo.Username, gc.Equals, "admin") 209 c.Assert(dialInfo.Password, gc.Equals, "dummyPassword") 210 c.Assert(dialInfo.Direct, gc.Equals, true) 211 c.Assert(dialInfo.Addrs, gc.DeepEquals, []string{fmt.Sprintf("%s:%d", privateAddress, statePort)}) 212 } 213 214 // TestUpdateMongoEntries has all the testing for this function to avoid creating multiple 215 // mongo instances. 216 func (r *RestoreSuite) TestUpdateMongoEntries(c *gc.C) { 217 server := &gitjujutesting.MgoInstance{} 218 err := server.Start(coretesting.Certs) 219 c.Assert(err, jc.ErrorIsNil) 220 defer server.DestroyWithLog() 221 dialInfo := server.DialInfo() 222 mgoAddr := server.Addr() 223 dialInfo.Addrs = []string{mgoAddr} 224 err = updateMongoEntries("1234", "0", "0", dialInfo) 225 c.Assert(err, gc.ErrorMatches, "cannot update machine 0 instance information: not found") 226 227 session := server.MustDial() 228 defer session.Close() 229 230 err = session.DB("juju").C("machines").Insert(bson.M{"machineid": "0", "instanceid": "0"}) 231 c.Assert(err, jc.ErrorIsNil) 232 233 query := session.DB("juju").C("machines").Find(bson.M{"machineid": "0", "instanceid": "1234"}) 234 n, err := query.Count() 235 c.Assert(err, jc.ErrorIsNil) 236 c.Assert(n, gc.Equals, 0) 237 238 err = updateMongoEntries("1234", "0", "0", dialInfo) 239 c.Assert(err, jc.ErrorIsNil) 240 241 query = session.DB("juju").C("machines").Find(bson.M{"machineid": "0", "instanceid": "1234"}) 242 n, err = query.Count() 243 c.Assert(err, jc.ErrorIsNil) 244 c.Assert(n, gc.Equals, 1) 245 } 246 247 func (r *RestoreSuite) TestNewConnection(c *gc.C) { 248 server := &gitjujutesting.MgoInstance{} 249 err := server.Start(coretesting.Certs) 250 c.Assert(err, jc.ErrorIsNil) 251 defer server.DestroyWithLog() 252 253 st := statetesting.Initialize(c, names.NewLocalUserTag("test-admin"), nil, nil) 254 c.Assert(st.Close(), jc.ErrorIsNil) 255 256 r.PatchValue(&mongoDefaultDialOpts, statetesting.NewDialOpts) 257 r.PatchValue(&environsNewStatePolicy, func() state.Policy { return nil }) 258 st, err = newStateConnection(st.EnvironTag(), statetesting.NewMongoInfo()) 259 c.Assert(err, jc.ErrorIsNil) 260 c.Assert(st.Close(), jc.ErrorIsNil) 261 } 262 263 func (r *RestoreSuite) TestRunViaSSH(c *gc.C) { 264 var ( 265 passedAddress string 266 passedArgs []string 267 ) 268 fakeSSHCommand := func(address string, args []string, options *ssh.Options) *ssh.Cmd { 269 passedAddress = address 270 passedArgs = args 271 return ssh.Command("", []string{"ls"}, &ssh.Options{}) 272 } 273 274 r.PatchValue(&sshCommand, fakeSSHCommand) 275 runViaSSH("invalidAddress", "invalidScript") 276 c.Assert(passedAddress, gc.Equals, "ubuntu@invalidAddress") 277 c.Assert(passedArgs, gc.DeepEquals, []string{"sudo", "-n", "bash", "-c 'invalidScript'"}) 278 }