awx/docs/schedules.md
Ryan Petrello 15906b7e3c
support TZID= in schedule rrules
this commit allows schedule `rrule` strings to include local timezone
information via TZID=NNNNN; occurrences are _generated_ in the local
time specific by the user (or UTC, if e.g., DTSTART:YYYYMMDDTHHMMSSZ)
while Schedule.next_run, Schedule.dtstart, and Schedule.dtend will be
stored in the UTC equivalent (i.e., the scheduler will still do math on
"what to run next" based on UTC datetimes).

in addition to this change, there is now a new API endpoint,
`/api/v2/schedules/preview/`, which takes an rrule and shows the next
10 occurrences in local and UTC time.

see: https://github.com/ansible/ansible-tower/issues/823
related: https://github.com/dateutil/dateutil/issues/614
2018-01-22 11:50:00 -05:00

5.0 KiB

Scheduled Jobs

awx allows jobs to run on a schedule (with optional recurrence rules) via an HTTP POST to a variety of API endpoints:

HTTP POST

https://tower-host.example.org/api/v2/job_templates/N/schedules/
https://tower-host.example.org/api/v2/projects/N/schedules/
https://tower-host.example.org/api/v2/inventory_sources/N/schedules/
https://tower-host.example.org/api/v2/system_jobs/N/schedules/
https://tower-host.example.org/api/v2/workflow_job_templates/N/schedules/

{
    'name': 'My Schedule Name',
    'rrule': 'DTSTART:20300115T120000Z RRULE:FREQ=DAILY;INTERVAL=1;COUNT=7'
    'extra_data': {}
}

...where rrule is a valid RFC5545 RRULE string. The specific example above would run a job every day - for seven consecutive days - starting on January 15th, 2030 at noon (UTC).

Specifying Timezones

DTSTART values provided to awx must provide timezone information (they may not be naive dates).

For UTC dates, DTSTART values should be denoted with the Z suffix:

DTSTART:20300115T120000Z

Local timezones can be specified using the TZID= parameter:

DTSTART;TZID=America/New_York:20300115T120000

A list of valid zone identifiers (which can vary by system) can be found at:

HTTP GET /api/v2/schedules/zoneinfo/

[
    "Africa/Abidjan",
    "Africa/Accra",
    "Africa/Addis_Ababa",
    ...
]

UNTIL and Timezones

RFC5545 specifies that:

Furthermore, if the "DTSTART" property is specified as a date with local time, then the UNTIL rule part MUST also be specified as a date with local time. If the "DTSTART" property is specified as a date with UTC time or a date with local time and time zone reference, then the UNTIL rule part MUST be specified as a date with UTC time.

Given this, this RRULE:

`DTSTART:20180601T120000Z RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20180606T170000Z`

...will be interpretted as "Starting on June 1st, 2018 at noon UTC, repeat daily, ending on June 6th, 2018 at 5PM UTC".

This RRULE:

`DTSTART;TZID=America/New_York:20180601T120000 RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20180606T170000`

...will be interpretted as "Starting on June 1st, 2018 at noon EDT, repeat daily, ending on June 6th, 2018 at 5PM EDT".

Previewing Schedules

awx provides an endpoint for previewing the future dates and times for a specified RRULE. A list of the next ten occurrences will be returned in local and UTC time:

POST https://tower-host.example.org/api/v2/schedules/preview/
{
    'rrule': 'DTSTART;TZID=America/New_York:20300115T120000 RRULE:FREQ=DAILY;INTERVAL=1;COUNT=7'
}

Content-Type: application/json
{
    "local": [
        "2030-01-15T12:00:00-05:00",
        "2030-01-16T12:00:00-05:00",
        "2030-01-17T12:00:00-05:00",
        "2030-01-18T12:00:00-05:00",
        "2030-01-19T12:00:00-05:00",
        "2030-01-20T12:00:00-05:00",
        "2030-01-21T12:00:00-05:00"
    ],
    "utc": [
        "2030-01-15T17:00:00Z",
        "2030-01-16T17:00:00Z",
        "2030-01-17T17:00:00Z",
        "2030-01-18T17:00:00Z",
        "2030-01-19T17:00:00Z",
        "2030-01-20T17:00:00Z",
        "2030-01-21T17:00:00Z"
    ]
}

RRULE Limitations

The following aspects of RFC5545 are not supported by awx schedules:

  • Strings with more than a single DTSTART: component
  • Strings with more than a single RRULE component
  • The use of FREQ=SECONDLY in an RRULE
  • The use of more than a single FREQ=BYMONTHDAY component in an RRULE
  • The use of more than a single FREQ=BYMONTHS component in an RRULE
  • The use of FREQ=BYYEARDAY in an RRULE
  • The use of FREQ=BYWEEKNO in an RRULE
  • The use of FREQ=BYWEEKNO in an RRULE
  • The use of COUNT= in an RRULE with a value over 999

Implementation Details

Any time an awx.model.Schedule is saved with a valid rrule value, the dateutil library is used to burst out a list of all occurrences. From here, the following dates are saved in the database:

  • main_schedule.rrule - the original RRULE string provided by the user
  • main_schedule.dtstart - the first datetime in the list of all occurrences (coerced to UTC)
  • main_schedule.dtend - the last datetime in the list of all occurrences (coerced to UTC)
  • main_schedule.next_run - the next datetime in list after utcnow() (coerced to UTC)

awx makes use of Celery Periodic Tasks (celerybeat) to run a periodic task that discovers new jobs that need to run at a regular interval (by default, every 30 seconds). When this task starts, it queries the database for Schedules where Schedule.next_run is between scheduler_last_runtime() and utcnow(). For each of these, a new job is launched, and Schedule.next_run is changed to the next chronological datetime in the list of all occurences.