Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 203 additions & 0 deletions API_DEFAULTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# Handling API default values

The Fastly control plane API is, unfortunately, inconsistent in its
handling of default values for attributes of objects. Some of the
inconsistent behaviors generate unwelcome interactions with
Terraform's expectations of object states, so this document provides
guidance for how to handle various scenarios when creating or
modifying a object in the provider.

The goal of this guide is to eliminate, wherever possible, situations
where a user of the provider creates or modifies a object and then
immediately sees 'intended changes' when executing `terraform
plan`. Users are frustrated and confused when this occurs, as they
don't understand why Terraform thinks additional changes are necessary
when their previous `terraform apply` process completed successfully
and they haven't made changes to the objects outside of Terraform.

If you are building or modifying a resource or data source in this
provider and encounter an object attribute with default behavior which
does not match any of the types listed below, you'll need guidance
from the Fastly Developer Tools team before proceeding. If you are a
Fastlyan, ask the team for help in the #customer-dev-tools channel in
Slack. If you are not a Fastlyan, open an issue in this repository and
describe the situation you have encountered.

# Type A

* The attribute has a documented default.

* The default is applied when the user does not provide a value, or
provides a value of `null`, for the attribute in a `POST` operation
(creating the object), and when the user sets the attribute's
value to `null` in a `PUT` or `PATCH` operation (updating the
object).

* When the default is in effect, the attribute *does not appear* in
the response bodies returned by `GET`, `PUT`, and `PATCH`
operations.

* When the user provides a value for the attribute which happens to
match the default value, that value *does appear* in the response
bodies returned by `GET`, `PUT`, and `PATCH` operations.

## Examples

TBD

## Terraform expectations

This type matches Terraform's expectations.

# Type B

* The attribute has a documented default.

* The default is applied when the user does not provide a value, or
provides a value of `null`, for the attribute in a `POST` operation
(creating the object), and when the user sets the attribute's
value to `null` in a `PUT` or `PATCH` operation (updating the
object).

* When the default is in effect, the attribute *does not appear* in
the response bodies returned by `GET`, `PUT`, and `PATCH`
operations.

* When the user provides a value for the attribute which happens to
match the default value, that value *does not appear* in the
response bodies returned by `GET`, `PUT`, and `PATCH` operations.

## Examples

TBD

## Terraform expectations

The last two items in this type does not match Terraform's
expectations: when the object is read from the API (during import,
during planning, or after creation/modification), the attribute will
be missing. When the user executes `terraform plan` after any of these
operations, Terraform will propose to set the value again, as it
believes the value was unset/removed in the object being managed.

# Type C

* The attribute has a documented default.

* The default is applied when the user does not provide a value, or
provides a value of `null`, for the attribute in a `POST` operation
(creating the object), and when the user sets the attribute's
value to `null` in a `PUT` or `PATCH` operation (updating the
object).

* The attribute *always appears* in the response bodies returned by
`GET`, `PUT`, and `PATCH` operations.

## Examples

TBD

## Terraform expectations

The last item in this type does not match Terraform's
expectations: when the object is read from the API (during import,
during planning, or after creation/modification), the attribute will
be present even if the user did not include it in their HCL. When the
user executes `terraform plan` after any of these operations,
Terraform will propose to remove the value, as it believes the value
was set outside of Terraform in the object being managed.

# Type D

* The attribute has a documented default.

* The default is applied when the user does not provide a value, or
provides a value of `null`, for the attribute in a `POST` operation
(creating the object), and when the user sets the attribute's
value to `null` in a `PUT` or `PATCH` operation (updating the
object).

* When the default is in effect, the attribute *does appear* in the
response bodies returned by `GET`, `PUT`, and `PATCH` operations,
however its value is the 'base' value for the attribute's type
(empty string for string attributes, zero for numeric attributes).

* When the user provides a value for the attribute which happens to
match the default value, that value *does appear* in the response
bodies returned by `GET`, `PUT`, and `PATCH` operations.

## Examples

TBD

## Terraform expectations

The second-to-last item in this type does not match Terraform's
expectations: when the object is read from the API (during import,
during planning, or after creation/modification), the attribute will
be present even if the user did not include it in their HCL. When the
user executes `terraform plan` after any of these operations,
Terraform will propose to remove the value, as it believes the value
was set outside of Terraform in the object being managed.

# Type E

* The attribute has a documented default.

* The attribute is not optional, it must always be included in the
request body in `POST` operations (creating the object), and
`PUT`, and `PATCH` operations (updating the object).

* The API accepts the 'base' value for the attribute's type (empty
string for string attributes, zero for numeric attributes) but
treats that as equivalent to the default value.

* The attribute *always appears* in the response bodies returned by
`GET`, `PUT`, and `PATCH` operations. The returned value is the
value provided by the user.

## Examples

* The `period` attribute in HTTPS Logging endpoints.

## Terraform expectations

This type matches Terraform's expectations.

# Type F

* There are two attributes with documented defaults.

* Both attributes are optional, and the API is documented to consider
them mutually exclusive (it is documented to return an error if both
attributes are included in the request body of a `POST`, `PUT`, or
`PATCH` operation).

* When a value for one attribute is provided in the request body of a
`POST` operation (creating the object), the API may set the other
attribute to a default value derived from the provided value.

* When a value for one attribute is provided in the request body of a
`PUT` or `PATCH` operation (updating the object), the API may
change the value of the other attribute to a value derived from the
provided value.

* The attributes *always appear* in the response bodies returned by
`GET`, `PUT`, and `PATCH` operations.

## Examples

* The `compression_codec` and `gzip_level` attributes in various
Logging endpoints (HTTPS, S3, and others).

## Terraform expectations

The third and fourth items in this type do not match Terraform's
expectations: when the object is read from the API (during import,
during planning, or after creation/modification), one or both of the
attributes will be present even if the user did not include them in
their HCL. In addition, the value of one of the attributes may have
changed since the last time it was read. When the user executes
`terraform plan` after any of these operations, Terraform will propose
to change or remove the value, as it believes the value was modified
(outside of Terraform) in the object being managed.