package resolver import ( "context" "fmt" "git.zb-server.de/Sebi/ssh-netbox-wrapper/internal/config" "git.zb-server.de/Sebi/ssh-netbox-wrapper/internal/netbox" ) // Chain tries each strategy in order until one returns an IP. type Chain struct { strategies []Strategy } // New builds a Chain from the strategy names listed in the resolver config. func New(cfg config.ResolverConfig) (*Chain, error) { var strategies []Strategy for _, name := range cfg.Strategies { s, err := newStrategy(name, cfg) if err != nil { return nil, fmt.Errorf("resolver strategy %q: %w", name, err) } strategies = append(strategies, s) } return &Chain{strategies: strategies}, nil } func (c *Chain) Resolve(ctx context.Context, entry *netbox.HostEntry, client *netbox.Client) (string, error) { for _, s := range c.strategies { ip, err := s.Resolve(ctx, entry, client) if err == nil { return ip, nil } } return "", fmt.Errorf("no strategy resolved an IP for %q", entry.Name) } func newStrategy(name string, cfg config.ResolverConfig) (Strategy, error) { switch name { case "primary_ip": return &PrimaryIPStrategy{}, nil case "management_subnet": s, err := NewManagementSubnetStrategy(cfg.ManagementSubnets) if err != nil { return nil, err } return s, nil case "interface_name": if cfg.InterfaceName == "" { return nil, fmt.Errorf("interface_name strategy requires resolver.interface_name to be set") } return &InterfaceNameStrategy{name: cfg.InterfaceName}, nil default: return nil, fmt.Errorf("unknown strategy %q", name) } }