Skip to content

Commit

Permalink
Add Placement to Pages & Workers
Browse files Browse the repository at this point in the history
  • Loading branch information
WalshyDev committed May 9, 2023
1 parent 9388783 commit 536b53c
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 7 deletions.
7 changes: 7 additions & 0 deletions .changelog/1279.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
pages: add support for Smart Placement. Added `Placement` in `PagesProjectDeploymentConfigEnvironment`.
```

```release-note:enhancement
workers: add support for Smart Placement. Added `Placement` in `CreateWorkerParams`.
```
2 changes: 2 additions & 0 deletions pages_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type PagesProjectDeploymentConfigEnvironment struct {
FailOpen bool `json:"fail_open"`
AlwaysUseLatestCompatibilityDate bool `json:"always_use_latest_compatibility_date"`
UsageModel UsageModel `json:"usage_model,omitempty"`
Placement *Placement `json:"placement,omitempty"`
}

// PagesProjectDeployment represents a deployment to a Pages project.
Expand All @@ -98,6 +99,7 @@ type PagesProjectDeployment struct {
D1Databases D1BindingMap `json:"d1_databases,omitempty"`
R2Bindings R2BindingMap `json:"r2_buckets,omitempty"`
ServiceBindings ServiceBindingMap `json:"services,omitempty"`
Placement *Placement `json:"placement,omitempty"`
DeploymentTrigger PagesProjectDeploymentTrigger `json:"deployment_trigger"`
Stages []PagesProjectDeploymentStage `json:"stages"`
BuildConfig PagesProjectBuildConfig `json:"build_config"`
Expand Down
17 changes: 16 additions & 1 deletion pages_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ const (
"compatibility_flags": ["production_flag"],
"fail_open": false,
"always_use_latest_compatibility_date": false,
"usage_model": "bundled"
"usage_model": "bundled",
"placement": {
"mode": "smart"
}
}
},
"latest_deployment": {
Expand Down Expand Up @@ -144,6 +147,9 @@ const (
"type": "secret_text"
}
},
"placement": {
"mode": "smart"
},
"compatibility_date": "2022-08-15",
"compatibility_flags": ["deployment_flag"],
"fail_open": false,
Expand Down Expand Up @@ -231,6 +237,9 @@ const (
"type": "secret_text"
}
},
"placement": {
"mode": "smart"
},
"compatibility_date": "2022-08-15",
"compatibility_flags": ["deployment_flag"],
"fail_open": false,
Expand Down Expand Up @@ -339,6 +348,9 @@ var (
Type: SecretText,
},
},
Placement: &Placement{
Mode: PlacementModeSmart,
},
CompatibilityFlags: []string{"deployment_flag"},
CompatibilityDate: "2022-08-15",
UsageModel: Bundled,
Expand Down Expand Up @@ -452,6 +464,9 @@ var (
FailOpen: false,
AlwaysUseLatestCompatibilityDate: false,
UsageModel: Bundled,
Placement: &Placement{
Mode: PlacementModeSmart,
},
}

expectedPagesProjectSource = &PagesProjectSource{
Expand Down
31 changes: 25 additions & 6 deletions workers.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type CreateWorkerParams struct {
// usually used together with CompatibilityDate.
// https://developers.cloudflare.com/workers/platform/compatibility-dates/#compatibility-flags
CompatibilityFlags []string

Placement *Placement
}

// WorkerScriptParams provides a worker script and the associated bindings.
Expand Down Expand Up @@ -90,11 +92,15 @@ type WorkerScript struct {

// WorkerMetaData contains worker script information such as size, creation & modification dates.
type WorkerMetaData struct {
ID string `json:"id,omitempty"`
ETAG string `json:"etag,omitempty"`
Size int `json:"size,omitempty"`
CreatedOn time.Time `json:"created_on,omitempty"`
ModifiedOn time.Time `json:"modified_on,omitempty"`
ID string `json:"id,omitempty"`
ETAG string `json:"etag,omitempty"`
Size int `json:"size,omitempty"`
CreatedOn time.Time `json:"created_on,omitempty"`
ModifiedOn time.Time `json:"modified_on,omitempty"`
Logpush *bool `json:"logpush,omitempty"`
LastDeployedFrom *string `json:"last_deployed_from,omitempty"`
DeploymentId *string `json:"deployment_id,omitempty"`
PlacementMode *PlacementMode `json:"placement_mode,omitempty"`
}

// WorkerListResponse wrapper struct for API response to worker script list API call.
Expand All @@ -117,6 +123,17 @@ type DeleteWorkerParams struct {
ScriptName string
}

type PlacementMode string

const (
PlacementModeOff PlacementMode = ""
PlacementModeSmart PlacementMode = "smart"
)

type Placement struct {
Mode PlacementMode `json:"mode"`
}

// DeleteWorker deletes a single Worker.
//
// API reference: https://api.cloudflare.com/#worker-script-delete-worker
Expand Down Expand Up @@ -234,7 +251,7 @@ func (api *API) UploadWorker(ctx context.Context, rc *ResourceContainer, params
err error
)

if params.Module || params.Logpush != nil || len(params.Bindings) > 0 || params.CompatibilityDate != "" || len(params.CompatibilityFlags) > 0 {
if params.Module || params.Logpush != nil || params.Placement != nil || len(params.Bindings) > 0 || params.CompatibilityDate != "" || len(params.CompatibilityFlags) > 0 {
contentType, body, err = formatMultipartBody(params)
if err != nil {
return WorkerScriptResponse{}, err
Expand Down Expand Up @@ -274,11 +291,13 @@ func formatMultipartBody(params CreateWorkerParams) (string, []byte, error) {
Logpush *bool `json:"logpush,omitempty"`
CompatibilityDate string `json:"compatibility_date,omitempty"`
CompatibilityFlags []string `json:"compatibility_flags,omitempty"`
Placement *Placement `json:"placement,omitempty"`
}{
Bindings: make([]workerBindingMeta, 0, len(params.Bindings)),
Logpush: params.Logpush,
CompatibilityDate: params.CompatibilityDate,
CompatibilityFlags: params.CompatibilityFlags,
Placement: params.Placement,
}

if params.Module {
Expand Down
63 changes: 63 additions & 0 deletions workers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,18 @@ export default {
}
--workermodulescriptdownload--
`
uploadModuleWorkerSmartPlacement = `{
"result": {
"script": "export default {\n async fetch(request, env, event) {\n event.passThroughOnException()\n return fetch(request)\n }\n}",
"etag": "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a",
"size": 191,
"modified_on": "2018-06-09T15:17:01.989141Z",
"placement_mode": "smart"
},
"success": true,
"errors": [],
"messages": []
}`
)

var (
Expand Down Expand Up @@ -280,6 +292,7 @@ type multipartUpload struct {
Logpush *bool
CompatibilityDate string
CompatibilityFlags []string
Placement *Placement
}

func parseMultipartUpload(r *http.Request) (multipartUpload, error) {
Expand All @@ -296,6 +309,7 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) {
Logpush *bool `json:"logpush,omitempty"`
CompatibilityDate string `json:"compatibility_date,omitempty"`
CompatibilityFlags []string `json:"compatibility_flags,omitempty"`
Placement *Placement `json:"placement,omitempty"`
}
err = json.Unmarshal(mdBytes, &metadata)
if err != nil {
Expand Down Expand Up @@ -327,6 +341,7 @@ func parseMultipartUpload(r *http.Request) (multipartUpload, error) {
Logpush: metadata.Logpush,
CompatibilityDate: metadata.CompatibilityDate,
CompatibilityFlags: metadata.CompatibilityFlags,
Placement: metadata.Placement,
}, nil
}

Expand Down Expand Up @@ -933,3 +948,51 @@ func TestUploadWorker_WithQueueBinding(t *testing.T) {
}})
assert.NoError(t, err)
}

func TestUploadWorker_WithSmartPlacementEnabled(t *testing.T) {
setup()
defer teardown()

placementMode := PlacementModeSmart
response := uploadModuleWorkerSmartPlacement

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)

assert.Equal(t, workerScript, mpUpload.Script)

w.Header().Set("content-type", "application/json")
fmt.Fprint(w, response)
}
mux.HandleFunc("/accounts/"+testAccountID+"/workers/scripts/bar", handler)

t.Run("Test enabling Smart Placement", func(t *testing.T) {
worker, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{
ScriptName: "bar",
Script: workerScript,
Placement: &Placement{
Mode: placementMode,
},
})
assert.NoError(t, err)
assert.Equal(t, placementMode, *worker.PlacementMode)
})

t.Run("Test disabling placement", func(t *testing.T) {
placementMode = PlacementModeOff
response = uploadWorkerModuleResponseData

worker, err := client.UploadWorker(context.Background(), AccountIdentifier(testAccountID), CreateWorkerParams{
ScriptName: "bar",
Script: workerScript,
Placement: &Placement{
Mode: placementMode,
},
})
assert.NoError(t, err)
assert.Nil(t, worker.PlacementMode)
})
}

0 comments on commit 536b53c

Please sign in to comment.