Skip to content

Commit 245c94a

Browse files
authored
fix(serverless): retry domain creation instead of resolving (#1932)
1 parent cc82175 commit 245c94a

File tree

8 files changed

+4906
-738
lines changed

8 files changed

+4906
-738
lines changed

scaleway/helpers_container.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package scaleway
22

33
import (
44
"context"
5+
"errors"
6+
"strings"
57
"time"
68

79
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -183,7 +185,33 @@ func expandContainerSecrets(secretsRawMap interface{}) []*container.Secret {
183185
return secrets
184186
}
185187

186-
func isContainerDomainResolved(ctx context.Context, ctnr *container.Container, hostname string, timeout time.Duration) bool {
187-
// Add a trailing dot to domain_name to follow cname format
188-
return cnameResolver(ctx, timeout, hostname, ctnr.DomainName+".")
188+
func isContainerDNSResolveError(err error) bool {
189+
responseError := &scw.ResponseError{}
190+
191+
if !errors.As(err, &responseError) {
192+
return false
193+
}
194+
195+
if strings.HasPrefix(responseError.Message, "could not validate domain") {
196+
return true
197+
}
198+
199+
return false
200+
}
201+
202+
func retryCreateContainerDomain(ctx context.Context, containerAPI *container.API, req *container.CreateDomainRequest, timeout time.Duration) (*container.Domain, error) {
203+
timeoutChannel := time.After(timeout)
204+
205+
for {
206+
select {
207+
case <-time.After(defaultContainerRetryInterval):
208+
domain, err := containerAPI.CreateDomain(req, scw.WithContext(ctx))
209+
if err != nil && isContainerDNSResolveError(err) {
210+
continue
211+
}
212+
return domain, err
213+
case <-timeoutChannel:
214+
return containerAPI.CreateDomain(req, scw.WithContext(ctx))
215+
}
216+
}
189217
}

scaleway/helpers_domain.go

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -274,55 +274,6 @@ func waitForDNSZone(ctx context.Context, domainAPI *domain.API, dnsZone string,
274274
}, scw.WithContext(ctx))
275275
}
276276

277-
func newDNSResolver() *net.Resolver {
278-
return &net.Resolver{
279-
PreferGo: true,
280-
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
281-
d := net.Dialer{
282-
Timeout: time.Millisecond * time.Duration(500),
283-
}
284-
conn, err := d.DialContext(ctx, network, "ns0.dom.scw.cloud:53")
285-
if err != nil {
286-
conn, err = d.DialContext(ctx, network, "ns1.dom.scw.cloud:53")
287-
}
288-
return conn, err
289-
},
290-
}
291-
}
292-
293-
var (
294-
dnsResolverTickDelay = time.Millisecond * 500
295-
disableDNSResolver bool
296-
)
297-
298-
func cnameResolver(ctx context.Context, timeout time.Duration, hostname, expectedCNAME string) bool {
299-
if disableDNSResolver {
300-
return true
301-
}
302-
ticker := time.Tick(dnsResolverTickDelay)
303-
ctx, cancel := context.WithTimeout(ctx, timeout)
304-
defer cancel()
305-
306-
r := newDNSResolver()
307-
308-
for range ticker {
309-
cname, err := r.LookupCNAME(ctx, hostname)
310-
if err != nil {
311-
select {
312-
case <-ctx.Done():
313-
return false
314-
default:
315-
continue
316-
}
317-
}
318-
if cname == expectedCNAME {
319-
return true
320-
}
321-
}
322-
323-
return false
324-
}
325-
326277
func findDefaultReverse(address string) string {
327278
parts := strings.Split(address, ".")
328279
for i, j := 0, len(parts)-1; i < j; i, j = i+1, j-1 {

scaleway/helpers_function.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package scaleway
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"net/http"
78
"net/http/httputil"
89
"os"
10+
"strings"
911
"time"
1012

1113
"github.com/hashicorp/terraform-plugin-log/tflog"
@@ -199,7 +201,33 @@ func expandFunctionsSecrets(secretsRawMap interface{}) []*function.Secret {
199201
return secrets
200202
}
201203

202-
func isFunctionDomainResolved(ctx context.Context, fc *function.Function, hostname string, timeout time.Duration) bool {
203-
// Add a trailing dot to domain_name to follow cname format
204-
return cnameResolver(ctx, timeout, hostname, fc.DomainName+".")
204+
func isFunctionDNSResolveError(err error) bool {
205+
responseError := &scw.ResponseError{}
206+
207+
if !errors.As(err, &responseError) {
208+
return false
209+
}
210+
211+
if strings.HasPrefix(responseError.Message, "could not validate domain") {
212+
return true
213+
}
214+
215+
return false
216+
}
217+
218+
func retryCreateFunctionDomain(ctx context.Context, functionAPI *function.API, req *function.CreateDomainRequest, timeout time.Duration) (*function.Domain, error) {
219+
timeoutChannel := time.After(timeout)
220+
221+
for {
222+
select {
223+
case <-time.After(defaultFunctionRetryInterval):
224+
domain, err := functionAPI.CreateDomain(req, scw.WithContext(ctx))
225+
if err != nil && isFunctionDNSResolveError(err) {
226+
continue
227+
}
228+
return domain, err
229+
case <-timeoutChannel:
230+
return functionAPI.CreateDomain(req, scw.WithContext(ctx))
231+
}
232+
}
205233
}

scaleway/provider_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,6 @@ func NewTestTools(t *testing.T) *TestTools {
572572
require.NoError(t, err)
573573

574574
if !*UpdateCassettes {
575-
disableDNSResolver = true
576575
tmp := 0 * time.Second
577576
DefaultWaitRetryInterval = &tmp
578577
}

scaleway/resource_container_domain.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package scaleway
22

33
import (
44
"context"
5-
"fmt"
65

76
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
87
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -61,20 +60,18 @@ func resourceScalewayContainerDomainCreate(ctx context.Context, d *schema.Resour
6160
hostname := d.Get("hostname").(string)
6261
containerID := expandID(d.Get("container_id"))
6362

64-
ctnr, err := waitForContainer(ctx, api, containerID, region, d.Timeout(schema.TimeoutCreate))
63+
_, err = waitForContainer(ctx, api, containerID, region, d.Timeout(schema.TimeoutCreate))
6564
if err != nil {
6665
return diag.FromErr(err)
6766
}
6867

69-
if !isContainerDomainResolved(ctx, ctnr, hostname, d.Timeout(schema.TimeoutCreate)) {
70-
return diag.FromErr(fmt.Errorf("your reverse must resolve. Ensure the command 'dig +short %s' matches your container domain", hostname))
71-
}
72-
73-
domain, err := api.CreateDomain(&container.CreateDomainRequest{
68+
req := &container.CreateDomainRequest{
7469
Region: region,
7570
Hostname: hostname,
7671
ContainerID: containerID,
77-
})
72+
}
73+
74+
domain, err := retryCreateContainerDomain(ctx, api, req, d.Timeout(schema.TimeoutCreate))
7875
if err != nil {
7976
return diag.FromErr(err)
8077
}

scaleway/resource_function_domain.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package scaleway
22

33
import (
44
"context"
5-
"fmt"
65

76
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
87
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -59,24 +58,20 @@ func resourceScalewayFunctionDomainCreate(ctx context.Context, d *schema.Resourc
5958
}
6059

6160
functionID := expandRegionalID(d.Get("function_id").(string)).ID
62-
fc, err := waitForFunction(ctx, api, region, functionID, d.Timeout(schema.TimeoutCreate))
61+
_, err = waitForFunction(ctx, api, region, functionID, d.Timeout(schema.TimeoutCreate))
6362
if err != nil {
6463
return diag.FromErr(err)
6564
}
6665

6766
hostname := d.Get("hostname").(string)
6867

69-
if !isFunctionDomainResolved(ctx, fc, hostname, d.Timeout(schema.TimeoutCreate)) {
70-
return diag.FromErr(fmt.Errorf("your reverse must resolve. Ensure the command 'dig +short %s' matches your function domain", hostname))
71-
}
72-
7368
req := &function.CreateDomainRequest{
7469
Region: region,
7570
FunctionID: functionID,
7671
Hostname: hostname,
7772
}
7873

79-
domain, err := api.CreateDomain(req, scw.WithContext(ctx))
74+
domain, err := retryCreateFunctionDomain(ctx, api, req, d.Timeout(schema.TimeoutCreate))
8075
if err != nil {
8176
return diag.FromErr(err)
8277
}

0 commit comments

Comments
 (0)