gen: regenerate protobuf code

This commit is contained in:
Kristoffer Dalby 2026-01-07 14:07:45 +01:00 committed by Kristoffer Dalby
parent eec54cbbf3
commit 0516c0ec37
7 changed files with 106 additions and 161 deletions

View file

@ -4,7 +4,6 @@ import (
"fmt"
"log"
"net/netip"
"slices"
"strconv"
"strings"
"time"
@ -22,7 +21,6 @@ import (
func init() {
rootCmd.AddCommand(nodeCmd)
listNodesCmd.Flags().StringP("user", "u", "", "Filter by user")
listNodesCmd.Flags().BoolP("tags", "t", false, "Show tags")
listNodesCmd.Flags().StringP("namespace", "n", "", "User")
listNodesNamespaceFlag := listNodesCmd.Flags().Lookup("namespace")
@ -148,10 +146,6 @@ var listNodesCmd = &cobra.Command{
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting user: %s", err), output)
}
showTags, err := cmd.Flags().GetBool("tags")
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error getting tags flag: %s", err), output)
}
ctx, client, conn, cancel := newHeadscaleCLIWithConfig()
defer cancel()
@ -174,7 +168,7 @@ var listNodesCmd = &cobra.Command{
SuccessOutput(response.GetNodes(), "", output)
}
tableData, err := nodesToPtables(user, showTags, response.GetNodes())
tableData, err := nodesToPtables(user, response.GetNodes())
if err != nil {
ErrorOutput(err, fmt.Sprintf("Error converting to table: %s", err), output)
}
@ -482,7 +476,6 @@ be assigned to nodes.`,
func nodesToPtables(
currentUser string,
showTags bool,
nodes []*v1.Node,
) (pterm.TableData, error) {
tableHeader := []string{
@ -492,6 +485,7 @@ func nodesToPtables(
"MachineKey",
"NodeKey",
"User",
"Tags",
"IP addresses",
"Ephemeral",
"Last seen",
@ -499,13 +493,6 @@ func nodesToPtables(
"Connected",
"Expired",
}
if showTags {
tableHeader = append(tableHeader, []string{
"ForcedTags",
"InvalidTags",
"ValidTags",
}...)
}
tableData := pterm.TableData{tableHeader}
for _, node := range nodes {
@ -560,28 +547,17 @@ func nodesToPtables(
expired = pterm.LightRed("yes")
}
var forcedTags string
for _, tag := range node.GetForcedTags() {
forcedTags += "\n" + tag
// TODO(kradalby): as part of CLI rework, we should add the posibility to show "unusable" tags as mentioned in
// https://github.com/juanfont/headscale/issues/2981
var tagsBuilder strings.Builder
for _, tag := range node.GetTags() {
tagsBuilder.WriteString("\n" + tag)
}
forcedTags = strings.TrimLeft(forcedTags, "\n")
var invalidTags string
for _, tag := range node.GetInvalidTags() {
if !slices.Contains(node.GetForcedTags(), tag) {
invalidTags += "\n" + pterm.LightRed(tag)
}
}
tags := tagsBuilder.String()
invalidTags = strings.TrimLeft(invalidTags, "\n")
var validTags string
for _, tag := range node.GetValidTags() {
if !slices.Contains(node.GetForcedTags(), tag) {
validTags += "\n" + pterm.LightGreen(tag)
}
}
validTags = strings.TrimLeft(validTags, "\n")
tags = strings.TrimLeft(tags, "\n")
var user string
if currentUser == "" || (currentUser == node.GetUser().GetName()) {
@ -608,6 +584,7 @@ func nodesToPtables(
machineKey.ShortString(),
nodeKey.ShortString(),
user,
tags,
strings.Join([]string{IPV4Address, IPV6Address}, ", "),
strconv.FormatBool(ephemeral),
lastSeenTime,
@ -615,9 +592,6 @@ func nodesToPtables(
online,
expired,
}
if showTags {
nodeData = append(nodeData, []string{forcedTags, invalidTags, validTags}...)
}
tableData = append(
tableData,
nodeData,

View file

@ -75,27 +75,29 @@ func (RegisterMethod) EnumDescriptor() ([]byte, []int) {
}
type Node struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
MachineKey string `protobuf:"bytes,2,opt,name=machine_key,json=machineKey,proto3" json:"machine_key,omitempty"`
NodeKey string `protobuf:"bytes,3,opt,name=node_key,json=nodeKey,proto3" json:"node_key,omitempty"`
DiscoKey string `protobuf:"bytes,4,opt,name=disco_key,json=discoKey,proto3" json:"disco_key,omitempty"`
IpAddresses []string `protobuf:"bytes,5,rep,name=ip_addresses,json=ipAddresses,proto3" json:"ip_addresses,omitempty"`
Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"`
User *User `protobuf:"bytes,7,opt,name=user,proto3" json:"user,omitempty"`
LastSeen *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=last_seen,json=lastSeen,proto3" json:"last_seen,omitempty"`
Expiry *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=expiry,proto3" json:"expiry,omitempty"`
PreAuthKey *PreAuthKey `protobuf:"bytes,11,opt,name=pre_auth_key,json=preAuthKey,proto3" json:"pre_auth_key,omitempty"`
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
RegisterMethod RegisterMethod `protobuf:"varint,13,opt,name=register_method,json=registerMethod,proto3,enum=headscale.v1.RegisterMethod" json:"register_method,omitempty"`
ForcedTags []string `protobuf:"bytes,18,rep,name=forced_tags,json=forcedTags,proto3" json:"forced_tags,omitempty"`
InvalidTags []string `protobuf:"bytes,19,rep,name=invalid_tags,json=invalidTags,proto3" json:"invalid_tags,omitempty"`
ValidTags []string `protobuf:"bytes,20,rep,name=valid_tags,json=validTags,proto3" json:"valid_tags,omitempty"`
GivenName string `protobuf:"bytes,21,opt,name=given_name,json=givenName,proto3" json:"given_name,omitempty"`
Online bool `protobuf:"varint,22,opt,name=online,proto3" json:"online,omitempty"`
ApprovedRoutes []string `protobuf:"bytes,23,rep,name=approved_routes,json=approvedRoutes,proto3" json:"approved_routes,omitempty"`
AvailableRoutes []string `protobuf:"bytes,24,rep,name=available_routes,json=availableRoutes,proto3" json:"available_routes,omitempty"`
SubnetRoutes []string `protobuf:"bytes,25,rep,name=subnet_routes,json=subnetRoutes,proto3" json:"subnet_routes,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
MachineKey string `protobuf:"bytes,2,opt,name=machine_key,json=machineKey,proto3" json:"machine_key,omitempty"`
NodeKey string `protobuf:"bytes,3,opt,name=node_key,json=nodeKey,proto3" json:"node_key,omitempty"`
DiscoKey string `protobuf:"bytes,4,opt,name=disco_key,json=discoKey,proto3" json:"disco_key,omitempty"`
IpAddresses []string `protobuf:"bytes,5,rep,name=ip_addresses,json=ipAddresses,proto3" json:"ip_addresses,omitempty"`
Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"`
User *User `protobuf:"bytes,7,opt,name=user,proto3" json:"user,omitempty"`
LastSeen *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=last_seen,json=lastSeen,proto3" json:"last_seen,omitempty"`
Expiry *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=expiry,proto3" json:"expiry,omitempty"`
PreAuthKey *PreAuthKey `protobuf:"bytes,11,opt,name=pre_auth_key,json=preAuthKey,proto3" json:"pre_auth_key,omitempty"`
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
RegisterMethod RegisterMethod `protobuf:"varint,13,opt,name=register_method,json=registerMethod,proto3,enum=headscale.v1.RegisterMethod" json:"register_method,omitempty"`
// Deprecated
// repeated string forced_tags = 18;
// repeated string invalid_tags = 19;
// repeated string valid_tags = 20;
GivenName string `protobuf:"bytes,21,opt,name=given_name,json=givenName,proto3" json:"given_name,omitempty"`
Online bool `protobuf:"varint,22,opt,name=online,proto3" json:"online,omitempty"`
ApprovedRoutes []string `protobuf:"bytes,23,rep,name=approved_routes,json=approvedRoutes,proto3" json:"approved_routes,omitempty"`
AvailableRoutes []string `protobuf:"bytes,24,rep,name=available_routes,json=availableRoutes,proto3" json:"available_routes,omitempty"`
SubnetRoutes []string `protobuf:"bytes,25,rep,name=subnet_routes,json=subnetRoutes,proto3" json:"subnet_routes,omitempty"`
Tags []string `protobuf:"bytes,26,rep,name=tags,proto3" json:"tags,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -214,27 +216,6 @@ func (x *Node) GetRegisterMethod() RegisterMethod {
return RegisterMethod_REGISTER_METHOD_UNSPECIFIED
}
func (x *Node) GetForcedTags() []string {
if x != nil {
return x.ForcedTags
}
return nil
}
func (x *Node) GetInvalidTags() []string {
if x != nil {
return x.InvalidTags
}
return nil
}
func (x *Node) GetValidTags() []string {
if x != nil {
return x.ValidTags
}
return nil
}
func (x *Node) GetGivenName() string {
if x != nil {
return x.GivenName
@ -270,6 +251,13 @@ func (x *Node) GetSubnetRoutes() []string {
return nil
}
func (x *Node) GetTags() []string {
if x != nil {
return x.Tags
}
return nil
}
type RegisterNodeRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
User string `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
@ -1210,7 +1198,7 @@ var File_headscale_v1_node_proto protoreflect.FileDescriptor
const file_headscale_v1_node_proto_rawDesc = "" +
"\n" +
"\x17headscale/v1/node.proto\x12\fheadscale.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1dheadscale/v1/preauthkey.proto\x1a\x17headscale/v1/user.proto\"\x98\x06\n" +
"\x17headscale/v1/node.proto\x12\fheadscale.v1\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1dheadscale/v1/preauthkey.proto\x1a\x17headscale/v1/user.proto\"\xc9\x05\n" +
"\x04Node\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x04R\x02id\x12\x1f\n" +
"\vmachine_key\x18\x02 \x01(\tR\n" +
@ -1227,19 +1215,15 @@ const file_headscale_v1_node_proto_rawDesc = "" +
"preAuthKey\x129\n" +
"\n" +
"created_at\x18\f \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x12E\n" +
"\x0fregister_method\x18\r \x01(\x0e2\x1c.headscale.v1.RegisterMethodR\x0eregisterMethod\x12\x1f\n" +
"\vforced_tags\x18\x12 \x03(\tR\n" +
"forcedTags\x12!\n" +
"\finvalid_tags\x18\x13 \x03(\tR\vinvalidTags\x12\x1d\n" +
"\n" +
"valid_tags\x18\x14 \x03(\tR\tvalidTags\x12\x1d\n" +
"\x0fregister_method\x18\r \x01(\x0e2\x1c.headscale.v1.RegisterMethodR\x0eregisterMethod\x12\x1d\n" +
"\n" +
"given_name\x18\x15 \x01(\tR\tgivenName\x12\x16\n" +
"\x06online\x18\x16 \x01(\bR\x06online\x12'\n" +
"\x0fapproved_routes\x18\x17 \x03(\tR\x0eapprovedRoutes\x12)\n" +
"\x10available_routes\x18\x18 \x03(\tR\x0favailableRoutes\x12#\n" +
"\rsubnet_routes\x18\x19 \x03(\tR\fsubnetRoutesJ\x04\b\t\x10\n" +
"J\x04\b\x0e\x10\x12\";\n" +
"\rsubnet_routes\x18\x19 \x03(\tR\fsubnetRoutes\x12\x12\n" +
"\x04tags\x18\x1a \x03(\tR\x04tagsJ\x04\b\t\x10\n" +
"J\x04\b\x0e\x10\x15\";\n" +
"\x13RegisterNodeRequest\x12\x12\n" +
"\x04user\x18\x01 \x01(\tR\x04user\x12\x10\n" +
"\x03key\x18\x02 \x01(\tR\x03key\">\n" +

View file

@ -1178,26 +1178,9 @@
"registerMethod": {
"$ref": "#/definitions/v1RegisterMethod"
},
"forcedTags": {
"type": "array",
"items": {
"type": "string"
}
},
"invalidTags": {
"type": "array",
"items": {
"type": "string"
}
},
"validTags": {
"type": "array",
"items": {
"type": "string"
}
},
"givenName": {
"type": "string"
"type": "string",
"title": "Deprecated\nrepeated string forced_tags = 18;\nrepeated string invalid_tags = 19;\nrepeated string valid_tags = 20;"
},
"online": {
"type": "boolean"
@ -1219,6 +1202,12 @@
"items": {
"type": "string"
}
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
}
}
},

View file

@ -339,11 +339,11 @@ func (api headscaleV1APIServer) SetTags(
// Validate tags not empty - tagged nodes must have at least one tag
if len(request.GetTags()) == 0 {
return &v1.SetTagsResponse{
Node: nil,
}, status.Error(
codes.InvalidArgument,
"cannot remove all tags from a node - tagged nodes must have at least one tag",
)
Node: nil,
}, status.Error(
codes.InvalidArgument,
"cannot remove all tags from a node - tagged nodes must have at least one tag",
)
}
// Validate tag format
@ -551,8 +551,6 @@ func nodesToProto(state *state.State, nodes views.Slice[types.NodeView]) []*v1.N
resp.User = types.TaggedDevices.Proto()
}
resp.ValidTags = node.Tags().AsSlice()
resp.SubnetRoutes = util.PrefixesToString(append(state.GetNodePrimaryRoutes(node.ID()), node.ExitRoutes()...))
response[index] = resp
}

View file

@ -377,7 +377,7 @@ func (node *Node) Proto() *v1.Node {
Name: node.Hostname,
GivenName: node.GivenName,
User: nil, // Will be set below based on node type
ForcedTags: node.Tags,
Tags: node.Tags,
Online: node.IsOnline != nil && *node.IsOnline,
// Only ApprovedRoutes and AvailableRoutes is set here. SubnetRoutes has

View file

@ -2814,7 +2814,7 @@ func TestACLTagPropagation(t *testing.T) {
assert.NotNil(c, node, "Node should still exist")
if node != nil {
assert.ElementsMatch(c, tt.tagChange, node.GetValidTags(), "Tags should be updated")
assert.ElementsMatch(c, tt.tagChange, node.GetTags(), "Tags should be updated")
}
}, 10*time.Second, 500*time.Millisecond, "verifying tag change applied")

View file

@ -67,7 +67,7 @@ func tagsEqual(actual, expected []string) bool {
// assertNodeHasTagsWithCollect asserts that a node has exactly the expected tags (order-independent).
func assertNodeHasTagsWithCollect(c *assert.CollectT, node *v1.Node, expectedTags []string) {
actualTags := node.GetValidTags()
actualTags := node.GetTags()
sortedActual := append([]string{}, actualTags...)
sortedExpected := append([]string{}, expectedTags...)
@ -78,7 +78,7 @@ func assertNodeHasTagsWithCollect(c *assert.CollectT, node *v1.Node, expectedTag
// assertNodeHasNoTagsWithCollect asserts that a node has no tags.
func assertNodeHasNoTagsWithCollect(c *assert.CollectT, node *v1.Node) {
assert.Empty(c, node.GetValidTags(), "Node %s should have no tags, but has: %v", node.GetName(), node.GetValidTags())
assert.Empty(c, node.GetTags(), "Node %s should have no tags, but has: %v", node.GetName(), node.GetTags())
}
// =============================================================================
@ -152,7 +152,7 @@ func TestTagsAuthKeyWithTagRequestDifferentTag(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetValidTags())
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetTags())
}
}, 10*time.Second, 500*time.Millisecond, "checking node state")
@ -222,7 +222,7 @@ func TestTagsAuthKeyWithTagNoAdvertiseFlag(t *testing.T) {
if len(nodes) == 1 {
node := nodes[0]
t.Logf("Node registered with tags: %v", node.GetValidTags())
t.Logf("Node registered with tags: %v", node.GetTags())
assertNodeHasTagsWithCollect(c, node, []string{"tag:valid-owned"})
}
}, 30*time.Second, 500*time.Millisecond, "verifying node inherited tags from auth key")
@ -320,10 +320,10 @@ func TestTagsAuthKeyWithTagCannotAddViaCLI(t *testing.T) {
if len(nodes) == 1 {
// If still only has original tag, that's the expected behavior
if tagsEqual(nodes[0].GetValidTags(), []string{"tag:valid-owned"}) {
t.Logf("Test 2.3 PASS: Tags unchanged after CLI attempt: %v", nodes[0].GetValidTags())
if tagsEqual(nodes[0].GetTags(), []string{"tag:valid-owned"}) {
t.Logf("Test 2.3 PASS: Tags unchanged after CLI attempt: %v", nodes[0].GetTags())
} else {
t.Logf("Test 2.3 FAIL: Tags changed unexpectedly to: %v", nodes[0].GetValidTags())
t.Logf("Test 2.3 FAIL: Tags changed unexpectedly to: %v", nodes[0].GetTags())
assert.Fail(c, "Tags should not have changed")
}
}
@ -416,10 +416,10 @@ func TestTagsAuthKeyWithTagCannotChangeViaCLI(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
if tagsEqual(nodes[0].GetValidTags(), []string{"tag:valid-owned"}) {
t.Logf("Test 2.4 PASS: Tags unchanged: %v", nodes[0].GetValidTags())
if tagsEqual(nodes[0].GetTags(), []string{"tag:valid-owned"}) {
t.Logf("Test 2.4 PASS: Tags unchanged: %v", nodes[0].GetTags())
} else {
t.Logf("Test 2.4 FAIL: Tags changed unexpectedly to: %v", nodes[0].GetValidTags())
t.Logf("Test 2.4 FAIL: Tags changed unexpectedly to: %v", nodes[0].GetTags())
assert.Fail(c, "Tags should not have changed")
}
}
@ -509,7 +509,7 @@ func TestTagsAuthKeyWithTagAdminOverrideReauthPreserves(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("After admin assignment, tags are: %v", nodes[0].GetValidTags())
t.Logf("After admin assignment, tags are: %v", nodes[0].GetTags())
assertNodeHasTagsWithCollect(c, nodes[0], []string{"tag:second"})
}
}, 10*time.Second, 500*time.Millisecond, "verifying admin tag assignment")
@ -535,7 +535,7 @@ func TestTagsAuthKeyWithTagAdminOverrideReauthPreserves(t *testing.T) {
if len(nodes) >= 1 {
// Find the most recently updated node (in case a new one was created)
node := nodes[len(nodes)-1]
t.Logf("After reauth, tags are: %v", node.GetValidTags())
t.Logf("After reauth, tags are: %v", node.GetTags())
// Expected: admin-assigned tags are preserved through reauth
assertNodeHasTagsWithCollect(c, node, []string{"tag:second"})
@ -648,7 +648,7 @@ func TestTagsAuthKeyWithTagCLICannotModifyAdminTags(t *testing.T) {
assert.Len(c, nodes, 1, "Should have exactly 1 node")
if len(nodes) == 1 {
t.Logf("After CLI attempt, tags are: %v", nodes[0].GetValidTags())
t.Logf("After CLI attempt, tags are: %v", nodes[0].GetTags())
// Expected: tags should remain unchanged (admin wins)
assertNodeHasTagsWithCollect(c, nodes[0], []string{"tag:valid-owned", "tag:second"})
@ -726,7 +726,7 @@ func TestTagsAuthKeyWithoutTagCannotRequestTags(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetValidTags())
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetTags())
}
}, 10*time.Second, 500*time.Millisecond, "checking node state")
@ -793,7 +793,7 @@ func TestTagsAuthKeyWithoutTagRegisterNoTags(t *testing.T) {
assert.Len(c, nodes, 1)
if len(nodes) == 1 {
t.Logf("Node registered with tags: %v", nodes[0].GetValidTags())
t.Logf("Node registered with tags: %v", nodes[0].GetTags())
assertNodeHasNoTagsWithCollect(c, nodes[0])
}
}, 30*time.Second, 500*time.Millisecond, "verifying node has no tags")
@ -889,10 +889,10 @@ func TestTagsAuthKeyWithoutTagCannotAddViaCLI(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
if len(nodes[0].GetValidTags()) == 0 {
if len(nodes[0].GetTags()) == 0 {
t.Logf("Test 3.3 PASS: Tags still empty after CLI attempt")
} else {
t.Logf("Test 3.3 FAIL: Tags changed to: %v", nodes[0].GetValidTags())
t.Logf("Test 3.3 FAIL: Tags changed to: %v", nodes[0].GetTags())
assert.Fail(c, "Tags should not have changed")
}
}
@ -1003,7 +1003,7 @@ func TestTagsAuthKeyWithoutTagCLINoOpAfterAdminWithReset(t *testing.T) {
assert.Len(c, nodes, 1, "Should have exactly 1 node")
if len(nodes) == 1 {
t.Logf("After --reset, tags are: %v", nodes[0].GetValidTags())
t.Logf("After --reset, tags are: %v", nodes[0].GetTags())
assertNodeHasTagsWithCollect(c, nodes[0], []string{"tag:valid-owned"})
}
}, 10*time.Second, 500*time.Millisecond, "admin tags should be preserved after --reset")
@ -1113,7 +1113,7 @@ func TestTagsAuthKeyWithoutTagCLINoOpAfterAdminWithEmptyAdvertise(t *testing.T)
assert.Len(c, nodes, 1, "Should have exactly 1 node")
if len(nodes) == 1 {
t.Logf("After empty --advertise-tags, tags are: %v", nodes[0].GetValidTags())
t.Logf("After empty --advertise-tags, tags are: %v", nodes[0].GetTags())
assertNodeHasTagsWithCollect(c, nodes[0], []string{"tag:valid-owned"})
}
}, 10*time.Second, 500*time.Millisecond, "admin tags should be preserved after empty --advertise-tags")
@ -1223,7 +1223,7 @@ func TestTagsAuthKeyWithoutTagCLICannotReduceAdminMultiTag(t *testing.T) {
assert.Len(c, nodes, 1, "Should have exactly 1 node")
if len(nodes) == 1 {
t.Logf("After CLI reduce attempt, tags are: %v", nodes[0].GetValidTags())
t.Logf("After CLI reduce attempt, tags are: %v", nodes[0].GetTags())
assertNodeHasTagsWithCollect(c, nodes[0], []string{"tag:valid-owned", "tag:second"})
}
}, 10*time.Second, 500*time.Millisecond, "admin tags should be preserved after CLI reduce attempt")
@ -1300,7 +1300,7 @@ func TestTagsUserLoginOwnedTagAtRegistration(t *testing.T) {
assert.Len(c, nodes, 1, "Should have exactly 1 node")
if len(nodes) == 1 {
t.Logf("Node registered with tags: %v", nodes[0].GetValidTags())
t.Logf("Node registered with tags: %v", nodes[0].GetTags())
assertNodeHasTagsWithCollect(c, nodes[0], []string{"tag:valid-owned"})
}
}, 30*time.Second, 500*time.Millisecond, "verifying node has advertised tag")
@ -1373,9 +1373,9 @@ func TestTagsUserLoginNonExistentTagAtRegistration(t *testing.T) {
t.Logf("Test 1.2 PASS: Registration rejected - no nodes registered")
} else {
// If a node was registered, it should NOT have the non-existent tag
assert.NotContains(c, nodes[0].GetValidTags(), "tag:nonexistent",
assert.NotContains(c, nodes[0].GetTags(), "tag:nonexistent",
"Non-existent tag should not be applied to node")
t.Logf("Test 1.2: Node registered with tags: %v (non-existent tag correctly rejected)", nodes[0].GetValidTags())
t.Logf("Test 1.2: Node registered with tags: %v (non-existent tag correctly rejected)", nodes[0].GetTags())
}
}, 10*time.Second, 500*time.Millisecond, "checking node registration result")
}
@ -1442,9 +1442,9 @@ func TestTagsUserLoginUnownedTagAtRegistration(t *testing.T) {
t.Logf("Test 1.3 PASS: Registration rejected - no nodes registered")
} else {
// If a node was registered, it should NOT have the unowned tag
assert.NotContains(c, nodes[0].GetValidTags(), "tag:valid-unowned",
assert.NotContains(c, nodes[0].GetTags(), "tag:valid-unowned",
"Unowned tag should not be applied to node (tag:valid-unowned is owned by other-user)")
t.Logf("Test 1.3: Node registered with tags: %v (unowned tag correctly rejected)", nodes[0].GetValidTags())
t.Logf("Test 1.3: Node registered with tags: %v (unowned tag correctly rejected)", nodes[0].GetTags())
}
}, 10*time.Second, 500*time.Millisecond, "checking node registration result")
}
@ -1509,7 +1509,7 @@ func TestTagsUserLoginAddTagViaCLIReauth(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("Initial tags: %v", nodes[0].GetValidTags())
t.Logf("Initial tags: %v", nodes[0].GetTags())
}
}, 30*time.Second, 500*time.Millisecond, "checking initial tags")
@ -1530,12 +1530,12 @@ func TestTagsUserLoginAddTagViaCLIReauth(t *testing.T) {
assert.NoError(c, err)
if len(nodes) >= 1 {
t.Logf("Test 1.4: After CLI, tags are: %v", nodes[0].GetValidTags())
t.Logf("Test 1.4: After CLI, tags are: %v", nodes[0].GetTags())
if tagsEqual(nodes[0].GetValidTags(), []string{"tag:valid-owned", "tag:second"}) {
if tagsEqual(nodes[0].GetTags(), []string{"tag:valid-owned", "tag:second"}) {
t.Logf("Test 1.4 PASS: Both tags present after reauth")
} else {
t.Logf("Test 1.4: Tags are %v (may require manual reauth completion)", nodes[0].GetValidTags())
t.Logf("Test 1.4: Tags are %v (may require manual reauth completion)", nodes[0].GetTags())
}
}
}, 30*time.Second, 500*time.Millisecond, "checking tags after CLI")
@ -1601,7 +1601,7 @@ func TestTagsUserLoginRemoveTagViaCLIReauth(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("Initial tags: %v", nodes[0].GetValidTags())
t.Logf("Initial tags: %v", nodes[0].GetTags())
}
}, 30*time.Second, 500*time.Millisecond, "checking initial tags")
@ -1622,9 +1622,9 @@ func TestTagsUserLoginRemoveTagViaCLIReauth(t *testing.T) {
assert.NoError(c, err)
if len(nodes) >= 1 {
t.Logf("Test 1.5: After CLI, tags are: %v", nodes[0].GetValidTags())
t.Logf("Test 1.5: After CLI, tags are: %v", nodes[0].GetTags())
if tagsEqual(nodes[0].GetValidTags(), []string{"tag:valid-owned"}) {
if tagsEqual(nodes[0].GetTags(), []string{"tag:valid-owned"}) {
t.Logf("Test 1.5 PASS: Only one tag after removal")
}
}
@ -1697,7 +1697,7 @@ func TestTagsUserLoginCLINoOpAfterAdminAssignment(t *testing.T) {
if len(nodes) == 1 {
nodeID = nodes[0].GetId()
t.Logf("Step 1: Node %d registered with tags: %v", nodeID, nodes[0].GetValidTags())
t.Logf("Step 1: Node %d registered with tags: %v", nodeID, nodes[0].GetTags())
}
}, 30*time.Second, 500*time.Millisecond, "waiting for initial registration")
@ -1710,7 +1710,7 @@ func TestTagsUserLoginCLINoOpAfterAdminAssignment(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("Step 2: After admin assignment, tags: %v", nodes[0].GetValidTags())
t.Logf("Step 2: After admin assignment, tags: %v", nodes[0].GetTags())
assertNodeHasTagsWithCollect(c, nodes[0], []string{"tag:second"})
}
}, 10*time.Second, 500*time.Millisecond, "verifying admin assignment")
@ -1731,7 +1731,7 @@ func TestTagsUserLoginCLINoOpAfterAdminAssignment(t *testing.T) {
assert.Len(c, nodes, 1, "Should have exactly 1 node")
if len(nodes) == 1 {
t.Logf("Step 3: After CLI, tags are: %v", nodes[0].GetValidTags())
t.Logf("Step 3: After CLI, tags are: %v", nodes[0].GetTags())
assertNodeHasTagsWithCollect(c, nodes[0], []string{"tag:second"})
}
}, 10*time.Second, 500*time.Millisecond, "admin tags should be preserved - CLI advertise-tags should be no-op")
@ -1816,7 +1816,7 @@ func TestTagsUserLoginCLICannotRemoveAdminTags(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("After admin assignment, tags: %v", nodes[0].GetValidTags())
t.Logf("After admin assignment, tags: %v", nodes[0].GetTags())
assertNodeHasTagsWithCollect(c, nodes[0], []string{"tag:valid-owned", "tag:second"})
}
}, 10*time.Second, 500*time.Millisecond, "verifying admin assignment")
@ -1837,7 +1837,7 @@ func TestTagsUserLoginCLICannotRemoveAdminTags(t *testing.T) {
assert.Len(c, nodes, 1, "Should have exactly 1 node")
if len(nodes) == 1 {
t.Logf("Test 1.7: After CLI, tags are: %v", nodes[0].GetValidTags())
t.Logf("Test 1.7: After CLI, tags are: %v", nodes[0].GetTags())
assertNodeHasTagsWithCollect(c, nodes[0], []string{"tag:valid-owned", "tag:second"})
}
}, 10*time.Second, 500*time.Millisecond, "admin tags should be preserved - CLI cannot remove them")
@ -1912,7 +1912,7 @@ func TestTagsAuthKeyWithTagRequestNonExistentTag(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetValidTags())
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetTags())
}
}, 10*time.Second, 500*time.Millisecond, "checking node state")
@ -1983,7 +1983,7 @@ func TestTagsAuthKeyWithTagRequestUnownedTag(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetValidTags())
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetTags())
}
}, 10*time.Second, 500*time.Millisecond, "checking node state")
@ -2058,7 +2058,7 @@ func TestTagsAuthKeyWithoutTagRequestNonExistentTag(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetValidTags())
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetTags())
}
}, 10*time.Second, 500*time.Millisecond, "checking node state")
@ -2129,7 +2129,7 @@ func TestTagsAuthKeyWithoutTagRequestUnownedTag(t *testing.T) {
assert.NoError(c, err)
if len(nodes) == 1 {
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetValidTags())
t.Logf("Node registered with tags: %v (expected rejection)", nodes[0].GetTags())
}
}, 10*time.Second, 500*time.Millisecond, "checking node state")
@ -2202,7 +2202,7 @@ func TestTagsAdminAPICannotSetNonExistentTag(t *testing.T) {
if len(nodes) == 1 {
nodeID = nodes[0].GetId()
t.Logf("Node %d registered with tags: %v", nodeID, nodes[0].GetValidTags())
t.Logf("Node %d registered with tags: %v", nodeID, nodes[0].GetTags())
}
}, 30*time.Second, 500*time.Millisecond, "waiting for registration")
@ -2275,7 +2275,7 @@ func TestTagsAdminAPICanSetUnownedTag(t *testing.T) {
if len(nodes) == 1 {
nodeID = nodes[0].GetId()
t.Logf("Node %d registered with tags: %v", nodeID, nodes[0].GetValidTags())
t.Logf("Node %d registered with tags: %v", nodeID, nodes[0].GetTags())
}
}, 30*time.Second, 500*time.Millisecond, "waiting for registration")
@ -2359,7 +2359,7 @@ func TestTagsAdminAPICannotRemoveAllTags(t *testing.T) {
if len(nodes) == 1 {
nodeID = nodes[0].GetId()
t.Logf("Node %d registered with tags: %v", nodeID, nodes[0].GetValidTags())
t.Logf("Node %d registered with tags: %v", nodeID, nodes[0].GetTags())
}
}, 30*time.Second, 500*time.Millisecond, "waiting for registration")
@ -2442,7 +2442,7 @@ func TestTagsAdminAPICannotSetInvalidFormat(t *testing.T) {
if len(nodes) == 1 {
nodeID = nodes[0].GetId()
t.Logf("Node %d registered with tags: %v", nodeID, nodes[0].GetValidTags())
t.Logf("Node %d registered with tags: %v", nodeID, nodes[0].GetTags())
}
}, 30*time.Second, 500*time.Millisecond, "waiting for registration")