package resolver import ( "strings" "firewall_containers/network-go/config" "firewall_containers/network-go/logger" ) // Resolver resolves names to IPs using the networks.json configuration type Resolver struct { cfg *config.NetworksConfig retries int } // NewResolver creates a new name resolver backed by the networks.json config func NewResolver(cfg *config.NetworksConfig) *Resolver { r := &Resolver{ cfg: cfg, retries: 2, } if cfg != nil { logger.Debug("RESOLVER: created with %d IPs in config", len(cfg.IPs)) } else { logger.Debug("RESOLVER: created with nil config") } return r } // SetConfig updates the config used for name resolution func (r *Resolver) SetConfig(cfg *config.NetworksConfig) { r.cfg = cfg if cfg != nil { logger.Debug("RESOLVER: config updated with %d IPs", len(cfg.IPs)) } else { logger.Debug("RESOLVER: config set to nil") } } // SetRetries sets the number of retries for resolution func (r *Resolver) SetRetries(n int) { r.retries = n logger.Debug("RESOLVER: retries set to %d", n) } // Resolve resolves a name to one or more IP addresses // It looks up the name in the networks.json config by container_name and selector fields func (r *Resolver) Resolve(name string) []string { if r.cfg == nil { logger.Debug("RESOLVER: resolve(%q): config is nil", name) return nil } logger.Debug("RESOLVER: resolving %q", name) var ips []string // Look up by container_name and selector in the IPs section for _, ipCfg := range r.cfg.IPs { if ipCfg.ContainerName == name || ipCfg.Selector == name { logger.Debug("RESOLVER: exact match for %q: container=%s selector=%s -> IP=%s", name, ipCfg.ContainerName, ipCfg.Selector, ipCfg.IP) ips = append(ips, ipCfg.IP) } } // If no exact match, try prefix matching: extract the prefix before the first dash // and match any container/selector starting with that prefix. // This allows "wireguardproxy-client" to match "wireguardproxyclient" (after dash stripping) // or "app-1"/"app-2" to match "app-x". if len(ips) == 0 && strings.Contains(name, "-") { prefix := name[:strings.Index(name, "-")] logger.Debug("RESOLVER: prefix matching %q with prefix %q", name, prefix) for _, ipCfg := range r.cfg.IPs { if strings.HasPrefix(ipCfg.ContainerName, prefix) || strings.HasPrefix(ipCfg.Selector, prefix) { logger.Debug("RESOLVER: prefix match for %q: %s -> IP=%s", prefix, ipCfg.ContainerName, ipCfg.IP) ips = append(ips, ipCfg.IP) } } } if len(ips) == 0 { logger.Warn("RESOLVER: no IP found for %q in networks.json config", name) } else { logger.Info("RESOLVER: %q resolved to %v", name, ips) } return ips }