Fixes #16560 Signed-off-by: Raj Singh <raj@tailscale.com>main
parent
f421907c38
commit
d6d29abbb6
@ -0,0 +1,147 @@ |
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package integration |
||||
|
||||
import ( |
||||
"errors" |
||||
"testing" |
||||
"time" |
||||
|
||||
"tailscale.com/tailcfg" |
||||
"tailscale.com/tstest" |
||||
) |
||||
|
||||
// TestPeerCapMap tests that the node capability map (CapMap) is included in peer information.
|
||||
func TestPeerCapMap(t *testing.T) { |
||||
tstest.Shard(t) |
||||
tstest.Parallel(t) |
||||
env := NewTestEnv(t) |
||||
|
||||
// Spin up two nodes.
|
||||
n1 := NewTestNode(t, env) |
||||
d1 := n1.StartDaemon() |
||||
n1.AwaitListening() |
||||
n1.MustUp() |
||||
n1.AwaitRunning() |
||||
|
||||
n2 := NewTestNode(t, env) |
||||
d2 := n2.StartDaemon() |
||||
n2.AwaitListening() |
||||
n2.MustUp() |
||||
n2.AwaitRunning() |
||||
|
||||
n1.AwaitIP4() |
||||
n2.AwaitIP4() |
||||
|
||||
// Get the nodes from the control server.
|
||||
nodes := env.Control.AllNodes() |
||||
if len(nodes) != 2 { |
||||
t.Fatalf("expected 2 nodes, got %d nodes", len(nodes)) |
||||
} |
||||
|
||||
// Figure out which node is which by comparing keys.
|
||||
st1 := n1.MustStatus() |
||||
var tn1, tn2 *tailcfg.Node |
||||
for _, n := range nodes { |
||||
if n.Key == st1.Self.PublicKey { |
||||
tn1 = n |
||||
} else { |
||||
tn2 = n |
||||
} |
||||
} |
||||
|
||||
// Set CapMap on both nodes.
|
||||
caps := make(tailcfg.NodeCapMap) |
||||
caps["example:custom"] = []tailcfg.RawMessage{`"value"`} |
||||
caps["example:enabled"] = []tailcfg.RawMessage{`true`} |
||||
|
||||
env.Control.SetNodeCapMap(tn1.Key, caps) |
||||
env.Control.SetNodeCapMap(tn2.Key, caps) |
||||
|
||||
// Check that nodes see each other's CapMap.
|
||||
if err := tstest.WaitFor(10*time.Second, func() error { |
||||
st1 := n1.MustStatus() |
||||
st2 := n2.MustStatus() |
||||
|
||||
if len(st1.Peer) == 0 || len(st2.Peer) == 0 { |
||||
return errors.New("no peers") |
||||
} |
||||
|
||||
// Check n1 sees n2's CapMap.
|
||||
p1 := st1.Peer[st1.Peers()[0]] |
||||
if p1.CapMap == nil { |
||||
return errors.New("peer CapMap is nil") |
||||
} |
||||
if p1.CapMap["example:custom"] == nil || p1.CapMap["example:enabled"] == nil { |
||||
return errors.New("peer CapMap missing entries") |
||||
} |
||||
|
||||
// Check n2 sees n1's CapMap.
|
||||
p2 := st2.Peer[st2.Peers()[0]] |
||||
if p2.CapMap == nil { |
||||
return errors.New("peer CapMap is nil") |
||||
} |
||||
if p2.CapMap["example:custom"] == nil || p2.CapMap["example:enabled"] == nil { |
||||
return errors.New("peer CapMap missing entries") |
||||
} |
||||
|
||||
return nil |
||||
}); err != nil { |
||||
t.Fatal(err) |
||||
} |
||||
|
||||
d1.MustCleanShutdown(t) |
||||
d2.MustCleanShutdown(t) |
||||
} |
||||
|
||||
// TestSetNodeCapMap tests that SetNodeCapMap updates are propagated to peers.
|
||||
func TestSetNodeCapMap(t *testing.T) { |
||||
tstest.Shard(t) |
||||
tstest.Parallel(t) |
||||
env := NewTestEnv(t) |
||||
|
||||
n1 := NewTestNode(t, env) |
||||
d1 := n1.StartDaemon() |
||||
n1.AwaitListening() |
||||
n1.MustUp() |
||||
n1.AwaitRunning() |
||||
|
||||
nodes := env.Control.AllNodes() |
||||
if len(nodes) != 1 { |
||||
t.Fatalf("expected 1 node, got %d nodes", len(nodes)) |
||||
} |
||||
node1 := nodes[0] |
||||
|
||||
// Set initial CapMap.
|
||||
caps := make(tailcfg.NodeCapMap) |
||||
caps["test:state"] = []tailcfg.RawMessage{`"initial"`} |
||||
env.Control.SetNodeCapMap(node1.Key, caps) |
||||
|
||||
// Start second node and verify it sees the first node's CapMap.
|
||||
n2 := NewTestNode(t, env) |
||||
d2 := n2.StartDaemon() |
||||
n2.AwaitListening() |
||||
n2.MustUp() |
||||
n2.AwaitRunning() |
||||
|
||||
if err := tstest.WaitFor(5*time.Second, func() error { |
||||
st := n2.MustStatus() |
||||
if len(st.Peer) == 0 { |
||||
return errors.New("no peers") |
||||
} |
||||
p := st.Peer[st.Peers()[0]] |
||||
if p.CapMap == nil || p.CapMap["test:state"] == nil { |
||||
return errors.New("peer CapMap not set") |
||||
} |
||||
if string(p.CapMap["test:state"][0]) != `"initial"` { |
||||
return errors.New("wrong CapMap value") |
||||
} |
||||
return nil |
||||
}); err != nil { |
||||
t.Fatal(err) |
||||
} |
||||
|
||||
d1.MustCleanShutdown(t) |
||||
d2.MustCleanShutdown(t) |
||||
} |
||||
Loading…
Reference in new issue