# frozen_string_literal: true require 'ipaddr' # a class that creates facts based on the subnet class SubnetAttributes SUBNET_TO_ATTRIBUTES = { '198.18.2.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # router loopbacks '198.18.13.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, '198.18.14.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, '198.18.15.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, '198.18.16.0/24' => { environment: 'test', region: 'syd1', country: 'au', zone: 'common' }, '198.18.17.0/24' => { environment: 'prod', region: 'drw1', country: 'au', zone: 'common' }, '198.18.18.0/24' => { environment: 'test', region: 'drw1', country: 'au', zone: 'common' }, '198.18.19.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # loopbacks '198.18.20.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # MPLS CORE BLOCKS '198.18.21.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # physical network 2.5gbe '198.18.22.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # ceph cluster '198.18.23.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # ceph public '198.18.24.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'dmz' }, # dmz 1 '198.18.25.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # common node0009 '198.18.26.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # common node0010 '198.18.27.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # common node0011 '198.18.28.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # common node0012 '198.18.29.0/24' => { environment: 'prod', region: 'syd1', country: 'au', zone: 'common' }, # common node0013 '198.18.30.0/24' => { environment: 'prod', region: 'syd2', country: 'au', zone: 'dmz' }, # binarylane syd dmz vpc '198.18.31.0/24' => { environment: 'prod', region: 'mel1', country: 'au', zone: 'dmz' } # binarylane mel dmz vpc }.freeze # Default attributes if no subnet matches, also defined as a constant DEFAULT_ATTRIBUTES = { environment: 'unknown', region: 'unknown', country: 'unknown' }.freeze # loopbacks and wg /31s sit in syd1 ranges, so they must not decide where a host lives SKIPPED_INTERFACES = /\A(lo\z|dum|wg)/.freeze # primary ip first, then the remaining interfaces in name order def self.from_networking(networking) match(networking['ip']) || interface_match(networking['interfaces'] || {}) || DEFAULT_ATTRIBUTES end def self.interface_match(interfaces) interfaces.sort .reject { |name, _interface| name.match?(SKIPPED_INTERFACES) } .flat_map { |_name, interface| addresses(interface) } .lazy.filter_map { |address| match(address) }.first end def self.addresses(interface) (interface['bindings'] || []).map { |binding| binding['address'] } end def self.match(ip) return unless ip addr = IPAddr.new(ip) SUBNET_TO_ATTRIBUTES.each do |subnet, attrs| return attrs if IPAddr.new(subnet).include?(addr) end nil end end subnet_attributes = SubnetAttributes.from_networking(Facter.value(:networking)) # Add separate facts for environment, region, and country Facter.add('environment') { setcode { subnet_attributes[:environment] } } Facter.add('region') { setcode { subnet_attributes[:region] } } Facter.add('country') { setcode { subnet_attributes[:country] } } Facter.add('zone') { setcode { subnet_attributes[:zone] } }