lego/providers/dns/linode/linode_test.go
2024-02-24 20:49:40 +01:00

359 lines
7.7 KiB
Go

package linode
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
"github.com/go-acme/lego/v4/platform/tester"
"github.com/linode/linodego"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type MockResponseMap map[string]interface{}
var envTest = tester.NewEnvTest(EnvToken)
func setupTest(t *testing.T, responses MockResponseMap) string {
t.Helper()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Ensure that we support the requested action.
action := r.Method + ":" + r.URL.Path
resp, ok := responses[action]
if !ok {
http.Error(w, fmt.Sprintf("Unsupported mock action: %q", action), http.StatusInternalServerError)
return
}
rawResponse, err := json.Marshal(resp)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to JSON encode response: %v", err), http.StatusInternalServerError)
return
}
// Send the response.
w.Header().Set("Content-Type", "application/json")
if err, ok := resp.(linodego.APIError); ok {
if err.Errors[0].Reason == "Not found" {
w.WriteHeader(http.StatusNotFound)
} else {
w.WriteHeader(http.StatusBadRequest)
}
} else {
w.WriteHeader(http.StatusOK)
}
_, err = w.Write(rawResponse)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
})
server := httptest.NewServer(handler)
t.Cleanup(server.Close)
time.Sleep(100 * time.Millisecond)
return server.URL
}
func TestNewDNSProvider(t *testing.T) {
testCases := []struct {
desc string
envVars map[string]string
expected string
}{
{
desc: "success",
envVars: map[string]string{
EnvToken: "123",
},
},
{
desc: "missing api key",
envVars: map[string]string{
EnvToken: "",
},
expected: "linode: some credentials information are missing: LINODE_TOKEN",
},
}
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 test.expected == "" {
require.NoError(t, err)
require.NotNil(t, p)
require.NotNil(t, p.config)
require.NotNil(t, p.client)
} else {
require.EqualError(t, err, test.expected)
}
})
}
}
func TestNewDNSProviderConfig(t *testing.T) {
testCases := []struct {
desc string
apiKey string
expected string
}{
{
desc: "success",
apiKey: "123",
},
{
desc: "missing credentials",
expected: "linode: Linode Access Token missing",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
config := NewDefaultConfig()
config.Token = test.apiKey
p, err := NewDNSProviderConfig(config)
if test.expected == "" {
require.NoError(t, err)
require.NotNil(t, p)
require.NotNil(t, p.config)
require.NotNil(t, p.client)
} else {
require.EqualError(t, err, test.expected)
}
})
}
}
func TestDNSProvider_Present(t *testing.T) {
defer envTest.RestoreEnv()
os.Setenv(EnvToken, "testing")
p, err := NewDNSProvider()
require.NoError(t, err)
require.NotNil(t, p)
domain := "example.com"
keyAuth := "dGVzdGluZw=="
testCases := []struct {
desc string
mockResponses MockResponseMap
expectedError string
}{
{
desc: "Success",
mockResponses: MockResponseMap{
"GET:/v4/domains": linodego.DomainsPagedResponse{
PageOptions: &linodego.PageOptions{
Pages: 1,
Results: 1,
Page: 1,
},
Data: []linodego.Domain{{
Domain: domain,
ID: 1234,
}},
},
"POST:/v4/domains/1234/records": linodego.DomainRecord{
ID: 1234,
},
},
},
{
desc: "NoDomain",
mockResponses: MockResponseMap{
"GET:/v4/domains": linodego.APIError{
Errors: []linodego.APIErrorReason{{
Reason: "Not found",
}},
},
},
expectedError: "[404] Not found",
},
{
desc: "CreateFailed",
mockResponses: MockResponseMap{
"GET:/v4/domains": &linodego.DomainsPagedResponse{
PageOptions: &linodego.PageOptions{
Pages: 1,
Results: 1,
Page: 1,
},
Data: []linodego.Domain{{
Domain: "example.com",
ID: 1234,
}},
},
"POST:/v4/domains/1234/records": linodego.APIError{
Errors: []linodego.APIErrorReason{{
Reason: "Failed to create domain resource",
Field: "somefield",
}},
},
},
expectedError: "[400] [somefield] Failed to create domain resource",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
serverURL := setupTest(t, test.mockResponses)
assert.NotNil(t, p.client)
p.client.SetBaseURL(serverURL)
err = p.Present(domain, "", keyAuth)
if test.expectedError == "" {
assert.NoError(t, err)
} else {
assert.EqualError(t, err, test.expectedError)
}
})
}
}
func TestDNSProvider_CleanUp(t *testing.T) {
defer envTest.RestoreEnv()
os.Setenv(EnvToken, "testing")
p, err := NewDNSProvider()
require.NoError(t, err)
domain := "example.com"
keyAuth := "dGVzdGluZw=="
testCases := []struct {
desc string
mockResponses MockResponseMap
expectedError string
}{
{
desc: "Success",
mockResponses: MockResponseMap{
"GET:/v4/domains": &linodego.DomainsPagedResponse{
PageOptions: &linodego.PageOptions{
Pages: 1,
Results: 1,
Page: 1,
},
Data: []linodego.Domain{{
Domain: "foobar.com",
ID: 1234,
}},
},
"GET:/v4/domains/1234/records": &linodego.DomainRecordsPagedResponse{
PageOptions: &linodego.PageOptions{
Pages: 1,
Results: 1,
Page: 1,
},
Data: []linodego.DomainRecord{{
ID: 1234,
Name: "_acme-challenge",
Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
Type: "TXT",
}},
},
"DELETE:/v4/domains/1234/records/1234": struct{}{},
},
},
{
desc: "NoDomain",
mockResponses: MockResponseMap{
"GET:/v4/domains": linodego.APIError{
Errors: []linodego.APIErrorReason{{
Reason: "Not found",
}},
},
"GET:/v4/domains/1234/records": linodego.APIError{
Errors: []linodego.APIErrorReason{{
Reason: "Not found",
}},
},
},
expectedError: "[404] Not found",
},
{
desc: "DeleteFailed",
mockResponses: MockResponseMap{
"GET:/v4/domains": linodego.DomainsPagedResponse{
PageOptions: &linodego.PageOptions{
Pages: 1,
Results: 1,
Page: 1,
},
Data: []linodego.Domain{{
ID: 1234,
Domain: "example.com",
}},
},
"GET:/v4/domains/1234/records": linodego.DomainRecordsPagedResponse{
PageOptions: &linodego.PageOptions{
Pages: 1,
Results: 1,
Page: 1,
},
Data: []linodego.DomainRecord{{
ID: 1234,
Name: "_acme-challenge",
Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
Type: "TXT",
}},
},
"DELETE:/v4/domains/1234/records/1234": linodego.APIError{
Errors: []linodego.APIErrorReason{{
Reason: "Failed to delete domain resource",
}},
},
},
expectedError: "[400] Failed to delete domain resource",
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
serverURL := setupTest(t, test.mockResponses)
p.client.SetBaseURL(serverURL)
err = p.CleanUp(domain, "", keyAuth)
if test.expectedError == "" {
assert.NoError(t, err)
} else {
assert.EqualError(t, err, test.expectedError)
}
})
}
}
func TestLivePresent(t *testing.T) {
if !envTest.IsLiveTest() {
t.Skip("Skipping live test")
}
// TODO implement this test
}
func TestLiveCleanUp(t *testing.T) {
if !envTest.IsLiveTest() {
t.Skip("Skipping live test")
}
// TODO implement this test
}