diff --git a/services/broadcast_info_task.go b/services/broadcast_info_task.go index 96578f2..1e1c8dc 100644 --- a/services/broadcast_info_task.go +++ b/services/broadcast_info_task.go @@ -4,5 +4,5 @@ type broadcastInfoTask struct { } func (c *broadcastInfoTask) Run(i *Instance) { - wsServer.BroadcastTo(i.session.Id, "instance stats", i.Name, i.Mem, i.Cpu, i.IsManager) + wsServer.BroadcastTo(i.session.Id, "instance stats", i.Name, i.Mem, i.Cpu, i.IsManager, i.Ports) } diff --git a/services/check_used_ports_task.go b/services/check_used_ports_task.go new file mode 100644 index 0000000..bf27cb7 --- /dev/null +++ b/services/check_used_ports_task.go @@ -0,0 +1,10 @@ +package services + +type checkUsedPortsTask struct { +} + +func (c checkUsedPortsTask) Run(i *Instance) { + if ports, err := GetUsedPorts(i); err == nil { + i.Ports = ports + } +} diff --git a/services/docker.go b/services/docker.go index 4c1ad2d..d461076 100644 --- a/services/docker.go +++ b/services/docker.go @@ -46,6 +46,28 @@ func GetDaemonInfo(i *Instance) (types.Info, error) { } return i.dockerClient.Info(context.Background()) } +func GetUsedPorts(i *Instance) ([]uint16, error) { + if i.dockerClient == nil { + return nil, fmt.Errorf("Docker client for DinD (%s) is not ready", i.IP) + } + opts := types.ContainerListOptions{} + containers, err := i.dockerClient.ContainerList(context.Background(), opts) + if err != nil { + return nil, err + } + + openPorts := []uint16{} + for _, c := range containers { + for _, p := range c.Ports { + // When port is not published on the host docker return public port as 0, so we need to avoid it + if p.PublicPort != 0 { + openPorts = append(openPorts, p.PublicPort) + } + } + } + + return openPorts, nil +} func CreateNetwork(name string) error { opts := types.NetworkCreate{Driver: "overlay", Attachable: true} diff --git a/services/instance.go b/services/instance.go index 67e1382..b03757c 100644 --- a/services/instance.go +++ b/services/instance.go @@ -27,6 +27,7 @@ type Instance struct { IsManager *bool `json:"is_manager"` Mem string `json:"mem"` Cpu string `json:"cpu"` + Ports []uint16 `json:"ports"` } func (i *Instance) IsConnected() bool { diff --git a/services/task.go b/services/task.go index 3beec87..0ee41fb 100644 --- a/services/task.go +++ b/services/task.go @@ -7,5 +7,5 @@ type periodicTask interface { var periodicTasks []periodicTask func init() { - periodicTasks = append(periodicTasks, &collectStatsTask{}, &checkSwarmStatusTask{}, &broadcastInfoTask{}) + periodicTasks = append(periodicTasks, &collectStatsTask{}, &checkSwarmStatusTask{}, &checkUsedPortsTask{}, &broadcastInfoTask{}) } diff --git a/www/assets/app.js b/www/assets/app.js index 8f5fb55..a75872f 100644 --- a/www/assets/app.js +++ b/www/assets/app.js @@ -141,10 +141,11 @@ $scope.connected = true; }); - socket.on('instance stats', function(name, mem, cpu, isManager) { + socket.on('instance stats', function(name, mem, cpu, isManager, ports) { $scope.idx[name].mem = mem; $scope.idx[name].cpu = cpu; $scope.idx[name].isManager = isManager; + $scope.idx[name].ports = ports; $scope.$apply(); }); @@ -167,6 +168,12 @@ }); } + $scope.getProxyUrl = function(instance, port) { + var url = window.location.protocol + '//ip' + instance.ip.replace(/\./g, '_') + '-' + port + '.' + window.location.host; + + return url; + } + $scope.showInstance = function(instance) { $scope.selectedInstance = instance; if (!instance.creatingTerminal) { diff --git a/www/index.html b/www/index.html index 6722967..7cb3bd0 100644 --- a/www/index.html +++ b/www/index.html @@ -64,10 +64,17 @@ {{instance.name}} - - - - +
+ + + + + + + {{$chip}} + + +