Skip to content

Commit

Permalink
Merge pull request #1251 from jacobbednarz/make-zone-settings-more-fl…
Browse files Browse the repository at this point in the history
…exible

zone: make settings more flexible
  • Loading branch information
jacobbednarz authored Mar 28, 2023
2 parents dbc7a5f + c300573 commit 5cf30da
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 10 deletions.
11 changes: 11 additions & 0 deletions .changelog/1251.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```release-note:breaking-change
zone: `ZoneSingleSetting` has been renamed to `GetZoneSetting` and updated method signature inline with our expected conventions
```

```release-note:breaking-change
zone: `UpdateZoneSingleSetting` has been renamed to `UpdateZoneSetting` and updated method signature inline with our expected conventions
```

```release-note:enhancement
zone: `GetZoneSetting` and `UpdateZoneSetting` now allow configuring the path for where a setting resides instead of assuming `settings`
```
2 changes: 2 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const (

errInvalidResourceContainerAccess = "requested resource container (%q) is not supported for this endpoint"
errRequiredAccountLevelResourceContainer = "this endpoint requires using an account level resource container and identifiers"
errRequiredZoneLevelResourceContainer = "this endpoint requires using a zone level resource container and identifiers"
)

var (
Expand All @@ -43,6 +44,7 @@ var (
ErrMissingResourceIdentifier = errors.New(errMissingResourceIdentifier)

ErrRequiredAccountLevelResourceContainer = errors.New(errRequiredAccountLevelResourceContainer)
ErrRequiredZoneLevelResourceContainer = errors.New(errRequiredZoneLevelResourceContainer)
)

type ErrorType string
Expand Down
63 changes: 53 additions & 10 deletions zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ import (
"golang.org/x/net/idna"
)

var (
// ErrMissingSettingName is for when setting name is required but missing.
ErrMissingSettingName = errors.New("zone setting name required but missing")
)

// Owner describes the resource owner.
type Owner struct {
ID string `json:"id"`
Expand Down Expand Up @@ -300,6 +305,17 @@ type zoneSubscriptionRatePlanPayload struct {
} `json:"rate_plan"`
}

type GetZoneSettingParams struct {
Name string `json:"-"`
PathPrefix string `json:"-"`
}

type UpdateZoneSettingParams struct {
Name string `json:"-"`
PathPrefix string `json:"-"`
Value interface{} `json:"value"`
}

// CreateZone creates a zone on an account.
//
// Setting jumpstart to true will attempt to automatically scan for existing
Expand Down Expand Up @@ -897,11 +913,25 @@ func normalizeZoneName(name string) string {
return name
}

// ZoneSingleSetting returns information about specified setting to the specified zone.
// GetZoneSetting returns information about specified setting to the specified
// zone.
//
// API reference: https://api.cloudflare.com/#zone-settings-get-all-zone-settings
func (api *API) ZoneSingleSetting(ctx context.Context, zoneID, settingName string) (ZoneSetting, error) {
uri := fmt.Sprintf("/zones/%s/settings/%s", zoneID, settingName)
func (api *API) GetZoneSetting(ctx context.Context, rc *ResourceContainer, params GetZoneSettingParams) (ZoneSetting, error) {
if rc.Level != ZoneRouteLevel {
return ZoneSetting{}, ErrRequiredZoneLevelResourceContainer
}

if rc.Identifier == "" {
return ZoneSetting{}, ErrMissingName
}

pathPrefix := "settings"
if params.PathPrefix != "" {
pathPrefix = params.PathPrefix
}

uri := fmt.Sprintf("/zones/%s/%s/%s", rc.Identifier, pathPrefix, params.Name)
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return ZoneSetting{}, err
Expand All @@ -914,23 +944,36 @@ func (api *API) ZoneSingleSetting(ctx context.Context, zoneID, settingName strin
return r.Result, nil
}

// UpdateZoneSingleSetting updates the specified setting for a given zone.
// UpdateZoneSetting updates the specified setting for a given zone.
//
// API reference: https://api.cloudflare.com/#zone-settings-edit-zone-settings-info
func (api *API) UpdateZoneSingleSetting(ctx context.Context, zoneID, settingName string, setting ZoneSetting) (*ZoneSettingSingleResponse, error) {
uri := fmt.Sprintf("/zones/%s/settings/%s", zoneID, settingName)
res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, setting)
func (api *API) UpdateZoneSetting(ctx context.Context, rc *ResourceContainer, params UpdateZoneSettingParams) (ZoneSetting, error) {
if rc.Level != ZoneRouteLevel {
return ZoneSetting{}, ErrRequiredZoneLevelResourceContainer
}

if rc.Identifier == "" {
return ZoneSetting{}, ErrMissingName
}

pathPrefix := "settings"
if params.PathPrefix != "" {
pathPrefix = params.PathPrefix
}

uri := fmt.Sprintf("/zones/%s/%s/%s", rc.Identifier, pathPrefix, params.Name)
res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params)
if err != nil {
return nil, err
return ZoneSetting{}, err
}

response := &ZoneSettingSingleResponse{}
err = json.Unmarshal(res, &response)
if err != nil {
return nil, fmt.Errorf("%s: %w", errUnmarshalError, err)
return ZoneSetting{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return response, nil
return response.Result, nil
}

// ZoneExport returns the text BIND config for the given zone
Expand Down
100 changes: 100 additions & 0 deletions zone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1510,3 +1510,103 @@ func TestUpdateZoneSSLSettings(t *testing.T) {
assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z")
}
}

func TestGetZoneSetting(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, `{
"result": {
"id": "ssl",
"value": "off",
"editable": true,
"modified_on": "2014-01-01T05:20:00.12345Z"
}
}`)
}
mux.HandleFunc("/zones/foo/settings/ssl", handler)
s, err := client.GetZoneSetting(context.Background(), ZoneIdentifier("foo"), GetZoneSettingParams{Name: "ssl"})
if assert.NoError(t, err) {
assert.Equal(t, s.ID, "ssl")
assert.Equal(t, s.Value, "off")
assert.Equal(t, s.Editable, true)
assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z")
}
}

func TestGetZoneSettingWithCustomPathPrefix(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, `{
"result": {
"id": "ssl",
"value": "off",
"editable": true,
"modified_on": "2014-01-01T05:20:00.12345Z"
}
}`)
}
mux.HandleFunc("/zones/foo/my_custom_path/ssl", handler)
s, err := client.GetZoneSetting(context.Background(), ZoneIdentifier("foo"), GetZoneSettingParams{Name: "ssl", PathPrefix: "my_custom_path"})
if assert.NoError(t, err) {
assert.Equal(t, s.ID, "ssl")
assert.Equal(t, s.Value, "off")
assert.Equal(t, s.Editable, true)
assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z")
}
}

func TestUpdateZoneSetting(t *testing.T) {
setup()
defer teardown()
handler := func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method)
w.Header().Set("content-type", "application/json")
_, _ = fmt.Fprintf(w, `{
"result": {
"id": "ssl",
"value": "off",
"editable": true,
"modified_on": "2014-01-01T05:20:00.12345Z"
}
}`)
}
mux.HandleFunc("/zones/foo/settings/ssl", handler)
s, err := client.UpdateZoneSetting(context.Background(), ZoneIdentifier("foo"), UpdateZoneSettingParams{Name: "ssl", Value: "off"})
if assert.NoError(t, err) {
assert.Equal(t, s.ID, "ssl")
assert.Equal(t, s.Value, "off")
assert.Equal(t, s.Editable, true)
assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z")
}
}

func TestUpdateZoneSettingWithCustomPathPrefix(t *testing.T) {
setup()
defer teardown()
handler := func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPatch, r.Method, "Expected method 'PATCH', got %s", r.Method)
w.Header().Set("content-type", "application/json")
_, _ = fmt.Fprintf(w, `{
"result": {
"id": "ssl",
"value": "off",
"editable": true,
"modified_on": "2014-01-01T05:20:00.12345Z"
}
}`)
}
mux.HandleFunc("/zones/foo/my_custom_path/ssl", handler)
s, err := client.UpdateZoneSetting(context.Background(), ZoneIdentifier("foo"), UpdateZoneSettingParams{Name: "ssl", PathPrefix: "my_custom_path", Value: "off"})
if assert.NoError(t, err) {
assert.Equal(t, s.ID, "ssl")
assert.Equal(t, s.Value, "off")
assert.Equal(t, s.Editable, true)
assert.Equal(t, s.ModifiedOn, "2014-01-01T05:20:00.12345Z")
}
}

0 comments on commit 5cf30da

Please sign in to comment.