github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/mongo/mongo_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package mongo_test 5 6 import ( 7 "encoding/base64" 8 "fmt" 9 "io/ioutil" 10 "os" 11 "os/exec" 12 "path" 13 "path/filepath" 14 "regexp" 15 "runtime" 16 "strconv" 17 "strings" 18 19 "github.com/juju/errors" 20 "github.com/juju/loggo" 21 "github.com/juju/testing" 22 jc "github.com/juju/testing/checkers" 23 "github.com/juju/utils/series" 24 gc "gopkg.in/check.v1" 25 26 "github.com/juju/juju/controller" 27 "github.com/juju/juju/mongo" 28 "github.com/juju/juju/network" 29 "github.com/juju/juju/service/common" 30 svctesting "github.com/juju/juju/service/common/testing" 31 coretesting "github.com/juju/juju/testing" 32 ) 33 34 type MongoSuite struct { 35 coretesting.BaseSuite 36 mongodConfigPath string 37 mongodPath string 38 mongodVersion mongo.Version 39 40 data *svctesting.FakeServiceData 41 } 42 43 var _ = gc.Suite(&MongoSuite{}) 44 45 var testInfo = struct { 46 StatePort int 47 Cert string 48 PrivateKey string 49 SharedSecret string 50 }{ 51 StatePort: 25252, 52 Cert: "foobar-cert", 53 PrivateKey: "foobar-privkey", 54 SharedSecret: "foobar-sharedsecret", 55 } 56 57 var expectedArgs = struct { 58 MongoInstall []jc.SimpleMessage 59 YumBase []string 60 AptGetBase []string 61 Semanage []string 62 Chcon []string 63 }{ 64 MongoInstall: []jc.SimpleMessage{ 65 {loggo.INFO, "Ensuring mongo server is running; data directory.*"}, 66 {loggo.INFO, "Running: yum --assumeyes --debuglevel=1 install epel-release"}, 67 {loggo.INFO, regexp.QuoteMeta("installing [mongodb-server]")}, 68 {loggo.INFO, "Running: yum --assumeyes --debuglevel=1 install mongodb-server"}, 69 }, 70 YumBase: []string{ 71 "--assumeyes", 72 "--debuglevel=1", 73 "install", 74 }, 75 AptGetBase: []string{ 76 "--option=Dpkg::Options::=--force-confold", 77 "--option=Dpkg::options::=--force-unsafe-io", 78 "--assume-yes", 79 "--quiet", 80 "install", 81 }, 82 Semanage: []string{ 83 "port", 84 "-a", 85 "-t", 86 "mongod_port_t", 87 "-p", 88 "tcp", 89 strconv.Itoa(controller.DefaultStatePort), 90 }, 91 Chcon: []string{ 92 "-R", 93 "-v", 94 "-t", 95 "mongod_var_lib_t", 96 "/var/lib/juju/", 97 }, 98 } 99 100 func makeEnsureServerParams(dataDir string) mongo.EnsureServerParams { 101 return mongo.EnsureServerParams{ 102 StatePort: testInfo.StatePort, 103 Cert: testInfo.Cert, 104 PrivateKey: testInfo.PrivateKey, 105 SharedSecret: testInfo.SharedSecret, 106 107 DataDir: dataDir, 108 } 109 } 110 111 func (s *MongoSuite) makeConfigArgs(dataDir string) mongo.ConfigArgs { 112 return mongo.ConfigArgs{ 113 DataDir: dataDir, 114 DBDir: dataDir, 115 MongoPath: mongo.JujuMongod24Path, 116 Port: 1234, 117 OplogSizeMB: 1024, 118 WantNUMACtl: false, 119 Version: s.mongodVersion, 120 Auth: true, 121 IPv6: true, 122 } 123 } 124 125 func (s *MongoSuite) SetUpTest(c *gc.C) { 126 s.BaseSuite.SetUpTest(c) 127 128 s.mongodVersion = mongo.Mongo24 129 130 testing.PatchExecutable(c, s, "mongod", "#!/bin/bash\n\nprintf %s 'db version v2.4.9'\n") 131 jujuMongodPath, err := exec.LookPath("mongod") 132 c.Assert(err, jc.ErrorIsNil) 133 134 s.PatchValue(&mongo.JujuMongod24Path, jujuMongodPath) 135 s.mongodPath = jujuMongodPath 136 137 // Patch "df" such that it always reports there's 1MB free. 138 s.PatchValue(mongo.AvailSpace, func(dir string) (float64, error) { 139 info, err := os.Stat(dir) 140 if err != nil { 141 return 0, err 142 } 143 if info.IsDir() { 144 return 1, nil 145 146 } 147 return 0, fmt.Errorf("not a directory") 148 }) 149 s.PatchValue(mongo.MinOplogSizeMB, 1) 150 151 testPath := c.MkDir() 152 s.mongodConfigPath = filepath.Join(testPath, "mongodConfig") 153 s.PatchValue(mongo.MongoConfigPath, s.mongodConfigPath) 154 155 s.data = svctesting.NewFakeServiceData() 156 mongo.PatchService(s.PatchValue, s.data) 157 } 158 159 func (s *MongoSuite) patchSeries(ser string) { 160 s.PatchValue(&series.HostSeries, func() string { return ser }) 161 } 162 163 func (s *MongoSuite) TestJujuMongodPath(c *gc.C) { 164 obtained, err := mongo.Path(s.mongodVersion) 165 c.Check(err, jc.ErrorIsNil) 166 c.Check(obtained, gc.Matches, s.mongodPath) 167 } 168 169 func (s *MongoSuite) TestDefaultMongodPath(c *gc.C) { 170 s.PatchValue(&mongo.JujuMongod24Path, "/not/going/to/exist/mongod") 171 s.PatchEnvPathPrepend(filepath.Dir(s.mongodPath)) 172 173 c.Logf("mongo version is %q", s.mongodVersion) 174 obtained, err := mongo.Path(s.mongodVersion) 175 c.Check(err, jc.ErrorIsNil) 176 c.Check(obtained, gc.Matches, s.mongodPath) 177 } 178 179 func (s *MongoSuite) TestMakeJournalDirs(c *gc.C) { 180 dir := c.MkDir() 181 err := mongo.MakeJournalDirs(dir) 182 c.Assert(err, jc.ErrorIsNil) 183 184 testJournalDirs(dir, c) 185 } 186 187 func testJournalDirs(dir string, c *gc.C) { 188 journalDir := path.Join(dir, "journal") 189 190 c.Assert(journalDir, jc.IsDirectory) 191 info, err := os.Stat(filepath.Join(journalDir, "prealloc.0")) 192 c.Assert(err, jc.ErrorIsNil) 193 194 size := int64(1024 * 1024) 195 196 c.Assert(info.Size(), gc.Equals, size) 197 info, err = os.Stat(filepath.Join(journalDir, "prealloc.1")) 198 c.Assert(err, jc.ErrorIsNil) 199 c.Assert(info.Size(), gc.Equals, size) 200 info, err = os.Stat(filepath.Join(journalDir, "prealloc.2")) 201 c.Assert(err, jc.ErrorIsNil) 202 c.Assert(info.Size(), gc.Equals, size) 203 } 204 205 func (s *MongoSuite) assertSSLKeyFile(c *gc.C, dataDir string) { 206 contents, err := ioutil.ReadFile(mongo.SSLKeyPath(dataDir)) 207 c.Assert(err, jc.ErrorIsNil) 208 c.Assert(string(contents), gc.Equals, testInfo.Cert+"\n"+testInfo.PrivateKey) 209 } 210 211 func (s *MongoSuite) assertSharedSecretFile(c *gc.C, dataDir string) { 212 contents, err := ioutil.ReadFile(mongo.SharedSecretPath(dataDir)) 213 c.Assert(err, jc.ErrorIsNil) 214 c.Assert(string(contents), gc.Equals, testInfo.SharedSecret) 215 } 216 217 func (s *MongoSuite) assertMongoConfigFile(c *gc.C) { 218 contents, err := ioutil.ReadFile(s.mongodConfigPath) 219 c.Assert(err, jc.ErrorIsNil) 220 c.Assert(contents, jc.DeepEquals, []byte("ENABLE_MONGODB=no")) 221 } 222 223 func (s *MongoSuite) TestEnsureServer(c *gc.C) { 224 dataDir := s.testEnsureServerNUMACtl(c, false) 225 226 s.assertSSLKeyFile(c, dataDir) 227 s.assertSharedSecretFile(c, dataDir) 228 s.assertMongoConfigFile(c) 229 230 // make sure that we log the version of mongodb as we get ready to 231 // start it 232 tlog := c.GetTestLog() 233 any := `(.|\n)*` 234 start := "^" + any 235 tail := any + "$" 236 c.Assert(tlog, gc.Matches, start+`using mongod: .*/mongod --version: "db version v\d\.\d\.\d`+tail) 237 } 238 239 func (s *MongoSuite) TestEnsureServerServerExistsAndRunning(c *gc.C) { 240 dataDir := c.MkDir() 241 242 pm, err := coretesting.GetPackageManager() 243 c.Assert(err, jc.ErrorIsNil) 244 245 testing.PatchExecutableAsEchoArgs(c, s, pm.PackageManager) 246 247 s.data.SetStatus(mongo.ServiceName, "running") 248 s.data.SetErrors(nil, nil, nil, errors.New("shouldn't be called")) 249 250 err = mongo.EnsureServer(makeEnsureServerParams(dataDir)) 251 c.Assert(err, jc.ErrorIsNil) 252 253 // These should still be written out even if the service was installed. 254 s.assertSSLKeyFile(c, dataDir) 255 s.assertSharedSecretFile(c, dataDir) 256 s.assertMongoConfigFile(c) 257 258 c.Check(s.data.Installed(), gc.HasLen, 0) 259 s.data.CheckCallNames(c, "Installed", "Exists", "Running") 260 } 261 262 func (s *MongoSuite) TestEnsureServerServerExistsNotRunningIsStarted(c *gc.C) { 263 dataDir := c.MkDir() 264 265 pm, err := coretesting.GetPackageManager() 266 c.Assert(err, jc.ErrorIsNil) 267 testing.PatchExecutableAsEchoArgs(c, s, pm.PackageManager) 268 269 s.data.SetStatus(mongo.ServiceName, "installed") 270 271 err = mongo.EnsureServer(makeEnsureServerParams(dataDir)) 272 c.Assert(err, jc.ErrorIsNil) 273 274 // These should still be written out even if the service was installed. 275 s.assertSSLKeyFile(c, dataDir) 276 s.assertSharedSecretFile(c, dataDir) 277 s.assertMongoConfigFile(c) 278 279 c.Check(s.data.Installed(), gc.HasLen, 0) 280 s.data.CheckCallNames(c, "Installed", "Exists", "Running", "Start") 281 } 282 283 func (s *MongoSuite) TestEnsureServerServerExistsNotRunningStartError(c *gc.C) { 284 dataDir := c.MkDir() 285 286 pm, err := coretesting.GetPackageManager() 287 c.Assert(err, jc.ErrorIsNil) 288 testing.PatchExecutableAsEchoArgs(c, s, pm.PackageManager) 289 290 s.data.SetStatus(mongo.ServiceName, "installed") 291 failure := errors.New("won't start") 292 s.data.SetErrors(nil, nil, nil, failure) // Installed, Exists, Running, Running, Start 293 294 err = mongo.EnsureServer(makeEnsureServerParams(dataDir)) 295 296 c.Check(errors.Cause(err), gc.Equals, failure) 297 c.Check(s.data.Installed(), gc.HasLen, 0) 298 s.data.CheckCallNames(c, "Installed", "Exists", "Running", "Start") 299 } 300 301 func (s *MongoSuite) TestEnsureServerNUMACtl(c *gc.C) { 302 s.testEnsureServerNUMACtl(c, true) 303 } 304 305 func (s *MongoSuite) testEnsureServerNUMACtl(c *gc.C, setNUMAPolicy bool) string { 306 dataDir := c.MkDir() 307 dbDir := filepath.Join(dataDir, "db") 308 309 pm, err := coretesting.GetPackageManager() 310 c.Assert(err, jc.ErrorIsNil) 311 testing.PatchExecutableAsEchoArgs(c, s, pm.PackageManager) 312 313 testParams := makeEnsureServerParams(dataDir) 314 testParams.SetNUMAControlPolicy = setNUMAPolicy 315 err = mongo.EnsureServer(testParams) 316 c.Assert(err, jc.ErrorIsNil) 317 318 testJournalDirs(dbDir, c) 319 320 assertInstalled := func() { 321 installed := s.data.Installed() 322 c.Assert(installed, gc.HasLen, 1) 323 service := installed[0] 324 c.Assert(service.Name(), gc.Equals, "juju-db") 325 c.Assert(service.Conf().Desc, gc.Equals, "juju state database") 326 if setNUMAPolicy { 327 stripped := strings.Replace(service.Conf().ExtraScript, "\n", "", -1) 328 c.Assert(stripped, gc.Matches, `.* sysctl .*`) 329 } else { 330 c.Assert(service.Conf().ExtraScript, gc.Equals, "") 331 } 332 c.Assert(service.Conf().ExecStart, gc.Matches, `.*/mongod.*`) 333 c.Assert(service.Conf().Logfile, gc.Equals, "") 334 } 335 assertInstalled() 336 return dataDir 337 } 338 339 func (s *MongoSuite) TestInstallMongod(c *gc.C) { 340 type installs struct { 341 series string 342 cmd [][]string 343 } 344 345 tests := []installs{ 346 {"precise", [][]string{{"--target-release", "precise-updates/cloud-tools", "mongodb-server"}}}, 347 {"trusty", [][]string{{"juju-mongodb3.2"}, {"juju-mongo-tools3.2"}}}, 348 {"wily", [][]string{{"juju-mongodb3.2"}, {"juju-mongo-tools3.2"}}}, 349 {"xenial", [][]string{{"juju-mongodb3.2"}, {"juju-mongo-tools3.2"}}}, 350 } 351 352 testing.PatchExecutableAsEchoArgs(c, s, "add-apt-repository") 353 testing.PatchExecutableAsEchoArgs(c, s, "apt-get") 354 for _, test := range tests { 355 c.Logf("install for series %v", test.series) 356 dataDir := c.MkDir() 357 s.patchSeries(test.series) 358 err := mongo.EnsureServer(makeEnsureServerParams(dataDir)) 359 c.Assert(err, jc.ErrorIsNil) 360 361 for _, cmd := range test.cmd { 362 match := append(expectedArgs.AptGetBase, cmd...) 363 testing.AssertEchoArgs(c, "apt-get", match...) 364 } 365 } 366 } 367 368 var fakeInstallScript = `#!/bin/bash 369 if [ $# -lt 1 ] 370 then 371 echo "Install fail - not enough arguments" 372 exit 1 373 fi 374 375 # The package name is the last argument 376 package=${@: -1} 377 echo $package >> %s 378 379 if [ $package == "juju-mongodb" ] 380 then 381 echo "Installed successfully!" 382 exit 0 383 fi 384 385 if [ $package == "mongodb-server" ] 386 then 387 echo "Installed successfully!" 388 exit 0 389 fi 390 391 echo "Unable to locate package $package" 392 exit 100 393 ` 394 395 func (s *MongoSuite) TestInstallMongodFallsBack(c *gc.C) { 396 if runtime.GOOS == "windows" { 397 c.Skip("Skipping TestInstallMongodFallsBack as mongo is not installed on windows") 398 } 399 400 type installs struct { 401 series string 402 cmd string 403 } 404 405 tests := []installs{ 406 {"precise", "mongodb-server"}, 407 {"trusty", "juju-mongodb3.2\njuju-mongodb"}, 408 {"wily", "juju-mongodb3.2\njuju-mongodb"}, 409 {"xenial", "juju-mongodb3.2\njuju-mongodb"}, 410 } 411 412 dataDir := c.MkDir() 413 outputFile := filepath.Join(dataDir, "apt-get-args") 414 testing.PatchExecutable(c, s, "apt-get", fmt.Sprintf(fakeInstallScript, outputFile)) 415 for _, test := range tests { 416 c.Logf("Testing mongo install for series: %s", test.series) 417 s.patchSeries(test.series) 418 err := mongo.EnsureServer(makeEnsureServerParams(dataDir)) 419 c.Assert(err, jc.ErrorIsNil) 420 421 args, err := ioutil.ReadFile(outputFile) 422 c.Assert(err, jc.ErrorIsNil) 423 c.Check(strings.TrimSpace(string(args)), gc.Equals, test.cmd) 424 425 err = os.Remove(outputFile) 426 c.Assert(err, jc.ErrorIsNil) 427 } 428 } 429 430 func (s *MongoSuite) TestInstallFailChconMongodCentOS(c *gc.C) { 431 returnCode := 1 432 execNameFail := "chcon" 433 434 exec := []string{"yum", "chcon"} 435 436 expectedResult := append(expectedArgs.MongoInstall, []jc.SimpleMessage{ 437 {loggo.INFO, "running " + execNameFail + " .*"}, 438 {loggo.ERROR, execNameFail + " failed to change file security context error exit status " + strconv.Itoa(returnCode)}, 439 {loggo.ERROR, regexp.QuoteMeta("cannot install/upgrade mongod (will proceed anyway): exit status " + strconv.Itoa(returnCode))}, 440 }...) 441 s.assertSuccessWithInstallStepFailCentOS(c, exec, execNameFail, returnCode, expectedResult) 442 } 443 444 func (s *MongoSuite) TestSemanageRuleExistsDoesNotFail(c *gc.C) { 445 // if the return code is 1 then the rule already exists and we do not fail 446 returnCode := 1 447 execNameFail := "semanage" 448 449 exec := []string{"yum", "chcon"} 450 451 expectedResult := append(expectedArgs.MongoInstall, []jc.SimpleMessage{ 452 {loggo.INFO, "running chcon .*"}, 453 {loggo.INFO, "running " + execNameFail + " .*"}, 454 }...) 455 456 s.assertSuccessWithInstallStepFailCentOS(c, exec, execNameFail, returnCode, expectedResult) 457 } 458 459 func (s *MongoSuite) TestInstallFailSemanageMongodCentOS(c *gc.C) { 460 returnCode := 2 461 execNameFail := "semanage" 462 463 exec := []string{"yum", "chcon"} 464 465 expectedResult := append(expectedArgs.MongoInstall, []jc.SimpleMessage{ 466 {loggo.INFO, "running chcon .*"}, 467 {loggo.INFO, "running " + execNameFail + " .*"}, 468 {loggo.ERROR, execNameFail + " failed to provide access on port " + strconv.Itoa(controller.DefaultStatePort) + " error exit status " + strconv.Itoa(returnCode)}, 469 {loggo.ERROR, regexp.QuoteMeta("cannot install/upgrade mongod (will proceed anyway): exit status " + strconv.Itoa(returnCode))}, 470 }...) 471 s.assertSuccessWithInstallStepFailCentOS(c, exec, execNameFail, returnCode, expectedResult) 472 } 473 474 func (s *MongoSuite) assertSuccessWithInstallStepFailCentOS(c *gc.C, exec []string, execNameFail string, returnCode int, expectedResult []jc.SimpleMessage) { 475 type installs struct { 476 series string 477 pkg string 478 } 479 test := installs{ 480 "centos7", "mongodb*", 481 } 482 483 for _, e := range exec { 484 testing.PatchExecutableAsEchoArgs(c, s, e) 485 } 486 487 testing.PatchExecutableThrowError(c, s, execNameFail, returnCode) 488 489 dataDir := c.MkDir() 490 s.patchSeries(test.series) 491 492 var tw loggo.TestWriter 493 c.Assert(loggo.RegisterWriter("mongosuite", &tw), jc.ErrorIsNil) 494 defer loggo.RemoveWriter("mongosuite") 495 496 err := mongo.EnsureServer(makeEnsureServerParams(dataDir)) 497 c.Assert(err, jc.ErrorIsNil) 498 c.Assert(tw.Log(), jc.LogMatches, expectedResult) 499 } 500 501 func (s *MongoSuite) TestInstallSuccessMongodCentOS(c *gc.C) { 502 type installs struct { 503 series string 504 pkg string 505 } 506 test := installs{ 507 "centos7", "mongodb*", 508 } 509 510 testing.PatchExecutableAsEchoArgs(c, s, "yum") 511 testing.PatchExecutableAsEchoArgs(c, s, "chcon") 512 testing.PatchExecutableAsEchoArgs(c, s, "semanage") 513 514 dataDir := c.MkDir() 515 s.patchSeries(test.series) 516 517 err := mongo.EnsureServer(makeEnsureServerParams(dataDir)) 518 c.Assert(err, jc.ErrorIsNil) 519 520 expected := append(expectedArgs.YumBase, "epel-release") 521 522 testing.AssertEchoArgs(c, "yum", expected...) 523 524 testing.AssertEchoArgs(c, "chcon", expectedArgs.Chcon...) 525 526 testing.AssertEchoArgs(c, "semanage", expectedArgs.Semanage...) 527 } 528 529 func (s *MongoSuite) TestMongoAptGetFails(c *gc.C) { 530 s.assertTestMongoGetFails(c, "trusty", "apt-get") 531 } 532 533 func (s *MongoSuite) TestMongoYumFails(c *gc.C) { 534 s.assertTestMongoGetFails(c, "centos7", "yum") 535 } 536 537 func (s *MongoSuite) assertTestMongoGetFails(c *gc.C, series string, packageManager string) { 538 s.patchSeries(series) 539 540 // Any exit code from apt-get that isn't 0 or 100 will be treated 541 // as unexpected, skipping the normal retry loop. failCmd causes 542 // the command to exit with 1. 543 binDir := c.MkDir() 544 s.PatchEnvPathPrepend(binDir) 545 failCmd(filepath.Join(binDir, packageManager)) 546 547 // Set the mongodb service as installed but not running. 548 s.data.SetStatus(mongo.ServiceName, "installed") 549 550 var tw loggo.TestWriter 551 writer := loggo.NewMinimumLevelWriter(&tw, loggo.ERROR) 552 c.Assert(loggo.RegisterWriter("test-writer", writer), jc.ErrorIsNil) 553 defer loggo.RemoveWriter("test-writer") 554 555 dataDir := c.MkDir() 556 err := mongo.EnsureServer(makeEnsureServerParams(dataDir)) 557 558 // Even though apt-get failed, EnsureServer should continue and 559 // not return the error - even though apt-get failed, the Juju 560 // mongodb package is most likely already installed. 561 // The error should be logged however. 562 c.Assert(err, jc.ErrorIsNil) 563 564 c.Check(tw.Log(), jc.LogMatches, []jc.SimpleMessage{ 565 {loggo.ERROR, `packaging command failed: .+`}, 566 {loggo.ERROR, `cannot install/upgrade mongod \(will proceed anyway\): packaging command failed`}, 567 }) 568 569 // Verify that EnsureServer continued and started the mongodb service. 570 c.Check(s.data.Installed(), gc.HasLen, 0) 571 s.data.CheckCallNames(c, "Installed", "Exists", "Running", "Start") 572 } 573 574 func (s *MongoSuite) TestInstallMongodServiceExists(c *gc.C) { 575 pm, err := coretesting.GetPackageManager() 576 c.Assert(err, jc.ErrorIsNil) 577 testing.PatchExecutableAsEchoArgs(c, s, pm.PackageManager) 578 if pm.PackageManager == "yum" { 579 testing.PatchExecutableAsEchoArgs(c, s, "chcon") 580 testing.PatchExecutableAsEchoArgs(c, s, "semanage") 581 } 582 583 dataDir := c.MkDir() 584 585 s.data.SetStatus(mongo.ServiceName, "running") 586 s.data.SetErrors(nil, nil, nil, errors.New("shouldn't be called")) 587 588 err = mongo.EnsureServer(makeEnsureServerParams(dataDir)) 589 c.Assert(err, jc.ErrorIsNil) 590 591 c.Check(s.data.Installed(), gc.HasLen, 0) 592 s.data.CheckCallNames(c, "Installed", "Exists", "Running") 593 } 594 595 func (s *MongoSuite) TestNewServiceWithReplSet(c *gc.C) { 596 conf := mongo.NewConf(s.makeConfigArgs(c.MkDir())) 597 c.Assert(strings.Contains(conf.ExecStart, "--replSet"), jc.IsTrue) 598 } 599 600 func (s *MongoSuite) TestNewServiceWithNumCtl(c *gc.C) { 601 args := s.makeConfigArgs(c.MkDir()) 602 args.WantNUMACtl = true 603 conf := mongo.NewConf(args) 604 c.Assert(conf.ExtraScript, gc.Not(gc.Matches), "") 605 } 606 607 func (s *MongoSuite) TestNewServiceWithIPv6(c *gc.C) { 608 args := s.makeConfigArgs(c.MkDir()) 609 args.IPv6 = true 610 conf := mongo.NewConf(args) 611 c.Assert(strings.Contains(conf.ExecStart, "--ipv6"), jc.IsTrue) 612 } 613 614 func (s *MongoSuite) TestNewServiceWithoutIPv6(c *gc.C) { 615 args := s.makeConfigArgs(c.MkDir()) 616 args.IPv6 = false 617 conf := mongo.NewConf(args) 618 c.Assert(strings.Contains(conf.ExecStart, "--ipv6"), jc.IsFalse) 619 } 620 621 func (s *MongoSuite) TestNewServiceWithJournal(c *gc.C) { 622 args := s.makeConfigArgs(c.MkDir()) 623 conf := mongo.NewConf(args) 624 c.Assert(conf.ExecStart, gc.Matches, `.* --journal.*`) 625 } 626 627 func (s *MongoSuite) TestRemoveService(c *gc.C) { 628 s.data.SetStatus(mongo.ServiceName, "running") 629 630 err := mongo.RemoveService() 631 c.Assert(err, jc.ErrorIsNil) 632 633 removed := s.data.Removed() 634 if !c.Check(removed, gc.HasLen, 1) { 635 c.Check(removed[0].Name(), gc.Equals, "juju-db-namespace") 636 c.Check(removed[0].Conf(), jc.DeepEquals, common.Conf{}) 637 } 638 s.data.CheckCallNames(c, "Stop", "Remove") 639 } 640 641 func (s *MongoSuite) TestNoMongoDir(c *gc.C) { 642 // Make a non-existent directory that can nonetheless be 643 // created. 644 pm, err := coretesting.GetPackageManager() 645 c.Assert(err, jc.ErrorIsNil) 646 testing.PatchExecutableAsEchoArgs(c, s, pm.PackageManager) 647 648 dataDir := filepath.Join(c.MkDir(), "dir", "data") 649 err = mongo.EnsureServer(makeEnsureServerParams(dataDir)) 650 c.Check(err, jc.ErrorIsNil) 651 652 _, err = os.Stat(filepath.Join(dataDir, "db")) 653 c.Assert(err, jc.ErrorIsNil) 654 } 655 656 func (s *MongoSuite) TestSelectPeerAddress(c *gc.C) { 657 addresses := []network.Address{{ 658 Value: "10.0.0.1", 659 Type: network.IPv4Address, 660 Scope: network.ScopeCloudLocal, 661 }, { 662 Value: "8.8.8.8", 663 Type: network.IPv4Address, 664 Scope: network.ScopePublic, 665 }} 666 667 address := mongo.SelectPeerAddress(addresses) 668 c.Assert(address, gc.Equals, "10.0.0.1") 669 } 670 671 func (s *MongoSuite) TestSelectPeerHostPort(c *gc.C) { 672 673 hostPorts := []network.HostPort{{ 674 Address: network.Address{ 675 Value: "10.0.0.1", 676 Type: network.IPv4Address, 677 Scope: network.ScopeCloudLocal, 678 }, 679 Port: controller.DefaultStatePort}, { 680 Address: network.Address{ 681 Value: "8.8.8.8", 682 Type: network.IPv4Address, 683 Scope: network.ScopePublic, 684 }, 685 Port: controller.DefaultStatePort}} 686 687 address := mongo.SelectPeerHostPort(hostPorts) 688 c.Assert(address, gc.Equals, "10.0.0.1:"+strconv.Itoa(controller.DefaultStatePort)) 689 } 690 691 func (s *MongoSuite) TestGenerateSharedSecret(c *gc.C) { 692 secret, err := mongo.GenerateSharedSecret() 693 c.Assert(err, jc.ErrorIsNil) 694 c.Assert(secret, gc.HasLen, 1024) 695 _, err = base64.StdEncoding.DecodeString(secret) 696 c.Assert(err, jc.ErrorIsNil) 697 } 698 699 func (s *MongoSuite) TestAddEpelInCentOS(c *gc.C) { 700 testing.PatchExecutableAsEchoArgs(c, s, "yum") 701 702 s.patchSeries("centos7") 703 704 testing.PatchExecutableAsEchoArgs(c, s, "chcon") 705 testing.PatchExecutableAsEchoArgs(c, s, "semanage") 706 testing.PatchExecutableAsEchoArgs(c, s, "yum-config-manager") 707 708 dataDir := c.MkDir() 709 err := mongo.EnsureServer(makeEnsureServerParams(dataDir)) 710 c.Assert(err, jc.ErrorIsNil) 711 712 expectedEpelRelease := append(expectedArgs.YumBase, "epel-release") 713 testing.AssertEchoArgs(c, "yum", expectedEpelRelease...) 714 715 expectedMongodbServer := append(expectedArgs.YumBase, "mongodb-server") 716 testing.AssertEchoArgs(c, "yum", expectedMongodbServer...) 717 718 testing.AssertEchoArgs(c, "chcon", expectedArgs.Chcon...) 719 720 testing.AssertEchoArgs(c, "semanage", expectedArgs.Semanage...) 721 } 722 723 // failCmd creates an executable file at the given location that will do nothing 724 // except return an error. 725 func failCmd(path string) { 726 err := ioutil.WriteFile(path, []byte("#!/bin/bash --norc\nexit 1"), 0755) 727 if err != nil { 728 panic(err) 729 } 730 }