Skip to content

Commit 0a57b8c

Browse files
committed
Restrict sandbox plugin to services
* Reject compiled operations that enable plugins.sandbox on non-service runs. * Allow disabled sandbox configs to keep existing job specs valid.
1 parent 6867ba9 commit 0a57b8c

3 files changed

Lines changed: 51 additions & 2 deletions

File tree

cli/polyaxon/_flow/operations/compiled_operation.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
from typing import Dict, List, Optional
22
from typing_extensions import Literal
33

4+
from clipped.compact.pydantic import model_validator, validation_after
5+
from clipped.config.schema import skip_partial
6+
47
from polyaxon._flow.io import V1IO
58
from polyaxon._flow.operations.base import BaseOp
69
from polyaxon._flow.params import ParamSpec, ops_params
7-
from polyaxon._flow.run import RunMixin, V1Runtime
10+
from polyaxon._flow.run import RunMixin, V1RunKind, V1Runtime
811
from polyaxon.exceptions import PolyaxonSchemaError
912

1013

@@ -21,6 +24,23 @@ class V1CompiledOperation(BaseOp, RunMixin):
2124
def get_run_kind(self):
2225
return self.run.kind if self.run else None
2326

27+
@model_validator(**validation_after)
28+
@skip_partial
29+
def validate_sandbox_kind(cls, values):
30+
plugins = cls.get_value_for_key("plugins", values)
31+
sandbox = cls.get_value_for_key("sandbox", plugins) if plugins else None
32+
if sandbox is None or sandbox is False:
33+
return values
34+
35+
run = cls.get_value_for_key("run", values)
36+
if not run or run.kind != V1RunKind.SERVICE:
37+
got = run.kind if run else "unset"
38+
raise ValueError(
39+
"plugins.sandbox is only supported on kind: service in this version. "
40+
f"Got kind: {got}."
41+
)
42+
return values
43+
2444
def validate_params(
2545
self,
2646
params: Optional[Dict] = None,

cli/tests/test_polyflow/test_ops/test_op_runs.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,35 @@ def test_job_refs_params(self):
864864
params=params, inputs=config.inputs, outputs=None, is_template=False
865865
)
866866

867+
def test_sandbox_requires_service(self):
868+
config_dict = {
869+
"plugins": {"sandbox": True},
870+
"run": {"kind": V1RunKind.JOB, "container": {"image": "test"}},
871+
}
872+
with self.assertRaises(ValidationError) as ctx:
873+
V1CompiledOperation.from_dict(config_dict)
874+
assert "plugins.sandbox is only supported" in str(ctx.exception)
875+
876+
config_dict = {
877+
"plugins": {"sandbox": "{{ inputs.sandbox }}"},
878+
"run": {"kind": V1RunKind.JOB, "container": {"image": "test"}},
879+
}
880+
with self.assertRaises(ValidationError) as ctx:
881+
V1CompiledOperation.from_dict(config_dict)
882+
assert "plugins.sandbox is only supported" in str(ctx.exception)
883+
884+
config_dict = {
885+
"plugins": {"sandbox": False},
886+
"run": {"kind": V1RunKind.JOB, "container": {"image": "test"}},
887+
}
888+
V1CompiledOperation.from_dict(config_dict)
889+
890+
config_dict = {
891+
"plugins": {"sandbox": True},
892+
"run": {"kind": V1RunKind.SERVICE, "container": {"image": "test"}},
893+
}
894+
V1CompiledOperation.from_dict(config_dict)
895+
867896
def test_executable(self):
868897
config_dict = {
869898
"startAt": "foo",

cli/tests/test_polyflow/test_plugins/test_plugins.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def test_get_from_spec(self):
9797
"externalHost": True,
9898
"sandbox": True,
9999
},
100-
"run": {"kind": V1RunKind.JOB, "container": {"image": "test"}},
100+
"run": {"kind": V1RunKind.SERVICE, "container": {"image": "test"}},
101101
}
102102
)
103103
plugins = compiled_operation.plugins

0 commit comments

Comments
 (0)