Cannot effectively overlay methods of DnsInterface by prepending a module

I’m developing a plugin Foreman v3.5.1 (starting with Foreman Plugin Template) and face the issue that one of my modules (DnsInterfaceExtensions) does not properly overlay the methods of DnsInterface.

While the foreman-rake console does show my module as ancestor and source location of the methods as my Ruby code…

irb(main):001:0> DnsInterface.ancestors
=> [ForemanCnames::DnsInterfaceExtensions, DnsInterface]

irb(main):002:0> DnsInterface.instance_method(:dns_feasible?).source_location
=> ["/usr/local/share/gems/gems/foreman_cnames-0.0.1/app/models/foreman_cnames/dns_interface_extensions.rb", 13]

… I find that actually Foreman keeps using it own original method:

[root@satellite-test-01 foreman]# grep ORIGINAL app/models/concerns/dns_interface.rb
    Foreman::Logging.logger('foreman_cnames').debug "ORIGINAL #{__method__} called"

[root@satellite-test-01 foreman]# egrep 'ed1bd4ac.*dns_feasible\?' /var/log/foreman/production.log
2024-07-29T11:05:03 [D|for|ed1bd4ac] ORIGINAL dns_feasible? called
2024-07-29T11:05:03 [D|for|ed1bd4ac] ORIGINAL dns_feasible? called
2024-07-29T11:05:03 [D|for|ed1bd4ac] ORIGINAL dns_feasible? called
2024-07-29T11:05:03 [D|for|ed1bd4ac] ORIGINAL dns_feasible? called
2024-07-29T11:05:03 [D|for|ed1bd4ac] ORIGINAL dns_feasible? called
2024-07-29T11:05:03 [D|for|ed1bd4ac] ORIGINAL dns_feasible? called
2024-07-29T11:05:03 [D|for|ed1bd4ac] ORIGINAL dns_feasible? called

Should I rather add our override to Nic::Managed?

irb(main):001:0> Nic::Managed.ancestors.filter { |c| c.name =~ /Dns/ }
=> [DnsInterface]
irb(main):002:0> Nic::Managed.ancestors.filter { |c| c.name =~ /Cnames/ }
=> [ForemanCnames::Concerns::NicExtensions] # <<< different prepended module!
irb(main):003:0> Nic::Managed.instance_method(:dns_feasible?).source_location
=> ["/usr/share/foreman/app/models/concerns/dns_interface.rb", 22]

Using ForemanCnames::Concerns::NicExtensions doesn’t work, because it shows up too far down the list of ancestors of Nic::Managed.

irb(main):001:0> Nic::Managed.ancestors.index DnsInterface
=> 5
irb(main):002:0> Nic::Managed.ancestors.index ForemanCnames::Concerns::NicExtensions
=> 27

And this will likely be the same for any module from any plugin, I suppose?

And this will likely be the same for any module from any plugin, I suppose?

Only accurate when prepending to Nic::Base (like ForemanCnames::Concerns::NicExtensions was in this instance). But by prepending ForemanCnames::DnsInterfaceExtensions to Net::Managed, I get a more promising situation:

irb(main):001:0> Nic::Managed.ancestors.index DnsInterface
=> 6
irb(main):002:0> Nic::Managed.ancestors.index ForemanCnames::DnsInterfaceExtensions
=> 0
irb(main):005:0> Nic::Managed.instance_method(:dns_feasible?).source_location
=> ["/usr/local/share/gems/gems/foreman_cnames-0.0.1/app/models/foreman_cnames/dns_interface_extensions.rb", 11]

The log contains prove that my function was executed, too.

2024-07-29T13:13:16 [D|for|259676de] OVERRIDDEN dns_feasible? called

Sadly, super seems to be broken now and Foreman falls into a recursive call to dns_feasible?

2024-07-29T13:13:16 [W|app|259676de] stack level too deep

super seems to be broken now

And that’s because I had modified DenInterfaceExtensions, so that was my own fault. This question is resolved.