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

don't use a default profile #514

Merged
merged 3 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading