github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/observer/recorder_test.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package observer_test 5 6 import ( 7 "time" 8 9 "github.com/juju/clock/testclock" 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/apiserver/observer" 15 "github.com/juju/juju/apiserver/observer/fakeobserver" 16 "github.com/juju/juju/apiserver/params" 17 apitesting "github.com/juju/juju/apiserver/testing" 18 "github.com/juju/juju/core/auditlog" 19 "github.com/juju/juju/rpc" 20 ) 21 22 type recorderSuite struct { 23 testing.IsolationSuite 24 } 25 26 var _ = gc.Suite(&recorderSuite{}) 27 28 func (s *recorderSuite) TestServerRequest(c *gc.C) { 29 fake := &fakeobserver.Instance{} 30 log := &apitesting.FakeAuditLog{} 31 clock := testclock.NewClock(time.Now()) 32 auditRecorder, err := auditlog.NewRecorder(log, clock, auditlog.ConversationArgs{ 33 ConnectionID: 4567, 34 }) 35 c.Assert(err, jc.ErrorIsNil) 36 factory := observer.NewRecorderFactory(fake, auditRecorder, observer.CaptureArgs) 37 recorder := factory() 38 hdr := &rpc.Header{ 39 RequestId: 123, 40 Request: rpc.Request{"Type", 5, "", "Action"}, 41 } 42 err = recorder.HandleRequest(hdr, "the args") 43 c.Assert(err, jc.ErrorIsNil) 44 45 fake.CheckCallNames(c, "RPCObserver") 46 fakeOb := fake.Calls()[0].Args[0].(*fakeobserver.RPCInstance) 47 fakeOb.CheckCallNames(c, "ServerRequest") 48 fakeOb.CheckCall(c, 0, "ServerRequest", hdr, "the args") 49 50 log.CheckCallNames(c, "AddConversation", "AddRequest") 51 52 request := log.Calls()[1].Args[0].(auditlog.Request) 53 c.Assert(request.ConversationID, gc.HasLen, 16) 54 request.ConversationID = "abcdef0123456789" 55 c.Assert(request, gc.Equals, auditlog.Request{ 56 ConversationID: "abcdef0123456789", 57 ConnectionID: "11D7", 58 RequestID: 123, 59 When: clock.Now().Format(time.RFC3339), 60 Facade: "Type", 61 Method: "Action", 62 Version: 5, 63 Args: `"the args"`, 64 }) 65 } 66 67 func (s *recorderSuite) TestServerRequestNoArgs(c *gc.C) { 68 fake := &fakeobserver.Instance{} 69 log := &apitesting.FakeAuditLog{} 70 clock := testclock.NewClock(time.Now()) 71 auditRecorder, err := auditlog.NewRecorder(log, clock, auditlog.ConversationArgs{ 72 ConnectionID: 4567, 73 }) 74 c.Assert(err, jc.ErrorIsNil) 75 factory := observer.NewRecorderFactory(fake, auditRecorder, observer.NoCaptureArgs) 76 recorder := factory() 77 hdr := &rpc.Header{ 78 RequestId: 123, 79 Request: rpc.Request{"Type", 5, "", "Action"}, 80 } 81 err = recorder.HandleRequest(hdr, "the args") 82 c.Assert(err, jc.ErrorIsNil) 83 84 log.CheckCallNames(c, "AddConversation", "AddRequest") 85 86 request := log.Calls()[1].Args[0].(auditlog.Request) 87 c.Assert(request.ConversationID, gc.HasLen, 16) 88 request.ConversationID = "abcdef0123456789" 89 c.Assert(request, gc.Equals, auditlog.Request{ 90 ConversationID: "abcdef0123456789", 91 ConnectionID: "11D7", 92 RequestID: 123, 93 When: clock.Now().Format(time.RFC3339), 94 Facade: "Type", 95 Method: "Action", 96 Version: 5, 97 }) 98 } 99 100 func (s *recorderSuite) TestServerReply(c *gc.C) { 101 fake := &fakeobserver.Instance{} 102 log := &apitesting.FakeAuditLog{} 103 clock := testclock.NewClock(time.Now()) 104 auditRecorder, err := auditlog.NewRecorder(log, clock, auditlog.ConversationArgs{ 105 ConnectionID: 4567, 106 }) 107 c.Assert(err, jc.ErrorIsNil) 108 factory := observer.NewRecorderFactory(fake, auditRecorder, observer.CaptureArgs) 109 recorder := factory() 110 111 req := rpc.Request{"Type", 5, "", "Action"} 112 hdr := &rpc.Header{RequestId: 123} 113 err = recorder.HandleReply(req, hdr, "the response") 114 c.Assert(err, jc.ErrorIsNil) 115 116 fake.CheckCallNames(c, "RPCObserver") 117 fakeOb := fake.Calls()[0].Args[0].(*fakeobserver.RPCInstance) 118 fakeOb.CheckCallNames(c, "ServerReply") 119 fakeOb.CheckCall(c, 0, "ServerReply", req, hdr, "the response") 120 121 log.CheckCallNames(c, "AddConversation", "AddResponse") 122 123 respErrors := log.Calls()[1].Args[0].(auditlog.ResponseErrors) 124 c.Assert(respErrors.ConversationID, gc.HasLen, 16) 125 respErrors.ConversationID = "abcdef0123456789" 126 c.Assert(respErrors, gc.DeepEquals, auditlog.ResponseErrors{ 127 ConversationID: "abcdef0123456789", 128 ConnectionID: "11D7", 129 RequestID: 123, 130 When: clock.Now().Format(time.RFC3339), 131 Errors: nil, 132 }) 133 } 134 135 func (s *recorderSuite) TestReplyResultNotAStruct(c *gc.C) { 136 s.checkServerReplyErrors(c, 12345, nil) 137 } 138 139 func (s *recorderSuite) TestReplyResultNoErrorAttrs(c *gc.C) { 140 s.checkServerReplyErrors(c, 141 params.ApplicationCharmRelationsResults{ 142 CharmRelations: []string{"abc", "123"}, 143 }, 144 nil, 145 ) 146 } 147 148 func (s *recorderSuite) TestReplyResultErrorSlice(c *gc.C) { 149 s.checkServerReplyErrors(c, 150 params.ErrorResults{ 151 Results: []params.ErrorResult{{ 152 Error: ¶ms.Error{ 153 Message: "antiphon", 154 Code: "midlake", 155 }, 156 }, { 157 Error: nil, 158 }}, 159 }, 160 []*auditlog.Error{{ 161 Message: "antiphon", 162 Code: "midlake", 163 }, nil}, 164 ) 165 } 166 167 func (s *recorderSuite) TestReplyResultError(c *gc.C) { 168 s.checkServerReplyErrors(c, 169 params.ErrorResult{ 170 Error: ¶ms.Error{ 171 Message: "antiphon", 172 Code: "midlake", 173 }, 174 }, 175 []*auditlog.Error{{ 176 Message: "antiphon", 177 Code: "midlake", 178 }}, 179 ) 180 } 181 182 func (s *recorderSuite) TestReplyResultSlice(c *gc.C) { 183 s.checkServerReplyErrors(c, 184 params.AddMachinesResults{ 185 Machines: []params.AddMachinesResult{{ 186 Machine: "some-machine", 187 }, { 188 Error: ¶ms.Error{ 189 Message: "something bad", 190 Code: "fall-down-go-boom", 191 Info: ¶ms.ErrorInfo{MacaroonPath: "somewhere"}, 192 }, 193 }}, 194 }, 195 []*auditlog.Error{nil, { 196 Message: "something bad", 197 Code: "fall-down-go-boom", 198 }}, 199 ) 200 } 201 202 func (s *recorderSuite) checkServerReplyErrors(c *gc.C, result interface{}, expected []*auditlog.Error) { 203 fake := &fakeobserver.Instance{} 204 log := &apitesting.FakeAuditLog{} 205 clock := testclock.NewClock(time.Now()) 206 auditRecorder, err := auditlog.NewRecorder(log, clock, auditlog.ConversationArgs{ 207 ConnectionID: 4567, 208 }) 209 c.Assert(err, jc.ErrorIsNil) 210 factory := observer.NewRecorderFactory(fake, auditRecorder, observer.CaptureArgs) 211 recorder := factory() 212 213 req := rpc.Request{"Type", 5, "", "Action"} 214 hdr := &rpc.Header{RequestId: 123} 215 err = recorder.HandleReply(req, hdr, result) 216 c.Assert(err, jc.ErrorIsNil) 217 218 log.CheckCallNames(c, "AddConversation", "AddResponse") 219 220 respErrors := log.Calls()[1].Args[0].(auditlog.ResponseErrors) 221 c.Assert(respErrors.ConversationID, gc.HasLen, 16) 222 respErrors.ConversationID = "" 223 c.Assert(respErrors, gc.DeepEquals, auditlog.ResponseErrors{ 224 ConnectionID: "11D7", 225 RequestID: 123, 226 When: clock.Now().Format(time.RFC3339), 227 Errors: expected, 228 }) 229 } 230 231 func (s *recorderSuite) TestNoAuditRequest(c *gc.C) { 232 fake := &fakeobserver.Instance{} 233 factory := observer.NewRecorderFactory(fake, nil, observer.NoCaptureArgs) 234 recorder := factory() 235 hdr := &rpc.Header{ 236 RequestId: 123, 237 Request: rpc.Request{"Type", 0, "", "Action"}, 238 } 239 err := recorder.HandleRequest(hdr, "the body") 240 c.Assert(err, jc.ErrorIsNil) 241 } 242 243 func (s *recorderSuite) TestNoAuditReply(c *gc.C) { 244 fake := &fakeobserver.Instance{} 245 factory := observer.NewRecorderFactory(fake, nil, observer.NoCaptureArgs) 246 recorder := factory() 247 req := rpc.Request{"Type", 0, "", "Action"} 248 hdr := &rpc.Header{RequestId: 123} 249 err := recorder.HandleReply(req, hdr, "the body") 250 c.Assert(err, jc.ErrorIsNil) 251 }