Skip to content

spark_on_k8s.planning

See the reference overview for supported entry points and task guides. A module may also contain helpers outside the documented public API.

ApplicationPlan dataclass

An offline preview; generated identifiers are illustrative, not reserved runs.

Source code in spark_on_k8s/planning.py
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
@dataclass(frozen=True)
class ApplicationPlan:
    """An offline preview; generated identifiers are illustrative, not reserved runs."""

    namespace: str
    app_id: str
    driver_pod: str
    resources: tuple[dict[str, Any], ...] = field(repr=False)
    capacity: dict[str, Any] | None = None

    def to_dict(self) -> dict[str, Any]:
        resources = copy.deepcopy(self.resources)
        for resource in resources:
            if resource["kind"] in {"Secret", "ConfigMap"}:
                for field in ("data", "stringData", "binaryData"):
                    if field in resource:
                        resource[field] = dict.fromkeys(resource[field], "<redacted>")
            if resource["kind"] == "Pod":
                containers = resource["spec"].get("containers", [])
                for index, container in enumerate(containers + resource["spec"].get("initContainers", [])):
                    for variable in container.get("env", []):
                        if "value" in variable:
                            variable["value"] = "<redacted>"
                    # Positional application arguments can contain credentials with no identifying key.
                    args = container.get("args", [])
                    if "command" in container:
                        container["command"] = ["<redacted command>" for _ in container["command"]]
                    if index == 0 and containers and args and args[0] == "driver":
                        position = 1
                        while position < len(args) and args[position].startswith("--"):
                            position += 2
                        if position < len(args):
                            args[position + 1 :] = ["<redacted argument>" for _ in args[position + 1 :]]
                    elif args:
                        container["args"] = ["<redacted argument>" for _ in args]
        return {
            "schema_version": 1,
            "preview": True,
            "namespace": self.namespace,
            "app_id": self.app_id,
            "driver_pod": self.driver_pod,
            "resources": [redact(resource) for resource in resources],
            "capacity": copy.deepcopy(self.capacity),
        }

redact(value, *, key='')

Return a display-only copy. Secret payloads and embedded file contents stay private.

Source code in spark_on_k8s/planning.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def redact(value: Any, *, key: str = "") -> Any:
    """Return a display-only copy. Secret payloads and embedded file contents stay private."""
    if _SENSITIVE.search(key) and not key.endswith(("KeyRef", "secretRef")):
        return "<redacted>"
    if isinstance(value, dict):
        return {name: redact(item, key=name) for name, item in value.items()}
    if isinstance(value, list):
        return [redact(item) for item in value]
    if isinstance(value, str):
        if "=" in value and (
            value.startswith(("spark.kubernetes.driverEnv.", "spark.executorEnv."))
            or _SENSITIVE.search(value.partition("=")[0])
        ):
            return value.partition("=")[0] + "=<redacted>"
        # Includes signed-URL parameters (Azure SAS sig, S3/GCS X-*-Signature and session tokens).
        value = re.sub(
            r"([?;&](?:x-(?:amz|goog)-)?(?:password|passwd|secret|token|credential|access[._-]?key"
            r"|private[._-]?key|api[._-]?key|sig|signature|security-token)=)[^&#;\s]*",
            r"\1<redacted>",
            value,
            flags=re.I,
        )
        return re.sub(r"([a-z][a-z0-9+.-]*://)[^/@\s]+:[^/@\s]+@", r"\1<redacted>@", value, flags=re.I)
    return value