Skip to content

Commit 16b0d29

Browse files
authored
RUBY-3296 Write to log when non-genuine host is detected (#2791)
* RUBY-3296 write to log when non-genuine host is detected * rubocop appeasement * apparently the Lint/Debugger rubocop is needed in CI, but not locally?
1 parent e9bed68 commit 16b0d29

File tree

4 files changed

+105
-0
lines changed

4 files changed

+105
-0
lines changed

Diff for: lib/mongo/cluster.rb

+26
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ def initialize(seeds, monitoring, options = Options::Redacted.new)
186186
recreate_topology(topology, opening_topology)
187187
end
188188

189+
possibly_warn_about_compatibility!
190+
189191
if load_balanced?
190192
# We are required by the specifications to produce certain SDAM events
191193
# when in load-balanced topology.
@@ -1082,6 +1084,30 @@ def recreate_topology(new_topology_template, previous_topology)
10821084
Monitoring::Event::TopologyChanged.new(previous_topology, @topology)
10831085
)
10841086
end
1087+
1088+
COSMOSDB_HOST_PATTERNS = %w[ .cosmos.azure.com ]
1089+
COSMOSDB_LOG_MESSAGE = 'You appear to be connected to a CosmosDB cluster. ' \
1090+
'For more information regarding feature compatibility and support please visit ' \
1091+
'https://www.mongodb.com/supportability/cosmosdb'
1092+
1093+
DOCUMENTDB_HOST_PATTERNS = %w[ .docdb.amazonaws.com .docdb-elastic.amazonaws.com ]
1094+
DOCUMENTDB_LOG_MESSAGE = 'You appear to be connected to a DocumentDB cluster. ' \
1095+
'For more information regarding feature compatibility and support please visit ' \
1096+
'https://www.mongodb.com/supportability/documentdb'
1097+
1098+
# Compares the server hosts with address suffixes of known services
1099+
# that provide limited MongoDB API compatibility, and warns about them.
1100+
def possibly_warn_about_compatibility!
1101+
if topology.server_hosts_match_any?(COSMOSDB_HOST_PATTERNS)
1102+
log_info COSMOSDB_LOG_MESSAGE
1103+
return
1104+
end
1105+
1106+
if topology.server_hosts_match_any?(DOCUMENTDB_HOST_PATTERNS)
1107+
log_info DOCUMENTDB_LOG_MESSAGE
1108+
return
1109+
end
1110+
end
10851111
end
10861112
end
10871113

Diff for: lib/mongo/cluster/topology/base.rb

+16
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,22 @@ def new_max_set_version(description)
211211
end
212212
end
213213

214+
# Compares each server address against the list of patterns.
215+
#
216+
# @param [ Array<String> ] patterns the URL suffixes to compare
217+
# each server against.
218+
#
219+
# @return [ true | false ] whether any of the addresses match any of
220+
# the patterns or not.
221+
#
222+
# @api private
223+
def server_hosts_match_any?(patterns)
224+
server_descriptions.any? do |addr_spec, _desc|
225+
addr, _port = addr_spec.split(/:/)
226+
patterns.any? { |pattern| addr.end_with?(pattern) }
227+
end
228+
end
229+
214230
private
215231

216232
# Validates and/or transforms options as necessary for the topology.

Diff for: spec/mongo/cluster_spec.rb

+36
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require 'spec_helper'
4+
require 'support/recording_logger'
45

56
# let these existing styles stand, rather than going in for a deep refactoring
67
# of these specs.
@@ -84,6 +85,41 @@
8485
)
8586
end
8687
end
88+
89+
context 'when a non-genuine host is detected' do
90+
before { described_class.new(host_names, monitoring, logger: logger, monitoring_io: false) }
91+
92+
let(:logger) { RecordingLogger.new }
93+
94+
shared_examples 'an action that logs' do
95+
it 'writes a warning to the log' do
96+
expect(logger.lines).to include(a_string_matching(expected_log_output))
97+
end
98+
end
99+
100+
context 'when CosmosDB is detected' do
101+
let(:host_names) { %w[ xyz.cosmos.azure.com ] }
102+
let(:expected_log_output) { %r{https://www.mongodb.com/supportability/cosmosdb} }
103+
104+
it_behaves_like 'an action that logs'
105+
end
106+
107+
context 'when DocumentDB is detected' do
108+
let(:expected_log_output) { %r{https://www.mongodb.com/supportability/documentdb} }
109+
110+
context 'with docdb uri' do
111+
let(:host_names) { [ 'xyz.docdb.amazonaws.com' ] }
112+
113+
it_behaves_like 'an action that logs'
114+
end
115+
116+
context 'with docdb-elastic uri' do
117+
let(:host_names) { [ 'xyz.docdb-elastic.amazonaws.com' ] }
118+
119+
it_behaves_like 'an action that logs'
120+
end
121+
end
122+
end
87123
end
88124

89125
describe '#==' do

Diff for: spec/support/recording_logger.rb

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# frozen_string_literal: true
2+
# rubocop:todo all
3+
4+
require 'stringio'
5+
6+
# A "Logger-alike" class, quacking like ::Logger, used for recording messages
7+
# as they are written to the log
8+
class RecordingLogger < Logger
9+
def initialize(*args, **kwargs)
10+
@buffer = StringIO.new
11+
super(@buffer, *args, **kwargs)
12+
end
13+
14+
# Accesses the raw contents of the log
15+
#
16+
# @return [ String ] the raw contents of the log
17+
def contents
18+
@buffer.string
19+
end
20+
21+
# Returns the contents of the log as individual lines.
22+
#
23+
# @return [ Array<String> ] the individual log lines
24+
def lines
25+
contents.split(/\n/)
26+
end
27+
end

0 commit comments

Comments
 (0)