github.com/clly/consul@v1.4.5/agent/consul/internal_endpoint_test.go (about) 1 package consul 2 3 import ( 4 "encoding/base64" 5 "os" 6 "testing" 7 8 "github.com/hashicorp/consul/acl" 9 "github.com/hashicorp/consul/agent/structs" 10 "github.com/hashicorp/consul/api" 11 "github.com/hashicorp/consul/lib" 12 "github.com/hashicorp/consul/testrpc" 13 "github.com/hashicorp/net-rpc-msgpackrpc" 14 ) 15 16 func TestInternal_NodeInfo(t *testing.T) { 17 t.Parallel() 18 dir1, s1 := testServer(t) 19 defer os.RemoveAll(dir1) 20 defer s1.Shutdown() 21 codec := rpcClient(t, s1) 22 defer codec.Close() 23 24 testrpc.WaitForLeader(t, s1.RPC, "dc1") 25 26 arg := structs.RegisterRequest{ 27 Datacenter: "dc1", 28 Node: "foo", 29 Address: "127.0.0.1", 30 Service: &structs.NodeService{ 31 ID: "db", 32 Service: "db", 33 Tags: []string{"master"}, 34 }, 35 Check: &structs.HealthCheck{ 36 Name: "db connect", 37 Status: api.HealthPassing, 38 ServiceID: "db", 39 }, 40 } 41 var out struct{} 42 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil { 43 t.Fatalf("err: %v", err) 44 } 45 46 var out2 structs.IndexedNodeDump 47 req := structs.NodeSpecificRequest{ 48 Datacenter: "dc1", 49 Node: "foo", 50 } 51 if err := msgpackrpc.CallWithCodec(codec, "Internal.NodeInfo", &req, &out2); err != nil { 52 t.Fatalf("err: %v", err) 53 } 54 55 nodes := out2.Dump 56 if len(nodes) != 1 { 57 t.Fatalf("Bad: %v", nodes) 58 } 59 if nodes[0].Node != "foo" { 60 t.Fatalf("Bad: %v", nodes[0]) 61 } 62 if !lib.StrContains(nodes[0].Services[0].Tags, "master") { 63 t.Fatalf("Bad: %v", nodes[0]) 64 } 65 if nodes[0].Checks[0].Status != api.HealthPassing { 66 t.Fatalf("Bad: %v", nodes[0]) 67 } 68 } 69 70 func TestInternal_NodeDump(t *testing.T) { 71 t.Parallel() 72 dir1, s1 := testServer(t) 73 defer os.RemoveAll(dir1) 74 defer s1.Shutdown() 75 codec := rpcClient(t, s1) 76 defer codec.Close() 77 78 testrpc.WaitForLeader(t, s1.RPC, "dc1") 79 80 arg := structs.RegisterRequest{ 81 Datacenter: "dc1", 82 Node: "foo", 83 Address: "127.0.0.1", 84 Service: &structs.NodeService{ 85 ID: "db", 86 Service: "db", 87 Tags: []string{"master"}, 88 }, 89 Check: &structs.HealthCheck{ 90 Name: "db connect", 91 Status: api.HealthPassing, 92 ServiceID: "db", 93 }, 94 } 95 var out struct{} 96 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil { 97 t.Fatalf("err: %v", err) 98 } 99 100 arg = structs.RegisterRequest{ 101 Datacenter: "dc1", 102 Node: "bar", 103 Address: "127.0.0.2", 104 Service: &structs.NodeService{ 105 ID: "db", 106 Service: "db", 107 Tags: []string{"slave"}, 108 }, 109 Check: &structs.HealthCheck{ 110 Name: "db connect", 111 Status: api.HealthWarning, 112 ServiceID: "db", 113 }, 114 } 115 if err := msgpackrpc.CallWithCodec(codec, "Catalog.Register", &arg, &out); err != nil { 116 t.Fatalf("err: %v", err) 117 } 118 119 var out2 structs.IndexedNodeDump 120 req := structs.DCSpecificRequest{ 121 Datacenter: "dc1", 122 } 123 if err := msgpackrpc.CallWithCodec(codec, "Internal.NodeDump", &req, &out2); err != nil { 124 t.Fatalf("err: %v", err) 125 } 126 127 nodes := out2.Dump 128 if len(nodes) != 3 { 129 t.Fatalf("Bad: %v", nodes) 130 } 131 132 var foundFoo, foundBar bool 133 for _, node := range nodes { 134 switch node.Node { 135 case "foo": 136 foundFoo = true 137 if !lib.StrContains(node.Services[0].Tags, "master") { 138 t.Fatalf("Bad: %v", nodes[0]) 139 } 140 if node.Checks[0].Status != api.HealthPassing { 141 t.Fatalf("Bad: %v", nodes[0]) 142 } 143 144 case "bar": 145 foundBar = true 146 if !lib.StrContains(node.Services[0].Tags, "slave") { 147 t.Fatalf("Bad: %v", nodes[1]) 148 } 149 if node.Checks[0].Status != api.HealthWarning { 150 t.Fatalf("Bad: %v", nodes[1]) 151 } 152 153 default: 154 continue 155 } 156 } 157 if !foundFoo || !foundBar { 158 t.Fatalf("missing foo or bar") 159 } 160 } 161 162 func TestInternal_KeyringOperation(t *testing.T) { 163 t.Parallel() 164 key1 := "H1dfkSZOVnP/JUnaBfTzXg==" 165 keyBytes1, err := base64.StdEncoding.DecodeString(key1) 166 if err != nil { 167 t.Fatalf("err: %s", err) 168 } 169 dir1, s1 := testServerWithConfig(t, func(c *Config) { 170 c.SerfLANConfig.MemberlistConfig.SecretKey = keyBytes1 171 c.SerfWANConfig.MemberlistConfig.SecretKey = keyBytes1 172 }) 173 defer os.RemoveAll(dir1) 174 defer s1.Shutdown() 175 codec := rpcClient(t, s1) 176 defer codec.Close() 177 178 testrpc.WaitForLeader(t, s1.RPC, "dc1") 179 180 var out structs.KeyringResponses 181 req := structs.KeyringRequest{ 182 Operation: structs.KeyringList, 183 Datacenter: "dc1", 184 } 185 if err := msgpackrpc.CallWithCodec(codec, "Internal.KeyringOperation", &req, &out); err != nil { 186 t.Fatalf("err: %v", err) 187 } 188 189 // Two responses (local lan/wan pools) from single-node cluster 190 if len(out.Responses) != 2 { 191 t.Fatalf("bad: %#v", out) 192 } 193 if _, ok := out.Responses[0].Keys[key1]; !ok { 194 t.Fatalf("bad: %#v", out) 195 } 196 wanResp, lanResp := 0, 0 197 for _, resp := range out.Responses { 198 if resp.WAN { 199 wanResp++ 200 } else { 201 lanResp++ 202 } 203 } 204 if lanResp != 1 || wanResp != 1 { 205 t.Fatalf("should have one lan and one wan response") 206 } 207 208 // Start a second agent to test cross-dc queries 209 dir2, s2 := testServerWithConfig(t, func(c *Config) { 210 c.SerfLANConfig.MemberlistConfig.SecretKey = keyBytes1 211 c.SerfWANConfig.MemberlistConfig.SecretKey = keyBytes1 212 c.Datacenter = "dc2" 213 }) 214 defer os.RemoveAll(dir2) 215 defer s2.Shutdown() 216 217 // Try to join 218 joinWAN(t, s2, s1) 219 220 var out2 structs.KeyringResponses 221 req2 := structs.KeyringRequest{ 222 Operation: structs.KeyringList, 223 } 224 if err := msgpackrpc.CallWithCodec(codec, "Internal.KeyringOperation", &req2, &out2); err != nil { 225 t.Fatalf("err: %v", err) 226 } 227 228 // 3 responses (one from each DC LAN, one from WAN) in two-node cluster 229 if len(out2.Responses) != 3 { 230 t.Fatalf("bad: %#v", out) 231 } 232 wanResp, lanResp = 0, 0 233 for _, resp := range out2.Responses { 234 if resp.WAN { 235 wanResp++ 236 } else { 237 lanResp++ 238 } 239 } 240 if lanResp != 2 || wanResp != 1 { 241 t.Fatalf("should have two lan and one wan response") 242 } 243 } 244 245 func TestInternal_NodeInfo_FilterACL(t *testing.T) { 246 t.Parallel() 247 dir, token, srv, codec := testACLFilterServer(t) 248 defer os.RemoveAll(dir) 249 defer srv.Shutdown() 250 defer codec.Close() 251 252 opt := structs.NodeSpecificRequest{ 253 Datacenter: "dc1", 254 Node: srv.config.NodeName, 255 QueryOptions: structs.QueryOptions{Token: token}, 256 } 257 reply := structs.IndexedNodeDump{} 258 if err := msgpackrpc.CallWithCodec(codec, "Health.NodeChecks", &opt, &reply); err != nil { 259 t.Fatalf("err: %s", err) 260 } 261 for _, info := range reply.Dump { 262 found := false 263 for _, chk := range info.Checks { 264 if chk.ServiceName == "foo" { 265 found = true 266 } 267 if chk.ServiceName == "bar" { 268 t.Fatalf("bad: %#v", info.Checks) 269 } 270 } 271 if !found { 272 t.Fatalf("bad: %#v", info.Checks) 273 } 274 275 found = false 276 for _, svc := range info.Services { 277 if svc.Service == "foo" { 278 found = true 279 } 280 if svc.Service == "bar" { 281 t.Fatalf("bad: %#v", info.Services) 282 } 283 } 284 if !found { 285 t.Fatalf("bad: %#v", info.Services) 286 } 287 } 288 289 // We've already proven that we call the ACL filtering function so we 290 // test node filtering down in acl.go for node cases. This also proves 291 // that we respect the version 8 ACL flag, since the test server sets 292 // that to false (the regression value of *not* changing this is better 293 // for now until we change the sense of the version 8 ACL flag). 294 } 295 296 func TestInternal_NodeDump_FilterACL(t *testing.T) { 297 t.Parallel() 298 dir, token, srv, codec := testACLFilterServer(t) 299 defer os.RemoveAll(dir) 300 defer srv.Shutdown() 301 defer codec.Close() 302 303 opt := structs.DCSpecificRequest{ 304 Datacenter: "dc1", 305 QueryOptions: structs.QueryOptions{Token: token}, 306 } 307 reply := structs.IndexedNodeDump{} 308 if err := msgpackrpc.CallWithCodec(codec, "Health.NodeChecks", &opt, &reply); err != nil { 309 t.Fatalf("err: %s", err) 310 } 311 for _, info := range reply.Dump { 312 found := false 313 for _, chk := range info.Checks { 314 if chk.ServiceName == "foo" { 315 found = true 316 } 317 if chk.ServiceName == "bar" { 318 t.Fatalf("bad: %#v", info.Checks) 319 } 320 } 321 if !found { 322 t.Fatalf("bad: %#v", info.Checks) 323 } 324 325 found = false 326 for _, svc := range info.Services { 327 if svc.Service == "foo" { 328 found = true 329 } 330 if svc.Service == "bar" { 331 t.Fatalf("bad: %#v", info.Services) 332 } 333 } 334 if !found { 335 t.Fatalf("bad: %#v", info.Services) 336 } 337 } 338 339 // We've already proven that we call the ACL filtering function so we 340 // test node filtering down in acl.go for node cases. This also proves 341 // that we respect the version 8 ACL flag, since the test server sets 342 // that to false (the regression value of *not* changing this is better 343 // for now until we change the sense of the version 8 ACL flag). 344 } 345 346 func TestInternal_EventFire_Token(t *testing.T) { 347 t.Parallel() 348 dir, srv := testServerWithConfig(t, func(c *Config) { 349 c.ACLDatacenter = "dc1" 350 c.ACLsEnabled = true 351 c.ACLMasterToken = "root" 352 c.ACLDownPolicy = "deny" 353 c.ACLDefaultPolicy = "deny" 354 }) 355 defer os.RemoveAll(dir) 356 defer srv.Shutdown() 357 358 codec := rpcClient(t, srv) 359 defer codec.Close() 360 361 testrpc.WaitForLeader(t, srv.RPC, "dc1") 362 363 // No token is rejected 364 event := structs.EventFireRequest{ 365 Name: "foo", 366 Datacenter: "dc1", 367 Payload: []byte("nope"), 368 } 369 err := msgpackrpc.CallWithCodec(codec, "Internal.EventFire", &event, nil) 370 if !acl.IsErrPermissionDenied(err) { 371 t.Fatalf("bad: %s", err) 372 } 373 374 // Root token is allowed to fire 375 event.Token = "root" 376 err = msgpackrpc.CallWithCodec(codec, "Internal.EventFire", &event, nil) 377 if err != nil { 378 t.Fatalf("err: %s", err) 379 } 380 }