Skip to content

Commit 5ab035d

Browse files
authored
containers: allow users to specify the kind of container rollout they want (#9151)
1 parent 6f62053 commit 5ab035d

File tree

5 files changed

+132
-13
lines changed

5 files changed

+132
-13
lines changed

.changeset/grumpy-baboons-post.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
wrangler containers can be configured with the kind of application rollout on `apply`

packages/wrangler/src/__tests__/cloudchamber/apply.test.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,88 @@ describe("cloudchamber apply", () => {
303303
/* eslint-enable */
304304
});
305305

306+
test("can skip a simple existing application and create other", async () => {
307+
setIsTTY(false);
308+
writeAppConfiguration(
309+
{
310+
name: "my-container-app",
311+
instances: 4,
312+
class_name: "DurableObjectClass",
313+
configuration: {
314+
image: "./Dockerfile",
315+
},
316+
rollout_kind: "none",
317+
},
318+
{
319+
name: "my-container-app-2",
320+
instances: 1,
321+
class_name: "DurableObjectClass2",
322+
configuration: {
323+
image: "other-app/Dockerfile",
324+
},
325+
}
326+
);
327+
mockGetApplications([
328+
{
329+
id: "abc",
330+
name: "my-container-app",
331+
instances: 3,
332+
created_at: new Date().toString(),
333+
account_id: "1",
334+
version: 1,
335+
scheduling_policy: SchedulingPolicy.REGIONAL,
336+
configuration: {
337+
image: "./Dockerfile",
338+
},
339+
constraints: {
340+
tier: 1,
341+
},
342+
},
343+
]);
344+
mockCreateApplication({ id: "abc" } as Application);
345+
await runWrangler("cloudchamber apply --json");
346+
347+
/* eslint-disable */
348+
expect(std.stdout).toMatchInlineSnapshot(`
349+
"╭ Deploy a container application deploy changes to your application
350+
351+
│ Container application changes
352+
353+
├ EDIT my-container-app
354+
355+
│ [[containers]]
356+
│ - instances = 3
357+
│ + instances = 4
358+
│ name = \\"my-container-app\\"
359+
│ Skipping application rollout
360+
361+
├ NEW my-container-app-2
362+
363+
│ [[containers]]
364+
│ name = \\"my-container-app-2\\"
365+
│ instances = 1
366+
│ scheduling_policy = \\"regional\\"
367+
368+
│ [containers.configuration]
369+
│ image = \\"other-app/Dockerfile\\"
370+
371+
│ [containers.constraints]
372+
│ tier = 1
373+
374+
├ Do you want to apply these changes?
375+
│ yes
376+
377+
378+
│  SUCCESS  Created application my-container-app-2 (Application ID: abc)
379+
380+
╰ Applied changes
381+
382+
"
383+
`);
384+
expect(std.stderr).toMatchInlineSnapshot(`""`);
385+
/* eslint-enable */
386+
});
387+
306388
test("can apply a simple existing application and create other", async () => {
307389
setIsTTY(false);
308390
writeAppConfiguration(

packages/wrangler/src/cloudchamber/apply.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ function containerAppToCreateApplication(
139139
delete (app as Record<string, unknown>)["image_build_context"];
140140
delete (app as Record<string, unknown>)["image_vars"];
141141
delete (app as Record<string, unknown>)["rollout_step_percentage"];
142+
delete (app as Record<string, unknown>)["rollout_kind"];
142143

143144
return app;
144145
}
@@ -366,6 +367,7 @@ export async function apply(
366367
id: ApplicationID;
367368
name: ApplicationName;
368369
rollout_step_percentage?: number;
370+
rollout_kind: CreateApplicationRolloutRequest.kind;
369371
}
370372
)[] = [];
371373

@@ -499,19 +501,24 @@ export async function apply(
499501
}
500502
}
501503

502-
actions.push({
503-
action: "modify",
504-
application: createApplicationToModifyApplication(appConfig),
505-
id: application.id,
506-
name: application.name,
507-
// The rollout logic is still pretty much attached
508-
// to the fact of the container application using DOs.
509-
// When we allow rollouts on non-DO, this should not be necessary.
510-
rollout_step_percentage:
511-
application.durable_objects !== undefined
512-
? appConfigNoDefaults.rollout_step_percentage ?? 25
513-
: undefined,
514-
});
504+
if (appConfigNoDefaults.rollout_kind !== "none") {
505+
actions.push({
506+
action: "modify",
507+
application: createApplicationToModifyApplication(appConfig),
508+
id: application.id,
509+
name: application.name,
510+
rollout_step_percentage:
511+
application.durable_objects !== undefined
512+
? appConfigNoDefaults.rollout_step_percentage ?? 25
513+
: appConfigNoDefaults.rollout_step_percentage,
514+
rollout_kind:
515+
appConfigNoDefaults.rollout_kind == "full_manual"
516+
? CreateApplicationRolloutRequest.kind.FULL_MANUAL
517+
: CreateApplicationRolloutRequest.kind.FULL_AUTO,
518+
});
519+
} else {
520+
log("Skipping application rollout");
521+
}
515522

516523
printLine("");
517524
continue;
@@ -675,6 +682,7 @@ export async function apply(
675682
(action.application
676683
.configuration as ModifyDeploymentV2RequestBody) ?? {},
677684
step_percentage: action.rollout_step_percentage,
685+
kind: action.rollout_kind,
678686
}),
679687
{
680688
json: args.json,

packages/wrangler/src/config/environment.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ export type ContainerApp = {
9595

9696
/** How a rollout should be done, defining the size of it */
9797
rollout_step_percentage?: number;
98+
99+
/**
100+
* How a rollout should be created. It supports the following modes:
101+
* - full_auto: The container application will be rolled out fully automatically.
102+
* - none: The container application won't have a roll out or update.
103+
* - manual: The container application will be rollout fully by manually actioning progress steps.
104+
*/
105+
rollout_kind?: "full_auto" | "none" | "full_manual";
98106
};
99107

100108
/**

packages/wrangler/src/config/validation.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2331,6 +2331,22 @@ const validateContainerAppConfig: ValidatorFn = (
23312331
}
23322332
}
23332333

2334+
if (
2335+
"rollout_kind" in containerAppOptional &&
2336+
containerAppOptional.rollout_kind !== undefined
2337+
) {
2338+
if (
2339+
typeof containerAppOptional.rollout_kind !== "string" ||
2340+
!["full_auto", "full_manual", "none"].includes(
2341+
containerAppOptional.rollout_kind
2342+
)
2343+
) {
2344+
diagnostics.errors.push(
2345+
`"containers.rollout_kind" should be either 'full_auto', 'full_manual' or 'none', but got ${containerAppOptional.rollout_kind}`
2346+
);
2347+
}
2348+
}
2349+
23342350
if (
23352351
"image" in containerAppOptional &&
23362352
containerAppOptional.image !== undefined

0 commit comments

Comments
 (0)