Repository: cloudflare/cloudflare-go
Pull request #1176 (2023-01-11 21:04:40)

Add queue binding type for workers scripts
## Description

Adds the Queue binding type. Workers scripts use this binding to write messages to a Queue.

## Has your change been tested?

* Added new unit test
* Manually tested alongside terraform provider changes here: https://github.com/cloudflare/terraform-provider-cloudflare/pull/2134

## 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:

- [ ] 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.
- [ ] All new and existing tests passed.
- [ ] 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/


codecov-commenter: # [Codecov](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) Report
> Merging [#1176](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) (a3d8914) 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.04%`.
> The diff coverage is `47.43%`.

```diff
@@            Coverage Diff             @@
##           master    #1176      +/-   ##
==========================================
- Coverage   49.40%   49.35%   -0.05%     
==========================================
  Files         127      128       +1     
  Lines       12290    12432     +142     
==========================================
+ Hits         6072     6136      +64     
- Misses       4840     4892      +52     
- Partials     1378     1404      +26     
```


| [Impacted Files](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) | Coverage Δ | |
|---|---|---|
| [access\_organization.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-YWNjZXNzX29yZ2FuaXphdGlvbi5nbw==) | `64.70% <ø> (ø)` | |
| [cloudflare\_experimental.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-Y2xvdWRmbGFyZV9leHBlcmltZW50YWwuZ28=) | `0.00% <0.00%> (ø)` | |
| [utils.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-dXRpbHMuZ28=) | `72.72% <ø> (ø)` | |
| [cloudflare.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-Y2xvdWRmbGFyZS5nbw==) | `68.37% <14.28%> (-0.34%)` | :arrow_down: |
| [mtls\_certificates.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?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%> (ø)` | |
| [workers\_bindings.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-d29ya2Vyc19iaW5kaW5ncy5nbw==) | `67.44% <40.00%> (-2.31%)` | :arrow_down: |
| [origin\_ca.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-b3JpZ2luX2NhLmdv) | `57.26% <90.90%> (-2.09%)` | :arrow_down: |
| [dns.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-ZG5zLmdv) | `72.97% <96.22%> (+9.24%)` | :arrow_up: |
| [devices\_managed\_networks.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-ZGV2aWNlc19tYW5hZ2VkX25ldHdvcmtzLmdv) | `41.55% <100.00%> (+9.09%)` | :arrow_up: |
| [email\_routing\_destination.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-ZW1haWxfcm91dGluZ19kZXN0aW5hdGlvbi5nbw==) | `66.66% <100.00%> (+0.41%)` | :arrow_up: |
| ... and [10 more](https://codecov.io/gh/cloudflare/cloudflare-go/pull/1176?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) | |

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)

jbw1991: Changelog entry added!

As far as the API docs go, the workers script upload endpoint is documented (https://api.cloudflare.com/#worker-script-upload-worker) but it looks like it does not specifically cover each individual binding type.

I'm not sure if this repo contains documentation for the various workers binding types, but LMK if so and I can add a description.

Patch:
diff --git a/.changelog/1176.txt b/.changelog/1176.txt
new file mode 100644
index 000000000..4d3e6d894
--- /dev/null
+++ b/.changelog/1176.txt
@@ -0,0 +1,3 @@
+```release-note:enhancement
+workers: script upload now supports Queues bindings
+```
\ No newline at end of file
diff --git a/workers_bindings.go b/workers_bindings.go
index 963106589..11f4ba7cd 100644
--- a/workers_bindings.go
+++ b/workers_bindings.go
@@ -39,6 +39,8 @@ const (
 	WorkerR2BucketBindingType WorkerBindingType = "r2_bucket"
 	// WorkerAnalyticsEngineBindingType is the type for Analytics Engine dataset bindings.
 	WorkerAnalyticsEngineBindingType WorkerBindingType = "analytics_engine"
+	// WorkerQueueBindingType is the type for queue bindings.
+	WorkerQueueBindingType WorkerBindingType = "queue"
 )
 
 type ListWorkerBindingsParams struct {
@@ -309,6 +311,34 @@ func (b WorkerAnalyticsEngineBinding) serialize(bindingName string) (workerBindi
 	}, nil, nil
 }
 
+// WorkerQueueBinding is a binding to a Workers Queue.
+//
+// https://developers.cloudflare.com/workers/platform/bindings/#queue-bindings
+type WorkerQueueBinding struct {
+	Binding string
+	Queue   string
+}
+
+// Type returns the type of the binding.
+func (b WorkerQueueBinding) Type() WorkerBindingType {
+	return WorkerQueueBindingType
+}
+
+func (b WorkerQueueBinding) serialize(bindingName string) (workerBindingMeta, workerBindingBodyWriter, error) {
+	if b.Binding == "" {
+		return nil, nil, fmt.Errorf(`Binding name for binding "%s" cannot be empty`, bindingName)
+	}
+	if b.Queue == "" {
+		return nil, nil, fmt.Errorf(`Queue name for binding "%s" cannot be empty`, bindingName)
+	}
+
+	return workerBindingMeta{
+		"type":       b.Type(),
+		"name":       b.Binding,
+		"queue_name": b.Queue,
+	}, nil, nil
+}
+
 // Each binding that adds a part to the multipart form body will need
 // a unique part name so we just generate a random 128bit hex string.
 func getRandomPartName() string {
@@ -377,6 +407,12 @@ func (api *API) ListWorkerBindings(ctx context.Context, rc *ResourceContainer, p
 			bindingListItem.Binding = WorkerKvNamespaceBinding{
 				NamespaceID: namespaceID,
 			}
+		case WorkerQueueBindingType:
+			queueName := jsonBinding["queue_name"].(string)
+			bindingListItem.Binding = WorkerQueueBinding{
+				Binding: name,
+				Queue:   queueName,
+			}
 		case WorkerWebAssemblyBindingType:
 			bindingListItem.Binding = WorkerWebAssemblyBinding{
 				Module: &bindingContentReader{


Test patch:
diff --git a/workers_test.go b/workers_test.go
index b9b7fc2d6..348abed24 100644
--- a/workers_test.go
+++ b/workers_test.go
@@ -896,3 +896,40 @@ func TestUploadWorker_WithCompatibilityFlags(t *testing.T) {
 	})
 	assert.NoError(t, err)
 }
+
+func TestUploadWorker_WithQueueBinding(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := 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)
+
+		expectedBindings := map[string]workerBindingMeta{
+			"b1": {
+				"name":       "b1",
+				"type":       "queue",
+				"queue_name": "test-queue",
+			},
+		}
+		assert.Equal(t, workerScript, mpUpload.Script)
+		assert.Equal(t, expectedBindings, mpUpload.BindingMeta)
+
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprint(w, uploadWorkerResponseData)
+	}
+	mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler)
+
+	_, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{
+		ScriptName: "bar",
+		Script:     workerScript,
+		Bindings: map[string]WorkerBinding{
+			"b1": WorkerQueueBinding{
+				Binding: "b1",
+				Queue:   "test-queue",
+			},
+		}})
+	assert.NoError(t, err)
+}