Skip to content

Commit

Permalink
don't use a default profile (#514)
Browse files Browse the repository at this point in the history
* don't use a default profile

* add test
  • Loading branch information
mwilde345 authored Dec 12, 2024
1 parent 1801770 commit 45ddf9c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 35 deletions.
54 changes: 31 additions & 23 deletions src/lib/config/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -99,49 +99,57 @@ function validateConfig(profileName, profileBody, configPath) {
* @returns {object} - The yargs parser
*/
export function configParser(argvInput, path) {
const userProvidedConfigPath =
Boolean(process.env.FAUNA_CONFIG) || argvInput.indexOf("--config") > -1;
let parsedPath = path;
let parsedProfile;
const logger = container.resolve("logger");

if (path === process.cwd()) {
parsedPath = checkForDefaultConfig(process.cwd());
}
const argv = yargsParser(argvInput, {
alias: {
profile: ["p"],
},
string: ["profile"],
});

const profile = argv.profile || process.env.FAUNA_PROFILE;

if (!parsedPath) {
// if there no config file, we need to assert that no either no profile is
// specified or that the profile is "default"
const preConfigArgv = yargsParser(argvInput, {
alias: {
profile: ["p"],
},
string: ["profile"],
});
if (preConfigArgv.profile && preConfigArgv.profile !== "default") {
// if there no config file, we need to assert that no profile is specified

if (profile) {
throw new ValidationError(
`Profile "${preConfigArgv.profile}" cannot be specified because there was no config file found at "${path}". ` +
`Profile "${profile}" cannot be specified because there was no config file found at "${path}". ` +
`Remove the profile, or provide a config file.`,
);
}
return {};
}
if (!userProvidedConfigPath && !profile) {
// There is a config file, but it's in the default location, the user did not specify a path.
// Ignore the config file unless they specified a profile.
return {};
}

if (userProvidedConfigPath && !profile) {
// The user specified a config file, but no profile. Don't just default the profile value, require it
// explicitly
throw new ValidationError(
`A config file was provided at "${path}" but no profile was specified. Provide a profile value with ` +
`--profile or FAUNA_PROFILE env var to use the config file.`,
);
}

logger.debug(`Reading config from ${parsedPath}.`, "config");
const config = getConfig(parsedPath);

// The "default" profile will be injected here
const argv = yargsParser(argvInput, {
alias: {
profile: ["p"],
},
default: {
profile: "default",
},
string: ["profile"],
});
logger.debug(`Using profile ${argv.profile}...`, "config");
parsedProfile = config.toJSON()[argv.profile];
logger.debug(`Using profile ${profile}...`, "config");
parsedProfile = config.toJSON()[profile];

validateConfig(argv.profile, parsedProfile, parsedPath);
validateConfig(profile, parsedProfile, parsedPath);

logger.debug(
`Applying config: ${JSON.stringify(parsedProfile, null, 4)}`,
Expand Down
50 changes: 38 additions & 12 deletions test/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ describe("configuration file", function () {
fs = container.resolve("fs");
delete process.env.FAUNA_CONFIG;
delete process.env.FAUNA_SECRET;
delete process.env.FAUNA_PROFILE;
});

/**
Expand Down Expand Up @@ -104,7 +105,7 @@ describe("configuration file", function () {
describe("location", function () {
it("can be specified by setting a flag", async function () {
await runArgvTest({
cmd: `argv --config ./prod.yaml`,
cmd: `argv --config ./prod.yaml --profile default`,
pathMatcher: path.join(__dirname, "../prod.yaml"),
argvMatcher: sinon.match({
secret: "very-secret",
Expand All @@ -117,7 +118,10 @@ describe("configuration file", function () {
it("can be specified by setting an env variable", async function () {
await runArgvTest({
cmd: `argv`,
env: { FAUNA_CONFIG: path.join(__dirname, "../prod.yaml") },
env: {
FAUNA_CONFIG: path.join(__dirname, "../prod.yaml"),
FAUNA_PROFILE: "default",
},
pathMatcher: path.join(__dirname, "../prod.yaml"),
argvMatcher: sinon.match({
secret: "very-secret",
Expand All @@ -130,7 +134,7 @@ describe("configuration file", function () {
it("a flag location is prioritized over an env var location", async function () {
await runArgvTest({
cmd: `argv --config ./dev.yaml`,
env: { FAUNA_CONFIG: "./prod.yaml" },
env: { FAUNA_CONFIG: "./prod.yaml", FAUNA_PROFILE: "default" },
pathMatcher: path.join(__dirname, "../dev.yaml"),
argvMatcher: sinon.match({
secret: "very-secret",
Expand All @@ -152,7 +156,7 @@ describe("configuration file", function () {
]);

await runArgvTest({
cmd: `argv`,
cmd: `argv --profile default`,
argvMatcher: sinon.match({
secret: "very-secret",
url: "https://db.fauna.com:443",
Expand Down Expand Up @@ -247,7 +251,7 @@ describe("configuration file", function () {
.throws(fakeFSError);

try {
await run(`argv --config ./dev.yaml`, container);
await run(`argv --config ./dev.yaml --profile default`, container);
} catch (e) {}

const errorText = `Config file not found at path ${configPath}.`;
Expand All @@ -260,7 +264,7 @@ describe("configuration file", function () {
describe("parsing", function () {
it("can parse YAML", async function () {
await runArgvTest({
cmd: `argv --config ./dev.yaml`,
cmd: `argv --config ./dev.yaml --profile default`,
pathMatcher: path.join(__dirname, "../dev.yaml"),
argvMatcher: sinon.match({
secret: "very-secret",
Expand All @@ -273,7 +277,7 @@ describe("configuration file", function () {

it("can parse JSON", async function () {
await runArgvTest({
cmd: `argv --config ./dev.yaml`,
cmd: `argv --config ./dev.yaml --profile default`,
pathMatcher: path.join(__dirname, "../dev.yaml"),
argvMatcher: sinon.match({
secret: "very-secret",
Expand All @@ -285,7 +289,7 @@ describe("configuration file", function () {

it.skip("supports all global config options", async function () {});
it.skip("does not exit with an error if the config file is empty", async function () {});
it("exits with an error if no profile is specified and the config does not have a 'default' key", async function () {
it("exits with an error if no profile is specified with user-provided config path", async function () {
const noDefaultConfig = JSON.stringify({
dev: {
secret: "shouted",
Expand All @@ -295,7 +299,7 @@ describe("configuration file", function () {

try {
await runArgvTest({
cmd: `argv --config ./dev.yaml "Database.all()"`,
cmd: `argv --config ./dev.yaml`,
pathMatcher: path.join(__dirname, "../dev.yaml"),
argvMatcher: sinon.match({
apiVersion: "10",
Expand All @@ -308,7 +312,7 @@ describe("configuration file", function () {
configToReturn: noDefaultConfig,
});
} catch (e) {}
const errorText = `No "default" profile found in the config file at "${path.join(__dirname, "../dev.yaml")}". Either specify a profile with "--profile NAME" or add a "default" profile.`;
const errorText = `A config file was provided at "${path.join(__dirname, "../dev.yaml")}" but no profile was specified. Provide a profile value with --profile or FAUNA_PROFILE env var to use the config file.`;
const message = `${await builtYargs.getHelp()}\n\n${errorText}\n`;
expect(stdout.getWritten()).to.equal("");
expect(stripAnsi(stderr.getWritten())).to.equal(message);
Expand Down Expand Up @@ -344,6 +348,28 @@ describe("configuration file", function () {
expect(stripAnsi(stderr.getWritten())).to.equal(message);
});

it("ignores default config file if neither profile nor config are specified", async function () {
const defaultConfig = `
{
"default": {
"color": false,
"json": true,
"quiet": true,
},
}
`.trim();
await runArgvTest({
cmd: `argv`,
pathMatcher: path.join(__dirname, "../fauna.config.yaml"),
argvMatcher: sinon.match({
color: true,
json: false,
quiet: false,
}),
configToReturn: defaultConfig,
});
});

it.skip("preserves comments in the config file", async function () {});
});

Expand All @@ -353,7 +379,7 @@ describe("configuration file", function () {
it("prioritizes flags over env variables", async function () {
await runArgvTest({
cmd: `argv --secret whispered --config ./dev.yaml`,
env: { FAUNA_SECRET: "not-so-secret" },
env: { FAUNA_SECRET: "not-so-secret", FAUNA_PROFILE: "default" },
pathMatcher: path.join(__dirname, "../dev.yaml"),
argvMatcher: sinon.match({
secret: "whispered",
Expand All @@ -367,7 +393,7 @@ describe("configuration file", function () {
it("prioritizes env variables over config entries", async function () {
await runArgvTest({
cmd: `argv --config ./dev.yaml`,
env: { FAUNA_SECRET: "not-so-secret" },
env: { FAUNA_SECRET: "not-so-secret", FAUNA_PROFILE: "default" },
pathMatcher: path.join(__dirname, "../dev.yaml"),
argvMatcher: sinon.match({
secret: "not-so-secret",
Expand Down

0 comments on commit 45ddf9c

Please sign in to comment.