From 94dc1a90274aff69e104cb0b8fad231434792001 Mon Sep 17 00:00:00 2001 From: Przemko Robakowski Date: Fri, 15 Nov 2024 17:25:30 +0100 Subject: [PATCH] Add dynamic Windows desktops to terraform provider (#48160) * yaml * make tfschema * make tfschema again * make tfschema again + tests * tests + docs * lint * rename resource * example fix and labels --- .../data-sources/data-sources.mdx | 1 + .../data-sources/dynamic_windows_desktop.mdx | 58 ++ .../resources/dynamic_windows_desktop.mdx | 81 ++ .../resources/resources.mdx | 1 + .../resource.tf | 20 + integrations/terraform/gen/main.go | 19 + .../protoc-gen-terraform-teleport.yaml | 27 +- ...source_teleport_dynamic_windows_desktop.go | 82 ++ integrations/terraform/provider/provider.go | 2 + ...source_teleport_dynamic_windows_desktop.go | 335 +++++++ .../testlib/dynamic_windows_desktop_test.go | 163 ++++ .../dynamic_windows_desktop_0_create.tf | 16 + .../dynamic_windows_desktop_1_update.tf | 16 + .../terraform/tfschema/types_terraform.go | 859 ++++++++++++++++++ lib/services/presets.go | 11 +- 15 files changed, 1683 insertions(+), 8 deletions(-) create mode 100644 docs/pages/reference/terraform-provider/data-sources/dynamic_windows_desktop.mdx create mode 100644 docs/pages/reference/terraform-provider/resources/dynamic_windows_desktop.mdx create mode 100644 integrations/terraform/examples/resources/teleport_dynamic_windows_desktop/resource.tf create mode 100755 integrations/terraform/provider/data_source_teleport_dynamic_windows_desktop.go create mode 100755 integrations/terraform/provider/resource_teleport_dynamic_windows_desktop.go create mode 100644 integrations/terraform/testlib/dynamic_windows_desktop_test.go create mode 100644 integrations/terraform/testlib/fixtures/dynamic_windows_desktop_0_create.tf create mode 100644 integrations/terraform/testlib/fixtures/dynamic_windows_desktop_1_update.tf diff --git a/docs/pages/reference/terraform-provider/data-sources/data-sources.mdx b/docs/pages/reference/terraform-provider/data-sources/data-sources.mdx index 047a8a04a630b..92e37199d2dd6 100644 --- a/docs/pages/reference/terraform-provider/data-sources/data-sources.mdx +++ b/docs/pages/reference/terraform-provider/data-sources/data-sources.mdx @@ -20,6 +20,7 @@ The Teleport Terraform provider supports the following data-sources: - [`teleport_cluster_maintenance_config`](./cluster_maintenance_config.mdx) - [`teleport_cluster_networking_config`](./cluster_networking_config.mdx) - [`teleport_database`](./database.mdx) + - [`teleport_dynamic_windows_desktop`](./dynamic_windows_desktop.mdx) - [`teleport_github_connector`](./github_connector.mdx) - [`teleport_installer`](./installer.mdx) - [`teleport_login_rule`](./login_rule.mdx) diff --git a/docs/pages/reference/terraform-provider/data-sources/dynamic_windows_desktop.mdx b/docs/pages/reference/terraform-provider/data-sources/dynamic_windows_desktop.mdx new file mode 100644 index 0000000000000..41c132bbddd3e --- /dev/null +++ b/docs/pages/reference/terraform-provider/data-sources/dynamic_windows_desktop.mdx @@ -0,0 +1,58 @@ +--- +title: Reference for the teleport_dynamic_windows_desktop Terraform data-source +description: This page describes the supported values of the teleport_dynamic_windows_desktop data-source of the Teleport Terraform provider. +--- + +{/*Auto-generated file. Do not edit.*/} +{/*To regenerate, navigate to integrations/terraform and run `make docs`.*/} + + + + + +{/* schema generated by tfplugindocs */} +## Schema + +### Required + +- `spec` (Attributes) Spec is the DynamicWindows host spec. (see [below for nested schema](#nested-schema-for-spec)) +- `version` (String) Version is the API version used to create the resource. It must be specified. Based on this version, Teleport will apply different defaults on resource creation or deletion. It must be an integer prefixed by "v". For example: `v1` + +### Optional + +- `metadata` (Attributes) Metadata is resource metadata (see [below for nested schema](#nested-schema-for-metadata)) +- `sub_kind` (String) SubKind is an optional resource sub kind, used in some resources + +### Nested Schema for `spec` + +Required: + +- `addr` (String) Addr is the address that this host can be reached at. + +Optional: + +- `domain` (String) Domain is the ActiveDirectory domain that this host belongs to. +- `non_ad` (Boolean) NonAD marks this desktop as a standalone host that is not joined to an Active Directory domain. +- `screen_size` (Attributes) ScreenSize specifies the size of the screen to use for sessions on this host. In most cases this should be unspecified, in which case Teleport will fill the browser window. (see [below for nested schema](#nested-schema-for-specscreen_size)) + +### Nested Schema for `spec.screen_size` + +Optional: + +- `height` (Number) +- `width` (Number) + + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is an object name + +Optional: + +- `description` (String) Description is object description +- `expires` (String) Expires is a global expiry time header can be set on any resource in the system. +- `labels` (Map of String) Labels is a set of labels + diff --git a/docs/pages/reference/terraform-provider/resources/dynamic_windows_desktop.mdx b/docs/pages/reference/terraform-provider/resources/dynamic_windows_desktop.mdx new file mode 100644 index 0000000000000..4484e3b97cf13 --- /dev/null +++ b/docs/pages/reference/terraform-provider/resources/dynamic_windows_desktop.mdx @@ -0,0 +1,81 @@ +--- +title: Reference for the teleport_dynamic_windows_desktop Terraform resource +description: This page describes the supported values of the teleport_dynamic_windows_desktop resource of the Teleport Terraform provider. +--- + +{/*Auto-generated file. Do not edit.*/} +{/*To regenerate, navigate to integrations/terraform and run `make docs`.*/} + + + +## Example Usage + +```hcl +resource "teleport_dynamic_windows_desktop" "example" { + version = "v1" + metadata = { + name = "example" + description = "Test Windows desktop" + labels = { + "teleport.dev/origin" = "dynamic" // This label is added on Teleport side by default + } + } + + spec = { + addr = "some.host.com" + non_ad = true + domain = "my.domain" + screen_size = { + width = 800 + height = 600 + } + } +} +``` + +{/* schema generated by tfplugindocs */} +## Schema + +### Required + +- `spec` (Attributes) Spec is the DynamicWindows host spec. (see [below for nested schema](#nested-schema-for-spec)) +- `version` (String) Version is the API version used to create the resource. It must be specified. Based on this version, Teleport will apply different defaults on resource creation or deletion. It must be an integer prefixed by "v". For example: `v1` + +### Optional + +- `metadata` (Attributes) Metadata is resource metadata (see [below for nested schema](#nested-schema-for-metadata)) +- `sub_kind` (String) SubKind is an optional resource sub kind, used in some resources + +### Nested Schema for `spec` + +Required: + +- `addr` (String) Addr is the address that this host can be reached at. + +Optional: + +- `domain` (String) Domain is the ActiveDirectory domain that this host belongs to. +- `non_ad` (Boolean) NonAD marks this desktop as a standalone host that is not joined to an Active Directory domain. +- `screen_size` (Attributes) ScreenSize specifies the size of the screen to use for sessions on this host. In most cases this should be unspecified, in which case Teleport will fill the browser window. (see [below for nested schema](#nested-schema-for-specscreen_size)) + +### Nested Schema for `spec.screen_size` + +Optional: + +- `height` (Number) +- `width` (Number) + + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Name is an object name + +Optional: + +- `description` (String) Description is object description +- `expires` (String) Expires is a global expiry time header can be set on any resource in the system. +- `labels` (Map of String) Labels is a set of labels + diff --git a/docs/pages/reference/terraform-provider/resources/resources.mdx b/docs/pages/reference/terraform-provider/resources/resources.mdx index ac150d8a43048..51d7bb8d2e3b3 100644 --- a/docs/pages/reference/terraform-provider/resources/resources.mdx +++ b/docs/pages/reference/terraform-provider/resources/resources.mdx @@ -21,6 +21,7 @@ The Teleport Terraform provider supports the following resources: - [`teleport_cluster_maintenance_config`](./cluster_maintenance_config.mdx) - [`teleport_cluster_networking_config`](./cluster_networking_config.mdx) - [`teleport_database`](./database.mdx) + - [`teleport_dynamic_windows_desktop`](./dynamic_windows_desktop.mdx) - [`teleport_github_connector`](./github_connector.mdx) - [`teleport_installer`](./installer.mdx) - [`teleport_login_rule`](./login_rule.mdx) diff --git a/integrations/terraform/examples/resources/teleport_dynamic_windows_desktop/resource.tf b/integrations/terraform/examples/resources/teleport_dynamic_windows_desktop/resource.tf new file mode 100644 index 0000000000000..04c8761db6aba --- /dev/null +++ b/integrations/terraform/examples/resources/teleport_dynamic_windows_desktop/resource.tf @@ -0,0 +1,20 @@ +resource "teleport_dynamic_windows_desktop" "example" { + version = "v1" + metadata = { + name = "example" + description = "Test Windows desktop" + labels = { + "teleport.dev/origin" = "dynamic" // This label is added on Teleport side by default + } + } + + spec = { + addr = "some.host.com" + non_ad = true + domain = "my.domain" + screen_size = { + width = 800 + height = 600 + } + } +} diff --git a/integrations/terraform/gen/main.go b/integrations/terraform/gen/main.go index 2252399cd5cc7..3053e7b56098a 100644 --- a/integrations/terraform/gen/main.go +++ b/integrations/terraform/gen/main.go @@ -207,6 +207,23 @@ var ( HasCheckAndSetDefaults: true, } + dynamicWindowsDesktop = payload{ + Name: "DynamicWindowsDesktop", + TypeName: "DynamicWindowsDesktopV1", + VarName: "desktop", + IfaceName: "DynamicWindowsDesktop", + GetMethod: "DynamicDesktopClient().GetDynamicWindowsDesktop", + CreateMethod: "DynamicDesktopClient().CreateDynamicWindowsDesktop", + UpdateMethod: "DynamicDesktopClient().UpdateDynamicWindowsDesktop", + DeleteMethod: "DynamicDesktopClient().DeleteDynamicWindowsDesktop", + UpsertMethodArity: 2, + ID: `desktop.Metadata.Name`, + Kind: "dynamic_windows_desktop", + HasStaticID: false, + TerraformResourceType: "teleport_dynamic_windows_desktop", + HasCheckAndSetDefaults: true, + } + githubConnector = payload{ Name: "GithubConnector", TypeName: "GithubConnectorV3", @@ -519,6 +536,8 @@ func genTFSchema() { generateDataSource(clusterNetworking, singularDataSource) generateResource(database, pluralResource) generateDataSource(database, pluralDataSource) + generateResource(dynamicWindowsDesktop, pluralResource) + generateDataSource(dynamicWindowsDesktop, pluralDataSource) generateResource(githubConnector, pluralResource) generateDataSource(githubConnector, pluralDataSource) generateResource(oidcConnector, pluralResource) diff --git a/integrations/terraform/protoc-gen-terraform-teleport.yaml b/integrations/terraform/protoc-gen-terraform-teleport.yaml index b532749d63783..ae75409b83af1 100644 --- a/integrations/terraform/protoc-gen-terraform-teleport.yaml +++ b/integrations/terraform/protoc-gen-terraform-teleport.yaml @@ -21,6 +21,7 @@ types: - "TrustedClusterV2" - "UserV2" - "InstallerV1" + - "DynamicWindowsDesktopV1" # id field is required for integration tests. It is not used by provider. # We have to add it manually (might be removed in the future versions). @@ -130,6 +131,13 @@ injected_fields: computed: true plan_modifiers: - "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()" + DynamicWindowsDesktopV1: + - + name: id + type: github.com/hashicorp/terraform-plugin-framework/types.StringType + computed: true + plan_modifiers: + - "github.com/hashicorp/terraform-plugin-framework/tfsdk.UseStateForUnknown()" # These fields will be excluded exclude_fields: @@ -173,7 +181,7 @@ computed_fields: # App - "AppV3.Metadata.Labels" - - "AppV3.Kind" + - "AppV3.Kind" # Auth preference - "AuthPreferenceV2.Spec.SecondFactor" @@ -214,15 +222,15 @@ computed_fields: # Computed is often used to represent values that are not user configurable or can not be known at time of terraform plan or apply, #------------------------------------ # role_test.go:244: Step 1/8 error: Error running apply: exit status 1 - # + # # Error: Provider produced inconsistent result after apply - # + # # When applying changes to teleport_role.upgrade, provider # "provider[\"registry.terraform.io/hashicorp/teleport\"]" produced an # unexpected new value: .spec.allow.kubernetes_resources: was null, but now # cty.ListVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{"kind":cty.StringVal("pod"), # "name":cty.StringVal("*"), "namespace":cty.StringVal("*")})}). - # + # # This is a bug in the provider, which should be reported in the provider's own # issue tracker. #------------------------------------ @@ -276,6 +284,9 @@ computed_fields: # Installer - "InstallerV1.Kind" + # DynamicWindowsDesktop + - "DynamicWindowsDesktopV1.Kind" + # These fields will be marked as Required: true required_fields: # App @@ -343,6 +354,12 @@ required_fields: - "InstallerV1.Metadata.Name" - "InstallerV1.Version" + # DynamicWindowsDesktop + - "DynamicWindowsDesktopV1.Spec" + - "DynamicWindowsDesktopV1.Spec.Addr" + - "DynamicWindowsDesktopV1.Metadata.Name" + - "DynamicWindowsDesktopV1.Version" + # These fields must be marked as sensitive sensitive_fields: - "SAMLConnectorV2.Spec.Cert" @@ -413,6 +430,8 @@ validators: - UseVersionBetween(1,1) InstallerV1.Version: - UseVersionBetween(1,1) + DynamicWindowsDesktopV1.Version: + - UseVersionBetween(1,1) time_type: type: "TimeType" diff --git a/integrations/terraform/provider/data_source_teleport_dynamic_windows_desktop.go b/integrations/terraform/provider/data_source_teleport_dynamic_windows_desktop.go new file mode 100755 index 0000000000000..48b07e49e476c --- /dev/null +++ b/integrations/terraform/provider/data_source_teleport_dynamic_windows_desktop.go @@ -0,0 +1,82 @@ +// Code generated by _gen/main.go DO NOT EDIT +/* +Copyright 2015-2024 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package provider + +import ( + "context" + + apitypes "github.com/gravitational/teleport/api/types" + "github.com/gravitational/trace" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" + "github.com/hashicorp/terraform-plugin-framework/types" + + "github.com/gravitational/teleport/integrations/terraform/tfschema" +) + +// dataSourceTeleportDynamicWindowsDesktopType is the data source metadata type +type dataSourceTeleportDynamicWindowsDesktopType struct{} + +// dataSourceTeleportDynamicWindowsDesktop is the resource +type dataSourceTeleportDynamicWindowsDesktop struct { + p Provider +} + +// GetSchema returns the data source schema +func (r dataSourceTeleportDynamicWindowsDesktopType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { + return tfschema.GenSchemaDynamicWindowsDesktopV1(ctx) +} + +// NewDataSource creates the empty data source +func (r dataSourceTeleportDynamicWindowsDesktopType) NewDataSource(_ context.Context, p tfsdk.Provider) (tfsdk.DataSource, diag.Diagnostics) { + return dataSourceTeleportDynamicWindowsDesktop{ + p: *(p.(*Provider)), + }, nil +} + +// Read reads teleport DynamicWindowsDesktop +func (r dataSourceTeleportDynamicWindowsDesktop) Read(ctx context.Context, req tfsdk.ReadDataSourceRequest, resp *tfsdk.ReadDataSourceResponse) { + var id types.String + diags := req.Config.GetAttribute(ctx, path.Root("metadata").AtName("name"), &id) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + desktopI, err := r.p.Client.DynamicDesktopClient().GetDynamicWindowsDesktop(ctx, id.Value) + if err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", trace.Wrap(err), "dynamic_windows_desktop")) + return + } + + var state types.Object + + desktop := desktopI.(*apitypes.DynamicWindowsDesktopV1) + diags = tfschema.CopyDynamicWindowsDesktopV1ToTerraform(ctx, desktop, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} diff --git a/integrations/terraform/provider/provider.go b/integrations/terraform/provider/provider.go index 1f1a923a60c91..ec2648df1b274 100644 --- a/integrations/terraform/provider/provider.go +++ b/integrations/terraform/provider/provider.go @@ -486,6 +486,7 @@ func (p *Provider) GetResources(_ context.Context) (map[string]tfsdk.ResourceTyp "teleport_cluster_maintenance_config": resourceTeleportClusterMaintenanceConfigType{}, "teleport_cluster_networking_config": resourceTeleportClusterNetworkingConfigType{}, "teleport_database": resourceTeleportDatabaseType{}, + "teleport_dynamic_windows_desktop": resourceTeleportDynamicWindowsDesktopType{}, "teleport_github_connector": resourceTeleportGithubConnectorType{}, "teleport_provision_token": resourceTeleportProvisionTokenType{}, "teleport_oidc_connector": resourceTeleportOIDCConnectorType{}, @@ -514,6 +515,7 @@ func (p *Provider) GetDataSources(_ context.Context) (map[string]tfsdk.DataSourc "teleport_cluster_maintenance_config": dataSourceTeleportClusterMaintenanceConfigType{}, "teleport_cluster_networking_config": dataSourceTeleportClusterNetworkingConfigType{}, "teleport_database": dataSourceTeleportDatabaseType{}, + "teleport_dynamic_windows_desktop": dataSourceTeleportDynamicWindowsDesktopType{}, "teleport_github_connector": dataSourceTeleportGithubConnectorType{}, "teleport_provision_token": dataSourceTeleportProvisionTokenType{}, "teleport_oidc_connector": dataSourceTeleportOIDCConnectorType{}, diff --git a/integrations/terraform/provider/resource_teleport_dynamic_windows_desktop.go b/integrations/terraform/provider/resource_teleport_dynamic_windows_desktop.go new file mode 100755 index 0000000000000..b02a57ad04cd0 --- /dev/null +++ b/integrations/terraform/provider/resource_teleport_dynamic_windows_desktop.go @@ -0,0 +1,335 @@ +// Code generated by _gen/main.go DO NOT EDIT +/* +Copyright 2015-2024 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package provider + +import ( + "context" + "fmt" + + apitypes "github.com/gravitational/teleport/api/types" + + "github.com/gravitational/teleport/integrations/lib/backoff" + "github.com/gravitational/trace" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/jonboulle/clockwork" + + "github.com/gravitational/teleport/integrations/terraform/tfschema" +) + +// resourceTeleportDynamicWindowsDesktopType is the resource metadata type +type resourceTeleportDynamicWindowsDesktopType struct{} + +// resourceTeleportDynamicWindowsDesktop is the resource +type resourceTeleportDynamicWindowsDesktop struct { + p Provider +} + +// GetSchema returns the resource schema +func (r resourceTeleportDynamicWindowsDesktopType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { + return tfschema.GenSchemaDynamicWindowsDesktopV1(ctx) +} + +// NewResource creates the empty resource +func (r resourceTeleportDynamicWindowsDesktopType) NewResource(_ context.Context, p tfsdk.Provider) (tfsdk.Resource, diag.Diagnostics) { + return resourceTeleportDynamicWindowsDesktop{ + p: *(p.(*Provider)), + }, nil +} + +// Create creates the DynamicWindowsDesktop +func (r resourceTeleportDynamicWindowsDesktop) Create(ctx context.Context, req tfsdk.CreateResourceRequest, resp *tfsdk.CreateResourceResponse) { + var err error + if !r.p.IsConfigured(resp.Diagnostics) { + return + } + + var plan types.Object + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + desktop := &apitypes.DynamicWindowsDesktopV1{} + diags = tfschema.CopyDynamicWindowsDesktopV1FromTerraform(ctx, plan, desktop) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + + desktopResource := desktop + + err = desktopResource.CheckAndSetDefaults() + if err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error setting DynamicWindowsDesktop defaults", trace.Wrap(err), "dynamic_windows_desktop")) + return + } + + id := desktopResource.Metadata.Name + + _, err = r.p.Client.DynamicDesktopClient().GetDynamicWindowsDesktop(ctx, id) + if !trace.IsNotFound(err) { + if err == nil { + existErr := fmt.Sprintf("DynamicWindowsDesktop exists in Teleport. Either remove it (tctl rm dynamic_windows_desktop/%v)"+ + " or import it to the existing state (terraform import teleport_dynamic_windows_desktop.%v %v)", id, id, id) + + resp.Diagnostics.Append(diagFromErr("DynamicWindowsDesktop exists in Teleport", trace.Errorf(existErr))) + return + } + + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", trace.Wrap(err), "dynamic_windows_desktop")) + return + } + + _, err = r.p.Client.DynamicDesktopClient().CreateDynamicWindowsDesktop(ctx, desktopResource) + if err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error creating DynamicWindowsDesktop", trace.Wrap(err), "dynamic_windows_desktop")) + return + } + + // Not really an inferface, just using the same name for easier templating. + var desktopI apitypes.DynamicWindowsDesktop + tries := 0 + backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) + for { + tries = tries + 1 + desktopI, err = r.p.Client.DynamicDesktopClient().GetDynamicWindowsDesktop(ctx, id) + if trace.IsNotFound(err) { + if bErr := backoff.Do(ctx); bErr != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", trace.Wrap(bErr), "dynamic_windows_desktop")) + return + } + if tries >= r.p.RetryConfig.MaxTries { + diagMessage := fmt.Sprintf("Error reading DynamicWindowsDesktop (tried %d times) - state outdated, please import resource", tries) + resp.Diagnostics.AddError(diagMessage, "dynamic_windows_desktop") + } + continue + } + break + } + + if err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", trace.Wrap(err), "dynamic_windows_desktop")) + return + } + + desktopResource, ok := desktopI.(*apitypes.DynamicWindowsDesktopV1) + if !ok { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", trace.Errorf("Can not convert %T to DynamicWindowsDesktopV1", desktopI), "dynamic_windows_desktop")) + return + } + desktop = desktopResource + + diags = tfschema.CopyDynamicWindowsDesktopV1ToTerraform(ctx, desktop, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + plan.Attrs["id"] = types.String{Value: desktop.Metadata.Name} + + diags = resp.State.Set(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +// Read reads teleport DynamicWindowsDesktop +func (r resourceTeleportDynamicWindowsDesktop) Read(ctx context.Context, req tfsdk.ReadResourceRequest, resp *tfsdk.ReadResourceResponse) { + var state types.Object + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + var id types.String + diags = req.State.GetAttribute(ctx, path.Root("metadata").AtName("name"), &id) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + desktopI, err := r.p.Client.DynamicDesktopClient().GetDynamicWindowsDesktop(ctx, id.Value) + if trace.IsNotFound(err) { + resp.State.RemoveResource(ctx) + return + } + + if err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", trace.Wrap(err), "dynamic_windows_desktop")) + return + } + + desktop := desktopI.(*apitypes.DynamicWindowsDesktopV1) + diags = tfschema.CopyDynamicWindowsDesktopV1ToTerraform(ctx, desktop, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +// Update updates teleport DynamicWindowsDesktop +func (r resourceTeleportDynamicWindowsDesktop) Update(ctx context.Context, req tfsdk.UpdateResourceRequest, resp *tfsdk.UpdateResourceResponse) { + if !r.p.IsConfigured(resp.Diagnostics) { + return + } + + var plan types.Object + diags := req.Plan.Get(ctx, &plan) + + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + desktop := &apitypes.DynamicWindowsDesktopV1{} + diags = tfschema.CopyDynamicWindowsDesktopV1FromTerraform(ctx, plan, desktop) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + desktopResource := desktop + + + if err := desktopResource.CheckAndSetDefaults(); err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error updating DynamicWindowsDesktop", err, "dynamic_windows_desktop")) + return + } + name := desktopResource.Metadata.Name + + desktopBefore, err := r.p.Client.DynamicDesktopClient().GetDynamicWindowsDesktop(ctx, name) + if err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", err, "dynamic_windows_desktop")) + return + } + + _, err = r.p.Client.DynamicDesktopClient().UpdateDynamicWindowsDesktop(ctx, desktopResource) + if err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error updating DynamicWindowsDesktop", err, "dynamic_windows_desktop")) + return + } + + // Not really an inferface, just using the same name for easier templating. + var desktopI apitypes.DynamicWindowsDesktop + + tries := 0 + backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) + for { + tries = tries + 1 + desktopI, err = r.p.Client.DynamicDesktopClient().GetDynamicWindowsDesktop(ctx, name) + if err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", err, "dynamic_windows_desktop")) + return + } + if desktopBefore.GetMetadata().Revision != desktopI.GetMetadata().Revision || false { + break + } + + if err := backoff.Do(ctx); err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", trace.Wrap(err), "dynamic_windows_desktop")) + return + } + if tries >= r.p.RetryConfig.MaxTries { + diagMessage := fmt.Sprintf("Error reading DynamicWindowsDesktop (tried %d times) - state outdated, please import resource", tries) + resp.Diagnostics.AddError(diagMessage, "dynamic_windows_desktop") + return + } + } + + desktopResource, ok := desktopI.(*apitypes.DynamicWindowsDesktopV1) + if !ok { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", trace.Errorf("Can not convert %T to DynamicWindowsDesktopV1", desktopI), "dynamic_windows_desktop")) + return + } + diags = tfschema.CopyDynamicWindowsDesktopV1ToTerraform(ctx, desktop, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + diags = resp.State.Set(ctx, plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +// Delete deletes Teleport DynamicWindowsDesktop +func (r resourceTeleportDynamicWindowsDesktop) Delete(ctx context.Context, req tfsdk.DeleteResourceRequest, resp *tfsdk.DeleteResourceResponse) { + var id types.String + diags := req.State.GetAttribute(ctx, path.Root("metadata").AtName("name"), &id) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + err := r.p.Client.DynamicDesktopClient().DeleteDynamicWindowsDesktop(ctx, id.Value) + if err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error deleting DynamicWindowsDesktopV1", trace.Wrap(err), "dynamic_windows_desktop")) + return + } + + resp.State.RemoveResource(ctx) +} + +// ImportState imports DynamicWindowsDesktop state +func (r resourceTeleportDynamicWindowsDesktop) ImportState(ctx context.Context, req tfsdk.ImportResourceStateRequest, resp *tfsdk.ImportResourceStateResponse) { + desktop, err := r.p.Client.DynamicDesktopClient().GetDynamicWindowsDesktop(ctx, req.ID) + if err != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DynamicWindowsDesktop", trace.Wrap(err), "dynamic_windows_desktop")) + return + } + + + desktopResource := desktop.(*apitypes.DynamicWindowsDesktopV1) + + var state types.Object + + diags := resp.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + diags = tfschema.CopyDynamicWindowsDesktopV1ToTerraform(ctx, desktopResource, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + id := desktopResource.GetName() + + state.Attrs["id"] = types.String{Value: id} + + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} diff --git a/integrations/terraform/testlib/dynamic_windows_desktop_test.go b/integrations/terraform/testlib/dynamic_windows_desktop_test.go new file mode 100644 index 0000000000000..59b214df9af82 --- /dev/null +++ b/integrations/terraform/testlib/dynamic_windows_desktop_test.go @@ -0,0 +1,163 @@ +/* +Copyright 2015-2021 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package testlib + +import ( + "context" + "time" + + "github.com/gravitational/trace" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/stretchr/testify/require" + + "github.com/gravitational/teleport/api/types" +) + +func (s *TerraformSuiteOSS) TestDynamicWindowsDesktop() { + ctx, cancel := context.WithCancel(context.Background()) + s.T().Cleanup(cancel) + + checkDestroyed := func(state *terraform.State) error { + _, err := s.client.DynamicDesktopClient().GetDynamicWindowsDesktop(ctx, "test") + if trace.IsNotFound(err) { + return nil + } + + return err + } + + name := "teleport_dynamic_windows_desktop.test" + + resource.Test(s.T(), resource.TestCase{ + ProtoV6ProviderFactories: s.terraformProviders, + CheckDestroy: checkDestroyed, + IsUnitTest: true, + Steps: []resource.TestStep{ + { + Config: s.getFixture("dynamic_windows_desktop_0_create.tf"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "kind", "dynamic_windows_desktop"), + resource.TestCheckResourceAttr(name, "spec.addr", "localhost:3000"), + resource.TestCheckResourceAttr(name, "spec.non_ad", "true"), + resource.TestCheckResourceAttr(name, "spec.domain", "my.domain"), + ), + }, + { + Config: s.getFixture("dynamic_windows_desktop_0_create.tf"), + PlanOnly: true, + }, + { + Config: s.getFixture("dynamic_windows_desktop_1_update.tf"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "kind", "dynamic_windows_desktop"), + resource.TestCheckResourceAttr(name, "spec.addr", "localhost:3000"), + resource.TestCheckResourceAttr(name, "spec.non_ad", "false"), + resource.TestCheckResourceAttr(name, "spec.domain", "my.domain2"), + ), + }, + { + Config: s.getFixture("dynamic_windows_desktop_1_update.tf"), + PlanOnly: true, + }, + }, + }) +} + +func (s *TerraformSuiteOSS) TestImportDynamicWindowsDesktop() { + ctx, cancel := context.WithCancel(context.Background()) + s.T().Cleanup(cancel) + + r := "teleport_dynamic_windows_desktop" + id := "test_import" + name := r + "." + id + + app, err := types.NewDynamicWindowsDesktopV1(id, nil, types.DynamicWindowsDesktopSpecV1{ + Addr: "localhost:3000", + }) + require.NoError(s.T(), err) + err = app.CheckAndSetDefaults() + require.NoError(s.T(), err) + + _, err = s.client.DynamicDesktopClient().CreateDynamicWindowsDesktop(ctx, app) + require.NoError(s.T(), err) + + require.Eventually(s.T(), func() bool { + _, err := s.client.DynamicDesktopClient().GetDynamicWindowsDesktop(ctx, app.GetName()) + if trace.IsNotFound(err) { + return false + } + require.NoError(s.T(), err) + return true + }, 5*time.Second, time.Second) + + resource.Test(s.T(), resource.TestCase{ + ProtoV6ProviderFactories: s.terraformProviders, + IsUnitTest: true, + Steps: []resource.TestStep{ + { + Config: s.terraformConfig + "\n" + `resource "` + r + `" "` + id + `" { }`, + ResourceName: name, + ImportState: true, + ImportStateId: id, + ImportStateCheck: func(state []*terraform.InstanceState) error { + require.Equal(s.T(), "dynamic_windows_desktop", state[0].Attributes["kind"]) + require.Equal(s.T(), "localhost:3000", state[0].Attributes["spec.addr"]) + + return nil + }, + }, + }, + }) +} + +func (s *TerraformSuiteOSSWithCache) TestDynamicWindowsDesktopWithCache() { + ctx, cancel := context.WithCancel(context.Background()) + s.T().Cleanup(cancel) + + checkDestroyed := func(state *terraform.State) error { + _, err := s.client.DynamicDesktopClient().GetDynamicWindowsDesktop(ctx, "test") + if trace.IsNotFound(err) { + return nil + } + + return err + } + + name := "teleport_dynamic_windows_desktop.test" + + resource.Test(s.T(), resource.TestCase{ + ProtoV6ProviderFactories: s.terraformProviders, + CheckDestroy: checkDestroyed, + IsUnitTest: true, + Steps: []resource.TestStep{ + { + Config: s.getFixture("dynamic_windows_desktop_0_create.tf"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(name, "kind", "dynamic_windows_desktop"), + resource.TestCheckResourceAttr(name, "spec.addr", "localhost:3000"), + resource.TestCheckResourceAttr(name, "spec.non_ad", "true"), + resource.TestCheckResourceAttr(name, "spec.domain", "my.domain"), + ), + }, + { + Config: s.getFixture("dynamic_windows_desktop_0_create.tf"), + PlanOnly: true, + }, + }, + }) +} diff --git a/integrations/terraform/testlib/fixtures/dynamic_windows_desktop_0_create.tf b/integrations/terraform/testlib/fixtures/dynamic_windows_desktop_0_create.tf new file mode 100644 index 0000000000000..953a02b967691 --- /dev/null +++ b/integrations/terraform/testlib/fixtures/dynamic_windows_desktop_0_create.tf @@ -0,0 +1,16 @@ +resource "teleport_dynamic_windows_desktop" "test" { + version = "v1" + metadata = { + name = "example" + labels = { + example = "yes" + "teleport.dev/origin" = "dynamic" + } + } + + spec = { + addr = "localhost:3000" + non_ad = true + domain = "my.domain" + } +} diff --git a/integrations/terraform/testlib/fixtures/dynamic_windows_desktop_1_update.tf b/integrations/terraform/testlib/fixtures/dynamic_windows_desktop_1_update.tf new file mode 100644 index 0000000000000..5e0ddeea8e285 --- /dev/null +++ b/integrations/terraform/testlib/fixtures/dynamic_windows_desktop_1_update.tf @@ -0,0 +1,16 @@ +resource "teleport_dynamic_windows_desktop" "test" { + version = "v1" + metadata = { + name = "test" + labels = { + example = "yes" + "teleport.dev/origin" = "dynamic" + } + } + + spec = { + addr = "localhost:3000" + non_ad = false + domain = "my.domain2" + } +} diff --git a/integrations/terraform/tfschema/types_terraform.go b/integrations/terraform/tfschema/types_terraform.go index c0bd40a041b0d..822f6396a24f0 100644 --- a/integrations/terraform/tfschema/types_terraform.go +++ b/integrations/terraform/tfschema/types_terraform.go @@ -3636,6 +3636,114 @@ func GenSchemaTrustedClusterV2(ctx context.Context) (github_com_hashicorp_terraf }}, nil } +// GenSchemaDynamicWindowsDesktopV1 returns tfsdk.Schema definition for DynamicWindowsDesktopV1 +func GenSchemaDynamicWindowsDesktopV1(ctx context.Context) (github_com_hashicorp_terraform_plugin_framework_tfsdk.Schema, github_com_hashicorp_terraform_plugin_framework_diag.Diagnostics) { + return github_com_hashicorp_terraform_plugin_framework_tfsdk.Schema{Attributes: map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{ + "id": { + Computed: true, + Optional: false, + PlanModifiers: []github_com_hashicorp_terraform_plugin_framework_tfsdk.AttributePlanModifier{github_com_hashicorp_terraform_plugin_framework_tfsdk.UseStateForUnknown()}, + Required: false, + Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, + }, + "kind": { + Computed: true, + Description: "Kind is a resource kind", + Optional: true, + PlanModifiers: []github_com_hashicorp_terraform_plugin_framework_tfsdk.AttributePlanModifier{github_com_hashicorp_terraform_plugin_framework_tfsdk.UseStateForUnknown()}, + Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, + }, + "metadata": { + Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.SingleNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{ + "description": { + Description: "Description is object description", + Optional: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, + }, + "expires": { + Description: "Expires is a global expiry time header can be set on any resource in the system.", + Optional: true, + Type: UseRFC3339Time(), + Validators: []github_com_hashicorp_terraform_plugin_framework_tfsdk.AttributeValidator{MustTimeBeInFuture()}, + }, + "labels": { + Description: "Labels is a set of labels", + Optional: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.MapType{ElemType: github_com_hashicorp_terraform_plugin_framework_types.StringType}, + }, + "name": { + Description: "Name is an object name", + PlanModifiers: []github_com_hashicorp_terraform_plugin_framework_tfsdk.AttributePlanModifier{github_com_hashicorp_terraform_plugin_framework_tfsdk.RequiresReplace()}, + Required: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, + }, + "namespace": { + Computed: true, + Description: "Namespace is object namespace. The field should be called \"namespace\" when it returns in Teleport 2.4.", + Optional: true, + PlanModifiers: []github_com_hashicorp_terraform_plugin_framework_tfsdk.AttributePlanModifier{github_com_hashicorp_terraform_plugin_framework_tfsdk.UseStateForUnknown()}, + Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, + }, + "revision": { + Description: "Revision is an opaque identifier which tracks the versions of a resource over time. Clients should ignore and not alter its value but must return the revision in any updates of a resource.", + Optional: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, + }, + }), + Description: "Metadata is resource metadata", + Optional: true, + }, + "spec": { + Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.SingleNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{ + "addr": { + Description: "Addr is the address that this host can be reached at.", + Required: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, + }, + "domain": { + Description: "Domain is the ActiveDirectory domain that this host belongs to.", + Optional: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, + }, + "non_ad": { + Description: "NonAD marks this desktop as a standalone host that is not joined to an Active Directory domain.", + Optional: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.BoolType, + }, + "screen_size": { + Attributes: github_com_hashicorp_terraform_plugin_framework_tfsdk.SingleNestedAttributes(map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{ + "height": { + Description: "", + Optional: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.Int64Type, + }, + "width": { + Description: "", + Optional: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.Int64Type, + }, + }), + Description: "ScreenSize specifies the size of the screen to use for sessions on this host. In most cases this should be unspecified, in which case Teleport will fill the browser window.", + Optional: true, + }, + }), + Description: "Spec is the DynamicWindows host spec.", + Required: true, + }, + "sub_kind": { + Description: "SubKind is an optional resource sub kind, used in some resources", + Optional: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, + }, + "version": { + Description: "Version is the API version used to create the resource. It must be specified. Based on this version, Teleport will apply different defaults on resource creation or deletion. It must be an integer prefixed by \"v\". For example: `v1`", + Required: true, + Type: github_com_hashicorp_terraform_plugin_framework_types.StringType, + Validators: []github_com_hashicorp_terraform_plugin_framework_tfsdk.AttributeValidator{UseVersionBetween(1, 1)}, + }, + }}, nil +} + // GenSchemaInstallerV1 returns tfsdk.Schema definition for InstallerV1 func GenSchemaInstallerV1(ctx context.Context) (github_com_hashicorp_terraform_plugin_framework_tfsdk.Schema, github_com_hashicorp_terraform_plugin_framework_diag.Diagnostics) { return github_com_hashicorp_terraform_plugin_framework_tfsdk.Schema{Attributes: map[string]github_com_hashicorp_terraform_plugin_framework_tfsdk.Attribute{ @@ -35793,6 +35901,757 @@ func CopyTrustedClusterV2ToTerraform(ctx context.Context, obj *github_com_gravit return diags } +// CopyDynamicWindowsDesktopV1FromTerraform copies contents of the source Terraform object into a target struct +func CopyDynamicWindowsDesktopV1FromTerraform(_ context.Context, tf github_com_hashicorp_terraform_plugin_framework_types.Object, obj *github_com_gravitational_teleport_api_types.DynamicWindowsDesktopV1) github_com_hashicorp_terraform_plugin_framework_diag.Diagnostics { + var diags github_com_hashicorp_terraform_plugin_framework_diag.Diagnostics + { + a, ok := tf.Attrs["kind"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Kind"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Kind", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } else { + var t string + if !v.Null && !v.Unknown { + t = string(v.Value) + } + obj.Kind = t + } + } + } + { + a, ok := tf.Attrs["sub_kind"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.SubKind"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.SubKind", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } else { + var t string + if !v.Null && !v.Unknown { + t = string(v.Value) + } + obj.SubKind = t + } + } + } + { + a, ok := tf.Attrs["version"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Version"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Version", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } else { + var t string + if !v.Null && !v.Unknown { + t = string(v.Value) + } + obj.Version = t + } + } + } + { + a, ok := tf.Attrs["metadata"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Metadata"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.Object) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata", "github.com/hashicorp/terraform-plugin-framework/types.Object"}) + } else { + obj.Metadata = github_com_gravitational_teleport_api_types.Metadata{} + if !v.Null && !v.Unknown { + tf := v + obj := &obj.Metadata + { + a, ok := tf.Attrs["name"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Metadata.Name"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Name", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } else { + var t string + if !v.Null && !v.Unknown { + t = string(v.Value) + } + obj.Name = t + } + } + } + { + a, ok := tf.Attrs["namespace"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Metadata.Namespace"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Namespace", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } else { + var t string + if !v.Null && !v.Unknown { + t = string(v.Value) + } + obj.Namespace = t + } + } + } + { + a, ok := tf.Attrs["description"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Metadata.Description"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Description", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } else { + var t string + if !v.Null && !v.Unknown { + t = string(v.Value) + } + obj.Description = t + } + } + } + { + a, ok := tf.Attrs["labels"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Metadata.Labels"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.Map) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Labels", "github.com/hashicorp/terraform-plugin-framework/types.Map"}) + } else { + obj.Labels = make(map[string]string, len(v.Elems)) + if !v.Null && !v.Unknown { + for k, a := range v.Elems { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Labels", "github_com_hashicorp_terraform_plugin_framework_types.String"}) + } else { + var t string + if !v.Null && !v.Unknown { + t = string(v.Value) + } + obj.Labels[k] = t + } + } + } + } + } + } + { + a, ok := tf.Attrs["expires"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Metadata.Expires"}) + } else { + v, ok := a.(TimeValue) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Expires", "TimeValue"}) + } else { + var t *time.Time + if !v.Null && !v.Unknown { + c := time.Time(v.Value) + t = &c + } + obj.Expires = t + } + } + } + { + a, ok := tf.Attrs["revision"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Metadata.Revision"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Revision", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } else { + var t string + if !v.Null && !v.Unknown { + t = string(v.Value) + } + obj.Revision = t + } + } + } + } + } + } + } + { + a, ok := tf.Attrs["spec"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Spec"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.Object) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Spec", "github.com/hashicorp/terraform-plugin-framework/types.Object"}) + } else { + obj.Spec = github_com_gravitational_teleport_api_types.DynamicWindowsDesktopSpecV1{} + if !v.Null && !v.Unknown { + tf := v + obj := &obj.Spec + { + a, ok := tf.Attrs["addr"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Spec.Addr"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.Addr", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } else { + var t string + if !v.Null && !v.Unknown { + t = string(v.Value) + } + obj.Addr = t + } + } + } + { + a, ok := tf.Attrs["domain"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Spec.Domain"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.Domain", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } else { + var t string + if !v.Null && !v.Unknown { + t = string(v.Value) + } + obj.Domain = t + } + } + } + { + a, ok := tf.Attrs["non_ad"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Spec.NonAD"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.Bool) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.NonAD", "github.com/hashicorp/terraform-plugin-framework/types.Bool"}) + } else { + var t bool + if !v.Null && !v.Unknown { + t = bool(v.Value) + } + obj.NonAD = t + } + } + } + { + a, ok := tf.Attrs["screen_size"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.Object) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize", "github.com/hashicorp/terraform-plugin-framework/types.Object"}) + } else { + obj.ScreenSize = nil + if !v.Null && !v.Unknown { + tf := v + obj.ScreenSize = &github_com_gravitational_teleport_api_types.Resolution{} + obj := obj.ScreenSize + { + a, ok := tf.Attrs["width"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize.Width"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.Int64) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize.Width", "github.com/hashicorp/terraform-plugin-framework/types.Int64"}) + } else { + var t uint32 + if !v.Null && !v.Unknown { + t = uint32(v.Value) + } + obj.Width = t + } + } + } + { + a, ok := tf.Attrs["height"] + if !ok { + diags.Append(attrReadMissingDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize.Height"}) + } else { + v, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.Int64) + if !ok { + diags.Append(attrReadConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize.Height", "github.com/hashicorp/terraform-plugin-framework/types.Int64"}) + } else { + var t uint32 + if !v.Null && !v.Unknown { + t = uint32(v.Value) + } + obj.Height = t + } + } + } + } + } + } + } + } + } + } + } + return diags +} + +// CopyDynamicWindowsDesktopV1ToTerraform copies contents of the source Terraform object into a target struct +func CopyDynamicWindowsDesktopV1ToTerraform(ctx context.Context, obj *github_com_gravitational_teleport_api_types.DynamicWindowsDesktopV1, tf *github_com_hashicorp_terraform_plugin_framework_types.Object) github_com_hashicorp_terraform_plugin_framework_diag.Diagnostics { + var diags github_com_hashicorp_terraform_plugin_framework_diag.Diagnostics + tf.Null = false + tf.Unknown = false + if tf.Attrs == nil { + tf.Attrs = make(map[string]github_com_hashicorp_terraform_plugin_framework_attr.Value) + } + { + t, ok := tf.AttrTypes["kind"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Kind"}) + } else { + v, ok := tf.Attrs["kind"].(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Kind", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Kind", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } + v.Null = string(obj.Kind) == "" + } + v.Value = string(obj.Kind) + v.Unknown = false + tf.Attrs["kind"] = v + } + } + { + t, ok := tf.AttrTypes["sub_kind"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.SubKind"}) + } else { + v, ok := tf.Attrs["sub_kind"].(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.SubKind", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.SubKind", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } + v.Null = string(obj.SubKind) == "" + } + v.Value = string(obj.SubKind) + v.Unknown = false + tf.Attrs["sub_kind"] = v + } + } + { + t, ok := tf.AttrTypes["version"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Version"}) + } else { + v, ok := tf.Attrs["version"].(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Version", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Version", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } + v.Null = string(obj.Version) == "" + } + v.Value = string(obj.Version) + v.Unknown = false + tf.Attrs["version"] = v + } + } + { + a, ok := tf.AttrTypes["metadata"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Metadata"}) + } else { + o, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.ObjectType) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata", "github.com/hashicorp/terraform-plugin-framework/types.ObjectType"}) + } else { + v, ok := tf.Attrs["metadata"].(github_com_hashicorp_terraform_plugin_framework_types.Object) + if !ok { + v = github_com_hashicorp_terraform_plugin_framework_types.Object{ + + AttrTypes: o.AttrTypes, + Attrs: make(map[string]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(o.AttrTypes)), + } + } else { + if v.Attrs == nil { + v.Attrs = make(map[string]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(tf.AttrTypes)) + } + } + { + obj := obj.Metadata + tf := &v + { + t, ok := tf.AttrTypes["name"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Metadata.Name"}) + } else { + v, ok := tf.Attrs["name"].(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Metadata.Name", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Name", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } + v.Null = string(obj.Name) == "" + } + v.Value = string(obj.Name) + v.Unknown = false + tf.Attrs["name"] = v + } + } + { + t, ok := tf.AttrTypes["namespace"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Metadata.Namespace"}) + } else { + v, ok := tf.Attrs["namespace"].(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Metadata.Namespace", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Namespace", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } + v.Null = string(obj.Namespace) == "" + } + v.Value = string(obj.Namespace) + v.Unknown = false + tf.Attrs["namespace"] = v + } + } + { + t, ok := tf.AttrTypes["description"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Metadata.Description"}) + } else { + v, ok := tf.Attrs["description"].(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Metadata.Description", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Description", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } + v.Null = string(obj.Description) == "" + } + v.Value = string(obj.Description) + v.Unknown = false + tf.Attrs["description"] = v + } + } + { + a, ok := tf.AttrTypes["labels"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Metadata.Labels"}) + } else { + o, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.MapType) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Labels", "github.com/hashicorp/terraform-plugin-framework/types.MapType"}) + } else { + c, ok := tf.Attrs["labels"].(github_com_hashicorp_terraform_plugin_framework_types.Map) + if !ok { + c = github_com_hashicorp_terraform_plugin_framework_types.Map{ + + ElemType: o.ElemType, + Elems: make(map[string]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.Labels)), + Null: true, + } + } else { + if c.Elems == nil { + c.Elems = make(map[string]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(obj.Labels)) + } + } + if obj.Labels != nil { + t := o.ElemType + for k, a := range obj.Labels { + v, ok := tf.Attrs["labels"].(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Metadata.Labels", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Labels", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } + v.Null = false + } + v.Value = string(a) + v.Unknown = false + c.Elems[k] = v + } + if len(obj.Labels) > 0 { + c.Null = false + } + } + c.Unknown = false + tf.Attrs["labels"] = c + } + } + } + { + t, ok := tf.AttrTypes["expires"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Metadata.Expires"}) + } else { + v, ok := tf.Attrs["expires"].(TimeValue) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Metadata.Expires", err}) + } + v, ok = i.(TimeValue) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Expires", "TimeValue"}) + } + v.Null = false + } + if obj.Expires == nil { + v.Null = true + } else { + v.Null = false + v.Value = time.Time(*obj.Expires) + } + v.Unknown = false + tf.Attrs["expires"] = v + } + } + { + t, ok := tf.AttrTypes["revision"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Metadata.Revision"}) + } else { + v, ok := tf.Attrs["revision"].(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Metadata.Revision", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Metadata.Revision", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } + v.Null = string(obj.Revision) == "" + } + v.Value = string(obj.Revision) + v.Unknown = false + tf.Attrs["revision"] = v + } + } + } + v.Unknown = false + tf.Attrs["metadata"] = v + } + } + } + { + a, ok := tf.AttrTypes["spec"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Spec"}) + } else { + o, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.ObjectType) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Spec", "github.com/hashicorp/terraform-plugin-framework/types.ObjectType"}) + } else { + v, ok := tf.Attrs["spec"].(github_com_hashicorp_terraform_plugin_framework_types.Object) + if !ok { + v = github_com_hashicorp_terraform_plugin_framework_types.Object{ + + AttrTypes: o.AttrTypes, + Attrs: make(map[string]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(o.AttrTypes)), + } + } else { + if v.Attrs == nil { + v.Attrs = make(map[string]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(tf.AttrTypes)) + } + } + { + obj := obj.Spec + tf := &v + { + t, ok := tf.AttrTypes["addr"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Spec.Addr"}) + } else { + v, ok := tf.Attrs["addr"].(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Spec.Addr", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.Addr", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } + v.Null = string(obj.Addr) == "" + } + v.Value = string(obj.Addr) + v.Unknown = false + tf.Attrs["addr"] = v + } + } + { + t, ok := tf.AttrTypes["domain"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Spec.Domain"}) + } else { + v, ok := tf.Attrs["domain"].(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Spec.Domain", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.String) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.Domain", "github.com/hashicorp/terraform-plugin-framework/types.String"}) + } + v.Null = string(obj.Domain) == "" + } + v.Value = string(obj.Domain) + v.Unknown = false + tf.Attrs["domain"] = v + } + } + { + t, ok := tf.AttrTypes["non_ad"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Spec.NonAD"}) + } else { + v, ok := tf.Attrs["non_ad"].(github_com_hashicorp_terraform_plugin_framework_types.Bool) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Spec.NonAD", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.Bool) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.NonAD", "github.com/hashicorp/terraform-plugin-framework/types.Bool"}) + } + v.Null = bool(obj.NonAD) == false + } + v.Value = bool(obj.NonAD) + v.Unknown = false + tf.Attrs["non_ad"] = v + } + } + { + a, ok := tf.AttrTypes["screen_size"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize"}) + } else { + o, ok := a.(github_com_hashicorp_terraform_plugin_framework_types.ObjectType) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize", "github.com/hashicorp/terraform-plugin-framework/types.ObjectType"}) + } else { + v, ok := tf.Attrs["screen_size"].(github_com_hashicorp_terraform_plugin_framework_types.Object) + if !ok { + v = github_com_hashicorp_terraform_plugin_framework_types.Object{ + + AttrTypes: o.AttrTypes, + Attrs: make(map[string]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(o.AttrTypes)), + } + } else { + if v.Attrs == nil { + v.Attrs = make(map[string]github_com_hashicorp_terraform_plugin_framework_attr.Value, len(tf.AttrTypes)) + } + } + if obj.ScreenSize == nil { + v.Null = true + } else { + obj := obj.ScreenSize + tf := &v + { + t, ok := tf.AttrTypes["width"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize.Width"}) + } else { + v, ok := tf.Attrs["width"].(github_com_hashicorp_terraform_plugin_framework_types.Int64) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Spec.ScreenSize.Width", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.Int64) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize.Width", "github.com/hashicorp/terraform-plugin-framework/types.Int64"}) + } + v.Null = int64(obj.Width) == 0 + } + v.Value = int64(obj.Width) + v.Unknown = false + tf.Attrs["width"] = v + } + } + { + t, ok := tf.AttrTypes["height"] + if !ok { + diags.Append(attrWriteMissingDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize.Height"}) + } else { + v, ok := tf.Attrs["height"].(github_com_hashicorp_terraform_plugin_framework_types.Int64) + if !ok { + i, err := t.ValueFromTerraform(ctx, github_com_hashicorp_terraform_plugin_go_tftypes.NewValue(t.TerraformType(ctx), nil)) + if err != nil { + diags.Append(attrWriteGeneralError{"DynamicWindowsDesktopV1.Spec.ScreenSize.Height", err}) + } + v, ok = i.(github_com_hashicorp_terraform_plugin_framework_types.Int64) + if !ok { + diags.Append(attrWriteConversionFailureDiag{"DynamicWindowsDesktopV1.Spec.ScreenSize.Height", "github.com/hashicorp/terraform-plugin-framework/types.Int64"}) + } + v.Null = int64(obj.Height) == 0 + } + v.Value = int64(obj.Height) + v.Unknown = false + tf.Attrs["height"] = v + } + } + } + v.Unknown = false + tf.Attrs["screen_size"] = v + } + } + } + } + v.Unknown = false + tf.Attrs["spec"] = v + } + } + } + return diags +} + // CopyInstallerV1FromTerraform copies contents of the source Terraform object into a target struct func CopyInstallerV1FromTerraform(_ context.Context, tf github_com_hashicorp_terraform_plugin_framework_types.Object, obj *github_com_gravitational_teleport_api_types.InstallerV1) github_com_hashicorp_terraform_plugin_framework_diag.Diagnostics { var diags github_com_hashicorp_terraform_plugin_framework_diag.Diagnostics diff --git a/lib/services/presets.go b/lib/services/presets.go index a4b6fec68e70c..2601730179647 100644 --- a/lib/services/presets.go +++ b/lib/services/presets.go @@ -578,12 +578,14 @@ func NewPresetTerraformProviderRole() types.Role { Spec: types.RoleSpecV6{ Allow: types.RoleConditions{ // In Teleport, you can only see what you have access to. To be able to reconcile - // Apps, Databases, and Nodes, Terraform must be able to access them all. + // Apps, Databases, Dynamic Windows Desktops, and Nodes, Terraform must be able to + // access them all. // For Databases and Nodes, Terraform cannot actually access them because it has no // Login/user set. - AppLabels: map[string]apiutils.Strings{types.Wildcard: []string{types.Wildcard}}, - DatabaseLabels: map[string]apiutils.Strings{types.Wildcard: []string{types.Wildcard}}, - NodeLabels: map[string]apiutils.Strings{types.Wildcard: []string{types.Wildcard}}, + AppLabels: map[string]apiutils.Strings{types.Wildcard: []string{types.Wildcard}}, + DatabaseLabels: map[string]apiutils.Strings{types.Wildcard: []string{types.Wildcard}}, + NodeLabels: map[string]apiutils.Strings{types.Wildcard: []string{types.Wildcard}}, + WindowsDesktopLabels: map[string]apiutils.Strings{types.Wildcard: []string{types.Wildcard}}, // Every resource currently supported by the Terraform provider. Rules: []types.Rule{ { @@ -594,6 +596,7 @@ func NewPresetTerraformProviderRole() types.Role { types.KindClusterMaintenanceConfig, types.KindClusterNetworkingConfig, types.KindDatabase, + types.KindDynamicWindowsDesktop, types.KindDevice, types.KindGithub, types.KindLoginRule,