@@ -52,19 +52,18 @@ var (
52
52
cluster string
53
53
colorMode = ColorAuto
54
54
sourcePlatform = migrate .SourcePlatformUnspecified // default to auto-detecting the source platform
55
- doDebug = false
55
+ doDebug = pkg . GetenvBool ( "DEFANG_DEBUG" )
56
56
hasTty = term .IsTerminal () && ! pkg .GetenvBool ("CI" )
57
57
hideUpdate = pkg .GetenvBool ("DEFANG_HIDE_UPDATE" )
58
58
mode = Mode (defangv1 .DeploymentMode_MODE_UNSPECIFIED )
59
59
modelId = os .Getenv ("DEFANG_MODEL_ID" ) // for Pro users only
60
60
nonInteractive = ! hasTty
61
- org string
62
- tenantFlag string
61
+ org = os .Getenv ("DEFANG_ORG" )
63
62
providerID = cliClient .ProviderID (pkg .Getenv ("DEFANG_PROVIDER" , "auto" ))
64
- verbose = false
63
+ verbose = pkg . GetenvBool ( "DEFANG_VERBOSE" )
65
64
)
66
65
67
- func getCluster () string {
66
+ func getOrgCluster () string {
68
67
if org == "" {
69
68
return cluster
70
69
}
@@ -165,12 +164,11 @@ func SetupCommands(ctx context.Context, version string) {
165
164
RootCmd .PersistentFlags ().Var (& colorMode , "color" , fmt .Sprintf (`colorize output; one of %v` , allColorModes ))
166
165
RootCmd .PersistentFlags ().StringVarP (& cluster , "cluster" , "s" , pcluster .DefangFabric , "Defang cluster to connect to" )
167
166
RootCmd .PersistentFlags ().MarkHidden ("cluster" )
168
- RootCmd .PersistentFlags ().StringVar (& org , "org" , os .Getenv ("DEFANG_ORG" ), "override GitHub organization name (tenant)" )
169
- RootCmd .PersistentFlags ().StringVar (& tenantFlag , "tenant" , "" , "select tenant by name" )
167
+ RootCmd .PersistentFlags ().StringVar (& org , "org" , "" , "override organization name (tenant)" )
170
168
RootCmd .PersistentFlags ().VarP (& providerID , "provider" , "P" , fmt .Sprintf (`bring-your-own-cloud provider; one of %v` , cliClient .AllProviders ()))
171
169
// RootCmd.Flag("provider").NoOptDefVal = "auto" NO this will break the "--provider aws"
172
170
RootCmd .PersistentFlags ().BoolVarP (& verbose , "verbose" , "v" , false , "verbose logging" ) // backwards compat: only used by tail
173
- RootCmd .PersistentFlags ().BoolVar (& doDebug , "debug" , pkg . GetenvBool ( "DEFANG_DEBUG" ) , "debug logging for troubleshooting the CLI" )
171
+ RootCmd .PersistentFlags ().BoolVar (& doDebug , "debug" , false , "debug logging for troubleshooting the CLI" )
174
172
RootCmd .PersistentFlags ().BoolVar (& dryrun .DoDryRun , "dry-run" , false , "dry run (don't actually change anything)" )
175
173
RootCmd .PersistentFlags ().BoolVarP (& nonInteractive , "non-interactive" , "T" , ! hasTty , "disable interactive prompts / no TTY" )
176
174
RootCmd .PersistentFlags ().StringP ("project-name" , "p" , "" , "project name" )
@@ -372,19 +370,10 @@ var RootCmd = &cobra.Command{
372
370
}
373
371
}
374
372
375
- // Configure tenant selection based on --tenant flag
376
- if f := cmd .Root ().Flag ("tenant" ); f != nil && f .Changed {
377
- // Highest precedence: explicit --tenant flag
378
- auth .SetSelectedTenantName (tenantFlag )
379
- } else if envTenant := os .Getenv ("DEFANG_TENANT" ); strings .TrimSpace (envTenant ) != "" {
380
- // Next precedence: DEFANG_TENANT environment variable
381
- auth .SetSelectedTenantName (envTenant )
382
- } else {
383
- // Default behavior: auto-select tenant by JWT subject if no explicit name is provided
384
- auth .SetAutoSelectBySub (true )
385
- }
373
+ // Configure tenant selection based on --org flag
374
+ auth .SetSelectedTenantName (org )
386
375
387
- client , err = cli .Connect (ctx , getCluster ())
376
+ client , err = cli .Connect (ctx , getOrgCluster ())
388
377
389
378
if v , err := client .GetVersions (ctx ); err == nil {
390
379
version := cmd .Root ().Version // HACK to avoid circular dependency with RootCmd
@@ -405,20 +394,20 @@ var RootCmd = &cobra.Command{
405
394
if nonInteractive {
406
395
err = client .CheckLoginAndToS (ctx )
407
396
} else {
408
- err = login .InteractiveRequireLoginAndToS (ctx , client , getCluster ())
397
+ err = login .InteractiveRequireLoginAndToS (ctx , client , getOrgCluster ())
409
398
}
410
399
411
400
if err != nil {
412
401
return err
413
402
}
414
403
415
404
// Ensure tenant is resolved post-login as we now have a token
416
- if tok := pcluster .GetExistingToken (getCluster ()); tok != "" {
405
+ if tok := pcluster .GetExistingToken (getOrgCluster ()); tok != "" {
417
406
if err2 := auth .ResolveAndSetTenantFromToken (ctx , tok ); err2 != nil {
418
407
return err2
419
408
}
420
409
// log the tenant name and id
421
- term .Debug ("Selected tenant:" , auth .GetSelectedTenantName (), "(" , auth .GetSelectedTenantID (), ")" )
410
+ term .Debugf ("Selected tenant: %q (%s) " , auth .GetSelectedTenantName (), auth .GetSelectedTenantID ())
422
411
}
423
412
424
413
return nil
@@ -427,63 +416,49 @@ var RootCmd = &cobra.Command{
427
416
428
417
var tenantsCmd = & cobra.Command {
429
418
Use : "tenants" ,
419
+ Aliases : []string {"tenant" , "orgs" , "org" },
430
420
Args : cobra .NoArgs ,
431
421
Annotations : authNeededAnnotation ,
432
422
Short : "List tenants available to the logged-in user" ,
433
423
RunE : func (cmd * cobra.Command , args []string ) error {
434
424
ctx := cmd .Context ()
435
- tok := pcluster .GetExistingToken (getCluster ())
436
- if strings .TrimSpace (tok ) == "" {
437
- return errors .New ("not logged in; run 'defang login'" )
438
- }
439
425
426
+ tok := pcluster .GetExistingToken (getOrgCluster ())
440
427
tenants , err := auth .ListTenantsFromToken (ctx , tok )
441
428
if err != nil {
442
429
return err
443
430
}
444
431
432
+ if len (tenants ) == 0 {
433
+ term .Warn ("No tenants found" )
434
+ return nil
435
+ }
436
+
445
437
// Sort by name for stable output
446
- slices .SortFunc (tenants , func (a , b auth.Tenant ) int {
438
+ slices .SortStableFunc (tenants , func (a , b auth.Tenant ) int {
447
439
return strings .Compare (strings .ToLower (a .Name ), strings .ToLower (b .Name ))
448
440
})
449
441
450
- if len ( tenants ) == 0 {
451
- term . Info ( "No tenants found" )
452
- return nil
453
- }
442
+ printTenants := make ([] struct {
443
+ Active string
444
+ auth. Tenant
445
+ }, len ( tenants ))
454
446
455
447
currentID := auth .GetSelectedTenantID ()
456
448
currentName := auth .GetSelectedTenantName ()
457
-
458
- // Compute longest name for aligned output
459
- maxNameLen := 0
460
- for _ , t := range tenants {
461
- if l := len (t .Name ); l > maxNameLen {
462
- maxNameLen = l
463
- }
464
- }
465
-
466
- for _ , t := range tenants {
449
+ for i , t := range tenants {
450
+ printTenants [i ].Tenant = t
467
451
selected := t .ID == currentID || (currentID == "" && t .Name == currentName && strings .TrimSpace (currentName ) != "" )
468
- marker := "-"
469
452
if selected {
470
- marker = "*" // highlight selected
471
- }
472
-
473
- var line string
474
- if verbose {
475
- line = fmt .Sprintf ("%s %-*s (%s)\n " , marker , maxNameLen , t .Name , t .ID )
476
- } else {
477
- line = fmt .Sprintf ("%s %s\n " , marker , t .Name )
453
+ printTenants [i ].Active = "*" // highlight selected
478
454
}
455
+ }
479
456
480
- if selected {
481
- term .Printc (term .BrightCyan , line )
482
- } else {
483
- term .Printc (term .InfoColor , line )
484
- }
457
+ attrs := []string {"Active" , "Name" }
458
+ if verbose {
459
+ attrs = append (attrs , "ID" )
485
460
}
486
- return nil
461
+ return term . Table ( printTenants , attrs )
487
462
},
488
463
}
489
464
@@ -495,11 +470,11 @@ var loginCmd = &cobra.Command{
495
470
trainingOptOut , _ := cmd .Flags ().GetBool ("training-opt-out" )
496
471
497
472
if nonInteractive {
498
- if err := login .NonInteractiveGitHubLogin (cmd .Context (), client , getCluster ()); err != nil {
473
+ if err := login .NonInteractiveGitHubLogin (cmd .Context (), client , getOrgCluster ()); err != nil {
499
474
return err
500
475
}
501
476
} else {
502
- err := login .InteractiveLogin (cmd .Context (), client , getCluster ())
477
+ err := login .InteractiveLogin (cmd .Context (), client , getOrgCluster ())
503
478
if err != nil {
504
479
return err
505
480
}
@@ -616,7 +591,7 @@ var generateCmd = &cobra.Command{
616
591
Heroku : migrate .NewHerokuClient (),
617
592
ModelID : modelId ,
618
593
Fabric : client ,
619
- Cluster : getCluster (),
594
+ Cluster : getOrgCluster (),
620
595
}
621
596
622
597
sample := ""
@@ -644,7 +619,7 @@ var initCmd = &cobra.Command{
644
619
Heroku : migrate .NewHerokuClient (),
645
620
ModelID : modelId ,
646
621
Fabric : client ,
647
- Cluster : getCluster (),
622
+ Cluster : getOrgCluster (),
648
623
}
649
624
650
625
if len (args ) > 0 {
0 commit comments