diff --git a/integrations/terraform/gen/plural_resource.go.tpl b/integrations/terraform/gen/plural_resource.go.tpl index 89b4557008a8f..72a5f39a458df 100644 --- a/integrations/terraform/gen/plural_resource.go.tpl +++ b/integrations/terraform/gen/plural_resource.go.tpl @@ -163,6 +163,7 @@ func (r resourceTeleport{{.Name}}) Create(ctx context.Context, req tfsdk.CreateR var {{.VarName}}I {{.ProtoPackage}}.{{ if ne .IfaceName ""}}{{.IfaceName}}{{else}}{{.Name}}{{end}} {{- end}} {{- end }} + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -170,12 +171,13 @@ func (r resourceTeleport{{.Name}}) Create(ctx context.Context, req tfsdk.CreateR {{.VarName}}I, err = r.p.Client.{{.GetMethod}}(ctx, {{if .Namespaced}}defaults.Namespace, {{end}}id{{if ne .WithSecrets ""}}, {{.WithSecrets}}{{end}}) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading {{.Name}}", trace.Wrap(bErr), "{{.Kind}}")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading {{.Name}}", trace.Wrap(err), "{{.Kind}}")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading {{.Name}} (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "{{.Kind}}") + return } continue } diff --git a/integrations/terraform/gen/singular_resource.go.tpl b/integrations/terraform/gen/singular_resource.go.tpl index 69584a90a74f6..3ff7e22962da6 100644 --- a/integrations/terraform/gen/singular_resource.go.tpl +++ b/integrations/terraform/gen/singular_resource.go.tpl @@ -140,11 +140,27 @@ func (r resourceTeleport{{.Name}}) Create(ctx context.Context, req tfsdk.CreateR var {{.VarName}}I {{.ProtoPackage}}.{{ if ne .IfaceName ""}}{{.IfaceName}}{{else}}{{.Name}}{{end}} {{- end}} + // Try getting the resource until it exists and is different than the previous ones. + // There are two types of singleton resources: + // - the ones who can deleted and return a trace.NotFoundErr + // - the ones who cannot be deleted, only reset. In this case, the resource revision is used to know if the change got applied. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { tries = tries + 1 {{.VarName}}I, err = r.p.Client.{{.GetMethod}}(ctx) + if trace.IsNotFound(err) { + if bErr := backoff.Do(ctx); bErr != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading {{.Name}}", trace.Wrap(err), "{{.Kind}}")) + return + } + if tries >= r.p.RetryConfig.MaxTries { + diagMessage := fmt.Sprintf("Error reading {{.Name}} (tried %d times) - state outdated, please import resource", tries) + resp.Diagnostics.AddError(diagMessage, "{{.Kind}}") + return + } + continue + } if err != nil { resp.Diagnostics.Append(diagFromWrappedErr("Error reading {{.Name}}", trace.Wrap(err), "{{.Kind}}")) return diff --git a/integrations/terraform/provider/resource_teleport_access_list.go b/integrations/terraform/provider/resource_teleport_access_list.go index 340f1818cb0f5..3394454a255e0 100755 --- a/integrations/terraform/provider/resource_teleport_access_list.go +++ b/integrations/terraform/provider/resource_teleport_access_list.go @@ -109,6 +109,7 @@ func (r resourceTeleportAccessList) Create(ctx context.Context, req tfsdk.Create return } var accessListI = accessListResource + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -116,12 +117,13 @@ func (r resourceTeleportAccessList) Create(ctx context.Context, req tfsdk.Create accessListI, err = r.p.Client.AccessListClient().GetAccessList(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading AccessList", trace.Wrap(bErr), "access_list")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading AccessList", trace.Wrap(err), "access_list")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading AccessList (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "access_list") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_access_monitoring_rule.go b/integrations/terraform/provider/resource_teleport_access_monitoring_rule.go index 011cd58b37615..44c7306dd908d 100755 --- a/integrations/terraform/provider/resource_teleport_access_monitoring_rule.go +++ b/integrations/terraform/provider/resource_teleport_access_monitoring_rule.go @@ -103,6 +103,7 @@ func (r resourceTeleportAccessMonitoringRule) Create(ctx context.Context, req tf return } var accessMonitoringRuleI *accessmonitoringrulesv1.AccessMonitoringRule + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -110,12 +111,13 @@ func (r resourceTeleportAccessMonitoringRule) Create(ctx context.Context, req tf accessMonitoringRuleI, err = r.p.Client.AccessMonitoringRulesClient().GetAccessMonitoringRule(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading AccessMonitoringRule", trace.Wrap(bErr), "access_monitoring_rule")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading AccessMonitoringRule", trace.Wrap(err), "access_monitoring_rule")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading AccessMonitoringRule (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "access_monitoring_rule") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_app.go b/integrations/terraform/provider/resource_teleport_app.go index 13ccba95012f9..adbfde525a05d 100755 --- a/integrations/terraform/provider/resource_teleport_app.go +++ b/integrations/terraform/provider/resource_teleport_app.go @@ -108,6 +108,7 @@ func (r resourceTeleportApp) Create(ctx context.Context, req tfsdk.CreateResourc // Not really an inferface, just using the same name for easier templating. var appI apitypes.Application + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportApp) Create(ctx context.Context, req tfsdk.CreateResourc appI, err = r.p.Client.GetApp(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading App", trace.Wrap(bErr), "app")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading App", trace.Wrap(err), "app")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading App (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "app") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_auth_preference.go b/integrations/terraform/provider/resource_teleport_auth_preference.go index 72ab6e4d6d1bd..30171a7bd67c2 100755 --- a/integrations/terraform/provider/resource_teleport_auth_preference.go +++ b/integrations/terraform/provider/resource_teleport_auth_preference.go @@ -94,11 +94,27 @@ func (r resourceTeleportAuthPreference) Create(ctx context.Context, req tfsdk.Cr var authPreferenceI apitypes.AuthPreference + // Try getting the resource until it exists and is different than the previous ones. + // There are two types of singleton resources: + // - the ones who can deleted and return a trace.NotFoundErr + // - the ones who cannot be deleted, only reset. In this case, the resource revision is used to know if the change got applied. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { tries = tries + 1 authPreferenceI, err = r.p.Client.GetAuthPreference(ctx) + if trace.IsNotFound(err) { + if bErr := backoff.Do(ctx); bErr != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading AuthPreference", trace.Wrap(err), "cluster_auth_preference")) + return + } + if tries >= r.p.RetryConfig.MaxTries { + diagMessage := fmt.Sprintf("Error reading AuthPreference (tried %d times) - state outdated, please import resource", tries) + resp.Diagnostics.AddError(diagMessage, "cluster_auth_preference") + return + } + continue + } if err != nil { resp.Diagnostics.Append(diagFromWrappedErr("Error reading AuthPreference", trace.Wrap(err), "cluster_auth_preference")) return diff --git a/integrations/terraform/provider/resource_teleport_autoupdate_config.go b/integrations/terraform/provider/resource_teleport_autoupdate_config.go index 695484bee0eed..ce0ba0e4b223a 100755 --- a/integrations/terraform/provider/resource_teleport_autoupdate_config.go +++ b/integrations/terraform/provider/resource_teleport_autoupdate_config.go @@ -99,11 +99,27 @@ func (r resourceTeleportAutoUpdateConfig) Create(ctx context.Context, req tfsdk. var autoUpdateConfigI *autoupdatev1.AutoUpdateConfig + // Try getting the resource until it exists and is different than the previous ones. + // There are two types of singleton resources: + // - the ones who can deleted and return a trace.NotFoundErr + // - the ones who cannot be deleted, only reset. In this case, the resource revision is used to know if the change got applied. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { tries = tries + 1 autoUpdateConfigI, err = r.p.Client.GetAutoUpdateConfig(ctx) + if trace.IsNotFound(err) { + if bErr := backoff.Do(ctx); bErr != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading AutoUpdateConfig", trace.Wrap(err), "autoupdate_config")) + return + } + if tries >= r.p.RetryConfig.MaxTries { + diagMessage := fmt.Sprintf("Error reading AutoUpdateConfig (tried %d times) - state outdated, please import resource", tries) + resp.Diagnostics.AddError(diagMessage, "autoupdate_config") + return + } + continue + } if err != nil { resp.Diagnostics.Append(diagFromWrappedErr("Error reading AutoUpdateConfig", trace.Wrap(err), "autoupdate_config")) return diff --git a/integrations/terraform/provider/resource_teleport_autoupdate_version.go b/integrations/terraform/provider/resource_teleport_autoupdate_version.go index ff1b27cb1e75b..2a3216b99484c 100755 --- a/integrations/terraform/provider/resource_teleport_autoupdate_version.go +++ b/integrations/terraform/provider/resource_teleport_autoupdate_version.go @@ -99,11 +99,27 @@ func (r resourceTeleportAutoUpdateVersion) Create(ctx context.Context, req tfsdk var autoUpdateVersionI *autoupdatev1.AutoUpdateVersion + // Try getting the resource until it exists and is different than the previous ones. + // There are two types of singleton resources: + // - the ones who can deleted and return a trace.NotFoundErr + // - the ones who cannot be deleted, only reset. In this case, the resource revision is used to know if the change got applied. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { tries = tries + 1 autoUpdateVersionI, err = r.p.Client.GetAutoUpdateVersion(ctx) + if trace.IsNotFound(err) { + if bErr := backoff.Do(ctx); bErr != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading AutoUpdateVersion", trace.Wrap(err), "autoupdate_version")) + return + } + if tries >= r.p.RetryConfig.MaxTries { + diagMessage := fmt.Sprintf("Error reading AutoUpdateVersion (tried %d times) - state outdated, please import resource", tries) + resp.Diagnostics.AddError(diagMessage, "autoupdate_version") + return + } + continue + } if err != nil { resp.Diagnostics.Append(diagFromWrappedErr("Error reading AutoUpdateVersion", trace.Wrap(err), "autoupdate_version")) return diff --git a/integrations/terraform/provider/resource_teleport_cluster_maintenance_config.go b/integrations/terraform/provider/resource_teleport_cluster_maintenance_config.go index e8780760a3805..9b796f4a8440e 100755 --- a/integrations/terraform/provider/resource_teleport_cluster_maintenance_config.go +++ b/integrations/terraform/provider/resource_teleport_cluster_maintenance_config.go @@ -100,11 +100,27 @@ func (r resourceTeleportClusterMaintenanceConfig) Create(ctx context.Context, re var clusterMaintenanceConfigI apitypes.ClusterMaintenanceConfig + // Try getting the resource until it exists and is different than the previous ones. + // There are two types of singleton resources: + // - the ones who can deleted and return a trace.NotFoundErr + // - the ones who cannot be deleted, only reset. In this case, the resource revision is used to know if the change got applied. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { tries = tries + 1 clusterMaintenanceConfigI, err = r.p.Client.GetClusterMaintenanceConfig(ctx) + if trace.IsNotFound(err) { + if bErr := backoff.Do(ctx); bErr != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading ClusterMaintenanceConfig", trace.Wrap(err), "cluster_maintenance_config")) + return + } + if tries >= r.p.RetryConfig.MaxTries { + diagMessage := fmt.Sprintf("Error reading ClusterMaintenanceConfig (tried %d times) - state outdated, please import resource", tries) + resp.Diagnostics.AddError(diagMessage, "cluster_maintenance_config") + return + } + continue + } if err != nil { resp.Diagnostics.Append(diagFromWrappedErr("Error reading ClusterMaintenanceConfig", trace.Wrap(err), "cluster_maintenance_config")) return diff --git a/integrations/terraform/provider/resource_teleport_cluster_networking_config.go b/integrations/terraform/provider/resource_teleport_cluster_networking_config.go index a8a3561eaf660..ba82d51ea5caf 100755 --- a/integrations/terraform/provider/resource_teleport_cluster_networking_config.go +++ b/integrations/terraform/provider/resource_teleport_cluster_networking_config.go @@ -94,11 +94,27 @@ func (r resourceTeleportClusterNetworkingConfig) Create(ctx context.Context, req var clusterNetworkingConfigI apitypes.ClusterNetworkingConfig + // Try getting the resource until it exists and is different than the previous ones. + // There are two types of singleton resources: + // - the ones who can deleted and return a trace.NotFoundErr + // - the ones who cannot be deleted, only reset. In this case, the resource revision is used to know if the change got applied. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { tries = tries + 1 clusterNetworkingConfigI, err = r.p.Client.GetClusterNetworkingConfig(ctx) + if trace.IsNotFound(err) { + if bErr := backoff.Do(ctx); bErr != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading ClusterNetworkingConfig", trace.Wrap(err), "cluster_networking_config")) + return + } + if tries >= r.p.RetryConfig.MaxTries { + diagMessage := fmt.Sprintf("Error reading ClusterNetworkingConfig (tried %d times) - state outdated, please import resource", tries) + resp.Diagnostics.AddError(diagMessage, "cluster_networking_config") + return + } + continue + } if err != nil { resp.Diagnostics.Append(diagFromWrappedErr("Error reading ClusterNetworkingConfig", trace.Wrap(err), "cluster_networking_config")) return diff --git a/integrations/terraform/provider/resource_teleport_database.go b/integrations/terraform/provider/resource_teleport_database.go index 91496c5221bef..ac3ec2787be9f 100755 --- a/integrations/terraform/provider/resource_teleport_database.go +++ b/integrations/terraform/provider/resource_teleport_database.go @@ -108,6 +108,7 @@ func (r resourceTeleportDatabase) Create(ctx context.Context, req tfsdk.CreateRe // Not really an inferface, just using the same name for easier templating. var databaseI apitypes.Database + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportDatabase) Create(ctx context.Context, req tfsdk.CreateRe databaseI, err = r.p.Client.GetDatabase(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading Database", trace.Wrap(bErr), "db")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading Database", trace.Wrap(err), "db")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading Database (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "db") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_device_trust.go b/integrations/terraform/provider/resource_teleport_device_trust.go index fd7e350159917..5d0261425f6cd 100755 --- a/integrations/terraform/provider/resource_teleport_device_trust.go +++ b/integrations/terraform/provider/resource_teleport_device_trust.go @@ -105,6 +105,7 @@ func (r resourceTeleportDeviceV1) Create(ctx context.Context, req tfsdk.CreateRe return } var trustedDeviceI *apitypes.DeviceV1 + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -112,12 +113,13 @@ func (r resourceTeleportDeviceV1) Create(ctx context.Context, req tfsdk.CreateRe trustedDeviceI, err = r.p.Client.GetDeviceResource(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading DeviceV1", trace.Wrap(bErr), "device")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading DeviceV1", trace.Wrap(err), "device")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading DeviceV1 (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "device") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_dynamic_windows_desktop.go b/integrations/terraform/provider/resource_teleport_dynamic_windows_desktop.go index 9305bb538e716..e3facf4b00e15 100755 --- a/integrations/terraform/provider/resource_teleport_dynamic_windows_desktop.go +++ b/integrations/terraform/provider/resource_teleport_dynamic_windows_desktop.go @@ -108,6 +108,7 @@ func (r resourceTeleportDynamicWindowsDesktop) Create(ctx context.Context, req t // Not really an inferface, just using the same name for easier templating. var desktopI apitypes.DynamicWindowsDesktop + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportDynamicWindowsDesktop) Create(ctx context.Context, req t 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")) + 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 } continue } diff --git a/integrations/terraform/provider/resource_teleport_github_connector.go b/integrations/terraform/provider/resource_teleport_github_connector.go index 74d91649735ab..ac8fe75cd5b30 100755 --- a/integrations/terraform/provider/resource_teleport_github_connector.go +++ b/integrations/terraform/provider/resource_teleport_github_connector.go @@ -108,6 +108,7 @@ func (r resourceTeleportGithubConnector) Create(ctx context.Context, req tfsdk.C // Not really an inferface, just using the same name for easier templating. var githubConnectorI apitypes.GithubConnector + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportGithubConnector) Create(ctx context.Context, req tfsdk.C githubConnectorI, err = r.p.Client.GetGithubConnector(ctx, id, true) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading GithubConnector", trace.Wrap(bErr), "github")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading GithubConnector", trace.Wrap(err), "github")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading GithubConnector (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "github") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_installer.go b/integrations/terraform/provider/resource_teleport_installer.go index 9582e64e4a9c9..eb7631eabdd26 100755 --- a/integrations/terraform/provider/resource_teleport_installer.go +++ b/integrations/terraform/provider/resource_teleport_installer.go @@ -108,6 +108,7 @@ func (r resourceTeleportInstaller) Create(ctx context.Context, req tfsdk.CreateR // Not really an inferface, just using the same name for easier templating. var installerI apitypes.Installer + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportInstaller) Create(ctx context.Context, req tfsdk.CreateR installerI, err = r.p.Client.GetInstaller(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading Installer", trace.Wrap(bErr), "installer")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading Installer", trace.Wrap(err), "installer")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading Installer (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "installer") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_login_rule.go b/integrations/terraform/provider/resource_teleport_login_rule.go index 8e329896d9961..1f460a8d8d990 100755 --- a/integrations/terraform/provider/resource_teleport_login_rule.go +++ b/integrations/terraform/provider/resource_teleport_login_rule.go @@ -101,6 +101,7 @@ func (r resourceTeleportLoginRule) Create(ctx context.Context, req tfsdk.CreateR return } var loginRuleI *loginrulev1.LoginRule + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -108,12 +109,13 @@ func (r resourceTeleportLoginRule) Create(ctx context.Context, req tfsdk.CreateR loginRuleI, err = r.p.Client.GetLoginRule(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading LoginRule", trace.Wrap(bErr), "login_rule")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading LoginRule", trace.Wrap(err), "login_rule")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading LoginRule (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "login_rule") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_oidc_connector.go b/integrations/terraform/provider/resource_teleport_oidc_connector.go index bd99743d97067..d825ed280a192 100755 --- a/integrations/terraform/provider/resource_teleport_oidc_connector.go +++ b/integrations/terraform/provider/resource_teleport_oidc_connector.go @@ -108,6 +108,7 @@ func (r resourceTeleportOIDCConnector) Create(ctx context.Context, req tfsdk.Cre // Not really an inferface, just using the same name for easier templating. var oidcConnectorI apitypes.OIDCConnector + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportOIDCConnector) Create(ctx context.Context, req tfsdk.Cre oidcConnectorI, err = r.p.Client.GetOIDCConnector(ctx, id, true) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading OIDCConnector", trace.Wrap(bErr), "oidc")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading OIDCConnector", trace.Wrap(err), "oidc")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading OIDCConnector (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "oidc") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_okta_import_rule.go b/integrations/terraform/provider/resource_teleport_okta_import_rule.go index 3e13f4bc8e06c..d7e45ac8ae2dc 100755 --- a/integrations/terraform/provider/resource_teleport_okta_import_rule.go +++ b/integrations/terraform/provider/resource_teleport_okta_import_rule.go @@ -108,6 +108,7 @@ func (r resourceTeleportOktaImportRule) Create(ctx context.Context, req tfsdk.Cr // Not really an inferface, just using the same name for easier templating. var oktaImportRuleI apitypes.OktaImportRule + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportOktaImportRule) Create(ctx context.Context, req tfsdk.Cr oktaImportRuleI, err = r.p.Client.OktaClient().GetOktaImportRule(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading OktaImportRule", trace.Wrap(bErr), "okta_import_rule")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading OktaImportRule", trace.Wrap(err), "okta_import_rule")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading OktaImportRule (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "okta_import_rule") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_provision_token.go b/integrations/terraform/provider/resource_teleport_provision_token.go index 2c83e3366c53e..52e3b5f9ac2e9 100755 --- a/integrations/terraform/provider/resource_teleport_provision_token.go +++ b/integrations/terraform/provider/resource_teleport_provision_token.go @@ -119,6 +119,7 @@ func (r resourceTeleportProvisionToken) Create(ctx context.Context, req tfsdk.Cr // Not really an inferface, just using the same name for easier templating. var provisionTokenI apitypes.ProvisionToken + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -126,12 +127,13 @@ func (r resourceTeleportProvisionToken) Create(ctx context.Context, req tfsdk.Cr provisionTokenI, err = r.p.Client.GetToken(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading ProvisionToken", trace.Wrap(bErr), "token")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading ProvisionToken", trace.Wrap(err), "token")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading ProvisionToken (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "token") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_role.go b/integrations/terraform/provider/resource_teleport_role.go index 11e81415ce0d3..9824a28171932 100755 --- a/integrations/terraform/provider/resource_teleport_role.go +++ b/integrations/terraform/provider/resource_teleport_role.go @@ -108,6 +108,7 @@ func (r resourceTeleportRole) Create(ctx context.Context, req tfsdk.CreateResour // Not really an inferface, just using the same name for easier templating. var roleI apitypes.Role + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportRole) Create(ctx context.Context, req tfsdk.CreateResour roleI, err = r.p.Client.GetRole(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading Role", trace.Wrap(bErr), "role")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading Role", trace.Wrap(err), "role")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading Role (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "role") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_saml_connector.go b/integrations/terraform/provider/resource_teleport_saml_connector.go index ee4eaf4a71b98..905981378bd01 100755 --- a/integrations/terraform/provider/resource_teleport_saml_connector.go +++ b/integrations/terraform/provider/resource_teleport_saml_connector.go @@ -108,6 +108,7 @@ func (r resourceTeleportSAMLConnector) Create(ctx context.Context, req tfsdk.Cre // Not really an inferface, just using the same name for easier templating. var samlConnectorI apitypes.SAMLConnector + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportSAMLConnector) Create(ctx context.Context, req tfsdk.Cre samlConnectorI, err = r.p.Client.GetSAMLConnector(ctx, id, true) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading SAMLConnector", trace.Wrap(bErr), "saml")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading SAMLConnector", trace.Wrap(err), "saml")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading SAMLConnector (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "saml") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_server.go b/integrations/terraform/provider/resource_teleport_server.go index d19a4ab661064..a531bcb267a75 100755 --- a/integrations/terraform/provider/resource_teleport_server.go +++ b/integrations/terraform/provider/resource_teleport_server.go @@ -110,6 +110,7 @@ func (r resourceTeleportServer) Create(ctx context.Context, req tfsdk.CreateReso // Not really an inferface, just using the same name for easier templating. var serverI apitypes.Server + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -117,12 +118,13 @@ func (r resourceTeleportServer) Create(ctx context.Context, req tfsdk.CreateReso serverI, err = r.p.Client.GetNode(ctx, defaults.Namespace, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading Server", trace.Wrap(bErr), "node")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading Server", trace.Wrap(err), "node")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading Server (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "node") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_session_recording_config.go b/integrations/terraform/provider/resource_teleport_session_recording_config.go index e9080ee2b018c..a4e6a703b3e79 100755 --- a/integrations/terraform/provider/resource_teleport_session_recording_config.go +++ b/integrations/terraform/provider/resource_teleport_session_recording_config.go @@ -94,11 +94,27 @@ func (r resourceTeleportSessionRecordingConfig) Create(ctx context.Context, req var sessionRecordingConfigI apitypes.SessionRecordingConfig + // Try getting the resource until it exists and is different than the previous ones. + // There are two types of singleton resources: + // - the ones who can deleted and return a trace.NotFoundErr + // - the ones who cannot be deleted, only reset. In this case, the resource revision is used to know if the change got applied. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { tries = tries + 1 sessionRecordingConfigI, err = r.p.Client.GetSessionRecordingConfig(ctx) + if trace.IsNotFound(err) { + if bErr := backoff.Do(ctx); bErr != nil { + resp.Diagnostics.Append(diagFromWrappedErr("Error reading SessionRecordingConfig", trace.Wrap(err), "session_recording_config")) + return + } + if tries >= r.p.RetryConfig.MaxTries { + diagMessage := fmt.Sprintf("Error reading SessionRecordingConfig (tried %d times) - state outdated, please import resource", tries) + resp.Diagnostics.AddError(diagMessage, "session_recording_config") + return + } + continue + } if err != nil { resp.Diagnostics.Append(diagFromWrappedErr("Error reading SessionRecordingConfig", trace.Wrap(err), "session_recording_config")) return diff --git a/integrations/terraform/provider/resource_teleport_static_host_user.go b/integrations/terraform/provider/resource_teleport_static_host_user.go index 61acd2e81fb26..ba4f0c4a12b17 100755 --- a/integrations/terraform/provider/resource_teleport_static_host_user.go +++ b/integrations/terraform/provider/resource_teleport_static_host_user.go @@ -103,6 +103,7 @@ func (r resourceTeleportStaticHostUser) Create(ctx context.Context, req tfsdk.Cr return } var staticHostUserI *userprovisioningv2.StaticHostUser + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -110,12 +111,13 @@ func (r resourceTeleportStaticHostUser) Create(ctx context.Context, req tfsdk.Cr staticHostUserI, err = r.p.Client.StaticHostUserClient().GetStaticHostUser(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading StaticHostUser", trace.Wrap(bErr), "static_host_user")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading StaticHostUser", trace.Wrap(err), "static_host_user")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading StaticHostUser (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "static_host_user") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_trusted_cluster.go b/integrations/terraform/provider/resource_teleport_trusted_cluster.go index c1398989468f9..fe536ce2426c9 100755 --- a/integrations/terraform/provider/resource_teleport_trusted_cluster.go +++ b/integrations/terraform/provider/resource_teleport_trusted_cluster.go @@ -108,6 +108,7 @@ func (r resourceTeleportTrustedCluster) Create(ctx context.Context, req tfsdk.Cr // Not really an inferface, just using the same name for easier templating. var trustedClusterI apitypes.TrustedCluster + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportTrustedCluster) Create(ctx context.Context, req tfsdk.Cr trustedClusterI, err = r.p.Client.GetTrustedCluster(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading TrustedCluster", trace.Wrap(bErr), "trusted_cluster")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading TrustedCluster", trace.Wrap(err), "trusted_cluster")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading TrustedCluster (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "trusted_cluster") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_user.go b/integrations/terraform/provider/resource_teleport_user.go index 0064798bc07cf..7bca3c57d1bf5 100755 --- a/integrations/terraform/provider/resource_teleport_user.go +++ b/integrations/terraform/provider/resource_teleport_user.go @@ -108,6 +108,7 @@ func (r resourceTeleportUser) Create(ctx context.Context, req tfsdk.CreateResour // Not really an inferface, just using the same name for easier templating. var userI apitypes.User + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -115,12 +116,13 @@ func (r resourceTeleportUser) Create(ctx context.Context, req tfsdk.CreateResour userI, err = r.p.Client.GetUser(ctx, id, false) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading User", trace.Wrap(bErr), "user")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading User", trace.Wrap(err), "user")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading User (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "user") + return } continue } diff --git a/integrations/terraform/provider/resource_teleport_workload_identity.go b/integrations/terraform/provider/resource_teleport_workload_identity.go index e5c59e0993b44..9120fb6edf36f 100755 --- a/integrations/terraform/provider/resource_teleport_workload_identity.go +++ b/integrations/terraform/provider/resource_teleport_workload_identity.go @@ -102,6 +102,7 @@ func (r resourceTeleportWorkloadIdentity) Create(ctx context.Context, req tfsdk. return } var workloadIdentityI *workloadidentityv1.WorkloadIdentity + // Try getting the resource until it exists. tries := 0 backoff := backoff.NewDecorr(r.p.RetryConfig.Base, r.p.RetryConfig.Cap, clockwork.NewRealClock()) for { @@ -109,12 +110,13 @@ func (r resourceTeleportWorkloadIdentity) Create(ctx context.Context, req tfsdk. workloadIdentityI, err = r.p.Client.GetWorkloadIdentity(ctx, id) if trace.IsNotFound(err) { if bErr := backoff.Do(ctx); bErr != nil { - resp.Diagnostics.Append(diagFromWrappedErr("Error reading WorkloadIdentity", trace.Wrap(bErr), "workload_identity")) + resp.Diagnostics.Append(diagFromWrappedErr("Error reading WorkloadIdentity", trace.Wrap(err), "workload_identity")) return } if tries >= r.p.RetryConfig.MaxTries { diagMessage := fmt.Sprintf("Error reading WorkloadIdentity (tried %d times) - state outdated, please import resource", tries) resp.Diagnostics.AddError(diagMessage, "workload_identity") + return } continue }