Repository: cloudflare/cloudflare-go
Pull request #2722 (2024-07-03 19:21:09)

Feat/add gateway categories
This pull request adds support for the `ListGatewayCategories` endpoint.

## Description
Our main driver is that we are looking into have this data available as a data resource in the terraform provider, please let me know if this is the right direction.

## Has your change been tested?

besides the test case I created [this script](https://gist.github.com/brennoo/e3e04bf76cebe1ccdbfe5b550627204a) and the output seems correct

## Types of changes

What sort of change does your code introduce/modify?

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist:

- [x] My code follows the code style of this project.
- [x] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [x] I have added tests to cover my changes.
- [x] All new and existing tests passed.
- [x] This change is using publicly documented in [cloudflare/api-schemas](https://github.com/cloudflare/api-schemas) 
      and relies on stable APIs.

[1]: https://help.github.com/articles/closing-issues-using-keywords/



Patch:
diff --git a/.changelog/2722.txt b/.changelog/2722.txt
new file mode 100644
index 000000000..974f083d7
--- /dev/null
+++ b/.changelog/2722.txt
@@ -0,0 +1,3 @@
+```release-note:enhancement
+gateway_categories: add ListGatewayCategories which returns all gateway categories.
+```
diff --git a/gateway_categories.go b/gateway_categories.go
new file mode 100644
index 000000000..da23a74e1
--- /dev/null
+++ b/gateway_categories.go
@@ -0,0 +1,54 @@
+package cloudflare
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+
+	"github.com/goccy/go-json"
+)
+
+// GatewayCategory represents a single gateway category.
+type GatewayCategory struct {
+	Beta          *bool             `json:"beta,omitempty"`
+	Class         string            `json:"class"`
+	Description   string            `json:"description"`
+	ID            int               `json:"id"`
+	Name          string            `json:"name"`
+	Subcategories []GatewayCategory `json:"subcategories"`
+}
+
+// GatewayCategoriesResponse represents the response from the list
+// gateway categories endpoint.
+type GatewayCategoriesResponse struct {
+	Success    bool              `json:"success"`
+	Result     []GatewayCategory `json:"result"`
+	Errors     []string          `json:"errors"`
+	Messages   []string          `json:"messages"`
+	ResultInfo ResultInfo        `json:"result_info"`
+}
+
+// ListGatewayCategoriesParams represents the parameters for listing gateway categories.
+type ListGatewayCategoriesParams struct {
+	ResultInfo
+}
+
+// ListGatewayCategories returns all gateway categories within an account.
+//
+// API reference: https://developers.cloudflare.com/api/operations/zero-trust-gateway-categories-list-categories
+func (api *API) ListGatewayCategories(ctx context.Context, rc *ResourceContainer, params ListGatewayCategoriesParams) ([]GatewayCategory, ResultInfo, error) {
+	uri := fmt.Sprintf("/accounts/%s/gateway/categories", rc.Identifier)
+
+	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+	if err != nil {
+		return []GatewayCategory{}, ResultInfo{}, err
+	}
+
+	var gResponse GatewayCategoriesResponse
+	err = json.Unmarshal(res, &gResponse)
+	if err != nil {
+		return []GatewayCategory{}, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+	}
+
+	return gResponse.Result, gResponse.ResultInfo, nil
+}


Test patch:
diff --git a/gateway_categories_test.go b/gateway_categories_test.go
new file mode 100644
index 000000000..e1b4f2bcc
--- /dev/null
+++ b/gateway_categories_test.go
@@ -0,0 +1,76 @@
+package cloudflare
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestListGatewayCategories(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprintf(w, `{
+			"success": true,
+			"errors": [],
+			"messages": [],
+			"result": [
+				{
+					"beta": false,
+					"class": "premium",
+					"description": "Sites related to educational content.",
+					"id": 0,
+					"name": "Education",
+					"subcategories": [
+						{
+							"beta": true,
+							"class": "premium",
+							"description": "Sites related to educational content.",
+							"id": 0,
+							"name": "Education"
+						}
+					]
+				}
+			],
+			"result_info": {
+				"count": 1,
+				"page": 1,
+				"per_page": 20,
+				"total_count": 2000
+			}
+		}`)
+	}
+
+	want := []GatewayCategory{
+		{
+			Beta:        BoolPtr(false),
+			Class:       "premium",
+			Description: "Sites related to educational content.",
+			ID:          0,
+			Name:        "Education",
+			Subcategories: []GatewayCategory{
+				{
+					Beta:        BoolPtr(true),
+					Class:       "premium",
+					Description: "Sites related to educational content.",
+					ID:          0,
+					Name:        "Education",
+				},
+			},
+		},
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/gateway/categories", handler)
+
+	actual, _, err := client.ListGatewayCategories(context.Background(), AccountIdentifier(testAccountID), ListGatewayCategoriesParams{})
+
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, actual)
+	}
+}