Skip to content

Commit

Permalink
helm: add option to disable k8s manifest parsing for dependency infer…
Browse files Browse the repository at this point in the history
…ence (#21282)

We have a lot of `helm_deployments`, so any `pants dependents` call is
super slow, because helm is trying to parse all the helm_deployments.
It's really sad, because we don't even use the docker image inference
and specify the dependencies manually!

So here I introduce a flag `--helm-infer-deployment-dependencies` which
can disable that costly parsing. The option controls whether Pants will
parse k8s manifests generated by helm to find dependencies on other
targets like docker images.
  • Loading branch information
grihabor authored Aug 21, 2024
1 parent 680e6d2 commit a2134e3
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 11 deletions.
2 changes: 2 additions & 0 deletions docs/notes/2.23.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ Fixed pulling `helm_artifact`s from OCI repositories.

Improve warning on dependent images not being found. Pants can now validate that values passed into Helm charts that will be used for container images are valid `docker_image` targets or known 3rd-party images. See the [documentation in the helm-infer subsystem](https://www.pantsbuild.org/2.23/reference/subsystems/helm-infer).

Added option `[helm-infer].deployment_dependencies` to disable costly parsing of k8s manifests.

#### Shell

Added `workspace_invalidation_sources` field to `adhoc_tool` and `shell_command` target types. This new field allows declaring that these targets depend on files without bringing those files into the execution sandbox, but that the target should still be re-executed if those files change. This is intended to work with the `workspace_environment` support where processes are executed in the workspace and not in a separate sandbox.
Expand Down
30 changes: 23 additions & 7 deletions src/python/pants/backend/helm/dependency_inference/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,16 +278,32 @@ class InferHelmDeploymentDependenciesRequest(InferDependenciesRequest):
@rule(desc="Find the dependencies needed by a Helm deployment")
async def inject_deployment_dependencies(
request: InferHelmDeploymentDependenciesRequest,
infer_subsystem: HelmInferSubsystem,
) -> InferredDependencies:
chart_address, explicitly_provided_deps, mapping = await MultiGet(
Get(Address, AddressInput, request.field_set.chart.to_address_input()),
Get(ExplicitlyProvidedDependencies, DependenciesRequest(request.field_set.dependencies)),
Get(
FirstPartyHelmDeploymentMapping,
FirstPartyHelmDeploymentMappingRequest(request.field_set),
),
get_address = Get(Address, AddressInput, request.field_set.chart.to_address_input())
get_explicit_deps = Get(
ExplicitlyProvidedDependencies,
DependenciesRequest(request.field_set.dependencies),
)

if infer_subsystem.deployment_dependencies:
chart_address, explicitly_provided_deps, mapping = await MultiGet(
get_address,
get_explicit_deps,
Get(
FirstPartyHelmDeploymentMapping,
FirstPartyHelmDeploymentMappingRequest(request.field_set),
),
)
else:
(chart_address, explicitly_provided_deps), mapping = (
await MultiGet(get_address, get_explicit_deps),
FirstPartyHelmDeploymentMapping(
request.field_set.address,
FrozenYamlIndex.empty(),
),
)

dependencies: OrderedSet[Address] = OrderedSet()
dependencies.add(chart_address)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from enum import Enum
from functools import cached_property

from pants.option.option_types import EnumOption, StrListOption
from pants.option.option_types import BoolOption, EnumOption, StrListOption
from pants.option.subsystem import Subsystem
from pants.util.strutil import softwrap

Expand Down Expand Up @@ -73,6 +73,12 @@ class HelmInferSubsystem(Subsystem):
),
)

deployment_dependencies = BoolOption(
default=True,
help="If true, parse k8s manifests generated by helm to find dependencies on other targets like docker images.",
advanced=True,
)

@cached_property
def external_base_images(self) -> set[str]:
return set(self.external_docker_images)
11 changes: 8 additions & 3 deletions src/python/pants/backend/helm/utils/yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def insert(
def frozen(self) -> FrozenYamlIndex[T]:
"""Transforms this collection into a frozen (immutable) one."""

return FrozenYamlIndex(self)
return FrozenYamlIndex.create(self)


@dataclass(frozen=True)
Expand Down Expand Up @@ -190,7 +190,8 @@ class FrozenYamlIndex(Generic[T]):

_data: FrozenDict[PurePath, Collection[_YamlDocumentIndexNode[T]]]

def __init__(self, other: MutableYamlIndex[T]) -> None:
@classmethod
def create(cls, other: MutableYamlIndex[T]) -> FrozenYamlIndex[T]:
data: dict[PurePath, Collection[_YamlDocumentIndexNode[T]]] = {}
for file_path, doc_index in other._data.items():
max_index = max(doc_index.keys())
Expand All @@ -202,7 +203,11 @@ def __init__(self, other: MutableYamlIndex[T]) -> None:
doc_list[idx] = _YamlDocumentIndexNode(paths=FrozenDict(item_map))

data[file_path] = Collection(doc_list)
object.__setattr__(self, "_data", FrozenDict(data))
return FrozenYamlIndex(_data=FrozenDict(data))

@classmethod
def empty(cls: type[FrozenYamlIndex[T]]) -> FrozenYamlIndex[T]:
return FrozenYamlIndex[T](_data=FrozenDict())

def transform_values(self, func: Callable[[T], Optional[R]]) -> FrozenYamlIndex[R]:
"""Transforms the values of the given indexed collection into those that are returned from
Expand Down

0 comments on commit a2134e3

Please sign in to comment.