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"` Prefix string `mapstructure:"sshpoke.prefix"` 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, Prefix: labels.Prefix, Domain: labels.Domain, }, true } func getKeyVal(m map[string]*network.EndpointSettings) *network.EndpointSettings { for _, v := range m { return v } return nil }