2019-03-11 16:56:48 +00:00
|
|
|
package internal
|
2018-09-15 17:26:45 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2021-08-25 09:44:11 +00:00
|
|
|
"io"
|
2018-09-15 17:26:45 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func handlerMock(method string, response *apiResponse, data interface{}) http.Handler {
|
|
|
|
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
|
|
|
if req.Method != method {
|
|
|
|
content, err := json.Marshal(apiResponse{
|
|
|
|
Code: 999, // random code only for the test
|
|
|
|
Message: fmt.Sprintf("invalid method: got %s want %s", req.Method, method),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
http.Error(rw, string(content), http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
jsonData, err := json.Marshal(data)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response.Data = jsonData
|
|
|
|
|
|
|
|
content, err := json.Marshal(response)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-09-24 19:07:20 +00:00
|
|
|
_, err = rw.Write(content)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
2018-09-15 17:26:45 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestClientGetDomainInformation(t *testing.T) {
|
|
|
|
type result struct {
|
|
|
|
domain *Data
|
|
|
|
error bool
|
|
|
|
}
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
fqdn string
|
|
|
|
response *apiResponse
|
|
|
|
data []Data
|
|
|
|
expected result
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "domain found",
|
|
|
|
fqdn: "_acme-challenge.foo.com.",
|
|
|
|
response: &apiResponse{
|
|
|
|
Code: 1,
|
|
|
|
},
|
|
|
|
data: []Data{
|
|
|
|
{
|
|
|
|
ID: "1",
|
|
|
|
Domain: "bar.com.",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: "2",
|
|
|
|
Domain: "foo.com.",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: result{domain: &Data{
|
|
|
|
ID: "2",
|
|
|
|
Domain: "foo.com.",
|
|
|
|
}},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "domains not found",
|
|
|
|
fqdn: "_acme-challenge.huu.com.",
|
|
|
|
response: &apiResponse{
|
|
|
|
Code: 1,
|
|
|
|
},
|
|
|
|
data: []Data{
|
|
|
|
{
|
|
|
|
ID: "5",
|
|
|
|
Domain: "bar.com.",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: "6",
|
|
|
|
Domain: "foo.com.",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expected: result{error: true},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
server := httptest.NewServer(handlerMock(http.MethodGet, test.response, test.data))
|
2021-11-01 23:52:38 +00:00
|
|
|
t.Cleanup(server.Close)
|
2018-09-15 17:26:45 +00:00
|
|
|
|
|
|
|
client, _ := NewClient("myKey", "mySecret")
|
|
|
|
client.BaseURL = server.URL + "/"
|
|
|
|
|
|
|
|
domain, err := client.GetDomainInformation(test.fqdn)
|
|
|
|
|
|
|
|
if test.expected.error {
|
|
|
|
require.Error(t, err)
|
|
|
|
} else {
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, test.expected.domain, domain)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestClientFindTxtRecord(t *testing.T) {
|
|
|
|
type result struct {
|
|
|
|
txtRecord *TXTRecord
|
|
|
|
error bool
|
|
|
|
}
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
fqdn string
|
|
|
|
zoneID string
|
|
|
|
txtRecords []TXTRecord
|
|
|
|
response *apiResponse
|
|
|
|
expected result
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "record found",
|
|
|
|
fqdn: "_acme-challenge.foo.com.",
|
|
|
|
zoneID: "test-zone",
|
|
|
|
txtRecords: []TXTRecord{
|
|
|
|
{
|
|
|
|
ID: 1,
|
|
|
|
RecordID: "Record-A",
|
|
|
|
Host: "_acme-challenge.foo.com",
|
|
|
|
Value: "txtTXTtxtTXTtxtTXTtxtTXT",
|
|
|
|
Type: "TXT",
|
|
|
|
LineID: 6,
|
|
|
|
TTL: 30,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: 2,
|
|
|
|
RecordID: "Record-B",
|
|
|
|
Host: "_acme-challenge.bar.com",
|
|
|
|
Value: "TXTtxtTXTtxtTXTtxtTXTtxt",
|
|
|
|
Type: "TXT",
|
|
|
|
LineID: 6,
|
|
|
|
TTL: 30,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
response: &apiResponse{
|
|
|
|
Code: 1,
|
|
|
|
},
|
|
|
|
expected: result{
|
|
|
|
txtRecord: &TXTRecord{
|
|
|
|
ID: 1,
|
|
|
|
RecordID: "Record-A",
|
|
|
|
Host: "_acme-challenge.foo.com",
|
|
|
|
Value: "txtTXTtxtTXTtxtTXTtxtTXT",
|
|
|
|
Type: "TXT",
|
|
|
|
LineID: 6,
|
|
|
|
TTL: 30,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "record not found",
|
|
|
|
fqdn: "_acme-challenge.huu.com.",
|
|
|
|
zoneID: "test-zone",
|
|
|
|
txtRecords: []TXTRecord{
|
|
|
|
{
|
|
|
|
ID: 1,
|
|
|
|
RecordID: "Record-A",
|
|
|
|
Host: "_acme-challenge.foo.com",
|
|
|
|
Value: "txtTXTtxtTXTtxtTXTtxtTXT",
|
|
|
|
Type: "TXT",
|
|
|
|
LineID: 6,
|
|
|
|
TTL: 30,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: 2,
|
|
|
|
RecordID: "Record-B",
|
|
|
|
Host: "_acme-challenge.bar.com",
|
|
|
|
Value: "TXTtxtTXTtxtTXTtxtTXTtxt",
|
|
|
|
Type: "TXT",
|
|
|
|
LineID: 6,
|
|
|
|
TTL: 30,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
response: &apiResponse{
|
|
|
|
Code: 1,
|
|
|
|
},
|
|
|
|
expected: result{error: true},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
server := httptest.NewServer(handlerMock(http.MethodGet, test.response, test.txtRecords))
|
2021-11-01 23:52:38 +00:00
|
|
|
t.Cleanup(server.Close)
|
2018-09-15 17:26:45 +00:00
|
|
|
|
|
|
|
client, _ := NewClient("myKey", "mySecret")
|
|
|
|
client.BaseURL = server.URL + "/"
|
|
|
|
|
|
|
|
txtRecord, err := client.FindTxtRecord(test.zoneID, test.fqdn)
|
|
|
|
|
|
|
|
if test.expected.error {
|
|
|
|
require.Error(t, err)
|
|
|
|
} else {
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, test.expected.txtRecord, txtRecord)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestClientAddTxtRecord(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
desc string
|
|
|
|
domain *Data
|
|
|
|
fqdn string
|
|
|
|
value string
|
|
|
|
ttl int
|
|
|
|
expected string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "sub-domain",
|
|
|
|
domain: &Data{
|
|
|
|
ID: "1",
|
|
|
|
Domain: "bar.com.",
|
|
|
|
},
|
|
|
|
fqdn: "_acme-challenge.foo.bar.com.",
|
|
|
|
value: "txtTXTtxtTXTtxtTXTtxtTXT",
|
|
|
|
ttl: 30,
|
|
|
|
expected: `{"domain_id":1,"host":"_acme-challenge.foo","value":"txtTXTtxtTXTtxtTXTtxtTXT","type":"TXT","line_id":"1","ttl":"30"}`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "main domain",
|
|
|
|
domain: &Data{
|
|
|
|
ID: "2",
|
|
|
|
Domain: "bar.com.",
|
|
|
|
},
|
|
|
|
fqdn: "_acme-challenge.bar.com.",
|
|
|
|
value: "TXTtxtTXTtxtTXTtxtTXTtxt",
|
|
|
|
ttl: 30,
|
|
|
|
expected: `{"domain_id":2,"host":"_acme-challenge","value":"TXTtxtTXTtxtTXTtxtTXTtxt","type":"TXT","line_id":"1","ttl":"30"}`,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range testCases {
|
|
|
|
t.Run(test.desc, func(t *testing.T) {
|
|
|
|
response := &apiResponse{
|
|
|
|
Code: 1,
|
|
|
|
}
|
|
|
|
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
|
|
|
assert.NotNil(t, req.Body)
|
2021-08-25 09:44:11 +00:00
|
|
|
content, err := io.ReadAll(req.Body)
|
2018-09-15 17:26:45 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
assert.Equal(t, test.expected, string(content))
|
|
|
|
|
|
|
|
handlerMock(http.MethodPost, response, nil).ServeHTTP(rw, req)
|
|
|
|
}))
|
2021-11-01 23:52:38 +00:00
|
|
|
t.Cleanup(server.Close)
|
2018-09-15 17:26:45 +00:00
|
|
|
|
|
|
|
client, _ := NewClient("myKey", "mySecret")
|
|
|
|
client.BaseURL = server.URL + "/"
|
|
|
|
|
|
|
|
err := client.AddTxtRecord(test.domain, test.fqdn, test.value, test.ttl)
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|