93 lines
2.7 KiB
Go
93 lines
2.7 KiB
Go
|
package docker
|
||
|
|
||
|
import (
|
||
|
"net"
|
||
|
"strconv"
|
||
|
|
||
|
"github.com/Neur0toxine/sshpoke/internal/logger"
|
||
|
"github.com/Neur0toxine/sshpoke/internal/model"
|
||
|
"github.com/docker/docker/api/types"
|
||
|
"github.com/docker/docker/api/types/events"
|
||
|
"github.com/docker/docker/api/types/network"
|
||
|
"github.com/mitchellh/mapstructure"
|
||
|
)
|
||
|
|
||
|
type labelsConfig struct {
|
||
|
Enable boolStr `mapstructure:"sshpoke.enable"`
|
||
|
Network string `mapstructure:"sshpoke.network"`
|
||
|
Server string `mapstructure:"sshpoke.server"`
|
||
|
Port string `mapstructure:"sshpoke.port"`
|
||
|
Domain string `mapstructure:"sshpoke.domain"`
|
||
|
}
|
||
|
|
||
|
type boolStr string
|
||
|
|
||
|
func (b boolStr) Bool() bool {
|
||
|
return string(b) == "true"
|
||
|
}
|
||
|
|
||
|
func actorEnabled(actor events.Actor) bool {
|
||
|
label, ok := actor.Attributes["sshpoke.enable"]
|
||
|
if !ok {
|
||
|
return false
|
||
|
}
|
||
|
return boolStr(label).Bool()
|
||
|
}
|
||
|
|
||
|
func dockerContainerToInternal(container types.Container) (result model.Container, ok bool) {
|
||
|
var labels labelsConfig
|
||
|
if err := mapstructure.Decode(container.Labels, &labels); err != nil {
|
||
|
logger.Sugar.Debugf("skipping container %s because configuration is invalid: %s", container.ID, err)
|
||
|
return result, false
|
||
|
}
|
||
|
if !labels.Enable.Bool() {
|
||
|
logger.Sugar.Debugf("skipping container %s because sshpoke is not enabled for it", container.ID)
|
||
|
return result, false
|
||
|
}
|
||
|
if labels.Server == "" {
|
||
|
logger.Sugar.Debugf("skipping container %s because 'sshpoke.server' is not defined", container.ID)
|
||
|
return result, false
|
||
|
}
|
||
|
if container.NetworkSettings == nil ||
|
||
|
container.NetworkSettings.Networks == nil ||
|
||
|
len(container.NetworkSettings.Networks) == 0 {
|
||
|
logger.Sugar.Debugf("skipping container %s because network settings are empty", container.ID)
|
||
|
return result, false
|
||
|
}
|
||
|
var ip net.IP
|
||
|
if len(container.NetworkSettings.Networks) == 1 {
|
||
|
ip = net.ParseIP(getKeyVal(container.NetworkSettings.Networks).IPAddress)
|
||
|
} else {
|
||
|
if labels.Network == "" {
|
||
|
logger.Sugar.Debugf("container %s has %d networks and 'sshpoke.network' label is not specified",
|
||
|
container.ID, len(container.NetworkSettings.Networks))
|
||
|
return result, false
|
||
|
}
|
||
|
ntwrk, exists := container.NetworkSettings.Networks[labels.Network]
|
||
|
if !exists {
|
||
|
logger.Sugar.Debugf("container %s does not have network %s", container.ID, labels.Network)
|
||
|
return result, false
|
||
|
}
|
||
|
ip = net.ParseIP(ntwrk.IPAddress)
|
||
|
}
|
||
|
port, err := strconv.Atoi(labels.Port)
|
||
|
if err != nil {
|
||
|
logger.Sugar.Debugf("skipping container %s because 'sshpoke.port' is not numeric", container.ID)
|
||
|
return result, false
|
||
|
}
|
||
|
|
||
|
return model.Container{
|
||
|
IP: ip,
|
||
|
Port: uint16(port),
|
||
|
Server: labels.Server,
|
||
|
Domain: labels.Domain,
|
||
|
}, true
|
||
|
}
|
||
|
|
||
|
func getKeyVal(m map[string]*network.EndpointSettings) *network.EndpointSettings {
|
||
|
for _, v := range m {
|
||
|
return v
|
||
|
}
|
||
|
return nil
|
||
|
}
|