sshpoke/internal/docker/convert.go

107 lines
3.0 KiB
Go

package docker
import (
"net"
"strconv"
"strings"
"github.com/Neur0toxine/sshpoke/internal/logger"
"github.com/Neur0toxine/sshpoke/pkg/dto"
"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"`
RemoteHost string `mapstructure:"sshpoke.remote_host"`
}
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 dto.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 dto.Container{
ID: container.ID,
Names: convertNames(container.Names),
IP: ip,
Port: uint16(port),
Server: labels.Server,
RemoteHost: labels.RemoteHost,
}, true
}
func convertNames(src []string) []string {
if len(src) == 0 {
return nil
}
dst := make([]string, len(src))
for i := 0; i < len(src); i++ {
dst[i] = strings.TrimLeft(src[i], "/")
}
return dst
}
func getKeyVal(m map[string]*network.EndpointSettings) *network.EndpointSettings {
for _, v := range m {
return v
}
return nil
}