func (s *BootstrapSuite) TestGUIArchiveInfoError(c *gc.C) { if runtime.GOOS == "windows" { // TODO frankban: skipping for now due to chmod problems with mode 0000 // on Windows. We will re-enable this test after further investigation: // "jujud bootstrap" is never run on Windows anyway. c.Skip("needs chmod investigation") } dir := filepath.FromSlash(agenttools.SharedGUIDir(s.dataDir)) info := filepath.Join(dir, "downloaded-gui.txt") err := os.Chmod(info, 0000) c.Assert(err, jc.ErrorIsNil) defer os.Chmod(info, 0600) _, cmd, err := s.initBootstrapCommand( c, nil, "--model-config", s.b64yamlControllerModelConfig, "--hosted-model-config", s.b64yamlHostedModelConfig, "--instance-id", string(s.instanceId)) c.Assert(err, jc.ErrorIsNil) var tw loggo.TestWriter err = loggo.RegisterWriter("bootstrap-test", &tw, loggo.DEBUG) c.Assert(err, jc.ErrorIsNil) defer loggo.RemoveWriter("bootstrap-test") err = cmd.Run(nil) c.Assert(err, jc.ErrorIsNil) c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{ loggo.WARNING, `cannot set up Juju GUI: cannot fetch GUI info: cannot read GUI metadata in tools directory: .*`, }}) }
func (s *MongoSuite) assertTestMongoGetFails(c *gc.C, series string, packageManager string) { s.patchSeries(series) // Any exit code from apt-get that isn't 0 or 100 will be treated // as unexpected, skipping the normal retry loop. failCmd causes // the command to exit with 1. binDir := c.MkDir() s.PatchEnvPathPrepend(binDir) failCmd(filepath.Join(binDir, packageManager)) // Set the mongodb service as installed but not running. s.data.SetStatus(mongo.ServiceName, "installed") var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("test-writer", &tw, loggo.ERROR), jc.ErrorIsNil) defer loggo.RemoveWriter("test-writer") dataDir := c.MkDir() err := mongo.EnsureServer(makeEnsureServerParams(dataDir)) // Even though apt-get failed, EnsureServer should continue and // not return the error - even though apt-get failed, the Juju // mongodb package is most likely already installed. // The error should be logged however. c.Assert(err, jc.ErrorIsNil) c.Check(tw.Log(), jc.LogMatches, []jc.SimpleMessage{ {loggo.ERROR, `packaging command failed: .+`}, {loggo.ERROR, `cannot install/upgrade mongod \(will proceed anyway\): packaging command failed`}, }) // Verify that EnsureServer continued and started the mongodb service. c.Check(s.data.Installed(), gc.HasLen, 0) s.data.CheckCallNames(c, "Installed", "Exists", "Running", "Start") }
func (s *MongoSuite) TestQuantalAptAddRepo(c *gc.C) { dir := c.MkDir() // patch manager.RunCommandWithRetry for repository addition: s.PatchValue(&manager.RunCommandWithRetry, func(string) (string, int, error) { return "", 1, fmt.Errorf("packaging command failed: exit status 1") }) s.PatchEnvPathPrepend(dir) failCmd(filepath.Join(dir, "add-apt-repository")) mockShellCommand(c, &s.CleanupSuite, "apt-get") var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("test-writer", &tw, loggo.ERROR), jc.ErrorIsNil) defer loggo.RemoveWriter("test-writer") // test that we call add-apt-repository only for quantal // (and that if it fails, we log the error) s.PatchValue(&version.Current.Series, "quantal") err := mongo.EnsureServer(makeEnsureServerParams(dir, "")) c.Assert(err, jc.ErrorIsNil) c.Assert(tw.Log(), jc.LogMatches, []jc.SimpleMessage{ {loggo.ERROR, `cannot install/upgrade mongod \(will proceed anyway\): packaging command failed`}, }) s.PatchValue(&manager.RunCommandWithRetry, func(string) (string, int, error) { return "", 0, nil }) s.PatchValue(&version.Current.Series, "trusty") failCmd(filepath.Join(dir, "mongod")) err = mongo.EnsureServer(makeEnsureServerParams(dir, "")) c.Assert(err, jc.ErrorIsNil) }
func (s *SimpleStreamsToolsSuite) TestFindToolsFiltering(c *gc.C) { var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("filter-tester", &tw, loggo.TRACE), gc.IsNil) defer loggo.RemoveWriter("filter-tester") logger := loggo.GetLogger("juju.environs") defer logger.SetLogLevel(logger.LogLevel()) logger.SetLogLevel(loggo.TRACE) _, err := envtools.FindTools( s.env, 1, -1, "released", coretools.Filter{Number: version.Number{Major: 1, Minor: 2, Patch: 3}}) c.Assert(err, jc.Satisfies, errors.IsNotFound) // This is slightly overly prescriptive, but feel free to change or add // messages. This still helps to ensure that all log messages are // properly formed. messages := []jc.SimpleMessage{ {loggo.INFO, "reading tools with major version 1"}, {loggo.INFO, "filtering tools by version: \\d+\\.\\d+\\.\\d+"}, {loggo.TRACE, "no architecture specified when finding tools, looking for "}, {loggo.TRACE, "no series specified when finding tools, looking for \\[.*\\]"}, } sources, err := envtools.GetMetadataSources(s.env) c.Assert(err, jc.ErrorIsNil) for i := 0; i < 2*len(sources); i++ { messages = append(messages, jc.SimpleMessage{loggo.TRACE, `fetchData failed for .*`}, jc.SimpleMessage{loggo.TRACE, `cannot load index .*`}) } c.Check(tw.Log(), jc.LogMatches, messages) }
func (s *syncToolsSuite) TestSyncToolsCommandDeprecatedDestination(c *gc.C) { called := false dir := c.MkDir() syncTools = func(sctx *sync.SyncContext) error { c.Assert(sctx.AllVersions, gc.Equals, false) c.Assert(sctx.DryRun, gc.Equals, false) c.Assert(sctx.Dev, gc.Equals, false) c.Assert(sctx.Source, gc.Equals, "") url, err := sctx.Target.URL("") c.Assert(err, gc.IsNil) c.Assert(url, gc.Equals, "file://"+dir) called = true return nil } // Register writer. var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("deprecated-tester", &tw, loggo.DEBUG), gc.IsNil) defer loggo.RemoveWriter("deprecated-tester") // Add deprecated message to be checked. messages := []jc.SimpleMessage{ {loggo.WARNING, "Use of the --destination flag is deprecated in 1.18. Please use --local-dir instead."}, } // Run sync-tools command with --destination flag. ctx, err := runSyncToolsCommand(c, "-e", "test-target", "--destination", dir) c.Assert(err, gc.IsNil) c.Assert(ctx, gc.NotNil) c.Assert(called, jc.IsTrue) // Check deprecated message was logged. c.Check(tw.Log(), jc.LogMatches, messages) s.Reset(c) }
func (s *syncToolsSuite) TestSyncToolsCommandDeprecatedDestination(c *gc.C) { called := false dir := c.MkDir() syncTools = func(sctx *sync.SyncContext) error { c.Assert(sctx.AllVersions, jc.IsFalse) c.Assert(sctx.DryRun, jc.IsFalse) c.Assert(sctx.Stream, gc.Equals, "released") c.Assert(sctx.Source, gc.Equals, "") c.Assert(sctx.TargetToolsUploader, gc.FitsTypeOf, sync.StorageToolsUploader{}) uploader := sctx.TargetToolsUploader.(sync.StorageToolsUploader) url, err := uploader.Storage.URL("") c.Assert(err, jc.ErrorIsNil) c.Assert(url, gc.Equals, utils.MakeFileURL(dir)) called = true return nil } // Register writer. var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("deprecated-tester", &tw, loggo.DEBUG), gc.IsNil) defer loggo.RemoveWriter("deprecated-tester") // Add deprecated message to be checked. messages := []jc.SimpleMessage{ {loggo.WARNING, "Use of the --destination flag is deprecated in 1.18. Please use --local-dir instead."}, } // Run sync-tools command with --destination flag. ctx, err := runSyncToolsCommand(c, "-m", "test-target", "--destination", dir, "--stream", "released") c.Assert(err, jc.ErrorIsNil) c.Assert(ctx, gc.NotNil) c.Assert(called, jc.IsTrue) // Check deprecated message was logged. c.Check(tw.Log(), jc.LogMatches, messages) }
func (*diskStoreSuite) TestConcurrentAccess(c *gc.C) { var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("test-log", &tw, loggo.DEBUG), gc.IsNil) dir := c.MkDir() store, err := configstore.NewDisk(dir) c.Assert(err, jc.ErrorIsNil) envDir := storePath(dir, "") lock, err := configstore.AcquireEnvironmentLock(envDir, "blocking-op") c.Assert(err, jc.ErrorIsNil) defer lock.Unlock() _, err = store.ReadInfo("someenv") c.Assert(errors.Cause(err), gc.Equals, fslock.ErrTimeout) // Using . between environments and env.lock so we don't have to care // about forward vs. backwards slash separator. messages := []jc.SimpleMessage{ {loggo.WARNING, `configstore lock held, lock dir: .*environments.env\.lock`}, {loggo.WARNING, `lock holder message: pid: \d+, operation: blocking-op`}, } c.Check(tw.Log(), jc.LogMatches, messages) }
func (s *MongoSuite) assertSuccessWithInstallStepFailCentOS(c *gc.C, exec []string, execNameFail string, returnCode int, expectedResult []jc.SimpleMessage) { type installs struct { series string pkg string } test := installs{ "centos7", "mongodb*", } for _, e := range exec { testing.PatchExecutableAsEchoArgs(c, s, e) } testing.PatchExecutableThrowError(c, s, execNameFail, returnCode) dataDir := c.MkDir() s.patchSeries(test.series) var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("mongosuite", &tw, loggo.INFO), jc.ErrorIsNil) defer loggo.RemoveWriter("mongosuite") err := mongo.EnsureServer(makeEnsureServerParams(dataDir)) c.Assert(err, jc.ErrorIsNil) c.Assert(tw.Log(), jc.LogMatches, expectedResult) }
func gatherLog(f func()) []loggo.Entry { var tw loggo.TestWriter err := loggo.RegisterWriter("test", &tw) if err != nil { panic(err) } defer loggo.RemoveWriter("test") f() return tw.Log() }
func (s *prepareSuite) assertCall(c *gc.C, args params.Entities, expectResults *params.MachineNetworkConfigResults, expectErr string) (error, []loggo.TestLogValues) { // Capture the logs for later inspection. logger := loggo.GetLogger("juju.apiserver.provisioner") defer logger.SetLogLevel(logger.LogLevel()) logger.SetLogLevel(loggo.TRACE) var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("test", &tw, loggo.TRACE), gc.IsNil) defer loggo.RemoveWriter("test") results, err := s.provAPI.PrepareContainerInterfaceInfo(args) c.Logf("PrepareContainerInterfaceInfo returned: err=%v, results=%v", err, results) c.Assert(results.Results, gc.HasLen, len(args.Entities)) if expectErr == "" { c.Assert(err, jc.ErrorIsNil) c.Assert(expectResults, gc.NotNil) c.Assert(results.Results, gc.HasLen, len(expectResults.Results)) // Check for any "regex:" prefixes first. Then replace // addresses in expected with the actual ones, so we can use // jc.DeepEquals on the whole result below. // Also check MAC addresses are valid, but as they're randomly // generated we can't test specific values. for i, expect := range expectResults.Results { cfg := results.Results[i].Config c.Assert(cfg, gc.HasLen, len(expect.Config)) for j, expCfg := range expect.Config { if strings.HasPrefix(expCfg.Address, "regex:") { rex := strings.TrimPrefix(expCfg.Address, "regex:") c.Assert(cfg[j].Address, gc.Matches, rex) expectResults.Results[i].Config[j].Address = cfg[j].Address } macAddress := cfg[j].MACAddress c.Assert(macAddress[:8], gc.Equals, provisioner.MACAddressTemplate[:8]) remainder := strings.Replace(macAddress[8:], ":", "", 3) c.Assert(remainder, gc.HasLen, 6) _, err = hex.DecodeString(remainder) c.Assert(err, jc.ErrorIsNil) expectResults.Results[i].Config[j].MACAddress = macAddress } } c.Assert(results, jc.DeepEquals, *expectResults) } else { c.Assert(err, gc.ErrorMatches, expectErr) if len(args.Entities) > 0 { result := results.Results[0] // Not using jc.ErrorIsNil below because // (*params.Error)(nil) does not satisfy the error // interface. c.Assert(result.Error, gc.IsNil) c.Assert(result.Config, gc.IsNil) } } return err, tw.Log() }
func (*auditSuite) TestAuditEventWrittenToAuditLogger(c *gc.C) { var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("audit-log", &tw, loggo.DEBUG), gc.IsNil) u := &mockUser{tag: "user-agnus"} Audit(u, "donut eaten, %v donut(s) remain", 7) // Add deprecated message to be checked. messages := []jc.SimpleMessage{ {loggo.INFO, `user-agnus: donut eaten, 7 donut\(s\) remain`}, } c.Check(tw.Log(), jc.LogMatches, messages) }
func (s *BootstrapSuite) TestBootstrapJenvWarning(c *gc.C) { const envName = "devenv" s.patchVersionAndSeries(c, envName) store, err := configstore.Default() c.Assert(err, jc.ErrorIsNil) ctx := coretesting.Context(c) environs.PrepareFromName(envName, envcmd.BootstrapContext(ctx), store) logger := "jenv.warning.test" var testWriter loggo.TestWriter loggo.RegisterWriter(logger, &testWriter, loggo.WARNING) defer loggo.RemoveWriter(logger) _, errc := cmdtesting.RunCommand(ctx, newBootstrapCommand(), "-e", envName, "--auto-upgrade") c.Assert(<-errc, gc.IsNil) c.Assert(testWriter.Log(), jc.LogMatches, []string{"ignoring environments.yaml: using bootstrap config in .*"}) }
func (s *ServiceSuite) TestSetUnsupportedConstraintsWarning(c *gc.C) { defer loggo.ResetWriters() logger := loggo.GetLogger("test") logger.SetLogLevel(loggo.DEBUG) var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("constraints-tester", &tw, loggo.DEBUG), gc.IsNil) cons := constraints.MustParse("mem=4G cpu-power=10") err := s.mysql.SetConstraints(cons) c.Assert(err, gc.IsNil) c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{ loggo.WARNING, `setting constraints on service "mysql": unsupported constraints: cpu-power`}, }) scons, err := s.mysql.Constraints() c.Assert(err, gc.IsNil) c.Assert(scons, gc.DeepEquals, cons) }
func (s *BootstrapSuite) TestGUIArchiveSuccess(c *gc.C) { _, cmd, err := s.initBootstrapCommand( c, nil, "--model-config", s.b64yamlControllerModelConfig, "--hosted-model-config", s.b64yamlHostedModelConfig, "--instance-id", string(s.instanceId)) c.Assert(err, jc.ErrorIsNil) var tw loggo.TestWriter err = loggo.RegisterWriter("bootstrap-test", &tw, loggo.DEBUG) c.Assert(err, jc.ErrorIsNil) defer loggo.RemoveWriter("bootstrap-test") err = cmd.Run(nil) c.Assert(err, jc.ErrorIsNil) c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{ loggo.DEBUG, `Juju GUI successfully set up`, }}) // Retrieve the state so that it is possible to access the GUI storage. st, err := state.Open(testing.ModelTag, &mongo.MongoInfo{ Info: mongo.Info{ Addrs: []string{gitjujutesting.MgoServer.Addr()}, CACert: testing.CACert, }, Password: testPassword, }, mongotest.DialOpts(), environs.NewStatePolicy()) c.Assert(err, jc.ErrorIsNil) defer st.Close() // The GUI archive has been uploaded to the GUI storage. storage, err := st.GUIStorage() c.Assert(err, jc.ErrorIsNil) defer storage.Close() allMeta, err := storage.AllMetadata() c.Assert(err, jc.ErrorIsNil) c.Assert(allMeta, gc.HasLen, 1) c.Assert(allMeta[0].Version, gc.Equals, "2.0.42") // The current GUI version has been set. vers, err := st.GUIVersion() c.Assert(err, jc.ErrorIsNil) c.Assert(vers.String(), gc.Equals, "2.0.42") }
func (s *loginSuite) TestLoginSetsLogIdentifier(c *gc.C) { info, cleanup := s.setupServer(c) defer cleanup() machineInState, err := s.State.AddMachine("quantal", state.JobHostUnits) c.Assert(err, gc.IsNil) err = machineInState.SetProvisioned("foo", "fake_nonce", nil) c.Assert(err, gc.IsNil) password, err := utils.RandomPassword() c.Assert(err, gc.IsNil) err = machineInState.SetPassword(password) c.Assert(err, gc.IsNil) c.Assert(machineInState.Tag(), gc.Equals, names.NewMachineTag("0")) var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("login-tester", &tw, loggo.DEBUG), gc.IsNil) defer loggo.RemoveWriter("login-tester") // TODO(dfc) this should be a Tag info.Tag = machineInState.Tag().String() info.Password = password info.Nonce = "fake_nonce" apiConn, err := api.Open(info, fastDialOpts) c.Assert(err, gc.IsNil) defer apiConn.Close() // TODO(dfc) why does this return a string apiMachine, err := apiConn.Machiner().Machine(machineInState.Tag().(names.MachineTag)) c.Assert(err, gc.IsNil) c.Assert(apiMachine.Tag(), gc.Equals, machineInState.Tag().String()) c.Assert(tw.Log(), jc.LogMatches, []string{ `<- \[[0-9A-F]+\] <unknown> {"RequestId":1,"Type":"Admin","Request":"Login",` + `"Params":{"AuthTag":"machine-0","Password":"******"]*","Nonce":"fake_nonce"}` + `}`, // Now that we are logged in, we see the entity's tag // [0-9.umns] is to handle timestamps that are ns, us, ms, or s // long, though we expect it to be in the 'ms' range. `-> \[[0-9A-F]+\] machine-0 [0-9.]+[umn]?s {"RequestId":1,"Response":.*} Admin\[""\].Login`, `<- \[[0-9A-F]+\] machine-0 {"RequestId":2,"Type":"Machiner","Request":"Life","Params":{"Entities":\[{"Tag":"machine-0"}\]}}`, `-> \[[0-9A-F]+\] machine-0 [0-9.umns]+ {"RequestId":2,"Response":{"Results":\[{"Life":"alive","Error":null}\]}} Machiner\[""\]\.Life`, }) }
func assertLogs(c *gc.C, ctx jujuc.Context, writer *loggo.TestWriter, unitname, badge string) { msg1 := "the chickens" msg2 := "are 110% AWESOME" com, err := jujuc.NewCommand(ctx, cmdString("juju-log")) c.Assert(err, jc.ErrorIsNil) for _, t := range []struct { args []string level loggo.Level }{ { level: loggo.INFO, }, { args: []string{"--debug"}, level: loggo.DEBUG, }, { args: []string{"--log-level", "TRACE"}, level: loggo.TRACE, }, { args: []string{"--log-level", "info"}, level: loggo.INFO, }, { args: []string{"--log-level", "WaRnInG"}, level: loggo.WARNING, }, { args: []string{"--log-level", "error"}, level: loggo.ERROR, }, } { writer.Clear() c.Assert(err, jc.ErrorIsNil) args := append(t.args, msg1, msg2) code := cmd.Main(com, &cmd.Context{}, args) c.Assert(code, gc.Equals, 0) log := writer.Log() c.Assert(log, gc.HasLen, 1) c.Assert(log[0].Level, gc.Equals, t.level) c.Assert(log[0].Module, gc.Equals, fmt.Sprintf("unit.%s.juju-log", unitname)) c.Assert(log[0].Message, gc.Equals, fmt.Sprintf("%s%s %s", badge, msg1, msg2)) } }
func (s *BootstrapSuite) TestCannotRecordThenCannotStop(c *gc.C) { innerStorage := newStorage(s, c) stor := &mockStorage{Storage: innerStorage} startInstance := func( _ string, _ constraints.Value, _ []string, _ tools.List, _ *cloudinit.MachineConfig, ) ( instance.Instance, *instance.HardwareCharacteristics, []network.Info, error, ) { stor.putErr = fmt.Errorf("suddenly a wild blah") return &mockInstance{id: "i-blah"}, nil, nil, nil } var stopped []instance.Id stopInstances := func(instances []instance.Id) error { stopped = append(stopped, instances...) return fmt.Errorf("bork bork borken") } var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("bootstrap-tester", &tw, loggo.DEBUG), gc.IsNil) defer loggo.RemoveWriter("bootstrap-tester") env := &mockEnviron{ storage: stor, startInstance: startInstance, stopInstances: stopInstances, config: configGetter(c), } ctx := coretesting.Context(c) _, _, _, err := common.Bootstrap(ctx, env, environs.BootstrapParams{ AvailableTools: tools.List{&tools.Tools{Version: version.Current}}, }) c.Assert(err, gc.ErrorMatches, "cannot save state: suddenly a wild blah") c.Assert(stopped, gc.HasLen, 1) c.Assert(stopped[0], gc.Equals, instance.Id("i-blah")) c.Assert(tw.Log(), jc.LogMatches, []jc.SimpleMessage{{ loggo.ERROR, `cannot stop failed bootstrap instance "i-blah": bork bork borken`, }}) }
func (s *BootstrapSuite) TestGUIArchiveError(c *gc.C) { dir := filepath.FromSlash(agenttools.SharedGUIDir(s.dataDir)) archive := filepath.Join(dir, "gui.tar.bz2") err := os.Remove(archive) c.Assert(err, jc.ErrorIsNil) _, cmd, err := s.initBootstrapCommand( c, nil, "--model-config", s.b64yamlControllerModelConfig, "--hosted-model-config", s.b64yamlHostedModelConfig, "--instance-id", string(s.instanceId)) c.Assert(err, jc.ErrorIsNil) var tw loggo.TestWriter err = loggo.RegisterWriter("bootstrap-test", &tw, loggo.DEBUG) c.Assert(err, jc.ErrorIsNil) defer loggo.RemoveWriter("bootstrap-test") err = cmd.Run(nil) c.Assert(tw.Log(), jc.LogMatches, jc.SimpleMessages{{ loggo.WARNING, `cannot set up Juju GUI: cannot read GUI archive: .*`, }}) }
func (s *BootstrapSuite) TestBootstrapJenvWarning(c *gc.C) { env := resetJujuHome(c, "devenv") defaultSeriesVersion := version.Current defaultSeriesVersion.Series = config.PreferredSeries(env.Config()) // Force a dev version by having a non zero build number. // This is because we have not uploaded any tools and auto // upload is only enabled for dev versions. defaultSeriesVersion.Build = 1234 s.PatchValue(&version.Current, defaultSeriesVersion) store, err := configstore.Default() c.Assert(err, jc.ErrorIsNil) ctx := coretesting.Context(c) environs.PrepareFromName("devenv", envcmd.BootstrapContext(ctx), store) logger := "jenv.warning.test" var testWriter loggo.TestWriter loggo.RegisterWriter(logger, &testWriter, loggo.WARNING) defer loggo.RemoveWriter(logger) _, errc := cmdtesting.RunCommand(ctx, envcmd.Wrap(new(BootstrapCommand)), "-e", "devenv") c.Assert(<-errc, gc.IsNil) c.Assert(testWriter.Log(), jc.LogMatches, []string{"ignoring environments.yaml: using bootstrap config in .*"}) }
func (*diskStoreSuite) TestConcurrentAccessBreaksIfTimeExceeded(c *gc.C) { var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("test-log", &tw, loggo.DEBUG), gc.IsNil) dir := c.MkDir() store, err := configstore.NewDisk(dir) c.Assert(err, jc.ErrorIsNil) envDir := storePath(dir, "") _, err = configstore.AcquireEnvironmentLock(envDir, "blocking-op") c.Assert(err, jc.ErrorIsNil) _, err = store.ReadInfo("somemodel") c.Check(err, jc.Satisfies, errors.IsNotFound) // Using . between environments and env.lock so we don't have to care // about forward vs. backwards slash separator. messages := []jc.SimpleMessage{ {loggo.WARNING, `breaking configstore lock, lock dir: .*models.env\.lock`}, {loggo.WARNING, `lock holder message: pid: \d+, operation: blocking-op`}, } c.Check(tw.Log(), jc.LogMatches, messages) }
func (*suite) TestNoWarningForDeprecatedButUnusedEnv(c *gc.C) { // This tests that a config that has a deprecated field doesn't // generate a Warning if we don't actually ask for that environment. // However, we can only really trigger that when we have a deprecated // field. If support for the field is removed entirely, another // mechanism will need to be used content := ` environments: valid: type: dummy state-server: false deprecated: type: dummy state-server: false tools-metadata-url: aknowndeprecatedfield lxc-use-clone: true ` var tw loggo.TestWriter // we only capture Warning or above c.Assert(loggo.RegisterWriter("invalid-env-tester", &tw, loggo.WARNING), gc.IsNil) defer loggo.RemoveWriter("invalid-env-tester") envs, err := environs.ReadEnvironsBytes([]byte(content)) c.Check(err, jc.ErrorIsNil) names := envs.Names() sort.Strings(names) c.Check(names, gc.DeepEquals, []string{"deprecated", "valid"}) // There should be no warning in the log c.Check(tw.Log(), gc.HasLen, 0) // Now we actually grab the 'valid' entry _, err = envs.Config("valid") c.Check(err, jc.ErrorIsNil) // And still we have no warnings c.Check(tw.Log(), gc.HasLen, 0) // Only once we grab the deprecated one do we see any warnings _, err = envs.Config("deprecated") c.Check(err, jc.ErrorIsNil) c.Check(tw.Log(), gc.HasLen, 2) }
func checkLastMessage(c *gc.C, writer *loggo.TestWriter, expected string) { log := writer.Log() writer.Clear() obtained := log[len(log)-1].Message c.Check(obtained, gc.Equals, expected) }
func (s *ConstraintsSuite) TestDefaults(c *gc.C) { for _, test := range []struct { cons string expected kvm.StartParams infoLog []string }{{ expected: kvm.StartParams{ Memory: kvm.DefaultMemory, CpuCores: kvm.DefaultCpu, RootDisk: kvm.DefaultDisk, }, }, { cons: "mem=256M", expected: kvm.StartParams{ Memory: kvm.MinMemory, CpuCores: kvm.DefaultCpu, RootDisk: kvm.DefaultDisk, }, }, { cons: "mem=4G", expected: kvm.StartParams{ Memory: 4 * 1024, CpuCores: kvm.DefaultCpu, RootDisk: kvm.DefaultDisk, }, }, { cons: "cpu-cores=4", expected: kvm.StartParams{ Memory: kvm.DefaultMemory, CpuCores: 4, RootDisk: kvm.DefaultDisk, }, }, { cons: "cpu-cores=0", expected: kvm.StartParams{ Memory: kvm.DefaultMemory, CpuCores: kvm.MinCpu, RootDisk: kvm.DefaultDisk, }, }, { cons: "root-disk=512M", expected: kvm.StartParams{ Memory: kvm.DefaultMemory, CpuCores: kvm.DefaultCpu, RootDisk: kvm.MinDisk, }, }, { cons: "root-disk=4G", expected: kvm.StartParams{ Memory: kvm.DefaultMemory, CpuCores: kvm.DefaultCpu, RootDisk: 4, }, }, { cons: "arch=armhf", expected: kvm.StartParams{ Memory: kvm.DefaultMemory, CpuCores: kvm.DefaultCpu, RootDisk: kvm.DefaultDisk, }, infoLog: []string{ `arch constraint of "armhf" being ignored as not supported`, }, }, { cons: "container=lxc", expected: kvm.StartParams{ Memory: kvm.DefaultMemory, CpuCores: kvm.DefaultCpu, RootDisk: kvm.DefaultDisk, }, infoLog: []string{ `container constraint of "lxc" being ignored as not supported`, }, }, { cons: "cpu-power=100", expected: kvm.StartParams{ Memory: kvm.DefaultMemory, CpuCores: kvm.DefaultCpu, RootDisk: kvm.DefaultDisk, }, infoLog: []string{ `cpu-power constraint of 100 being ignored as not supported`, }, }, { cons: "tags=foo,bar", expected: kvm.StartParams{ Memory: kvm.DefaultMemory, CpuCores: kvm.DefaultCpu, RootDisk: kvm.DefaultDisk, }, infoLog: []string{ `tags constraint of "foo,bar" being ignored as not supported`, }, }, { cons: "mem=4G cpu-cores=4 root-disk=20G arch=armhf cpu-power=100 container=lxc tags=foo,bar", expected: kvm.StartParams{ Memory: 4 * 1024, CpuCores: 4, RootDisk: 20, }, infoLog: []string{ `arch constraint of "armhf" being ignored as not supported`, `container constraint of "lxc" being ignored as not supported`, `cpu-power constraint of 100 being ignored as not supported`, `tags constraint of "foo,bar" being ignored as not supported`, }, }} { var tw loggo.TestWriter c.Assert(loggo.RegisterWriter("constraint-tester", &tw, loggo.DEBUG), gc.IsNil) cons := constraints.MustParse(test.cons) params := kvm.ParseConstraintsToStartParams(cons) c.Check(params, gc.DeepEquals, test.expected) c.Check(tw.Log(), jc.LogMatches, test.infoLog) loggo.RemoveWriter("constraint-tester") } }