Skip to content

Commit e7cae16

Browse files
validate id in wrangler containers delete and also include container API calls in WRANGLER_LOG=debug (#10232)
* validate id for containers delete * changeset * add debug logging to containers api calls * Update packages/wrangler/src/containers/containers.ts Co-authored-by: Nikita Sharma <[email protected]> * update test * lint * feedback --------- Co-authored-by: Nikita Sharma <[email protected]>
1 parent d16de46 commit e7cae16

File tree

8 files changed

+74
-9
lines changed

8 files changed

+74
-9
lines changed

.changeset/blue-seas-visit.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+
fix: validate `wrangler containers delete ID` to ensure a valid ID has been provided. Previously if you provided the container name (or any non-ID shaped string) you would get an auth error instead of a 404.

.changeset/pink-heads-help.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+
include containers API calls in output of WRANGLER_LOG=debug

packages/containers-shared/src/client/core/OpenAPI.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* istanbul ignore file */
22
/* tslint:disable */
3+
import type { Logger } from "../../types";
34
import type { ApiRequestOptions } from "./ApiRequestOptions";
45

56
type Resolver<T> = (options: ApiRequestOptions) => Promise<T>;
@@ -15,6 +16,7 @@ export type OpenAPIConfig = {
1516
PASSWORD?: string | Resolver<string>;
1617
HEADERS?: Headers | Resolver<Headers>;
1718
ENCODE_PATH?: (path: string) => string;
19+
LOGGER?: Logger | undefined;
1820
};
1921

2022
export const OpenAPI: OpenAPIConfig = {
@@ -27,4 +29,5 @@ export const OpenAPI: OpenAPIConfig = {
2729
PASSWORD: undefined,
2830
HEADERS: undefined,
2931
ENCODE_PATH: undefined,
32+
LOGGER: undefined,
3033
};

packages/containers-shared/src/client/core/request.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ export const request = <T>(
352352
const formData = getFormData(options);
353353
const body = getRequestBody(options);
354354
const headers = await getHeaders(config, options);
355+
debugLogRequest(config, url, headers, formData ?? body ?? {});
355356

356357
if (!onCancel.isCancelled) {
357358
const response = await sendRequest(
@@ -387,7 +388,7 @@ export const request = <T>(
387388
body: responseHeader ?? responseBody,
388389
};
389390
}
390-
391+
debugLogResponse(config, result);
391392
catchErrorCodes(options, result);
392393
resolve(result.body);
393394
}
@@ -396,3 +397,38 @@ export const request = <T>(
396397
}
397398
});
398399
};
400+
401+
const debugLogRequest = async (
402+
config: OpenAPIConfig,
403+
url: string,
404+
headers: Headers,
405+
body: FormData | unknown
406+
) => {
407+
config.LOGGER?.debug(`-- START CF API REQUEST: ${url}`);
408+
const logHeaders = new Headers(headers);
409+
logHeaders.delete("Authorization");
410+
config.LOGGER?.debugWithSanitization(
411+
"HEADERS:",
412+
JSON.stringify(logHeaders, null, 2)
413+
);
414+
config.LOGGER?.debugWithSanitization(
415+
"BODY:",
416+
JSON.stringify(
417+
body instanceof FormData ? await new Response(body).text() : body,
418+
null,
419+
2
420+
)
421+
);
422+
config.LOGGER?.debug("-- END CF API REQUEST");
423+
};
424+
425+
const debugLogResponse = (config: OpenAPIConfig, response: ApiResult) => {
426+
config.LOGGER?.debug(
427+
"-- START CF API RESPONSE:",
428+
response.statusText,
429+
response.status
430+
);
431+
432+
config.LOGGER?.debugWithSanitization("RESPONSE:", response.body);
433+
config.LOGGER?.debug("-- END CF API RESPONSE");
434+
};

packages/containers-shared/src/types.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type { InstanceType, SchedulingPolicy } from "./client";
22

33
export interface Logger {
4-
debug: (message: string) => void;
5-
log: (message: string) => void;
6-
info: (message: string) => void;
7-
warn: (message: string) => void;
8-
error: (error: Error) => void;
4+
debug: (...args: unknown[]) => void;
5+
debugWithSanitization: (label: string, ...args: unknown[]) => void;
6+
log: (...args: unknown[]) => void;
7+
info: (...args: unknown[]) => void;
8+
warn: (...args: unknown[]) => void;
9+
error: (...args: unknown[]) => void;
910
}
1011

1112
export type BuildArgs = {

packages/wrangler/src/__tests__/containers/delete.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ describe("containers delete", () => {
4343
`);
4444
});
4545

46+
it("should reject invalid container ID format", async () => {
47+
setWranglerConfig({});
48+
await expect(
49+
runWrangler("containers delete invalid-id")
50+
).rejects.toMatchInlineSnapshot(
51+
`[Error: Expected a container ID but got invalid-id. Use \`wrangler containers list\` to view your containers and corresponding IDs.]`
52+
);
53+
});
54+
4655
async function testStatusCode(code: number) {
4756
setWranglerConfig({});
4857
msw.use(

packages/wrangler/src/cloudchamber/common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ export async function fillOpenAPIConfiguration(
194194
...(OpenAPI.HEADERS ?? {}),
195195
...Object.fromEntries(headers.entries()),
196196
};
197+
OpenAPI.LOGGER = logger;
197198
}
198199

199200
type NonObject = undefined | null | boolean | string | number;

packages/wrangler/src/containers/containers.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,20 @@ export function deleteYargs(args: CommonYargsArgv) {
2727
return args.positional("ID", {
2828
describe: "id of the containers to delete",
2929
type: "string",
30+
demandOption: true,
3031
});
3132
}
3233

3334
export async function deleteCommand(
3435
deleteArgs: StrictYargsOptionsToInterface<typeof deleteYargs>,
3536
_config: Config
3637
) {
37-
if (!deleteArgs.ID) {
38-
throw new Error(
39-
"You must provide an ID. Use 'wrangler containers list` to view your containers."
38+
// API gateway has path restrictions so if someone provides a string that isn't ID shaped, we get a weird error instead of a 404
39+
const uuidRegex =
40+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
41+
if (!uuidRegex.test(deleteArgs.ID)) {
42+
throw new UserError(
43+
`Expected a container ID but got ${deleteArgs.ID}. Use \`wrangler containers list\` to view your containers and corresponding IDs.`
4044
);
4145
}
4246

0 commit comments

Comments
 (0)