service: provide backwards compatibility for socket strings

The previous PR changed how sockets were represented in the JSON
API for formulae and that would cause problems when trying to install
packages with service sockets. This provides backwards compatibility
until all users have upgraded to versions of homebrew that can deserialize
sockets hashes (maybe a couple weeks). Essentially, we store the
socket string when serializing sockets that were originally defined with
only the string parameter otherwise we serialize it to a hash.
This commit is contained in:
apainintheneck 2023-09-29 19:45:55 -07:00
parent 043aca2df4
commit 215419daa5
2 changed files with 38 additions and 17 deletions

View File

@ -1,6 +1,7 @@
# typed: true
# frozen_string_literal: true
require "ipaddr"
require "extend/on_system"
module Homebrew
@ -187,7 +188,7 @@ module Homebrew
end
end
SOCKET_STRING_REGEX = %r{([a-z]+)://([a-z0-9.]+):([0-9]+)}i.freeze
SOCKET_STRING_REGEX = %r{^([a-z]+)://(.+):([0-9]+)$}i.freeze
sig {
params(value: T.nilable(T.any(String, T::Hash[Symbol, String])))
@ -206,6 +207,13 @@ module Homebrew
raise TypeError, "Service#sockets a formatted socket definition as <type>://<host>:<port>" if match.blank?
type, host, port = match.captures
begin
IPAddr.new(host)
rescue IPAddr::InvalidAddressError
raise TypeError, "Service#sockets expects a valid ipv4 or ipv6 host address"
end
{ host: host, port: port, type: type }
end
end
@ -424,7 +432,6 @@ module Homebrew
SockNodeName: info[:host],
SockServiceName: info[:port],
SockProtocol: info[:type].upcase,
SockFamily: "IPv4v6",
}
end
end
@ -522,9 +529,18 @@ module Homebrew
.join(" ")
end
sockets_hash = if @sockets.present?
@sockets.transform_values do |info|
"#{info[:type]}://#{info[:host]}:#{info[:port]}"
sockets_var = if @sockets.present?
@sockets.transform_values { |info| "#{info[:type]}://#{info[:host]}:#{info[:port]}" }
.then do |sockets_hash|
# TODO: Remove this code when all users are running on versions of Homebrew
# that can process sockets hashes (this commit or later).
if sockets_hash.size == 1 && sockets_hash.key?(:listeners)
# When original #sockets argument was a string: `sockets "tcp://127.0.0.1:80"`
sockets_hash.fetch(:listeners)
else
# When original #sockets argument was a hash: `sockets http: "tcp://0.0.0.0:80"`
sockets_hash
end
end
end
@ -546,7 +562,7 @@ module Homebrew
restart_delay: @restart_delay,
process_type: @process_type,
macos_legacy_timers: @macos_legacy_timers,
sockets: sockets_hash,
sockets: sockets_var,
}.compact
end

View File

@ -116,7 +116,7 @@ describe Homebrew::Service do
it "throws for missing type" do
[
stub_formula_with_service_sockets("127.0.0.1:80"),
stub_formula_with_service_sockets({ "Socket" => "127.0.0.1:80" }),
stub_formula_with_service_sockets({ socket: "127.0.0.1:80" }),
].each do |f|
expect { f.service.manual_command }.to raise_error TypeError, sockets_type_error_message
end
@ -125,7 +125,7 @@ describe Homebrew::Service do
it "throws for missing host" do
[
stub_formula_with_service_sockets("tcp://:80"),
stub_formula_with_service_sockets({ "Socket" => "tcp://:80" }),
stub_formula_with_service_sockets({ socket: "tcp://:80" }),
].each do |f|
expect { f.service.manual_command }.to raise_error TypeError, sockets_type_error_message
end
@ -134,11 +134,22 @@ describe Homebrew::Service do
it "throws for missing port" do
[
stub_formula_with_service_sockets("tcp://127.0.0.1"),
stub_formula_with_service_sockets({ "Socket" => "tcp://127.0.0.1" }),
stub_formula_with_service_sockets({ socket: "tcp://127.0.0.1" }),
].each do |f|
expect { f.service.manual_command }.to raise_error TypeError, sockets_type_error_message
end
end
it "throws for invalid host" do
[
stub_formula_with_service_sockets("tcp://300.0.0.1:80"),
stub_formula_with_service_sockets({ socket: "tcp://300.0.0.1:80" }),
].each do |f|
expect do
f.service.manual_command
end.to raise_error TypeError, "Service#sockets expects a valid ipv4 or ipv6 host address"
end
end
end
describe "#manual_command" do
@ -283,8 +294,6 @@ describe Homebrew::Service do
\t<dict>
\t\t<key>listeners</key>
\t\t<dict>
\t\t\t<key>SockFamily</key>
\t\t\t<string>IPv4v6</string>
\t\t\t<key>SockNodeName</key>
\t\t\t<string>127.0.0.1</string>
\t\t\t<key>SockProtocol</key>
@ -341,8 +350,6 @@ describe Homebrew::Service do
\t<dict>
\t\t<key>socket</key>
\t\t<dict>
\t\t\t<key>SockFamily</key>
\t\t\t<string>IPv4v6</string>
\t\t\t<key>SockNodeName</key>
\t\t\t<string>0.0.0.0</string>
\t\t\t<key>SockProtocol</key>
@ -352,8 +359,6 @@ describe Homebrew::Service do
\t\t</dict>
\t\t<key>socket_tls</key>
\t\t<dict>
\t\t\t<key>SockFamily</key>
\t\t\t<string>IPv4v6</string>
\t\t\t<key>SockNodeName</key>
\t\t\t<string>0.0.0.0</string>
\t\t\t<key>SockProtocol</key>
@ -1049,7 +1054,7 @@ describe Homebrew::Service do
run_type: :immediate,
working_dir: "/$HOME",
cron: "0 0 * * 0",
sockets: { listeners: "tcp://0.0.0.0:80" },
sockets: "tcp://0.0.0.0:80",
}
end