Repository: cloudflare/cloudflare-go
Pull request #1160 (2022-12-29 19:46:37)

feat(workers): allow enabling logpush on worker uploads
This allows cloudflare-go users to turn on/off [logpush support for Cloudflare Workers](https://developers.cloudflare.com/workers/platform/logpush/).
The analogous functionality in Wrangler can be found here: https://github.com/cloudflare/wrangler2/blob/7169142171b1c9b4ff2f19b8b46871932ef7d10a/packages/wrangler/src/create-worker-upload-form.ts#L294

## Description

This adds a new option to `CreateWorkerParams` that allows control over the logpush setting. Note its a nullable bool: the 3 states are true - on / false - off / nil - unchanged. Again, this is analogous to wrangler with its `boolean | undefined` type.

## Has your change been tested?

A new test was created to test this. 

## Screenshots (if appropriate):

## 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.
- [ ] 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 (api.cloudflare.com or developers.cloudflare.com) and stable APIs.

[1]: https://help.github.com/articles/closing-issues-using-keywords/


ndisidore: Re: `My code follows the code style of this project.` - it looks like there are a number of lint errors present, but none that this change set has introduced
```
cloudflare-go on  nathan/feat/workers-logpush via 🐹 v1.19.4
❯ golangci-lint --new-from-rev=HEAD~1 run ./..
```
github-actions[bot]: Oops! It looks like no changelog entry is attached to this PR. Please include a release note as described in https://github.com/cloudflare/cloudflare-go/blob/master/docs/changelog-process.md.

Example: 

~~~
```release-note:TYPE
Release note
```
~~~

If you do not require a release note to be included, please add the `workflow/skip-changelog-entry` label.
codecov-commenter: # [Codecov](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1160?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) Report
> Merging [#1160](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1160?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) (688a493) into [master](https://codecov.io/gh/cloudflare/cloudflare-go/commit/6153c1e32fa46b7049683687b7f76eb554c95217?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) (6153c1e) will **decrease** coverage by `0.10%`.
> The diff coverage is `51.65%`.

```diff
@@            Coverage Diff             @@
##           master    #1160      +/-   ##
==========================================
- Coverage   49.40%   49.30%   -0.11%     
==========================================
  Files         127      128       +1     
  Lines       12290    12399     +109     
==========================================
+ Hits         6072     6113      +41     
- Misses       4840     4885      +45     
- Partials     1378     1401      +23     
```


| [Impacted Files](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1160?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) | Coverage Δ | |
|---|---|---|
| [utils.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1160/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-dXRpbHMuZ28=) | `72.72% <ø> (ø)` | |
| [mtls\_certificates.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1160/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-bXRsc19jZXJ0aWZpY2F0ZXMuZ28=) | `26.59% <26.59%> (ø)` | |
| [dns.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1160/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-ZG5zLmdv) | `68.69% <92.45%> (+4.97%)` | :arrow_up: |
| [workers.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1160/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-d29ya2Vycy5nbw==) | `57.62% <100.00%> (+0.48%)` | :arrow_up: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare)


Patch:
diff --git a/.changelog/1156.txt b/.changelog/1156.txt
deleted file mode 100644
index 2a19167b7..000000000
--- a/.changelog/1156.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-```release-note:bug
-firewall_rules: use empty reponse struct on each page call
-```
-
-```release-note:bug
-filter: use empty reponse struct on each page call
-```
-
-```release-note:bug
-email_routing_destination: use empty reponse struct on each page call
-```
-
-```release-note:bug
-email_routing_rules: use empty reponse struct on each page call
-```
-
-```release-note:bug
-lockdown: use empty reponse struct on each page call
-```
-
-```release-note:bug
-queue: use empty reponse struct on each page call
-```
-
-```release-note:bug
-teams_list: use empty reponse struct on each page call
-```
-
-```release-note:bug
-workers_kv: use empty reponse struct on each page call
-```
diff --git a/.changelog/1160.txt b/.changelog/1160.txt
new file mode 100644
index 000000000..b4893dc46
--- /dev/null
+++ b/.changelog/1160.txt
@@ -0,0 +1,3 @@
+```release-note:enhancement
+workers: Add support for workers logpush enablement on script upload
+```
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9ee5e9b2..e93bc6ed8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,17 +11,6 @@ ENHANCEMENTS:
 * dns: add support for tags and comments ([#1151](https://github.com/cloudflare/cloudflare-go/issues/1151))
 * mtls_certificate: add support for managing mTLS certificates and assocations ([#1150](https://github.com/cloudflare/cloudflare-go/issues/1150))
 
-BUG FIXES:
-
-* email_routing_destination: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156))
-* email_routing_rules: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156))
-* filter: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156))
-* firewall_rules: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156))
-* lockdown: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156))
-* queue: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156))
-* teams_list: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156))
-* workers_kv: use empty reponse struct on each page call ([#1156](https://github.com/cloudflare/cloudflare-go/issues/1156))
-
 ## 0.57.1 (December 23rd, 2022)
 
 ENHANCEMENTS:
diff --git a/email_routing_destination.go b/email_routing_destination.go
index cb9e30a94..e9705e559 100644
--- a/email_routing_destination.go
+++ b/email_routing_destination.go
@@ -61,7 +61,6 @@ func (api *API) ListEmailRoutingDestinationAddresses(ctx context.Context, rc *Re
 	var addresses []EmailRoutingDestinationAddress
 	var eResponse ListEmailRoutingAddressResponse
 	for {
-		eResponse = ListEmailRoutingAddressResponse{}
 		uri := buildURI(fmt.Sprintf("/accounts/%s/email/routing/addresses", rc.Identifier), params)
 
 		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
diff --git a/email_routing_rules.go b/email_routing_rules.go
index a6c075f82..22101b624 100644
--- a/email_routing_rules.go
+++ b/email_routing_rules.go
@@ -103,7 +103,6 @@ func (api *API) ListEmailRoutingRules(ctx context.Context, rc *ResourceContainer
 	var rules []EmailRoutingRule
 	var rResponse ListEmailRoutingRuleResponse
 	for {
-		rResponse = ListEmailRoutingRuleResponse{}
 		uri := buildURI(fmt.Sprintf("/zones/%s/email/routing/rules", rc.Identifier), params)
 
 		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
diff --git a/filter.go b/filter.go
index b5f084648..904b6b055 100644
--- a/filter.go
+++ b/filter.go
@@ -124,7 +124,6 @@ func (api *API) Filters(ctx context.Context, rc *ResourceContainer, params Filte
 	var filters []Filter
 	var fResponse FiltersDetailResponse
 	for {
-		fResponse = FiltersDetailResponse{}
 		uri := buildURI(fmt.Sprintf("/zones/%s/filters", rc.Identifier), params)
 
 		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
diff --git a/firewall_rules.go b/firewall_rules.go
index 51b4ae87e..4d5636c37 100644
--- a/firewall_rules.go
+++ b/firewall_rules.go
@@ -90,7 +90,6 @@ func (api *API) FirewallRules(ctx context.Context, rc *ResourceContainer, params
 	var firewallRules []FirewallRule
 	var fResponse FirewallRulesDetailResponse
 	for {
-		fResponse = FirewallRulesDetailResponse{}
 		uri := buildURI(fmt.Sprintf("/zones/%s/firewall/rules", rc.Identifier), params)
 
 		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
diff --git a/lockdown.go b/lockdown.go
index a946e5a21..2a2f74464 100644
--- a/lockdown.go
+++ b/lockdown.go
@@ -166,7 +166,6 @@ func (api *API) ListZoneLockdowns(ctx context.Context, rc *ResourceContainer, pa
 	var zoneLockdowns []ZoneLockdown
 	var zResponse ZoneLockdownListResponse
 	for {
-		zResponse = ZoneLockdownListResponse{}
 		uri := buildURI(fmt.Sprintf("/zones/%s/firewall/lockdowns", rc.Identifier), params)
 
 		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
diff --git a/queue.go b/queue.go
index 3b9aa5e90..0bd5a4dfa 100644
--- a/queue.go
+++ b/queue.go
@@ -129,7 +129,6 @@ func (api *API) ListQueues(ctx context.Context, rc *ResourceContainer, params Li
 	var queues []Queue
 	var qResponse QueueListResponse
 	for {
-		qResponse = QueueListResponse{}
 		uri := buildURI(fmt.Sprintf("/accounts/%s/workers/queues", rc.Identifier), params)
 
 		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
@@ -277,7 +276,6 @@ func (api *API) ListQueueConsumers(ctx context.Context, rc *ResourceContainer, p
 	var queuesConsumers []QueueConsumer
 	var qResponse ListQueueConsumersResponse
 	for {
-		qResponse = ListQueueConsumersResponse{}
 		uri := buildURI(fmt.Sprintf("/accounts/%s/workers/queues/%s/consumers", rc.Identifier, params.QueueName), params)
 
 		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
diff --git a/teams_list.go b/teams_list.go
index 30c21d9d2..2f4300156 100644
--- a/teams_list.go
+++ b/teams_list.go
@@ -172,7 +172,6 @@ func (api *API) ListTeamsListItems(ctx context.Context, rc *ResourceContainer, p
 	var teamListItems []TeamsListItem
 	var lResponse TeamsListItemsListResponse
 	for {
-		lResponse = TeamsListItemsListResponse{}
 		uri := buildURI(
 			fmt.Sprintf("/%s/%s/gateway/lists/%s/items", rc.Level, rc.Identifier, params.ListID),
 			params,
diff --git a/workers.go b/workers.go
index b1b3ed7f5..b834c58b1 100644
--- a/workers.go
+++ b/workers.go
@@ -28,6 +28,10 @@ type CreateWorkerParams struct {
 	// ES Module syntax script.
 	Module bool
 
+	// Logpush opts the worker into Workers Logpush logging. A nil value leaves the current setting unchanged.
+	//  https://developers.cloudflare.com/workers/platform/logpush/
+	Logpush *bool
+
 	// Bindings should be a map where the keys are the binding name, and the
 	// values are the binding content
 	Bindings map[string]WorkerBinding
@@ -220,7 +224,7 @@ func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params
 		err         error
 	)
 
-	if params.Module || len(params.Bindings) > 0 {
+	if params.Module || params.Logpush != nil || len(params.Bindings) > 0 {
 		contentType, body, err = formatMultipartBody(params)
 		if err != nil {
 			return WorkerScriptResponse{}, err
@@ -257,8 +261,10 @@ func formatMultipartBody(params CreateWorkerParams) (string, []byte, error) {
 		BodyPart   string              `json:"body_part,omitempty"`
 		MainModule string              `json:"main_module,omitempty"`
 		Bindings   []workerBindingMeta `json:"bindings"`
+		Logpush    *bool               `json:"logpush,omitempty"`
 	}{
 		Bindings: make([]workerBindingMeta, 0, len(params.Bindings)),
+		Logpush:  params.Logpush,
 	}
 
 	if params.Module {
diff --git a/workers_kv.go b/workers_kv.go
index 8a62924b6..7cdf30e3c 100644
--- a/workers_kv.go
+++ b/workers_kv.go
@@ -153,7 +153,6 @@ func (api *API) ListWorkersKVNamespaces(ctx context.Context, rc *ResourceContain
 	var namespaces []WorkersKVNamespace
 	var nsResponse ListWorkersKVNamespacesResponse
 	for {
-		nsResponse = ListWorkersKVNamespacesResponse{}
 		uri := buildURI(fmt.Sprintf("/accounts/%s/storage/kv/namespaces", rc.Identifier), params)
 
 		res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)


Test patch:
diff --git a/workers_test.go b/workers_test.go
index 647f1af32..c76b7d053 100644
--- a/workers_test.go
+++ b/workers_test.go
@@ -277,6 +277,7 @@ func getFileDetails(r *http.Request, key string) (*multipart.FileHeader, error)
 type multipartUpload struct {
 	Script      string
 	BindingMeta map[string]workerBindingMeta
+	Logpush     *bool
 }
 
 func parseMultipartUpload(r *http.Request) (multipartUpload, error) {
@@ -290,6 +291,7 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) {
 		BodyPart   string              `json:"body_part,omitempty"`
 		MainModule string              `json:"main_module,omitempty"`
 		Bindings   []workerBindingMeta `json:"bindings"`
+		Logpush    *bool               `json:"logpush,omitempty"`
 	}
 	err = json.Unmarshal(mdBytes, &metadata)
 	if err != nil {
@@ -318,6 +320,7 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) {
 	return multipartUpload{
 		Script:      string(script),
 		BindingMeta: bindingMeta,
+		Logpush:     metadata.Logpush,
 	}, nil
 }
 
@@ -823,3 +826,36 @@ func TestUploadWorker_WithServiceBinding(t *testing.T) {
 	})
 	assert.NoError(t, err)
 }
+
+func TestUploadWorker_WithLogpush(t *testing.T) {
+	setup()
+	defer teardown()
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/foo", func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method)
+		mpUpload, err := parseMultipartUpload(r)
+		assert.NoError(t, err)
+
+		expected := true
+		assert.Equal(t, &expected, mpUpload.Logpush)
+
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprint(w, uploadWorkerResponseData)
+	})
+	res, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{ScriptName: "foo", Script: workerScript, Logpush: BoolPtr(true)})
+	formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z")
+	want := WorkerScriptResponse{
+		successResponse,
+		false,
+		WorkerScript{
+			Script: workerScript,
+			WorkerMetaData: WorkerMetaData{
+				ETAG:       "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a",
+				Size:       191,
+				ModifiedOn: formattedTime,
+			},
+		}}
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, res)
+	}
+}