Files
ubicloud/lib/net_addr_sequel.rb
Jeremy Evans fc58e6b5d3 Better NetAddr/Sequel integration
Previously, the only integration was conversion procs for inet and
cidr. This adds:

* conversion procs for inet[] and cidr[] (previously these used
  IPAddr instead of NetAddr)

* typecasting support

* schema type validation

* NetAddr object literalization and bound variable support

Update the update_firewall_rules prog to handle NetAddr instead
of IPAddr instances.

This gives inet/cidr/inet[]/cidr[] columns a schema type when they
did not have a schema type previously, which breaks the usage of
literal string values for array columns in model objects. Literal
strings are expressions and not values, and therefore shouldn't
be used as model object values, they only work due to implementation
details if a schema type is not present.  Fix cases where literal
strings were used as model object values, making all affected code
simpler.
2025-06-12 07:32:57 +09:00

88 lines
2.1 KiB
Ruby

# frozen_string_literal: true
module NetAddrSequel
module DatasetMethods
def literal_other_append(sql, value)
case value
when NetAddr::IPv4, NetAddr::IPv6
literal_append(sql, value.to_s)
sql << "::inet"
when NetAddr::IPv4Net, NetAddr::IPv6Net
literal_append(sql, value.to_s)
sql << "::cidr"
else
super
end
end
end
module DatabaseMethods
def schema_type_class(type)
case type
when :inet
[NetAddr::IPv4, NetAddr::IPv6]
when :cidr
[NetAddr::IPv4Net, NetAddr::IPv6Net]
else
super
end
end
private
# :nocov:
# Called when generating the schema caches, but not called at runtime, as
# the values from the schema cache are used.
def schema_column_type(db_type)
case db_type
when "inet"
:inet
when "cidr"
:cidr
else
super
end
end
# :nocov:
def typecast_value_inet(value)
case value
when String
begin
NetAddr.parse_ip(value)
rescue
raise Sequel::InvalidValue, "invalid value for inet: #{value.inspect}"
end
when NetAddr::IPv4, NetAddr::IPv6
value
else
raise Sequel::InvalidValue, "invalid value for inet: #{value.inspect}"
end
end
def typecast_value_cidr(value)
case value
when String
_typecast_value_cidr_string(value)
when NetAddr::IPv4, NetAddr::IPv6
_typecast_value_cidr_string(value.to_s)
when NetAddr::IPv4Net, NetAddr::IPv6Net
value
else
raise Sequel::InvalidValue, "invalid value for cidr: #{value.inspect}"
end
rescue NetAddr::ValidationError
raise Sequel::InvalidValue, "invalid value for cidr: #{value.inspect}"
end
def _typecast_value_cidr_string(value)
if value.include?(":") && !value.include?("/")
# Work around NetAddr behavior of assuming /64 netmask for IPv6 addresses
NetAddr.parse_net("#{value}/128")
else
NetAddr.parse_net(value)
end
end
end
end