Cron Notes

4 min read

Cron notes work with cron schedule expressions. They cover three problems: extracting individual fields from a string expression, converting between string and structured-map shapes, and producing human-readable descriptions.

Reference

NoteDescription
cronFromMapConvert a schedule map to a five-field cron string.
cronFromAnyConvert a schedule value to a five-field cron string.
cronToMapConvert a cron string to the structured map shape.
cronNormalizeNormalize a cron string: expand @-macros, trim whitespace, ensure exactly five fields.
cronDescribeReturn a human-readable description of a cron expression.
cronValidReturn true when the expression is structurally valid (five fields present after macro expansion).
cronExprBuild a five-field cron expression from five explicit string parts.
cronMinuteExtract a single field by position from a cron string.
cronHourExtract a single field by position from a cron string.
cronDomExtract a single field by position from a cron string.
cronMonthExtract a single field by position from a cron string.
cronDowExtract a single field by position from a cron string.
cronFieldExtract a field by index (0–4).

Examples

# cronFromMap
# onReconcile Path B — input is guaranteed a map by the when: gate
- name: "{{ .metadata.name }}"
  schedule: "{{ cronFromMap .spec.schedule }}"
  when:
    - field: spec.schedule
      operator: typeOf
      value: map
{minute: "*/5", hour: "0", dayOfMonth: "*", month: "*", dayOfWeek: "1"}
→ "*/5 0 * * 1"

# cronFromAny
# normalize block — user input may be either shape
normalize:
  spec:
    schedule: "{{ cronFromAny .spec.schedule }}"

# v2 → v1 conversion — legacy v2 objects may have a flat string
- from: v2
  to: v1
  spec:
    schedule: "{{ cronFromAny .spec.schedule }}"

# status field — safe regardless of stored shape
- path: scheduleExpression
  value: "{{ cronFromAny .spec.schedule }}"
{minute: "*/5", hour: "0", dayOfMonth: "*", month: "*", dayOfWeek: "1"}
→ "*/5 0 * * 1"

"*/5 0 * * 1"
→ "*/5 0 * * 1"   (string passthrough, normalised)
# Old:
schedule: >
  {{ if typeMap .spec.schedule }}{{ cronFromMap .spec.schedule }}
  {{ else }}{{ cronNormalize .spec.schedule }}{{ end }}

# New:
schedule: "{{ cronFromAny .spec.schedule }}"

# cronToMap
# v1 → v2 conversion path
- from: v1
  to: v2
  spec:
    schedule: "{{ cronToMap .spec.schedule }}"
"*/5 0 * * 1"
→ {minute:"*/5", hour:"0", dayOfMonth:"*", month:"*", dayOfWeek:"1"}

"@hourly"
→ {minute:"0", hour:"*", dayOfMonth:"*", month:"*", dayOfWeek:"*"}

# cronNormalize
# value: "{{ cronNormalize .spec.schedule }}"
# "@daily"      → "0 0 * * *"
# "@hourly"     → "0 * * * *"
# "*/5 * * * *" → "*/5 * * * *"  (unchanged, already valid)
# ""            → "* * * * *"

# cronDescribe
- path: scheduleDescription
  value: "{{ cronDescribe .spec.schedule }}"

# cronValid
validation:
  rules:
    - field: spec.schedule
      operator: custom
      value: "{{ cronValid .spec.schedule }}"
      message: "spec.schedule must be a valid cron expression"
      action: deny

# cronExpr
# value: "{{ cronExpr .spec.schedule.minute .spec.schedule.hour .spec.schedule.dayOfMonth .spec.schedule.month .spec.schedule.dayOfWeek }}"
# minute="*/1", hour="*", dom="*", month="*", dow="*" → "*/1 * * * *"

# cronMinute
# value: "{{ cronMinute \"*/5 2 * * 1\" }}"   → "*/5"
# value: "{{ cronHour   \"*/5 2 * * 1\" }}"   → "2"
# value: "{{ cronDom    \"0 0 15 * *\" }}"    → "15"
# value: "{{ cronMonth  \"0 0 1 6 *\" }}"     → "6"
# value: "{{ cronDow    \"0 0 * * 1\" }}"     → "1"

# cronHour
# value: "{{ cronMinute \"*/5 2 * * 1\" }}"   → "*/5"
# value: "{{ cronHour   \"*/5 2 * * 1\" }}"   → "2"
# value: "{{ cronDom    \"0 0 15 * *\" }}"    → "15"
# value: "{{ cronMonth  \"0 0 1 6 *\" }}"     → "6"
# value: "{{ cronDow    \"0 0 * * 1\" }}"     → "1"

# cronDom
# value: "{{ cronMinute \"*/5 2 * * 1\" }}"   → "*/5"
# value: "{{ cronHour   \"*/5 2 * * 1\" }}"   → "2"
# value: "{{ cronDom    \"0 0 15 * *\" }}"    → "15"
# value: "{{ cronMonth  \"0 0 1 6 *\" }}"     → "6"
# value: "{{ cronDow    \"0 0 * * 1\" }}"     → "1"

# cronMonth
# value: "{{ cronMinute \"*/5 2 * * 1\" }}"   → "*/5"
# value: "{{ cronHour   \"*/5 2 * * 1\" }}"   → "2"
# value: "{{ cronDom    \"0 0 15 * *\" }}"    → "15"
# value: "{{ cronMonth  \"0 0 1 6 *\" }}"     → "6"
# value: "{{ cronDow    \"0 0 * * 1\" }}"     → "1"

# cronDow
# value: "{{ cronMinute \"*/5 2 * * 1\" }}"   → "*/5"
# value: "{{ cronHour   \"*/5 2 * * 1\" }}"   → "2"
# value: "{{ cronDom    \"0 0 15 * *\" }}"    → "15"
# value: "{{ cronMonth  \"0 0 1 6 *\" }}"     → "6"
# value: "{{ cronDow    \"0 0 * * 1\" }}"     → "1"

# cronField
# value: "{{ cronField .spec.schedule 0 }}"   → minute field
# value: "{{ cronField .spec.schedule 3 }}"   → month field