diff --git a/.tool-versions b/.tool-versions index 4933a41..968cdc9 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -golang 1.18 +golang 1.19.4 diff --git a/docs/index.md b/docs/index.md index d1bd7db..38ec592 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,4 +19,5 @@ description: |- - `api_key` (String) API Key for Porkbun - `base_url` (String) Override Porkbun Base URL +- `max_retries` (Number) Should only be changed if needing to work around Porkbun API rate limits - `secret_key` (String) Secret Key for Porkbun diff --git a/go.mod b/go.mod index fc31541..48e5cc2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/cullenmcdermott/terraform-provider-porkbun -go 1.18 +go 1.19 require ( github.com/hashicorp/terraform-plugin-docs v0.13.0 @@ -8,8 +8,9 @@ require ( github.com/hashicorp/terraform-plugin-go v0.14.0 github.com/hashicorp/terraform-plugin-log v0.7.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.21.0 - github.com/nrdcg/porkbun v0.1.1 - github.com/stretchr/testify v1.7.2 + github.com/nrdcg/porkbun v0.2.0 + github.com/stretchr/testify v1.8.1 + golang.org/x/exp v0.0.0-20221230162634-c8adb6e14cba ) require ( @@ -64,7 +65,7 @@ require ( github.com/zclconf/go-cty v1.10.0 // indirect golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect - golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b // indirect + golang.org/x/sys v0.1.0 // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/appengine v1.6.6 // indirect google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d // indirect diff --git a/go.sum b/go.sum index fd30029..4c2c86d 100644 --- a/go.sum +++ b/go.sum @@ -201,8 +201,8 @@ github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nrdcg/porkbun v0.1.1 h1:gxVzQYfFUGXhnBax/aVugoE3OIBAdHgrJgyMPyY5Sjo= -github.com/nrdcg/porkbun v0.1.1/go.mod h1:JWl/WKnguWos4mjfp4YizvvToigk9qpQwrodOk+CPoA= +github.com/nrdcg/porkbun v0.2.0 h1:ghaqPtIKcffba99epWFkK3VWf6TKJT9WMXMgaTqv95Y= +github.com/nrdcg/porkbun v0.2.0/go.mod h1:i0uLMn9ItFsLsSQIAeEu1wQ9/+6EvX1eQw15hulMMRw= github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= @@ -230,14 +230,19 @@ github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= @@ -264,6 +269,8 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20221230162634-c8adb6e14cba h1:Qa0t0rPXHxjZBt3IJdkf6gku8KvMpBwiCmhAL5tYNEI= +golang.org/x/exp v0.0.0-20221230162634-c8adb6e14cba/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -311,8 +318,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8= -golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= diff --git a/internal/provider/provider.go b/internal/provider/provider.go index e81affe..ae4929d 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -5,6 +5,7 @@ import ( "fmt" "net/url" "os" + "strconv" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/provider" @@ -20,13 +21,15 @@ type porkbunProvider struct { client *porkbun.Client configured bool version string + MaxRetries int } // providerData can be used to store data from the Terraform configuration. type providerData struct { - ApiKey types.String `tfsdk:"api_key"` - SecretKey types.String `tfsdk:"secret_key"` - BaseUrl types.String `tfsdk:"base_url"` + ApiKey types.String `tfsdk:"api_key"` + SecretKey types.String `tfsdk:"secret_key"` + BaseUrl types.String `tfsdk:"base_url"` + MaxRetries types.Int64 `tfsdk:"max_retries"` } func (p *porkbunProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { @@ -94,6 +97,23 @@ func (p *porkbunProvider) Configure(ctx context.Context, req provider.ConfigureR c.BaseURL, _ = url.Parse(baseUrl) } + if data.MaxRetries.Null { + if mr, ok := os.LookupEnv("PORKBUN_MAX_RETRIES"); ok { + mri, err := strconv.Atoi(mr) + if err != nil { + resp.Diagnostics.AddError( + "failed converting max retries", + err.Error(), + ) + } + p.MaxRetries = mri + } else { + p.MaxRetries = 10 + } + } else { + p.MaxRetries = int(data.MaxRetries.Value) + } + p.client = c p.configured = true } @@ -129,6 +149,12 @@ func (p *porkbunProvider) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Dia Optional: true, Type: types.StringType, }, + "max_retries": { + MarkdownDescription: "Should only be changed if needing to work around Porkbun API rate limits", + Required: false, + Optional: true, + Type: types.Int64Type, + }, }, }, nil } diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index a1768c5..e0eb378 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -1,10 +1,24 @@ package provider import ( + "net/url" + + "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-plugin-framework/providerserver" "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/nrdcg/porkbun" ) +func newPorkbunProvider(testUrl string) provider.Provider { + client := porkbun.New("sk1_foobarbaz", "pk1_foobarbaz") + client.BaseURL, _ = url.Parse(testUrl) + return &porkbunProvider{ + client: client, + configured: true, + version: "test", + } +} + func protoV6ProviderFactories(url string) map[string]func() (tfprotov6.ProviderServer, error) { return map[string]func() (tfprotov6.ProviderServer, error){ "porkbun": providerserver.NewProtocol6WithError(newPorkbunProvider(url)), diff --git a/internal/provider/resource_dns_record.go b/internal/provider/resource_dns_record.go index 7d4f523..e0b2c92 100644 --- a/internal/provider/resource_dns_record.go +++ b/internal/provider/resource_dns_record.go @@ -3,9 +3,6 @@ package provider import ( "context" "fmt" - "strconv" - "strings" - "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/provider" @@ -14,6 +11,10 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/nrdcg/porkbun" + "golang.org/x/exp/slices" + "strconv" + "strings" + "time" ) // Ensure provider defined types fully satisfy framework interfaces @@ -21,6 +22,14 @@ var _ provider.ResourceType = porkbunDnsRecordResourceType{} var _ resource.Resource = porkbunDnsRecordResource{} var _ resource.ResourceWithImportState = porkbunDnsRecordResource{} +// The API returns a string of "SUCCESS" or "ERROR" except for when we're rate limited +// We get a 503 and the go library expects a string so we need to treat this as a string for now +var retryableCodes = []int{503} + +var ( + sleep = 10 +) + type porkbunDnsRecordResourceType struct{} func (t porkbunDnsRecordResourceType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) { @@ -102,6 +111,7 @@ type porkbunDnsRecordResource struct { func (r porkbunDnsRecordResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { var data porkbunDnsRecordResourceData + attempts := r.provider.MaxRetries diags := req.Config.Get(ctx, &data) resp.Diagnostics.Append(diags...) @@ -119,7 +129,7 @@ func (r porkbunDnsRecordResource) Create(ctx context.Context, req resource.Creat Notes: data.Notes.Value, // Not documented } - id, err := r.provider.client.CreateRecord(ctx, data.Domain.Value, record) + id, err := retry(attempts, sleep, func() (int, error) { return r.provider.client.CreateRecord(ctx, data.Domain.Value, record) }) if err != nil { resp.Diagnostics.AddError( "Error creating DNS Record", @@ -135,6 +145,7 @@ func (r porkbunDnsRecordResource) Create(ctx context.Context, req resource.Creat func (r porkbunDnsRecordResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { var data porkbunDnsRecordResourceData + attempts := r.provider.MaxRetries diags := req.State.Get(ctx, &data) resp.Diagnostics.Append(diags...) @@ -143,15 +154,20 @@ func (r porkbunDnsRecordResource) Read(ctx context.Context, req resource.ReadReq return } - records, err := r.provider.client.RetrieveRecords(ctx, data.Domain.Value) + getRecordsResult, err := retry(attempts, sleep, func() ([]porkbun.Record, error) { return r.getRecords(ctx, data.Domain.Value) }) + if err != nil { resp.Diagnostics.AddError( - fmt.Sprintf("Could not retrieve records for %s", data.Domain.Value), - fmt.Sprintf("Error: %s", err), + fmt.Sprintf( + `Could not retrieve records for %s.`, + data.Domain.Value, + ), + fmt.Sprintf("Error: %s", err.Error()), ) } - tflog.Info(ctx, fmt.Sprintf("Found records: %s", records)) - for _, record := range records { + + tflog.Info(ctx, fmt.Sprintf("Found records: %s", getRecordsResult)) + for _, record := range getRecordsResult { tflog.Info(ctx, fmt.Sprintf("This record is: %s", record.ID)) if record.ID == data.Id.Value { data.Content.Value = record.Content @@ -177,6 +193,7 @@ func (r porkbunDnsRecordResource) Read(ctx context.Context, req resource.ReadReq func (r porkbunDnsRecordResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { var data porkbunDnsRecordResourceData var recordId string + attempts := r.provider.MaxRetries diags := req.Plan.Get(ctx, &data) req.State.GetAttribute(ctx, path.Root("id"), &recordId) @@ -203,7 +220,7 @@ func (r porkbunDnsRecordResource) Update(ctx context.Context, req resource.Updat ) } - err = r.provider.client.EditRecord(ctx, data.Domain.Value, intId, record) + err = retrySingleReturn(attempts, sleep, func() error { return r.provider.client.EditRecord(ctx, data.Domain.Value, intId, record) }) if err != nil { resp.Diagnostics.AddError( "Error updating the record", @@ -222,8 +239,7 @@ func (r porkbunDnsRecordResource) Update(ctx context.Context, req resource.Updat func (r porkbunDnsRecordResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { var state porkbunDnsRecordResourceData - - //var data exampleResourceData + attempts := r.provider.MaxRetries diags := req.State.Get(ctx, &state) resp.Diagnostics.Append(diags...) @@ -240,7 +256,7 @@ func (r porkbunDnsRecordResource) Delete(ctx context.Context, req resource.Delet ) } - err = r.provider.client.DeleteRecord(ctx, state.Domain.Value, intId) + err = retrySingleReturn(attempts, sleep, func() error { return r.provider.client.DeleteRecord(ctx, state.Domain.Value, intId) }) if err != nil { resp.Diagnostics.AddError( "Error deleting record", @@ -256,3 +272,62 @@ func (r porkbunDnsRecordResource) Delete(ctx context.Context, req resource.Delet func (r porkbunDnsRecordResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } + +// Originally from https://stackoverflow.com/questions/67069723/keep-retrying-a-function-in-golang +func retry[T any](attempts int, sleep int, f func() (T, error)) (result T, err error) { + for i := 0; i < attempts; i++ { + if i > 0 { + time.Sleep(time.Duration(sleep) * time.Second) + sleep *= 2 + } + result, err = f() + if err == nil { + return result, nil + } + status, ok := err.(porkbun.Status) + if ok { + if status.Status != "SUCCESS" { + return result, fmt.Errorf("cannot be retried: %s", status.Error()) + } + } + servererr, ok := err.(porkbun.ServerError) + if ok { + if !isRetryable(servererr.StatusCode) { + return result, fmt.Errorf("received error is not retryable: %s", servererr.Error()) + } + } + } + return result, fmt.Errorf("after %d attempts, last error: %s", attempts, err) +} + +func retrySingleReturn(attempts int, sleep int, f func() error) (err error) { + for i := 0; i < attempts; i++ { + if i > 0 { + time.Sleep(time.Duration(sleep) * time.Second) + sleep *= 2 + } + err = f() + if err == nil { + return nil + } + err, ok := err.(porkbun.ServerError) + if ok { + if !isRetryable(err.StatusCode) { + return fmt.Errorf("received error is not retryable: %s", err) + } + } + } + return fmt.Errorf("after %d attempts, last error: %s", attempts, err) +} + +func (r porkbunDnsRecordResource) getRecords(ctx context.Context, domain string) ([]porkbun.Record, error) { + records, err := r.provider.client.RetrieveRecords(ctx, domain) + if err != nil { + return []porkbun.Record{}, err + } + return records, nil +} + +func isRetryable(status int) bool { + return slices.Contains(retryableCodes, status) +} diff --git a/internal/provider/resource_dns_record_test.go b/internal/provider/resource_dns_record_test.go index c53b0af..c99ad81 100644 --- a/internal/provider/resource_dns_record_test.go +++ b/internal/provider/resource_dns_record_test.go @@ -8,7 +8,6 @@ import ( "os" "testing" - "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/nrdcg/porkbun" "github.com/stretchr/testify/require" @@ -41,27 +40,12 @@ type retrieveResponse struct { Records []porkbun.Record } -func getProvider(client *porkbun.Client) porkbunProvider { - return porkbunProvider{ - client: client, - } -} - -func newPorkbunProvider(testUrl string) provider.Provider { - client := porkbun.New("sk1_foobarbaz", "pk1_foobarbaz") - client.BaseURL, _ = url.Parse(testUrl) - return &porkbunProvider{ - client: client, - configured: true, - version: "test", - } -} - -func TestPorkbunDnsRecordSuccess(t *testing.T) { +func Test_CreateRecordSuccess(t *testing.T) { testUrl, expectRequest, _ := MockPorkbun(t) os.Setenv("PORKBUN_API_KEY", "pk1_foobarbaz") os.Setenv("PORKBUN_SECRET_KEY", "sk1_foobarbaz") os.Setenv("PORKBUN_BASE_URL", testUrl) + os.Setenv("PORKBUN_MAX_RETRIES", "1") tests := []struct { name string @@ -109,8 +93,9 @@ func TestPorkbunDnsRecordSuccess(t *testing.T) { }, }, } - for _, test := range tests { + + t.Log("Running test ", test.name) r := require.New(t) expectRequest(func(w http.ResponseWriter, req *http.Request) { r.Equal(http.MethodPost, req.Method) @@ -140,7 +125,6 @@ func TestPorkbunDnsRecordSuccess(t *testing.T) { Status: "SUCCESS", })) }) - // Run the terraform twice to ensure its idempotent resource.UnitTest(t, resource.TestCase{ IsUnitTest: true, @@ -149,22 +133,78 @@ func TestPorkbunDnsRecordSuccess(t *testing.T) { ProtoV6ProviderFactories: protoV6ProviderFactories(testUrl), Config: test.testResource, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("porkbun_dns_record.test", "content", "0.0.0.1"), + resource.TestCheckResourceAttr("porkbun_dns_record.test", "content", test.record.Content), ), }, { ProtoV6ProviderFactories: protoV6ProviderFactories(testUrl), Config: test.testResource, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("porkbun_dns_record.test", "content", "0.0.0.1"), + resource.TestCheckResourceAttr("porkbun_dns_record.test", "content", test.record.Content), ), }, }, }) } - } +//func Test_CreateRecordFailure(t *testing.T) { +// testUrl, expectRequest, _ := MockPorkbun(t) +// os.Setenv("PORKBUN_API_KEY", "pk1_foobarbaz") +// os.Setenv("PORKBUN_SECRET_KEY", "sk1_foobarbaz") +// os.Setenv("PORKBUN_BASE_URL", testUrl) +// +// tests := []struct { +// name string +// testResource string +// record porkbun.Record +// }{ +// { +// name: "withSubdomain", +// testResource: ` +// resource "porkbun_dns_record" "test" { +// name = "test" +// domain = "foobar.dev" +// content = "0.0.0.1" +// type = "A" +// } +// `, +// record: porkbun.Record{}, +// }, +// } +// for _, test := range tests { +// r := require.New(t) +// expectRequest(func(w http.ResponseWriter, req *http.Request) { +// r.Equal(http.MethodPost, req.Method) +// r.Equal("/dns/delete/foobar.dev/0", req.URL.Path) +// r.Error(json.NewEncoder(w).Encode(&createResponse{ +// Status: "FAILURE", +// })) +// }) +// expectRequest(func(w http.ResponseWriter, req *http.Request) { +// r.Equal(http.MethodPost, req.Method) +// r.Equal("/dns/delete/foobar.dev/0", req.URL.Path) +// r.Error(json.NewEncoder(w).Encode(&createResponse{ +// Status: "FAILURE", +// })) +// }) +// // Run the terraform twice to ensure its idempotent +// resource.UnitTest(t, resource.TestCase{ +// IsUnitTest: true, +// Steps: []resource.TestStep{ +// { +// ProtoV6ProviderFactories: protoV6ProviderFactories(testUrl), +// Config: test.testResource, +// Check: resource.ComposeTestCheckFunc( +// resource.TestCheckResourceAttr("porkbun_dns_record.test", "content", "0.0.0.1"), +// ), +// }, +// }, +// }) +// } +// +//} + func MockPorkbun(t *testing.T) (string, func(http.HandlerFunc), func()) { var ( receivedCalls int