The below example script handles most of the annoying parts of implementing
the protocol between Python and Terraform when using the external
resource
type. In order to prevent required dependencies, this script only uses
built-in Python modules for argument parsing and result serialization. It
will current do the following:
- Automatically parse and validate input arguments based on defined
dataclass
as defined by the Terraform protocol specification. - Automatically serialize output results based on defined
dataclass
as defined by the Terraform protocol specification. - Automatically handle any uncaught exceptions and output errors in accordance with the Terraform protocol specification.
You should first define the dataclass representing your input arguments by
editing the QueryInput
class. This is a standard Python dataclass. The
parsing is not complex, but is capable of recognizing arguments with
defaults as optional (via dataclasses.field(default=...)
or
dataclasses.field(default_factor=...)
).
The parse_input()
function will also automatically return errors to
Terraform using exit_error
if any of the following conditions are
detected:
- Parsing the JSON document from stdin fails.
- The JSON object passed via stdin is not a dictionary.
- A query argument was passed that does not exist in
QueryInput
. - A field of
QueryInput
was missing from the input and has no defaults.
Terraform only allows a single key-value input to external scripts, and
values are restricted to the string type. The parser implemented in
parse_input
will attempt to coerce input strings to the declared
field type by simply calling field.type(value)
. This does not work
in all cases. For more complex types, you should probably override your
constructor in order to sainly handle this.
The Response
dataclass is used to return results from your main function.
It will be serialized automatically to JSON before returning it to Terraform.
You can add any fields you like.
NOTE: Terraform only allows string key-value pairs in the response, so
the exit_result
function will attempt to coerce any values in your Result
object to a string using str()
. Additionally, bool
values are coerced
using str(value).lower()
in order to produce the nicer true
and false
strings.
The main()
function is used for your main script execution. It is only
called if the input was correctly validated from QueryInput
, and is
passed an instance of QueryInput
as it's only argument.
Any exceptions raised in main()
will be caught. An error message containing
the string representation of the exception object will be printed to stderr
and an exit code of 1
will be returned from the process in accordance with
the Terraform protocol specification.
The main()
function should return an instance of the Result
class which
will be automatically serialized and returned to Terraform to be stored in
the Terraform State.