@@ -17,55 +17,67 @@ import (
17
17
"encoding/json"
18
18
"fmt"
19
19
"io"
20
+ "net/url"
20
21
"os"
22
+ "sort"
21
23
"time"
22
24
23
25
"github.com/AlecAivazis/survey/v2"
24
26
"github.com/choria-io/fisk"
25
27
"github.com/dustin/go-humanize"
26
28
"github.com/fatih/color"
27
29
"github.com/nats-io/nats-server/v2/server"
28
- "github.com/nats-io/natscli/columns"
29
30
ab "github.com/synadia-io/jwt-auth-builder.go"
30
31
)
31
32
32
33
type authAccountCommand struct {
33
34
accountName string
34
- operatorName string
35
- expiry time. Duration
35
+ advertise bool
36
+ advertiseIsSet bool
36
37
bearerAllowed bool
37
- maxSubs int64
38
- maxConns int64
39
- maxPayloadString string
40
- maxPayload int64
41
- maxLeafnodes int64
42
- maxImports int64
43
- maxExports int64
44
- jetStream bool
38
+ connTypes []string
45
39
defaults bool
40
+ description string
41
+ descriptionIsSet bool
42
+ expiry time.Duration
43
+ exportName string
44
+ force bool
45
+ isService bool
46
+ jetStream bool
47
+ listNames bool
48
+ locale string
46
49
maxAckPending int64
47
- storeMaxString string
48
- storeMax int64
49
- storeMaxStreamString string
50
- storeMaxStream int64
51
- memMaxString string
50
+ maxConns int64
51
+ maxConsumers int64
52
+ maxExports int64
53
+ maxImports int64
54
+ maxLeafnodes int64
55
+ maxPayload int64
56
+ maxPayloadString string
57
+ maxStreams int64
58
+ maxSubs int64
52
59
memMax int64
53
- memMaxStreamString string
54
60
memMaxStream int64
55
- streamSizeRequired bool
56
- maxStreams int64
57
- maxConsumers int64
58
- listNames bool
59
- force bool
60
- skRole string
61
- locale string
62
- connTypes []string
61
+ memMaxStreamString string
62
+ memMaxString string
63
+ operatorName string
64
+ output string
63
65
pubAllow []string
64
66
pubDeny []string
67
+ showJWT bool
68
+ skRole string
69
+ storeMax int64
70
+ storeMaxStream int64
71
+ storeMaxStreamString string
72
+ storeMaxString string
73
+ streamSizeRequired bool
65
74
subAllow []string
66
75
subDeny []string
67
- showJWT bool
68
- output string
76
+ subject string
77
+ tokenPosition uint
78
+ tokenRequired bool
79
+ tokenRequiredIsSet bool
80
+ url * url.URL
69
81
}
70
82
71
83
func configureAuthAccountCommand (auth commandHost ) {
@@ -108,29 +120,71 @@ func configureAuthAccountCommand(auth commandHost) {
108
120
info .Arg ("name" , "Account to view" ).StringVar (& c .accountName )
109
121
info .Flag ("operator" , "Operator hosting the account" ).StringVar (& c .operatorName )
110
122
111
- edit := acct .Command ("edit" , "Edit account settings" ).Alias ("update" ).Action (c .editAction )
123
+ edit := acct .Command ("edit" , "Edit Account settings" ).Alias ("update" ).Action (c .editAction )
112
124
edit .Arg ("name" , "Unique name for this Account" ).StringVar (& c .accountName )
113
125
edit .Flag ("operator" , "Operator to add the account to" ).StringVar (& c .operatorName )
114
126
addCreateFlags (edit , false )
115
127
116
- ls := acct .Command ("ls" , "List accounts " ).Action (c .lsAction )
128
+ ls := acct .Command ("ls" , "List Accounts " ).Action (c .lsAction )
117
129
ls .Arg ("operator" , "Operator to act on" ).StringVar (& c .operatorName )
118
130
ls .Flag ("names" , "Show just the Account names" ).UnNegatableBoolVar (& c .listNames )
119
131
120
- rm := acct .Command ("rm" , "Removes an account " ).Action (c .rmAction )
132
+ rm := acct .Command ("rm" , "Removes an Account " ).Action (c .rmAction )
121
133
rm .Arg ("name" , "Account to view" ).StringVar (& c .accountName )
122
- rm .Flag ("operator" , "Operator hosting the account " ).StringVar (& c .operatorName )
134
+ rm .Flag ("operator" , "Operator hosting the Account " ).StringVar (& c .operatorName )
123
135
rm .Flag ("force" , "Removes without prompting" ).Short ('f' ).UnNegatableBoolVar (& c .force )
124
136
125
- push := acct .Command ("push" , "Push the account to the NATS Resolver" ).Action (c .pushAction )
137
+ push := acct .Command ("push" , "Push the Account to the NATS Resolver" ).Action (c .pushAction )
126
138
push .Arg ("name" , "Account to act on" ).StringVar (& c .accountName )
127
139
push .Flag ("operator" , "Operator to act on" ).StringVar (& c .operatorName )
128
140
push .Flag ("show" , "Show the Account JWT before pushing" ).UnNegatableBoolVar (& c .showJWT )
129
141
130
- query := acct .Command ("query" , "Pull the account from the NATS Resolver and view it" ).Alias ("pull" ).Action (c .queryAction )
142
+ query := acct .Command ("query" , "Pull the Account from the NATS Resolver and view it" ).Alias ("pull" ).Action (c .queryAction )
131
143
query .Arg ("name" , "Account to act on" ).Required ().StringVar (& c .accountName )
132
144
query .Arg ("output" , "Saves the JWT to a file" ).StringVar (& c .output )
133
145
146
+ // imports := acct.Command("imports", "Manage account Imports").Alias("i").Alias("imp").Alias("import")
147
+ // imports.Command("ls", "List Imports").Alias("list").Action(c.importLsAction)
148
+
149
+ exports := acct .Command ("exports" , "Manage account Exports" ).Alias ("e" ).Alias ("exp" ).Alias ("export" )
150
+
151
+ expAdd := exports .Command ("add" , "Adds an Export" ).Alias ("new" ).Alias ("a" ).Alias ("n" ).Action (c .exportAddAction )
152
+ expAdd .Arg ("name" , "A unique name for the Export" ).Required ().StringVar (& c .exportName )
153
+ expAdd .Arg ("subject" , "The Subject to export" ).Required ().StringVar (& c .subject )
154
+ expAdd .Arg ("account" , "Account to act on" ).StringVar (& c .accountName )
155
+ expAdd .Flag ("operator" , "Operator hosting the account" ).StringVar (& c .operatorName )
156
+ expAdd .Flag ("activation" , "Requires an activation token" ).UnNegatableBoolVar (& c .tokenRequired )
157
+ expAdd .Flag ("description" , "Friendly description" ).StringVar (& c .description )
158
+ expAdd .Flag ("url" , "Sets a URL for further information" ).URLVar (& c .url )
159
+ expAdd .Flag ("token-position" , "The position to use for the Account name" ).UintVar (& c .tokenPosition )
160
+ expAdd .Flag ("advertise" , "Advertise the Export" ).UnNegatableBoolVar (& c .advertise )
161
+ expAdd .Flag ("service" , "Sets the Export to be a Service rather than a Stream" ).UnNegatableBoolVar (& c .isService )
162
+
163
+ expInfo := exports .Command ("info" , "Show information for an Export" ).Alias ("i" ).Alias ("show" ).Alias ("view" ).Action (c .exportInfoAction )
164
+ expInfo .Arg ("subject" , "Export to view by subject" ).StringVar (& c .subject )
165
+ expInfo .Arg ("account" , "Account to act on" ).StringVar (& c .accountName )
166
+ expInfo .Flag ("operator" , "Operator hosting the account" ).StringVar (& c .operatorName )
167
+
168
+ expEdit := exports .Command ("edit" , "Edits an Export" ).Alias ("update" ).Action (c .exportEditAction )
169
+ expEdit .Arg ("subject" , "The Subject to export" ).Required ().StringVar (& c .subject )
170
+ expEdit .Arg ("account" , "Account to act on" ).StringVar (& c .accountName )
171
+ expEdit .Flag ("operator" , "Operator hosting the account" ).StringVar (& c .operatorName )
172
+ expEdit .Flag ("activation" , "Requires an activation token" ).IsSetByUser (& c .tokenRequiredIsSet ).BoolVar (& c .tokenRequired )
173
+ expEdit .Flag ("description" , "Friendly description" ).IsSetByUser (& c .descriptionIsSet ).StringVar (& c .description )
174
+ expEdit .Flag ("url" , "Sets a URL for further information" ).URLVar (& c .url )
175
+ expEdit .Flag ("token-position" , "The position to use for the Account name" ).UintVar (& c .tokenPosition )
176
+ expEdit .Flag ("advertise" , "Advertise the Export" ).IsSetByUser (& c .advertiseIsSet ).BoolVar (& c .advertise )
177
+
178
+ expLs := exports .Command ("ls" , "List Exports" ).Alias ("list" ).Action (c .exportLsAction )
179
+ expLs .Arg ("account" , "Account to act on" ).StringVar (& c .accountName )
180
+ expLs .Flag ("operator" , "Operator to act on" ).StringVar (& c .operatorName )
181
+
182
+ expRm := exports .Command ("rm" , "Removes an Export" ).Action (c .exportRmAction )
183
+ expRm .Arg ("subject" , "Export to remove by subject" ).StringVar (& c .subject )
184
+ expRm .Arg ("account" , "Account to act on" ).StringVar (& c .accountName )
185
+ expRm .Flag ("operator" , "Operator hosting the account" ).StringVar (& c .operatorName )
186
+ expRm .Flag ("force" , "Removes without prompting" ).Short ('f' ).UnNegatableBoolVar (& c .force )
187
+
134
188
sk := acct .Command ("keys" , "Manage Scoped Signing Keys" ).Alias ("sk" ).Alias ("s" )
135
189
136
190
skadd := sk .Command ("add" , "Adds a signing key" ).Alias ("new" ).Alias ("a" ).Alias ("n" ).Action (c .skAddAction )
@@ -147,12 +201,12 @@ func configureAuthAccountCommand(auth commandHost) {
147
201
skadd .Flag ("sub-allow" , "Sets subjects where subscribing is allowed" ).StringsVar (& c .subAllow )
148
202
skadd .Flag ("sub-deny" , "Sets subjects where subscribing is allowed" ).StringsVar (& c .subDeny )
149
203
150
- skInfo := sk .Command ("info" , "Show information for a Scoped Signing Key" ).Action (c .skInfoAction )
204
+ skInfo := sk .Command ("info" , "Show information for a Scoped Signing Key" ).Alias ( "i" ). Alias ( "show" ). Alias ( "view" ). Action (c .skInfoAction )
151
205
skInfo .Arg ("name" , "Account to view" ).StringVar (& c .accountName )
152
206
skInfo .Arg ("key" , "The role or key to view" ).StringVar (& c .skRole )
153
207
skInfo .Flag ("operator" , "Operator to act on" ).StringVar (& c .operatorName )
154
208
155
- skls := sk .Command ("list " , "List Scoped Signing Keys" ).Alias ("ls " ).Action (c .skListAction )
209
+ skls := sk .Command ("ls " , "List Scoped Signing Keys" ).Alias ("list " ).Action (c .skListAction )
156
210
skls .Arg ("name" , "Account to act on" ).StringVar (& c .accountName )
157
211
skls .Flag ("operator" , "Operator to act on" ).StringVar (& c .operatorName )
158
212
@@ -163,6 +217,308 @@ func configureAuthAccountCommand(auth commandHost) {
163
217
skrm .Flag ("force" , "Removes without prompting" ).Short ('f' ).UnNegatableBoolVar (& c .force )
164
218
}
165
219
220
+ func (c * authAccountCommand ) findExport (account ab.Account , subject string ) ab.Export {
221
+ for _ , exp := range account .Exports ().Streams ().List () {
222
+ if exp .Subject () == subject {
223
+ return exp
224
+ }
225
+ }
226
+ for _ , exp := range account .Exports ().Services ().List () {
227
+ if exp .Subject () == subject {
228
+ return exp
229
+ }
230
+ }
231
+
232
+ return nil
233
+ }
234
+
235
+ func (c * authAccountCommand ) exportBySubject (acct ab.Account ) []ab.Export {
236
+ var ret []ab.Export
237
+
238
+ for _ , svc := range acct .Exports ().Streams ().List () {
239
+ ret = append (ret , svc )
240
+ }
241
+ for _ , svc := range acct .Exports ().Services ().List () {
242
+ ret = append (ret , svc )
243
+ }
244
+
245
+ sort .Slice (ret , func (i , j int ) bool {
246
+ return ret [i ].Subject () < ret [j ].Subject ()
247
+ })
248
+
249
+ return ret
250
+ }
251
+
252
+ func (c * authAccountCommand ) exportSubjects (export ab.Exports ) []string {
253
+ var known []string
254
+ for _ , exp := range export .Services ().List () {
255
+ known = append (known , exp .Subject ())
256
+ }
257
+ for _ , exp := range export .Streams ().List () {
258
+ known = append (known , exp .Subject ())
259
+ }
260
+
261
+ sort .Strings (known )
262
+
263
+ return known
264
+ }
265
+
266
+ func (c * authAccountCommand ) fShowExport (w io.Writer , exp ab.Export ) error {
267
+ out , err := c .showExport (exp )
268
+ if err != nil {
269
+ return err
270
+ }
271
+
272
+ _ , err = fmt .Fprintln (w , out )
273
+ return err
274
+ }
275
+
276
+ func (c * authAccountCommand ) showExport (exp ab.Export ) (string , error ) {
277
+ cols := newColumns ("Export info for %s exporting %s" , exp .Name (), exp .Subject ())
278
+
279
+ cols .AddSectionTitle ("Configuration" )
280
+ cols .AddRow ("Name" , exp .Name ())
281
+ cols .AddRowIfNotEmpty ("Description" , exp .Description ())
282
+ cols .AddRowIfNotEmpty ("Info" , exp .InfoURL ())
283
+ cols .AddRow ("Subject" , exp .Subject ())
284
+ cols .AddRow ("Activation Required" , exp .TokenRequired ())
285
+ cols .AddRow ("Account Token Position" , exp .AccountTokenPosition ())
286
+ cols .AddRow ("Advertised" , exp .IsAdvertised ())
287
+
288
+ cols .AddSectionTitle ("Revocations" )
289
+
290
+ if len (exp .Revocations ().List ()) > 0 {
291
+ for _ , rev := range exp .Revocations ().List () {
292
+ cols .AddRow (rev .At ().Format (time .RFC3339 ), rev .PublicKey ())
293
+ }
294
+ } else {
295
+ cols .Println ()
296
+ cols .Println ("No revocations found" )
297
+ }
298
+
299
+ return cols .Render ()
300
+ }
301
+
302
+ func (c * authAccountCommand ) exportRmAction (_ * fisk.ParseContext ) error {
303
+ auth , _ , acct , err := c .selectAccount (true )
304
+ if err != nil {
305
+ return err
306
+ }
307
+
308
+ exp := c .findExport (acct , c .subject )
309
+ if exp == nil {
310
+ return fmt .Errorf ("subject %q is not exported" , c .subject )
311
+ }
312
+
313
+ if ! c .force {
314
+ ok , err := askConfirmation (fmt .Sprintf ("Really remove the %s Export" , exp .Subject ()), false )
315
+ if err != nil {
316
+ return err
317
+ }
318
+
319
+ if ! ok {
320
+ return nil
321
+ }
322
+ }
323
+
324
+ switch exp .(type ) {
325
+ case ab.StreamExport :
326
+ _ , err = acct .Exports ().Streams ().Delete (c .subject )
327
+ fmt .Printf ("Removing Stream Export for subject %q\n " , c .subject )
328
+ case ab.ServiceExport :
329
+ _ , err = acct .Exports ().Services ().Delete (c .subject )
330
+ fmt .Printf ("Removing Service Export for subject %q\n " , c .subject )
331
+ }
332
+ if err != nil {
333
+ return err
334
+ }
335
+
336
+ return auth .Commit ()
337
+ }
338
+
339
+ func (c * authAccountCommand ) exportInfoAction (_ * fisk.ParseContext ) error {
340
+ _ , _ , acct , err := c .selectAccount (true )
341
+ if err != nil {
342
+ return err
343
+ }
344
+
345
+ if c .subject == "" {
346
+ known := c .exportSubjects (acct .Exports ())
347
+
348
+ if len (known ) == 0 {
349
+ return fmt .Errorf ("no exports defined" )
350
+ }
351
+
352
+ err = askOne (& survey.Select {
353
+ Message : "Select an Export" ,
354
+ Options : known ,
355
+ PageSize : selectPageSize (len (known )),
356
+ }, & c .subject )
357
+ if err != nil {
358
+ return err
359
+ }
360
+ }
361
+
362
+ if c .subject == "" {
363
+ return fmt .Errorf ("subject is required" )
364
+ }
365
+
366
+ exp := c .findExport (acct , c .subject )
367
+ if exp == nil {
368
+ return fmt .Errorf ("unknown export" )
369
+ }
370
+
371
+ return c .fShowExport (os .Stdout , exp )
372
+ }
373
+
374
+ func (c * authAccountCommand ) exportEditAction (_ * fisk.ParseContext ) error {
375
+ auth , _ , acct , err := c .selectAccount (true )
376
+ if err != nil {
377
+ return err
378
+ }
379
+
380
+ exp := c .findExport (acct , c .subject )
381
+ if exp == nil {
382
+ return fmt .Errorf ("export for subject %q not found" , c .subject )
383
+ }
384
+
385
+ if c .tokenRequiredIsSet {
386
+ err = exp .SetTokenRequired (c .tokenRequired )
387
+ if err != nil {
388
+ return err
389
+ }
390
+ }
391
+
392
+ if c .url != nil {
393
+ err = exp .SetInfoURL (c .url .String ())
394
+ if err != nil {
395
+ return err
396
+ }
397
+ }
398
+
399
+ if c .descriptionIsSet {
400
+ err = exp .SetDescription (c .description )
401
+ if err != nil {
402
+ return err
403
+ }
404
+ }
405
+
406
+ if c .tokenPosition > 0 {
407
+ err = exp .SetAccountTokenPosition (c .tokenPosition )
408
+ if err != nil {
409
+ return err
410
+ }
411
+ }
412
+
413
+ if c .advertiseIsSet {
414
+ err = exp .SetAdvertised (c .advertise )
415
+ if err != nil {
416
+ return err
417
+ }
418
+ }
419
+
420
+ err = auth .Commit ()
421
+ if err != nil {
422
+ return err
423
+ }
424
+
425
+ return c .fShowExport (os .Stdout , exp )
426
+ }
427
+
428
+ func (c * authAccountCommand ) exportAddAction (_ * fisk.ParseContext ) error {
429
+ auth , _ , acct , err := c .selectAccount (true )
430
+ if err != nil {
431
+ return err
432
+ }
433
+
434
+ var exp ab.Export
435
+
436
+ if c .isService {
437
+ exp , err = ab .NewServiceExport (c .exportName , c .subject )
438
+ if err != nil {
439
+ return err
440
+ }
441
+ } else {
442
+ exp , err = ab .NewStreamExport (c .exportName , c .subject )
443
+ if err != nil {
444
+ return err
445
+ }
446
+ }
447
+
448
+ err = exp .SetAccountTokenPosition (c .tokenPosition )
449
+ if err != nil {
450
+ return err
451
+ }
452
+ err = exp .SetAdvertised (c .advertise )
453
+ if err != nil {
454
+ return err
455
+ }
456
+ err = exp .SetDescription (c .description )
457
+ if err != nil {
458
+ return err
459
+ }
460
+ if c .url != nil {
461
+ err = exp .SetInfoURL (c .url .String ())
462
+ if err != nil {
463
+ return err
464
+ }
465
+ }
466
+ err = exp .SetTokenRequired (c .tokenRequired )
467
+ if err != nil {
468
+ return err
469
+ }
470
+
471
+ if c .isService {
472
+ err = acct .Exports ().Services ().AddWithConfig (exp .(ab.ServiceExport ))
473
+ if err != nil {
474
+ return err
475
+ }
476
+ } else {
477
+ err = acct .Exports ().Streams ().AddWithConfig (exp .(ab.StreamExport ))
478
+ if err != nil {
479
+ return err
480
+ }
481
+ }
482
+
483
+ err = auth .Commit ()
484
+ if err != nil {
485
+ return err
486
+ }
487
+
488
+ return c .fShowExport (os .Stdout , exp )
489
+ }
490
+
491
+ func (c * authAccountCommand ) exportLsAction (_ * fisk.ParseContext ) error {
492
+ _ , _ , acct , err := c .selectAccount (true )
493
+ if err != nil {
494
+ return err
495
+ }
496
+
497
+ services := acct .Exports ().Services ().List ()
498
+ streams := acct .Exports ().Streams ().List ()
499
+
500
+ if len (services ) == 0 && len (streams ) == 0 {
501
+ fmt .Println ("No Exports defined" )
502
+ return nil
503
+ }
504
+
505
+ exports := c .exportBySubject (acct )
506
+
507
+ tbl := newTableWriter ("Exports for account %s" , acct .Name ())
508
+ tbl .AddHeaders ("Name" , "Kind" , "Subject" , "Activation Required" , "Advertised" , "Token Position" , "Revocations" )
509
+ for _ , e := range exports {
510
+ switch exp := e .(type ) {
511
+ case ab.StreamExport :
512
+ tbl .AddRow (exp .Name (), "Stream" , exp .Subject (), exp .TokenRequired (), exp .IsAdvertised (), exp .AccountTokenPosition (), f (len (exp .Revocations ().List ())))
513
+ case ab.ServiceExport :
514
+ tbl .AddRow (exp .Name (), "Service" , exp .Subject (), exp .TokenRequired (), exp .IsAdvertised (), exp .AccountTokenPosition (), f (len (exp .Revocations ().List ())))
515
+ }
516
+ }
517
+ fmt .Println (tbl .Render ())
518
+
519
+ return nil
520
+ }
521
+
166
522
func (c * authAccountCommand ) selectAccount (pick bool ) (* ab.AuthImpl , ab.Operator , ab.Account , error ) {
167
523
auth , oper , acct , err := selectOperatorAccount (c .operatorName , c .accountName , pick )
168
524
if err != nil {
@@ -788,6 +1144,8 @@ func (c *authAccountCommand) showAccount(operator ab.Operator, acct ab.Account)
788
1144
js := limits .JetStream ()
789
1145
serviceExports := len (acct .Exports ().Services ().List ())
790
1146
streamExports := len (acct .Exports ().Streams ().List ())
1147
+ serviceImports := len (acct .Imports ().Services ().List ())
1148
+ streamImports := len (acct .Imports ().Streams ().List ())
791
1149
792
1150
cols := newColumns ("Account %s (%s)" , acct .Name (), acct .Subject ())
793
1151
@@ -804,6 +1162,8 @@ func (c *authAccountCommand) showAccount(operator ab.Operator, acct ab.Account)
804
1162
cols .AddRow ("Revocations" , len (acct .Revocations ().List ()))
805
1163
cols .AddRow ("Service Exports" , serviceExports )
806
1164
cols .AddRow ("Stream Exports" , streamExports )
1165
+ cols .AddRow ("Service Imports" , serviceImports )
1166
+ cols .AddRow ("Stream Imports" , streamImports )
807
1167
808
1168
cols .AddSectionTitle ("Limits" )
809
1169
cols .AddRow ("Bearer Tokens Allowed" , ! limits .DisallowBearerTokens ())
@@ -817,51 +1177,6 @@ func (c *authAccountCommand) showAccount(operator ab.Operator, acct ab.Account)
817
1177
cols .AddRowUnlimited ("Imports" , limits .MaxImports (), - 1 )
818
1178
cols .AddRowUnlimited ("Exports" , limits .MaxExports (), - 1 )
819
1179
820
- if serviceExports > 0 || streamExports > 0 {
821
- renderExport := func (cols * columns.Writer , export ab.Export ) {
822
- revocations := len (export .Revocations ().List ())
823
- cols .AddRowIfNotEmpty ("Name" , export .Name ())
824
- cols .AddRowIfNotEmpty ("Description" , export .Description ())
825
- cols .AddRowIfNotEmpty ("Information" , export .InfoURL ())
826
- cols .AddRowIf ("Account Token Position" , export .AccountTokenPosition (), export .AccountTokenPosition () > 0 )
827
- cols .AddRowIf ("Token Required" , export .TokenRequired (), export .TokenRequired ())
828
- cols .AddRowIf ("Revocation" , f (revocations ), revocations > 0 )
829
- }
830
-
831
- cols .AddSectionTitle ("Exports" )
832
- cols .Indent (2 )
833
- if serviceExports > 0 {
834
- cols .AddSectionTitle ("Service Exports" )
835
- for _ , export := range acct .Exports ().Services ().List () {
836
- cols .AddSectionTitle (export .Subject ())
837
- cols .Indent (4 )
838
-
839
- renderExport (cols , export )
840
- if export .Tracing () != nil {
841
- if export .Tracing ().SamplingRate > 0 {
842
- cols .AddRow ("Tracing" , fmt .Sprintf ("%s sampling %d%%" , export .Tracing ().Subject , export .Tracing ().SamplingRate ))
843
- } else {
844
- cols .AddRow ("Tracing" , export .Tracing ().Subject )
845
- }
846
- }
847
- cols .Indent (2 )
848
- }
849
- }
850
-
851
- if streamExports > 0 {
852
- cols .AddSectionTitle ("Stream Exports" )
853
- for _ , export := range acct .Exports ().Streams ().List () {
854
- cols .AddSectionTitle (export .Subject ())
855
- cols .Indent (4 )
856
-
857
- renderExport (cols , export )
858
- cols .Indent (2 )
859
- }
860
- }
861
-
862
- cols .Indent (0 )
863
- }
864
-
865
1180
if js .IsJetStreamEnabled () {
866
1181
cols .Indent (2 )
867
1182
cols .AddSectionTitle ("JetStream Limits" )
0 commit comments