From 0d836d7e3bb0395146f8c2850740f3fbd35f836e Mon Sep 17 00:00:00 2001 From: Jener Rasmussen Date: Tue, 3 Dec 2024 14:57:30 +0100 Subject: [PATCH 1/9] Refactor error message to common constant --- pkg/tidydns/tidydns.go | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/pkg/tidydns/tidydns.go b/pkg/tidydns/tidydns.go index 4fe0861..da72ea8 100644 --- a/pkg/tidydns/tidydns.go +++ b/pkg/tidydns/tidydns.go @@ -86,6 +86,8 @@ const ( RecordTypeCAA RecordType = 10 ) +const errorTidyDNS = "error from tidyDNS server: %s" + type tidyDNSClient struct { client *http.Client username string @@ -118,7 +120,7 @@ func (c *tidyDNSClient) GetSubnetIDs(ctx context.Context, subnetCIDR string) (*S _ = Body.Close() }(res.Body) if res.StatusCode != http.StatusOK { - return nil, fmt.Errorf("error from tidyDNS server: %s", res.Status) + return nil, fmt.Errorf(errorTidyDNS, res.Status) } var subnets []dhcpSubnet @@ -158,7 +160,7 @@ func (c *tidyDNSClient) GetFreeIP(ctx context.Context, subnetID int) (string, er _ = Body.Close() }(res.Body) if res.StatusCode != http.StatusOK { - return "", fmt.Errorf("error from tidyDNS server: %s", res.Status) + return "", fmt.Errorf(errorTidyDNS, res.Status) } var freeIP dhcpFreeIP @@ -205,7 +207,7 @@ func (c *tidyDNSClient) CreateDHCPInterface(ctx context.Context, createInfo Crea if strings.Contains(bodyString, checkstring) { return 1, fmt.Errorf("try again") } - return 0, fmt.Errorf("error from tidyDNS server: %s", res.Status) + return 0, fmt.Errorf(errorTidyDNS, res.Status) } var createResp interfaceCreate @@ -233,7 +235,7 @@ func (c *tidyDNSClient) ReadDHCPInterface(ctx context.Context, interfaceID int) _ = Body.Close() }(res.Body) if res.StatusCode != http.StatusOK { - return nil, fmt.Errorf("error from tidyDNS server: %s", res.Status) + return nil, fmt.Errorf(errorTidyDNS, res.Status) } var interfaceRead interfaceRead @@ -268,7 +270,7 @@ func (c *tidyDNSClient) UpdateDHCPInterfaceName(ctx context.Context, interfaceID _ = Body.Close() }(res.Body) if res.StatusCode != http.StatusOK { - return 0, fmt.Errorf("error from tidyDNS server: %s", res.Status) + return 0, fmt.Errorf(errorTidyDNS, res.Status) } var createResp interfaceCreate @@ -296,7 +298,7 @@ func (c *tidyDNSClient) DeleteDHCPInterface(ctx context.Context, interfaceID int _ = Body.Close() }(res.Body) if res.StatusCode != http.StatusOK { - return fmt.Errorf("error from tidyDNS server: %s", res.Status) + return fmt.Errorf(errorTidyDNS, res.Status) } return nil @@ -365,7 +367,7 @@ func (c *tidyDNSClient) CreateRecord(ctx context.Context, zoneID int, info Recor _ = Body.Close() }(res.Body) if res.StatusCode != http.StatusOK { - return 0, fmt.Errorf("error from tidyDNS server: %s", res.Status) + return 0, fmt.Errorf(errorTidyDNS, res.Status) } req, err = http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/=/record_merged?zone_id=%d", c.baseURL, zoneID), nil) @@ -383,7 +385,7 @@ func (c *tidyDNSClient) CreateRecord(ctx context.Context, zoneID int, info Recor _ = Body.Close() }(res.Body) if res.StatusCode != http.StatusOK { - return 0, fmt.Errorf("error from tidyDNS server: %s", res.Status) + return 0, fmt.Errorf(errorTidyDNS, res.Status) } var records []recordList @@ -425,7 +427,7 @@ func (c *tidyDNSClient) UpdateRecord(ctx context.Context, zoneID int, recordID i _ = Body.Close() }(res.Body) if res.StatusCode != http.StatusOK { - return fmt.Errorf("error from tidyDNS server: %s", res.Status) + return fmt.Errorf(errorTidyDNS, res.Status) } return nil @@ -512,7 +514,7 @@ func (c *tidyDNSClient) DeleteRecord(ctx context.Context, zoneID int, recordID i _ = Body.Close() }(res.Body) if res.StatusCode != http.StatusOK { - return fmt.Errorf("error from tidyDNS server: %s", res.Status) + return fmt.Errorf(errorTidyDNS, res.Status) } return nil @@ -534,7 +536,7 @@ func (c *tidyDNSClient) getData(ctx context.Context, url string, value interface _ = Body.Close() }(res.Body) if res.StatusCode != http.StatusOK { - return fmt.Errorf("error from tidyDNS server: %s", res.Status) + return fmt.Errorf(errorTidyDNS, res.Status) } err = json.NewDecoder(res.Body).Decode(value) From d02affa652f07f1020e4589de9a181693603c8da Mon Sep 17 00:00:00 2001 From: Jener Rasmussen Date: Wed, 4 Dec 2024 10:49:44 +0100 Subject: [PATCH 2/9] Update dependencies --- go.mod | 4 ++-- go.sum | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 75aff6a..e61355b 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/neticdk/tidydns-go -go 1.21 +go 1.23 -require github.com/stretchr/testify v1.8.4 +require github.com/stretchr/testify v1.10.0 require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index d096685..7825265 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 4358102471126c57c8e4a75ec03c4fe47b5d9020 Mon Sep 17 00:00:00 2001 From: Jener Rasmussen Date: Wed, 4 Dec 2024 10:53:11 +0100 Subject: [PATCH 3/9] Move common strings to constants --- pkg/tidydns/tidydns.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/tidydns/tidydns.go b/pkg/tidydns/tidydns.go index da72ea8..27c03a7 100644 --- a/pkg/tidydns/tidydns.go +++ b/pkg/tidydns/tidydns.go @@ -87,6 +87,8 @@ const ( ) const errorTidyDNS = "error from tidyDNS server: %s" +const headerContentType = "Content-Type" +const mimeForm = "application/x-www-form-urlencoded" type tidyDNSClient struct { client *http.Client @@ -188,7 +190,7 @@ func (c *tidyDNSClient) CreateDHCPInterface(ctx context.Context, createInfo Crea return 0, err } req.SetBasicAuth(c.username, c.password) - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set(headerContentType, mimeForm) res, err := c.client.Do(req) if err != nil { @@ -260,7 +262,7 @@ func (c *tidyDNSClient) UpdateDHCPInterfaceName(ctx context.Context, interfaceID return 0, err } req.SetBasicAuth(c.username, c.password) - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set(headerContentType, mimeForm) res, err := c.client.Do(req) if err != nil { @@ -357,7 +359,7 @@ func (c *tidyDNSClient) CreateRecord(ctx context.Context, zoneID int, info Recor return 0, err } req.SetBasicAuth(c.username, c.password) - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set(headerContentType, mimeForm) res, err := c.client.Do(req) if err != nil || res == nil { @@ -417,7 +419,7 @@ func (c *tidyDNSClient) UpdateRecord(ctx context.Context, zoneID int, recordID i return err } req.SetBasicAuth(c.username, c.password) - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set(headerContentType, mimeForm) res, err := c.client.Do(req) if err != nil || res == nil { From 22f8c2a0ca307cb2bd8e51ff5cb687fc88472233 Mon Sep 17 00:00:00 2001 From: Jener Rasmussen Date: Wed, 4 Dec 2024 10:56:43 +0100 Subject: [PATCH 4/9] Internal Users API --- pkg/tidydns/tidydns.go | 257 ++++++++++++++++++++++++++++++++++++ pkg/tidydns/tidydns_test.go | 107 +++++++++++++++ pkg/tidydns/types.go | 28 ++++ 3 files changed, 392 insertions(+) diff --git a/pkg/tidydns/tidydns.go b/pkg/tidydns/tidydns.go index 27c03a7..339683a 100644 --- a/pkg/tidydns/tidydns.go +++ b/pkg/tidydns/tidydns.go @@ -9,6 +9,7 @@ import ( "net/url" "strconv" "strings" + "time" ) type TidyDNSClient interface { @@ -26,6 +27,10 @@ type TidyDNSClient interface { FindRecord(ctx context.Context, zoneID int, name string, rType RecordType) ([]*RecordInfo, error) ListRecords(ctx context.Context, zoneID int) ([]*RecordInfo, error) DeleteRecord(ctx context.Context, zoneID int, recordID int) error + CreateInternalUser(ctx context.Context, username string, password string, description string, changePasswordOnFirstLogin bool, authGroup AuthGroup, userAllow []UserAllowID) (UserID, error) + GetInternalUser(ctx context.Context, userID UserID) (*UserInfo, error) + UpdateInternalUser(ctx context.Context, userID UserID, password *string, description *string, authGroup *AuthGroup, userAllow []UserAllowID) error + DeleteInternalUser(ctx context.Context, userID UserID) error } type ZoneInfo struct { @@ -63,9 +68,32 @@ type RecordInfo struct { Location LocationID } +type UserInfo struct { + ModifiedBy string + Description string + ModifiedDate time.Time + Username string + AuthGroup AuthGroup + Name string + PasswdChangedDate time.Time + Id UserID + Groups []UserInfoGroup +} + +type UserInfoGroup struct { + GroupName string + Name string + Notes *string + Id int + Description *string +} + +type UserID int type LocationID int type RecordType int type RecordStatus int +type AuthGroup int +type UserAllowID int //goland:noinspection GoUnusedConst const ( @@ -84,6 +112,9 @@ const ( RecordTypeSSHFP RecordType = 8 RecordTypeTLSA RecordType = 9 RecordTypeCAA RecordType = 10 + + AuthGroupUser AuthGroup = 2 + AuthGroupSuperAdmin AuthGroup = 1 ) const errorTidyDNS = "error from tidyDNS server: %s" @@ -97,6 +128,232 @@ type tidyDNSClient struct { baseURL string } +func (c *tidyDNSClient) CreateInternalUser(ctx context.Context, username string, password string, description string, changePasswordOnFirstLogin bool, authGroup AuthGroup, userAllow []UserAllowID) (UserID, error) { + var userAllowFormatted []string + if len(userAllow) > 0 { + userAllowFormatted = make([]string, 0, len(userAllowFormatted)) + for _, id := range userAllow { + userAllowFormatted = append(userAllowFormatted, strconv.Itoa(int(id))) + } + } else { + userAllowFormatted = []string{""} + } + + var changePasswordOnFirstLoginFormatted string + if changePasswordOnFirstLogin { + changePasswordOnFirstLoginFormatted = "1" + } else { + changePasswordOnFirstLoginFormatted = "0" + } + + data := url.Values{ + "username": {username}, + "epassword": {password}, + "epassword_verify": {password}, + "change_password_on_first_login": {changePasswordOnFirstLoginFormatted}, + "description": {description}, + "auth_group": {strconv.Itoa(int(authGroup))}, + //"tmp_auth_group": {""}, + "user_allow": userAllowFormatted, + } + + req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/=/user/new", c.baseURL), strings.NewReader(data.Encode())) + if err != nil { + return 0, err + } + req.SetBasicAuth(c.username, c.password) + req.Header.Set(headerContentType, mimeForm) + + res, err := c.client.Do(req) + if err != nil { + return 0, err + } + defer func(Body io.ReadCloser) { + _ = Body.Close() + }(res.Body) + if res.StatusCode != http.StatusOK { + bodyBytes, err := io.ReadAll(res.Body) + bodyString := string(bodyBytes) + if err != nil { + return 0, err + } + if strings.Contains(bodyString, fmt.Sprintf("Key (username)=(%s) already exists", username)) { + return 0, fmt.Errorf("username already exists") + } + return 0, fmt.Errorf(errorTidyDNS, res.Status) + } + + var user userCreate + err = json.NewDecoder(res.Body).Decode(&user) + if err != nil { + return 0, err + } + + return UserID(user.Data.Id), nil +} + +func (c *tidyDNSClient) GetInternalUser(ctx context.Context, userID UserID) (*UserInfo, error) { + req, err := http.NewRequestWithContext( + ctx, + "GET", + fmt.Sprintf("%s/=/user/%s", c.baseURL, strconv.Itoa(int(userID))), + nil, + ) + if err != nil { + return nil, err + } + + req.SetBasicAuth(c.username, c.password) + + res, err := c.client.Do(req) + if err != nil { + return nil, err + } + defer func(Body io.ReadCloser) { + _ = Body.Close() + }(res.Body) + if res.StatusCode != http.StatusOK { + return nil, fmt.Errorf(errorTidyDNS, res.Status) + } + + var user userRead + err = json.NewDecoder(res.Body).Decode(&user) + if err != nil { + return nil, err + } + + var groups = make([]UserInfoGroup, 0, len(user.Groups)) + for _, group := range user.Groups { + groups = append(groups, UserInfoGroup{ + GroupName: group.GroupName, + Name: group.Name, + Notes: group.Notes, + Id: group.Id, + Description: group.Description, + }) + } + + modifiedDate, err := time.Parse(time.DateTime, user.ModifiedDate) + if err != nil { + return nil, err + } + + passwordChangedDate, err := time.Parse(time.DateTime, user.PasswdChangedDate) + if err != nil { + return nil, err + } + + var ag AuthGroup + switch user.AuthGroup { + case "User": + ag = AuthGroupUser + case "SuperAdmin": + ag = AuthGroupSuperAdmin + default: + return nil, fmt.Errorf("unknown auth group") + } + + return &UserInfo{ + ModifiedBy: user.ModifiedBy, + Description: user.Description, + ModifiedDate: modifiedDate, + Username: user.Username, + AuthGroup: ag, + Name: user.Name, + PasswdChangedDate: passwordChangedDate, + Id: UserID(user.Id), + Groups: groups, + }, nil +} + +func (c *tidyDNSClient) UpdateInternalUser(ctx context.Context, userID UserID, password *string, description *string, authGroup *AuthGroup, userAllow []UserAllowID) error { + data := url.Values{} + + if password != nil { + data.Set("epassword", *password) + data.Set("epassword_verify", *password) + } + + if description != nil { + data.Set("description", *description) + } + + if authGroup != nil { + data.Set("auth_group", strconv.Itoa(int(*authGroup))) + } + + if userAllow != nil { + var userAllowFormatted []string + if len(userAllow) > 0 { + userAllowFormatted = make([]string, 0, len(userAllowFormatted)) + for _, id := range userAllow { + userAllowFormatted = append(userAllowFormatted, strconv.Itoa(int(id))) + } + } else { + userAllowFormatted = []string{""} + } + data["user_allow"] = userAllowFormatted + } + + req, err := http.NewRequestWithContext( + ctx, + "POST", + fmt.Sprintf("%s/=/user/%s", c.baseURL, strconv.Itoa(int(userID))), + strings.NewReader(data.Encode()), + ) + if err != nil { + return err + } + req.SetBasicAuth(c.username, c.password) + req.Header.Set(headerContentType, mimeForm) + + res, err := c.client.Do(req) + if err != nil { + return err + } + defer func(Body io.ReadCloser) { + _ = Body.Close() + }(res.Body) + if res.StatusCode != http.StatusOK { + return fmt.Errorf(errorTidyDNS, res.Status) + } + + var user userCreate + err = json.NewDecoder(res.Body).Decode(&user) + if err != nil { + return err + } + + return nil +} + +func (c *tidyDNSClient) DeleteInternalUser(ctx context.Context, userID UserID) error { + req, err := http.NewRequestWithContext( + ctx, + "DELETE", + fmt.Sprintf("%s/=/user/%s", c.baseURL, strconv.Itoa(int(userID))), + nil, + ) + if err != nil { + return err + } + + req.SetBasicAuth(c.username, c.password) + + res, err := c.client.Do(req) + if err != nil { + return err + } + defer func(Body io.ReadCloser) { + _ = Body.Close() + }(res.Body) + if res.StatusCode != http.StatusOK { + return fmt.Errorf(errorTidyDNS, res.Status) + } + + return nil +} + func New(baseURL, username, password string) TidyDNSClient { return &tidyDNSClient{ baseURL: baseURL, diff --git a/pkg/tidydns/tidydns_test.go b/pkg/tidydns/tidydns_test.go index c6a89fa..e7c7ef9 100644 --- a/pkg/tidydns/tidydns_test.go +++ b/pkg/tidydns/tidydns_test.go @@ -5,6 +5,7 @@ import ( "net/http" "net/http/httptest" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -100,6 +101,11 @@ const readResponse = `{ "brother_destination": null }` +const userCreateResponse = `{"data":{"id":144},"status":"0"}` +const userReadResponse = `{"modified_by":"jra-api-test","description":"Awesome test user","modified_date":"2024-12-03 14:17:22","username":"jra-test-user","auth_group":"User","name":"jra-test-user","epassword":"*****","passwd_changed_date":"2024-12-03 14:17:22","id":148,"groups":[{"groupname":"user","name":"User","notes":null,"id":2,"description":null}]}` +const userUpdateResponse = `{"status":"0","data":{"id":146}}` +const userDeleteResponse = `{"status":"0"}` + func TestGetSubnetIDs(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Equal(t, "10.68.0.128/26", req.URL.Query().Get("subnet")) @@ -334,6 +340,107 @@ func TestListRecords(t *testing.T) { assert.Equal(t, len(records), 22) } +func TestCreateInternalUser(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + assert.NoError(t, req.ParseForm()) + assert.Equal(t, "/=/user/new", req.URL.Path) + assert.Equal(t, "POST", req.Method) + assert.Equal(t, "test_user", req.PostForm.Get("username")) + assert.Equal(t, "test_password", req.PostForm.Get("epassword")) + assert.Equal(t, "test_password", req.PostForm.Get("epassword_verify")) + assert.Equal(t, "0", req.PostForm.Get("change_password_on_first_login")) + assert.Equal(t, "1", req.PostForm.Get("auth_group")) + assert.Equal(t, "", req.PostForm.Get("user_allow")) + rw.Write([]byte(userCreateResponse)) + })) + defer server.Close() + + c := New(server.URL, "username", "password") + id, err := c.CreateInternalUser( + context.Background(), + "test_user", + "test_password", + "description", + false, + AuthGroupUser, + []UserAllowID{}, + ) + assert.NoError(t, err) + assert.Equal(t, id, UserID(144)) +} + +func TestGetInternalUser(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + assert.Equal(t, "/=/user/144", req.URL.Path) + assert.Equal(t, "GET", req.Method) + rw.Write([]byte(userReadResponse)) + })) + defer server.Close() + + c := New(server.URL, "username", "password") + userInfo, err := c.GetInternalUser(context.Background(), 144) + assert.NoError(t, err) + assert.Equal(t, userInfo.AuthGroup, AuthGroupUser) + assert.Equal(t, userInfo.Description, "Awesome test user") + assert.Equal(t, len(userInfo.Groups), 1) + assert.Equal(t, userInfo.Groups[0].Id, 2) + assert.Equal(t, userInfo.Groups[0].Name, "User") + assert.Nil(t, userInfo.Groups[0].Notes) + assert.Equal(t, userInfo.Groups[0].GroupName, "user") + assert.Nil(t, userInfo.Groups[0].Description) + assert.Equal(t, userInfo.Id, UserID(148)) + assert.Equal(t, userInfo.ModifiedBy, "jra-api-test") + assert.Equal(t, userInfo.ModifiedDate, time.Date(2024, 12, 03, 14, 17, 22, 0, time.UTC)) + assert.Equal(t, userInfo.Name, "jra-test-user") + assert.Equal(t, userInfo.PasswdChangedDate, time.Date(2024, 12, 03, 14, 17, 22, 0, time.UTC)) + assert.Equal(t, userInfo.Username, "jra-test-user") +} + +func toPtr[T any](s T) *T { + return &s +} + +func TestUpdateInternalUser(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + assert.NoError(t, req.ParseForm()) + assert.Equal(t, "/=/user/146", req.URL.Path) + assert.Equal(t, "POST", req.Method) + assert.False(t, req.PostForm.Has("username")) + assert.Equal(t, "test_password", req.PostForm.Get("epassword")) + assert.Equal(t, "test_password", req.PostForm.Get("epassword_verify")) + assert.False(t, req.PostForm.Has("change_password_on_first_login")) + assert.Equal(t, "1", req.PostForm.Get("auth_group")) + assert.Equal(t, "", req.PostForm.Get("user_allow")) + assert.Equal(t, "desc", req.PostForm.Get("description")) + rw.Write([]byte(userUpdateResponse)) + })) + defer server.Close() + + c := New(server.URL, "username", "password") + err := c.UpdateInternalUser( + context.Background(), + UserID(146), + toPtr("test_password"), + toPtr("desc"), + toPtr(AuthGroupUser), + []UserAllowID{}, + ) + assert.NoError(t, err) +} + +func TestDeleteInternalUser(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + assert.Equal(t, "/=/user/144", req.URL.Path) + assert.Equal(t, "DELETE", req.Method) + rw.Write([]byte(userDeleteResponse)) + })) + defer server.Close() + + c := New(server.URL, "username", "password") + err := c.DeleteInternalUser(context.Background(), UserID(144)) + assert.NoError(t, err) +} + const zoneSearchResponse = `[ { "soa_record": null, diff --git a/pkg/tidydns/types.go b/pkg/tidydns/types.go index a1ca23d..b855371 100644 --- a/pkg/tidydns/types.go +++ b/pkg/tidydns/types.go @@ -54,3 +54,31 @@ type recordList struct { Status interface{} `json:"status"` Location LocationID `json:"location_id"` } + +type userCreate struct { + Data struct { + Id int `json:"id"` + } `json:"data"` + Status string `json:"status"` +} + +type userRead struct { + ModifiedBy string `json:"modified_by"` + Description string `json:"description"` + ModifiedDate string `json:"modified_date"` + Username string `json:"username"` + AuthGroup string `json:"auth_group"` + Name string `json:"name"` + Epassword string `json:"epassword"` + PasswdChangedDate string `json:"passwd_changed_date"` + Id int `json:"id"` + Groups []userGroup `json:"groups"` +} + +type userGroup struct { + GroupName string `json:"groupname"` + Name string `json:"name"` + Notes *string `json:"notes,omitempty"` + Id int `json:"id"` + Description *string `json:"description,omitempty"` +} From 6e2b129ad1415538baffffe094c209db2c42e2f6 Mon Sep 17 00:00:00 2001 From: Jener Rasmussen Date: Wed, 4 Dec 2024 11:00:21 +0100 Subject: [PATCH 5/9] Explicitly ignore write error in tests --- pkg/tidydns/tidydns_test.go | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/pkg/tidydns/tidydns_test.go b/pkg/tidydns/tidydns_test.go index e7c7ef9..49f9356 100644 --- a/pkg/tidydns/tidydns_test.go +++ b/pkg/tidydns/tidydns_test.go @@ -110,7 +110,7 @@ func TestGetSubnetIDs(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Equal(t, "10.68.0.128/26", req.URL.Query().Get("subnet")) assert.Equal(t, "GET", req.Method) - rw.Write([]byte(subnetResponse)) + _, _ = rw.Write([]byte(subnetResponse)) })) defer server.Close() @@ -126,7 +126,7 @@ func TestGetFreeIP(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Contains(t, req.URL.Path, "1185") assert.Equal(t, "GET", req.Method) - rw.Write([]byte(freeIPResponse)) + _, _ = rw.Write([]byte(freeIPResponse)) })) defer server.Close() @@ -139,7 +139,7 @@ func TestGetFreeIP(t *testing.T) { func TestCreateDHCPInterfaceV1(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Equal(t, "POST", req.Method) - rw.Write([]byte(createResponseV1)) + _, _ = rw.Write([]byte(createResponseV1)) })) defer server.Close() @@ -158,7 +158,7 @@ func TestCreateDHCPInterfaceV1(t *testing.T) { func TestCreateDHCPInterfaceV2(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Equal(t, "POST", req.Method) - rw.Write([]byte(createResponseV2)) + _, _ = rw.Write([]byte(createResponseV2)) })) defer server.Close() @@ -178,7 +178,7 @@ func TestReadDHCPInterface(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Equal(t, "30641", req.URL.Query().Get("id")) assert.Equal(t, "GET", req.Method) - rw.Write([]byte(readResponse)) + _, _ = rw.Write([]byte(readResponse)) })) defer server.Close() @@ -193,7 +193,7 @@ func TestUpdateDHCPInterfaceName(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Contains(t, req.URL.Path, "30641") assert.Equal(t, "POST", req.Method) - rw.Write([]byte(createResponseV1)) + _, _ = rw.Write([]byte(createResponseV1)) })) defer server.Close() @@ -207,7 +207,7 @@ func TestDeleteDHCPInterface(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Contains(t, req.URL.Path, "30641") assert.Equal(t, "DELETE", req.Method) - rw.Write([]byte(createResponseV1)) + _, _ = rw.Write([]byte(createResponseV1)) })) defer server.Close() @@ -220,7 +220,7 @@ func TestFindZoneID(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Contains(t, req.URL.Query().Get("name"), "hackerdays.trifork.dev") assert.Equal(t, "GET", req.Method) - rw.Write([]byte(zoneSearchResponse)) + _, _ = rw.Write([]byte(zoneSearchResponse)) })) defer server.Close() @@ -232,7 +232,7 @@ func TestFindZoneID(t *testing.T) { func TestCreateRecord(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - rw.Write([]byte(readRecordListResponse)) + _, _ = rw.Write([]byte(readRecordListResponse)) })) defer server.Close() @@ -253,7 +253,7 @@ func TestReadRecord(t *testing.T) { assert.Contains(t, req.URL.Path, "2861") assert.Contains(t, req.URL.Path, "64694") assert.Equal(t, "GET", req.Method) - rw.Write([]byte(readRecordResponse)) + _, _ = rw.Write([]byte(readRecordResponse)) })) defer server.Close() @@ -272,7 +272,7 @@ func TestDeleteRecord(t *testing.T) { assert.Contains(t, req.URL.Path, "2861") assert.Contains(t, req.URL.Path, "64694") assert.Equal(t, "DELETE", req.Method) - rw.Write([]byte(createResponse)) + _, _ = rw.Write([]byte(createResponse)) })) defer server.Close() @@ -284,7 +284,7 @@ func TestDeleteRecord(t *testing.T) { func TestUpdateRecord(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Equal(t, "POST", req.Method) - rw.Write([]byte(readRecordListResponse)) + _, _ = rw.Write([]byte(readRecordListResponse)) })) defer server.Close() @@ -302,7 +302,7 @@ func TestFindRecord(t *testing.T) { assert.Equal(t, "prod1-api.trifork.shared", req.URL.Query().Get("name")) assert.Equal(t, "2861", req.URL.Query().Get("zone")) assert.Equal(t, "GET", req.Method) - rw.Write([]byte(findRecordResponse)) + _, _ = rw.Write([]byte(findRecordResponse)) })) defer server.Close() @@ -316,7 +316,7 @@ func TestFindRecord(t *testing.T) { func TestListZones(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Equal(t, "GET", req.Method) - rw.Write([]byte(listZonesResponse)) + _, _ = rw.Write([]byte(listZonesResponse)) })) defer server.Close() @@ -330,7 +330,7 @@ func TestListRecords(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Equal(t, "2861", req.URL.Query().Get("zone_id")) assert.Equal(t, "GET", req.Method) - rw.Write([]byte(listRecordsResponse)) + _, _ = rw.Write([]byte(listRecordsResponse)) })) defer server.Close() @@ -351,7 +351,7 @@ func TestCreateInternalUser(t *testing.T) { assert.Equal(t, "0", req.PostForm.Get("change_password_on_first_login")) assert.Equal(t, "1", req.PostForm.Get("auth_group")) assert.Equal(t, "", req.PostForm.Get("user_allow")) - rw.Write([]byte(userCreateResponse)) + _, _ = rw.Write([]byte(userCreateResponse)) })) defer server.Close() @@ -373,7 +373,7 @@ func TestGetInternalUser(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Equal(t, "/=/user/144", req.URL.Path) assert.Equal(t, "GET", req.Method) - rw.Write([]byte(userReadResponse)) + _, _ = rw.Write([]byte(userReadResponse)) })) defer server.Close() @@ -412,7 +412,7 @@ func TestUpdateInternalUser(t *testing.T) { assert.Equal(t, "1", req.PostForm.Get("auth_group")) assert.Equal(t, "", req.PostForm.Get("user_allow")) assert.Equal(t, "desc", req.PostForm.Get("description")) - rw.Write([]byte(userUpdateResponse)) + _, _ = rw.Write([]byte(userUpdateResponse)) })) defer server.Close() @@ -432,7 +432,7 @@ func TestDeleteInternalUser(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { assert.Equal(t, "/=/user/144", req.URL.Path) assert.Equal(t, "DELETE", req.Method) - rw.Write([]byte(userDeleteResponse)) + _, _ = rw.Write([]byte(userDeleteResponse)) })) defer server.Close() From 1ba43ba357ab7aa0ad442cad2c28594c1d8eb6ca Mon Sep 17 00:00:00 2001 From: Jener Rasmussen Date: Wed, 4 Dec 2024 11:16:16 +0100 Subject: [PATCH 6/9] Fix broken test af AuthGroup was corrected --- pkg/tidydns/tidydns_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/tidydns/tidydns_test.go b/pkg/tidydns/tidydns_test.go index 49f9356..7a50a56 100644 --- a/pkg/tidydns/tidydns_test.go +++ b/pkg/tidydns/tidydns_test.go @@ -349,7 +349,7 @@ func TestCreateInternalUser(t *testing.T) { assert.Equal(t, "test_password", req.PostForm.Get("epassword")) assert.Equal(t, "test_password", req.PostForm.Get("epassword_verify")) assert.Equal(t, "0", req.PostForm.Get("change_password_on_first_login")) - assert.Equal(t, "1", req.PostForm.Get("auth_group")) + assert.Equal(t, "2", req.PostForm.Get("auth_group")) assert.Equal(t, "", req.PostForm.Get("user_allow")) _, _ = rw.Write([]byte(userCreateResponse)) })) @@ -409,7 +409,7 @@ func TestUpdateInternalUser(t *testing.T) { assert.Equal(t, "test_password", req.PostForm.Get("epassword")) assert.Equal(t, "test_password", req.PostForm.Get("epassword_verify")) assert.False(t, req.PostForm.Has("change_password_on_first_login")) - assert.Equal(t, "1", req.PostForm.Get("auth_group")) + assert.Equal(t, "2", req.PostForm.Get("auth_group")) assert.Equal(t, "", req.PostForm.Get("user_allow")) assert.Equal(t, "desc", req.PostForm.Get("description")) _, _ = rw.Write([]byte(userUpdateResponse)) From 7b5d42d726b9bf22133aae712230e3f6e6d8ccec Mon Sep 17 00:00:00 2001 From: Jener Rasmussen Date: Wed, 4 Dec 2024 14:12:39 +0100 Subject: [PATCH 7/9] Standardize closing of HTTP response bodies --- pkg/tidydns/tidydns.go | 66 ++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 45 deletions(-) diff --git a/pkg/tidydns/tidydns.go b/pkg/tidydns/tidydns.go index 339683a..4d386a4 100644 --- a/pkg/tidydns/tidydns.go +++ b/pkg/tidydns/tidydns.go @@ -168,9 +168,7 @@ func (c *tidyDNSClient) CreateInternalUser(ctx context.Context, username string, if err != nil { return 0, err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { bodyBytes, err := io.ReadAll(res.Body) bodyString := string(bodyBytes) @@ -209,9 +207,7 @@ func (c *tidyDNSClient) GetInternalUser(ctx context.Context, userID UserID) (*Us if err != nil { return nil, err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return nil, fmt.Errorf(errorTidyDNS, res.Status) } @@ -311,9 +307,7 @@ func (c *tidyDNSClient) UpdateInternalUser(ctx context.Context, userID UserID, p if err != nil { return err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return fmt.Errorf(errorTidyDNS, res.Status) } @@ -344,9 +338,7 @@ func (c *tidyDNSClient) DeleteInternalUser(ctx context.Context, userID UserID) e if err != nil { return err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return fmt.Errorf(errorTidyDNS, res.Status) } @@ -363,6 +355,12 @@ func New(baseURL, username, password string) TidyDNSClient { } } +func closeResponse(resp *http.Response) { + if resp != nil { + _ = resp.Body.Close() + } +} + func (c *tidyDNSClient) GetSubnetIDs(ctx context.Context, subnetCIDR string) (*SubnetIDs, error) { req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/=/dhcp_subnet?subnet=%s", c.baseURL, subnetCIDR), nil) if err != nil { @@ -375,9 +373,7 @@ func (c *tidyDNSClient) GetSubnetIDs(ctx context.Context, subnetCIDR string) (*S if err != nil { return nil, err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return nil, fmt.Errorf(errorTidyDNS, res.Status) } @@ -415,9 +411,7 @@ func (c *tidyDNSClient) GetFreeIP(ctx context.Context, subnetID int) (string, er if err != nil { return "", err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return "", fmt.Errorf(errorTidyDNS, res.Status) } @@ -453,9 +447,7 @@ func (c *tidyDNSClient) CreateDHCPInterface(ctx context.Context, createInfo Crea if err != nil { return 0, err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { bodyBytes, err := io.ReadAll(res.Body) @@ -490,9 +482,7 @@ func (c *tidyDNSClient) ReadDHCPInterface(ctx context.Context, interfaceID int) if err != nil { return nil, err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return nil, fmt.Errorf(errorTidyDNS, res.Status) } @@ -525,9 +515,7 @@ func (c *tidyDNSClient) UpdateDHCPInterfaceName(ctx context.Context, interfaceID if err != nil { return 0, err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return 0, fmt.Errorf(errorTidyDNS, res.Status) } @@ -553,9 +541,7 @@ func (c *tidyDNSClient) DeleteDHCPInterface(ctx context.Context, interfaceID int if err != nil { return err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return fmt.Errorf(errorTidyDNS, res.Status) } @@ -622,9 +608,7 @@ func (c *tidyDNSClient) CreateRecord(ctx context.Context, zoneID int, info Recor if err != nil || res == nil { return 0, err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return 0, fmt.Errorf(errorTidyDNS, res.Status) } @@ -640,9 +624,7 @@ func (c *tidyDNSClient) CreateRecord(ctx context.Context, zoneID int, info Recor if err != nil || res == nil { return 0, err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return 0, fmt.Errorf(errorTidyDNS, res.Status) } @@ -682,9 +664,7 @@ func (c *tidyDNSClient) UpdateRecord(ctx context.Context, zoneID int, recordID i if err != nil || res == nil { return err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return fmt.Errorf(errorTidyDNS, res.Status) } @@ -769,9 +749,7 @@ func (c *tidyDNSClient) DeleteRecord(ctx context.Context, zoneID int, recordID i if err != nil || res == nil { return err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return fmt.Errorf(errorTidyDNS, res.Status) } @@ -791,9 +769,7 @@ func (c *tidyDNSClient) getData(ctx context.Context, url string, value interface if err != nil || res == nil { return err } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(res.Body) + defer closeResponse(res) if res.StatusCode != http.StatusOK { return fmt.Errorf(errorTidyDNS, res.Status) } From f3e89705b58756b42e4baea37af900e6df125d05 Mon Sep 17 00:00:00 2001 From: Jener Rasmussen Date: Wed, 4 Dec 2024 14:31:24 +0100 Subject: [PATCH 8/9] Remove redundant struct definition --- pkg/tidydns/tidydns.go | 23 ++++++----------------- pkg/tidydns/types.go | 28 ++++++++++------------------ 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/pkg/tidydns/tidydns.go b/pkg/tidydns/tidydns.go index 4d386a4..b2da17e 100644 --- a/pkg/tidydns/tidydns.go +++ b/pkg/tidydns/tidydns.go @@ -81,11 +81,11 @@ type UserInfo struct { } type UserInfoGroup struct { - GroupName string - Name string - Notes *string - Id int - Description *string + GroupName string `json:"groupname"` + Name string `json:"name"` + Notes *string `json:"notes,omitempty"` + Id int `json:"id"` + Description *string `json:"description,omitempty"` } type UserID int @@ -218,17 +218,6 @@ func (c *tidyDNSClient) GetInternalUser(ctx context.Context, userID UserID) (*Us return nil, err } - var groups = make([]UserInfoGroup, 0, len(user.Groups)) - for _, group := range user.Groups { - groups = append(groups, UserInfoGroup{ - GroupName: group.GroupName, - Name: group.Name, - Notes: group.Notes, - Id: group.Id, - Description: group.Description, - }) - } - modifiedDate, err := time.Parse(time.DateTime, user.ModifiedDate) if err != nil { return nil, err @@ -258,7 +247,7 @@ func (c *tidyDNSClient) GetInternalUser(ctx context.Context, userID UserID) (*Us Name: user.Name, PasswdChangedDate: passwordChangedDate, Id: UserID(user.Id), - Groups: groups, + Groups: user.Groups, }, nil } diff --git a/pkg/tidydns/types.go b/pkg/tidydns/types.go index b855371..c4432c7 100644 --- a/pkg/tidydns/types.go +++ b/pkg/tidydns/types.go @@ -63,22 +63,14 @@ type userCreate struct { } type userRead struct { - ModifiedBy string `json:"modified_by"` - Description string `json:"description"` - ModifiedDate string `json:"modified_date"` - Username string `json:"username"` - AuthGroup string `json:"auth_group"` - Name string `json:"name"` - Epassword string `json:"epassword"` - PasswdChangedDate string `json:"passwd_changed_date"` - Id int `json:"id"` - Groups []userGroup `json:"groups"` -} - -type userGroup struct { - GroupName string `json:"groupname"` - Name string `json:"name"` - Notes *string `json:"notes,omitempty"` - Id int `json:"id"` - Description *string `json:"description,omitempty"` + ModifiedBy string `json:"modified_by"` + Description string `json:"description"` + ModifiedDate string `json:"modified_date"` + Username string `json:"username"` + AuthGroup string `json:"auth_group"` + Name string `json:"name"` + Epassword string `json:"epassword"` + PasswdChangedDate string `json:"passwd_changed_date"` + Id int `json:"id"` + Groups []UserInfoGroup `json:"groups"` } From 8af455f958157e535c862e83bfb021205b0e0e32 Mon Sep 17 00:00:00 2001 From: Jener Rasmussen Date: Wed, 4 Dec 2024 14:53:15 +0100 Subject: [PATCH 9/9] Refactor url building --- pkg/tidydns/tidydns.go | 132 +++++++++++++++++++++++++++++++++++------ 1 file changed, 113 insertions(+), 19 deletions(-) diff --git a/pkg/tidydns/tidydns.go b/pkg/tidydns/tidydns.go index b2da17e..78f52a6 100644 --- a/pkg/tidydns/tidydns.go +++ b/pkg/tidydns/tidydns.go @@ -157,7 +157,13 @@ func (c *tidyDNSClient) CreateInternalUser(ctx context.Context, username string, "user_allow": userAllowFormatted, } - req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/=/user/new", c.baseURL), strings.NewReader(data.Encode())) + newUserUrl := fmt.Sprintf("%s/=/user/new", c.baseURL) + req, err := http.NewRequestWithContext( + ctx, + "POST", + newUserUrl, + strings.NewReader(data.Encode()), + ) if err != nil { return 0, err } @@ -191,10 +197,11 @@ func (c *tidyDNSClient) CreateInternalUser(ctx context.Context, username string, } func (c *tidyDNSClient) GetInternalUser(ctx context.Context, userID UserID) (*UserInfo, error) { + userLookupUrl := fmt.Sprintf("%s/=/user/%s", c.baseURL, strconv.Itoa(int(userID))) req, err := http.NewRequestWithContext( ctx, "GET", - fmt.Sprintf("%s/=/user/%s", c.baseURL, strconv.Itoa(int(userID))), + userLookupUrl, nil, ) if err != nil { @@ -280,10 +287,11 @@ func (c *tidyDNSClient) UpdateInternalUser(ctx context.Context, userID UserID, p data["user_allow"] = userAllowFormatted } + userLookupUrl := fmt.Sprintf("%s/=/user/%s", c.baseURL, strconv.Itoa(int(userID))) req, err := http.NewRequestWithContext( ctx, "POST", - fmt.Sprintf("%s/=/user/%s", c.baseURL, strconv.Itoa(int(userID))), + userLookupUrl, strings.NewReader(data.Encode()), ) if err != nil { @@ -311,10 +319,11 @@ func (c *tidyDNSClient) UpdateInternalUser(ctx context.Context, userID UserID, p } func (c *tidyDNSClient) DeleteInternalUser(ctx context.Context, userID UserID) error { + userLookupUrl := fmt.Sprintf("%s/=/user/%s", c.baseURL, strconv.Itoa(int(userID))) req, err := http.NewRequestWithContext( ctx, "DELETE", - fmt.Sprintf("%s/=/user/%s", c.baseURL, strconv.Itoa(int(userID))), + userLookupUrl, nil, ) if err != nil { @@ -351,7 +360,13 @@ func closeResponse(resp *http.Response) { } func (c *tidyDNSClient) GetSubnetIDs(ctx context.Context, subnetCIDR string) (*SubnetIDs, error) { - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/=/dhcp_subnet?subnet=%s", c.baseURL, subnetCIDR), nil) + dhcpSubnetUrl := fmt.Sprintf("%s/=/dhcp_subnet?subnet=%s", c.baseURL, subnetCIDR) + req, err := http.NewRequestWithContext( + ctx, + "GET", + dhcpSubnetUrl, + nil, + ) if err != nil { return nil, err } @@ -389,7 +404,13 @@ func (c *tidyDNSClient) GetSubnetIDs(ctx context.Context, subnetCIDR string) (*S } func (c *tidyDNSClient) GetFreeIP(ctx context.Context, subnetID int) (string, error) { - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/=/dhcp_subnet_free_ip/%d", c.baseURL, subnetID), nil) + dhcpFreeIPUrl := fmt.Sprintf("%s/=/dhcp_subnet_free_ip/%d", c.baseURL, subnetID) + req, err := http.NewRequestWithContext( + ctx, + "GET", + dhcpFreeIPUrl, + nil, + ) if err != nil { return "", err } @@ -425,7 +446,13 @@ func (c *tidyDNSClient) CreateDHCPInterface(ctx context.Context, createInfo Crea var checkstring = fmt.Sprintf("Key (destination)=(%s) already exists", createInfo.InterfaceIP) - req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/=/dhcp_interface//new", c.baseURL), strings.NewReader(data.Encode())) + dhcpInterfaceNewUrl := fmt.Sprintf("%s/=/dhcp_interface//new", c.baseURL) + req, err := http.NewRequestWithContext( + ctx, + "POST", + dhcpInterfaceNewUrl, + strings.NewReader(data.Encode()), + ) if err != nil { return 0, err } @@ -460,7 +487,13 @@ func (c *tidyDNSClient) CreateDHCPInterface(ctx context.Context, createInfo Crea } func (c *tidyDNSClient) ReadDHCPInterface(ctx context.Context, interfaceID int) (*InterfaceInfo, error) { - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/=/dhcp_interface/?id=%d", c.baseURL, interfaceID), nil) + dhcpInterfaceReadUrl := fmt.Sprintf("%s/=/dhcp_interface/?id=%d", c.baseURL, interfaceID) + req, err := http.NewRequestWithContext( + ctx, + "GET", + dhcpInterfaceReadUrl, + nil, + ) if err != nil { return nil, err } @@ -493,7 +526,13 @@ func (c *tidyDNSClient) UpdateDHCPInterfaceName(ctx context.Context, interfaceID "name": {interfaceName}, } - req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/=/dhcp_interface//%d", c.baseURL, interfaceID), strings.NewReader(data.Encode())) + dhcpInterfaceLookupUrl := fmt.Sprintf("%s/=/dhcp_interface//%d", c.baseURL, interfaceID) + req, err := http.NewRequestWithContext( + ctx, + "POST", + dhcpInterfaceLookupUrl, + strings.NewReader(data.Encode()), + ) if err != nil { return 0, err } @@ -519,7 +558,13 @@ func (c *tidyDNSClient) UpdateDHCPInterfaceName(ctx context.Context, interfaceID } func (c *tidyDNSClient) DeleteDHCPInterface(ctx context.Context, interfaceID int) error { - req, err := http.NewRequestWithContext(ctx, "DELETE", fmt.Sprintf("%s/=/dhcp_interface/%d", c.baseURL, interfaceID), nil) + dhcpInterfaceLookupUrl := fmt.Sprintf("%s/=/dhcp_interface/%d", c.baseURL, interfaceID) + req, err := http.NewRequestWithContext( + ctx, + "DELETE", + dhcpInterfaceLookupUrl, + nil, + ) if err != nil { return err } @@ -540,7 +585,12 @@ func (c *tidyDNSClient) DeleteDHCPInterface(ctx context.Context, interfaceID int func (c *tidyDNSClient) ListZones(ctx context.Context) ([]*ZoneInfo, error) { var zones []zoneInfo - err := c.getData(ctx, fmt.Sprintf("%s/=/zone?type=json", c.baseURL), &zones) + zoneListUrl := fmt.Sprintf("%s/=/zone?type=json", c.baseURL) + err := c.getData( + ctx, + zoneListUrl, + &zones, + ) if err != nil { return nil, err } @@ -557,7 +607,12 @@ func (c *tidyDNSClient) ListZones(ctx context.Context) ([]*ZoneInfo, error) { func (c *tidyDNSClient) FindZoneID(ctx context.Context, name string) (int, error) { var zones []zoneInfo - err := c.getData(ctx, fmt.Sprintf("%s/=/zone?type=json&name=%s", c.baseURL, name), &zones) + zoneLookupUrl := fmt.Sprintf("%s/=/zone?type=json&name=%s", c.baseURL, name) + err := c.getData( + ctx, + zoneLookupUrl, + &zones, + ) if err != nil { return 0, err } @@ -586,7 +641,13 @@ func (c *tidyDNSClient) CreateRecord(ctx context.Context, zoneID int, info Recor "location_id": {strconv.Itoa(int(info.Location))}, } - req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/=/record/new/%d", c.baseURL, zoneID), strings.NewReader(data.Encode())) + newRecordUrl := fmt.Sprintf("%s/=/record/new/%d", c.baseURL, zoneID) + req, err := http.NewRequestWithContext( + ctx, + "POST", + newRecordUrl, + strings.NewReader(data.Encode()), + ) if err != nil { return 0, err } @@ -602,7 +663,13 @@ func (c *tidyDNSClient) CreateRecord(ctx context.Context, zoneID int, info Recor return 0, fmt.Errorf(errorTidyDNS, res.Status) } - req, err = http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/=/record_merged?zone_id=%d", c.baseURL, zoneID), nil) + recordMergeUrl := fmt.Sprintf("%s/=/record_merged?zone_id=%d", c.baseURL, zoneID) + req, err = http.NewRequestWithContext( + ctx, + "GET", + recordMergeUrl, + nil, + ) if err != nil { return 0, err } @@ -642,7 +709,13 @@ func (c *tidyDNSClient) UpdateRecord(ctx context.Context, zoneID int, recordID i "location_id": {strconv.Itoa(int(info.Location))}, } - req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/=/record/%d/%d", c.baseURL, recordID, zoneID), strings.NewReader(data.Encode())) + zoneLookupUrl := fmt.Sprintf("%s/=/record/%d/%d", c.baseURL, recordID, zoneID) + req, err := http.NewRequestWithContext( + ctx, + "POST", + zoneLookupUrl, + strings.NewReader(data.Encode()), + ) if err != nil { return err } @@ -663,7 +736,12 @@ func (c *tidyDNSClient) UpdateRecord(ctx context.Context, zoneID int, recordID i func (c *tidyDNSClient) FindRecord(ctx context.Context, zoneID int, name string, rType RecordType) ([]*RecordInfo, error) { var records []recordList - err := c.getData(ctx, fmt.Sprintf("%s/=/record?type=json&zone=%d&name=%s", c.baseURL, zoneID, name), &records) + recordLookupUrl := fmt.Sprintf("%s/=/record?type=json&zone=%d&name=%s", c.baseURL, zoneID, name) + err := c.getData( + ctx, + recordLookupUrl, + &records, + ) if err != nil { return nil, err } @@ -687,7 +765,12 @@ func (c *tidyDNSClient) FindRecord(ctx context.Context, zoneID int, name string, func (c *tidyDNSClient) ListRecords(ctx context.Context, zoneID int) ([]*RecordInfo, error) { var records []recordList - err := c.getData(ctx, fmt.Sprintf("%s/=/record_merged?type=json&zone_id=%d&showall=1", c.baseURL, zoneID), &records) + recordMergeUrl := fmt.Sprintf("%s/=/record_merged?type=json&zone_id=%d&showall=1", c.baseURL, zoneID) + err := c.getData( + ctx, + recordMergeUrl, + &records, + ) if err != nil { return nil, err } @@ -709,7 +792,12 @@ func (c *tidyDNSClient) ListRecords(ctx context.Context, zoneID int) ([]*RecordI func (c *tidyDNSClient) ReadRecord(ctx context.Context, zoneID int, recordID int) (*RecordInfo, error) { var record recordRead - err := c.getData(ctx, fmt.Sprintf("%s/=/record/%d/%d", c.baseURL, zoneID, recordID), &record) + recordLookupUrl := fmt.Sprintf("%s/=/record/%d/%d", c.baseURL, zoneID, recordID) + err := c.getData( + ctx, + recordLookupUrl, + &record, + ) if err != nil { return nil, err } @@ -727,7 +815,13 @@ func (c *tidyDNSClient) ReadRecord(ctx context.Context, zoneID int, recordID int } func (c *tidyDNSClient) DeleteRecord(ctx context.Context, zoneID int, recordID int) error { - req, err := http.NewRequestWithContext(ctx, "DELETE", fmt.Sprintf("%s/=/record/%d/%d", c.baseURL, recordID, zoneID), nil) + recordLookupUrl := fmt.Sprintf("%s/=/record/%d/%d", c.baseURL, recordID, zoneID) + req, err := http.NewRequestWithContext( + ctx, + "DELETE", + recordLookupUrl, + nil, + ) if err != nil { return err }