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

Commit

Permalink
Ensure kube_resources always have the correct defaults, even after ve…
Browse files Browse the repository at this point in the history
…rsion change
  • Loading branch information
hugoShaka committed Mar 21, 2024
1 parent fd8a0b8 commit 5a56884
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 1 deletion.
2 changes: 2 additions & 0 deletions terraform/protoc-gen-terraform-teleport.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ plan_modifiers:
ProvisionTokenV2.Metadata.Name:
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.RequiresReplace()"
- "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()"
RoleV6.Spec.Allow.KubernetesResources:
- "DefaultRoleKubeResources()"

validators:
# Expires must be in the future
Expand Down
91 changes: 91 additions & 0 deletions terraform/tfschema/role_plan_modifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package tfschema

import (
"context"
"fmt"

Check failure on line 5 in terraform/tfschema/role_plan_modifier.go

View workflow job for this annotation

GitHub Actions / Plugins Lint (Go)

File is not `gci`-ed with --skip-generated -s standard -s default -s prefix(github.com/gravitational/teleport-plugins) --custom-order (gci)

Check failure on line 5 in terraform/tfschema/role_plan_modifier.go

View workflow job for this annotation

GitHub Actions / Plugins Lint (Go)

File is not `goimports`-ed (goimports)
apitypes "github.com/gravitational/teleport/api/types"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
tftypes "github.com/hashicorp/terraform-plugin-framework/types"
)

const (
DefaultRoleKubeModifierErrSummary = "DefaultRoleKubeResources modifier failed"
DefaultRoleKubeModifierDescription = `This modifier re-render the role.spec.allow.kubernetes_resources from the user provided config instead of using the state.
The state contains server-generated defaults (in fact they are generated in the pre-apply plan).
However, those defaults become outdated if the version changes.
One way to deal with version change is to force-recreate, but this is too destructive.
The workaround we found was to use this plan modifier.`
)

func DefaultRoleKubeResources() tfsdk.AttributePlanModifier {
return DefaultRoleKubeResourceModifier{}
}

type DefaultRoleKubeResourceModifier struct {
}

func (d DefaultRoleKubeResourceModifier) Description(ctx context.Context) string {
return DefaultRoleKubeModifierDescription
}

func (d DefaultRoleKubeResourceModifier) MarkdownDescription(ctx context.Context) string {
return DefaultRoleKubeModifierDescription
}

func (d DefaultRoleKubeResourceModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) {
var config tftypes.Object
diags := req.Config.Get(ctx, &config)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
resp.Diagnostics.AddError(DefaultRoleKubeModifierErrSummary, "Failed to get config.")
return
}

role := &apitypes.RoleV6{}
diags = CopyRoleV6FromTerraform(ctx, config, role)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
resp.Diagnostics.AddError(DefaultRoleKubeModifierErrSummary, "Failed to create a role from the config.")
return
}

err := role.CheckAndSetDefaults()
if err != nil {
resp.Diagnostics.AddError(DefaultRoleKubeModifierErrSummary, fmt.Sprintf("Failed to set the role defaults: %s", err))
return
}

diags = CopyRoleV6ToTerraform(ctx, role, &config)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
resp.Diagnostics.AddError(DefaultRoleKubeModifierErrSummary, "Failed to convert back the role into a TF Object.")
return
}

specRaw, ok := config.Attrs["spec"]
if !ok {
resp.Diagnostics.AddError(DefaultRoleKubeModifierErrSummary, "Failed to get 'spec' from TF object.")
return
}
spec, ok := specRaw.(tftypes.Object)
if !ok {
resp.Diagnostics.AddError(DefaultRoleKubeModifierErrSummary, "Failed to cast 'spec' as a TF object.")
return
}
allowRaw, ok := spec.Attrs["allow"]
if !ok {
resp.Diagnostics.AddError(DefaultRoleKubeModifierErrSummary, "Failed to get 'spec' from TF object.")
return
}
allow, ok := allowRaw.(tftypes.Object)
if !ok {
resp.Diagnostics.AddError(DefaultRoleKubeModifierErrSummary, "Failed to cast 'allow' as a TF object.")
return
}
kubeResources, ok := allow.Attrs["kubernetes_resources"]
if !ok {
resp.Diagnostics.AddError(DefaultRoleKubeModifierErrSummary, "Failed to get 'kubernetes_resources' from TF object.")
return
}
resp.AttributePlan = kubeResources
}
2 changes: 1 addition & 1 deletion terraform/tfschema/types_terraform.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5a56884

Please sign in to comment.