• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 18917981582

29 Oct 2025 06:16PM UTC coverage: 79.819% (-0.2%) from 80.004%
18917981582

Pull #22837

github

web-flow
Merge 05341325b into 1a7da5c5e
Pull Request #22837: Updated Treesitter dependencies

77044 of 96523 relevant lines covered (79.82%)

3.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.26
/src/python/pants/backend/helm/util_rules/post_renderer_test.py
1
# Copyright 2022 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
1✔
5

6
from textwrap import dedent
1✔
7

8
import pytest
1✔
9

10
from pants.backend.docker.target_types import (
1✔
11
    DockerImageTags,
12
    DockerImageTagsRequest,
13
    DockerImageTarget,
14
)
15
from pants.backend.helm.dependency_inference import deployment as infer_deployment
1✔
16
from pants.backend.helm.subsystems.post_renderer import (
1✔
17
    HELM_POST_RENDERER_CFG_FILENAME,
18
    HelmPostRenderer,
19
)
20
from pants.backend.helm.target_types import (
1✔
21
    HelmChartTarget,
22
    HelmDeploymentFieldSet,
23
    HelmDeploymentTarget,
24
)
25
from pants.backend.helm.testutil import HELM_CHART_FILE, HELM_TEMPLATE_HELPERS_FILE
1✔
26
from pants.backend.helm.util_rules import post_renderer
1✔
27
from pants.backend.helm.util_rules.post_renderer import HelmDeploymentPostRendererRequest
1✔
28
from pants.backend.helm.util_rules.renderer import (
1✔
29
    HelmDeploymentCmd,
30
    HelmDeploymentRequest,
31
    RenderedHelmFiles,
32
)
33
from pants.backend.helm.util_rules.testutil import _read_file_from_digest
1✔
34
from pants.backend.helm.util_rules.tool import HelmProcess
1✔
35
from pants.backend.shell.target_types import ShellCommandRunTarget, ShellSourcesGeneratorTarget
1✔
36
from pants.backend.shell.util_rules import shell_command
1✔
37
from pants.core.goals import package
1✔
38
from pants.core.goals.run import rules as run_rules
1✔
39
from pants.core.util_rules import source_files
1✔
40
from pants.engine.addresses import Address
1✔
41
from pants.engine.fs import CreateDigest, Digest, FileContent
1✔
42
from pants.engine.process import ProcessResult
1✔
43
from pants.engine.rules import QueryRule, rule
1✔
44
from pants.engine.target import Target
1✔
45
from pants.engine.unions import UnionRule
1✔
46
from pants.testutil.rule_runner import PYTHON_BOOTSTRAP_ENV, RuleRunner
1✔
47

48

49
class CustomTestImageTagRequest(DockerImageTagsRequest):
1✔
50
    @classmethod
1✔
51
    def is_applicable(cls, target: Target) -> bool:
1✔
52
        return "bar" in target.address.target_name
×
53

54

55
@rule
1✔
56
async def custom_test_image_tags(_: CustomTestImageTagRequest) -> DockerImageTags:
1✔
57
    return DockerImageTags(["custom-tag"])
×
58

59

60
@pytest.fixture
1✔
61
def rule_runner() -> RuleRunner:
1✔
62
    rule_runner = RuleRunner(
1✔
63
        target_types=[
64
            HelmChartTarget,
65
            HelmDeploymentTarget,
66
            DockerImageTarget,
67
            ShellSourcesGeneratorTarget,
68
            ShellCommandRunTarget,
69
        ],
70
        rules=[
71
            *infer_deployment.rules(),
72
            *source_files.rules(),
73
            *post_renderer.rules(),
74
            *run_rules(),
75
            *shell_command.rules(),
76
            *package.rules(),
77
            custom_test_image_tags,
78
            UnionRule(DockerImageTagsRequest, CustomTestImageTagRequest),
79
            QueryRule(HelmPostRenderer, (HelmDeploymentPostRendererRequest,)),
80
            QueryRule(RenderedHelmFiles, (HelmDeploymentRequest,)),
81
            QueryRule(ProcessResult, (HelmProcess,)),
82
        ],
83
    )
84
    source_root_patterns = ("src/*",)
1✔
85
    rule_runner.set_options(
1✔
86
        [
87
            f"--source-root-patterns={repr(source_root_patterns)}",
88
            "--helm-infer-external-docker-images=['busybox']",
89
        ],
90
        env_inherit=PYTHON_BOOTSTRAP_ENV,
91
    )
92
    return rule_runner
1✔
93

94

95
_TEST_GIVEN_CONFIGMAP_FILE = dedent(
1✔
96
    """\
97
    apiVersion: v1
98
    kind: ConfigMap
99
    metadata:
100
      name: foo-config
101
    data:
102
      foo_key: foo_value
103
    """
104
)
105

106
_TEST_EXPECTED_CONFIGMAP_FILE = (
1✔
107
    dedent(
108
        """\
109
      ---
110
      # Source: mychart/templates/configmap.yaml
111
      """
112
    )
113
    + _TEST_GIVEN_CONFIGMAP_FILE
114
)
115

116

117
def test_can_prepare_post_renderer(rule_runner: RuleRunner) -> None:
1✔
118
    rule_runner.write_files(
1✔
119
        {
120
            "src/mychart/BUILD": "helm_chart()",
121
            "src/mychart/Chart.yaml": HELM_CHART_FILE,
122
            "src/mychart/values.yaml": dedent(
123
                """\
124
                pods: []
125
                conditionalPodEnabled: false
126
                """
127
            ),
128
            "src/mychart/templates/_helpers.tpl": HELM_TEMPLATE_HELPERS_FILE,
129
            "src/mychart/templates/configmap.yaml": _TEST_GIVEN_CONFIGMAP_FILE,
130
            "src/mychart/templates/conditional-pod.yaml": dedent(
131
                """\
132
                # Conditional pod that should not break dependency inference when
133
                # it is not enabled. When not enabled, this manifest will consist
134
                # of _only_ these comment lines, which will not be parsable.
135
                {{- if .Values.conditionalPodEnabled }}
136
                apiVersion: v1
137
                kind: Pod
138
                metadata:
139
                  name: conditional-pod
140
                spec:
141
                  containers:
142
                    - name: busy
143
                      image: busybox:1.29
144
                {{- end }}
145
                """
146
            ),
147
            "src/mychart/templates/pod.yaml": dedent(
148
                """\
149
                {{- $root := . -}}
150
                {{- range $pod := .Values.pods }}
151
                ---
152
                apiVersion: v1
153
                kind: Pod
154
                metadata:
155
                  name: {{ template "fullname" $root }}-{{ $pod.name }}
156
                  labels:
157
                    chart: "{{ $root.Chart.Name }}-{{ $root.Chart.Version | replace "+" "_" }}"
158
                spec:
159
                  initContainers:
160
                    - name: myapp-init-container
161
                      image: {{ $pod.initContainerImage }}
162
                  containers:
163
                    - name: busy
164
                      image: busybox:1.29
165
                    - name: myapp-container
166
                      image: {{ $pod.appImage }}
167
                {{- end }}
168
                """
169
            ),
170
            "src/deployment/BUILD": "helm_deployment(name='test', chart='//src/mychart')",
171
            "src/deployment/values.yaml": dedent(
172
                """\
173
                pods:
174
                  - name: foo
175
                    initContainerImage: src/image:init_foo
176
                    appImage: src/image:app_foo
177
                  - name: bar
178
                    initContainerImage: src/image:init_bar
179
                    appImage: src/image:app_bar
180
                """
181
            ),
182
            "src/image/BUILD": dedent(
183
                """\
184
                docker_image(name="init_foo", source="Dockerfile.init")
185
                docker_image(name="app_foo", source="Dockerfile.app")
186

187
                docker_image(name="init_bar", source="Dockerfile.init")
188
                docker_image(name="app_bar", source="Dockerfile.app")
189
                """
190
            ),
191
            "src/image/Dockerfile.init": "FROM busybox:1.28",
192
            "src/image/Dockerfile.app": "FROM busybox:1.28",
193
        }
194
    )
195

196
    expected_config_file = dedent(
1✔
197
        """\
198
        ---
199
        mychart/templates/pod.yaml:
200
        - paths:
201
            /spec/containers/1/image: app_foo:latest
202
            /spec/initContainers/0/image: init_foo:latest
203
        - paths:
204
            /spec/containers/1/image: app_bar:custom-tag
205
            /spec/initContainers/0/image: init_bar:custom-tag
206
        """
207
    )
208

209
    expected_rendered_pod = dedent(
1✔
210
        """\
211
        ---
212
        # Source: mychart/templates/pod.yaml
213
        apiVersion: v1
214
        kind: Pod
215
        metadata:
216
          name: test-mychart-foo
217
          labels:
218
            chart: mychart-0.1.0
219
        spec:
220
          initContainers:
221
            - name: myapp-init-container
222
              image: init_foo:latest
223
          containers:
224
            - name: busy
225
              image: busybox:1.29
226
            - name: myapp-container
227
              image: app_foo:latest
228
        ---
229
        # Source: mychart/templates/pod.yaml
230
        apiVersion: v1
231
        kind: Pod
232
        metadata:
233
          name: test-mychart-bar
234
          labels:
235
            chart: mychart-0.1.0
236
        spec:
237
          initContainers:
238
            - name: myapp-init-container
239
              image: init_bar:custom-tag
240
          containers:
241
            - name: busy
242
              image: busybox:1.29
243
            - name: myapp-container
244
              image: app_bar:custom-tag
245
        """
246
    )
247

248
    deployment_addr = Address("src/deployment", target_name="test")
1✔
249
    tgt = rule_runner.get_target(deployment_addr)
1✔
250
    field_set = HelmDeploymentFieldSet.create(tgt)
1✔
251

252
    post_renderer = rule_runner.request(
1✔
253
        HelmPostRenderer,
254
        [HelmDeploymentPostRendererRequest(field_set)],
255
    )
256

257
    config_file = _read_file_from_digest(
×
258
        rule_runner, digest=post_renderer.digest, filename=HELM_POST_RENDERER_CFG_FILENAME
259
    )
260
    assert config_file == expected_config_file
×
261

262
    rendered_output = rule_runner.request(
×
263
        RenderedHelmFiles,
264
        [
265
            HelmDeploymentRequest(
266
                field_set=field_set,
267
                cmd=HelmDeploymentCmd.RENDER,
268
                description="Test post-renderer output",
269
                post_renderer=post_renderer,
270
            )
271
        ],
272
    )
273
    assert "mychart/templates/pod.yaml" in rendered_output.snapshot.files
×
274
    assert "mychart/templates/configmap.yaml" in rendered_output.snapshot.files
×
275

276
    rendered_configmap_file = _read_file_from_digest(
×
277
        rule_runner,
278
        digest=rendered_output.snapshot.digest,
279
        filename="mychart/templates/configmap.yaml",
280
    )
281
    assert rendered_configmap_file == _TEST_EXPECTED_CONFIGMAP_FILE
×
282

283
    rendered_pod_file = _read_file_from_digest(
×
284
        rule_runner, digest=rendered_output.snapshot.digest, filename="mychart/templates/pod.yaml"
285
    )
286
    assert rendered_pod_file == expected_rendered_pod
×
287

288

289
def test_use_simple_extra_post_renderer(rule_runner: RuleRunner) -> None:
1✔
290
    rule_runner.write_files(
1✔
291
        {
292
            "src/mychart/BUILD": "helm_chart()",
293
            "src/mychart/Chart.yaml": HELM_CHART_FILE,
294
            "src/mychart/templates/_helpers.tpl": HELM_TEMPLATE_HELPERS_FILE,
295
            "src/mychart/templates/configmap.yaml": _TEST_GIVEN_CONFIGMAP_FILE,
296
            "src/shell/BUILD": dedent(
297
                """\
298
              shell_sources(name="scripts")
299

300
              run_shell_command(
301
                name="custom_post_renderer",
302
                command="src/shell/my-script.sh",
303
                execution_dependencies=[":scripts"]
304
              )
305
              """
306
            ),
307
            "src/deployment/BUILD": dedent(
308
                """\
309
              helm_deployment(
310
                name="test",
311
                chart="//src/mychart",
312
                post_renderers=["//src/shell:custom_post_renderer"]
313
              )
314
              """
315
            ),
316
        }
317
    )
318

319
    # We need to create the post-renderer script as a digest to ensure it has running permissions.
320
    post_renderer_script_digest = rule_runner.request(
1✔
321
        Digest,
322
        [
323
            CreateDigest(
324
                [
325
                    FileContent(
326
                        path="src/shell/my-script.sh",
327
                        content=dedent(
328
                            """\
329
                            #!/bin/bash
330
                            cat <&0
331
                            """
332
                        ).encode(),
333
                        is_executable=True,
334
                    )
335
                ]
336
            )
337
        ],
338
    )
339

340
    rule_runner.write_digest(post_renderer_script_digest)
1✔
341

342
    deployment_addr = Address("src/deployment", target_name="test")
1✔
343
    tgt = rule_runner.get_target(deployment_addr)
1✔
344
    field_set = HelmDeploymentFieldSet.create(tgt)
1✔
345

346
    post_renderer = rule_runner.request(
1✔
347
        HelmPostRenderer,
348
        [HelmDeploymentPostRendererRequest(field_set)],
349
    )
350

351
    rendered_output = rule_runner.request(
×
352
        RenderedHelmFiles,
353
        [
354
            HelmDeploymentRequest(
355
                field_set=field_set,
356
                cmd=HelmDeploymentCmd.RENDER,
357
                description="Test post-renderer output",
358
                post_renderer=post_renderer,
359
            )
360
        ],
361
    )
362
    assert "mychart/templates/configmap.yaml" in rendered_output.snapshot.files
×
363

364
    rendered_configmap_file = _read_file_from_digest(
×
365
        rule_runner,
366
        digest=rendered_output.snapshot.digest,
367
        filename="mychart/templates/configmap.yaml",
368
    )
369
    assert rendered_configmap_file == _TEST_EXPECTED_CONFIGMAP_FILE
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc