|
| 1 | +apiVersion: infrastructure.kedge.faros.sh/v1alpha1 |
| 2 | +kind: Template |
| 3 | +metadata: |
| 4 | + name: cron-job |
| 5 | +spec: |
| 6 | + displayName: "Scheduled job" |
| 7 | + description: "A container that runs on a cron schedule and exits — CronJob only, no Service, no URL. Reports, cleanups, periodic syncs." |
| 8 | + category: Workloads |
| 9 | + version: 0.1.0 |
| 10 | + backend: kro |
| 11 | + # One-click provision defaults for the portal form. busybox's default |
| 12 | + # entrypoint exits 0 immediately, so the sample schedule visibly produces |
| 13 | + # completed Jobs with zero external setup. |
| 14 | + sampleValues: |
| 15 | + name: demo-job |
| 16 | + image: busybox:stable |
| 17 | + schedule: "*/30 * * * *" |
| 18 | + # Operational guidance for AI agents discovering this template over MCP. |
| 19 | + agent: |
| 20 | + usage: | |
| 21 | + Runs ONE container on a cron schedule; each run must do its work and |
| 22 | + EXIT 0. Choose this for periodic work — reports, cleanups, backups, |
| 23 | + syncs. It is the opposite lifecycle of the worker template (a process |
| 24 | + that runs forever): a cron-job container that never exits will pile up |
| 25 | + overlapping-forbidden runs, not "keep running". |
| 26 | +
|
| 27 | + YOU SUPPLY exactly one container image whose ENTRYPOINT performs the |
| 28 | + task and exits: 0 on success, non-zero on failure (failed runs are |
| 29 | + retried up to 3 times, then recorded as a failed Job). There is no |
| 30 | + command/args input — bake the task into the image entrypoint. |
| 31 | +
|
| 32 | + SCHEDULE: standard 5-field cron (schedule input, default "0 * * * *" = |
| 33 | + hourly, evaluated in UTC). Concurrent runs are forbidden — if a run is |
| 34 | + still going when the next tick fires, the new run is skipped. Runs may |
| 35 | + occasionally fire late or be skipped; the task must be idempotent and |
| 36 | + tolerate that. |
| 37 | +
|
| 38 | + This template has NO development mode — develop and test the image |
| 39 | + elsewhere, then provision it here. No network exposure; durable state |
| 40 | + belongs in a database template instance. |
| 41 | +
|
| 42 | + INPUTS you set when provisioning: name, image (both required); schedule. |
| 43 | + outputs: |
| 44 | + - "status.schedule — the active cron schedule." |
| 45 | + # ── Portal presentation ─────────────────────────────────────────────── |
| 46 | + view: |
| 47 | + columns: |
| 48 | + - header: Schedule |
| 49 | + path: spec.schedule |
| 50 | + type: code |
| 51 | + detail: |
| 52 | + - title: Configuration |
| 53 | + fields: |
| 54 | + - label: Schedule |
| 55 | + path: status.schedule |
| 56 | + type: code |
| 57 | + - label: Image |
| 58 | + path: spec.image |
| 59 | + type: code |
| 60 | + instanceCRD: |
| 61 | + group: infrastructure.kedge.faros.sh |
| 62 | + version: v1alpha1 |
| 63 | + resource: scheduledjobs |
| 64 | + kind: ScheduledJob |
| 65 | + schema: |
| 66 | + type: object |
| 67 | + properties: |
| 68 | + name: |
| 69 | + type: string |
| 70 | + description: "Logical name; used as the CronJob name in the tenant namespace." |
| 71 | + image: |
| 72 | + type: string |
| 73 | + description: "Container image whose entrypoint performs the task and exits (0 = success)." |
| 74 | + schedule: |
| 75 | + type: string |
| 76 | + default: "0 * * * *" |
| 77 | + description: "Standard 5-field cron expression, evaluated in UTC. Default: hourly." |
| 78 | + required: |
| 79 | + - name |
| 80 | + - image |
| 81 | + |
| 82 | + # ── backendConfig: the kro resource graph ───────────────────────────── |
| 83 | + # namespace: default is remapped to the per-tenant namespace on the runtime |
| 84 | + # cluster — same convention as every seed template. |
| 85 | + backendConfig: |
| 86 | + resources: |
| 87 | + - id: cronJob |
| 88 | + template: |
| 89 | + apiVersion: batch/v1 |
| 90 | + kind: CronJob |
| 91 | + metadata: |
| 92 | + name: ${schema.spec.name} |
| 93 | + namespace: default |
| 94 | + spec: |
| 95 | + schedule: ${schema.spec.schedule} |
| 96 | + # A run still going when the next tick fires wins; the new run is |
| 97 | + # skipped. Matches the agent contract above. |
| 98 | + concurrencyPolicy: Forbid |
| 99 | + successfulJobsHistoryLimit: 3 |
| 100 | + failedJobsHistoryLimit: 1 |
| 101 | + jobTemplate: |
| 102 | + spec: |
| 103 | + backoffLimit: 3 |
| 104 | + template: |
| 105 | + metadata: |
| 106 | + labels: |
| 107 | + app: ${schema.spec.name} |
| 108 | + spec: |
| 109 | + restartPolicy: Never |
| 110 | + containers: |
| 111 | + - name: job |
| 112 | + image: ${schema.spec.image} |
| 113 | + # Echoed from the materialized CronJob (this kro fork forbids ${schema.*} |
| 114 | + # in status — status may reference resources only). |
| 115 | + status: |
| 116 | + schedule: ${cronJob.spec.schedule} |
0 commit comments