Skip to content

Commit 53d641f

Browse files
authored
pants-plugins/uses_services: respect ST2_DATABASE__* vars (#6278)
2 parents fefe7e5 + 07762ae commit 53d641f

File tree

7 files changed

+95
-25
lines changed

7 files changed

+95
-25
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Added
6969
working on StackStorm, improve our security posture, and improve CI reliability thanks in part
7070
to pants' use of PEX lockfiles. This is not a user-facing addition.
7171
#6118 #6141 #6133 #6120 #6181 #6183 #6200 #6237 #6229 #6240 #6241 #6244 #6251 #6253
72-
#6254 #6258 #6259 #6260 #6269 #6275 #6279
72+
#6254 #6258 #6259 #6260 #6269 #6275 #6279 #6278
7373
Contributed by @cognifloyd
7474
* Build of ST2 EL9 packages #6153
7575
Contributed by @amanda11

pants-plugins/uses_services/exceptions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class ServiceSpecificMessages:
3434

3535
service_start_cmd_generic: str
3636

37+
env_vars_hint: str = ""
38+
3739

3840
class ServiceMissingError(Exception):
3941
"""Error raised when a test uses a service but that service is missing."""
@@ -162,6 +164,9 @@ def generate(
162164
"""
163165
)
164166

167+
if messages.env_vars_hint:
168+
instructions += f"\n\n{messages.env_vars_hint}"
169+
165170
return cls(
166171
service=service,
167172
platform=platform,

pants-plugins/uses_services/mongo_rules.py

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
from __future__ import annotations
1415

1516
from dataclasses import dataclass
1617
from textwrap import dedent
@@ -27,6 +28,8 @@
2728
VenvPexProcess,
2829
rules as pex_rules,
2930
)
31+
from pants.core.goals.test import TestExtraEnv
32+
from pants.engine.env_vars import EnvironmentVars
3033
from pants.engine.fs import CreateDigest, Digest, FileContent
3134
from pants.engine.rules import collect_rules, Get, MultiGet, rule
3235
from pants.engine.process import FallibleProcessResult, ProcessCacheScope
@@ -55,21 +58,50 @@ class UsesMongoRequest:
5558
# for unit tests: st2tests/st2tests/config.py
5659
# for integration tests: conf/st2.tests*.conf st2tests/st2tests/fixtures/conf/st2.tests*.conf
5760
# (changed by setting ST2_CONFIG_PATH env var inside the tests)
58-
# TODO: for unit tests: modify code to pull db connect settings from env vars
59-
# TODO: for int tests: modify st2.tests*.conf on the fly to set the per-pantsd-slot db_name
60-
# and either add env vars for db connect settings or modify conf files as well
61-
62-
# with our version of oslo.config (newer are slower) we can't directly override opts w/ environment variables.
61+
# These can also be updated via the ST2_DATABASE__* env vars (which oslo_config reads).
62+
# Integration tests should pass these changes onto subprocesses via the same env vars.
6363

6464
db_host: str = "127.0.0.1" # localhost in test_db.DbConnectionTestCase
6565
db_port: int = 27017
6666
# db_name is "st2" in test_db.DbConnectionTestCase
6767
db_name: str = "st2-test{}" # {} will be replaced by test slot (a format string)
6868

69+
# username and password are not required to validate connectivity, so this doesn't have them.
70+
6971
db_connection_timeout: int = 3000
7072

7173
execution_slot_var: str = "ST2TESTS_PARALLEL_SLOT"
7274

75+
@classmethod
76+
def from_env(
77+
cls, execution_slot_var: str, env: EnvironmentVars
78+
) -> UsesMongoRequest:
79+
default = cls()
80+
host = env.get("ST2_DATABASE__HOST", default.db_host)
81+
port_raw = env.get("ST2_DATABASE__PORT", str(default.db_port))
82+
db_name = default.db_name # not overridable via ST2_DATABASE__DB_NAME
83+
db_connection_timeout_raw = env.get(
84+
"ST2_DATABASE__CONNECTION_TIMEOUT", str(default.db_connection_timeout)
85+
)
86+
87+
try:
88+
port = int(port_raw)
89+
except (TypeError, ValueError):
90+
port = default.db_port
91+
92+
try:
93+
db_connection_timeout = int(db_connection_timeout_raw)
94+
except (TypeError, ValueError):
95+
db_connection_timeout = default.db_connection_timeout
96+
97+
return cls(
98+
db_host=host,
99+
db_port=port,
100+
db_name=db_name,
101+
db_connection_timeout=db_connection_timeout,
102+
execution_slot_var=execution_slot_var,
103+
)
104+
73105

74106
@dataclass(frozen=True)
75107
class MongoIsRunning:
@@ -90,7 +122,9 @@ def is_applicable(cls, target: Target) -> bool:
90122
level=LogLevel.DEBUG,
91123
)
92124
async def mongo_is_running_for_pytest(
93-
request: PytestUsesMongoRequest, pytest: PyTest
125+
request: PytestUsesMongoRequest,
126+
pytest: PyTest,
127+
test_extra_env: TestExtraEnv,
94128
) -> PytestPluginSetup:
95129
# TODO: delete these comments once the Makefile becomes irrelevant.
96130
# the comments explore how the Makefile prepares to run and runs tests
@@ -109,7 +143,9 @@ async def mongo_is_running_for_pytest(
109143
# this will raise an error if mongo is not running
110144
_ = await Get(
111145
MongoIsRunning,
112-
UsesMongoRequest(execution_slot_var=pytest.execution_slot_var or ""),
146+
UsesMongoRequest.from_env(
147+
execution_slot_var=pytest.execution_slot_var or "", env=test_extra_env.env
148+
),
113149
)
114150

115151
return PytestPluginSetup()
@@ -151,8 +187,8 @@ async def mongo_is_running(
151187
str(request.db_port),
152188
request.db_name,
153189
str(request.db_connection_timeout),
154-
request.execution_slot_var,
155190
),
191+
extra_env={"PANTS_PYTEST_EXECUTION_SLOT_VAR": request.execution_slot_var},
156192
input_digest=script_digest,
157193
execution_slot_variable=request.execution_slot_var,
158194
description="Checking to see if Mongo is up and accessible.",
@@ -200,6 +236,18 @@ async def mongo_is_running(
200236
"""
201237
),
202238
service_start_cmd_generic="systemctl start mongod",
239+
env_vars_hint=dedent(
240+
"""\
241+
You can also export the ST2_DATABASE__HOST and ST2_DATABASE__PORT
242+
env vars to automatically use any MongoDB host, local or remote,
243+
while running unit and integration tests. Note that you cannot
244+
override the db-name, which is st2-test suffixed by an integer
245+
to allow tests to safely run in parallel. If needed you can also
246+
override the default username, password, and connection timeout
247+
by exporting one or more of: ST2_DATABASE__USERNAME,
248+
ST2_DATABASE__PASSWORD, and ST2_DATABASE__CONNECTION_TIMEOUT.
249+
"""
250+
),
203251
),
204252
)
205253

pants-plugins/uses_services/mongo_rules_test.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,17 @@ def run_mongo_is_running(
5151
"--backend-packages=uses_services",
5252
*(extra_args or ()),
5353
],
54-
env_inherit={"PATH", "PYENV_ROOT", "HOME"},
54+
env_inherit={
55+
"PATH",
56+
"PYENV_ROOT",
57+
"HOME",
58+
"ST2_DATABASE__HOST",
59+
"ST2_DATABASE__PORT",
60+
"ST2_DATABASE__USERNAME",
61+
"ST2_DATABASE__PASSWORD",
62+
"ST2_DATABASE__CONNECTION_TIMEOUT",
63+
"ST2TESTS_PARALLEL_SLOT",
64+
},
5565
)
5666
result = rule_runner.request(
5767
MongoIsRunning,
@@ -62,7 +72,9 @@ def run_mongo_is_running(
6272

6373
# Warning this requires that mongo be running
6474
def test_mongo_is_running(rule_runner: RuleRunner) -> None:
65-
request = UsesMongoRequest()
75+
request = UsesMongoRequest.from_env(
76+
execution_slot_var="ST2TESTS_PARALLEL_SLOT", env=rule_runner.environment
77+
)
6678
mock_platform = platform(os="TestMock")
6779

6880
# we are asserting that this does not raise an exception

pants-plugins/uses_services/redis_rules.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,6 @@ async def redis_is_running(
143143
if is_running:
144144
return RedisIsRunning()
145145

146-
env_vars_hint = dedent(
147-
"""
148-
You can also export the ST2TESTS_REDIS_HOST and ST2TESTS_REDIS_PORT
149-
env vars to automatically use any redis host, local or remote,
150-
while running unit and integration tests.
151-
"""
152-
)
153146
# redis is not running, so raise an error with instructions.
154147
raise ServiceMissingError.generate(
155148
platform=platform,
@@ -162,21 +155,24 @@ async def redis_is_running(
162155
"""\
163156
sudo yum -y install redis
164157
# Don't forget to start redis.
165-
166158
"""
167-
)
168-
+ env_vars_hint,
159+
),
169160
service_start_cmd_deb="systemctl start redis",
170161
not_installed_clause_deb="this is one way to install it:",
171162
install_instructions_deb=dedent(
172163
"""\
173164
sudo apt-get install -y mongodb redis
174165
# Don't forget to start redis.
175-
176166
"""
177-
)
178-
+ env_vars_hint,
167+
),
179168
service_start_cmd_generic="systemctl start redis",
169+
env_vars_hint=dedent(
170+
"""\
171+
You can also export the ST2TESTS_REDIS_HOST and ST2TESTS_REDIS_PORT
172+
env vars to automatically use any redis host, local or remote,
173+
while running unit and integration tests.
174+
"""
175+
),
180176
),
181177
)
182178

pants-plugins/uses_services/scripts/is_mongo_running.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ def _is_mongo_running(
5454
db_name = args.get(3, "st2-test{}")
5555
connection_timeout_ms = args.get(4, 3000)
5656

57-
slot_var = args.get(5, "ST2TESTS_PARALLEL_SLOT")
57+
slot_var = os.environ.get(
58+
"PANTS_PYTEST_EXECUTION_SLOT_VAR", "ST2TESTS_PARALLEL_SLOT"
59+
)
5860
db_name = db_name.format(os.environ.get(slot_var) or "")
5961

6062
is_running = _is_mongo_running(

pants.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,13 @@ extra_env_vars = [
240240
# Use this so that the test system does not require the stanley user.
241241
# For example: export ST2TESTS_SYSTEM_USER=${USER}
242242
"ST2TESTS_SYSTEM_USER",
243+
# Use these to override MongoDB connection details
244+
# "ST2_DATABASE__HOST", # Tests override this with "127.0.0.1"
245+
"ST2_DATABASE__PORT",
246+
# "ST2_DATABASE__DB_NAME", # Tests override this with: "st2-test{ST2TESTS_PARALLEL_SLOT}"
247+
"ST2_DATABASE__CONNECTION_TIMEOUT",
248+
"ST2_DATABASE__USERNAME",
249+
"ST2_DATABASE__PASSWORD",
243250
# Use these to override the redis host and port
244251
"ST2TESTS_REDIS_HOST",
245252
"ST2TESTS_REDIS_PORT",

0 commit comments

Comments
 (0)