Skip to content
This repository has been archived by the owner on Jun 4, 2024. It is now read-only.

Terraform provider: make version mandatory and immutable #1007

Merged
merged 2 commits into from
Jan 30, 2024
Merged
Changes from 1 commit
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
Next Next commit
tf: make version mandatory
hugoShaka committed Jan 23, 2024
commit ab2705cc825d782af65afc02fa38fb153114e8f5
39 changes: 39 additions & 0 deletions terraform/gen/referencedocs.go.tpl
Original file line number Diff line number Diff line change
@@ -67,6 +67,45 @@ provider "teleport" {
root_ca_path = "tf.ca"
}
```

## Provider resource versioning

Since Teleport 15, you MUST set the version on each resource, and version cannot
be changed in-place. Terraform will delete the resource and create a new one if
a version change is required.

This is not enforced on previous Teleport provider versions, but we recommend doing
so. When the version is not specified, Terraform will pick the latest one by default.
However, version upgrades don't re-apply the resource defaults. This could lead
to different results if you create a new resource or upgrade an existing one.
To mitigate this, you should explicitly set the resource version.

<Adminition type="danger">
Upgrading the Terraform Provider to a new version with `teleport_role`
resources without a specified version can change the role behavior and access
rules. You must set the role version before upgrading to ensure the role
access rules don't change.

The default role version is the highest supported:

* v12 default role version is `v5`
* v13 default role version is `v6`
* v14 default role version is `v7`

For example, before upgrading from v12 to v13, edit every unversionned role
to pin the `v5` version:

```terraform
resource "teleport_role" "test" {
version = "v5"
metadata = {
name = "my-role"
}
// ...
}
```
</Adminition>

{{range $_, $resource := .resourcesDoc}}
## {{$resource.Name}}

13 changes: 13 additions & 0 deletions terraform/protoc-gen-terraform-accesslist.yaml
Original file line number Diff line number Diff line change
@@ -46,14 +46,27 @@ computed_fields:
# These fields will be marked as Required: true
required_fields:
- "Metadata.name"
- "AccessList.header.version"
- "AccessList.spec.owners"
- "AccessList.spec.grants"
- "AccessList.spec.audit"
- "AccessList.spec.audit.recurrence"
- "AccessList.spec.audit.recurrence.frequency"

plan_modifiers:
# Force to recreate resource if it's name changes
Metadata.name:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"

# Version MUST NOT change. Due to the way Terraform imports back the resource
# in its state (the provider relies on `USeStateForUnknown`) and the fact
# Teleport mixes the injected defaults with the original resource, defaults
# are set only on resource creation. Upgrading an existing resource will
# create a hybrid: a resource with the new version but old defaults.
AccessList.header.version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"

# This must be defined for the generator to be happy, but in reality all time
# fields are overridden (because the protobuf timestamps contain locks and the
# linter gets mad if we use raw structs instead of pointers).
13 changes: 10 additions & 3 deletions terraform/protoc-gen-terraform-devicetrust.yaml
Original file line number Diff line number Diff line change
@@ -32,7 +32,6 @@ computed_fields:
# Metadata
- "DeviceV1.Metadata"
- "DeviceV1.Kind"
- "DeviceV1.Version"
# DeviceV1
- "DeviceV1.spec.enroll_status"

@@ -41,6 +40,7 @@ computed_fields:
required_fields:
- "DeviceV1.spec.asset_tag"
- "DeviceV1.spec.os_type"
- "DeviceV1.Version"


exclude_fields:
@@ -54,12 +54,20 @@ exclude_fields:
- "DeviceV1.spec.update_time"
- "DeviceV1.spec.credential"
- "DeviceV1.spec.collected_data"

- "DeviceV1.spec.profile"

plan_modifiers:
# Force to recreate resource if asset tag changes
"DeviceV1.spec.asset_tag":
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
# Version MUST NOT change. Due to the way Terraform imports back the resource
# in its state (the provider relies on `USeStateForUnknown`) and the fact
# Teleport mixes the injected defaults with the original resource, defaults
# are set only on resource creation. Upgrading an existing resource will
# create a hybrid: a resource with the new version but old defaults.
DeviceV1.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"


time_type:
@@ -68,4 +76,3 @@ time_type:
cast_to_type: "time.Time"
cast_from_type: "time.Time"
type_constructor: "github.com/gravitational/teleport-plugins/terraform/tfschema.UseRFC3339Time()"

14 changes: 11 additions & 3 deletions terraform/protoc-gen-terraform-loginrule.yaml
Original file line number Diff line number Diff line change
@@ -38,14 +38,22 @@ computed_fields:
# These fields will be marked as Required: true
required_fields:
# LoginRule
- "LoginRule.Metadata.Name"
- "LoginRule.Version"
- "LoginRule.Priority"
- "Metadata.Name"
- "LoginRule.version"
- "LoginRule.priority"

plan_modifiers:
# Force to recreate resource if it's name changes
Metadata.Name:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
# Version MUST NOT change. Due to the way Terraform imports back the resource
# in its state (the provider relies on `USeStateForUnknown`) and the fact
# Teleport mixes the injected defaults with the original resource, defaults
# are set only on resource creation. Upgrading an existing resource will
# create a hybrid: a resource with the new version but old defaults.
LoginRule.version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"

validators:
Metadata.Expires:
85 changes: 65 additions & 20 deletions terraform/protoc-gen-terraform-teleport.yaml
Original file line number Diff line number Diff line change
@@ -163,7 +163,6 @@ computed_fields:
# App
- "AppV3.Metadata.Labels"
- "AppV3.Kind"
- "AppV3.Version"

# Auth preference
- "AuthPreferenceV2.Spec.SecondFactor"
@@ -172,11 +171,9 @@ computed_fields:
- "AuthPreferenceV2.Metadata.Namespace"
- "AuthPreferenceV2.Metadata.Labels"
- "AuthPreferenceV2.Kind"
- "AuthPreferenceV2.Version"

# ClusterMaintenanceConfig
- "ClusterMaintenanceConfigV1.Kind"
- "ClusterMaintenanceConfigV1.Version"

# Cluster networking
- "ClusterNetworkingConfigV2.Spec.KeepAliveCountMax"
@@ -186,25 +183,20 @@ computed_fields:

# Database
- "DatabaseV3.Kind"
- "DatabaseV3.Version"

# Github connector
- "GithubConnectorV3.Kind"
- "GithubConnectorV3.Version"

# Provision token
- "ProvisionTokenV2.Spec.AWSIIDTTL"
- "ProvisionTokenV2.Kind"
- "ProvisionTokenV2.Metadata.Name"
- "ProvisionTokenV2.Version"

# OIDC connector
- "OIDCConnectorV3.Kind"
- "OIDCConnectorV3.Version"

# Okta import rule
- "OktaImportRuleV1.Kind"
- "OktaImportRuleV1.Version"

# Role
- "RoleV6.Spec.Options.MaxSessionTTL"
@@ -235,7 +227,6 @@ computed_fields:
- "RoleV6.Spec.Allow.KubernetesResources.Verbs"
- "RoleV6.Spec.Options.BPF"
- "RoleV6.Kind"
- "RoleV6.Version"

# SAML connector
- "SAMLConnectorV2.Spec.Audience"
@@ -249,25 +240,22 @@ computed_fields:
- "SAMLConnectorV2.Spec.EncryptionKeyPair.PrivateKey"
- "SAMLConnectorV2.Spec.EncryptionKeyPair.Cert"
- "SAMLConnectorV2.Kind"
- "SAMLConnectorV2.Version"

# Session recording
- "SessionRecordingConfigV2.Spec.Mode"
- "SessionRecordingConfigV2.Kind"
- "SessionRecordingConfigV2.Version"

# Trusted cluster
- "TrustedClusterV2.Kind"
- "TrustedClusterV2.Version"

# User
- "UserV2.Kind"
- "UserV2.Version"

# These fields will be marked as Required: true
required_fields:
# App
- "AppV3.Metadata.Name"
- "AppV3.Version"

# Auth preference
- "AuthPreferenceV2.Spec"
@@ -277,42 +265,54 @@ required_fields:
- "DatabaseV3.Spec.Protocol"
- "DatabaseV3.Spec.URI"
- "DatabaseV3.Metadata.Name"
- "DatabaseV3.Version"

# Github connector
- "GithubConnectorV3.Spec"
- "GithubConnectorV3.Spec.ClientID"
- "GithubConnectorV3.Spec.ClientSecret"
- "GithubConnectorV3.Metadata.Name"
- "GithubConnectorV3.Version"

# OIDC connector
- "OIDCConnectorV3.Spec"
- "OIDCConnectorV3.Metadata.Name"
- "OIDCConnectorV3.Version"

# Okta import rule
- "OktaImportRuleV1.Spec"
- "OktaImportRuleV1.Metadata.Name"
- "OktaImportRuleV1.Version"

# Provision token
- "ProvisionTokenV2.Spec"
- "ProvisionTokenV2.Spec.Options"
- "ProvisionTokenV2.Spec.Roles"
- "ProvisionTokenV2.Version"

# Role
- "RoleV6.Metadata.Name"
# Role
- "RoleV6.Metadata.Name"
- "RoleV6.Version"

# SAML connector
- "SAMLConnectorV2.Spec"
- "SAMLConnectorV2.Spec.AssertionConsumerService"
- "SAMLConnectorV2.Spec.AttributesToRoles"
- "SAMLConnectorV2.Metadata.Name"
- "SAMLConnectorV2.Metadata.Name"
- "SAMLConnectorV2.Version"

# Trusted cluster
- "TrustedClusterV2.Metadata.Name"
- "TrustedClusterV2.Metadata.Name"
- "TrustedClusterV2.Version"
- "TrustedClusterV2.Spec"

# User
- "UserV2.Metadata.Name"

- "UserV2.Version"

- "SessionRecordingConfigV2.Version"
- "ClusterMaintenanceConfigV1.Version"
- "AuthPreferenceV2.Version"

# These fields must be marked as sensitive
sensitive_fields:
@@ -341,6 +341,51 @@ plan_modifiers:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"

# Version MUST NOT change. Due to the way Terraform imports back the resource
# in its state (the provider relies on `USeStateForUnknown`) and the fact
# Teleport mixes the injected defaults with the original resource, defaults
# are set only on resource creation. Upgrading an existing resource will
# create a hybrid: a resource with the new version but old defaults.
AppV3.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
DatabaseV3.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
GithubConnectorV3.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
OIDCConnectorV3.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
OktaImportRuleV1.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
ProvisionTokenV2.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
RoleV6.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
SAMLConnectorV2.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
TrustedClusterV2.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
UserV2.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
SessionRecordingConfigV2.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
ClusterMaintenanceConfigV1.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
AuthPreferenceV2.Version:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"

validators:
# Expires must be in the future
Metadata.Expires:
@@ -379,8 +424,8 @@ validators:
- UseMapKeysPresentValidator("teleport.dev/origin")
UserV2.Version:
- UseVersionBetween(2,2)
ClsuterMaintenanceConfigV1.Version:
- UserVersionBetween(1,1)
ClusterMaintenanceConfigV1.Version:
- UseVersionBetween(1,1)

time_type:
type: "TimeType"
Loading