0
# Task Execution
1
2
Abstract task runner framework supporting different deployment contexts (Local, Dev, Kubernetes) with Docker Compose integration. The task system provides a unified interface for executing commands across various deployment environments.
3
4
## Capabilities
5
6
### Base Task Runner
7
8
Abstract base class for all task execution contexts providing common functionality.
9
10
```python { .api }
11
class BaseTaskRunner:
12
"""
13
Abstract base class for task execution in different environments.
14
"""
15
def __init__(self, root: str, config: Config):
16
"""
17
Initialize task runner with root directory and configuration.
18
19
Args:
20
root (str): Project root directory path
21
config (Config): Configuration dictionary
22
"""
23
24
def run_task_from_template(self, service: str, *path: str) -> None:
25
"""
26
Run a task command loaded from a template file.
27
28
Args:
29
service (str): Service name to run task in
30
*path (str): Path components to template file containing command
31
"""
32
33
def run_task_from_str(self, service: str, command: str) -> None:
34
"""
35
Run a task command from a string.
36
37
Args:
38
service (str): Service name to run task in
39
command (str): Command string to execute
40
"""
41
42
def render(self, *path: str) -> str:
43
"""
44
Render a template file with current configuration.
45
46
Args:
47
*path (str): Path components to template file
48
49
Returns:
50
str: Rendered template content
51
"""
52
53
def run_task(self, service: str, command: str) -> int:
54
"""
55
Execute a command in the specified service. Must be implemented by subclasses.
56
57
Args:
58
service (str): Service name to run command in
59
command (str): Command to execute
60
61
Returns:
62
int: Exit code of the command
63
"""
64
```
65
66
### Docker Compose Task Runner
67
68
Base class for task runners that use Docker Compose for service management.
69
70
```python { .api }
71
class BaseComposeTaskRunner(BaseTaskRunner):
72
"""
73
Base class for Docker Compose-based task runners.
74
"""
75
def docker_compose(self, *command: str) -> int:
76
"""
77
Execute a docker-compose command. Must be implemented by subclasses.
78
79
Args:
80
*command (str): Docker Compose command arguments
81
82
Returns:
83
int: Exit code of the docker-compose command
84
"""
85
86
def run_task(self, service: str, command: str) -> int:
87
"""
88
Execute a command in a service using docker-compose exec.
89
90
Args:
91
service (str): Service name to run command in
92
command (str): Command to execute
93
94
Returns:
95
int: Exit code of the command
96
"""
97
98
def start(self) -> None:
99
"""
100
Start all services using docker-compose up.
101
"""
102
103
def stop(self) -> None:
104
"""
105
Stop all services using docker-compose stop.
106
"""
107
108
def restart(self) -> None:
109
"""
110
Restart all services.
111
"""
112
113
def logs(self, *services: str, follow: bool = False, tail: int = None) -> None:
114
"""
115
Display logs from services.
116
117
Args:
118
*services (str): Service names to show logs for (empty for all)
119
follow (bool): Follow log output
120
tail (int): Number of lines to show from end
121
"""
122
```
123
124
### Local Task Runner
125
126
Task runner for local development with Docker Compose.
127
128
```python { .api }
129
class LocalTaskRunner(BaseComposeTaskRunner):
130
"""
131
Task runner for local development environment.
132
"""
133
def docker_compose(self, *command: str) -> int:
134
"""
135
Execute docker-compose command with local configuration.
136
137
Args:
138
*command (str): Docker Compose command arguments
139
140
Returns:
141
int: Exit code of the command
142
"""
143
144
def is_running(self) -> bool:
145
"""
146
Check if local services are currently running.
147
148
Returns:
149
bool: True if services are running
150
"""
151
152
def launch(self, non_interactive: bool = False, pullimages: bool = False,
153
skip_build: bool = False) -> None:
154
"""
155
Configure and launch the platform from scratch.
156
157
Args:
158
non_interactive (bool): Skip interactive configuration
159
pullimages (bool): Pull images before starting
160
skip_build (bool): Skip building custom images
161
"""
162
```
163
164
### Development Task Runner
165
166
Task runner for development mode with additional debugging capabilities.
167
168
```python { .api }
169
class DevTaskRunner(BaseComposeTaskRunner):
170
"""
171
Task runner for development environment with debugging features.
172
"""
173
def docker_compose(self, *command: str) -> int:
174
"""
175
Execute docker-compose command with development configuration.
176
177
Args:
178
*command (str): Docker Compose command arguments
179
180
Returns:
181
int: Exit code of the command
182
"""
183
184
def hosts(self) -> None:
185
"""
186
Display status of all services with their URLs and access information.
187
"""
188
189
def launch(self, non_interactive: bool = False, pullimages: bool = False,
190
skip_build: bool = False) -> None:
191
"""
192
Configure and launch the platform in development mode.
193
194
Args:
195
non_interactive (bool): Skip interactive configuration
196
pullimages (bool): Pull images before starting
197
skip_build (bool): Skip building custom images
198
"""
199
```
200
201
### Kubernetes Task Runner
202
203
Task runner for Kubernetes deployments using kubectl.
204
205
```python { .api }
206
class K8sTaskRunner(BaseTaskRunner):
207
"""
208
Task runner for Kubernetes deployment environment.
209
"""
210
def kubectl(self, *command: str) -> int:
211
"""
212
Execute a kubectl command.
213
214
Args:
215
*command (str): kubectl command arguments
216
217
Returns:
218
int: Exit code of the kubectl command
219
"""
220
221
def run_task(self, service: str, command: str) -> int:
222
"""
223
Execute a command in a Kubernetes pod.
224
225
Args:
226
service (str): Service/pod name to run command in
227
command (str): Command to execute
228
229
Returns:
230
int: Exit code of the command
231
"""
232
233
def start(self) -> None:
234
"""
235
Start all Kubernetes resources.
236
"""
237
238
def stop(self) -> None:
239
"""
240
Stop all Kubernetes resources.
241
"""
242
243
def launch(self, non_interactive: bool = False, pullimages: bool = False,
244
skip_build: bool = False) -> None:
245
"""
246
Configure and launch the platform on Kubernetes.
247
248
Args:
249
non_interactive (bool): Skip interactive configuration
250
pullimages (bool): Pull images before starting
251
skip_build (bool): Skip building custom images
252
"""
253
254
def logs(self, *services: str, follow: bool = False, tail: int = None) -> None:
255
"""
256
Display logs from Kubernetes pods.
257
258
Args:
259
*services (str): Service names to show logs for
260
follow (bool): Follow log output
261
tail (int): Number of lines to show from end
262
"""
263
```
264
265
### Task Context Management
266
267
Context classes that provide environment-specific settings and behavior.
268
269
```python { .api }
270
class Context:
271
"""
272
Base context providing access to configuration and root directory.
273
"""
274
def __init__(self, root: str):
275
"""
276
Initialize context with project root.
277
278
Args:
279
root (str): Project root directory path
280
"""
281
282
@property
283
def root(self) -> str:
284
"""
285
Get the project root directory.
286
287
Returns:
288
str: Project root directory path
289
"""
290
291
class LocalContext(Context):
292
"""
293
Context for local development environment.
294
"""
295
pass
296
297
class DevContext(Context):
298
"""
299
Context for development environment with debugging features.
300
"""
301
pass
302
303
class K8sContext(Context):
304
"""
305
Context for Kubernetes deployment environment.
306
"""
307
pass
308
```
309
310
## Common Services
311
312
### Standard Service Names
313
314
Services available across different deployment environments.
315
316
```python { .api }
317
# Core Open edX services
318
"lms" # Learning Management System
319
"cms" # Content Management System (Studio)
320
"lms-worker" # LMS Celery worker
321
"cms-worker" # CMS Celery worker
322
323
# Supporting services
324
"mysql" # MySQL database
325
"redis" # Redis cache and message broker
326
"elasticsearch" # Search engine (if enabled)
327
"mongodb" # MongoDB (if enabled)
328
"caddy" # Reverse proxy (local/dev)
329
"nginx" # Web server (production)
330
331
# Development services
332
"lms-dev" # LMS development server
333
"cms-dev" # CMS development server
334
"openedx-dev" # Development image builder
335
```
336
337
## Usage Examples
338
339
### Local Development
340
341
```python
342
from tutor.commands.local import LocalTaskRunner, LocalContext
343
from tutor import config
344
345
# Initialize local environment
346
context = LocalContext("/path/to/tutor/root")
347
config_data = config.load(context.root)
348
runner = LocalTaskRunner(context.root, config_data)
349
350
# Launch platform
351
runner.launch(non_interactive=True)
352
353
# Check if running
354
if runner.is_running():
355
print("Platform is running")
356
357
# Run a command in LMS
358
runner.run_task("lms", "./manage.py lms shell")
359
360
# View logs
361
runner.logs("lms", "cms", follow=True)
362
```
363
364
### Development Mode
365
366
```python
367
from tutor.commands.dev import DevTaskRunner, DevContext
368
from tutor import config
369
370
# Initialize development environment
371
context = DevContext("/path/to/tutor/root")
372
config_data = config.load(context.root)
373
runner = DevTaskRunner(context.root, config_data)
374
375
# Launch in development mode
376
runner.launch()
377
378
# Show service URLs
379
runner.hosts()
380
381
# Run development tasks
382
runner.run_task("lms-dev", "python manage.py createsuperuser")
383
```
384
385
### Kubernetes Deployment
386
387
```python
388
from tutor.commands.k8s import K8sTaskRunner, K8sContext
389
from tutor import config
390
391
# Initialize Kubernetes environment
392
context = K8sContext("/path/to/tutor/root")
393
config_data = config.load(context.root)
394
runner = K8sTaskRunner(context.root, config_data)
395
396
# Deploy to Kubernetes
397
runner.launch(non_interactive=True)
398
399
# Check pod status
400
runner.kubectl("get", "pods")
401
402
# Execute command in pod
403
runner.run_task("lms", "python manage.py migrate")
404
405
# View pod logs
406
runner.logs("lms", follow=True, tail=100)
407
```
408
409
### Custom Task Execution
410
411
```python
412
from tutor.tasks import BaseTaskRunner
413
from tutor import config
414
415
class CustomTaskRunner(BaseTaskRunner):
416
def run_task(self, service: str, command: str) -> int:
417
# Custom implementation for task execution
418
print(f"Running {command} in {service}")
419
return 0
420
421
# Use custom runner
422
config_data = config.load("/path/to/tutor/root")
423
runner = CustomTaskRunner("/path/to/tutor/root", config_data)
424
425
# Run template-based task
426
runner.run_task_from_template("lms", "tasks", "migrate.sh")
427
428
# Run string command
429
runner.run_task_from_str("cms", "python manage.py collectstatic")
430
```
431
432
### Template-based Commands
433
434
```python
435
from tutor.commands.local import LocalTaskRunner, LocalContext
436
from tutor import config
437
438
context = LocalContext("/path/to/tutor/root")
439
config_data = config.load(context.root)
440
runner = LocalTaskRunner(context.root, config_data)
441
442
# Create template file at templates/tasks/custom-setup.sh
443
# Content: python manage.py migrate && python manage.py collectstatic
444
445
# Run task from template
446
runner.run_task_from_template("lms", "tasks", "custom-setup.sh")
447
448
# Template will be rendered with configuration variables
449
```