github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/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 "github.com/juju/utils/ssh" 22 gc "gopkg.in/check.v1" 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/mongotest" 28 "github.com/juju/juju/state" 29 statetesting "github.com/juju/juju/state/testing" 30 coretesting "github.com/juju/juju/testing" 31 jujuversion "github.com/juju/juju/version" 32 ) 33 34 var _ = gc.Suite(&RestoreSuite{}) 35 36 type RestoreSuite struct { 37 coretesting.BaseSuite 38 cwd string 39 testFiles []string 40 } 41 42 func (r *RestoreSuite) SetUpSuite(c *gc.C) { 43 r.BaseSuite.SetUpSuite(c) 44 } 45 46 func (r *RestoreSuite) SetUpTest(c *gc.C) { 47 r.cwd = c.MkDir() 48 r.BaseSuite.SetUpTest(c) 49 } 50 51 func (r *RestoreSuite) createTestFiles(c *gc.C) { 52 tarDirE := path.Join(r.cwd, "TarDirectoryEmpty") 53 err := os.Mkdir(tarDirE, os.FileMode(0755)) 54 c.Check(err, jc.ErrorIsNil) 55 56 tarDirP := path.Join(r.cwd, "TarDirectoryPopulated") 57 err = os.Mkdir(tarDirP, os.FileMode(0755)) 58 c.Check(err, jc.ErrorIsNil) 59 60 tarSubFile1 := path.Join(tarDirP, "TarSubFile1") 61 tarSubFile1Handle, err := os.Create(tarSubFile1) 62 c.Check(err, jc.ErrorIsNil) 63 tarSubFile1Handle.WriteString("TarSubFile1") 64 tarSubFile1Handle.Close() 65 66 tarSubDir := path.Join(tarDirP, "TarDirectoryPopulatedSubDirectory") 67 err = os.Mkdir(tarSubDir, os.FileMode(0755)) 68 c.Check(err, jc.ErrorIsNil) 69 70 tarFile1 := path.Join(r.cwd, "TarFile1") 71 tarFile1Handle, err := os.Create(tarFile1) 72 c.Check(err, jc.ErrorIsNil) 73 tarFile1Handle.WriteString("TarFile1") 74 tarFile1Handle.Close() 75 76 tarFile2 := path.Join(r.cwd, "TarFile2") 77 tarFile2Handle, err := os.Create(tarFile2) 78 c.Check(err, jc.ErrorIsNil) 79 tarFile2Handle.WriteString("TarFile2") 80 tarFile2Handle.Close() 81 r.testFiles = []string{tarDirE, tarDirP, tarFile1, tarFile2} 82 } 83 84 func (r *RestoreSuite) TestReplicasetIsReset(c *gc.C) { 85 server := &gitjujutesting.MgoInstance{Params: []string{"--replSet", "juju"}} 86 err := server.Start(coretesting.Certs) 87 c.Assert(err, jc.ErrorIsNil) 88 defer server.DestroyWithLog() 89 mgoAddr := server.Addr() 90 dialInfo := server.DialInfo() 91 92 var cfg *replicaset.Config 93 dialInfo = server.DialInfo() 94 dialInfo.Addrs = []string{mgoAddr} 95 err = resetReplicaSet(dialInfo, mgoAddr) 96 97 session, err := server.Dial() 98 c.Assert(err, jc.ErrorIsNil) 99 defer session.Close() 100 cfg, err = replicaset.CurrentConfig(session) 101 c.Assert(err, jc.ErrorIsNil) 102 c.Assert(cfg.Members, gc.HasLen, 1) 103 c.Assert(cfg.Members[0].Address, gc.Equals, mgoAddr) 104 } 105 106 type backupConfigTests struct { 107 yamlFile io.Reader 108 expectedError error 109 message string 110 } 111 112 func (r *RestoreSuite) TestSetAgentAddressScript(c *gc.C) { 113 testServerAddresses := []string{ 114 "FirstNewControllerAddress:30303", 115 "SecondNewControllerAddress:30304", 116 "ThirdNewControllerAddress:30305", 117 "FourthNewControllerAddress:30306", 118 "FiftNewControllerAddress:30307", 119 "SixtNewControllerAddress:30308", 120 } 121 for _, address := range testServerAddresses { 122 template := setAgentAddressScript(address) 123 expectedString := fmt.Sprintf("\t\ts/- .*(:[0-9]+)/- %s\\1/\n", address) 124 logger.Infof(fmt.Sprintf("Testing with address %q", address)) 125 c.Assert(strings.Contains(template, expectedString), gc.Equals, true) 126 } 127 } 128 129 var caCertPEM = ` 130 -----BEGIN CERTIFICATE----- 131 MIIBnTCCAUmgAwIBAgIBADALBgkqhkiG9w0BAQUwJjENMAsGA1UEChMEanVqdTEV 132 MBMGA1UEAxMManVqdSB0ZXN0aW5nMB4XDTEyMTExNDE0Mzg1NFoXDTIyMTExNDE0 133 NDM1NFowJjENMAsGA1UEChMEanVqdTEVMBMGA1UEAxMManVqdSB0ZXN0aW5nMFow 134 CwYJKoZIhvcNAQEBA0sAMEgCQQCCOOpn9aWKcKr2GQGtygwD7PdfNe1I9BYiPAqa 135 2I33F5+6PqFdfujUKvoyTJI6XG4Qo/CECaaN9smhyq9DxzMhAgMBAAGjZjBkMA4G 136 A1UdDwEB/wQEAwIABDASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBQQDswP 137 FQGeGMeTzPbHW62EZbbTJzAfBgNVHSMEGDAWgBQQDswPFQGeGMeTzPbHW62EZbbT 138 JzALBgkqhkiG9w0BAQUDQQAqZzN0DqUyEfR8zIanozyD2pp10m9le+ODaKZDDNfH 139 8cB2x26F1iZ8ccq5IC2LtQf1IKJnpTcYlLuDvW6yB96g 140 -----END CERTIFICATE----- 141 ` 142 143 func (r *RestoreSuite) TestNewDialInfo(c *gc.C) { 144 145 cases := []struct { 146 machineTag string 147 apiPassword string 148 oldPassword string 149 expectedPassword string 150 expectedUser string 151 expectedError string 152 }{ 153 {"machine-0", 154 "", 155 "123456", 156 "123456", 157 "admin", 158 "", 159 }, 160 {"machine-1", 161 "123123", 162 "", 163 "123123", 164 "machine-1", 165 "", 166 }, 167 } 168 169 dataDir := path.Join(r.cwd, "dataDir") 170 err := os.Mkdir(dataDir, os.FileMode(0755)) 171 c.Assert(err, jc.ErrorIsNil) 172 173 logDir := path.Join(r.cwd, "logDir") 174 err = os.Mkdir(logDir, os.FileMode(0755)) 175 c.Assert(err, jc.ErrorIsNil) 176 for _, testCase := range cases { 177 machineTag, err := names.ParseTag(testCase.machineTag) 178 c.Assert(err, jc.ErrorIsNil) 179 180 configParams := agent.AgentConfigParams{ 181 Paths: agent.Paths{ 182 DataDir: dataDir, 183 LogDir: logDir, 184 }, 185 UpgradedToVersion: jujuversion.Current, 186 Tag: machineTag, 187 Model: coretesting.ModelTag, 188 Password: "placeholder", 189 Nonce: "dummyNonce", 190 StateAddresses: []string{"fakeStateAddress:1234"}, 191 APIAddresses: []string{"fakeAPIAddress:12345"}, 192 CACert: caCertPEM, 193 } 194 statePort := 12345 195 privateAddress := "dummyPrivateAddress" 196 servingInfo := params.StateServingInfo{ 197 APIPort: 1234, 198 StatePort: statePort, 199 Cert: caCertPEM, 200 CAPrivateKey: "a ca key", 201 PrivateKey: "a key", 202 SharedSecret: "a secret", 203 SystemIdentity: "an identity", 204 } 205 206 conf, err := agent.NewStateMachineConfig(configParams, servingInfo) 207 c.Assert(err, jc.ErrorIsNil) 208 conf.SetOldPassword(testCase.oldPassword) 209 conf.SetPassword(testCase.apiPassword) 210 211 dialInfo, err := newDialInfo(privateAddress, conf) 212 if testCase.expectedError != "" { 213 c.Assert(err, gc.ErrorMatches, testCase.expectedError) 214 } else { 215 c.Assert(err, jc.ErrorIsNil) 216 c.Assert(dialInfo.Username, gc.Equals, testCase.expectedUser) 217 c.Assert(dialInfo.Password, gc.Equals, testCase.expectedPassword) 218 c.Assert(dialInfo.Direct, gc.Equals, true) 219 c.Assert(dialInfo.Addrs, gc.DeepEquals, []string{net.JoinHostPort(privateAddress, strconv.Itoa(statePort))}) 220 } 221 } 222 } 223 224 // TestUpdateMongoEntries has all the testing for this function to avoid creating multiple 225 // mongo instances. 226 func (r *RestoreSuite) TestUpdateMongoEntries(c *gc.C) { 227 server := &gitjujutesting.MgoInstance{} 228 err := server.Start(coretesting.Certs) 229 c.Assert(err, jc.ErrorIsNil) 230 defer server.DestroyWithLog() 231 dialInfo := server.DialInfo() 232 mgoAddr := server.Addr() 233 dialInfo.Addrs = []string{mgoAddr} 234 err = updateMongoEntries("1234", "0", "0", dialInfo) 235 c.Assert(err, gc.ErrorMatches, "cannot update machine 0 instance information: not found") 236 237 session, err := server.Dial() 238 c.Assert(err, jc.ErrorIsNil) 239 defer session.Close() 240 241 err = session.DB("juju").C("machines").Insert(bson.M{"machineid": "0", "instanceid": "0"}) 242 c.Assert(err, jc.ErrorIsNil) 243 244 query := session.DB("juju").C("machines").Find(bson.M{"machineid": "0", "instanceid": "1234"}) 245 n, err := query.Count() 246 c.Assert(err, jc.ErrorIsNil) 247 c.Assert(n, gc.Equals, 0) 248 249 err = updateMongoEntries("1234", "0", "0", dialInfo) 250 c.Assert(err, jc.ErrorIsNil) 251 252 query = session.DB("juju").C("machines").Find(bson.M{"machineid": "0", "instanceid": "1234"}) 253 n, err = query.Count() 254 c.Assert(err, jc.ErrorIsNil) 255 c.Assert(n, gc.Equals, 1) 256 } 257 258 func (r *RestoreSuite) TestNewConnection(c *gc.C) { 259 server := &gitjujutesting.MgoInstance{} 260 err := server.Start(coretesting.Certs) 261 c.Assert(err, jc.ErrorIsNil) 262 defer server.DestroyWithLog() 263 264 st := statetesting.Initialize(c, names.NewLocalUserTag("test-admin"), nil, nil) 265 c.Assert(st.Close(), jc.ErrorIsNil) 266 267 r.PatchValue(&mongoDefaultDialOpts, mongotest.DialOpts) 268 r.PatchValue(&environsNewStatePolicy, func() state.Policy { return nil }) 269 st, err = newStateConnection(st.ModelTag(), statetesting.NewMongoInfo()) 270 c.Assert(err, jc.ErrorIsNil) 271 c.Assert(st.Close(), jc.ErrorIsNil) 272 } 273 274 func (r *RestoreSuite) TestRunViaSSH(c *gc.C) { 275 var ( 276 passedAddress string 277 passedArgs []string 278 ) 279 fakeSSHCommand := func(address string, args []string, options *ssh.Options) *ssh.Cmd { 280 passedAddress = address 281 passedArgs = args 282 return ssh.Command("", []string{"ls"}, &ssh.Options{}) 283 } 284 285 r.PatchValue(&sshCommand, fakeSSHCommand) 286 runViaSSH("invalidAddress", "invalidScript") 287 c.Assert(passedAddress, gc.Equals, "ubuntu@invalidAddress") 288 c.Assert(passedArgs, gc.DeepEquals, []string{"sudo", "-n", "bash", "-c 'invalidScript'"}) 289 }