Skip to content

Commit

Permalink
Merge pull request #76 from vinyldns/global-rs-search
Browse files Browse the repository at this point in the history
add RecordSetsGlobalListAll method
  • Loading branch information
mdb authored Sep 17, 2020
2 parents 88487d4 + 1b6b7f2 commit 148a5f6
Show file tree
Hide file tree
Showing 9 changed files with 302 additions and 7 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
VERSION=0.9.12
VERSION=0.9.13
SOURCE?=./...
VINYLDNS_REPO=github.com/vinyldns/vinyldns
VINYLDNS_VERSION=0.9.3
VINYLDNS_VERSION=0.9.5

all: check-fmt test build integration stop-api validate-version install

Expand Down
42 changes: 42 additions & 0 deletions vinyldns/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ func recordSetsListEP(c *Client, zoneID string, f ListFilter) string {
return concatStrs("", recordSetsEP(c, zoneID), query)
}

func recordSetsGlobalListEP(c *Client, f GlobalListFilter) string {
query := buildGlobalListQuery(f)
base := concatStrs("", c.Host, "/recordsets")

return concatStrs("", base, query)
}

func recordSetEP(c *Client, zoneID, recordSetID string) string {
return concatStrs("", recordSetsEP(c, zoneID), "/", recordSetID)
}
Expand Down Expand Up @@ -125,3 +132,38 @@ func buildQuery(f ListFilter, nameFilterName string) string {

return query + strings.Join(params, "&")
}

func buildGlobalListQuery(f GlobalListFilter) string {
params := []string{}
query := "?"

if f.RecordNameFilter != "" {
params = append(params, fmt.Sprintf("%s=%s", "recordNameFilter", f.RecordNameFilter))
}

if f.RecordTypeFilter != "" {
params = append(params, fmt.Sprintf("%s=%s", "recordTypeFilter", f.RecordTypeFilter))
}

if f.RecordOwnerGroupFilter != "" {
params = append(params, fmt.Sprintf("%s=%s", "recordOwnerGroupFilter", f.RecordOwnerGroupFilter))
}

if f.NameSort != "" {
params = append(params, fmt.Sprintf("%s=%s", "nameSort", f.NameSort))
}

if f.StartFrom != "" {
params = append(params, fmt.Sprintf("startFrom=%s", f.StartFrom))
}

if f.MaxItems != 0 {
params = append(params, fmt.Sprintf("maxItems=%d", f.MaxItems))
}

if len(params) == 0 {
query = ""
}

return query + strings.Join(params, "&")
}
73 changes: 73 additions & 0 deletions vinyldns/endpoints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,54 @@ func TestRecordSetsListEP(t *testing.T) {
}
}

func TestRecordSetsGlobalListEP(t *testing.T) {
rs := recordSetsGlobalListEP(c, GlobalListFilter{})
expected := "http://host.com/recordsets"
msg := "recordSetsGlobalListEP should return the right endpoint"

if rs != expected {
fmt.Printf("Expected: %s", expected)
fmt.Printf("Actual: %s", rs)
t.Error(msg)
}

rs = recordSetsGlobalListEP(c, GlobalListFilter{
StartFrom: "nextplease",
})
expected = "http://host.com/recordsets?startFrom=nextplease"

if rs != expected {
fmt.Printf("Expected: %s", expected)
fmt.Printf("Actual: %s", rs)
t.Error(msg)
}

rs = recordSetsGlobalListEP(c, GlobalListFilter{
StartFrom: "nextplease",
MaxItems: 99,
})
expected = "http://host.com/recordsets?startFrom=nextplease&maxItems=99"

if rs != expected {
fmt.Printf("Expected: %s", expected)
fmt.Printf("Actual: %s", rs)
t.Error(msg)
}

rs = recordSetsGlobalListEP(c, GlobalListFilter{
RecordNameFilter: "foo",
StartFrom: "nextplease",
MaxItems: 99,
})
expected = "http://host.com/recordsets?recordNameFilter=foo&startFrom=nextplease&maxItems=99"

if rs != expected {
fmt.Printf("Expected: %s", expected)
fmt.Printf("Actual: %s", rs)
t.Error(msg)
}
}

func TestRecordSetEP(t *testing.T) {
rs := recordSetEP(c, "123", "456")
expected := "http://host.com/zones/123/recordsets/456"
Expand Down Expand Up @@ -354,3 +402,28 @@ func TestBuildQueryWithNoQuery(t *testing.T) {
t.Error("buildQuery should return the right string")
}
}

func TestBuildGlobalListQuery(t *testing.T) {
query := buildGlobalListQuery(GlobalListFilter{
MaxItems: 1,
RecordNameFilter: "foo",
})
expected := "?recordNameFilter=foo&maxItems=1"

if query != expected {
fmt.Printf("Expected: %s", expected)
fmt.Printf("Actual: %s", query)
t.Error("buildGlobalListQuery should return the right string")
}
}

func TestBuildGlobalListQueryWithNoQuery(t *testing.T) {
query := buildGlobalListQuery(GlobalListFilter{})
expected := ""

if query != expected {
fmt.Printf("Expected: %s", expected)
fmt.Printf("Actual: %s", query)
t.Error("buildGlobalListQuery should return the right string")
}
}
34 changes: 34 additions & 0 deletions vinyldns/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,40 @@ func TestRecordSetsListAllIntegrationFilterForNonexistentName(t *testing.T) {
}
}

func TestRecordSetsGlobalListAllIntegrationFilterForExistentName(t *testing.T) {
c := client()
rName := "foo"

records, err := c.RecordSetsGlobalListAll(GlobalListFilter{
RecordNameFilter: "*" + rName + "*",
})
if err != nil {
t.Error(err)
}

if len(records) < 1 {
t.Error(fmt.Sprintf("Expected RecordSetsGlobalListAll for records named '%s' to yield results", rName))
}

if records[0].Name != rName {
t.Error(fmt.Sprintf("Expected RecordSetsGlobalListAll for records named '%s' to return the matching record", rName))
}
}

func TestRecordSetsGlobalListAllIntegrationFilterForNonexistentName(t *testing.T) {
c := client()
records, err := c.RecordSetsGlobalListAll(GlobalListFilter{
RecordNameFilter: "thisdoesnotexist",
})
if err != nil {
t.Error(err)
}

if len(records) > 0 {
t.Error("Expected RecordSetsListAll for records named 'thisdoesnotexist' to yield no results")
}
}

func TestRecordSetDeleteIntegration(t *testing.T) {
c := client()
zs, err := c.ZonesListAll(ListFilter{})
Expand Down
30 changes: 28 additions & 2 deletions vinyldns/recordsets.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ func (c *Client) RecordSets(id string) ([]RecordSet, error) {
return recordSets, nil
}

// RecordSetsListAll retrieves the complete list of record sets with the ListFilter criteria passed.
// Handles paging through results on the user's behalf.
// RecordSetsListAll retrieves the complete list of record sets from
// the specified zone with the ListFilter criteria passed.
// It handles paging through results on the user's behalf.
func (c *Client) RecordSetsListAll(zoneID string, filter ListFilter) ([]RecordSet, error) {
if filter.MaxItems > 100 {
return nil, fmt.Errorf("MaxItems must be between 1 and 100")
Expand All @@ -115,6 +116,31 @@ func (c *Client) RecordSetsListAll(zoneID string, filter ListFilter) ([]RecordSe
}
}

// RecordSetsGlobalListAll retrieves the complete list of record sets with the
// GlobalListFilter criteria passed, across all zones.
// It handles paging through results on the user's behalf.
func (c *Client) RecordSetsGlobalListAll(filter GlobalListFilter) ([]RecordSet, error) {
if filter.MaxItems > 100 {
return nil, fmt.Errorf("MaxItems must be between 1 and 100")
}

rss := []RecordSet{}

for {
resp, err := c.recordSetsGlobalList(filter)
if err != nil {
return nil, err
}

rss = append(rss, resp.RecordSets...)
filter.StartFrom = resp.NextID

if len(filter.StartFrom) == 0 {
return rss, nil
}
}
}

// RecordSet retrieves the record matching the Zone ID and RecordSet ID it's passed.
func (c *Client) RecordSet(zoneID, recordSetID string) (RecordSet, error) {
rs := &RecordSetResponse{}
Expand Down
15 changes: 14 additions & 1 deletion vinyldns/recordsets_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ limitations under the License.

package vinyldns

// recordSetsList retrieves the list of record sets with the List criteria passed.
// recordSetsList retrieves the list of record sets with the List criteria passed,
// for the specified zone.
func (c *Client) recordSetsList(zoneID string, filter ListFilter) (*RecordSetsResponse, error) {
recordSets := &RecordSetsResponse{}
err := resourceRequest(c, recordSetsListEP(c, zoneID, filter), "GET", nil, recordSets)
Expand All @@ -22,3 +23,15 @@ func (c *Client) recordSetsList(zoneID string, filter ListFilter) (*RecordSetsRe

return recordSets, nil
}

// recordSetsGlobalList retrieves the list of record sets with the List criteria passed,
// across all zones.
func (c *Client) recordSetsGlobalList(filter GlobalListFilter) (*RecordSetsResponse, error) {
recordSets := &RecordSetsResponse{}
err := resourceRequest(c, recordSetsGlobalListEP(c, filter), "GET", nil, recordSets)
if err != nil {
return recordSets, err
}

return recordSets, nil
}
84 changes: 84 additions & 0 deletions vinyldns/recordsets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,90 @@ func TestRecordSetsListAllWhenNoneExist(t *testing.T) {
}
}

func TestRecordSetsGlobalListAll(t *testing.T) {
recordSetsListJSON1, err := readFile("test-fixtures/recordsets/recordsets-list-json-1.json")
if err != nil {
t.Error(err)
}
recordSetsListJSON2, err := readFile("test-fixtures/recordsets/recordsets-list-json-2.json")
if err != nil {
t.Error(err)
}
server, client := testTools([]testToolsConfig{
{
endpoint: "http://host.com/recordsets?maxItems=1",
code: 200,
body: recordSetsListJSON1,
},
{
endpoint: "http://host.com/recordsets?startFrom=2&maxItems=1",
code: 200,
body: recordSetsListJSON2,
},
})

defer server.Close()

if _, err := client.RecordSetsGlobalListAll(GlobalListFilter{
MaxItems: 200,
}); err == nil {
t.Error("Expected error -- MaxItems must be between 1 and 100")
}

records, err := client.RecordSetsGlobalListAll(GlobalListFilter{
MaxItems: 1,
})
if err != nil {
t.Error(err)
}

if len(records) != 2 {
t.Error("Expected 2 records; got ", len(records))
}

if records[0].ID != "1" {
t.Error("Expected RecordSet.ID to be 1")
}

if records[1].ID != "2" {
t.Error("Expected RecordSet.ID to be 2")
}
}

func TestRecordSetsGlobalListAllWhenNoneExist(t *testing.T) {
recordSetsListNoneJSON, err := readFile("test-fixtures/recordsets/recordsets-list-none.json")
if err != nil {
t.Error(err)
}
server, client := testTools([]testToolsConfig{
{
endpoint: "http://host.com/recordsets",
code: 200,
body: recordSetsListNoneJSON,
},
})

defer server.Close()

records, err := client.RecordSetsGlobalListAll(GlobalListFilter{})
if err != nil {
t.Error(err)
}

if len(records) != 0 {
t.Error("Expected 0 records; got ", len(records))
}

j, err := json.Marshal(records)
if err != nil {
t.Error(err)
}

if string(j) != "[]" {
t.Error("Expected string-converted marshaled JSON to be '[]'; got ", string(j))
}
}

func TestRecordSetCollector(t *testing.T) {
recordSetsJSON, err := readFile("test-fixtures/recordsets/recordsets.json")
if err != nil {
Expand Down
25 changes: 24 additions & 1 deletion vinyldns/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,32 @@ func (d Error) Error() string {
}

// ListFilter represents the list query parameters that may be passed to
// VinylDNS API endpoints such as /zones and /recordsets
// VinylDNS API endpoints such as /zones and /zones/${zone_id}/recordsets
type ListFilter struct {
NameFilter string
StartFrom string
MaxItems int
}

// NameSort specifies the name sort order for record sets returned by the global list record set response.
// Valid values are ASC (ascending; default) and DESC (descending).
type NameSort string

const (
// ASC represents an ascending NameSort
ASC NameSort = "ASC"

// DESC represents a descending NameSort
DESC NameSort = "DESC"
)

// GlobalListFilter represents the list query parameters that may be passed to
// VinylDNS API endpoints such as /recordsets
type GlobalListFilter struct {
RecordNameFilter string
RecordTypeFilter string
RecordOwnerGroupFilter string
NameSort NameSort
StartFrom string
MaxItems int
}
2 changes: 1 addition & 1 deletion vinyldns/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ limitations under the License.
package vinyldns

// Version stores the go-vinyldns semantic version
var Version = "0.9.12"
var Version = "0.9.13"

0 comments on commit 148a5f6

Please sign in to comment.