Skip to content

Commit 9a70348

Browse files
committed
(wip) Add image pull policy to CLI kwargs
1 parent abdc993 commit 9a70348

File tree

5 files changed

+29
-6
lines changed

5 files changed

+29
-6
lines changed

backend/src/jobq_server/models.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from typing import Annotated, Any, Self, TypeAlias
66

77
from annotated_types import Ge
8-
from jobq import JobOptions
8+
from jobq import ImagePullPolicy, JobOptions
99
from pydantic import AfterValidator, BaseModel, Field, StrictStr
1010

1111
from jobq_server.utils.kueue import JobId, KueueWorkload, WorkloadSpec, WorkloadStatus
@@ -60,6 +60,7 @@ class CreateJobModel(BaseModel):
6060
image_ref: ImageRef
6161
mode: ExecutionMode
6262
options: JobOptions
63+
pull_policy: ImagePullPolicy = ImagePullPolicy.ALWAYS
6364
submission_context: SubmissionContext = Field(default_factory=dict)
6465

6566

backend/src/jobq_server/routers/jobs.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def job_fn(): ...
5050
detail=f"unsupported job execution mode: {opts.mode!r}",
5151
)
5252

53-
image = Image(opts.image_ref)
53+
image = Image(opts.image_ref, opts.pull_policy)
5454
workload_id = runner.run(job, image, opts.submission_context)
5555
return workload_id
5656

client/src/cli/commands/submit.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import openapi_client
99
from cli.types import Settings
1010
from cli.util import with_job_mgmt_api
11-
from jobq import Image, Job
11+
from jobq import Image, ImagePullPolicy, Job
1212
from jobq.submission_context import SubmissionContext
1313
from openapi_client import ExecutionMode
1414

@@ -32,6 +32,7 @@ def _submit_remote_job(
3232
client: openapi_client.JobManagementApi,
3333
job: Job,
3434
mode: ExecutionMode,
35+
pull_policy: ImagePullPolicy,
3536
settings: Settings,
3637
) -> None:
3738
# Job options sent to server do not need image options
@@ -44,6 +45,7 @@ def _submit_remote_job(
4445
file=job.file,
4546
image_ref=_build_image(job, mode).tag,
4647
mode=mode,
48+
pull_policy=pull_policy,
4749
options=openapi_client.JobOptions.model_validate(job.options.model_dump()),
4850
submission_context=SubmissionContext().to_dict(),
4951
)
@@ -57,13 +59,14 @@ def submit_job(
5759
settings: Settings,
5860
) -> None:
5961
mode = args.mode
62+
pull_policy = args.pull_policy
6063
logging.debug(f"Execution mode: {mode}")
6164
match mode:
6265
case ExecutionMode.LOCAL:
6366
# Run the job locally
6467
job()
6568
case _:
66-
_submit_remote_job(job, mode, settings=settings)
69+
_submit_remote_job(job, mode, pull_policy, settings=settings)
6770

6871

6972
def discover_job(args: argparse.Namespace) -> Job:
@@ -120,6 +123,12 @@ def add_parser(subparsers: Any, parent: argparse.ArgumentParser) -> None:
120123
choices=list(ExecutionMode),
121124
type=ExecutionMode,
122125
)
126+
parser.add_argument(
127+
"--pull-policy",
128+
default=ImagePullPolicy.ALWAYS,
129+
choices=list(ImagePullPolicy),
130+
type=ImagePullPolicy,
131+
)
123132

124133
parser.add_argument("entrypoint")
125134
# TODO: Factor out into command class

client/src/jobq/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from jobq import assembler
2-
from jobq.image import Image
2+
from jobq.image import Image, ImagePullPolicy
33
from jobq.job import (
44
ImageOptions,
55
Job,
@@ -14,6 +14,7 @@
1414
"Job",
1515
"JobOptions",
1616
"ImageOptions",
17+
"ImagePullPolicy",
1718
"ResourceOptions",
1819
"SchedulingOptions",
1920
"job",

client/src/jobq/image.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
from enum import Enum
2+
3+
4+
class ImagePullPolicy(Enum):
5+
ALWAYS = "Always"
6+
NEVER = "Never"
7+
IFNOTPRESENT = "IfNotPresent"
8+
9+
110
class Image:
2-
def __init__(self, tag: str) -> None:
11+
def __init__(
12+
self, tag: str, pull_policy: ImagePullPolicy = ImagePullPolicy.ALWAYS
13+
) -> None:
314
self.tag = tag
15+
self.pull_policy = pull_policy

0 commit comments

Comments
 (0)