Fix DNS record JSON parsing for MCNS response format
MCNS returns records wrapped in {"records": [...]} envelope with
uppercase field names (ID, Name, Type, Value), not bare arrays
with lowercase fields.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,11 +28,11 @@ type DNSRegistrar struct {
|
|||||||
|
|
||||||
// dnsRecord is the JSON representation of an MCNS record.
|
// dnsRecord is the JSON representation of an MCNS record.
|
||||||
type dnsRecord struct {
|
type dnsRecord struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"ID"`
|
||||||
Name string `json:"name"`
|
Name string `json:"Name"`
|
||||||
Type string `json:"type"`
|
Type string `json:"Type"`
|
||||||
Value string `json:"value"`
|
Value string `json:"Value"`
|
||||||
TTL int `json:"ttl"`
|
TTL int `json:"TTL"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSRegistrar creates a DNSRegistrar. Returns (nil, nil) if
|
// NewDNSRegistrar creates a DNSRegistrar. Returns (nil, nil) if
|
||||||
@@ -157,11 +157,13 @@ func (d *DNSRegistrar) listRecords(ctx context.Context, serviceName string) ([]d
|
|||||||
return nil, fmt.Errorf("list records: mcns returned %d: %s", resp.StatusCode, string(body))
|
return nil, fmt.Errorf("list records: mcns returned %d: %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
var records []dnsRecord
|
var envelope struct {
|
||||||
if err := json.Unmarshal(body, &records); err != nil {
|
Records []dnsRecord `json:"records"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(body, &envelope); err != nil {
|
||||||
return nil, fmt.Errorf("parse list response: %w", err)
|
return nil, fmt.Errorf("parse list response: %w", err)
|
||||||
}
|
}
|
||||||
return records, nil
|
return envelope.Records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createRecord creates an A record in the zone.
|
// createRecord creates an A record in the zone.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func TestEnsureRecordCreatesWhenMissing(t *testing.T) {
|
|||||||
if r.Method == http.MethodGet {
|
if r.Method == http.MethodGet {
|
||||||
// List returns empty — no existing records.
|
// List returns empty — no existing records.
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_, _ = w.Write([]byte("[]"))
|
_, _ = w.Write([]byte(`{"records":[]}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gotMethod = r.Method
|
gotMethod = r.Method
|
||||||
@@ -90,9 +90,9 @@ func TestEnsureRecordSkipsWhenExists(t *testing.T) {
|
|||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == http.MethodGet {
|
if r.Method == http.MethodGet {
|
||||||
// Return an existing record with the correct value.
|
// Return an existing record with the correct value.
|
||||||
records := []dnsRecord{{ID: 1, Name: "myservice", Type: "A", Value: "192.168.88.181", TTL: 300}}
|
resp := map[string][]dnsRecord{"records": {{ID: 1, Name: "myservice", Type: "A", Value: "192.168.88.181", TTL: 300}}}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_ = json.NewEncoder(w).Encode(records)
|
_ = json.NewEncoder(w).Encode(resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
createCalled = true
|
createCalled = true
|
||||||
@@ -124,9 +124,9 @@ func TestEnsureRecordUpdatesWrongValue(t *testing.T) {
|
|||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == http.MethodGet {
|
if r.Method == http.MethodGet {
|
||||||
// Return a record with a stale value.
|
// Return a record with a stale value.
|
||||||
records := []dnsRecord{{ID: 42, Name: "myservice", Type: "A", Value: "10.0.0.1", TTL: 300}}
|
resp := map[string][]dnsRecord{"records": {{ID: 42, Name: "myservice", Type: "A", Value: "10.0.0.1", TTL: 300}}}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_ = json.NewEncoder(w).Encode(records)
|
_ = json.NewEncoder(w).Encode(resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gotMethod = r.Method
|
gotMethod = r.Method
|
||||||
@@ -160,9 +160,9 @@ func TestRemoveRecordDeletes(t *testing.T) {
|
|||||||
|
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == http.MethodGet {
|
if r.Method == http.MethodGet {
|
||||||
records := []dnsRecord{{ID: 7, Name: "myservice", Type: "A", Value: "192.168.88.181", TTL: 300}}
|
resp := map[string][]dnsRecord{"records": {{ID: 7, Name: "myservice", Type: "A", Value: "192.168.88.181", TTL: 300}}}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_ = json.NewEncoder(w).Encode(records)
|
_ = json.NewEncoder(w).Encode(resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gotMethod = r.Method
|
gotMethod = r.Method
|
||||||
@@ -195,7 +195,7 @@ func TestRemoveRecordNoopWhenMissing(t *testing.T) {
|
|||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
// List returns empty.
|
// List returns empty.
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_, _ = w.Write([]byte("[]"))
|
_, _ = w.Write([]byte(`{"records":[]}`))
|
||||||
}))
|
}))
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user