Skip to content

Commit c01c4ee

Browse files
authored
Resolve container image name when modifying (#9923)
The container image name should be resolved into the full (namespaced) image name both when creating an application and when modifying an application. Move the image name resolution out of the create path and into the shared code path taken for both creation and modification.
1 parent ab75fd8 commit c01c4ee

File tree

4 files changed

+100
-21
lines changed

4 files changed

+100
-21
lines changed

.changeset/quiet-mangos-wave.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@cloudflare/containers-shared": patch
3+
"wrangler": patch
4+
---
5+
6+
Fix image name resolution when modifying a container application

packages/containers-shared/src/images.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,7 @@ export async function prepareContainerImagesForDev(
114114
* For now, this only converts images stored in the managed registry to contain
115115
* the user's account ID in the path.
116116
*/
117-
export async function resolveImageName(
118-
accountId: string,
119-
image: string
120-
): Promise<string> {
117+
export function resolveImageName(accountId: string, image: string): string {
121118
let url: URL;
122119
try {
123120
url = new URL(`http://${image}`);

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

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,7 +1858,7 @@ describe("cloudchamber apply", () => {
18581858
expect(app.configuration?.instance_type).toEqual("dev");
18591859
});
18601860

1861-
test("expands image names from managed registry", async () => {
1861+
test("expands image names from managed registry when creating an application", async () => {
18621862
setIsTTY(false);
18631863
const registry = getCloudflareContainerRegistry();
18641864
writeWranglerConfig({
@@ -1904,7 +1904,7 @@ describe("cloudchamber apply", () => {
19041904
│ tier = 2
19051905
19061906
│ [containers.configuration]
1907-
│ image = \\"${registry}/hello:1.0\\"
1907+
│ image = \\"${registry}/some-account-id/hello:1.0\\"
19081908
│ instance_type = \\"dev\\"
19091909
19101910
@@ -1915,4 +1915,79 @@ describe("cloudchamber apply", () => {
19151915
"
19161916
`);
19171917
});
1918+
1919+
test("expands image names from managed registry when modifying an application", async () => {
1920+
setIsTTY(false);
1921+
const registry = getCloudflareContainerRegistry();
1922+
writeWranglerConfig({
1923+
name: "my-container",
1924+
containers: [
1925+
{
1926+
name: "my-container-app",
1927+
instances: 3,
1928+
class_name: "DurableObjectClass",
1929+
image: `${registry}/hello:1.0`,
1930+
instance_type: "standard",
1931+
constraints: {
1932+
tier: 2,
1933+
},
1934+
},
1935+
],
1936+
});
1937+
1938+
mockGetApplications([
1939+
{
1940+
id: "abc",
1941+
name: "my-container-app",
1942+
instances: 3,
1943+
created_at: new Date().toString(),
1944+
version: 1,
1945+
account_id: "1",
1946+
scheduling_policy: SchedulingPolicy.REGIONAL,
1947+
configuration: {
1948+
image: `${registry}/some-account-id/hello:1.0`,
1949+
disk: {
1950+
size: "2GB",
1951+
size_mb: 2000,
1952+
},
1953+
vcpu: 0.0625,
1954+
memory: "256MB",
1955+
memory_mib: 256,
1956+
},
1957+
constraints: {
1958+
tier: 3,
1959+
},
1960+
},
1961+
]);
1962+
1963+
const applicationReqBodyPromise = mockModifyApplication();
1964+
await runWrangler("cloudchamber apply");
1965+
expect(std.stdout).toMatchInlineSnapshot(`
1966+
"╭ Deploy a container application deploy changes to your application
1967+
1968+
│ Container application changes
1969+
1970+
├ EDIT my-container-app
1971+
1972+
│ [containers.configuration]
1973+
│ image = \\"${registry}/some-account-id/hello:1.0\\"
1974+
│ - instance_type = \\"dev\\"
1975+
│ + instance_type = \\"standard\\"
1976+
1977+
│ [containers.constraints]
1978+
│ ...
1979+
│ - tier = 3
1980+
│ + tier = 2
1981+
1982+
1983+
│  SUCCESS  Modified application my-container-app
1984+
1985+
╰ Applied changes
1986+
1987+
"
1988+
`);
1989+
expect(std.stderr).toMatchInlineSnapshot(`""`);
1990+
const app = await applicationReqBodyPromise;
1991+
expect(app.configuration?.instance_type).toEqual("standard");
1992+
});
19181993
});

packages/wrangler/src/cloudchamber/apply.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,14 @@ function createApplicationToModifyApplication(
9393
}
9494

9595
function applicationToCreateApplication(
96+
accountId: string,
9697
application: Application
9798
): CreateApplicationRequest {
9899
const app: CreateApplicationRequest = {
99-
configuration: application.configuration,
100+
configuration: {
101+
...application.configuration,
102+
image: resolveImageName(accountId, application.configuration.image),
103+
},
100104
constraints: application.constraints,
101105
max_instances: application.max_instances,
102106
name: application.name,
@@ -194,6 +198,7 @@ function containerAppToInstanceType(
194198
}
195199

196200
function containerAppToCreateApplication(
201+
accountId: string,
197202
containerApp: ContainerApp,
198203
observability: Observability | undefined,
199204
existingApp: Application | undefined,
@@ -216,10 +221,15 @@ function containerAppToCreateApplication(
216221
telemetryMessage: true,
217222
});
218223
}
224+
219225
const app: CreateApplicationRequest = {
220226
...containerApp,
221227
name: containerApp.name,
222-
configuration,
228+
configuration: {
229+
...configuration,
230+
// De-sugar image name
231+
image: resolveImageName(accountId, configuration.image),
232+
},
223233
instances: containerApp.instances ?? 0,
224234
scheduling_policy:
225235
(containerApp.scheduling_policy as SchedulingPolicy) ??
@@ -506,7 +516,9 @@ export async function apply(
506516
appConfigNoDefaults.configuration.image = application.configuration.image;
507517
}
508518

519+
const accountId = config.account_id || (await getAccountId(config));
509520
const appConfig = containerAppToCreateApplication(
521+
accountId,
510522
appConfigNoDefaults,
511523
config.observability,
512524
application,
@@ -517,7 +529,7 @@ export async function apply(
517529
// we need to sort the objects (by key) because the diff algorithm works with
518530
// lines
519531
const prevApp = sortObjectRecursive<CreateApplicationRequest>(
520-
stripUndefined(applicationToCreateApplication(application))
532+
stripUndefined(applicationToCreateApplication(accountId, application))
521533
);
522534

523535
// fill up fields that their defaults were changed over-time,
@@ -688,18 +700,7 @@ export async function apply(
688700
printLine(el, " ");
689701
});
690702

691-
const accountId = config.account_id || (await getAccountId(config));
692-
const configToPush = {
693-
...appConfig,
694-
695-
configuration: {
696-
...appConfig.configuration,
697-
698-
// De-sugar image name. We do it here so that the user
699-
// sees the simplified image name in diffs.
700-
image: await resolveImageName(accountId, appConfig.configuration.image),
701-
},
702-
};
703+
const configToPush = { ...appConfig };
703704

704705
// add to the actions array to create the app later
705706
actions.push({

0 commit comments

Comments
 (0)