From ef59a188be8ae2b829ecbe10f92730eda27cc789 Mon Sep 17 00:00:00 2001 From: Dylan-Christopherson Date: Fri, 10 Jan 2025 11:01:04 -0600 Subject: [PATCH] Make resources use the sds_endpoint --- examples/ibm-sdsaas/README.md | 6 ++++- examples/ibm-sdsaas/main.tf | 5 ++++ examples/ibm-sdsaas/variables.tf | 6 +++++ go.mod | 7 ++--- go.sum | 17 +++++++----- ibm/conns/config.go | 1 - ibm/service/sdsaas/resource_ibm_sds_host.go | 18 +++++++++---- ibm/service/sdsaas/resource_ibm_sds_volume.go | 27 ++++++++++++++++--- 8 files changed, 66 insertions(+), 21 deletions(-) diff --git a/examples/ibm-sdsaas/README.md b/examples/ibm-sdsaas/README.md index 70fc61895e..41194c7538 100644 --- a/examples/ibm-sdsaas/README.md +++ b/examples/ibm-sdsaas/README.md @@ -24,6 +24,7 @@ Run `terraform destroy` when you don't need these resources. ```hcl resource "ibm_sds_volume" "sds_volume_instance" { + sds_endpoint = var.sds_endpoint hostnqnstring = var.sds_volume_hostnqnstring capacity = var.sds_volume_capacity name = var.sds_volume_name @@ -35,6 +36,7 @@ resource "ibm_sds_volume" "sds_volume_instance" { | Name | Description | Type | Required | |------|-------------|------|---------| | ibmcloud\_api\_key | IBM Cloud API key | `string` | true | +| sds_endpoint | IBM Cloud Endpoint | `string` | false | | hostnqnstring | The host nqn. | `string` | false | | capacity | The capacity of the volume (in gigabytes). | `number` | true | | name | The name of the volume. | `string` | false | @@ -55,6 +57,7 @@ resource "ibm_sds_volume" "sds_volume_instance" { ```hcl resource "ibm_sds_host" "sds_host_instance" { + sds_endpoint = var.sds_endpoint name = var.sds_host_name nqn = var.sds_host_nqn volumes = var.sds_host_volumes @@ -66,6 +69,7 @@ resource "ibm_sds_host" "sds_host_instance" { | Name | Description | Type | Required | |------|-------------|------|---------| | ibmcloud\_api\_key | IBM Cloud API key | `string` | true | +| sds_endpoint | IBM Cloud Endpoint | `string` | false | | name | The name for this host. The name must not be used by another host. If unspecified, the name will be a hyphenated list of randomly-selected words. | `string` | false | | nqn | The NQN of the host configured in customer's environment. | `string` | true | | volumes | The host-to-volume map. | `list()` | false | @@ -79,7 +83,7 @@ resource "ibm_sds_host" "sds_host_instance" { ## Assumptions -The `IBMCLOUD_SDS_ENDPOINT` is required to be set by the user before running the terraform commands. This is the endpoint provided to customers to perform operations against their service. +The `IBMCLOUD_SDS_ENDPOINT` can optionally be set instead of setting `sds_endpoint` in each of the resources. This is the endpoint provided to customers to perform operations against their service. ## Requirements diff --git a/examples/ibm-sdsaas/main.tf b/examples/ibm-sdsaas/main.tf index 31c380d86e..97bb39fe34 100644 --- a/examples/ibm-sdsaas/main.tf +++ b/examples/ibm-sdsaas/main.tf @@ -4,6 +4,8 @@ provider "ibm" { // Provision sds_volume resource instance resource "ibm_sds_volume" "sds_volume_instance_1" { + sds_endpoint = var.sds_endpoint + hostnqnstring = var.sds_volume_hostnqnstring capacity = var.sds_volume_capacity name = var.sds_volume_name_1 @@ -11,6 +13,8 @@ resource "ibm_sds_volume" "sds_volume_instance_1" { // Provision sds_volume resource instance resource "ibm_sds_volume" "sds_volume_instance_2" { + sds_endpoint = var.sds_endpoint + hostnqnstring = var.sds_volume_hostnqnstring capacity = var.sds_volume_capacity name = var.sds_volume_name_2 @@ -18,6 +22,7 @@ resource "ibm_sds_volume" "sds_volume_instance_2" { // Provision sds_host resource instance resource "ibm_sds_host" "sds_host_instance" { + sds_endpoint = var.sds_endpoint name = var.sds_host_name nqn = var.sds_host_nqn diff --git a/examples/ibm-sdsaas/variables.tf b/examples/ibm-sdsaas/variables.tf index ce8164efe0..b9583e3d2c 100644 --- a/examples/ibm-sdsaas/variables.tf +++ b/examples/ibm-sdsaas/variables.tf @@ -3,6 +3,12 @@ variable "ibmcloud_api_key" { type = string } +variable "sds_endpoint" { + description = "IBM SDS Endpoint" + type = string + default = "" +} + variable "sds_volume_hostnqnstring" { description = "The host nqn." type = string diff --git a/go.mod b/go.mod index ff07d9fa9a..15d7c5bd4b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/IBM-Cloud/terraform-provider-ibm -go 1.23.0 +go 1.22.5 toolchain go1.23.2 @@ -29,7 +29,7 @@ require ( github.com/IBM/ibm-hpcs-tke-sdk v0.0.0-20211109141421-a4b61b05f7d1 github.com/IBM/ibm-hpcs-uko-sdk v0.0.20-beta github.com/IBM/keyprotect-go-client v0.15.1 - github.com/IBM/logs-go-sdk v0.3.0 + github.com/IBM/logs-go-sdk v0.4.0 github.com/IBM/logs-router-go-sdk v1.0.5 github.com/IBM/mqcloud-go-sdk v0.2.0 github.com/IBM/networking-go-sdk v0.49.0 @@ -39,7 +39,6 @@ require ( github.com/IBM/sarama v1.41.2 github.com/IBM/scc-go-sdk/v5 v5.4.1 github.com/IBM/schematics-go-sdk v0.3.0 - github.com/IBM/sds-go-sdk v0.0.3 github.com/IBM/secrets-manager-go-sdk/v2 v2.0.7 github.com/IBM/vmware-go-sdk v0.1.2 github.com/IBM/vpc-beta-go-sdk v0.8.0 @@ -79,6 +78,7 @@ require ( require github.com/BurntSushi/toml v1.2.0 // indirect require ( + github.com/IBM/sds-go-sdk v0.0.4 // indirect github.com/Logicalis/asn1 v0.0.0-20190312173541-d60463189a56 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/PromonLogicalis/asn1 v0.0.0-20190312173541-d60463189a56 // indirect @@ -205,6 +205,7 @@ require ( go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.uber.org/atomic v1.9.0 // indirect go.uber.org/ratelimit v0.2.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/mod v0.21.0 // indirect diff --git a/go.sum b/go.sum index 180862c387..1d5b8049c6 100644 --- a/go.sum +++ b/go.sum @@ -148,8 +148,8 @@ github.com/IBM/ibm-hpcs-uko-sdk v0.0.20-beta/go.mod h1:MLVNHMYoKsvovJZ4v1gQCpIYt github.com/IBM/keyprotect-go-client v0.5.1/go.mod h1:5TwDM/4FRJq1ZOlwQL1xFahLWQ3TveR88VmL1u3njyI= github.com/IBM/keyprotect-go-client v0.15.1 h1:m4qzqF5zOumRxKZ8s7vtK7A/UV/D278L8xpRG+WgT0s= github.com/IBM/keyprotect-go-client v0.15.1/go.mod h1:asXtHwL/4uCHA221Vd/7SkXEi2pcRHDzPyyksc1DthE= -github.com/IBM/logs-go-sdk v0.3.0 h1:FHzTCCMyp9DvQGXgkppzcOPywC4ggt7x8xu0MR5h8xI= -github.com/IBM/logs-go-sdk v0.3.0/go.mod h1:yv/GCXC4/p+MZEeXl4xjZAOMvDAVRwu61WyHZFKFXQM= +github.com/IBM/logs-go-sdk v0.4.0 h1:CyUjm19EUtcJjf4mxsj6Rc7gkZDT8JEY5rLUIz8Eoag= +github.com/IBM/logs-go-sdk v0.4.0/go.mod h1:yv/GCXC4/p+MZEeXl4xjZAOMvDAVRwu61WyHZFKFXQM= github.com/IBM/logs-router-go-sdk v1.0.5 h1:r0kC1+HfmSeQCD6zQTUp4PDI/zp4Ueo1Zo19ipHuNlw= github.com/IBM/logs-router-go-sdk v1.0.5/go.mod h1:tCN2vFgu5xG0ob9iJcxi5M4bJ6mWmu3nhmRPnvlwev0= github.com/IBM/mqcloud-go-sdk v0.2.0 h1:QOWk8ZGk0QfIL0MOGTKzNdM3Qe0Hk+ifAFtNSFQo5HU= @@ -168,8 +168,8 @@ github.com/IBM/scc-go-sdk/v5 v5.4.1 h1:RXIuxOo9/hxkWyHCI69ae+KIJgSbXcAkJwTEl+fO3 github.com/IBM/scc-go-sdk/v5 v5.4.1/go.mod h1:2xQTDgNXG5QMEfQxBDKB067z+5ha6OgcaKCTcdGDAo8= github.com/IBM/schematics-go-sdk v0.3.0 h1:Vwxw85SONflakiBsNHAfViKLyp9zJiH5/hh6SewOP5Q= github.com/IBM/schematics-go-sdk v0.3.0/go.mod h1:Tw2OSAPdpC69AxcwoyqcYYaGTTW6YpERF9uNEU+BFRQ= -github.com/IBM/sds-go-sdk v0.0.3 h1:AlC2SOFdiD8hPHei7DIcwNLNq2ami3jDvb0MxZLpIE0= -github.com/IBM/sds-go-sdk v0.0.3/go.mod h1:mUak/6lrP0H7Pr5XBoZfosPe92cmV4emWMI4amRvAhQ= +github.com/IBM/sds-go-sdk v0.0.4 h1:zkkqDzc+TgFYU/BK4Oknv8cMBXJ08WKUu7yKCyzslvE= +github.com/IBM/sds-go-sdk v0.0.4/go.mod h1:HcqZfsgKMqfFxbU1RcRfF934ls+vQY97oXPGPSoIWPg= github.com/IBM/secrets-manager-go-sdk/v2 v2.0.7 h1:5lKt1rHuKaAaiZtbPfsF8dgiko/gGbVgreiut3zU128= github.com/IBM/secrets-manager-go-sdk/v2 v2.0.7/go.mod h1:RglK3v6CPe3T1myRtQCD6z+nBygXvNJwufAon0qcZok= github.com/IBM/vmware-go-sdk v0.1.2 h1:5lKWFyInWz9e2hwGsoFTEoLa1jYkD30SReN0fQ10w9M= @@ -370,7 +370,8 @@ github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8 github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= +github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= +github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4= github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -1270,7 +1271,8 @@ go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4x go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= -go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM= +go.mongodb.org/mongo-driver v1.16.1 h1:rIVLL3q0IHM39dvE+z2ulZLp9ENZKThVfuvN/IiN4l8= +go.mongodb.org/mongo-driver v1.16.1/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -1290,8 +1292,9 @@ go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVf go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= diff --git a/ibm/conns/config.go b/ibm/conns/config.go index e1cd2ee356..ef09b51336 100644 --- a/ibm/conns/config.go +++ b/ibm/conns/config.go @@ -3611,7 +3611,6 @@ func (c *Config) ClientSession() (interface{}, error) { if session.sdsaasClientErr == nil { // Construct the service options. sdsaasClientOptions := &sdsaasv1.SdsaasV1Options{ - URL: EnvFallBack([]string{"IBMCLOUD_SDS_ENDPOINT"}, ""), Authenticator: authenticator, } diff --git a/ibm/service/sdsaas/resource_ibm_sds_host.go b/ibm/service/sdsaas/resource_ibm_sds_host.go index 68766ff8d5..f834ece4a8 100644 --- a/ibm/service/sdsaas/resource_ibm_sds_host.go +++ b/ibm/service/sdsaas/resource_ibm_sds_host.go @@ -15,7 +15,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" "github.com/IBM/go-sdk-core/v5/core" @@ -31,6 +30,11 @@ func ResourceIBMSdsHost() *schema.Resource { Importer: &schema.ResourceImporter{}, Schema: map[string]*schema.Schema{ + "sds_endpoint": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The endpoint to use for operations", + }, "name": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -148,7 +152,8 @@ func ResourceIBMSdsHostValidator() *validate.ResourceValidator { } func resourceIBMSdsHostCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - sdsaasClient, err := meta.(conns.ClientSession).SdsaasV1() + endpoint := d.Get("sds_endpoint").(string) + sdsaasClient, err := getSDSConfigClient(meta, endpoint) if err != nil { tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_sds_host", "create", "initialize-client") log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) @@ -187,7 +192,8 @@ func resourceIBMSdsHostCreate(context context.Context, d *schema.ResourceData, m } func resourceIBMSdsHostRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - sdsaasClient, err := meta.(conns.ClientSession).SdsaasV1() + endpoint := d.Get("sds_endpoint").(string) + sdsaasClient, err := getSDSConfigClient(meta, endpoint) if err != nil { tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_sds_host", "read", "initialize-client") log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) @@ -244,7 +250,8 @@ func resourceIBMSdsHostRead(context context.Context, d *schema.ResourceData, met } func resourceIBMSdsHostUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - sdsaasClient, err := meta.(conns.ClientSession).SdsaasV1() + endpoint := d.Get("sds_endpoint").(string) + sdsaasClient, err := getSDSConfigClient(meta, endpoint) if err != nil { tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_sds_host", "update", "initialize-client") log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) @@ -282,7 +289,8 @@ func resourceIBMSdsHostUpdate(context context.Context, d *schema.ResourceData, m } func resourceIBMSdsHostDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - sdsaasClient, err := meta.(conns.ClientSession).SdsaasV1() + endpoint := d.Get("sds_endpoint").(string) + sdsaasClient, err := getSDSConfigClient(meta, endpoint) if err != nil { tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_sds_host", "delete", "initialize-client") log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) diff --git a/ibm/service/sdsaas/resource_ibm_sds_volume.go b/ibm/service/sdsaas/resource_ibm_sds_volume.go index 0db7a4cd33..571a3d66ff 100644 --- a/ibm/service/sdsaas/resource_ibm_sds_volume.go +++ b/ibm/service/sdsaas/resource_ibm_sds_volume.go @@ -31,6 +31,11 @@ func ResourceIBMSdsVolume() *schema.Resource { Importer: &schema.ResourceImporter{}, Schema: map[string]*schema.Schema{ + "sds_endpoint": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The endpoint to use for operations", + }, "hostnqnstring": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -110,6 +115,16 @@ func ResourceIBMSdsVolume() *schema.Resource { } } +func getSDSConfigClient(meta interface{}, endpoint string) (*sdsaasv1.SdsaasV1, error) { + sdsconfigClient, err := meta.(conns.ClientSession).SdsaasV1() + if err != nil { + return nil, err + } + url := conns.EnvFallBack([]string{"IBMCLOUD_SDS_ENDPOINT"}, endpoint) + sdsconfigClient.Service.Options.URL = url + return sdsconfigClient, nil +} + func ResourceIBMSdsVolumeValidator() *validate.ResourceValidator { validateSchema := make([]validate.ValidateSchema, 0) validateSchema = append(validateSchema, @@ -138,7 +153,8 @@ func ResourceIBMSdsVolumeValidator() *validate.ResourceValidator { } func resourceIBMSdsVolumeCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - sdsaasClient, err := meta.(conns.ClientSession).SdsaasV1() + endpoint := d.Get("sds_endpoint").(string) + sdsaasClient, err := getSDSConfigClient(meta, endpoint) if err != nil { tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_sds_volume", "create", "initialize-client") log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) @@ -168,7 +184,8 @@ func resourceIBMSdsVolumeCreate(context context.Context, d *schema.ResourceData, } func resourceIBMSdsVolumeRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - sdsaasClient, err := meta.(conns.ClientSession).SdsaasV1() + endpoint := d.Get("sds_endpoint").(string) + sdsaasClient, err := getSDSConfigClient(meta, endpoint) if err != nil { tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_sds_volume", "read", "initialize-client") log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) @@ -255,7 +272,8 @@ func resourceIBMSdsVolumeRead(context context.Context, d *schema.ResourceData, m } func resourceIBMSdsVolumeUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - sdsaasClient, err := meta.(conns.ClientSession).SdsaasV1() + endpoint := d.Get("sds_endpoint").(string) + sdsaasClient, err := getSDSConfigClient(meta, endpoint) if err != nil { tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_sds_volume", "update", "initialize-client") log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) @@ -298,7 +316,8 @@ func resourceIBMSdsVolumeUpdate(context context.Context, d *schema.ResourceData, } func resourceIBMSdsVolumeDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - sdsaasClient, err := meta.(conns.ClientSession).SdsaasV1() + endpoint := d.Get("sds_endpoint").(string) + sdsaasClient, err := getSDSConfigClient(meta, endpoint) if err != nil { tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_sds_volume", "delete", "initialize-client") log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage())