github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/auditconfigupdater/worker_test.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package auditconfigupdater_test 5 6 import ( 7 "reflect" 8 "sync" 9 10 "github.com/juju/collections/set" 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 "gopkg.in/juju/worker.v1" 15 "gopkg.in/juju/worker.v1/workertest" 16 17 apitesting "github.com/juju/juju/apiserver/testing" 18 "github.com/juju/juju/controller" 19 "github.com/juju/juju/core/auditlog" 20 "github.com/juju/juju/state" 21 "github.com/juju/juju/state/watcher/watchertest" 22 jujutesting "github.com/juju/juju/testing" 23 "github.com/juju/juju/worker/auditconfigupdater" 24 ) 25 26 type updaterSuite struct { 27 jujutesting.BaseSuite 28 } 29 30 var _ = gc.Suite(&updaterSuite{}) 31 32 var ding = struct{}{} 33 34 func (s *updaterSuite) TestWorker(c *gc.C) { 35 configChanged := make(chan struct{}, 1) 36 initial := auditlog.Config{ 37 Enabled: false, 38 } 39 source := configSource{ 40 watcher: watchertest.NewNotifyWatcher(configChanged), 41 cfg: makeControllerConfig(false, false), 42 } 43 44 fakeTarget := apitesting.FakeAuditLog{} 45 var calls []auditlog.Config 46 factory := func(cfg auditlog.Config) auditlog.AuditLog { 47 calls = append(calls, cfg) 48 return &fakeTarget 49 } 50 51 w, err := auditconfigupdater.New(&source, initial, factory) 52 c.Assert(err, jc.ErrorIsNil) 53 defer workertest.CleanKill(c, w) 54 55 source.setConfig(makeControllerConfig(true, false)) 56 configChanged <- ding 57 58 newConfig := waitForConfig(c, w, func(cfg auditlog.Config) bool { 59 return cfg.Enabled 60 }) 61 62 c.Assert(newConfig.Enabled, gc.Equals, true) 63 c.Assert(newConfig.CaptureAPIArgs, gc.Equals, false) 64 c.Assert(newConfig.ExcludeMethods, gc.DeepEquals, set.NewStrings()) 65 c.Assert(newConfig.Target, gc.Equals, auditlog.AuditLog(&fakeTarget)) 66 c.Assert(calls, gc.HasLen, 1) 67 } 68 69 func waitForConfig(c *gc.C, w worker.Worker, predicate func(auditlog.Config) bool) auditlog.Config { 70 for a := jujutesting.LongAttempt.Start(); a.Next(); { 71 config := getWorkerConfig(c, w) 72 if predicate(config) { 73 return config 74 } 75 } 76 c.Fatalf("timed out waiting for matching config") 77 return auditlog.Config{} 78 } 79 80 func (s *updaterSuite) TestKeepsLogFileWhenAuditingDisabled(c *gc.C) { 81 configChanged := make(chan struct{}, 1) 82 initial := auditlog.Config{ 83 Enabled: true, 84 Target: &apitesting.FakeAuditLog{}, 85 } 86 source := configSource{ 87 watcher: watchertest.NewNotifyWatcher(configChanged), 88 cfg: makeControllerConfig(true, false), 89 } 90 91 // Passing a nil factory means we can be sure it didn't try to 92 // create a new logfile. 93 w, err := auditconfigupdater.New(&source, initial, nil) 94 c.Assert(err, jc.ErrorIsNil) 95 defer workertest.CleanKill(c, w) 96 97 source.setConfig(makeControllerConfig(false, false)) 98 configChanged <- ding 99 100 newConfig := waitForConfig(c, w, func(cfg auditlog.Config) bool { 101 return !cfg.Enabled 102 }) 103 104 c.Assert(newConfig.Enabled, gc.Equals, false) 105 c.Assert(newConfig.Target, gc.Equals, initial.Target) 106 } 107 108 func (s *updaterSuite) TestKeepsLogFileWhenEnabled(c *gc.C) { 109 configChanged := make(chan struct{}, 1) 110 initial := auditlog.Config{ 111 Enabled: false, 112 Target: &apitesting.FakeAuditLog{}, 113 } 114 source := configSource{ 115 watcher: watchertest.NewNotifyWatcher(configChanged), 116 cfg: makeControllerConfig(false, false), 117 } 118 119 // Passing a nil factory means we can be sure it didn't try to 120 // create a new logfile. 121 w, err := auditconfigupdater.New(&source, initial, nil) 122 c.Assert(err, jc.ErrorIsNil) 123 defer workertest.CleanKill(c, w) 124 125 source.setConfig(makeControllerConfig(true, false)) 126 configChanged <- ding 127 128 newConfig := waitForConfig(c, w, func(cfg auditlog.Config) bool { 129 return cfg.Enabled 130 }) 131 132 c.Assert(newConfig.Enabled, gc.Equals, true) 133 c.Assert(newConfig.Target, gc.Equals, initial.Target) 134 } 135 136 func (s *updaterSuite) TestChangingExcludeMethod(c *gc.C) { 137 configChanged := make(chan struct{}, 1) 138 initial := auditlog.Config{ 139 Enabled: true, 140 ExcludeMethods: set.NewStrings("Pink.Floyd"), 141 Target: &apitesting.FakeAuditLog{}, 142 } 143 source := configSource{ 144 watcher: watchertest.NewNotifyWatcher(configChanged), 145 cfg: makeControllerConfig(true, false, "Pink.Floyd"), 146 } 147 148 w, err := auditconfigupdater.New(&source, initial, nil) 149 c.Assert(err, jc.ErrorIsNil) 150 defer workertest.CleanKill(c, w) 151 152 source.setConfig(makeControllerConfig(true, false, "Pink.Floyd", "Led.Zeppelin")) 153 configChanged <- ding 154 155 waitForConfig(c, w, func(cfg auditlog.Config) bool { 156 return reflect.DeepEqual(cfg.ExcludeMethods, set.NewStrings("Pink.Floyd", "Led.Zeppelin")) 157 }) 158 159 source.setConfig(makeControllerConfig(true, false, "Led.Zeppelin")) 160 configChanged <- ding 161 162 waitForConfig(c, w, func(cfg auditlog.Config) bool { 163 return reflect.DeepEqual(cfg.ExcludeMethods, set.NewStrings("Led.Zeppelin")) 164 }) 165 } 166 167 func (s *updaterSuite) TestChangingCaptureArgs(c *gc.C) { 168 configChanged := make(chan struct{}, 1) 169 initial := auditlog.Config{ 170 Enabled: true, 171 CaptureAPIArgs: false, 172 Target: &apitesting.FakeAuditLog{}, 173 } 174 source := configSource{ 175 watcher: watchertest.NewNotifyWatcher(configChanged), 176 cfg: makeControllerConfig(true, false, "Pink.Floyd"), 177 } 178 179 w, err := auditconfigupdater.New(&source, initial, nil) 180 c.Assert(err, jc.ErrorIsNil) 181 defer workertest.CleanKill(c, w) 182 183 source.setConfig(makeControllerConfig(true, true)) 184 configChanged <- ding 185 186 waitForConfig(c, w, func(cfg auditlog.Config) bool { 187 return cfg.CaptureAPIArgs 188 }) 189 } 190 191 func makeControllerConfig(auditEnabled bool, captureArgs bool, methods ...interface{}) controller.Config { 192 result := map[string]interface{}{ 193 "other-setting": "something", 194 "auditing-enabled": auditEnabled, 195 "audit-log-capture-args": captureArgs, 196 "audit-log-exclude-methods": methods, 197 } 198 return result 199 } 200 201 func getWorkerConfig(c *gc.C, w worker.Worker) auditlog.Config { 202 getter, ok := w.(interface { 203 CurrentConfig() auditlog.Config 204 }) 205 if !ok { 206 c.Fatalf("worker %T doesn't expose CurrentConfig()", w) 207 } 208 return getter.CurrentConfig() 209 } 210 211 type configSource struct { 212 mu sync.Mutex 213 stub testing.Stub 214 watcher *watchertest.NotifyWatcher 215 cfg controller.Config 216 } 217 218 func (s *configSource) WatchControllerConfig() state.NotifyWatcher { 219 s.stub.AddCall("WatchControllerConfig") 220 return s.watcher 221 } 222 223 func (s *configSource) ControllerConfig() (controller.Config, error) { 224 s.mu.Lock() 225 defer s.mu.Unlock() 226 s.stub.AddCall("ControllerConfig") 227 if err := s.stub.NextErr(); err != nil { 228 return nil, err 229 } 230 return s.cfg, nil 231 } 232 233 func (s *configSource) setConfig(cfg controller.Config) { 234 s.mu.Lock() 235 defer s.mu.Unlock() 236 s.cfg = cfg 237 }