Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace console.foo with helper functions #21

Merged
merged 3 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,16 @@ module.exports = {
{ checkIntersections: false },
],
"@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }],
// Allow console.log() statements
"no-console": "off",
// Use `print1` and `print2` instead
"no-console": "error",
},
ignorePatterns: [
".eslintrc.js",
"prettier.config.js",
"jest.config.js",
"public/**",
"build/**",
"__mocks__/**",
"node_modules/**",
],
overrides: [],
Expand Down
16 changes: 8 additions & 8 deletions src/commands/__tests__/__snapshots__/ls.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ls when error should print error message 1`] = `
exports[`ls when error should print1error message 1`] = `
{
"error": "p0 ls

Expand All @@ -16,21 +16,21 @@ Unknown argument: foo",
}
`;

exports[`ls when valid ls command should print list response 1`] = `
exports[`ls when valid ls command should print1list response 1`] = `
[
[
"Showing destinations:",
"instance-1",
],
[
"instance-2",
],
]
`;

exports[`ls when valid ls command should print list response 2`] = `
exports[`ls when valid ls command should print1list response 2`] = `
[
[
"instance-1",
],
[
"instance-2",
"Showing destinations:",
],
]
`;
8 changes: 4 additions & 4 deletions src/commands/__tests__/__snapshots__/request.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`request when error should print error message 1`] = `
exports[`request when error should print1error message 1`] = `
{
"error": "p0 request

Expand All @@ -18,23 +18,23 @@ Unknown argument: foo",
}
`;

exports[`request when valid request command preexisting=false persistent=false should print request response 1`] = `
exports[`request when valid request command preexisting=false persistent=false should print1request response 1`] = `
[
[
"a message",
],
]
`;

exports[`request when valid request command preexisting=false persistent=true should print request response 1`] = `
exports[`request when valid request command preexisting=false persistent=true should print1request response 1`] = `
[
[
"a message",
],
]
`;

exports[`request when valid request command preexisting=true persistent=false should print request response 1`] = `
exports[`request when valid request command preexisting=true persistent=false should print1request response 1`] = `
[
[
"a message",
Expand Down
14 changes: 8 additions & 6 deletions src/commands/__tests__/ls.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { fetchCommand } from "../../drivers/api";
import { print1, print2 } from "../../drivers/stdio";
import { lsCommand } from "../ls";
import yargs from "yargs";

jest.mock("../../drivers/api");
jest.mock("../../drivers/auth");
jest.mock("../../drivers/stdio");

const mockFetchCommand = fetchCommand as jest.Mock;
const stdout = jest.spyOn(global.console, "log");
const stderr = jest.spyOn(global.console, "error");
const mockPrint1 = print1 as jest.Mock;
const mockPrint2 = print2 as jest.Mock;

describe("ls", () => {
describe("when valid ls command", () => {
Expand All @@ -22,10 +24,10 @@ describe("ls", () => {
});
});

it("should print list response", async () => {
it("should print1list response", async () => {
await lsCommand(yargs).parse(command);
expect(stderr.mock.calls).toMatchSnapshot();
expect(stdout.mock.calls).toMatchSnapshot();
expect(mockPrint1.mock.calls).toMatchSnapshot();
expect(mockPrint2.mock.calls).toMatchSnapshot();
});
});

Expand All @@ -48,7 +50,7 @@ Unknown argument: foo`,
});
});

it("should print error message", async () => {
it("should print1error message", async () => {
let error: any;
try {
await lsCommand(yargs)
Expand Down
18 changes: 10 additions & 8 deletions src/commands/__tests__/request.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { fetchCommand } from "../../drivers/api";
import { print1, print2 } from "../../drivers/stdio";
import { RequestResponse } from "../../types/request";
import { sleep } from "../../util";
import { requestCommand } from "../request";
Expand All @@ -7,10 +8,11 @@ import yargs from "yargs";

jest.mock("../../drivers/api");
jest.mock("../../drivers/auth");
jest.mock("../../drivers/stdio");

const mockFetchCommand = fetchCommand as jest.Mock;
const stdout = jest.spyOn(global.console, "log");
const stderr = jest.spyOn(global.console, "error");
const mockPrint1 = print1 as jest.Mock;
const mockPrint2 = print2 as jest.Mock;

describe("request", () => {
beforeEach(() => jest.clearAllMocks());
Expand All @@ -36,11 +38,11 @@ describe("request", () => {
])(
"preexisting=%p persistent=%p",
(isPreexisting, isPersistent, should) => {
it(`should${should ? "" : " not"} print request response`, async () => {
it(`should${should ? "" : " not"} print1request response`, async () => {
mockFetch({ isPreexisting, isPersistent });
await requestCommand(yargs).parse(command);
expect(stderr.mock.calls).toMatchSnapshot();
expect(stdout).not.toHaveBeenCalled();
expect(mockPrint2.mock.calls).toMatchSnapshot();
expect(mockPrint1).not.toHaveBeenCalled();
});
}
);
Expand All @@ -54,8 +56,8 @@ describe("request", () => {
status: "DONE",
});
await expect(promise).resolves.toBeDefined();
expect(stderr.mock.calls).toMatchSnapshot();
expect(stdout).not.toHaveBeenCalled();
expect(mockPrint2.mock.calls).toMatchSnapshot();
expect(mockPrint1).not.toHaveBeenCalled();
});
});

Expand All @@ -80,7 +82,7 @@ Unknown argument: foo`,
});
});

it("should print error message", async () => {
it("should print1error message", async () => {
let error: any;
try {
await requestCommand(yargs)
Expand Down
11 changes: 6 additions & 5 deletions src/commands/aws/role.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { parseXml } from "../../common/xml";
import { authenticate } from "../../drivers/auth";
import { guard } from "../../drivers/firestore";
import { print1, print2 } from "../../drivers/stdio";
import { getAwsConfig } from "../../plugins/aws/config";
import { AwsItemConfig, AwsOktaSamlUidLocation } from "../../plugins/aws/types";
import { assumeRoleWithOktaSaml } from "../../plugins/okta/aws";
Expand Down Expand Up @@ -75,15 +76,15 @@ const oktaAwsAssumeRole = async (args: { account?: string; role: string }) => {
const authn = await authenticate();
const awsCredential = await assumeRoleWithOktaSaml(authn, args);
const isTty = sys.writeOutputIsTTY?.();
if (isTty) console.error("Execute the following commands:\n");
if (isTty) print2("Execute the following commands:\n");
const indent = isTty ? " " : "";
console.log(
print1(
Object.entries(awsCredential)
.map(([key, value]) => `${indent}export ${key}=${value}`)
.join("\n")
);
if (isTty)
console.error(`
print2(`
Or, populate these environment variables using BASH command substitution:

$(p0 aws${args.account ? ` --account ${args.account}` : ""} role assume ${
Expand Down Expand Up @@ -115,13 +116,13 @@ const oktaAwsListRoles = async (args: { account?: string }) => {
.filter((r) => r.startsWith(`arn:aws:iam::${account}:role/`))
.map((r) => r.split("/").slice(1).join("/"));
const isTty = sys.writeOutputIsTTY?.();
if (isTty) console.error(`Your available roles for account ${account}:`);
if (isTty) print2(`Your available roles for account ${account}:`);
if (!roles?.length) {
const accounts = uniq(arns.map((a) => a.split(":")[4])).sort();
throw `No roles found. You have roles on these accounts:\n${accounts.join(
"\n"
)}`;
}
const indent = isTty ? " " : "";
console.log(roles.map((r) => `${indent}${r}`).join("\n"));
print1(roles.map((r) => `${indent}${r}`).join("\n"));
};
7 changes: 4 additions & 3 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { print2 } from "../drivers/stdio";
import { awsCommand } from "./aws";
import { loginCommand } from "./login";
import { lsCommand } from "./ls";
Expand All @@ -22,10 +23,10 @@ export const cli = commands
.version(VERSION)
.demandCommand(1)
.fail((message, error, yargs) => {
if (error) console.error(error);
if (error) print2(error);
else {
console.error(yargs.help());
console.error(`\n${message}`);
print2(yargs.help());
print2(`\n${message}`);
}
sys.exit(1);
});
5 changes: 3 additions & 2 deletions src/commands/login.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IDENTITY_FILE_PATH, authenticate } from "../drivers/auth";
import { doc, guard } from "../drivers/firestore";
import { print2 } from "../drivers/stdio";
import { googleLogin } from "../plugins/google/login";
import { oktaLogin } from "../plugins/okta/login";
import { TokenResponse } from "../types/oidc";
Expand Down Expand Up @@ -39,12 +40,12 @@ export const login = async (
// validate auth
if (!options?.skipAuthenticate) await authenticate({ noRefresh: true });

console.error(`You are now logged in, and can use the p0 CLI.`);
print2(`You are now logged in, and can use the p0 CLI.`);
};

const writeIdentity = async (org: OrgData, credential: TokenResponse) => {
const expires_at = Date.now() * 1e-3 + credential.expires_in - 1; // Add 1 second safety margin
console.error(`Saving authorization to ${IDENTITY_FILE_PATH}.`);
print2(`Saving authorization to ${IDENTITY_FILE_PATH}.`);
const dir = path.dirname(IDENTITY_FILE_PATH);
await fs.mkdir(dir, { recursive: true });
await fs.writeFile(
Expand Down
5 changes: 3 additions & 2 deletions src/commands/ls.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { fetchCommand } from "../drivers/api";
import { authenticate } from "../drivers/auth";
import { guard } from "../drivers/firestore";
import { print2, print1 } from "../drivers/stdio";
import pluralize from "pluralize";
import yargs from "yargs";

Expand Down Expand Up @@ -41,13 +42,13 @@ const ls = async (
]);

if (data && "ok" in data && data.ok) {
console.error(
print2(
`Showing${
data.isTruncated ? ` the first ${data.items.length}` : ""
} ${pluralize(data.arg)}${data.term ? ` matching '${data.term}'` : ""}:`
);
for (const item of data.items) {
console.log(item);
print1(item);
}
} else {
throw data;
Expand Down
11 changes: 5 additions & 6 deletions src/commands/request.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { fetchCommand } from "../drivers/api";
import { authenticate } from "../drivers/auth";
import { doc, guard } from "../drivers/firestore";
import { print2 } from "../drivers/stdio";
import { Authn } from "../types/identity";
import { Request, RequestResponse } from "../types/request";
import { onSnapshot } from "firebase/firestore";
Expand Down Expand Up @@ -56,9 +57,7 @@ const waitForRequest = async (
) =>
await new Promise<number>((resolve) => {
if (logMessage)
console.error(
"Will wait up to 5 minutes for this request to complete..."
);
print2("Will wait up to 5 minutes for this request to complete...");
let cancel: NodeJS.Timeout | undefined = undefined;
const unsubscribe = onSnapshot<Request, object>(
doc(`o/${tenantId}/permission-requests/${requestId}`),
Expand All @@ -70,14 +69,14 @@ const waitForRequest = async (
if (cancel) clearTimeout(cancel);
unsubscribe?.();
const { message, code } = COMPLETED_REQUEST_STATUSES[status];
if (code !== 0 || logMessage) console.error(message);
if (code !== 0 || logMessage) print2(message);
resolve(code);
}
}
);
cancel = setTimeout(() => {
unsubscribe?.();
console.error("Your request did not complete within 5 minutes.");
print2("Your request did not complete within 5 minutes.");
resolve(4);
}, WAIT_TIMEOUT);
});
Expand Down Expand Up @@ -106,7 +105,7 @@ export const request = async (
(options?.message === "approval-required" &&
!data.isPreexisting &&
!data.isPersistent);
if (logMessage) console.error(data.message);
if (logMessage) print2(data.message);
const { id } = data;
if (args.wait && id && userCredential.user.tenantId) {
const code = await waitForRequest(
Expand Down
5 changes: 3 additions & 2 deletions src/commands/ssh.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { authenticate } from "../drivers/auth";
import { doc, guard } from "../drivers/firestore";
import { print2 } from "../drivers/stdio";
import { ssm } from "../plugins/aws/ssm";
import { AwsSsh } from "../plugins/aws/types";
import { Authn } from "../types/identity";
Expand Down Expand Up @@ -91,11 +92,11 @@ const ssh = async (args: yargs.ArgumentsCamelCase<{ instance: string }>) => {
{ message: "approval-required" }
);
if (!response) {
console.error("Did not receive access ID from server");
print2("Did not receive access ID from server");
return;
}
const { id, isPreexisting } = response;
if (!isPreexisting) console.error("Waiting for access to be provisioned");
if (!isPreexisting) print2("Waiting for access to be provisioned");
const requestData = await waitForProvisioning<AwsSsh>(authn, id);
await ssm(authn, { ...requestData, id });
};
36 changes: 0 additions & 36 deletions src/common/permission.ts

This file was deleted.

Loading
Loading