github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/worker/rsyslog/rsyslog_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  // +build !windows
     4  
     5  package rsyslog_test
     6  
     7  import (
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/juju/names"
    15  	jc "github.com/juju/testing/checkers"
    16  	gc "gopkg.in/check.v1"
    17  
    18  	"github.com/juju/juju/api"
    19  	"github.com/juju/juju/cert"
    20  	"github.com/juju/juju/network"
    21  	"github.com/juju/juju/state"
    22  	coretesting "github.com/juju/juju/testing"
    23  	"github.com/juju/juju/utils/syslog"
    24  	"github.com/juju/juju/worker/rsyslog"
    25  )
    26  
    27  func waitForRestart(c *gc.C, restarted chan struct{}) {
    28  	timeout := time.After(coretesting.LongWait)
    29  	for {
    30  		select {
    31  		case <-timeout:
    32  			c.Fatalf("timed out waiting for rsyslog to be restarted")
    33  		case <-restarted:
    34  			return
    35  		}
    36  	}
    37  }
    38  
    39  func assertPathExists(c *gc.C, path string) {
    40  	_, err := os.Stat(path)
    41  	c.Assert(err, jc.ErrorIsNil)
    42  }
    43  
    44  func (s *RsyslogSuite) TestStartStop(c *gc.C) {
    45  	st, m := s.OpenAPIAsNewMachine(c, state.JobHostUnits)
    46  	worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeForwarding, m.Tag(), "", []string{"0.1.2.3"})
    47  	c.Assert(err, jc.ErrorIsNil)
    48  	worker.Kill()
    49  	c.Assert(worker.Wait(), gc.IsNil)
    50  }
    51  
    52  func (s *RsyslogSuite) TestTearDown(c *gc.C) {
    53  	st, m := s.st, s.machine
    54  	worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, m.Tag(), "", []string{"0.1.2.3"})
    55  	c.Assert(err, jc.ErrorIsNil)
    56  	confFile := filepath.Join(*rsyslog.RsyslogConfDir, "25-juju.conf")
    57  	// On worker teardown, the rsyslog config file should be removed.
    58  	defer func() {
    59  		_, err := os.Stat(confFile)
    60  		c.Assert(err, jc.Satisfies, os.IsNotExist)
    61  	}()
    62  	defer func() { c.Assert(worker.Wait(), gc.IsNil) }()
    63  	defer worker.Kill()
    64  	waitForFile(c, confFile)
    65  }
    66  
    67  func (s *RsyslogSuite) TestRsyslogCert(c *gc.C) {
    68  	st, m := s.st, s.machine
    69  	err := s.machine.SetAddresses(network.NewAddress("example.com", network.ScopeUnknown))
    70  	c.Assert(err, jc.ErrorIsNil)
    71  
    72  	worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, m.Tag(), "", []string{"0.1.2.3"})
    73  	c.Assert(err, jc.ErrorIsNil)
    74  	defer func() { c.Assert(worker.Wait(), gc.IsNil) }()
    75  	defer worker.Kill()
    76  	waitForFile(c, filepath.Join(*rsyslog.LogDir, "rsyslog-cert.pem"))
    77  
    78  	rsyslogCertPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "rsyslog-cert.pem"))
    79  	c.Assert(err, jc.ErrorIsNil)
    80  
    81  	cert, err := cert.ParseCert(string(rsyslogCertPEM))
    82  	c.Assert(err, jc.ErrorIsNil)
    83  
    84  	c.Assert(cert.DNSNames, gc.DeepEquals, []string{"example.com", "*"})
    85  
    86  	subject := cert.Subject
    87  	c.Assert(subject.CommonName, gc.Equals, "*")
    88  	c.Assert(subject.Organization, gc.DeepEquals, []string{"juju"})
    89  
    90  	issuer := cert.Issuer
    91  	c.Assert(issuer.CommonName, gc.Equals, "juju-generated CA for environment \"rsyslog\"")
    92  	c.Assert(issuer.Organization, gc.DeepEquals, []string{"juju"})
    93  }
    94  
    95  func (s *RsyslogSuite) TestModeAccumulate(c *gc.C) {
    96  	st, m := s.st, s.machine
    97  	worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, m.Tag(), "", nil)
    98  	c.Assert(err, jc.ErrorIsNil)
    99  	defer func() { c.Assert(worker.Wait(), gc.IsNil) }()
   100  	defer worker.Kill()
   101  	waitForFile(c, filepath.Join(*rsyslog.LogDir, "ca-cert.pem"))
   102  
   103  	// We should have ca-cert.pem, rsyslog-cert.pem, and rsyslog-key.pem.
   104  	caCertPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "ca-cert.pem"))
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	rsyslogCertPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "rsyslog-cert.pem"))
   107  	c.Assert(err, jc.ErrorIsNil)
   108  	rsyslogKeyPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "rsyslog-key.pem"))
   109  	c.Assert(err, jc.ErrorIsNil)
   110  
   111  	_, _, err = cert.ParseCertAndKey(string(rsyslogCertPEM), string(rsyslogKeyPEM))
   112  	c.Assert(err, jc.ErrorIsNil)
   113  	err = cert.Verify(string(rsyslogCertPEM), string(caCertPEM), time.Now().UTC())
   114  	c.Assert(err, jc.ErrorIsNil)
   115  
   116  	// Verify rsyslog configuration.
   117  	waitForFile(c, filepath.Join(*rsyslog.RsyslogConfDir, "25-juju.conf"))
   118  	rsyslogConf, err := ioutil.ReadFile(filepath.Join(*rsyslog.RsyslogConfDir, "25-juju.conf"))
   119  	c.Assert(err, jc.ErrorIsNil)
   120  
   121  	syslogPort := s.Environ.Config().SyslogPort()
   122  	syslogConfig := syslog.NewAccumulateConfig(m.Tag().String(), *rsyslog.LogDir, syslogPort, "", []string{})
   123  	syslogConfig.ConfigDir = *rsyslog.RsyslogConfDir
   124  	rendered, err := syslogConfig.Render()
   125  	c.Assert(err, jc.ErrorIsNil)
   126  
   127  	c.Assert(string(rsyslogConf), gc.DeepEquals, string(rendered))
   128  
   129  	// Verify logrotate files
   130  	assertPathExists(c, filepath.Join(*rsyslog.LogDir, "logrotate.conf"))
   131  	assertPathExists(c, filepath.Join(*rsyslog.LogDir, "logrotate.run"))
   132  
   133  }
   134  
   135  func (s *RsyslogSuite) TestAccumulateHA(c *gc.C) {
   136  	m := s.machine
   137  	syslogConfig := syslog.NewAccumulateConfig(m.Tag().String(), *rsyslog.LogDir, 6541, "", []string{"192.168.1", "127.0.0.1"})
   138  	rendered, err := syslogConfig.Render()
   139  	c.Assert(err, jc.ErrorIsNil)
   140  
   141  	stateServer1Config := ":syslogtag, startswith, \"juju-\" @@192.168.1:6541;LongTagForwardFormat"
   142  	stateServer2Config := ":syslogtag, startswith, \"juju-\" @@127.0.0.1:6541;LongTagForwardFormat"
   143  
   144  	c.Assert(strings.Contains(string(rendered), stateServer1Config), jc.IsTrue)
   145  	c.Assert(strings.Contains(string(rendered), stateServer2Config), jc.IsTrue)
   146  }
   147  
   148  func (s *RsyslogSuite) TestNamespace(c *gc.C) {
   149  	st := s.st
   150  	// set the rsyslog cert
   151  	err := s.APIState.Client().EnvironmentSet(map[string]interface{}{"rsyslog-ca-cert": coretesting.CACert})
   152  	c.Assert(err, jc.ErrorIsNil)
   153  
   154  	// namespace only takes effect in filenames
   155  	// for machine-0; all others assume isolation.
   156  	s.testNamespace(c, st, names.NewMachineTag("0"), "", "25-juju.conf", *rsyslog.LogDir)
   157  	s.testNamespace(c, st, names.NewMachineTag("0"), "mynamespace", "25-juju-mynamespace.conf", *rsyslog.LogDir+"-mynamespace")
   158  	s.testNamespace(c, st, names.NewMachineTag("1"), "", "25-juju.conf", *rsyslog.LogDir)
   159  	s.testNamespace(c, st, names.NewMachineTag("1"), "mynamespace", "25-juju.conf", *rsyslog.LogDir)
   160  	s.testNamespace(c, st, names.NewUnitTag("myservice/0"), "", "26-juju-unit-myservice-0.conf", *rsyslog.LogDir)
   161  	s.testNamespace(c, st, names.NewUnitTag("myservice/0"), "mynamespace", "26-juju-unit-myservice-0.conf", *rsyslog.LogDir)
   162  }
   163  
   164  // testNamespace starts a worker and ensures that
   165  // the rsyslog config file has the expected filename,
   166  // and the appropriate log dir is used.
   167  func (s *RsyslogSuite) testNamespace(c *gc.C, st *api.State, tag names.Tag, namespace, expectedFilename, expectedLogDir string) {
   168  	restarted := make(chan struct{}, 2) // once for create, once for teardown
   169  	s.PatchValue(rsyslog.RestartRsyslog, func() error {
   170  		restarted <- struct{}{}
   171  		return nil
   172  	})
   173  
   174  	err := os.MkdirAll(expectedLogDir, 0755)
   175  	c.Assert(err, jc.ErrorIsNil)
   176  	worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, tag, namespace, []string{"0.1.2.3"})
   177  	c.Assert(err, jc.ErrorIsNil)
   178  	defer func() { c.Assert(worker.Wait(), gc.IsNil) }()
   179  	defer worker.Kill()
   180  
   181  	// change the API HostPorts to trigger an rsyslog restart
   182  	newHostPorts := network.NewHostPorts(6541, "127.0.0.1")
   183  	err = s.State.SetAPIHostPorts([][]network.HostPort{newHostPorts})
   184  	c.Assert(err, jc.ErrorIsNil)
   185  
   186  	// Wait for rsyslog to be restarted, so we can check to see
   187  	// what the name of the config file is.
   188  	waitForRestart(c, restarted)
   189  
   190  	// Ensure that ca-cert.pem gets written to the expected log dir.
   191  	waitForFile(c, filepath.Join(expectedLogDir, "ca-cert.pem"))
   192  
   193  	dir, err := os.Open(*rsyslog.RsyslogConfDir)
   194  	c.Assert(err, jc.ErrorIsNil)
   195  	names, err := dir.Readdirnames(-1)
   196  	dir.Close()
   197  	c.Assert(err, jc.ErrorIsNil)
   198  	c.Assert(names, gc.HasLen, 1)
   199  	c.Assert(names[0], gc.Equals, expectedFilename)
   200  }