- Fix go vet warnings across 4 files: update stale API calls in container/linuxkit_test.go, container/state_test.go, and devops/devops_test.go (removed io.Local arg from NewState/LoadState), rewrite container/templates_test.go for package-level function API - Add ansible/parser_test.go: 17 tests covering ParsePlaybook, ParseInventory, ParseTasks, GetHosts, GetHostVars, isModule, NormalizeModule (plays, vars, handlers, blocks, loops, roles, FQCN) - Add ansible/types_test.go: RoleRef/Task UnmarshalYAML, Inventory structure, Facts, TaskResult, KnownModules validation - Add ansible/executor_test.go: executor logic (getHosts, matchesTags, evaluateWhen, templateString, applyFilter, resolveLoop, templateArgs, handleNotify, normalizeConditions, helper functions) - Add infra/hetzner_test.go: HCloudClient/HRobotClient construction, do() round-trip via httptest, API error handling, JSON serialisation for HCloudServer, HCloudLoadBalancer, HRobotServer - Add infra/cloudns_test.go: doRaw() round-trip via httptest, zone/record JSON parsing, CRUD response validation, ACME challenge logic, auth param verification, error handling - Fix go.mod replace directive path (../go -> ../core) - All tests pass, go vet clean, go test -race clean Co-Authored-By: Virgil <virgil@lethean.io> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
625 lines
17 KiB
Go
625 lines
17 KiB
Go
package infra
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// --- Constructor ---
|
|
|
|
func TestNewCloudNSClient_Good(t *testing.T) {
|
|
c := NewCloudNSClient("12345", "secret")
|
|
assert.NotNil(t, c)
|
|
assert.Equal(t, "12345", c.authID)
|
|
assert.Equal(t, "secret", c.password)
|
|
assert.NotNil(t, c.client)
|
|
}
|
|
|
|
// --- authParams ---
|
|
|
|
func TestCloudNSClient_AuthParams_Good(t *testing.T) {
|
|
c := NewCloudNSClient("49500", "hunter2")
|
|
params := c.authParams()
|
|
|
|
assert.Equal(t, "49500", params.Get("auth-id"))
|
|
assert.Equal(t, "hunter2", params.Get("auth-password"))
|
|
}
|
|
|
|
// --- doRaw ---
|
|
|
|
func TestCloudNSClient_DoRaw_Good_ReturnsBody(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{"status":"Success"}`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
client := &CloudNSClient{
|
|
authID: "test",
|
|
password: "test",
|
|
client: ts.Client(),
|
|
}
|
|
|
|
ctx := context.Background()
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL+"/dns/test.json", nil)
|
|
require.NoError(t, err)
|
|
|
|
data, err := client.doRaw(req)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, string(data), "Success")
|
|
}
|
|
|
|
func TestCloudNSClient_DoRaw_Bad_HTTPError(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusForbidden)
|
|
_, _ = w.Write([]byte(`{"status":"Failed","statusDescription":"Invalid auth"}`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
client := &CloudNSClient{
|
|
authID: "bad",
|
|
password: "creds",
|
|
client: ts.Client(),
|
|
}
|
|
|
|
ctx := context.Background()
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL+"/dns/test.json", nil)
|
|
require.NoError(t, err)
|
|
|
|
_, err = client.doRaw(req)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "cloudns API 403")
|
|
}
|
|
|
|
func TestCloudNSClient_DoRaw_Bad_ServerError(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
_, _ = w.Write([]byte(`Internal Server Error`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
client := &CloudNSClient{
|
|
authID: "test",
|
|
password: "test",
|
|
client: ts.Client(),
|
|
}
|
|
|
|
ctx := context.Background()
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL+"/test", nil)
|
|
require.NoError(t, err)
|
|
|
|
_, err = client.doRaw(req)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "cloudns API 500")
|
|
}
|
|
|
|
// --- Zone JSON parsing ---
|
|
|
|
func TestCloudNSZone_JSON_Good(t *testing.T) {
|
|
data := `[
|
|
{"name": "example.com", "type": "master", "zone": "domain", "status": "1"},
|
|
{"name": "test.io", "type": "master", "zone": "domain", "status": "1"}
|
|
]`
|
|
|
|
var zones []CloudNSZone
|
|
err := json.Unmarshal([]byte(data), &zones)
|
|
|
|
require.NoError(t, err)
|
|
require.Len(t, zones, 2)
|
|
assert.Equal(t, "example.com", zones[0].Name)
|
|
assert.Equal(t, "master", zones[0].Type)
|
|
assert.Equal(t, "test.io", zones[1].Name)
|
|
}
|
|
|
|
func TestCloudNSZone_JSON_Good_EmptyResponse(t *testing.T) {
|
|
// CloudNS returns {} for no zones, not []
|
|
data := `{}`
|
|
|
|
var zones []CloudNSZone
|
|
err := json.Unmarshal([]byte(data), &zones)
|
|
|
|
// Should fail to parse as slice — this is the edge case ListZones handles
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
// --- Record JSON parsing ---
|
|
|
|
func TestCloudNSRecord_JSON_Good(t *testing.T) {
|
|
data := `{
|
|
"12345": {
|
|
"id": "12345",
|
|
"type": "A",
|
|
"host": "www",
|
|
"record": "1.2.3.4",
|
|
"ttl": "3600",
|
|
"status": 1
|
|
},
|
|
"12346": {
|
|
"id": "12346",
|
|
"type": "MX",
|
|
"host": "",
|
|
"record": "mail.example.com",
|
|
"ttl": "3600",
|
|
"priority": "10",
|
|
"status": 1
|
|
}
|
|
}`
|
|
|
|
var records map[string]CloudNSRecord
|
|
err := json.Unmarshal([]byte(data), &records)
|
|
|
|
require.NoError(t, err)
|
|
require.Len(t, records, 2)
|
|
|
|
aRecord := records["12345"]
|
|
assert.Equal(t, "12345", aRecord.ID)
|
|
assert.Equal(t, "A", aRecord.Type)
|
|
assert.Equal(t, "www", aRecord.Host)
|
|
assert.Equal(t, "1.2.3.4", aRecord.Record)
|
|
assert.Equal(t, "3600", aRecord.TTL)
|
|
assert.Equal(t, 1, aRecord.Status)
|
|
|
|
mxRecord := records["12346"]
|
|
assert.Equal(t, "MX", mxRecord.Type)
|
|
assert.Equal(t, "mail.example.com", mxRecord.Record)
|
|
assert.Equal(t, "10", mxRecord.Priority)
|
|
}
|
|
|
|
func TestCloudNSRecord_JSON_Good_TXTRecord(t *testing.T) {
|
|
data := `{
|
|
"99": {
|
|
"id": "99",
|
|
"type": "TXT",
|
|
"host": "_acme-challenge",
|
|
"record": "abc123def456",
|
|
"ttl": "60",
|
|
"status": 1
|
|
}
|
|
}`
|
|
|
|
var records map[string]CloudNSRecord
|
|
err := json.Unmarshal([]byte(data), &records)
|
|
|
|
require.NoError(t, err)
|
|
require.Len(t, records, 1)
|
|
|
|
txt := records["99"]
|
|
assert.Equal(t, "TXT", txt.Type)
|
|
assert.Equal(t, "_acme-challenge", txt.Host)
|
|
assert.Equal(t, "abc123def456", txt.Record)
|
|
assert.Equal(t, "60", txt.TTL)
|
|
}
|
|
|
|
// --- CreateRecord response parsing ---
|
|
|
|
func TestCloudNSClient_CreateRecord_Good_ResponseParsing(t *testing.T) {
|
|
// Verify the response shape CreateRecord expects
|
|
data := `{"status":"Success","statusDescription":"The record was created successfully.","data":{"id":54321}}`
|
|
|
|
var result struct {
|
|
Status string `json:"status"`
|
|
StatusDescription string `json:"statusDescription"`
|
|
Data struct {
|
|
ID int `json:"id"`
|
|
} `json:"data"`
|
|
}
|
|
|
|
err := json.Unmarshal([]byte(data), &result)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Success", result.Status)
|
|
assert.Equal(t, 54321, result.Data.ID)
|
|
}
|
|
|
|
func TestCloudNSClient_CreateRecord_Bad_FailedStatus(t *testing.T) {
|
|
// Verify non-Success status produces an error message
|
|
data := `{"status":"Failed","statusDescription":"Record already exists."}`
|
|
|
|
var result struct {
|
|
Status string `json:"status"`
|
|
StatusDescription string `json:"statusDescription"`
|
|
}
|
|
|
|
err := json.Unmarshal([]byte(data), &result)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Failed", result.Status)
|
|
assert.Equal(t, "Record already exists.", result.StatusDescription)
|
|
}
|
|
|
|
// --- UpdateRecord/DeleteRecord response parsing ---
|
|
|
|
func TestCloudNSClient_UpdateDelete_Good_ResponseParsing(t *testing.T) {
|
|
data := `{"status":"Success","statusDescription":"The record was updated successfully."}`
|
|
|
|
var result struct {
|
|
Status string `json:"status"`
|
|
StatusDescription string `json:"statusDescription"`
|
|
}
|
|
|
|
err := json.Unmarshal([]byte(data), &result)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Success", result.Status)
|
|
}
|
|
|
|
// --- Full round-trip tests via doRaw ---
|
|
|
|
func TestCloudNSClient_ListZones_Good_ViaDoRaw(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// Verify auth params are passed
|
|
assert.NotEmpty(t, r.URL.Query().Get("auth-id"))
|
|
assert.NotEmpty(t, r.URL.Query().Get("auth-password"))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`[{"name":"example.com","type":"master","zone":"domain","status":"1"}]`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
client := &CloudNSClient{
|
|
authID: "12345",
|
|
password: "secret",
|
|
client: ts.Client(),
|
|
}
|
|
|
|
// Build a request similar to what get() would build, but pointing at test server
|
|
ctx := context.Background()
|
|
params := client.authParams()
|
|
params.Set("page", "1")
|
|
params.Set("rows-per-page", "100")
|
|
params.Set("search", "")
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL+"/dns/list-zones.json?"+params.Encode(), nil)
|
|
require.NoError(t, err)
|
|
|
|
data, err := client.doRaw(req)
|
|
require.NoError(t, err)
|
|
|
|
var zones []CloudNSZone
|
|
err = json.Unmarshal(data, &zones)
|
|
require.NoError(t, err)
|
|
require.Len(t, zones, 1)
|
|
assert.Equal(t, "example.com", zones[0].Name)
|
|
}
|
|
|
|
func TestCloudNSClient_ListRecords_Good_ViaDoRaw(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
assert.Equal(t, "example.com", r.URL.Query().Get("domain-name"))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{
|
|
"1": {"id":"1","type":"A","host":"www","record":"1.2.3.4","ttl":"3600","status":1},
|
|
"2": {"id":"2","type":"CNAME","host":"blog","record":"www.example.com","ttl":"3600","status":1}
|
|
}`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
client := &CloudNSClient{
|
|
authID: "12345",
|
|
password: "secret",
|
|
client: ts.Client(),
|
|
}
|
|
|
|
ctx := context.Background()
|
|
params := client.authParams()
|
|
params.Set("domain-name", "example.com")
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL+"/dns/records.json?"+params.Encode(), nil)
|
|
require.NoError(t, err)
|
|
|
|
data, err := client.doRaw(req)
|
|
require.NoError(t, err)
|
|
|
|
var records map[string]CloudNSRecord
|
|
err = json.Unmarshal(data, &records)
|
|
require.NoError(t, err)
|
|
require.Len(t, records, 2)
|
|
assert.Equal(t, "A", records["1"].Type)
|
|
assert.Equal(t, "CNAME", records["2"].Type)
|
|
}
|
|
|
|
func TestCloudNSClient_CreateRecord_Good_ViaDoRaw(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
assert.Equal(t, http.MethodPost, r.Method)
|
|
assert.Equal(t, "example.com", r.URL.Query().Get("domain-name"))
|
|
assert.Equal(t, "www", r.URL.Query().Get("host"))
|
|
assert.Equal(t, "A", r.URL.Query().Get("record-type"))
|
|
assert.Equal(t, "1.2.3.4", r.URL.Query().Get("record"))
|
|
assert.Equal(t, "3600", r.URL.Query().Get("ttl"))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{"status":"Success","statusDescription":"The record was created successfully.","data":{"id":99}}`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
client := &CloudNSClient{
|
|
authID: "12345",
|
|
password: "secret",
|
|
client: ts.Client(),
|
|
}
|
|
|
|
ctx := context.Background()
|
|
params := client.authParams()
|
|
params.Set("domain-name", "example.com")
|
|
params.Set("host", "www")
|
|
params.Set("record-type", "A")
|
|
params.Set("record", "1.2.3.4")
|
|
params.Set("ttl", "3600")
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, ts.URL+"/dns/add-record.json", nil)
|
|
require.NoError(t, err)
|
|
req.URL.RawQuery = params.Encode()
|
|
|
|
data, err := client.doRaw(req)
|
|
require.NoError(t, err)
|
|
|
|
var result struct {
|
|
Status string `json:"status"`
|
|
Data struct {
|
|
ID int `json:"id"`
|
|
} `json:"data"`
|
|
}
|
|
err = json.Unmarshal(data, &result)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Success", result.Status)
|
|
assert.Equal(t, 99, result.Data.ID)
|
|
}
|
|
|
|
func TestCloudNSClient_DeleteRecord_Good_ViaDoRaw(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
assert.Equal(t, http.MethodPost, r.Method)
|
|
assert.Equal(t, "example.com", r.URL.Query().Get("domain-name"))
|
|
assert.Equal(t, "42", r.URL.Query().Get("record-id"))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{"status":"Success","statusDescription":"The record was deleted successfully."}`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
client := &CloudNSClient{
|
|
authID: "12345",
|
|
password: "secret",
|
|
client: ts.Client(),
|
|
}
|
|
|
|
ctx := context.Background()
|
|
params := client.authParams()
|
|
params.Set("domain-name", "example.com")
|
|
params.Set("record-id", "42")
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, ts.URL+"/dns/delete-record.json", nil)
|
|
require.NoError(t, err)
|
|
req.URL.RawQuery = params.Encode()
|
|
|
|
data, err := client.doRaw(req)
|
|
require.NoError(t, err)
|
|
|
|
var result struct {
|
|
Status string `json:"status"`
|
|
}
|
|
err = json.Unmarshal(data, &result)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Success", result.Status)
|
|
}
|
|
|
|
// --- ACME challenge helpers ---
|
|
|
|
func TestCloudNSClient_SetACMEChallenge_Good_ParamVerification(t *testing.T) {
|
|
// SetACMEChallenge delegates to CreateRecord with specific params.
|
|
// Verify the delegation shape by checking the expected call.
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
assert.Equal(t, "example.com", r.URL.Query().Get("domain-name"))
|
|
assert.Equal(t, "_acme-challenge", r.URL.Query().Get("host"))
|
|
assert.Equal(t, "TXT", r.URL.Query().Get("record-type"))
|
|
assert.Equal(t, "60", r.URL.Query().Get("ttl"))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{"status":"Success","statusDescription":"OK","data":{"id":777}}`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
client := &CloudNSClient{
|
|
authID: "12345",
|
|
password: "secret",
|
|
client: ts.Client(),
|
|
}
|
|
|
|
// Build request matching what SetACMEChallenge -> CreateRecord -> post() builds
|
|
ctx := context.Background()
|
|
params := client.authParams()
|
|
params.Set("domain-name", "example.com")
|
|
params.Set("host", "_acme-challenge")
|
|
params.Set("record-type", "TXT")
|
|
params.Set("record", "acme-token-value")
|
|
params.Set("ttl", "60")
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, ts.URL+"/dns/add-record.json", nil)
|
|
require.NoError(t, err)
|
|
req.URL.RawQuery = params.Encode()
|
|
|
|
data, err := client.doRaw(req)
|
|
require.NoError(t, err)
|
|
|
|
var result struct {
|
|
Status string `json:"status"`
|
|
Data struct {
|
|
ID int `json:"id"`
|
|
} `json:"data"`
|
|
}
|
|
err = json.Unmarshal(data, &result)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Success", result.Status)
|
|
assert.Equal(t, 777, result.Data.ID)
|
|
}
|
|
|
|
func TestCloudNSClient_ClearACMEChallenge_Good_Logic(t *testing.T) {
|
|
// ClearACMEChallenge lists records, finds _acme-challenge TXT records, deletes them.
|
|
// Test the logic by verifying the record filtering.
|
|
records := map[string]CloudNSRecord{
|
|
"1": {ID: "1", Type: "A", Host: "www", Record: "1.2.3.4"},
|
|
"2": {ID: "2", Type: "TXT", Host: "_acme-challenge", Record: "token1"},
|
|
"3": {ID: "3", Type: "TXT", Host: "_dmarc", Record: "v=DMARC1"},
|
|
"4": {ID: "4", Type: "TXT", Host: "_acme-challenge", Record: "token2"},
|
|
}
|
|
|
|
// Simulate the filtering logic from ClearACMEChallenge
|
|
var toDelete []string
|
|
for id, r := range records {
|
|
if r.Host == "_acme-challenge" && r.Type == "TXT" {
|
|
toDelete = append(toDelete, id)
|
|
}
|
|
}
|
|
|
|
assert.Len(t, toDelete, 2)
|
|
assert.Contains(t, toDelete, "2")
|
|
assert.Contains(t, toDelete, "4")
|
|
}
|
|
|
|
// --- EnsureRecord logic ---
|
|
|
|
func TestEnsureRecord_Good_Logic_AlreadyCorrect(t *testing.T) {
|
|
// Simulate the check: host matches, type matches, value matches => no change
|
|
records := map[string]CloudNSRecord{
|
|
"10": {ID: "10", Type: "A", Host: "www", Record: "1.2.3.4"},
|
|
}
|
|
|
|
host := "www"
|
|
recordType := "A"
|
|
value := "1.2.3.4"
|
|
|
|
var needsUpdate, needsCreate bool
|
|
for _, r := range records {
|
|
if r.Host == host && r.Type == recordType {
|
|
if r.Record == value {
|
|
// Already correct — no change needed
|
|
needsUpdate = false
|
|
needsCreate = false
|
|
} else {
|
|
needsUpdate = true
|
|
}
|
|
break
|
|
}
|
|
}
|
|
|
|
if !needsUpdate {
|
|
// Check if we found any match at all
|
|
found := false
|
|
for _, r := range records {
|
|
if r.Host == host && r.Type == recordType {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
needsCreate = true
|
|
}
|
|
}
|
|
|
|
assert.False(t, needsUpdate, "should not need update when value matches")
|
|
assert.False(t, needsCreate, "should not need create when record exists")
|
|
}
|
|
|
|
func TestEnsureRecord_Good_Logic_NeedsUpdate(t *testing.T) {
|
|
records := map[string]CloudNSRecord{
|
|
"10": {ID: "10", Type: "A", Host: "www", Record: "1.2.3.4"},
|
|
}
|
|
|
|
host := "www"
|
|
recordType := "A"
|
|
value := "5.6.7.8" // Different value
|
|
|
|
var needsUpdate bool
|
|
for _, r := range records {
|
|
if r.Host == host && r.Type == recordType {
|
|
if r.Record != value {
|
|
needsUpdate = true
|
|
}
|
|
break
|
|
}
|
|
}
|
|
|
|
assert.True(t, needsUpdate, "should need update when value differs")
|
|
}
|
|
|
|
func TestEnsureRecord_Good_Logic_NeedsCreate(t *testing.T) {
|
|
records := map[string]CloudNSRecord{
|
|
"10": {ID: "10", Type: "A", Host: "www", Record: "1.2.3.4"},
|
|
}
|
|
|
|
host := "api" // Does not exist
|
|
recordType := "A"
|
|
|
|
found := false
|
|
for _, r := range records {
|
|
if r.Host == host && r.Type == recordType {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
assert.False(t, found, "should not find record for non-existent host")
|
|
}
|
|
|
|
// --- Edge cases ---
|
|
|
|
func TestCloudNSClient_DoRaw_Good_EmptyBody(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
// Empty body
|
|
}))
|
|
defer ts.Close()
|
|
|
|
client := &CloudNSClient{
|
|
authID: "test",
|
|
password: "test",
|
|
client: ts.Client(),
|
|
}
|
|
|
|
ctx := context.Background()
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL+"/test", nil)
|
|
require.NoError(t, err)
|
|
|
|
data, err := client.doRaw(req)
|
|
require.NoError(t, err)
|
|
assert.Empty(t, data)
|
|
}
|
|
|
|
func TestCloudNSRecord_JSON_Good_EmptyMap(t *testing.T) {
|
|
// An empty record set is a valid empty map
|
|
data := `{}`
|
|
|
|
var records map[string]CloudNSRecord
|
|
err := json.Unmarshal([]byte(data), &records)
|
|
|
|
require.NoError(t, err)
|
|
assert.Empty(t, records)
|
|
}
|
|
|
|
func TestCloudNSClient_DoRaw_Good_AuthQueryParams(t *testing.T) {
|
|
// Verify that auth params make it to the server in the query string
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
assert.Equal(t, "49500", r.URL.Query().Get("auth-id"))
|
|
assert.Equal(t, "supersecret", r.URL.Query().Get("auth-password"))
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`[]`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
client := &CloudNSClient{
|
|
authID: "49500",
|
|
password: "supersecret",
|
|
client: ts.Client(),
|
|
}
|
|
|
|
ctx := context.Background()
|
|
params := client.authParams()
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL+"/dns/test.json?"+params.Encode(), nil)
|
|
require.NoError(t, err)
|
|
|
|
_, err = client.doRaw(req)
|
|
require.NoError(t, err)
|
|
}
|