From 34a6c80d4f702f0dee04616ad006b3e34cdb68c4 Mon Sep 17 00:00:00 2001 From: brookatlas Date: Fri, 3 May 2024 21:49:19 +0300 Subject: [PATCH] support nameservers update Signed-off-by: brookatlas --- namecheap/domains_ns_update.go | 50 +++++++ namecheap/domains_ns_update_test.go | 209 ++++++++++++++++++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 namecheap/domains_ns_update.go create mode 100644 namecheap/domains_ns_update_test.go diff --git a/namecheap/domains_ns_update.go b/namecheap/domains_ns_update.go new file mode 100644 index 0000000..3530fa0 --- /dev/null +++ b/namecheap/domains_ns_update.go @@ -0,0 +1,50 @@ +package namecheap + +import ( + "encoding/xml" + "fmt" +) + +type NameserversUpdateResponse struct { + XMLName *xml.Name `xml:"ApiResponse"` + Errors *[]struct { + Message *string `xml:",chardata"` + Number *string `xml:"Number,attr"` + } `xml:"Errors>Error"` + CommandResponse *NameserversCreateCommandResponse `xml:"CommandResponse"` +} + +type NameserversUpdateCommandResponse struct { + DomainNameserverUpdateResult *DomainsNSUpdateResult `xml:"DomainNSUpdateResult"` +} + +type DomainsNSUpdateResult struct { + Domain *string `xml:"Domain,attr"` + Nameserver *string `xml:"Nameserver,attr"` + IsSuccess *bool `xml:"IsSuccess,attr"` +} + +func (s *DomainsNSService) Update(SLD string, TLD string, Nameserver string, OldIP string, IP string) (*NameserversCreateCommandResponse, error) { + var response NameserversUpdateResponse + + params := map[string]string{ + "Command": "namecheap.domains.ns.update", + "SLD": SLD, + "TLD": TLD, + "Nameserver": Nameserver, + "OldIP": OldIP, + "IP": IP, + } + + _, err := s.client.DoXML(params, &response) + if err != nil { + return nil, err + } + + if response.Errors != nil && len(*response.Errors) > 0 { + apiErr := (*response.Errors)[0] + return nil, fmt.Errorf("%s (%s)", *apiErr.Message, *apiErr.Number) + } + + return response.CommandResponse, nil +} diff --git a/namecheap/domains_ns_update_test.go b/namecheap/domains_ns_update_test.go new file mode 100644 index 0000000..f1ccc9f --- /dev/null +++ b/namecheap/domains_ns_update_test.go @@ -0,0 +1,209 @@ +package namecheap + +import ( + "io/ioutil" + "net/http" + "net/http/httptest" + "net/url" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDomainNameserversUpdate(t *testing.T) { + fakeResponse := ` + + + + namecheap.domains.ns.update + + + + SEVER-ONE + +5 + 32.76 + + ` + + t.Run("request_command", func(t *testing.T) { + var sentBody url.Values + + mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + body, _ := ioutil.ReadAll(request.Body) + query, _ := url.ParseQuery(string(body)) + sentBody = query + _, _ = writer.Write([]byte(fakeResponse)) + })) + defer mockServer.Close() + + client := setupClient(nil) + client.BaseURL = mockServer.URL + + _, err := client.DomainsNS.Update("specific-sld", "specific-tld", "ns1.domain.com", "specific-old-ip", "specific-new-ip") + if err != nil { + t.Fatal("Unable to get domain nameserver", err) + } + + assert.Equal(t, "namecheap.domains.ns.update", sentBody.Get("Command")) + }) + + t.Run("server_empty_response", func(t *testing.T) { + fakeLocalResponse := "" + + mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte(fakeLocalResponse)) + })) + defer mockServer.Close() + + client := setupClient(nil) + client.BaseURL = mockServer.URL + + _, err := client.DomainsNS.Update("specific-sld", "specific-tld", "ns1.domain.com", "specific-old-ip", "specific-new-ip") + + assert.EqualError(t, err, "unable to parse server response: EOF") + }) + + t.Run("server_non_xml_response", func(t *testing.T) { + fakeLocalResponse := "non-xml response" + + mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte(fakeLocalResponse)) + })) + defer mockServer.Close() + + client := setupClient(nil) + client.BaseURL = mockServer.URL + + _, err := client.DomainsNS.Update("specific-sld", "specific-tld", "ns1.domain.com", "specific-old-ip", "specific-new-ip") + + assert.EqualError(t, err, "unable to parse server response: EOF") + }) + + t.Run("server_broken_xml_response", func(t *testing.T) { + fakeLocalResponse := "" + + mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte(fakeLocalResponse)) + })) + defer mockServer.Close() + + client := setupClient(nil) + client.BaseURL = mockServer.URL + + _, err := client.DomainsNS.Update("specific-sld", "specific-tld", "ns1.domain.com", "specific-old-ip", "specific-new-ip") + + assert.EqualError(t, err, "unable to parse server response: expected element type but have ") + }) + + t.Run("server_respond_with_domain_not_found_error", func(t *testing.T) { + fakeLocalResponse := ` + + + + Domain not found + + + namecheap.domains.ns.update + PHX01SBAPIEXT05 + --4:00 + 0.011 + + ` + + mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte(fakeLocalResponse)) + })) + defer mockServer.Close() + + client := setupClient(nil) + client.BaseURL = mockServer.URL + + _, err := client.DomainsNS.Update("specific-sld", "specific-tld", "ns1.domain.com", "specific-old-ip", "specific-new-ip") + + assert.EqualError(t, err, "Domain not found (2019166)") + }) + + t.Run("server_respond_with_domain_not_associated_with_account_error", func(t *testing.T) { + fakeLocalResponse := ` + + + + Domain is not associated with your account + + + namecheap.domains.ns.update + PHX01SBAPIEXT05 + --4:00 + 0.011 + + ` + + mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte(fakeLocalResponse)) + })) + defer mockServer.Close() + + client := setupClient(nil) + client.BaseURL = mockServer.URL + + _, err := client.DomainsNS.Update("specific-sld", "specific-tld", "ns1.domain.com", "specific-old-ip", "specific-new-ip") + + assert.EqualError(t, err, "Domain is not associated with your account (2016166)") + }) + + t.Run("server_respond_with_error_from_enom", func(t *testing.T) { + fakeLocalResponse := ` + + + + Error From Enom when Errorcount <> 0 + + + namecheap.domains.ns.update + PHX01SBAPIEXT05 + --4:00 + 0.011 + + ` + + mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte(fakeLocalResponse)) + })) + defer mockServer.Close() + + client := setupClient(nil) + client.BaseURL = mockServer.URL + + _, err := client.DomainsNS.Update("specific-sld", "specific-tld", "ns1.domain.com", "specific-old-ip", "specific-new-ip") + + assert.EqualError(t, err, "Error From Enom when Errorcount <> 0 (3031510)") + }) + + t.Run("server_respond_with_unknown_error_from_enom", func(t *testing.T) { + fakeLocalResponse := ` + + + + Unknown error from Enom + + + namecheap.domains.ns.update + PHX01SBAPIEXT05 + --4:00 + 0.011 + + ` + + mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + _, _ = writer.Write([]byte(fakeLocalResponse)) + })) + defer mockServer.Close() + + client := setupClient(nil) + client.BaseURL = mockServer.URL + + _, err := client.DomainsNS.Update("specific-sld", "specific-tld", "ns1.domain.com", "specific-old-ip", "specific-new-ip") + + assert.EqualError(t, err, "Unknown error from Enom (3050900)") + }) +}