github.com/Iqoqo/consul@v1.4.5/agent/event_endpoint_test.go (about) 1 package agent 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "net/http" 8 "net/http/httptest" 9 "testing" 10 "time" 11 12 "github.com/hashicorp/consul/testrpc" 13 14 "github.com/hashicorp/consul/acl" 15 "github.com/hashicorp/consul/agent/structs" 16 "github.com/hashicorp/consul/testutil/retry" 17 ) 18 19 func TestEventFire(t *testing.T) { 20 t.Parallel() 21 a := NewTestAgent(t, t.Name(), "") 22 defer a.Shutdown() 23 testrpc.WaitForTestAgent(t, a.RPC, "dc1") 24 25 body := bytes.NewBuffer([]byte("test")) 26 url := "/v1/event/fire/test?node=Node&service=foo&tag=bar" 27 req, _ := http.NewRequest("PUT", url, body) 28 resp := httptest.NewRecorder() 29 obj, err := a.srv.EventFire(resp, req) 30 if err != nil { 31 t.Fatalf("err: %v", err) 32 } 33 34 event, ok := obj.(*UserEvent) 35 if !ok { 36 t.Fatalf("bad: %#v", obj) 37 } 38 39 if event.ID == "" { 40 t.Fatalf("bad: %#v", event) 41 } 42 if event.Name != "test" { 43 t.Fatalf("bad: %#v", event) 44 } 45 if string(event.Payload) != "test" { 46 t.Fatalf("bad: %#v", event) 47 } 48 if event.NodeFilter != "Node" { 49 t.Fatalf("bad: %#v", event) 50 } 51 if event.ServiceFilter != "foo" { 52 t.Fatalf("bad: %#v", event) 53 } 54 if event.TagFilter != "bar" { 55 t.Fatalf("bad: %#v", event) 56 } 57 } 58 59 func TestEventFire_token(t *testing.T) { 60 t.Parallel() 61 a := NewTestAgent(t, t.Name(), TestACLConfig()+` 62 acl_default_policy = "deny" 63 `) 64 defer a.Shutdown() 65 testrpc.WaitForLeader(t, a.RPC, "dc1") 66 67 // Create an ACL token 68 args := structs.ACLRequest{ 69 Datacenter: "dc1", 70 Op: structs.ACLSet, 71 ACL: structs.ACL{ 72 Name: "User token", 73 Type: structs.ACLTokenTypeClient, 74 Rules: testEventPolicy, 75 }, 76 WriteRequest: structs.WriteRequest{Token: "root"}, 77 } 78 var token string 79 if err := a.RPC("ACL.Apply", &args, &token); err != nil { 80 t.Fatalf("err: %v", err) 81 } 82 83 type tcase struct { 84 event string 85 allowed bool 86 } 87 tcases := []tcase{ 88 {"foo", false}, 89 {"bar", false}, 90 {"baz", true}, 91 } 92 for _, c := range tcases { 93 // Try to fire the event over the HTTP interface 94 url := fmt.Sprintf("/v1/event/fire/%s?token=%s", c.event, token) 95 req, _ := http.NewRequest("PUT", url, nil) 96 resp := httptest.NewRecorder() 97 if _, err := a.srv.EventFire(resp, req); err != nil { 98 t.Fatalf("err: %s", err) 99 } 100 101 // Check the result 102 body := resp.Body.String() 103 if c.allowed { 104 if acl.IsErrPermissionDenied(errors.New(body)) { 105 t.Fatalf("bad: %s", body) 106 } 107 if resp.Code != 200 { 108 t.Fatalf("bad: %d", resp.Code) 109 } 110 } else { 111 if !acl.IsErrPermissionDenied(errors.New(body)) { 112 t.Fatalf("bad: %s", body) 113 } 114 if resp.Code != 403 { 115 t.Fatalf("bad: %d", resp.Code) 116 } 117 } 118 } 119 } 120 121 func TestEventList(t *testing.T) { 122 t.Parallel() 123 a := NewTestAgent(t, t.Name(), "") 124 defer a.Shutdown() 125 testrpc.WaitForTestAgent(t, a.RPC, "dc1") 126 127 p := &UserEvent{Name: "test"} 128 if err := a.UserEvent("dc1", "root", p); err != nil { 129 t.Fatalf("err: %v", err) 130 } 131 132 retry.Run(t, func(r *retry.R) { 133 req, _ := http.NewRequest("GET", "/v1/event/list", nil) 134 resp := httptest.NewRecorder() 135 obj, err := a.srv.EventList(resp, req) 136 if err != nil { 137 r.Fatal(err) 138 } 139 140 list, ok := obj.([]*UserEvent) 141 if !ok { 142 r.Fatalf("bad: %#v", obj) 143 } 144 if len(list) != 1 || list[0].Name != "test" { 145 r.Fatalf("bad: %#v", list) 146 } 147 header := resp.Header().Get("X-Consul-Index") 148 if header == "" || header == "0" { 149 r.Fatalf("bad: %#v", header) 150 } 151 }) 152 } 153 154 func TestEventList_Filter(t *testing.T) { 155 t.Parallel() 156 a := NewTestAgent(t, t.Name(), "") 157 defer a.Shutdown() 158 testrpc.WaitForTestAgent(t, a.RPC, "dc1") 159 160 p := &UserEvent{Name: "test"} 161 if err := a.UserEvent("dc1", "root", p); err != nil { 162 t.Fatalf("err: %v", err) 163 } 164 165 p = &UserEvent{Name: "foo"} 166 if err := a.UserEvent("dc1", "root", p); err != nil { 167 t.Fatalf("err: %v", err) 168 } 169 170 retry.Run(t, func(r *retry.R) { 171 req, _ := http.NewRequest("GET", "/v1/event/list?name=foo", nil) 172 resp := httptest.NewRecorder() 173 obj, err := a.srv.EventList(resp, req) 174 if err != nil { 175 r.Fatal(err) 176 } 177 178 list, ok := obj.([]*UserEvent) 179 if !ok { 180 r.Fatalf("bad: %#v", obj) 181 } 182 if len(list) != 1 || list[0].Name != "foo" { 183 r.Fatalf("bad: %#v", list) 184 } 185 header := resp.Header().Get("X-Consul-Index") 186 if header == "" || header == "0" { 187 r.Fatalf("bad: %#v", header) 188 } 189 }) 190 } 191 192 func TestEventList_ACLFilter(t *testing.T) { 193 t.Parallel() 194 a := NewTestAgent(t, t.Name(), TestACLConfig()) 195 defer a.Shutdown() 196 testrpc.WaitForLeader(t, a.RPC, "dc1") 197 198 // Fire an event. 199 p := &UserEvent{Name: "foo"} 200 if err := a.UserEvent("dc1", "root", p); err != nil { 201 t.Fatalf("err: %v", err) 202 } 203 204 t.Run("no token", func(t *testing.T) { 205 retry.Run(t, func(r *retry.R) { 206 req, _ := http.NewRequest("GET", "/v1/event/list", nil) 207 resp := httptest.NewRecorder() 208 obj, err := a.srv.EventList(resp, req) 209 if err != nil { 210 r.Fatal(err) 211 } 212 213 list, ok := obj.([]*UserEvent) 214 if !ok { 215 r.Fatalf("bad: %#v", obj) 216 } 217 if len(list) != 0 { 218 r.Fatalf("bad: %#v", list) 219 } 220 }) 221 }) 222 223 t.Run("root token", func(t *testing.T) { 224 retry.Run(t, func(r *retry.R) { 225 req, _ := http.NewRequest("GET", "/v1/event/list?token=root", nil) 226 resp := httptest.NewRecorder() 227 obj, err := a.srv.EventList(resp, req) 228 if err != nil { 229 r.Fatal(err) 230 } 231 232 list, ok := obj.([]*UserEvent) 233 if !ok { 234 r.Fatalf("bad: %#v", obj) 235 } 236 if len(list) != 1 || list[0].Name != "foo" { 237 r.Fatalf("bad: %#v", list) 238 } 239 }) 240 }) 241 } 242 243 func TestEventList_Blocking(t *testing.T) { 244 t.Parallel() 245 a := NewTestAgent(t, t.Name(), "") 246 defer a.Shutdown() 247 testrpc.WaitForTestAgent(t, a.RPC, "dc1") 248 249 p := &UserEvent{Name: "test"} 250 if err := a.UserEvent("dc1", "root", p); err != nil { 251 t.Fatalf("err: %v", err) 252 } 253 254 var index string 255 retry.Run(t, func(r *retry.R) { 256 req, _ := http.NewRequest("GET", "/v1/event/list", nil) 257 resp := httptest.NewRecorder() 258 if _, err := a.srv.EventList(resp, req); err != nil { 259 r.Fatal(err) 260 } 261 header := resp.Header().Get("X-Consul-Index") 262 if header == "" || header == "0" { 263 r.Fatalf("bad: %#v", header) 264 } 265 index = header 266 }) 267 268 go func() { 269 time.Sleep(50 * time.Millisecond) 270 p := &UserEvent{Name: "second"} 271 if err := a.UserEvent("dc1", "root", p); err != nil { 272 t.Fatalf("err: %v", err) 273 } 274 }() 275 276 retry.Run(t, func(r *retry.R) { 277 url := "/v1/event/list?index=" + index 278 req, _ := http.NewRequest("GET", url, nil) 279 resp := httptest.NewRecorder() 280 obj, err := a.srv.EventList(resp, req) 281 if err != nil { 282 r.Fatal(err) 283 } 284 285 list, ok := obj.([]*UserEvent) 286 if !ok { 287 r.Fatalf("bad: %#v", obj) 288 } 289 if len(list) != 2 || list[1].Name != "second" { 290 r.Fatalf("bad: %#v", list) 291 } 292 }) 293 } 294 295 func TestEventList_EventBufOrder(t *testing.T) { 296 t.Parallel() 297 a := NewTestAgent(t, t.Name(), "") 298 defer a.Shutdown() 299 testrpc.WaitForTestAgent(t, a.RPC, "dc1") 300 301 // Fire some events in a non-sequential order 302 expected := &UserEvent{Name: "foo"} 303 304 for _, e := range []*UserEvent{ 305 &UserEvent{Name: "foo"}, 306 &UserEvent{Name: "bar"}, 307 &UserEvent{Name: "foo"}, 308 expected, 309 &UserEvent{Name: "bar"}, 310 } { 311 if err := a.UserEvent("dc1", "root", e); err != nil { 312 t.Fatalf("err: %v", err) 313 } 314 } 315 // Test that the event order is preserved when name 316 // filtering on a list of > 1 matching event. 317 retry.Run(t, func(r *retry.R) { 318 url := "/v1/event/list?name=foo" 319 req, _ := http.NewRequest("GET", url, nil) 320 resp := httptest.NewRecorder() 321 obj, err := a.srv.EventList(resp, req) 322 if err != nil { 323 r.Fatal(err) 324 } 325 list, ok := obj.([]*UserEvent) 326 if !ok { 327 r.Fatalf("bad: %#v", obj) 328 } 329 if len(list) != 3 || list[2].ID != expected.ID { 330 r.Fatalf("bad: %#v", list) 331 } 332 }) 333 } 334 335 func TestUUIDToUint64(t *testing.T) { 336 t.Parallel() 337 inp := "cb9a81ad-fff6-52ac-92a7-5f70687805ec" 338 339 // Output value was computed using python 340 if uuidToUint64(inp) != 6430540886266763072 { 341 t.Fatalf("bad") 342 } 343 }