-
Notifications
You must be signed in to change notification settings - Fork 121
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
--- | ||
subcategory: "Transactional Email" | ||
page_title: "Scaleway: scaleway_tem_domain" | ||
--- | ||
|
||
# Resource: scaleway_tem_domain_validation | ||
|
||
This Terraform resource manages the validation of domains for use with Scaleway's Transactional Email Management (TEM) service. It ensures that domains used for sending emails are verified and comply with Scaleway's requirements for email sending. | ||
For more information see [the documentation](https://developers.scaleway.com/en/products/transactional_email/api/). | ||
|
||
## Example Usage | ||
|
||
### Basic | ||
|
||
```terraform | ||
resource "scaleway_tem_domain_validation" "example" { | ||
domain_id = "your-domain-id" | ||
region = "fr-par" | ||
timeout = 300 | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
- `domain_id` - (Required) The ID of the domain name used when sending emails. This ID must correspond to a domain already registered with Scaleway's Transactional Email service. | ||
|
||
- `region` - (Defaults to [provider](../index.md#region) `region`). Specifies the [region](../guides/regions_and_zones.md#regions) where the domain is registered. If not specified, it defaults to the provider's region. | ||
|
||
- `timeout` - (Optional) The maximum wait time in seconds before returning an error if the domain validation does not complete. The default is 300 seconds. | ||
|
||
## Attributes Reference | ||
|
||
In addition to all arguments above, the following attributes are exported: | ||
|
||
- `validated` - Indicates if the domain has been verified for email sending. This is computed after the creation or update of the domain validation resource. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package scaleway | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"strings" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
tem "github.com/scaleway/scaleway-sdk-go/api/tem/v1alpha1" | ||
"github.com/scaleway/scaleway-sdk-go/scw" | ||
) | ||
|
||
func resourceScalewayTemDomainValidation() *schema.Resource { | ||
return &schema.Resource{ | ||
CreateContext: resourceScalewayTemDomainValidationCreate, | ||
ReadContext: resourceScalewayTemDomainValidationRead, | ||
DeleteContext: resourceScalewayTemDomainValidationDelete, | ||
Importer: &schema.ResourceImporter{ | ||
StateContext: schema.ImportStatePassthroughContext, | ||
}, | ||
Timeouts: &schema.ResourceTimeout{ | ||
Create: schema.DefaultTimeout(defaultTemDomainValidationTimeout), | ||
Check failure on line 25 in scaleway/resource_tem_domain_validation.go
|
||
Delete: schema.DefaultTimeout(defaultTemDomainValidationTimeout), | ||
Check failure on line 26 in scaleway/resource_tem_domain_validation.go
|
||
Default: schema.DefaultTimeout(defaultTemDomainValidationTimeout), | ||
Check failure on line 27 in scaleway/resource_tem_domain_validation.go
|
||
}, | ||
SchemaVersion: 0, | ||
Schema: map[string]*schema.Schema{ | ||
"domain_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
Description: "The id of domain name used when sending emails.", | ||
}, | ||
"region": regionSchema(), | ||
"timeout": { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
ForceNew: true, | ||
Default: 300, | ||
Description: "Maximum wait time in second before returning an error.", | ||
}, | ||
"validated": { | ||
Type: schema.TypeBool, | ||
Computed: true, | ||
Description: "Indicates if the domain is verified for email sending", | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceScalewayTemDomainValidationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
api, region, err := temAPIWithRegion(d, meta) | ||
if err != nil { | ||
return diag.FromErr(err) | ||
} | ||
d.SetId(d.Get("domain_id").(string)) | ||
diagnostics := validateDomain(ctx, d, err, api, region) | ||
if diagnostics != nil { | ||
return diagnostics | ||
} | ||
return resourceScalewayTemDomainValidationRead(ctx, d, meta) | ||
} | ||
|
||
func resourceScalewayTemDomainValidationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
api, region, err := temAPIWithRegion(d, meta) | ||
if err != nil { | ||
return diag.FromErr(err) | ||
} | ||
|
||
domainID := d.Id() | ||
getDomainRequest := &tem.GetDomainRequest{ | ||
Region: region, | ||
DomainID: extractAfterSlash(domainID), | ||
} | ||
domain, err := api.GetDomain(getDomainRequest, scw.WithContext(ctx)) | ||
if err != nil { | ||
if is404Error(err) { | ||
d.SetId("") | ||
return nil | ||
} | ||
return diag.FromErr(err) | ||
} | ||
|
||
_ = d.Set("validated", domain.Status == "checked") | ||
|
||
return nil | ||
} | ||
|
||
func resourceScalewayTemDomainValidationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
func extractAfterSlash(s string) string { | ||
lastIndex := strings.LastIndex(s, "/") | ||
if lastIndex == -1 { | ||
return s | ||
} | ||
return s[lastIndex+1:] | ||
} | ||
|
||
func validateDomain(ctx context.Context, d *schema.ResourceData, err error, api *tem.API, region scw.Region) diag.Diagnostics { | ||
domain, err := api.GetDomain(&tem.GetDomainRequest{ | ||
Region: region, | ||
DomainID: extractAfterSlash(d.Get("domain_id").(string)), | ||
}, scw.WithContext(ctx)) | ||
if err != nil { | ||
if is404Error(err) { | ||
d.SetId("") | ||
return nil | ||
} | ||
return diag.FromErr(err) | ||
} | ||
timeout := time.Duration(d.Get("timeout").(int)) * time.Second | ||
err = retry.RetryContext(ctx, timeout, func() *retry.RetryError { | ||
domainCheck, _ := api.CheckDomain(&tem.CheckDomainRequest{ | ||
Region: region, | ||
DomainID: domain.ID, | ||
}) | ||
if domainCheck == nil || domainCheck.Status == "pending" || domainCheck.Status == "unchecked" { | ||
return retry.RetryableError(fmt.Errorf("retry")) | ||
} | ||
return nil | ||
}) | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package scaleway | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
) | ||
|
||
func init() { | ||
resource.AddTestSweepers("scaleway_tem_domain_validation", &resource.Sweeper{ | ||
Name: "scaleway_tem_domain_validation", | ||
F: testSweepTemDomain, | ||
}) | ||
} | ||
|
||
func TestAccScalewayTemDomainValidation_NoValidation(t *testing.T) { | ||
tt := NewTestTools(t) | ||
defer tt.Cleanup() | ||
|
||
domainName := "terraform-rs.test.local" | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
ProviderFactories: tt.ProviderFactories, | ||
CheckDestroy: testAccCheckScalewayTemDomainDestroy(tt), | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: fmt.Sprintf(` | ||
resource scaleway_tem_domain cr01 { | ||
name = "%s" | ||
accept_tos = true | ||
} | ||
resource scaleway_tem_domain_validation valid { | ||
domain_id = scaleway_tem_domain.cr01.id | ||
region = scaleway_tem_domain.cr01.region | ||
timeout = 1 | ||
} | ||
`, domainName), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr("scaleway_tem_domain_validation.valid", "validated", "false"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccScalewayTemDomainValidation_Validation(t *testing.T) { | ||
tt := NewTestTools(t) | ||
defer tt.Cleanup() | ||
domainName := "scaleway-terraform.com" | ||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
ProviderFactories: tt.ProviderFactories, | ||
CheckDestroy: testAccCheckScalewayTemDomainDestroy(tt), | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: fmt.Sprintf(` | ||
resource scaleway_tem_domain cr01 { | ||
name = "%s" | ||
accept_tos = true | ||
} | ||
resource "scaleway_domain_record" "spf" { | ||
dns_zone = "%s" | ||
type = "TXT" | ||
data = "v=spf1 ${scaleway_tem_domain.cr01.spf_config} -all" | ||
} | ||
resource "scaleway_domain_record" "dkim" { | ||
dns_zone = "%s" | ||
name = "${scaleway_tem_domain.cr01.project_id}._domainkey" | ||
type = "TXT" | ||
data = scaleway_tem_domain.cr01.dkim_config | ||
} | ||
resource "scaleway_domain_record" "mx" { | ||
dns_zone = "%s" | ||
type = "MX" | ||
data = "." | ||
} | ||
resource scaleway_tem_domain_validation valid { | ||
domain_id = scaleway_tem_domain.cr01.id | ||
region = scaleway_tem_domain.cr01.region | ||
timeout = 3600 | ||
} | ||
`, domainName, domainName, domainName, domainName), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr("scaleway_tem_domain_validation.valid", "validated", "true"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
--- | ||
version: 1 | ||
interactions: | ||
- request: | ||
body: '{"project_id":"46fd79d8-1a35-4548-bfb8-03df51a0ebae","domain_name":"terraform-rs.test.local","accept_tos":true}' | ||
form: {} | ||
headers: | ||
Content-Type: | ||
- application/json | ||
User-Agent: | ||
- scaleway-sdk-go/v1.0.0-beta.7+dev (go1.21.5; darwin; amd64) terraform-provider/develop | ||
terraform/terraform-tests | ||
url: https://api.scaleway.com/transactional-email/v1alpha1/regions/fr-par/domains | ||
method: POST | ||
response: | ||
body: '{"details":[{"current":3,"quota":3,"resource":"TemDomains"}],"message":"quota(s) | ||
exceeded for this resource","type":"quotas_exceeded"}' | ||
headers: | ||
Content-Length: | ||
- "134" | ||
Content-Security-Policy: | ||
- default-src 'none'; frame-ancestors 'none' | ||
Content-Type: | ||
- application/json | ||
Date: | ||
- Fri, 23 Feb 2024 14:30:23 GMT | ||
Server: | ||
- Scaleway API Gateway (fr-par-1;edge01) | ||
Strict-Transport-Security: | ||
- max-age=63072000 | ||
X-Content-Type-Options: | ||
- nosniff | ||
X-Frame-Options: | ||
- DENY | ||
X-Request-Id: | ||
- 41712974-663b-4829-bf95-e485f9dcf3cf | ||
status: 403 Forbidden | ||
code: 403 | ||
duration: "" |