@@ -105,6 +105,7 @@ func GetShortcuts() []string {
105105 common .FormatSCHeader ("m" , "Monitor" ),
106106 common .FormatSCHeader ("v" , "Volumes" ),
107107 common .FormatSCHeader ("n" , "Networks" ),
108+ common .FormatSCHeader ("shift-n" , "Attach Network" ),
108109 common .FormatSCHeader ("r" , "(Re)Start" ),
109110 common .FormatSCHeader ("p" , "Prune" ),
110111 common .FormatSCHeader ("ctrl-k" , "Stop" ),
@@ -138,6 +139,9 @@ func InputHandler(v *view.ResourceView, event *tcell.EventKey) *tcell.EventKey {
138139 case 'n' :
139140 Networks (app , v )
140141 return nil
142+ case 'N' :
143+ NetworksPicker (app , v )
144+ return nil
141145 case 'l' :
142146 Logs (app , v )
143147 return nil
@@ -448,3 +452,101 @@ func resolveContainerSubject(v *view.ResourceView, id string) string {
448452 }
449453 return subject
450454}
455+
456+ func NetworksPicker (app common.AppController , v * view.ResourceView ) {
457+ id , err := v .GetSelectedID ()
458+ if err != nil {
459+ return
460+ }
461+
462+ // Get all networks
463+ allNetworks , err := app .GetDocker ().ListNetworks ()
464+ if err != nil {
465+ app .SetFlashError (fmt .Sprintf ("%v" , err ))
466+ return
467+ }
468+
469+ // Get current container networks
470+ currentNetworks , err := app .GetDocker ().ListNetworksForContainer (id )
471+ if err != nil {
472+ app .SetFlashError (fmt .Sprintf ("%v" , err ))
473+ return
474+ }
475+
476+ attachedIDs := make (map [string ]bool )
477+ for _ , res := range currentNetworks {
478+ if n , ok := res .(dao.Network ); ok {
479+ attachedIDs [n .ID ] = true
480+ }
481+ }
482+
483+ var items []dialogs.MultiPickerItem
484+ for _ , res := range allNetworks {
485+ if n , ok := res .(dao.Network ); ok {
486+ if n .Scope == "swarm" {
487+ continue
488+ }
489+ items = append (items , dialogs.MultiPickerItem {
490+ ID : n .ID ,
491+ Label : n .Name ,
492+ Selected : attachedIDs [n .ID ],
493+ })
494+ }
495+ }
496+
497+ subject := resolveContainerSubject (v , id )
498+
499+ dialogs .ShowMultiPicker (app , fmt .Sprintf ("Networks for %s" , subject ), items , func (selected []string ) {
500+ selectedMap := make (map [string ]bool )
501+ for _ , sid := range selected {
502+ selectedMap [sid ] = true
503+ }
504+
505+ var toConnect []string
506+ var toDisconnect []string
507+
508+ // Check for new connections
509+ for _ , sid := range selected {
510+ if ! attachedIDs [sid ] {
511+ toConnect = append (toConnect , sid )
512+ }
513+ }
514+
515+ // Check for disconnections
516+ for attachedID := range attachedIDs {
517+ if ! selectedMap [attachedID ] {
518+ toDisconnect = append (toDisconnect , attachedID )
519+ }
520+ }
521+
522+ if len (toConnect ) == 0 && len (toDisconnect ) == 0 {
523+ return
524+ }
525+
526+ app .SetFlashPending ("updating networks..." )
527+ app .RunInBackground (func () {
528+ var errs []string
529+
530+ for _ , netID := range toConnect {
531+ if err := app .GetDocker ().ConnectNetwork (netID , id ); err != nil {
532+ errs = append (errs , fmt .Sprintf ("connect %s: %v" , netID , err ))
533+ }
534+ }
535+
536+ for _ , netID := range toDisconnect {
537+ if err := app .GetDocker ().DisconnectNetwork (netID , id ); err != nil {
538+ errs = append (errs , fmt .Sprintf ("disconnect %s: %v" , netID , err ))
539+ }
540+ }
541+
542+ app .GetTviewApp ().QueueUpdateDraw (func () {
543+ if len (errs ) > 0 {
544+ app .SetFlashError (strings .Join (errs , "; " ))
545+ } else {
546+ app .SetFlashSuccess ("networks updated" )
547+ app .RefreshCurrentView ()
548+ }
549+ })
550+ })
551+ })
552+ }
0 commit comments