Ilija Matoski

    ← Articles

    Generating a terraform provider from the AWX API

    AWX describes its own resources if you send it an OPTIONS request, so writing the schemas by hand was work I did not need to do.

    A year of hand writing resources for the AWX provider taught me that I was doing work the API had already done for me.

    If you send an OPTIONS request to any AWX endpoint it tells you the fields, the types, whether each one is required, whether it is read only, and what the help text is.

    curl -sk -u admin:password -X OPTIONS \
    https://awx.example.com/api/v2/organizations/ | jq '.actions.POST'

    That is the schema, and it’s the same thing I’d been typing out by hand from the documentation, except that it comes from the running version and it can’t drift.

    So we stopped writing resources and started generating them, the provider reads the API description, writes the Go, and what comes out the other end is what ships.

    Getting there meant tearing the repository apart, which took a few passes, and it’s why the history around October 2023 is almost entirely refactors.

    The API data moved out into its own tree, one directory per AWX version, so we can see what changed between versions by diffing two directories instead of reading a changelog.

    The package got renamed to include the version it was generated from, which looked strange at first.

    It turned out to be the thing that made supporting more than one AWX version possible later on.

    One thing worth fixing while everything was moving anyway was the provider option called insecure_skip_verify.

    It is now verify_ssl, which is what AWX itself calls it, and it means the option reads the same way in both places.

    The generator is templates and a config file.

    The config is where the exceptions live, because the API description is right most of the time and wrong in specific, boring ways.

    Some fields come back as strings that are really enums, some are write only and must never be read back into state, and some endpoints don’t support PATCH at all.

    None of that is in the OPTIONS output, so we carry it in the config, per version, and the generator applies it on the way through.

    Adding a resource isn’t a coding task any more, we regenerate, and if AWX has a new endpoint then the provider has it too.

    make generate build VERSION=23.5.1

    The part I did not expect is how much of the work becomes reviewing a diff of generated code instead of writing it.

    That is a different skill and it takes some getting used to.