Skip to content

Commit ccd5db9

Browse files
committed
feat(email_routing): add AccountRules.List and restore Rules.List
Previously, `Rules.List` was silently dropped from codegen because the Stainless config declared it at `GET /zones/{zone_id}/email/routing/rules`, while Stainless auto-collapses matching `/accounts/{account_id}/...` and `/zones/{zone_id}/...` operations into a single aggregate path (`/{accounts_or_zones}/{account_or_zone_id}/...`). Config entries that target only the zone-scoped path no longer match and are skipped. Fix in openapi.stainless.yml: - Point `email_routing.rules.list` at the aggregate path so `Rules.List` is generated again; `RuleListParams` now carries mutually exclusive `AccountID` / `ZoneID` fields. - Add a new `account_rules` subresource bound to the same aggregate path, producing `AccountRules.List` returning `AccountRule` (adds a `Zone` field over `Rule`). Marked `skip: [terraform]` since this is a Go-only surface addition for this release. CHANGELOG + v7.7.0 migration guide updated: the "Rules.List method removed" breaking change is dropped (the restore + additive AccountID param is backwards compatible), the remaining breaking-change sections renumbered, and the two new methods added to Features.
1 parent 24980ca commit ccd5db9

9 files changed

Lines changed: 407 additions & 67 deletions

File tree

.stats.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
configured_endpoints: 2447
1+
configured_endpoints: 2448

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ Full Changelog: [v7.6.0...v7.7.0](https://github.com/cloudflare/cloudflare-go/co
88

99
See the [v7.7.0 Migration Guide](./docs/migration-guides/v7.7.0-migration-guide.md) for before/after code examples and actions needed for each change.
1010

11-
* **email_routing:** `Rules.List` method removed.
1211
* **ssl:** `Recommendations.Get` method and `RecommendationGetResponse` / `RecommendationGetParams` types removed.
1312
* **ai_gateway, workflows, zero_trust/dlpemailaccountmapping:** merged-union parent fields with same-name-different-type collisions changed from a variant-struct type to `interface{}`. Affected fields:
1413
* `ai_gateway.AIGateway{New,Update,List,Delete,Get}ResponseSpendLimitsRulesMetadata.Mode` (5 structs)
@@ -38,6 +37,7 @@ See the [v7.7.0 Migration Guide](./docs/migration-guides/v7.7.0-migration-guide.
3837
* `LogExplorer.Datasets.Available.List`
3938
* **browser_rendering:** add `AccessibilityTree.New` method
4039
* **email_routing:** add `EmailRouting.Unlock` and `EmailRouting.Addresses.Edit` methods
40+
* **email_routing:** add `AccountRules.List` method (`GET /accounts/{account_id}/email/routing/rules`) returning `AccountRule` with new `Zone` field; `Rules.List` gains optional `AccountID` param (mutually exclusive with `ZoneID`) so callers can list rules by account or zone
4141
* **email_security:** add bulk investigation APIs
4242
* `Investigate.Bulk.{New,List,Delete,Get}`
4343
* `Investigate.Bulk.Cancel.New`

docs/migration-guides/v7.7.0-migration-guide.md

Lines changed: 8 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,57 +2,9 @@
22

33
## Breaking Changes
44

5-
### `email_routing`
6-
7-
#### 1. Rules.List method removed
8-
9-
**What changed:**
10-
The `List` method has been removed from `client.EmailRouting.Rules`. The underlying HTTP endpoint (`GET /zones/{zone_id}/email/routing/rules`) is still supported by the platform but is no longer exposed as a strongly-typed SDK method.
11-
12-
**Impact:**
13-
Code that iterates email routing rules via `client.EmailRouting.Rules.List(...)` will no longer compile.
14-
15-
**Removed Types:**
16-
- `EmailRouting.Rules.List` method
17-
- `RuleListParams`
18-
19-
**Before (v7.6.0):**
20-
```go
21-
iter := client.EmailRouting.Rules.ListAutoPaging(ctx, email_routing.RuleListParams{
22-
ZoneID: cloudflare.F("zone-id"),
23-
})
24-
for iter.Next() {
25-
rule := iter.Current()
26-
// ...
27-
}
28-
```
29-
30-
**After (v7.7.0):**
31-
32-
Either fetch a specific rule by identifier:
33-
34-
```go
35-
rule, err := client.EmailRouting.Rules.Get(ctx, "rule-identifier", email_routing.RuleGetParams{
36-
ZoneID: cloudflare.F("zone-id"),
37-
})
38-
```
39-
40-
Or call the endpoint directly using the low-level request helper:
41-
42-
```go
43-
var rules []email_routing.EmailRoutingRule
44-
err := client.Get(ctx, "zones/zone-id/email/routing/rules", nil, &rules)
45-
```
46-
47-
**Actions Needed:**
48-
1. Remove all `client.EmailRouting.Rules.List` / `ListAutoPaging` call sites.
49-
2. Replace with per-rule `Get` calls, or issue the HTTP request directly via `client.Get(...)`.
50-
51-
---
52-
535
### `ssl`
546

55-
#### 2. Recommendations.Get method and types removed
7+
#### 1. Recommendations.Get method and types removed
568

579
**What changed:**
5810
The `Recommendations` sub-resource has been removed from the SSL service. The endpoint `GET /zones/{zone_id}/ssl/recommendation` is no longer exposed by the SDK.
@@ -90,7 +42,7 @@ err := client.Get(ctx, "zones/zone-id/ssl/recommendation", nil, &rec)
9042

9143
### `ai_gateway`, `workflows`, `zero_trust`
9244

93-
#### 3. Union-merged parent fields changed to interface{}
45+
#### 2. Union-merged parent fields changed to interface{}
9446

9547
**What changed:**
9648
When the same field name appears on multiple union variants with different Go types, the merged parent struct's field is now typed as `interface{}` (with a `// This field can have the runtime type of ...` comment) instead of the variant-struct type. This matches how the code generator already emits sibling merged fields on the same structs (e.g. `Values`, `Fields`, `AllowedMicrosoftOrganizations`).
@@ -160,7 +112,7 @@ if s, ok := meta.Mode.(ai_gateway.AIGatewayNewResponseSpendLimitsRulesMetadataMo
160112

161113
### `zero_trust`
162114

163-
#### 4. Devices.DEXTests response type renamed to SchemaHTTP
115+
#### 3. Devices.DEXTests response type renamed to SchemaHTTP
164116

165117
**What changed:**
166118
The response types for the four `zero_trust.Devices.DEXTests` methods have been renamed from per-method types to a single shared type, `SchemaHTTP`. The **field structure is unchanged** — only the exported type names differ.
@@ -204,7 +156,7 @@ func printTest(t *zero_trust.SchemaHTTP) { /* ... */ }
204156

205157
---
206158

207-
#### 5. Devices.IPProfiles.List pagination type changed
159+
#### 4. Devices.IPProfiles.List pagination type changed
208160

209161
**What changed:**
210162
`client.ZeroTrust.Devices.IPProfiles.List` now returns `*pagination.V4PagePaginationArray[IPProfile]` instead of `*pagination.SinglePage[IPProfile]`.
@@ -233,8 +185,7 @@ page, err = client.ZeroTrust.Devices.IPProfiles.List(ctx, params)
233185

234186
## Summary of Breaking Changes
235187

236-
1. `email_routing.Rules.List` method removed (and `RuleListParams`).
237-
2. `ssl.Recommendations.Get` method removed along with `RecommendationGetResponse`, `RecommendationGetParams`, and `RecommendationService`.
238-
3. Eight union-merged parent-struct fields changed from a variant-struct type to `interface{}` across `ai_gateway`, `workflows`, and `zero_trust`.
239-
4. `zero_trust.Devices.DEXTests.{New,Update,List,Get}` response types renamed to shared `SchemaHTTP` (field structure unchanged).
240-
5. `zero_trust.Devices.IPProfiles.List` pagination changed from `SinglePage[IPProfile]` to `V4PagePaginationArray[IPProfile]`.
188+
1. `ssl.Recommendations.Get` method removed along with `RecommendationGetResponse`, `RecommendationGetParams`, and `RecommendationService`.
189+
2. Eight union-merged parent-struct fields changed from a variant-struct type to `interface{}` across `ai_gateway`, `workflows`, and `zero_trust`.
190+
3. `zero_trust.Devices.DEXTests.{New,Update,List,Get}` response types renamed to shared `SchemaHTTP` (field structure unchanged).
191+
4. `zero_trust.Devices.IPProfiles.List` pagination changed from `SinglePage[IPProfile]` to `V4PagePaginationArray[IPProfile]`.

email_routing/accountrule.go

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
package email_routing
4+
5+
import (
6+
"context"
7+
"errors"
8+
"fmt"
9+
"net/http"
10+
"net/url"
11+
"slices"
12+
13+
"github.com/cloudflare/cloudflare-go/v7/internal/apijson"
14+
"github.com/cloudflare/cloudflare-go/v7/internal/apiquery"
15+
"github.com/cloudflare/cloudflare-go/v7/internal/param"
16+
"github.com/cloudflare/cloudflare-go/v7/internal/requestconfig"
17+
"github.com/cloudflare/cloudflare-go/v7/option"
18+
"github.com/cloudflare/cloudflare-go/v7/packages/pagination"
19+
)
20+
21+
// AccountRuleService contains methods and other services that help with
22+
// interacting with the cloudflare API.
23+
//
24+
// Note, unlike clients, this service does not read variables from the environment
25+
// automatically. You should not instantiate this service directly, and instead use
26+
// the [NewAccountRuleService] method instead.
27+
type AccountRuleService struct {
28+
Options []option.RequestOption
29+
}
30+
31+
// NewAccountRuleService generates a new service that applies the given options to
32+
// each request. These options are applied after the parent client's options (if
33+
// there is one), and before any request-specific options.
34+
func NewAccountRuleService(opts ...option.RequestOption) (r *AccountRuleService) {
35+
r = &AccountRuleService{}
36+
r.Options = opts
37+
return
38+
}
39+
40+
// Lists existing routing rules across all zones in the account or zone.
41+
func (r *AccountRuleService) List(ctx context.Context, params AccountRuleListParams, opts ...option.RequestOption) (res *pagination.V4PagePaginationArray[AccountRule], err error) {
42+
var raw *http.Response
43+
opts = slices.Concat(r.Options, opts)
44+
opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
45+
var accountOrZone string
46+
var accountOrZoneID param.Field[string]
47+
if params.AccountID.Value != "" && params.ZoneID.Value != "" {
48+
err = errors.New("account ID and zone ID are mutually exclusive")
49+
return
50+
}
51+
if params.AccountID.Value == "" && params.ZoneID.Value == "" {
52+
err = errors.New("either account ID or zone ID must be provided")
53+
return
54+
}
55+
if params.AccountID.Value != "" {
56+
accountOrZone = "accounts"
57+
accountOrZoneID = params.AccountID
58+
}
59+
if params.ZoneID.Value != "" {
60+
accountOrZone = "zones"
61+
accountOrZoneID = params.ZoneID
62+
}
63+
path := fmt.Sprintf("%s/%s/email/routing/rules", accountOrZone, accountOrZoneID)
64+
cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, params, &res, opts...)
65+
if err != nil {
66+
return nil, err
67+
}
68+
err = cfg.Execute()
69+
if err != nil {
70+
return nil, err
71+
}
72+
res.SetPageConfig(cfg, raw)
73+
return res, nil
74+
}
75+
76+
// Lists existing routing rules across all zones in the account or zone.
77+
func (r *AccountRuleService) ListAutoPaging(ctx context.Context, params AccountRuleListParams, opts ...option.RequestOption) *pagination.V4PagePaginationArrayAutoPager[AccountRule] {
78+
return pagination.NewV4PagePaginationArrayAutoPager(r.List(ctx, params, opts...))
79+
}
80+
81+
type AccountRule struct {
82+
// Routing rule identifier.
83+
ID string `json:"id"`
84+
// List actions patterns.
85+
Actions []Action `json:"actions"`
86+
// Routing rule status.
87+
Enabled AccountRuleEnabled `json:"enabled"`
88+
// Matching patterns to forward to your actions.
89+
Matchers []Matcher `json:"matchers"`
90+
// Routing rule name.
91+
Name string `json:"name"`
92+
// Priority of the routing rule.
93+
Priority float64 `json:"priority"`
94+
// Who manages the rule. `api` covers dashboard, generic API, and Terraform;
95+
// `wrangler` means the rule is managed by a Worker's wrangler.jsonc. Defaults to
96+
// `api` when omitted on write.
97+
Source AccountRuleSource `json:"source"`
98+
// Routing rule tag. (Deprecated, replaced by routing rule identifier)
99+
//
100+
// Deprecated: deprecated
101+
Tag string `json:"tag"`
102+
// Zone information for the routing rule.
103+
Zone AccountRuleZone `json:"zone"`
104+
JSON accountRuleJSON `json:"-"`
105+
}
106+
107+
// accountRuleJSON contains the JSON metadata for the struct [AccountRule]
108+
type accountRuleJSON struct {
109+
ID apijson.Field
110+
Actions apijson.Field
111+
Enabled apijson.Field
112+
Matchers apijson.Field
113+
Name apijson.Field
114+
Priority apijson.Field
115+
Source apijson.Field
116+
Tag apijson.Field
117+
Zone apijson.Field
118+
raw string
119+
ExtraFields map[string]apijson.Field
120+
}
121+
122+
func (r *AccountRule) UnmarshalJSON(data []byte) (err error) {
123+
return apijson.UnmarshalRoot(data, r)
124+
}
125+
126+
func (r accountRuleJSON) RawJSON() string {
127+
return r.raw
128+
}
129+
130+
// Routing rule status.
131+
type AccountRuleEnabled bool
132+
133+
const (
134+
AccountRuleEnabledTrue AccountRuleEnabled = true
135+
AccountRuleEnabledFalse AccountRuleEnabled = false
136+
)
137+
138+
func (r AccountRuleEnabled) IsKnown() bool {
139+
switch r {
140+
case AccountRuleEnabledTrue, AccountRuleEnabledFalse:
141+
return true
142+
}
143+
return false
144+
}
145+
146+
// Who manages the rule. `api` covers dashboard, generic API, and Terraform;
147+
// `wrangler` means the rule is managed by a Worker's wrangler.jsonc. Defaults to
148+
// `api` when omitted on write.
149+
type AccountRuleSource string
150+
151+
const (
152+
AccountRuleSourceAPI AccountRuleSource = "api"
153+
AccountRuleSourceWrangler AccountRuleSource = "wrangler"
154+
)
155+
156+
func (r AccountRuleSource) IsKnown() bool {
157+
switch r {
158+
case AccountRuleSourceAPI, AccountRuleSourceWrangler:
159+
return true
160+
}
161+
return false
162+
}
163+
164+
// Zone information for the routing rule.
165+
type AccountRuleZone struct {
166+
// Zone name.
167+
Name string `json:"name"`
168+
// Zone tag.
169+
Tag string `json:"tag"`
170+
JSON accountRuleZoneJSON `json:"-"`
171+
}
172+
173+
// accountRuleZoneJSON contains the JSON metadata for the struct [AccountRuleZone]
174+
type accountRuleZoneJSON struct {
175+
Name apijson.Field
176+
Tag apijson.Field
177+
raw string
178+
ExtraFields map[string]apijson.Field
179+
}
180+
181+
func (r *AccountRuleZone) UnmarshalJSON(data []byte) (err error) {
182+
return apijson.UnmarshalRoot(data, r)
183+
}
184+
185+
func (r accountRuleZoneJSON) RawJSON() string {
186+
return r.raw
187+
}
188+
189+
type AccountRuleListParams struct {
190+
// The Account ID to use for this endpoint. Mutually exclusive with the Zone ID.
191+
AccountID param.Field[string] `path:"account_id"`
192+
// The Zone ID to use for this endpoint. Mutually exclusive with the Account ID.
193+
ZoneID param.Field[string] `path:"zone_id"`
194+
// Filter by enabled routing rules.
195+
Enabled param.Field[AccountRuleListParamsEnabled] `query:"enabled"`
196+
// Page number of paginated results.
197+
Page param.Field[float64] `query:"page"`
198+
// Maximum number of results per page.
199+
PerPage param.Field[float64] `query:"per_page"`
200+
}
201+
202+
// URLQuery serializes [AccountRuleListParams]'s query parameters as `url.Values`.
203+
func (r AccountRuleListParams) URLQuery() (v url.Values) {
204+
return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
205+
ArrayFormat: apiquery.ArrayQueryFormatRepeat,
206+
NestedFormat: apiquery.NestedQueryFormatDots,
207+
})
208+
}
209+
210+
// Filter by enabled routing rules.
211+
type AccountRuleListParamsEnabled bool
212+
213+
const (
214+
AccountRuleListParamsEnabledTrue AccountRuleListParamsEnabled = true
215+
AccountRuleListParamsEnabledFalse AccountRuleListParamsEnabled = false
216+
)
217+
218+
func (r AccountRuleListParamsEnabled) IsKnown() bool {
219+
switch r {
220+
case AccountRuleListParamsEnabledTrue, AccountRuleListParamsEnabledFalse:
221+
return true
222+
}
223+
return false
224+
}

email_routing/accountrule_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
package email_routing_test
4+
5+
import (
6+
"context"
7+
"errors"
8+
"os"
9+
"testing"
10+
11+
"github.com/cloudflare/cloudflare-go/v7"
12+
"github.com/cloudflare/cloudflare-go/v7/email_routing"
13+
"github.com/cloudflare/cloudflare-go/v7/internal/testutil"
14+
"github.com/cloudflare/cloudflare-go/v7/option"
15+
)
16+
17+
func TestAccountRuleListWithOptionalParams(t *testing.T) {
18+
baseURL := "http://localhost:4010"
19+
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
20+
baseURL = envURL
21+
}
22+
if !testutil.CheckTestServer(t, baseURL) {
23+
return
24+
}
25+
client := cloudflare.NewClient(
26+
option.WithBaseURL(baseURL),
27+
option.WithAPIKey("144c9defac04969c7bfad8efaa8ea194"),
28+
option.WithAPIEmail("user@example.com"),
29+
)
30+
_, err := client.EmailRouting.AccountRules.List(context.TODO(), email_routing.AccountRuleListParams{
31+
AccountID: cloudflare.F("account_id"),
32+
Enabled: cloudflare.F(email_routing.AccountRuleListParamsEnabledTrue),
33+
Page: cloudflare.F(1.000000),
34+
PerPage: cloudflare.F(5.000000),
35+
})
36+
if err != nil {
37+
var apierr *cloudflare.Error
38+
if errors.As(err, &apierr) {
39+
t.Log(string(apierr.DumpRequest(true)))
40+
}
41+
t.Fatalf("err should be nil: %s", err.Error())
42+
}
43+
}

0 commit comments

Comments
 (0)