Skip to content

Commit

Permalink
feat(tem) : add ressource for validate tem domain
Browse files Browse the repository at this point in the history
  • Loading branch information
jremy42 committed Feb 27, 2024
1 parent 228ca67 commit 836ed77
Show file tree
Hide file tree
Showing 8 changed files with 2,385 additions and 3 deletions.
38 changes: 38 additions & 0 deletions docs/resources/tem_domain_validation.md
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.

7 changes: 4 additions & 3 deletions scaleway/helpers_tem.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import (
)

const (
defaultTemDomainTimeout = 5 * time.Minute
defaultTemDomainRetryInterval = 15 * time.Second
defaultTemDomainTimeout = 5 * time.Minute
defaultTemDomainValidationTimeout = 60 * time.Minute
defaultTemDomainRetryInterval = 15 * time.Second
)

// temAPIWithRegion returns a new Tem API and the region for a Create request
// teemAPIWithRegion returns a new Tem API and the region for a Create request
func temAPIWithRegion(d *schema.ResourceData, m interface{}) (*tem.API, scw.Region, error) {
meta := m.(*Meta)
api := tem.NewAPI(meta.scwClient)
Expand Down
1 change: 1 addition & 0 deletions scaleway/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ func Provider(config *ProviderConfig) plugin.ProviderFunc {
"scaleway_lb_route": resourceScalewayLbRoute(),
"scaleway_registry_namespace": resourceScalewayRegistryNamespace(),
"scaleway_tem_domain": resourceScalewayTemDomain(),
"scaleway_tem_domain_validation": resourceScalewayTemDomainValidation(),
"scaleway_container": resourceScalewayContainer(),
"scaleway_container_token": resourceScalewayContainerToken(),
"scaleway_rdb_acl": resourceScalewayRdbACL(),
Expand Down
129 changes: 129 additions & 0 deletions scaleway/resource_tem_domain_validation.go
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),
Delete: schema.DefaultTimeout(defaultTemDomainValidationTimeout),
Default: schema.DefaultTimeout(defaultTemDomainValidationTimeout),
},
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 {

Check warning on line 92 in scaleway/resource_tem_domain_validation.go

View workflow job for this annotation

GitHub Actions / lint

unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
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

Check failure on line 117 in scaleway/resource_tem_domain_validation.go

View workflow job for this annotation

GitHub Actions / lint

Multiplication of durations: `time.Duration(d.Get("timeout").(int)) * time.Second` (durationcheck)
err = retry.RetryContext(ctx, timeout, func() *retry.RetryError {

Check failure on line 118 in scaleway/resource_tem_domain_validation.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to err (ineffassign)
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"))

Check failure on line 124 in scaleway/resource_tem_domain_validation.go

View workflow job for this annotation

GitHub Actions / lint

fmt.Errorf can be replaced with errors.New (perfsprint)
}
return nil
})
return nil
}
92 changes: 92 additions & 0 deletions scaleway/resource_tem_domain_validation_test.go
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"),
),
},
},
})
}
39 changes: 39 additions & 0 deletions scaleway/testdata/tem-domain-validation-basic.cassette.yaml
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: ""
Loading

0 comments on commit 836ed77

Please sign in to comment.