Skip to content

Commit cb9ff4a

Browse files
committed
feat(subview containers for network with container count on network list)
1 parent 6e74453 commit cb9ff4a

7 files changed

Lines changed: 124 additions & 19 deletions

File tree

internal/dao/docker.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ func (d *DockerClient) ScaleService(id string, replicas uint64) error {
290290
return d.Service.Scale(id, replicas)
291291
}
292292

293+
func (d *DockerClient) UpdateServiceImage(id string, image string) error {
294+
return d.Service.UpdateImage(id, image)
295+
}
296+
293297
func (d *DockerClient) RemoveService(id string) error {
294298
return d.Service.Remove(id)
295299
}

internal/dao/docker/container/container.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ type Container struct {
5959
Mem string
6060
IP string
6161
Cmd string
62+
Networks map[string]string
6263
}
6364

6465
func (c Container) GetID() string { return c.ID }
@@ -245,12 +246,13 @@ func (m *Manager) List() ([]common.Resource, error) {
245246
}
246247

247248
ip := ""
249+
networks := make(map[string]string)
248250
if c.NetworkSettings != nil {
249-
for _, n := range c.NetworkSettings.Networks {
250-
if n.IPAddress != "" {
251+
for name, n := range c.NetworkSettings.Networks {
252+
if ip == "" && n.IPAddress != "" {
251253
ip = n.IPAddress
252-
break
253254
}
255+
networks[name] = n.NetworkID
254256
}
255257
}
256258

@@ -283,6 +285,7 @@ func (m *Manager) List() ([]common.Resource, error) {
283285
Mem: memStr,
284286
IP: ip,
285287
Cmd: cmd,
288+
Networks: networks,
286289
}
287290
}
288291
return res, nil

internal/dao/docker/network/network.go

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"strings"
66

7+
"github.com/docker/docker/api/types"
78
"github.com/docker/docker/api/types/filters"
89
"github.com/docker/docker/api/types/network"
910
"github.com/docker/docker/client"
@@ -24,18 +25,23 @@ func NewManager(cli *client.Client, ctx context.Context) *Manager {
2425

2526
// Network Model
2627
type Network struct {
27-
ID string
28-
Name string
29-
Driver string
30-
Scope string
31-
Created string
32-
Internal string
33-
Subnet string
28+
ID string
29+
Name string
30+
Driver string
31+
Scope string
32+
Created string
33+
Internal string
34+
Subnet string
35+
Containers int
3436
}
3537

3638
func (n Network) GetID() string { return n.ID }
3739
func (n Network) GetCells() []string {
38-
return []string{n.ID[:12], n.Name, n.Driver, n.Scope, n.Created, n.Internal, n.Subnet}
40+
containersStr := fmt.Sprintf("%d", n.Containers)
41+
if n.Containers <= 0 {
42+
containersStr = ""
43+
}
44+
return []string{n.ID[:12], n.Name, n.Driver, n.Scope, containersStr, n.Created, n.Internal, n.Subnet}
3945
}
4046

4147
func (n Network) GetStatusColor() (tcell.Color, tcell.Color) {
@@ -52,6 +58,8 @@ func (n Network) GetColumnValue(column string) string {
5258
return n.Driver
5359
case "scope":
5460
return n.Scope
61+
case "containers":
62+
return fmt.Sprintf("%d", n.Containers)
5563
case "created":
5664
return n.Created
5765
case "internal":
@@ -94,13 +102,14 @@ func (m *Manager) List() ([]common.Resource, error) {
94102
}
95103

96104
res = append(res, Network{
97-
ID: n.ID,
98-
Name: n.Name,
99-
Driver: n.Driver,
100-
Scope: n.Scope,
101-
Created: common.FormatTime(n.Created.Unix()),
102-
Internal: internal,
103-
Subnet: strings.Join(subnets, ","),
105+
ID: n.ID,
106+
Name: n.Name,
107+
Driver: n.Driver,
108+
Scope: n.Scope,
109+
Created: common.FormatTime(n.Created.Unix()),
110+
Internal: internal,
111+
Subnet: strings.Join(subnets, ","),
112+
Containers: len(n.Containers),
104113
})
105114
}
106115
return res, nil

internal/dao/swarm/service/service.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,20 @@ func (m *Manager) Scale(id string, replicas uint64) error {
177177
return err
178178
}
179179

180+
func (m *Manager) UpdateImage(id string, image string) error {
181+
service, _, err := m.cli.ServiceInspectWithRaw(m.ctx, id, swarm.ServiceInspectOptions{})
182+
if err != nil {
183+
return err
184+
}
185+
186+
service.Spec.TaskTemplate.ContainerSpec.Image = image
187+
188+
_, err = m.cli.ServiceUpdate(m.ctx, id, service.Version, service.Spec, swarm.ServiceUpdateOptions{
189+
QueryRegistry: true,
190+
})
191+
return err
192+
}
193+
180194
func (m *Manager) Remove(id string) error {
181195
return m.cli.ServiceRemove(m.ctx, id)
182196
}

internal/ui/views/containers/containers.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@ func Fetch(app common.AppController, v *view.ResourceView) ([]dao.Resource, erro
7676
}
7777
}
7878
return scopedData, nil
79+
} else if scope.Type == "network" {
80+
var scopedData []dao.Resource
81+
for _, res := range data {
82+
if c, ok := res.(dao.Container); ok {
83+
for _, netID := range c.Networks {
84+
if netID == scope.Value {
85+
scopedData = append(scopedData, res)
86+
break
87+
}
88+
}
89+
}
90+
}
91+
return scopedData, nil
7992
}
8093
}
8194

internal/ui/views/networks/networks.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"github.com/jr-k/d4s/internal/ui/styles"
1414
)
1515

16-
var Headers = []string{"ID", "NAME", "DRIVER", "SCOPE", "CREATED", "INTERNAL", "SUBNET"}
16+
var Headers = []string{"ID", "NAME", "DRIVER", "SCOPE", "CONTAINERS", "CREATED", "INTERNAL", "SUBNET"}
1717

1818
func Fetch(app common.AppController, v *view.ResourceView) ([]dao.Resource, error) {
1919
scope := app.GetActiveScope()
@@ -56,6 +56,7 @@ func Inspect(app common.AppController, id string) {
5656
func GetShortcuts() []string {
5757
return []string{
5858
common.FormatSCHeader("d", "Describe"),
59+
common.FormatSCHeader("c", "Containers"),
5960
common.FormatSCHeader("a", "Add"),
6061
common.FormatSCHeader("p", "Prune"),
6162
common.FormatSCHeader("ctrl-d", "Delete"),
@@ -69,6 +70,26 @@ func InputHandler(v *view.ResourceView, event *tcell.EventKey) *tcell.EventKey {
6970
return nil
7071
}
7172
switch event.Rune() {
73+
case 'c':
74+
row, _ := v.Table.GetSelection()
75+
if row < 1 || row >= v.Table.GetRowCount() {
76+
return nil
77+
}
78+
dataIndex := row - 1
79+
if dataIndex < 0 || dataIndex >= len(v.Data) {
80+
return nil
81+
}
82+
if net, ok := v.Data[dataIndex].(dao.Network); ok {
83+
scope := &common.Scope{
84+
Type: "network",
85+
Value: net.ID,
86+
Label: net.Name,
87+
OriginView: styles.TitleNetworks,
88+
}
89+
app.SetActiveScope(scope)
90+
app.SwitchTo(styles.TitleContainers)
91+
}
92+
return nil
7293
case 'd':
7394
app.InspectCurrentSelection()
7495
return nil

internal/ui/views/services/services.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func Fetch(app common.AppController, v *view.ResourceView) ([]dao.Resource, erro
5151

5252
func GetShortcuts() []string {
5353
return []string{
54+
common.FormatSCHeader("e", "Edit"),
5455
common.FormatSCHeader("l", "Logs"),
5556
common.FormatSCHeader("d", "Describe"),
5657
common.FormatSCHeader("s", "Scale"),
@@ -73,6 +74,9 @@ func InputHandler(v *view.ResourceView, event *tcell.EventKey) *tcell.EventKey {
7374
}
7475

7576
switch event.Rune() {
77+
case 'e':
78+
EditAction(app, v)
79+
return nil
7680
case 's':
7781
ScaleAction(app, v)
7882
return nil
@@ -225,3 +229,40 @@ func Scale(app common.AppController, id string, currentReplicas string) {
225229
})
226230
})
227231
}
232+
233+
func EditAction(app common.AppController, v *view.ResourceView) {
234+
id, err := v.GetSelectedID()
235+
if err != nil {
236+
return
237+
}
238+
239+
currentImage := ""
240+
row, _ := v.Table.GetSelection()
241+
if row > 0 && row <= len(v.Data) {
242+
item := v.Data[row-1]
243+
cells := item.GetCells()
244+
if len(cells) > 2 {
245+
currentImage = strings.TrimSpace(cells[2])
246+
}
247+
}
248+
249+
dialogs.ShowInput(app, "Edit Service", "Image:", currentImage, func(text string) {
250+
if text == "" {
251+
return
252+
}
253+
254+
app.SetFlashPending(fmt.Sprintf("updating service %s...", id))
255+
256+
app.RunInBackground(func() {
257+
err := app.GetDocker().UpdateServiceImage(id, text)
258+
app.GetTviewApp().QueueUpdateDraw(func() {
259+
if err != nil {
260+
app.SetFlashError(fmt.Sprintf("%v", err))
261+
} else {
262+
app.SetFlashSuccess("service updated")
263+
app.RefreshCurrentView()
264+
}
265+
})
266+
})
267+
})
268+
}

0 commit comments

Comments
 (0)