@@ -55,6 +55,13 @@ type FatalNodeRoachtest struct {
5555 FatalLogs string
5656}
5757
58+ // NodeToIpMappingRoachtest contains the node to ip mapping from a roachtest
59+ // cluster
60+ type NodeToIpMappingRoachtest struct {
61+ Message ,
62+ NodeToIpMapping string
63+ }
64+
5865// A CondensedMessage is a test log output garnished with useful helper methods
5966// that extract concise information for seamless debugging.
6067type CondensedMessage string
@@ -67,7 +74,16 @@ var fatalRE = regexp.MustCompile(`(?ms)(^F\d{6}.*?\n)(goroutine \d+.*?\n)\n`)
6774var crasherRE = regexp .MustCompile (`(?s)( *rsg_test.go:\d{3}: Crash detected:.*?\n)(.*?;\n)` )
6875var reproRE = regexp .MustCompile (`(?s)( *rsg_test.go:\d{3}: To reproduce, use schema:)` )
6976
70- var roachtestNodeFatalRE = regexp .MustCompile (`(?ms)\A(.*?\n)((?:^F\d{6}\b[^\n]*(?:\n|$))+)` )
77+ var nodeFatalRoachtestRE = regexp .MustCompile (`(?ms)\A(.*?\n)((?:^F\d{6}\b[^\n]*(?:\n|$))+)` )
78+
79+ // nodeToIpRoachtestRE matches an entire Markdown table block
80+ // - including header, separator, and data rows:
81+ // - handles an arbitrary number of columns
82+ //
83+ // | Node | Public IP | Private IP |
84+ // | --- | --- | --- |
85+ // | node-0001 | 1.1.1.0 | 1.1.1.1 |
86+ var nodeToIpRoachtestRE = regexp .MustCompile (`(?m)^[[:space:]]*\|(?:[^|\n]*\|)+[[:space:]]*\n^[[:space:]]*\|(?:[[:space:]]*:?-{3,}:?[[:space:]]*\|)+[[:space:]]*\n(?:^[[:space:]]*\|(?:[^|\n]*\|)+[[:space:]]*(?:\n|$))+` )
7187
7288// FatalOrPanic constructs a FatalOrPanic. If no fatal or panic occurred in the
7389// test, ok=false is returned.
@@ -112,17 +128,35 @@ func (s CondensedMessage) RSGCrash(lineLimit int) (c RSGCrash, ok bool) {
112128// ok=false is returned
113129func (s CondensedMessage ) FatalNodeRoachtest () (fnr FatalNodeRoachtest , ok bool ) {
114130 ss := string (s )
115- if matches := roachtestNodeFatalRE .FindStringSubmatchIndex (ss ); matches != nil {
131+ if matches := nodeFatalRoachtestRE .FindStringSubmatchIndex (ss ); matches != nil {
116132 if len (matches ) != 6 {
117133 return FatalNodeRoachtest {}, false
118134 }
119- fnr .Message = ss [matches [2 ] : matches [3 ]- 1 ]
135+ msg := ss [matches [2 ]:matches [3 ]]
136+ fnr .Message = strings .TrimRight (msg , "\n " )
120137 fnr .FatalLogs = ss [matches [4 ]:matches [5 ]]
121138 return fnr , true
122139 }
123140 return FatalNodeRoachtest {}, false
124141}
125142
143+ // NodeToIpMappingRoachtest constructs a NodeToIpMappingRoachtest which is
144+ // used to construct an issue that contains cluster information
145+ func (s CondensedMessage ) NodeToIpMappingRoachtest () (nodeIpMap NodeToIpMappingRoachtest , ok bool ) {
146+ ss := string (s )
147+ if matches := nodeToIpRoachtestRE .FindStringSubmatchIndex (ss ); matches != nil {
148+ if len (matches ) != 2 {
149+ // only expecting a single match
150+ return NodeToIpMappingRoachtest {}, false
151+ }
152+ msg := ss [0 :matches [0 ]]
153+ nodeIpMap .Message = strings .TrimRight (msg , "\n " )
154+ nodeIpMap .NodeToIpMapping = ss [matches [0 ]:matches [1 ]]
155+ return nodeIpMap , true
156+ }
157+ return NodeToIpMappingRoachtest {}, false
158+ }
159+
126160// String calls .Digest(30).
127161func (s CondensedMessage ) String () string {
128162 return s .Digest (30 )
0 commit comments