Skip to content

Commit 900d364

Browse files
Fix .databrickscfg parsing for DEFAULT section (#112)
Fixes #106
1 parent 9eedaf7 commit 900d364

3 files changed

Lines changed: 104 additions & 16 deletions

File tree

packages/databricks-sdk-js/src/auth/configFile.test.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,37 @@ describe(__filename, () => {
3131
);
3232
});
3333

34-
it("should parse a config file", async () => {
34+
it("should parse a config file w/o DEFAULT header", async () => {
35+
await withFile(async ({path}) => {
36+
await writeFile(
37+
path,
38+
`
39+
host = https://cloud.databricks.com/
40+
token = dapitest1234
41+
42+
[STAGING]
43+
host = https://staging.cloud.databricks.com/
44+
token = dapitest54321
45+
`
46+
);
47+
48+
const profiles = await loadConfigFile(path);
49+
50+
assert.equal(Object.keys(profiles).length, 2);
51+
assert.equal(
52+
profiles.DEFAULT.host.href,
53+
"https://cloud.databricks.com/"
54+
);
55+
assert.equal(profiles.DEFAULT.token, "dapitest1234");
56+
assert.equal(
57+
profiles.STAGING.host.href,
58+
"https://staging.cloud.databricks.com/"
59+
);
60+
assert.equal(profiles.STAGING.token, "dapitest54321");
61+
});
62+
});
63+
64+
it("should parse a config file with DEFAULT header", async () => {
3565
await withFile(async ({path}) => {
3666
await writeFile(
3767
path,
@@ -41,7 +71,8 @@ token = dapitest1234
4171
4272
[STAGING]
4373
host = https://staging.cloud.databricks.com/
44-
token = dapitest54321`
74+
token = dapitest54321
75+
`
4576
);
4677

4778
const profiles = await loadConfigFile(path);

packages/databricks-sdk-js/src/auth/configFile.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,35 @@ export async function loadConfigFile(filePath?: string): Promise<Profiles> {
3838

3939
let config: any;
4040
let profiles: Profiles = {};
41+
let defaultSection: Record<string, any> = {};
42+
let defaultSectionFound = false;
4143
try {
4244
config = parse(fileContents);
43-
for (let profile in config) {
44-
profiles[profile] = {
45-
host: new URL(config[profile].host),
46-
token: config[profile].token,
45+
for (let key in config) {
46+
if (key === "DEFAULT") {
47+
for (let defaultSectionKey in config[key]) {
48+
defaultSection[defaultSectionKey] =
49+
config[key][defaultSectionKey];
50+
}
51+
defaultSectionFound = true;
52+
continue;
53+
}
54+
// for global values without a section header
55+
// put them in the default sections
56+
if (typeof config[key] === "string") {
57+
defaultSection[key] = config[key];
58+
defaultSectionFound = true;
59+
continue;
60+
}
61+
profiles[key] = {
62+
host: new URL(config[key].host),
63+
token: config[key].token,
64+
};
65+
}
66+
if (defaultSectionFound) {
67+
profiles["DEFAULT"] = {
68+
host: new URL(defaultSection.host),
69+
token: defaultSection.token,
4770
};
4871
}
4972
} catch (e: unknown) {
@@ -53,7 +76,7 @@ export async function loadConfigFile(filePath?: string): Promise<Profiles> {
5376
} else {
5477
message = e;
5578
}
56-
throw new ConfigFileError(`Can't parse ${filePath}: ${message}`);
79+
throw new ConfigFileError(`${message}`);
5780
}
5881

5982
return profiles;

packages/databricks-vscode/src/configuration/selectProfileWizard.ts

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,16 @@ import {
44
Profiles,
55
resolveConfigFilePath,
66
} from "@databricks/databricks-sdk";
7-
import {stat, unlink} from "fs/promises";
8-
import {QuickPickItem, QuickPickItemKind, window} from "vscode";
7+
import {copyFile, stat, unlink} from "fs/promises";
8+
import path from "path";
9+
import {
10+
commands,
11+
QuickPickItem,
12+
QuickPickItemKind,
13+
Uri,
14+
window,
15+
workspace,
16+
} from "vscode";
917
import {CliWrapper} from "../cli/CliWrapper";
1018
import {MultiStepInput} from "../ui/wizard";
1119

@@ -37,23 +45,49 @@ export async function selectProfile(
3745
if (!(e instanceof ConfigFileError)) {
3846
throw e;
3947
}
40-
const path = resolveConfigFilePath();
48+
const confPath = resolveConfigFilePath();
4149
let stats;
4250
try {
43-
stats = await stat(path);
51+
stats = await stat(confPath);
4452
} catch (e) {
4553
/*file doesn't exist*/
4654
}
4755
if (stats?.isFile()) {
4856
const option = await window.showErrorMessage(
49-
e.message,
50-
"Overwrite",
51-
"Cancel"
57+
`Can't parse config file`,
58+
{
59+
detail: e.message,
60+
},
61+
"Open Config File",
62+
"Backup and Overwrite Config File"
5263
);
53-
if (option === "Cancel") {
64+
if (option === undefined) {
65+
return;
66+
}
67+
if (option === "Open Config File") {
68+
await commands.executeCommand(
69+
"databricks.connection.openDatabricksConfigFile"
70+
);
5471
return;
5572
}
56-
await unlink(path);
73+
const backupPath = path.join(
74+
path.dirname(confPath),
75+
`${path.basename(confPath)}.${Date.now()}.bak`
76+
);
77+
await copyFile(confPath, backupPath);
78+
79+
const openBackup = await window.showErrorMessage(
80+
`Config file backed up at "${backupPath}"`,
81+
"Open Backup File",
82+
"Continue Without Opening"
83+
);
84+
if (openBackup === "Open Backup File") {
85+
const doc = await workspace.openTextDocument(
86+
Uri.file(backupPath)
87+
);
88+
await window.showTextDocument(doc);
89+
}
90+
await unlink(confPath);
5791
}
5892
}
5993

0 commit comments

Comments
 (0)