Terraform is a powerful tool for managing configuration, particularly infrastructure. When it comes to applications, however, some of the Terraform assumptions and conventions do not apply directly. As a result, there are a few things specific to PingDirectory that have had to be addressed in a non-typical manner under Terraform. Some of these situations result in Terraform behaving a bit different than other providers; others require the use of attributes in a different manner in the provider when compared to normal PingDirectory operations.
This document will provide guidance on things you should know when either using the provider or if you wish to contribute to the provider.
Certain configuration objects are edit-only. These objects do not fit in the typical Terraform model. Terraform expects to manage the entire lifecycle of an object, from creation to deletion. In the case of PingDirectory, some objects are configured out of the box with default values. However, leaving these objects out of the control of Terraform would severely restrict the ability to manage PingDirectory configuration using Terraform HCL. As an example, consider the global configuration, which is very useful and often modified in PingDirectory; this resource is edit-only.
In these cases, the strategy in Terraform is to “adopt” them on a typical create, and "forget" them on a delete action. When Terraform forgets, the resource still exists and can be managed elsewhere. This pattern is what the PingDirectory provider has implemented for edit-only objects.
Any resource that comes in the PingDirectory configuration by default can be managed by adding a "default_" prefix onto the resource type in the HCL code. For example, to create a Location config object, you can use the "pingdirectory_location" resource. To adopt the server's default Location, the "pingdirectory_default_location" resource can be used.
However, there is one major difference between how the PingDirectory provider handles edit-only resources versus many other providers. This difference is in how the resource is initialized. In the create action of the some providers, all of the properties of the existing edit-only object are wiped and replaced completely with what is specified in the Terraform file. In the global configuration of PingDirectory, for example, this action was determined to be impractical. Doing a wipe would require the person managing the global configuration to specify every single property of the global configuration (over 80 in total) in order to manage it with Terraform. All properties would be managed, even if only one of them needed to be changed from the default. Instead, a strategy of marking every property as Optional and Computed in the Terraform schema was adopted. In this way, defaults and existing values are allowed to flow through from PingDirectory, and from that point the user only needs to specify the values to be modified and managed in the Terraform file.
While the global configuration is used as an example here, all default resources are handled in this manner.
As part of the default resource strategy, all optional attributes of these resources are defined as computed so that users do not need to specify every available attribute.
When running dsconfig commands, the instance is referred to using the name variable. The convention in a Terraform provider is to use id as the naming attribute in most cases.
For example, consider these two examples using dsconfig and the provider that accomplish the same thing:
-
dsconfig create-location \ --location-name MyLocation \ --set "description:My description" dsconfig set-global-configuration-prop \ --set encrypt-data:true
-
resource "pingdirectory_location" "mylocation" { name = "MyLocation" description = "My description" } resource "pingdirectory_default_global_configuration" "global" { encrypt_data = true }
In Terraform, you can mark attributes of the schema as Computed. This annotation means that the provider can set its own value for the attribute. In some cases with PingDirectory, the use of this convention becomes necessary. For example, for any optional boolean value in a configuration object, the attribute must be marked as Computed. This setting is because PingDirectory will return a default boolean value (false or true depending on the attribute) if no value is specified. The same is true for any optional Set values, as PingDirectory will return a default empty set if no value is specified. This also applies for any attributes that have a default value in PingDirectory.
Computed values lead to some complications when trying to “unset” a value for edit-only configuration objects. If you simply remove a value from your Terraform file for a resource, the former Computed value will just remain as-is; Terraform will see this as no changes having been made. This behavior means that unsetting a value for an edit-only resource requires a deliberate action.
- For strings, PingDirectory sees the empty string as equivalent to unsetting that string, so you can simply set that string property to empty.
- For sets, an empty set can be used.
- For booleans, there is no need to unset because true or false can be used.
- For integer values, however, there is no way to unset a value using Terraform after it has been set for PingDirectory edit-only objects due to the way they are currently implemented.
Empty strings are treated as the equivalent to null in the provider.
We appreciate your help! To contribute through logging issues or creating pull requests, please read the contribution guidelines