From f62ff97c1f26de5e635768a79067f8b6c343f060 Mon Sep 17 00:00:00 2001 From: Sunil Pai Date: Mon, 4 Jul 2022 08:51:34 +0100 Subject: [PATCH] Added support for pubsub namespace (via @elithrar in https://github.com/cloudflare/wrangler2/pull/1314) This adds support for managing pubsub namespaces and brokers (https://developers.cloudflare.com/pub-sub/) --- .changeset/rude-queens-listen.md | 7 + .../wrangler/src/__tests__/pubsub.test.ts | 18 +- .../wrangler/src/pubsub/pubsub-commands.tsx | 898 +++++++++--------- 3 files changed, 460 insertions(+), 463 deletions(-) create mode 100644 .changeset/rude-queens-listen.md diff --git a/.changeset/rude-queens-listen.md b/.changeset/rude-queens-listen.md new file mode 100644 index 000000000000..74cee99ffce6 --- /dev/null +++ b/.changeset/rude-queens-listen.md @@ -0,0 +1,7 @@ +--- +"wrangler": patch +--- + +Added support for pubsub namespace (via @elithrar in https://github.com/cloudflare/wrangler2/pull/1314) + +This adds support for managing pubsub namespaces and brokers (https://developers.cloudflare.com/pub-sub/) diff --git a/packages/wrangler/src/__tests__/pubsub.test.ts b/packages/wrangler/src/__tests__/pubsub.test.ts index 9b4f5abc96fc..ab372fe234b1 100644 --- a/packages/wrangler/src/__tests__/pubsub.test.ts +++ b/packages/wrangler/src/__tests__/pubsub.test.ts @@ -40,7 +40,7 @@ describe("wrangler", () => { it("should create a namespace", async () => { const requests = mockCreateRequest("my-namespace"); - await runWrangler("pubsub namespaces create my-namespace"); + await runWrangler("pubsub namespace create my-namespace"); // TODO: check returned object expect(requests.count).toEqual(1); }); @@ -67,7 +67,7 @@ describe("wrangler", () => { { name: "namespace-2", created_on: "01-01-2001" }, ]; const requests = mockListRequest(expectedNamespaces); - await runWrangler("pubsub namespaces list"); + await runWrangler("pubsub namespace list"); expect(std.err).toMatchInlineSnapshot(`""`); // TODO(elithrar): check returned object @@ -97,7 +97,7 @@ describe("wrangler", () => { it("should create a broker", async () => { const requests = mockCreateRequest("my-broker"); await runWrangler( - "pubsub brokers create my-broker --namespace=some-namespace" + "pubsub broker create my-broker --namespace=some-namespace" ); // TODO: check returned object @@ -106,7 +106,7 @@ describe("wrangler", () => { it("fail to create broker when no namespace is set", async () => { await expect( - runWrangler("pubsub brokers create my-broker") + runWrangler("pubsub broker create my-broker") ).rejects.toThrowErrorMatchingInlineSnapshot( `"Missing required argument: namespace"` ); @@ -151,7 +151,7 @@ describe("wrangler", () => { expectedOnPublish ); await runWrangler( - "pubsub brokers update my-broker --namespace=some-namespace --expiration=24h --description='hello' --on-publish-url='https://foo.bar.example.com'" + "pubsub broker update my-broker --namespace=some-namespace --expiration=24h --description='hello' --on-publish-url='https://foo.bar.example.com'" ); expect(std.err).toMatchInlineSnapshot(`""`); @@ -182,7 +182,7 @@ describe("wrangler", () => { { name: "broker-2", created_on: "01-01-2001" }, ]; const requests = mockListRequest(expectedBrokers); - await runWrangler("pubsub brokers list --namespace=some-namespace"); + await runWrangler("pubsub broker list --namespace=some-namespace"); expect(std.err).toMatchInlineSnapshot(`""`); // TODO(elithrar): check returned object @@ -209,7 +209,7 @@ describe("wrangler", () => { it("should describe a single broker", async () => { const requests = mockGetRequest({ id: "1234", name: "my-broker" }); await runWrangler( - "pubsub brokers describe my-broker --namespace=some-namespace" + "pubsub broker describe my-broker --namespace=some-namespace" ); expect(std.err).toMatchInlineSnapshot(`""`); @@ -236,7 +236,7 @@ describe("wrangler", () => { it("should issue a token for the broker", async () => { const requests = mockIssueRequest("my-broker"); await runWrangler( - "pubsub brokers issue my-broker --namespace=some-namespace" + "pubsub broker issue my-broker --namespace=some-namespace" ); expect(std.err).toMatchInlineSnapshot(`""`); @@ -263,7 +263,7 @@ describe("wrangler", () => { it("should return the public keys for a broker", async () => { const requests = mockIssueRequest("my-broker"); await runWrangler( - "pubsub brokers public-keys my-broker --namespace=some-namespace" + "pubsub broker public-keys my-broker --namespace=some-namespace" ); expect(std.err).toMatchInlineSnapshot(`""`); diff --git a/packages/wrangler/src/pubsub/pubsub-commands.tsx b/packages/wrangler/src/pubsub/pubsub-commands.tsx index 32f46ad7377b..b63a92f877c5 100644 --- a/packages/wrangler/src/pubsub/pubsub-commands.tsx +++ b/packages/wrangler/src/pubsub/pubsub-commands.tsx @@ -15,7 +15,7 @@ export function pubSubCommands( return pubsubYargs .command(subHelp) .command( - "namespaces", + "namespace", "Manage your Pub/Sub Namespaces", (pubsubNamespaceYargs) => { pubsubNamespaceYargs @@ -120,485 +120,475 @@ export function pubSubCommands( return pubsubNamespaceYargs; } ) - .command( - "brokers", - "Interact with your Pub/Sub Brokers", - (brokersYargs) => { - brokersYargs - .command( - "create ", - "Create a new Pub/Sub Broker", - (yargs) => - yargs - .positional("name", { - describe: - "The name of the Pub/Sub Broker. This name will form part of the public endpoint, in the form ..cloudflarepubsub.com", - type: "string", - demandOption: true, - }) - .option("namespace", { - describe: - "An existing Namespace to associate the Broker with. This name will form part of the public endpoint, in the form ..cloudflarepubsub.com", - type: "string", - alias: "ns", - demandOption: true, - }) - .option("description", { - describe: "Longer description for the broker", - type: "string", - }) - .option("expiration", { - describe: - "Time to allow token validity (can use seconds, hours, months, weeks, years)", - type: "string", - }) - .option("on-publish-url", { - describe: - "A (HTTPS) Cloudflare Worker (or webhook) URL that messages will be sent to on-publish.", - type: "string", - }), - async (args) => { - const config = readConfig(args.config as ConfigPath, args); - const accountId = await requireAuth(config); - - const broker: pubsub.PubSubBroker = { - name: args.name, - }; - if (args.description) { - broker.description = args.description; - } - if (args.expiration) { - const expiration = parseHumanDuration(args.expiration); - if (isNaN(expiration)) { - throw new CommandLineArgsError( - `${args.expiration} is not a time duration. (Example of valid values are: 1y, 6 days)` - ); - } - broker.expiration = expiration; - } - if (args["on-publish-url"]) { - broker.on_publish = { - url: args["on-publish-url"], - }; - } - - logger.log( - await pubsub.createPubSubBroker( - accountId, - args.namespace, - broker - ) - ); + .command("broker", "Interact with your Pub/Sub Brokers", (brokersYargs) => { + brokersYargs + .command( + "create ", + "Create a new Pub/Sub Broker", + (yargs) => + yargs + .positional("name", { + describe: + "The name of the Pub/Sub Broker. This name will form part of the public endpoint, in the form ..cloudflarepubsub.com", + type: "string", + demandOption: true, + }) + .option("namespace", { + describe: + "An existing Namespace to associate the Broker with. This name will form part of the public endpoint, in the form ..cloudflarepubsub.com", + type: "string", + alias: "ns", + demandOption: true, + }) + .option("description", { + describe: "Longer description for the broker", + type: "string", + }) + .option("expiration", { + describe: + "Time to allow token validity (can use seconds, hours, months, weeks, years)", + type: "string", + }) + .option("on-publish-url", { + describe: + "A (HTTPS) Cloudflare Worker (or webhook) URL that messages will be sent to on-publish.", + type: "string", + }), + async (args) => { + const config = readConfig(args.config as ConfigPath, args); + const accountId = await requireAuth(config); + + const broker: pubsub.PubSubBroker = { + name: args.name, + }; + if (args.description) { + broker.description = args.description; } - ) - .epilogue(pubsub.pubSubBetaWarning); - - brokersYargs - .command( - "update ", - "Update an existing Pub/Sub Broker's configuration.", - (yargs) => - yargs - .positional("name", { - describe: "The name of an existing Pub/Sub Broker", - type: "string", - demandOption: true, - }) - .option("namespace", { - describe: "The Namespace the Broker is associated with", - type: "string", - alias: "ns", - demandOption: true, - }) - .option("description", { - describe: "A optional description of the Broker.", - type: "string", - }) - .option("expiration", { - describe: - "The expiration date for all client credentials issued by the Broker (can use seconds, hours, months, weeks, years)", - type: "string", - }) - .option("on-publish-url", { - describe: - "A (HTTPS) Cloudflare Worker (or webhook) URL that messages will be sent to on-publish.", - type: "string", - }), - async (args) => { - const config = readConfig(args.config as ConfigPath, args); - const accountId = await requireAuth(config); - - const broker: pubsub.PubSubBrokerUpdate = {}; - - if (args.description) { - broker.description = args.description; - } - - if (args.expiration) { - const expiration = parseHumanDuration(args.expiration); - if (isNaN(expiration)) { - throw new CommandLineArgsError( - `${args.expiration} is not a time duration. Examples of valid values include: '1y', '24h', or '6 days'.` - ); - } - broker.expiration = expiration; - } - - if (args["on-publish-url"]) { - broker.on_publish = { - url: args["on-publish-url"], - }; + if (args.expiration) { + const expiration = parseHumanDuration(args.expiration); + if (isNaN(expiration)) { + throw new CommandLineArgsError( + `${args.expiration} is not a time duration. (Example of valid values are: 1y, 6 days)` + ); } - - logger.log( - await pubsub.updatePubSubBroker( - accountId, - args.namespace, - args.name, - broker - ) - ); - logger.log(`Successfully updated Pub/Sub Broker ${args.name}`); + broker.expiration = expiration; + } + if (args["on-publish-url"]) { + broker.on_publish = { + url: args["on-publish-url"], + }; } - ) - .epilogue(pubsub.pubSubBetaWarning); - brokersYargs - .command( - "list", - "List the Pub/Sub Brokers within a Namespace", - (yargs) => { - return yargs.option("namespace", { - describe: "The Namespace the Brokers are associated with.", + logger.log( + await pubsub.createPubSubBroker(accountId, args.namespace, broker) + ); + } + ) + .epilogue(pubsub.pubSubBetaWarning); + + brokersYargs + .command( + "update ", + "Update an existing Pub/Sub Broker's configuration.", + (yargs) => + yargs + .positional("name", { + describe: "The name of an existing Pub/Sub Broker", + type: "string", + demandOption: true, + }) + .option("namespace", { + describe: "The Namespace the Broker is associated with", type: "string", alias: "ns", demandOption: true, - }); - }, - async (args) => { - const config = readConfig(args.config as ConfigPath, args); - const accountId = await requireAuth(config); + }) + .option("description", { + describe: "A optional description of the Broker.", + type: "string", + }) + .option("expiration", { + describe: + "The expiration date for all client credentials issued by the Broker (can use seconds, hours, months, weeks, years)", + type: "string", + }) + .option("on-publish-url", { + describe: + "A (HTTPS) Cloudflare Worker (or webhook) URL that messages will be sent to on-publish.", + type: "string", + }), + async (args) => { + const config = readConfig(args.config as ConfigPath, args); + const accountId = await requireAuth(config); - logger.log( - await pubsub.listPubSubBrokers(accountId, args.namespace) - ); - } - ) - .epilogue(pubsub.pubSubBetaWarning); + const broker: pubsub.PubSubBrokerUpdate = {}; - brokersYargs - .command( - "delete ", - "Delete an existing Pub/Sub Broker", - (yargs) => { - return yargs - .positional("name", { - describe: "The name of the Broker to delete", - type: "string", - demandOption: true, - }) - .option("namespace", { - describe: "The Namespace the Broker is associated with.", - type: "string", - alias: "ns", - demandOption: true, - }); - }, - async (args) => { - const config = readConfig(args.config as ConfigPath, args); - const accountId = await requireAuth(config); + if (args.description) { + broker.description = args.description; + } - if ( - await confirm( - `️❗️ Are you sure you want to delete the Pub/Sub Broker ${args.name}? This cannot be undone.\nAll existing clients will be disconnected.` - ) - ) { - logger.log(`Deleting Pub/Sub Broker ${args.name}.`); - await pubsub.deletePubSubBroker( - accountId, - args.namespace, - args.name + if (args.expiration) { + const expiration = parseHumanDuration(args.expiration); + if (isNaN(expiration)) { + throw new CommandLineArgsError( + `${args.expiration} is not a time duration. Examples of valid values include: '1y', '24h', or '6 days'.` ); - logger.log(`Deleted Pub/Sub Broker ${args.name}.`); } + broker.expiration = expiration; } - ) - .epilogue(pubsub.pubSubBetaWarning); - - brokersYargs - .command( - "describe ", - "Describe an existing Pub/Sub Broker.", - (yargs) => { - return yargs - .positional("name", { - describe: "The name of the Broker to describe.", - type: "string", - demandOption: true, - }) - .option("namespace", { - describe: "The Namespace the Broker is associated with.", - type: "string", - alias: "ns", - demandOption: true, - }); - }, - async (args) => { - const config = readConfig(args.config as ConfigPath, args); - const accountId = await requireAuth(config); - - logger.log( - await pubsub.describePubSubBroker( - accountId, - args.namespace, - args.name - ) - ); - } - ) - .epilogue(pubsub.pubSubBetaWarning); - - brokersYargs - .command( - "issue ", - "Issue new client credentials for a specific Pub/Sub Broker.", - (yargs) => { - return yargs - .positional("name", { - describe: "The name of the Broker to issue credentials for.", - type: "string", - demandOption: true, - }) - .option("namespace", { - describe: "The Namespace the Broker is associated with.", - type: "string", - alias: "ns", - demandOption: true, - }) - .option("number", { - describe: "The number of credentials to generate.", - type: "number", - alias: "n", - default: 1, - }) - .option("type", { - describe: "The type of credential to generate.", - type: "string", - default: "TOKEN", - }) - .option("expiration", { - describe: - "The expiration to set on the issued credentials. This overrides any Broker-level expiration that is set.", - type: "string", - alias: "exp", - }) - .option("client-id", { - describe: - "A list of existing clientIds to generate tokens for. By default, clientIds are randomly generated.", - type: "string", - alias: "jti", - array: true, - }); - }, - async (args) => { - const config = readConfig(args.config as ConfigPath, args); - const accountId = await requireAuth(config); - - let parsedExpiration: number | undefined; - if (args.expiration) { - const expiration = parseHumanDuration(args.expiration); - if (isNaN(expiration)) { - throw new CommandLineArgsError( - `${args.expiration} is not a time duration. Example of valid values are: 1y, 6 days.` - ); - } - parsedExpiration = expiration; - } - logger.log( - `🔑 Issuing credential(s) for ${args.name}.${args.namespace}...` - ); - - logger.log( - await pubsub.issuePubSubBrokerTokens( - accountId, - args.namespace, - args.name, - args.number, - args.type, - args["client-id"], - parsedExpiration - ) - ); + if (args["on-publish-url"]) { + broker.on_publish = { + url: args["on-publish-url"], + }; } - ) - .epilogue(pubsub.pubSubBetaWarning); - brokersYargs - .command( - "revoke ", - "Revoke a set of active client credentials associated with the given Broker", - (yargs) => { - return yargs - .positional("name", { - describe: - "The name of the Broker to revoke credentials against.", - type: "string", - demandOption: true, - }) - .option("namespace", { - describe: "The Namespace the Broker is associated with.", - type: "string", - alias: "ns", - demandOption: true, - }) - .option("jti", { - describe: "Tokens to revoke", - type: "string", - demandOption: true, - array: true, - }); - }, - async (args) => { - const config = readConfig(args.config as ConfigPath, args); - const accountId = await requireAuth(config); - - const numTokens = args.jti.length; - - logger.log( - `🔴 Revoking access to ${args.name} for ${numTokens} credential(s)...` - ); - - await pubsub.revokePubSubBrokerTokens( + logger.log( + await pubsub.updatePubSubBroker( accountId, args.namespace, args.name, - args.jti - ); - - logger.log(`Revoked ${args.jti.length} credential(s).`); - } - ) - .epilogue(pubsub.pubSubBetaWarning); - - brokersYargs - .command( - "unrevoke ", - "Restore access to a set of previously revoked client credentials.", - (yargs) => { - return yargs - .positional("name", { - describe: - "The name of the Broker to revoke credentials against.", - type: "string", - demandOption: true, - }) - .option("namespace", { - describe: "The Namespace the Broker is associated with.", - type: "string", - alias: "ns", - demandOption: true, - }) - .option("jti", { - describe: "Tokens to revoke", - type: "string", - demandOption: true, - array: true, - }); - }, - async (args) => { - const config = readConfig(args.config as ConfigPath, args); - const accountId = await requireAuth(config); - - const numTokens = args.jti.length; - logger.log( - `🟢 Restoring access to ${args.broker} for ${numTokens} credential(s)...` - ); - - await pubsub.unrevokePubSubBrokerTokens( + broker + ) + ); + logger.log(`Successfully updated Pub/Sub Broker ${args.name}`); + } + ) + .epilogue(pubsub.pubSubBetaWarning); + + brokersYargs + .command( + "list", + "List the Pub/Sub Brokers within a Namespace", + (yargs) => { + return yargs.option("namespace", { + describe: "The Namespace the Brokers are associated with.", + type: "string", + alias: "ns", + demandOption: true, + }); + }, + async (args) => { + const config = readConfig(args.config as ConfigPath, args); + const accountId = await requireAuth(config); + + logger.log( + await pubsub.listPubSubBrokers(accountId, args.namespace) + ); + } + ) + .epilogue(pubsub.pubSubBetaWarning); + + brokersYargs + .command( + "delete ", + "Delete an existing Pub/Sub Broker", + (yargs) => { + return yargs + .positional("name", { + describe: "The name of the Broker to delete", + type: "string", + demandOption: true, + }) + .option("namespace", { + describe: "The Namespace the Broker is associated with.", + type: "string", + alias: "ns", + demandOption: true, + }); + }, + async (args) => { + const config = readConfig(args.config as ConfigPath, args); + const accountId = await requireAuth(config); + + if ( + await confirm( + `️❗️ Are you sure you want to delete the Pub/Sub Broker ${args.name}? This cannot be undone.\nAll existing clients will be disconnected.` + ) + ) { + logger.log(`Deleting Pub/Sub Broker ${args.name}.`); + await pubsub.deletePubSubBroker( accountId, args.namespace, - args.name, - args.jti + args.name ); - - logger.log(`Unrevoked ${numTokens} credential(s)`); + logger.log(`Deleted Pub/Sub Broker ${args.name}.`); } - ) - .epilogue(pubsub.pubSubBetaWarning); - - brokersYargs - .command( - "show-revocations ", - "Show all previously revoked client credentials.", - (yargs) => { - return yargs - .positional("name", { - describe: - "The name of the Broker to revoke credentials against.", - type: "string", - demandOption: true, - }) - .option("namespace", { - describe: "The Namespace the Broker is associated with.", - type: "string", - alias: "ns", - demandOption: true, - }); - }, - async (args) => { - const config = readConfig(args.config as ConfigPath, args); - const accountId = await requireAuth(config); + } + ) + .epilogue(pubsub.pubSubBetaWarning); + + brokersYargs + .command( + "describe ", + "Describe an existing Pub/Sub Broker.", + (yargs) => { + return yargs + .positional("name", { + describe: "The name of the Broker to describe.", + type: "string", + demandOption: true, + }) + .option("namespace", { + describe: "The Namespace the Broker is associated with.", + type: "string", + alias: "ns", + demandOption: true, + }); + }, + async (args) => { + const config = readConfig(args.config as ConfigPath, args); + const accountId = await requireAuth(config); - logger.log( - `Listing previously revoked tokens for ${args.name}...` - ); - logger.log( - await pubsub.listRevokedPubSubBrokerTokens( - accountId, - args.namespace, - args.name - ) - ); + logger.log( + await pubsub.describePubSubBroker( + accountId, + args.namespace, + args.name + ) + ); + } + ) + .epilogue(pubsub.pubSubBetaWarning); + + brokersYargs + .command( + "issue ", + "Issue new client credentials for a specific Pub/Sub Broker.", + (yargs) => { + return yargs + .positional("name", { + describe: "The name of the Broker to issue credentials for.", + type: "string", + demandOption: true, + }) + .option("namespace", { + describe: "The Namespace the Broker is associated with.", + type: "string", + alias: "ns", + demandOption: true, + }) + .option("number", { + describe: "The number of credentials to generate.", + type: "number", + alias: "n", + default: 1, + }) + .option("type", { + describe: "The type of credential to generate.", + type: "string", + default: "TOKEN", + }) + .option("expiration", { + describe: + "The expiration to set on the issued credentials. This overrides any Broker-level expiration that is set.", + type: "string", + alias: "exp", + }) + .option("client-id", { + describe: + "A list of existing clientIds to generate tokens for. By default, clientIds are randomly generated.", + type: "string", + alias: "jti", + array: true, + }); + }, + async (args) => { + const config = readConfig(args.config as ConfigPath, args); + const accountId = await requireAuth(config); + + let parsedExpiration: number | undefined; + if (args.expiration) { + const expiration = parseHumanDuration(args.expiration); + if (isNaN(expiration)) { + throw new CommandLineArgsError( + `${args.expiration} is not a time duration. Example of valid values are: 1y, 6 days.` + ); + } + parsedExpiration = expiration; } - ) - .epilogue(pubsub.pubSubBetaWarning); - brokersYargs - .command( - "public-keys ", - "Show the public keys used for verifying on-publish hooks and credentials for a Broker.", - (yargs) => { - return yargs - .positional("name", { - describe: - "The name of the Broker to revoke credentials against.", - type: "string", - demandOption: true, - }) - .option("namespace", { - describe: "The Namespace the Broker is associated with.", - type: "string", - alias: "ns", - demandOption: true, - }); - }, - async (args) => { - const config = readConfig(args.config as ConfigPath, args); - const accountId = await requireAuth(config); + logger.log( + `🔑 Issuing credential(s) for ${args.name}.${args.namespace}...` + ); - logger.log( - await pubsub.getPubSubBrokerPublicKeys( - accountId, - args.namespace, - args.name - ) - ); - } - ) - .epilogue(pubsub.pubSubBetaWarning); + logger.log( + await pubsub.issuePubSubBrokerTokens( + accountId, + args.namespace, + args.name, + args.number, + args.type, + args["client-id"], + parsedExpiration + ) + ); + } + ) + .epilogue(pubsub.pubSubBetaWarning); + + brokersYargs + .command( + "revoke ", + "Revoke a set of active client credentials associated with the given Broker", + (yargs) => { + return yargs + .positional("name", { + describe: + "The name of the Broker to revoke credentials against.", + type: "string", + demandOption: true, + }) + .option("namespace", { + describe: "The Namespace the Broker is associated with.", + type: "string", + alias: "ns", + demandOption: true, + }) + .option("jti", { + describe: "Tokens to revoke", + type: "string", + demandOption: true, + array: true, + }); + }, + async (args) => { + const config = readConfig(args.config as ConfigPath, args); + const accountId = await requireAuth(config); + + const numTokens = args.jti.length; + + logger.log( + `🔴 Revoking access to ${args.name} for ${numTokens} credential(s)...` + ); + + await pubsub.revokePubSubBrokerTokens( + accountId, + args.namespace, + args.name, + args.jti + ); + + logger.log(`Revoked ${args.jti.length} credential(s).`); + } + ) + .epilogue(pubsub.pubSubBetaWarning); + + brokersYargs + .command( + "unrevoke ", + "Restore access to a set of previously revoked client credentials.", + (yargs) => { + return yargs + .positional("name", { + describe: + "The name of the Broker to revoke credentials against.", + type: "string", + demandOption: true, + }) + .option("namespace", { + describe: "The Namespace the Broker is associated with.", + type: "string", + alias: "ns", + demandOption: true, + }) + .option("jti", { + describe: "Tokens to revoke", + type: "string", + demandOption: true, + array: true, + }); + }, + async (args) => { + const config = readConfig(args.config as ConfigPath, args); + const accountId = await requireAuth(config); + + const numTokens = args.jti.length; + logger.log( + `🟢 Restoring access to ${args.broker} for ${numTokens} credential(s)...` + ); + + await pubsub.unrevokePubSubBrokerTokens( + accountId, + args.namespace, + args.name, + args.jti + ); + + logger.log(`Unrevoked ${numTokens} credential(s)`); + } + ) + .epilogue(pubsub.pubSubBetaWarning); + + brokersYargs + .command( + "show-revocations ", + "Show all previously revoked client credentials.", + (yargs) => { + return yargs + .positional("name", { + describe: + "The name of the Broker to revoke credentials against.", + type: "string", + demandOption: true, + }) + .option("namespace", { + describe: "The Namespace the Broker is associated with.", + type: "string", + alias: "ns", + demandOption: true, + }); + }, + async (args) => { + const config = readConfig(args.config as ConfigPath, args); + const accountId = await requireAuth(config); + + logger.log(`Listing previously revoked tokens for ${args.name}...`); + logger.log( + await pubsub.listRevokedPubSubBrokerTokens( + accountId, + args.namespace, + args.name + ) + ); + } + ) + .epilogue(pubsub.pubSubBetaWarning); + + brokersYargs + .command( + "public-keys ", + "Show the public keys used for verifying on-publish hooks and credentials for a Broker.", + (yargs) => { + return yargs + .positional("name", { + describe: + "The name of the Broker to revoke credentials against.", + type: "string", + demandOption: true, + }) + .option("namespace", { + describe: "The Namespace the Broker is associated with.", + type: "string", + alias: "ns", + demandOption: true, + }); + }, + async (args) => { + const config = readConfig(args.config as ConfigPath, args); + const accountId = await requireAuth(config); - return brokersYargs; - } - ); + logger.log( + await pubsub.getPubSubBrokerPublicKeys( + accountId, + args.namespace, + args.name + ) + ); + } + ) + .epilogue(pubsub.pubSubBetaWarning); + + return brokersYargs; + }); }