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 }