github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/featuretests/dblog_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package featuretests
     5  
     6  import (
     7  	"bufio"
     8  	"time"
     9  
    10  	"github.com/juju/loggo"
    11  	"github.com/juju/names"
    12  	jujutesting "github.com/juju/testing"
    13  	jc "github.com/juju/testing/checkers"
    14  	gc "gopkg.in/check.v1"
    15  	"gopkg.in/mgo.v2/bson"
    16  
    17  	"github.com/juju/juju/agent"
    18  	"github.com/juju/juju/api"
    19  	agentcmd "github.com/juju/juju/cmd/jujud/agent"
    20  	agenttesting "github.com/juju/juju/cmd/jujud/agent/testing"
    21  	"github.com/juju/juju/state"
    22  	coretesting "github.com/juju/juju/testing"
    23  	"github.com/juju/juju/testing/factory"
    24  	"github.com/juju/juju/worker/logsender"
    25  	"github.com/juju/juju/worker/peergrouper"
    26  )
    27  
    28  // dblogSuite tests that logs flow correctly from the machine and unit
    29  // agents over the API into MongoDB. These are very much integration
    30  // tests with more detailed testing of the individual components
    31  // being done in unit tests.
    32  type dblogSuite struct {
    33  	agenttesting.AgentSuite
    34  }
    35  
    36  func (s *dblogSuite) SetUpTest(c *gc.C) {
    37  	s.AgentSuite.SetUpTest(c)
    38  }
    39  
    40  func (s *dblogSuite) TestMachineAgentLogsGoToDB(c *gc.C) {
    41  	foundLogs := s.runMachineAgentTest(c)
    42  	c.Assert(foundLogs, jc.IsTrue)
    43  }
    44  
    45  func (s *dblogSuite) TestUnitAgentLogsGoToDB(c *gc.C) {
    46  	foundLogs := s.runUnitAgentTest(c)
    47  	c.Assert(foundLogs, jc.IsTrue)
    48  }
    49  
    50  func (s *dblogSuite) runMachineAgentTest(c *gc.C) bool {
    51  	// Create a machine and an agent for it.
    52  	m, password := s.Factory.MakeMachineReturningPassword(c, &factory.MachineParams{
    53  		Nonce: agent.BootstrapNonce,
    54  	})
    55  
    56  	s.PrimeAgent(c, m.Tag(), password)
    57  	agentConf := agentcmd.NewAgentConf(s.DataDir())
    58  	agentConf.ReadConfig(m.Tag().String())
    59  	logsCh, err := logsender.InstallBufferedLogWriter(1000)
    60  	c.Assert(err, jc.ErrorIsNil)
    61  	machineAgentFactory := agentcmd.MachineAgentFactoryFn(agentConf, logsCh, c.MkDir())
    62  	a := machineAgentFactory(m.Id())
    63  
    64  	// Ensure there's no logs to begin with.
    65  	c.Assert(s.getLogCount(c, m.Tag()), gc.Equals, 0)
    66  
    67  	// Start the agent.
    68  	go func() { c.Check(a.Run(nil), jc.ErrorIsNil) }()
    69  	defer a.Stop()
    70  
    71  	return s.waitForLogs(c, m.Tag())
    72  }
    73  
    74  func (s *dblogSuite) runUnitAgentTest(c *gc.C) bool {
    75  	// Create a unit and an agent for it.
    76  	u, password := s.Factory.MakeUnitReturningPassword(c, nil)
    77  	s.PrimeAgent(c, u.Tag(), password)
    78  	logsCh, err := logsender.InstallBufferedLogWriter(1000)
    79  	c.Assert(err, jc.ErrorIsNil)
    80  	a := agentcmd.NewUnitAgent(nil, logsCh)
    81  	s.InitAgent(c, a, "--unit-name", u.Name(), "--log-to-stderr=true")
    82  
    83  	// Ensure there's no logs to begin with.
    84  	c.Assert(s.getLogCount(c, u.Tag()), gc.Equals, 0)
    85  
    86  	// Start the agent.
    87  	go func() { c.Assert(a.Run(nil), jc.ErrorIsNil) }()
    88  	defer a.Stop()
    89  
    90  	return s.waitForLogs(c, u.Tag())
    91  }
    92  
    93  func (s *dblogSuite) getLogCount(c *gc.C, entity names.Tag) int {
    94  	// TODO(mjs) - replace this with State's functionality for reading
    95  	// logs from the DB, once it gets this. This will happen before
    96  	// the DB logging feature branch is merged.
    97  	logs := s.Session.DB("logs").C("logs")
    98  	count, err := logs.Find(bson.M{"n": entity.String()}).Count()
    99  	c.Assert(err, jc.ErrorIsNil)
   100  	return count
   101  }
   102  
   103  func (s *dblogSuite) waitForLogs(c *gc.C, entityTag names.Tag) bool {
   104  	for a := coretesting.LongAttempt.Start(); a.Next(); {
   105  		if s.getLogCount(c, entityTag) > 0 {
   106  			return true
   107  		}
   108  	}
   109  	return false
   110  }
   111  
   112  // debugLogDbSuite tests that the debuglog API works when logs are
   113  // being read from the database.
   114  type debugLogDbSuite struct {
   115  	agenttesting.AgentSuite
   116  }
   117  
   118  var _ = gc.Suite(&debugLogDbSuite{})
   119  
   120  func (s *debugLogDbSuite) SetUpSuite(c *gc.C) {
   121  	// Restart mongod with a the replicaset enabled.
   122  	mongod := jujutesting.MgoServer
   123  	mongod.Params = []string{"--replSet", "juju"}
   124  	mongod.Restart()
   125  
   126  	// Initiate the replicaset.
   127  	info := mongod.DialInfo()
   128  	args := peergrouper.InitiateMongoParams{
   129  		DialInfo:       info,
   130  		MemberHostPort: mongod.Addr(),
   131  	}
   132  	err := peergrouper.InitiateMongoServer(args)
   133  	c.Assert(err, jc.ErrorIsNil)
   134  
   135  	s.AgentSuite.SetUpSuite(c)
   136  }
   137  
   138  func (s *debugLogDbSuite) TearDownSuite(c *gc.C) {
   139  	// Restart mongod without the replicaset enabled so as not to
   140  	// affect other test that reply on this mongod instance in this
   141  	// package.
   142  	mongod := jujutesting.MgoServer
   143  	mongod.Params = []string{}
   144  	mongod.Restart()
   145  
   146  	s.AgentSuite.TearDownSuite(c)
   147  }
   148  
   149  func (s *debugLogDbSuite) TestLogsAPI(c *gc.C) {
   150  	dbLogger := state.NewDbLogger(s.State, names.NewMachineTag("99"))
   151  	defer dbLogger.Close()
   152  
   153  	t := time.Date(2015, 6, 23, 13, 8, 49, 0, time.UTC)
   154  	dbLogger.Log(t, "juju.foo", "code.go:42", loggo.INFO, "all is well")
   155  	dbLogger.Log(t.Add(time.Second), "juju.bar", "go.go:99", loggo.ERROR, "no it isn't")
   156  
   157  	lines := make(chan string)
   158  	go func(numLines int) {
   159  		client := s.APIState.Client()
   160  		reader, err := client.WatchDebugLog(api.DebugLogParams{})
   161  		c.Assert(err, jc.ErrorIsNil)
   162  		defer reader.Close()
   163  
   164  		bufReader := bufio.NewReader(reader)
   165  		for n := 0; n < numLines; n++ {
   166  			line, err := bufReader.ReadString('\n')
   167  			c.Assert(err, jc.ErrorIsNil)
   168  			lines <- line
   169  		}
   170  	}(3)
   171  
   172  	assertLine := func(expected string) {
   173  		select {
   174  		case actual := <-lines:
   175  			c.Assert(actual, gc.Equals, expected)
   176  		case <-time.After(coretesting.LongWait):
   177  			c.Fatal("timed out waiting for log line")
   178  		}
   179  	}
   180  
   181  	// Read the 2 lines that are in the logs collection.
   182  	assertLine("machine-99: 2015-06-23 13:08:49 INFO juju.foo code.go:42 all is well\n")
   183  	assertLine("machine-99: 2015-06-23 13:08:50 ERROR juju.bar go.go:99 no it isn't\n")
   184  
   185  	// Now write and observe another log. This should be read from the oplog.
   186  	dbLogger.Log(t.Add(2*time.Second), "ju.jitsu", "no.go:3", loggo.WARNING, "beep beep")
   187  	assertLine("machine-99: 2015-06-23 13:08:51 WARNING ju.jitsu no.go:3 beep beep\n")
   188  }