Skip to content

Commit 5373574

Browse files
authored
Merge pull request #5860: Add pants-plugins/sample_conf to streamline regenerating conf/st2.conf.sample
2 parents efa1b87 + a54e76e commit 5373574

13 files changed

+387
-3
lines changed

BUILD

+14
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,23 @@ python_requirements(
3131
"//:reqs#zake",
3232
]
3333
},
34+
# make sure anything that uses st2-auth-ldap gets the st2auth constant
35+
"st2-auth-ldap": {
36+
"dependencies": [
37+
"st2auth/st2auth/backends/constants.py",
38+
]
39+
},
3440
},
3541
)
3642

43+
target(
44+
name="auth_backends",
45+
dependencies=[
46+
"//:reqs#st2-auth-backend-flat-file",
47+
"//:reqs#st2-auth-ldap",
48+
],
49+
)
50+
3751
python_test_utils(
3852
name="test_utils",
3953
skip_pylint=True,

CHANGELOG.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Added
1414
working on StackStorm, improve our security posture, and improve CI reliability thanks in part
1515
to pants' use of PEX lockfiles. This is not a user-facing addition.
1616
#5778 #5789 #5817 #5795 #5830 #5833 #5834 #5841 #5840 #5838 #5842 #5837 #5849 #5850
17-
#5846 #5853 #5848 #5847 #5858 #5857
17+
#5846 #5853 #5848 #5847 #5858 #5857 #5860
1818
Contributed by @cognifloyd
1919

2020
* Added a joint index to solve the problem of slow mongo queries for scheduled executions. #5805

conf/BUILD

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ file(
33
source="st2rc.sample.ini",
44
)
55

6-
file(
6+
sample_conf( # defined in pants-plugins/sample_conf
77
name="st2.conf.sample",
88
source="st2.conf.sample",
9+
dependencies=[
10+
"tools/config_gen.py",
11+
],
912
)
1013

1114
file(

pants-plugins/README.md

+10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ To see available goals, do "./pants help goals" and "./pants help $goal".
1010

1111
These StackStorm-specific plugins are probably only useful for the st2 repo.
1212
- `api_spec`
13+
- `sample_conf`
1314
- `schemas`
1415

1516
### `api_spec` plugin
@@ -25,6 +26,15 @@ This plugin also wires up pants so that the `lint` goal runs additional
2526
api spec validation on `st2common/st2common/openapi.yaml` with something
2627
like `./pants lint st2common/st2common/openapi.yaml`.
2728

29+
### `sample_conf` plugin
30+
31+
This plugin wires up pants to make sure `conf/st2.conf.sample` gets
32+
regenerated whenever the source files change. Now, whenever someone runs
33+
the `fmt` goal (eg `./pants fmt conf/st2.conf.sample`), the sample will
34+
be regenerated if any of the files used to generate it have changed.
35+
Also, running the `lint` goal will fail if the sample needs to be
36+
regenerated.
37+
2838
### `schemas` plugin
2939

3040
This plugin wires up pants to make sure `contrib/schemas/*.json` gets

pants-plugins/sample_conf/BUILD

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
python_sources()
2+
3+
python_tests(
4+
name="tests",
5+
)

pants-plugins/sample_conf/__init__.py

Whitespace-only changes.

pants-plugins/sample_conf/register.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright 2023 The StackStorm Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from sample_conf.rules import rules as sample_conf_rules
16+
from sample_conf.target_types import SampleConf
17+
18+
19+
def rules():
20+
return [*sample_conf_rules()]
21+
22+
23+
def target_types():
24+
return [SampleConf]

pants-plugins/sample_conf/rules.py

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Copyright 2023 The StackStorm Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
from dataclasses import dataclass
15+
16+
from pants.backend.python.target_types import EntryPoint
17+
from pants.backend.python.util_rules import pex, pex_from_targets
18+
from pants.backend.python.util_rules.pex import (
19+
VenvPex,
20+
VenvPexProcess,
21+
)
22+
from pants.backend.python.util_rules.pex_from_targets import PexFromTargetsRequest
23+
from pants.core.goals.fmt import FmtResult, FmtTargetsRequest
24+
from pants.engine.addresses import Address
25+
from pants.engine.fs import (
26+
CreateDigest,
27+
Digest,
28+
FileContent,
29+
Snapshot,
30+
)
31+
from pants.engine.process import FallibleProcessResult
32+
from pants.engine.rules import Get, collect_rules, rule
33+
from pants.engine.target import FieldSet
34+
from pants.engine.unions import UnionRule
35+
from pants.util.logging import LogLevel
36+
37+
from sample_conf.target_types import SampleConfSourceField
38+
39+
40+
# these constants are also used in the tests.
41+
SCRIPT_DIR = "tools"
42+
SCRIPT = "config_gen"
43+
44+
45+
@dataclass(frozen=True)
46+
class GenerateSampleConfFieldSet(FieldSet):
47+
required_fields = (SampleConfSourceField,)
48+
49+
source: SampleConfSourceField
50+
51+
52+
class GenerateSampleConfViaFmtTargetsRequest(FmtTargetsRequest):
53+
field_set_type = GenerateSampleConfFieldSet
54+
name = SCRIPT
55+
56+
57+
@rule(
58+
desc=f"Update conf/st2.conf.sample with {SCRIPT_DIR}/{SCRIPT}.py",
59+
level=LogLevel.DEBUG,
60+
)
61+
async def generate_sample_conf_via_fmt(
62+
request: GenerateSampleConfViaFmtTargetsRequest,
63+
) -> FmtResult:
64+
# There will only be one target+field_set, but we iterate
65+
# to satisfy how fmt expects that there could be more than one.
66+
# If there is more than one, they will all get the same contents.
67+
68+
# actually generate it with an external script.
69+
# Generation cannot be inlined here because it needs to import the st2 code.
70+
pex = await Get(
71+
VenvPex,
72+
PexFromTargetsRequest(
73+
[
74+
Address(
75+
SCRIPT_DIR,
76+
target_name=SCRIPT_DIR,
77+
relative_file_path=f"{SCRIPT}.py",
78+
)
79+
],
80+
output_filename=f"{SCRIPT}.pex",
81+
internal_only=True,
82+
main=EntryPoint(SCRIPT),
83+
),
84+
)
85+
86+
result = await Get(
87+
FallibleProcessResult,
88+
VenvPexProcess(
89+
pex,
90+
description="Regenerating st2.conf.sample",
91+
),
92+
)
93+
94+
contents = [
95+
FileContent(
96+
f"{field_set.address.spec_path}/{field_set.source.value}",
97+
result.stdout,
98+
)
99+
for field_set in request.field_sets
100+
]
101+
102+
output_digest = await Get(Digest, CreateDigest(contents))
103+
output_snapshot = await Get(Snapshot, Digest, output_digest)
104+
return FmtResult.create(request, result, output_snapshot, strip_chroot_path=True)
105+
106+
107+
def rules():
108+
return [
109+
*collect_rules(),
110+
UnionRule(FmtTargetsRequest, GenerateSampleConfViaFmtTargetsRequest),
111+
*pex.rules(),
112+
*pex_from_targets.rules(),
113+
]
+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# Copyright 2023 The StackStorm Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
from __future__ import annotations
15+
16+
import pytest
17+
18+
from pants.backend.python import target_types_rules
19+
from pants.backend.python.target_types import PythonSourcesGeneratorTarget
20+
21+
from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
22+
from pants.engine.addresses import Address
23+
from pants.engine.fs import CreateDigest, Digest, FileContent, Snapshot
24+
from pants.engine.target import Target
25+
from pants.core.goals.fmt import FmtResult
26+
from pants.testutil.rule_runner import QueryRule, RuleRunner
27+
28+
from .rules import (
29+
SCRIPT,
30+
SCRIPT_DIR,
31+
GenerateSampleConfFieldSet,
32+
GenerateSampleConfViaFmtTargetsRequest,
33+
rules as sample_conf_rules,
34+
)
35+
from .target_types import SampleConf
36+
37+
38+
@pytest.fixture
39+
def rule_runner() -> RuleRunner:
40+
return RuleRunner(
41+
rules=[
42+
*sample_conf_rules(),
43+
*target_types_rules.rules(),
44+
QueryRule(FmtResult, (GenerateSampleConfViaFmtTargetsRequest,)),
45+
QueryRule(SourceFiles, (SourceFilesRequest,)),
46+
],
47+
target_types=[SampleConf, PythonSourcesGeneratorTarget],
48+
)
49+
50+
51+
def run_st2_generate_sample_conf(
52+
rule_runner: RuleRunner,
53+
targets: list[Target],
54+
*,
55+
extra_args: list[str] | None = None,
56+
) -> FmtResult:
57+
rule_runner.set_options(
58+
[
59+
"--backend-packages=sample_conf",
60+
f"--source-root-patterns=/{SCRIPT_DIR}",
61+
*(extra_args or ()),
62+
],
63+
env_inherit={"PATH", "PYENV_ROOT", "HOME"},
64+
)
65+
field_sets = [GenerateSampleConfFieldSet.create(tgt) for tgt in targets]
66+
input_sources = rule_runner.request(
67+
SourceFiles,
68+
[
69+
SourceFilesRequest(field_set.source for field_set in field_sets),
70+
],
71+
)
72+
fmt_result = rule_runner.request(
73+
FmtResult,
74+
[
75+
GenerateSampleConfViaFmtTargetsRequest(
76+
field_sets, snapshot=input_sources.snapshot
77+
),
78+
],
79+
)
80+
return fmt_result
81+
82+
83+
# copied from pantsbuild/pants.git/src/python/pants/backend/python/lint/black/rules_integration_test.py
84+
def get_snapshot(rule_runner: RuleRunner, source_files: dict[str, str]) -> Snapshot:
85+
files = [
86+
FileContent(path, content.encode()) for path, content in source_files.items()
87+
]
88+
digest = rule_runner.request(Digest, [CreateDigest(files)])
89+
return rule_runner.request(Snapshot, [digest])
90+
91+
92+
# add dummy script at tools/config_gen.py that the test can load.
93+
SCRIPT_PY = """
94+
def main():
95+
sample_conf_text = "{sample_conf_text}"
96+
print(sample_conf_text)
97+
98+
99+
if __name__ == "__main__":
100+
main()
101+
"""
102+
103+
104+
def write_files(
105+
sample_conf_dir: str,
106+
sample_conf_file: str,
107+
before: str,
108+
after: str,
109+
rule_runner: RuleRunner,
110+
) -> None:
111+
files = {
112+
f"{sample_conf_dir}/{sample_conf_file}": before,
113+
f"{sample_conf_dir}/BUILD": f"sample_conf(name='t', source='{sample_conf_file}')",
114+
# add in the target that's hard-coded in the generate_sample_conf_via_fmt rue
115+
f"{SCRIPT_DIR}/{SCRIPT}.py": SCRIPT_PY.format(sample_conf_text=after),
116+
f"{SCRIPT_DIR}/__init__.py": "",
117+
f"{SCRIPT_DIR}/BUILD": "python_sources()",
118+
}
119+
120+
rule_runner.write_files(files)
121+
122+
123+
def test_changed(rule_runner: RuleRunner) -> None:
124+
write_files(
125+
sample_conf_dir="my_dir",
126+
sample_conf_file="dummy.conf",
127+
before="BEFORE",
128+
after="AFTER",
129+
rule_runner=rule_runner,
130+
)
131+
132+
tgt = rule_runner.get_target(
133+
Address("my_dir", target_name="t", relative_file_path="dummy.conf")
134+
)
135+
fmt_result = run_st2_generate_sample_conf(rule_runner, [tgt])
136+
assert fmt_result.output == get_snapshot(
137+
rule_runner, {"my_dir/dummy.conf": "AFTER\n"}
138+
)
139+
assert fmt_result.did_change is True
140+
141+
142+
def test_unchanged(rule_runner: RuleRunner) -> None:
143+
write_files(
144+
sample_conf_dir="my_dir",
145+
sample_conf_file="dummy.conf",
146+
before="AFTER\n",
147+
after="AFTER", # print() adds a newline
148+
rule_runner=rule_runner,
149+
)
150+
151+
tgt = rule_runner.get_target(
152+
Address("my_dir", target_name="t", relative_file_path="dummy.conf")
153+
)
154+
fmt_result = run_st2_generate_sample_conf(rule_runner, [tgt])
155+
assert fmt_result.output == get_snapshot(
156+
rule_runner, {"my_dir/dummy.conf": "AFTER\n"}
157+
)
158+
assert fmt_result.did_change is False

0 commit comments

Comments
 (0)