1
0
mirror of https://github.com/go-acme/lego.git synced 2024-12-25 11:02:56 +02:00

Add DNS provider for Scaleway (#1047)

This commit is contained in:
Van Hau TRAN 2020-01-23 15:51:47 +01:00 committed by Ludovic Fernandez
parent 59ea57daf6
commit ee33cff002
9 changed files with 797 additions and 5 deletions

View File

@ -56,6 +56,6 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
| [Manual](https://go-acme.github.io/lego/dns/manual/) | [MyDNS.jp](https://go-acme.github.io/lego/dns/mydnsjp/) | [Name.com](https://go-acme.github.io/lego/dns/namedotcom/) | [Namecheap](https://go-acme.github.io/lego/dns/namecheap/) |
| [Namesilo](https://go-acme.github.io/lego/dns/namesilo/) | [Netcup](https://go-acme.github.io/lego/dns/netcup/) | [NIFCloud](https://go-acme.github.io/lego/dns/nifcloud/) | [NS1](https://go-acme.github.io/lego/dns/ns1/) |
| [Open Telekom Cloud](https://go-acme.github.io/lego/dns/otc/) | [Oracle Cloud](https://go-acme.github.io/lego/dns/oraclecloud/) | [OVH](https://go-acme.github.io/lego/dns/ovh/) | [PowerDNS](https://go-acme.github.io/lego/dns/pdns/) |
| [Rackspace](https://go-acme.github.io/lego/dns/rackspace/) | [RFC2136](https://go-acme.github.io/lego/dns/rfc2136/) | [Sakura Cloud](https://go-acme.github.io/lego/dns/sakuracloud/) | [Selectel](https://go-acme.github.io/lego/dns/selectel/) |
| [Stackpath](https://go-acme.github.io/lego/dns/stackpath/) | [TransIP](https://go-acme.github.io/lego/dns/transip/) | [VegaDNS](https://go-acme.github.io/lego/dns/vegadns/) | [Vscale](https://go-acme.github.io/lego/dns/vscale/) |
| [Versio](https://go-acme.github.io/lego/dns/versio/) | [Vultr](https://go-acme.github.io/lego/dns/vultr/) | [Zone.ee](https://go-acme.github.io/lego/dns/zoneee/) | |
| [Rackspace](https://go-acme.github.io/lego/dns/rackspace/) | [RFC2136](https://go-acme.github.io/lego/dns/rfc2136/) | [Sakura Cloud](https://go-acme.github.io/lego/dns/sakuracloud/) | [Scaleway](https://go-acme.github.io/lego/dns/scaleway/) |
| [Selectel](https://go-acme.github.io/lego/dns/selectel/) | [Stackpath](https://go-acme.github.io/lego/dns/stackpath/) | [TransIP](https://go-acme.github.io/lego/dns/transip/) | [VegaDNS](https://go-acme.github.io/lego/dns/vegadns/) |
| [Vscale](https://go-acme.github.io/lego/dns/vscale/) | [Versio](https://go-acme.github.io/lego/dns/versio/) | [Vultr](https://go-acme.github.io/lego/dns/vultr/) | [Zone.ee](https://go-acme.github.io/lego/dns/zoneee/) |

View File

@ -68,6 +68,7 @@ func allDNSCodes() string {
"rfc2136",
"route53",
"sakuracloud",
"scaleway",
"selectel",
"stackpath",
"transip",
@ -1237,6 +1238,28 @@ func displayDNSHelp(name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/sakuracloud`)
case "scaleway":
// generated from: providers/dns/scaleway/scaleway.toml
ew.writeln(`Configuration for Scaleway.`)
ew.writeln(`Code: 'scaleway'`)
ew.writeln(`Since: 'v3.4.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "SCALEWAY_API_TOKEN": API token`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "SCALEWAY_API_VERSION": API version`)
ew.writeln(` - "SCALEWAY_BASE_URL": API endpoint URL`)
ew.writeln(` - "SCALEWAY_HTTP_TIMEOUT": API request timeout`)
ew.writeln(` - "SCALEWAY_POLLING_INTERVAL": Time between DNS propagation check`)
ew.writeln(` - "SCALEWAY_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`)
ew.writeln(` - "SCALEWAY_TTL": The TTL of the TXT record used for the DNS challenge`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/scaleway`)
case "selectel":
// generated from: providers/dns/selectel/selectel.toml
ew.writeln(`Configuration for Selectel.`)

View File

@ -0,0 +1,64 @@
---
title: "Scaleway"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: scaleway
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/scaleway/scaleway.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Since: v3.4.0
Configuration for [Scaleway](https://developers.scaleway.com/).
<!--more-->
- Code: `scaleway`
Here is an example bash command using the Scaleway provider:
```bash
SCALEWAY_API_TOKEN=xxxxxxx-xxxxx-xxxx-xxx-xxxxxx \
lego --dns scaleway.com --domains my.domain.com --email my@email.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `SCALEWAY_API_TOKEN` | API token |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here](/lego/dns/#configuration-and-credentials).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `SCALEWAY_API_VERSION` | API version |
| `SCALEWAY_BASE_URL` | API endpoint URL |
| `SCALEWAY_HTTP_TIMEOUT` | API request timeout |
| `SCALEWAY_POLLING_INTERVAL` | Time between DNS propagation check |
| `SCALEWAY_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation |
| `SCALEWAY_TTL` | The TTL of the TXT record used for the DNS challenge |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here](/lego/dns/#configuration-and-credentials).
## More information
- [API documentation](https://developers.scaleway.com/en/products/domain/api/)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/scaleway/scaleway.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

View File

@ -59,6 +59,7 @@ import (
"github.com/go-acme/lego/v3/providers/dns/rfc2136"
"github.com/go-acme/lego/v3/providers/dns/route53"
"github.com/go-acme/lego/v3/providers/dns/sakuracloud"
"github.com/go-acme/lego/v3/providers/dns/scaleway"
"github.com/go-acme/lego/v3/providers/dns/selectel"
"github.com/go-acme/lego/v3/providers/dns/stackpath"
"github.com/go-acme/lego/v3/providers/dns/transip"
@ -182,10 +183,12 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return rfc2136.NewDNSProvider()
case "sakuracloud":
return sakuracloud.NewDNSProvider()
case "stackpath":
return stackpath.NewDNSProvider()
case "scaleway":
return scaleway.NewDNSProvider()
case "selectel":
return selectel.NewDNSProvider()
case "stackpath":
return stackpath.NewDNSProvider()
case "transip":
return transip.NewDNSProvider()
case "vegadns":

View File

@ -0,0 +1,228 @@
package internal
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
const (
defaultEndpoint = "https://api.scaleway.com/domain/v2alpha2"
uriUpdateRecords = "/dns-zones/%s/records"
operationSet = "set"
operationDelete = "delete"
operationAdd = "add"
)
// APIError represents an error response from the API.
type APIError struct {
Message string `json:"message"`
}
func (a APIError) Error() string {
return a.Message
}
// Record represents a DNS record
type Record struct {
Data string `json:"data,omitempty"`
Name string `json:"name,omitempty"`
Priority uint32 `json:"priority,omitempty"`
TTL uint32 `json:"ttl,omitempty"`
Type string `json:"type,omitempty"`
Comment string `json:"comment,omitempty"`
}
// RecordChangeAdd represents a list of add operations.
type RecordChangeAdd struct {
Records []*Record `json:"records,omitempty"`
}
// RecordChangeSet represents a list of set operations.
type RecordChangeSet struct {
Data string `json:"data,omitempty"`
Name string `json:"name,omitempty"`
TTL uint32 `json:"ttl,omitempty"`
Type string `json:"type,omitempty"`
Records []*Record `json:"records,omitempty"`
}
// RecordChangeDelete represents a list of delete operations.
type RecordChangeDelete struct {
Data string `json:"data,omitempty"`
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
}
// UpdateDNSZoneRecordsRequest represents a request to update DNS records on the API.
type UpdateDNSZoneRecordsRequest struct {
DNSZone string `json:"dns_zone,omitempty"`
Changes []interface{} `json:"changes,omitempty"`
ReturnAllRecords bool `json:"return_all_records,omitempty"`
}
// ClientOpts represents options to init client.
type ClientOpts struct {
BaseURL string
Token string
}
// Client represents DNS client.
type Client struct {
baseURL string
token string
httpClient *http.Client
}
// NewClient returns a client instance.
func NewClient(opts ClientOpts, httpClient *http.Client) *Client {
baseURL := defaultEndpoint
if opts.BaseURL != "" {
baseURL = opts.BaseURL
}
if httpClient == nil {
httpClient = &http.Client{}
}
return &Client{
token: opts.Token,
baseURL: baseURL,
httpClient: httpClient,
}
}
// AddRecord adds Record for given zone.
func (c *Client) AddRecord(zone string, record Record) error {
changes := map[string]RecordChangeAdd{
operationAdd: {
Records: []*Record{&record},
},
}
request := UpdateDNSZoneRecordsRequest{
DNSZone: zone,
Changes: []interface{}{changes},
ReturnAllRecords: false,
}
uri := fmt.Sprintf(uriUpdateRecords, zone)
req, err := c.newRequest(http.MethodPatch, uri, request)
if err != nil {
return err
}
return c.do(req)
}
// SetRecord sets a unique Record for given zone.
func (c *Client) SetRecord(zone string, record Record) error {
changes := map[string]RecordChangeSet{
operationSet: {
Name: record.Name,
Type: record.Type,
Records: []*Record{&record},
},
}
request := UpdateDNSZoneRecordsRequest{
DNSZone: zone,
Changes: []interface{}{changes},
ReturnAllRecords: false,
}
uri := fmt.Sprintf(uriUpdateRecords, zone)
req, err := c.newRequest(http.MethodPatch, uri, request)
if err != nil {
return err
}
return c.do(req)
}
// DeleteRecord deletes a Record for given zone.
func (c *Client) DeleteRecord(zone string, record Record) error {
delRecord := map[string]RecordChangeDelete{
operationDelete: {
Name: record.Name,
Type: record.Type,
Data: record.Data,
},
}
request := UpdateDNSZoneRecordsRequest{
DNSZone: zone,
Changes: []interface{}{delRecord},
ReturnAllRecords: false,
}
uri := fmt.Sprintf(uriUpdateRecords, zone)
req, err := c.newRequest(http.MethodPatch, uri, request)
if err != nil {
return err
}
return c.do(req)
}
func (c *Client) newRequest(method, uri string, body interface{}) (*http.Request, error) {
buf := new(bytes.Buffer)
if body != nil {
err := json.NewEncoder(buf).Encode(body)
if err != nil {
return nil, fmt.Errorf("failed to encode request body with error: %w", err)
}
}
req, err := http.NewRequest(method, c.baseURL+uri, buf)
if err != nil {
return nil, fmt.Errorf("failed to create new http request with error: %w", err)
}
req.Header.Add("X-auth-token", c.token)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
return req, nil
}
func (c *Client) do(req *http.Request) error {
resp, err := c.httpClient.Do(req)
if err != nil {
return fmt.Errorf("request failed with error: %w", err)
}
err = checkResponse(resp)
if err != nil {
return err
}
return checkResponse(resp)
}
func checkResponse(resp *http.Response) error {
if resp.StatusCode >= http.StatusBadRequest || resp.StatusCode < http.StatusOK {
if resp.Body == nil {
return fmt.Errorf("request failed with status code %d and empty body", resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
defer resp.Body.Close()
apiError := APIError{}
err = json.Unmarshal(body, &apiError)
if err != nil {
return fmt.Errorf("request failed with status code %d, response body: %s", resp.StatusCode, string(body))
}
return fmt.Errorf("request failed with status code %d: %w", resp.StatusCode, apiError)
}
return nil
}

View File

@ -0,0 +1,176 @@
package internal
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const fakeToken = "test"
func setupTest() (*Client, *http.ServeMux, func()) {
mux := http.NewServeMux()
svr := httptest.NewServer(mux)
opts := ClientOpts{
BaseURL: svr.URL,
Token: fakeToken,
}
client := NewClient(opts, nil)
return client, mux, func() {
svr.Close()
}
}
func TestClient_AddRecord(t *testing.T) {
client, mux, tearDown := setupTest()
defer tearDown()
mux.HandleFunc("/dns-zones/zone/records", func(rw http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPatch {
http.Error(rw, fmt.Sprintf("unsupported method: %s", req.Method), http.StatusBadRequest)
return
}
auth := req.Header.Get("X-Auth-Token")
if auth != fakeToken {
http.Error(rw, fmt.Sprintf("invalid token: %s", auth), http.StatusUnauthorized)
return
}
raw, err := ioutil.ReadAll(req.Body)
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
expected := `{"dns_zone":"zone","changes":[{"add":{"records":[{"data":"\"value\"","name":"fqdn","ttl":30,"type":"TXT"}]}}]}`
assert.Equal(t, expected+"\n", string(raw))
})
record := Record{
Type: "TXT",
TTL: 30,
Name: "fqdn",
Data: fmt.Sprintf(`"%s"`, "value"),
}
err := client.AddRecord("zone", record)
require.NoError(t, err)
}
func TestClient_AddRecord_error(t *testing.T) {
client, mux, tearDown := setupTest()
defer tearDown()
mux.HandleFunc("/dns-zones/zone/records", func(rw http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPatch {
http.Error(rw, fmt.Sprintf("unsupported method: %s", req.Method), http.StatusBadRequest)
return
}
auth := req.Header.Get("X-Auth-Token")
if auth != fakeToken {
http.Error(rw, fmt.Sprintf("invalid token: %s", auth), http.StatusUnauthorized)
return
}
rw.WriteHeader(http.StatusNotFound)
err := json.NewEncoder(rw).Encode(APIError{"oops"})
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
})
record := Record{
Type: "TXT",
TTL: 30,
Name: "fqdn",
Data: fmt.Sprintf(`"%s"`, "value"),
}
err := client.AddRecord("zone", record)
require.EqualError(t, err, "request failed with status code 404: oops")
}
func TestClient_SetRecord(t *testing.T) {
client, mux, tearDown := setupTest()
defer tearDown()
mux.HandleFunc("/dns-zones/zone/records", func(rw http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPatch {
http.Error(rw, fmt.Sprintf("unsupported method: %s", req.Method), http.StatusBadRequest)
return
}
auth := req.Header.Get("X-Auth-Token")
if auth != fakeToken {
http.Error(rw, fmt.Sprintf("invalid token: %s", auth), http.StatusUnauthorized)
return
}
raw, err := ioutil.ReadAll(req.Body)
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
expected := `{"dns_zone":"zone","changes":[{"set":{"name":"fqdn","type":"TXT","records":[{"data":"\"value\"","name":"fqdn","ttl":30,"type":"TXT"}]}}]}`
assert.Equal(t, expected+"\n", string(raw))
})
record := Record{
Type: "TXT",
TTL: 30,
Name: "fqdn",
Data: fmt.Sprintf(`"%s"`, "value"),
}
err := client.SetRecord("zone", record)
require.NoError(t, err)
}
func TestClient_DeleteRecord(t *testing.T) {
client, mux, tearDown := setupTest()
defer tearDown()
mux.HandleFunc("/dns-zones/zone/records", func(rw http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPatch {
http.Error(rw, fmt.Sprintf("unsupported method: %s", req.Method), http.StatusBadRequest)
return
}
auth := req.Header.Get("X-Auth-Token")
if auth != fakeToken {
http.Error(rw, fmt.Sprintf("invalid token: %s", auth), http.StatusUnauthorized)
return
}
raw, err := ioutil.ReadAll(req.Body)
if err != nil {
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
expected := `{"dns_zone":"zone","changes":[{"delete":{"data":"\"value\"","name":"fqdn","type":"TXT"}}]}`
assert.Equal(t, expected+"\n", string(raw))
})
record := Record{
Type: "TXT",
TTL: 30,
Name: "fqdn",
Data: fmt.Sprintf(`"%s"`, "value"),
}
err := client.DeleteRecord("zone", record)
require.NoError(t, err)
}

View File

@ -0,0 +1,143 @@
// Package scaleway implements a DNS provider for solving the DNS-01 challenge using Scaleway Domains API.
// Scaleway Domain API reference: https://developers.scaleway.com/en/products/domain/api/
// Token: https://www.scaleway.com/en/docs/generate-an-api-token/
package scaleway
import (
"errors"
"fmt"
"net/http"
"time"
"github.com/go-acme/lego/v3/challenge/dns01"
"github.com/go-acme/lego/v3/platform/config/env"
"github.com/go-acme/lego/v3/providers/dns/scaleway/internal"
)
const (
defaultBaseURL = "https://api.scaleway.com"
defaultVersion = "v2alpha2"
minTTL = 60
defaultPollingInterval = 10 * time.Second
defaultPropagationTimeout = 120 * time.Second
)
const (
envNamespace = "SCALEWAY_"
baseURLEnvVar = envNamespace + "BASE_URL"
apiTokenEnvVar = envNamespace + "API_TOKEN"
apiVersionEnvVar = envNamespace + "API_VERSION"
ttlEnvVar = envNamespace + "TTL"
propagationTimeoutEnvVar = envNamespace + "PROPAGATION_TIMEOUT"
pollingIntervalEnvVar = envNamespace + "POLLING_INTERVAL"
httpTimeoutEnvVar = envNamespace + "HTTP_TIMEOUT"
)
// Config is used to configure the creation of the DNSProvider.
type Config struct {
BaseURL string
Version string
Token string
PropagationTimeout time.Duration
PollingInterval time.Duration
TTL int
HTTPClient *http.Client
}
// NewDefaultConfig returns a default configuration for the DNSProvider.
func NewDefaultConfig() *Config {
return &Config{
BaseURL: env.GetOrDefaultString(baseURLEnvVar, defaultBaseURL),
Version: env.GetOrDefaultString(apiVersionEnvVar, defaultVersion),
TTL: env.GetOrDefaultInt(ttlEnvVar, minTTL),
PropagationTimeout: env.GetOrDefaultSecond(propagationTimeoutEnvVar, defaultPropagationTimeout),
PollingInterval: env.GetOrDefaultSecond(pollingIntervalEnvVar, defaultPollingInterval),
HTTPClient: &http.Client{
Timeout: env.GetOrDefaultSecond(httpTimeoutEnvVar, 30*time.Second),
},
}
}
// DNSProvider is an implementation of the challenge.Provider interface.
type DNSProvider struct {
config *Config
client *internal.Client
}
// NewDNSProvider returns a DNSProvider instance configured for Scaleway Domains API.
// API token must be passed in the environment variable SCALEWAY_API_TOKEN.
func NewDNSProvider() (*DNSProvider, error) {
values, err := env.Get(apiTokenEnvVar)
if err != nil {
return nil, fmt.Errorf("scaleway: %w", err)
}
config := NewDefaultConfig()
config.Token = values[apiTokenEnvVar]
return NewDNSProviderConfig(config)
}
// NewDNSProviderConfig return a DNSProvider instance configured for scaleway.
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
if config == nil {
return nil, errors.New("scaleway: the configuration of the DNS provider is nil")
}
if config.Token == "" {
return nil, errors.New("scaleway: credentials missing")
}
if config.TTL < minTTL {
config.TTL = minTTL
}
client := internal.NewClient(internal.ClientOpts{
BaseURL: fmt.Sprintf("%s/domain/%s", config.BaseURL, config.Version),
Token: config.Token,
}, config.HTTPClient)
return &DNSProvider{config: config, client: client}, nil
}
// Timeout returns the Timeout and interval to use when checking for DNS propagation.
// Adjusting here to cope with spikes in propagation times.
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval
}
// Present creates a TXT record to fulfill DNS-01 challenge.
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
fqdn, value := dns01.GetRecord(domain, keyAuth)
txtRecord := internal.Record{
Type: "TXT",
TTL: uint32(d.config.TTL),
Name: fqdn,
Data: fmt.Sprintf(`"%s"`, value),
}
err := d.client.AddRecord(domain, txtRecord)
if err != nil {
return fmt.Errorf("scaleway: %w", err)
}
return nil
}
// CleanUp removes a TXT record used for DNS-01 challenge.
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
fqdn, value := dns01.GetRecord(domain, keyAuth)
txtRecord := internal.Record{
Type: "TXT",
TTL: uint32(d.config.TTL),
Name: fqdn,
Data: fmt.Sprintf(`"%s"`, value),
}
err := d.client.DeleteRecord(domain, txtRecord)
if err != nil {
return fmt.Errorf("scaleway: %w", err)
}
return nil
}

View File

@ -0,0 +1,24 @@
Name = "Scaleway"
Description = ''''''
URL = "https://developers.scaleway.com/"
Code = "scaleway"
Since = "v3.4.0"
Example = '''
SCALEWAY_API_TOKEN=xxxxxxx-xxxxx-xxxx-xxx-xxxxxx \
lego --dns scaleway.com --domains my.domain.com --email my@email.com run
'''
[Configuration]
[Configuration.Credentials]
SCALEWAY_API_TOKEN = "API token"
[Configuration.Additional]
SCALEWAY_BASE_URL = "API endpoint URL"
SCALEWAY_API_VERSION = "API version"
SCALEWAY_POLLING_INTERVAL = "Time between DNS propagation check"
SCALEWAY_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
SCALEWAY_TTL = "The TTL of the TXT record used for the DNS challenge"
SCALEWAY_HTTP_TIMEOUT = "API request timeout"
[Links]
API = "https://developers.scaleway.com/en/products/domain/api/"

View File

@ -0,0 +1,131 @@
package scaleway
import (
"fmt"
"testing"
"time"
"github.com/go-acme/lego/v3/platform/tester"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const (
cleanUpDelay = 2 * time.Second
)
func TestNewDNSProvider(t *testing.T) {
var envTest = tester.NewEnvTest(apiTokenEnvVar, ttlEnvVar)
testCases := []struct {
desc string
envVars map[string]string
expected string
}{
{
desc: "success",
envVars: map[string]string{
apiTokenEnvVar: "123",
},
},
{
desc: "missing api key",
envVars: map[string]string{
apiTokenEnvVar: "",
},
expected: fmt.Sprintf("scaleway: some credentials information are missing: %s", apiTokenEnvVar),
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
defer envTest.RestoreEnv()
envTest.ClearEnv()
envTest.Apply(test.envVars)
p, err := NewDNSProvider()
if len(test.expected) == 0 {
require.NoError(t, err)
require.NotNil(t, p)
assert.NotNil(t, p.config)
assert.NotNil(t, p.client)
} else {
require.EqualError(t, err, test.expected)
}
})
}
}
func TestNewDNSProviderConfig(t *testing.T) {
testCases := []struct {
desc string
token string
ttl int
expected string
}{
{
desc: "success",
token: "123",
ttl: minTTL,
},
{
desc: "missing api key",
token: "",
ttl: minTTL,
expected: "scaleway: credentials missing",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
config := NewDefaultConfig()
config.TTL = test.ttl
config.Token = test.token
p, err := NewDNSProviderConfig(config)
if len(test.expected) == 0 {
require.NoError(t, err)
require.NotNil(t, p)
assert.NotNil(t, p.config)
assert.NotNil(t, p.client)
} else {
require.EqualError(t, err, test.expected)
}
})
}
}
func TestLivePresent(t *testing.T) {
var envTest = tester.NewEnvTest(apiTokenEnvVar, ttlEnvVar)
if !envTest.IsLiveTest() {
t.Skip("skipping live test")
}
envTest.RestoreEnv()
provider, err := NewDNSProvider()
require.NoError(t, err)
err = provider.Present(envTest.GetDomain(), "", "123d==")
require.NoError(t, err)
}
func TestLiveCleanUp(t *testing.T) {
var envTest = tester.NewEnvTest(apiTokenEnvVar, ttlEnvVar)
if !envTest.IsLiveTest() {
t.Skip("skipping live test")
}
envTest.RestoreEnv()
provider, err := NewDNSProvider()
require.NoError(t, err)
time.Sleep(cleanUpDelay)
err = provider.CleanUp(envTest.GetDomain(), "", "123d==")
require.NoError(t, err)
}