@@ -279,6 +279,86 @@ def cluster_health(cluster: ClusterClient):
279
279
click .echo (yaml .safe_dump (cluster .health .model_dump ()))
280
280
281
281
282
+ @cluster .group (cls = SectionedHelpGroup )
283
+ def registry ():
284
+ """Manage container registry configuration"""
285
+
286
+
287
+ @registry .group (cls = SectionedHelpGroup , name = "auth" )
288
+ def registry_auth ():
289
+ """Manage private container registry credentials"""
290
+
291
+
292
+ @registry_auth .command (name = "list" )
293
+ @cluster_client
294
+ def credentials_list (cluster : ClusterClient ):
295
+ """List container registry credentials"""
296
+
297
+ if creds := list (cluster .registry_credentials ):
298
+ click .echo (yaml .safe_dump (creds ))
299
+
300
+ else :
301
+ click .secho ("No registry credentials present in this cluster" , bold = True , fg = "red" )
302
+
303
+
304
+ @registry_auth .command (name = "info" )
305
+ @click .argument ("name" )
306
+ @cluster_client
307
+ def credentials_info (cluster : ClusterClient , name : str ):
308
+ """Show info about registry credentials"""
309
+
310
+ if not (creds := cluster .registry_credentials .get (name )):
311
+ raise click .UsageError (f"Unknown credentials '{ name } '" )
312
+
313
+ click .echo (yaml .safe_dump (creds .model_dump (exclude = {"id" , "name" })))
314
+
315
+
316
+ @registry_auth .command (name = "new" )
317
+ @click .argument ("name" )
318
+ @click .argument ("registry" )
319
+ @cluster_client
320
+ def credentials_new (cluster : ClusterClient , name : str , registry : str ):
321
+ """Add registry private registry credentials. This command will prompt you for a username and
322
+ password.
323
+ """
324
+
325
+ username = click .prompt ("Username" )
326
+ password = click .prompt ("Password" , hide_input = True )
327
+
328
+ creds = cluster .new_credentials (
329
+ name = name , hostname = registry , username = username , password = password
330
+ )
331
+ click .echo (yaml .safe_dump (creds .model_dump (exclude = {"id" })))
332
+
333
+
334
+ @registry_auth .command (name = "update" )
335
+ @click .argument ("name" )
336
+ @click .option ("-r" , "--registry" )
337
+ @cluster_client
338
+ def credentials_update (cluster : ClusterClient , name : str , registry : str | None = None ):
339
+ """Update registry registry credentials"""
340
+ if not (creds := cluster .registry_credentials .get (name )):
341
+ raise click .UsageError (f"Unknown credentials '{ name } '" )
342
+
343
+ username = click .prompt ("Username" )
344
+ password = click .prompt ("Password" , hide_input = True )
345
+
346
+ creds = creds .update (hostname = registry , username = username , password = password )
347
+ click .echo (yaml .safe_dump (creds .model_dump (exclude = {"id" })))
348
+
349
+
350
+ @registry_auth .command (name = "remove" )
351
+ @click .argument ("name" )
352
+ @cluster_client
353
+ def credentials_remove (cluster : ClusterClient , name : str ):
354
+ """Remove a set of registry credentials"""
355
+ if not (creds := cluster .registry_credentials .get (name )):
356
+ raise click .UsageError (f"Unknown credentials '{ name } '" )
357
+
358
+ creds .remove () # NOTE: No confirmation because can only delete if no references exist
359
+ click .secho (f"registry credentials '{ creds .name } ' removed." , fg = "green" , bold = True )
360
+
361
+
282
362
@cluster .group (cls = SectionedHelpGroup )
283
363
def vars ():
284
364
"""Manage groups of environment variables in a CLUSTER"""
@@ -424,6 +504,12 @@ def bots():
424
504
@click .option ("-n" , "--network" , required = True )
425
505
@click .option ("-a" , "--account" )
426
506
@click .option ("-g" , "--group" , "vargroups" , multiple = True )
507
+ @click .option (
508
+ "-r" ,
509
+ "--registry-credentials" ,
510
+ "registry_credentials_name" ,
511
+ help = "registry credentials to use to pull the image" ,
512
+ )
427
513
@click .argument ("name" )
428
514
@cluster_client
429
515
def new_bot (
@@ -432,6 +518,7 @@ def new_bot(
432
518
network : str ,
433
519
account : str | None ,
434
520
vargroups : list [str ],
521
+ registry_credentials_name : str | None ,
435
522
name : str ,
436
523
):
437
524
"""Create a new bot in a CLUSTER with the given configuration"""
@@ -441,17 +528,34 @@ def new_bot(
441
528
442
529
environment = [cluster .variable_groups [vg_name ].get_revision ("latest" ) for vg_name in vargroups ]
443
530
531
+ registry_credentials_id = None
532
+ if registry_credentials_name :
533
+ if not (
534
+ creds := cluster .registry_credentials .get (registry_credentials_name )
535
+ ): # NOTE: Check if credentials exist
536
+ raise click .UsageError (f"Unknown registry credentials '{ registry_credentials_name } '" )
537
+ registry_credentials_id = creds .id
538
+
444
539
click .echo (f"Name: { name } " )
445
540
click .echo (f"Image: { image } " )
446
541
click .echo (f"Network: { network } " )
447
542
if environment :
448
543
click .echo ("Environment:" )
449
544
click .echo (yaml .safe_dump ([var for vg in environment for var in vg .variables ]))
545
+ if registry_credentials_id :
546
+ click .echo (f"registry credentials: { registry_credentials_name } " )
450
547
451
548
if not click .confirm ("Do you want to create and start running this bot?" ):
452
549
return
453
550
454
- bot = cluster .new_bot (name , image , network , account = account , environment = environment )
551
+ bot = cluster .new_bot (
552
+ name ,
553
+ image ,
554
+ network ,
555
+ account = account ,
556
+ environment = environment ,
557
+ registry_credentials_id = registry_credentials_id ,
558
+ )
455
559
click .secho (f"Bot '{ bot .name } ' ({ bot .id } ) deploying..." , fg = "green" , bold = True )
456
560
457
561
@@ -477,7 +581,21 @@ def bot_info(cluster: ClusterClient, bot_name: str):
477
581
raise click .UsageError (f"Unknown bot '{ bot_name } '." )
478
582
479
583
# NOTE: Skip machine `.id`, and we already know it is `.name`
480
- click .echo (yaml .safe_dump (bot .model_dump (exclude = {"id" , "name" , "environment" })))
584
+ bot_dump = bot .model_dump (
585
+ exclude = {
586
+ "id" ,
587
+ "name" ,
588
+ "environment" ,
589
+ "registry_credentials_id" ,
590
+ "registry_credentials" ,
591
+ }
592
+ )
593
+ if bot .registry_credentials :
594
+ bot_dump ["registry_credentials" ] = bot .registry_credentials .model_dump (
595
+ exclude = {"id" , "name" }
596
+ )
597
+
598
+ click .echo (yaml .safe_dump (bot_dump ))
481
599
if bot .environment :
482
600
click .echo ("environment:" )
483
601
click .echo (yaml .safe_dump ([var .name for var in bot .environment ]))
@@ -489,6 +607,12 @@ def bot_info(cluster: ClusterClient, bot_name: str):
489
607
@click .option ("-n" , "--network" )
490
608
@click .option ("-a" , "--account" )
491
609
@click .option ("-g" , "--group" , "vargroups" , multiple = True )
610
+ @click .option (
611
+ "-r" ,
612
+ "--registry-credentials" ,
613
+ "registry_credentials_name" ,
614
+ help = "registry credentials to use to pull the image" ,
615
+ )
492
616
@click .argument ("name" , metavar = "BOT" )
493
617
@cluster_client
494
618
def update_bot (
@@ -498,6 +622,7 @@ def update_bot(
498
622
network : str | None ,
499
623
account : str | None ,
500
624
vargroups : list [str ],
625
+ registry_credentials_name : str | None ,
501
626
name : str ,
502
627
):
503
628
"""Update configuration of BOT in CLUSTER
@@ -516,6 +641,14 @@ def update_bot(
516
641
if network :
517
642
click .echo (f"Network:\n old: { bot .network } \n new: { network } " )
518
643
644
+ registry_credentials_id = None
645
+ if registry_credentials_name :
646
+ if not (
647
+ creds := cluster .registry_credentials .get (registry_credentials_name )
648
+ ): # NOTE: Check if credentials exist
649
+ raise click .UsageError (f"Unknown registry credentials '{ registry_credentials_name } '" )
650
+ registry_credentials_id = creds .id
651
+
519
652
redeploy_required = False
520
653
if image :
521
654
redeploy_required = True
@@ -549,6 +682,7 @@ def update_bot(
549
682
network = network ,
550
683
account = account ,
551
684
environment = environment if set_environment else None ,
685
+ registry_credentials_id = registry_credentials_id ,
552
686
)
553
687
554
688
# NOTE: Skip machine `.id`
0 commit comments