dataiku-sdk 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/types/src/index.d.ts +4 -0
- package/dist/packages/types/src/index.js +1 -0
- package/dist/src/cli.js +400 -41
- package/dist/src/errors.js +12 -0
- package/dist/src/index.d.ts +4 -4
- package/dist/src/resources/connections.d.ts +10 -0
- package/dist/src/resources/connections.js +16 -0
- package/dist/src/resources/datasets.d.ts +18 -0
- package/dist/src/resources/datasets.js +41 -0
- package/dist/src/resources/jobs.d.ts +52 -19
- package/dist/src/resources/jobs.js +121 -33
- package/dist/src/resources/notebooks.d.ts +6 -4
- package/dist/src/resources/notebooks.js +6 -4
- package/dist/src/resources/recipes.d.ts +54 -1
- package/dist/src/resources/recipes.js +235 -0
- package/dist/src/resources/sql.js +84 -3
- package/package.json +1 -1
- package/packages/types/dist/index.d.ts +4 -0
- package/packages/types/dist/index.js +1 -0
package/dist/src/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readFileSync, } from "node:fs";
|
|
3
|
-
import { writeFile, } from "node:fs/promises";
|
|
4
|
-
import { dirname, resolve, } from "node:path";
|
|
3
|
+
import { mkdir, writeFile, } from "node:fs/promises";
|
|
4
|
+
import { dirname, join, resolve, } from "node:path";
|
|
5
5
|
import { createInterface, } from "node:readline";
|
|
6
6
|
import { Writable, } from "node:stream";
|
|
7
7
|
import { fileURLToPath, } from "node:url";
|
|
@@ -12,6 +12,7 @@ import { DataikuError, dataikuErrorCode, } from "./errors.js";
|
|
|
12
12
|
import { AGENTS, detectAgents, findWorkspaceRoot, installSkill, } from "./skill.js";
|
|
13
13
|
import { appendCleanupLedgerEntry, readCleanupLedger, } from "./utils/cleanup-ledger.js";
|
|
14
14
|
import { deepMerge, } from "./utils/deep-merge.js";
|
|
15
|
+
import { sanitizeFileName, } from "./utils/sanitize.js";
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
16
17
|
// Utility helpers
|
|
17
18
|
// ---------------------------------------------------------------------------
|
|
@@ -43,12 +44,48 @@ function jobBuildTargetType(v) {
|
|
|
43
44
|
if (v === undefined)
|
|
44
45
|
return "DATASET";
|
|
45
46
|
if (typeof v !== "string") {
|
|
46
|
-
throw new UsageError("Invalid
|
|
47
|
+
throw new UsageError("Invalid job target type. Use dataset or managed-folder.", "invalid_enum");
|
|
47
48
|
}
|
|
48
49
|
const normalized = v.trim().toUpperCase().replace(/-/g, "_");
|
|
49
50
|
if (normalized === "DATASET" || normalized === "MANAGED_FOLDER")
|
|
50
51
|
return normalized;
|
|
51
|
-
throw new UsageError("Invalid
|
|
52
|
+
throw new UsageError("Invalid job target type. Use dataset or managed-folder.", "invalid_enum");
|
|
53
|
+
}
|
|
54
|
+
function jobBuildTargetTypeFromFlags(flags) {
|
|
55
|
+
return jobBuildTargetType(flags["target-type"] ?? flags["type"]);
|
|
56
|
+
}
|
|
57
|
+
function maxLogLinesFromFlags(flags) {
|
|
58
|
+
return num(flags["max-log-lines"] ?? flags["max-lines"]);
|
|
59
|
+
}
|
|
60
|
+
function jobLogFilterFromFlag(v) {
|
|
61
|
+
if (v === undefined)
|
|
62
|
+
return undefined;
|
|
63
|
+
if (typeof v !== "string") {
|
|
64
|
+
throw new UsageError("Invalid --log-filter value. Use stdout, stderr, user, or errors.", "invalid_enum");
|
|
65
|
+
}
|
|
66
|
+
const normalized = v.trim().toLowerCase();
|
|
67
|
+
if (normalized === "stdout" || normalized === "stderr" || normalized === "user"
|
|
68
|
+
|| normalized === "errors") {
|
|
69
|
+
return normalized;
|
|
70
|
+
}
|
|
71
|
+
throw new UsageError("Invalid --log-filter value. Use stdout, stderr, user, or errors.", "invalid_enum");
|
|
72
|
+
}
|
|
73
|
+
function recipePayloadBackupPath(recipeName, backupDir) {
|
|
74
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
75
|
+
return join(backupDir, `${sanitizeFileName(recipeName, "recipe")}-${stamp}.payload`);
|
|
76
|
+
}
|
|
77
|
+
function recipeRunShouldWait(flags) {
|
|
78
|
+
if (flags["wait"] === true && flags["no-wait"] === true) {
|
|
79
|
+
throw new UsageError("--wait and --no-wait are mutually exclusive.", "invalid_enum");
|
|
80
|
+
}
|
|
81
|
+
const waitImplied = flags["include-logs"] === true
|
|
82
|
+
|| flags["summary"] === true
|
|
83
|
+
|| flags["timeout"] !== undefined
|
|
84
|
+
|| flags["poll-interval"] !== undefined;
|
|
85
|
+
if (flags["no-wait"] === true && waitImplied) {
|
|
86
|
+
throw new UsageError("--include-logs, --summary, --timeout, and --poll-interval require waiting; remove --no-wait.", "invalid_enum");
|
|
87
|
+
}
|
|
88
|
+
return flags["no-wait"] !== true && (flags["wait"] === true || waitImplied);
|
|
52
89
|
}
|
|
53
90
|
function splitCsvFlag(v) {
|
|
54
91
|
if (typeof v !== "string")
|
|
@@ -130,7 +167,7 @@ function json(v) {
|
|
|
130
167
|
return undefined;
|
|
131
168
|
return JSON.parse(v);
|
|
132
169
|
}
|
|
133
|
-
const SQL_QUERY_USAGE = "dss sql query [SQL | --sql QUERY | --sql-file PATH | --sql - | --stdin] (--connection CONN | --dataset FULL_NAME) [--database DB] [--project-key KEY]";
|
|
170
|
+
const SQL_QUERY_USAGE = "dss sql query [SQL | --sql QUERY | --sql-file PATH | --sql - | --stdin] (--connection CONN | --dataset FULL_NAME) [--database DB] [--output PATH|--output-file PATH] [--request-timeout MS] [--project-key KEY]";
|
|
134
171
|
function readStdinText() {
|
|
135
172
|
return readFileSync(0, "utf-8");
|
|
136
173
|
}
|
|
@@ -146,6 +183,48 @@ function jsonInput(flags) {
|
|
|
146
183
|
}
|
|
147
184
|
return undefined;
|
|
148
185
|
}
|
|
186
|
+
function unknownJsonInput(flags) {
|
|
187
|
+
if (flags["stdin"] === true)
|
|
188
|
+
return JSON.parse(readStdinText());
|
|
189
|
+
if (typeof flags["data-file"] === "string") {
|
|
190
|
+
return JSON.parse(readFileSync(flags["data-file"], "utf-8"));
|
|
191
|
+
}
|
|
192
|
+
if (typeof flags["data"] === "string")
|
|
193
|
+
return JSON.parse(flags["data"]);
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
function schemaColumnsInput(flags, usage) {
|
|
197
|
+
const input = unknownJsonInput(flags);
|
|
198
|
+
if (input === undefined) {
|
|
199
|
+
throw new UsageError(`--data, --data-file, or --stdin is required. Usage: ${usage}`);
|
|
200
|
+
}
|
|
201
|
+
const columns = Array.isArray(input)
|
|
202
|
+
? input
|
|
203
|
+
: input && typeof input === "object" && Array.isArray(input.columns)
|
|
204
|
+
? input.columns
|
|
205
|
+
: undefined;
|
|
206
|
+
if (!columns) {
|
|
207
|
+
throw new UsageError("Schema input must be an array of columns or an object with a columns array.");
|
|
208
|
+
}
|
|
209
|
+
return columns.map((column, index) => {
|
|
210
|
+
if (!column || typeof column !== "object" || Array.isArray(column)) {
|
|
211
|
+
throw new UsageError(`Schema column at index ${index} must be an object.`);
|
|
212
|
+
}
|
|
213
|
+
const record = column;
|
|
214
|
+
if (typeof record.name !== "string" || record.name.length === 0) {
|
|
215
|
+
throw new UsageError(`Schema column at index ${index} is missing string field "name".`);
|
|
216
|
+
}
|
|
217
|
+
if (typeof record.type !== "string" || record.type.length === 0) {
|
|
218
|
+
throw new UsageError(`Schema column "${record.name}" is missing string field "type".`);
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
...record,
|
|
222
|
+
name: record.name,
|
|
223
|
+
type: record.type,
|
|
224
|
+
...(typeof record.comment === "string" ? { comment: record.comment, } : {}),
|
|
225
|
+
};
|
|
226
|
+
});
|
|
227
|
+
}
|
|
149
228
|
function textInput(flags) {
|
|
150
229
|
if (typeof flags["content"] === "string")
|
|
151
230
|
return flags["content"];
|
|
@@ -289,6 +368,28 @@ function formatLineDiff(remoteName, localPath, remoteContent, localContent) {
|
|
|
289
368
|
function writeCommandResult(result) {
|
|
290
369
|
process.stdout.write(`${JSON.stringify(result ?? { ok: true, }, null, 2)}\n`);
|
|
291
370
|
}
|
|
371
|
+
function transientBodyWithTargetContext(body, target, elapsedMs) {
|
|
372
|
+
try {
|
|
373
|
+
const parsed = JSON.parse(body);
|
|
374
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
375
|
+
const record = parsed;
|
|
376
|
+
const message = typeof record.message === "string" && record.message.length > 0
|
|
377
|
+
? `Target: ${target}\nElapsed: ${elapsedMs}ms\n${record.message}`
|
|
378
|
+
: `Target: ${target}\nElapsed: ${elapsedMs}ms`;
|
|
379
|
+
return JSON.stringify({ ...record, message, target, elapsedMs, });
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
catch {
|
|
383
|
+
// Non-JSON DSS bodies are wrapped as text below.
|
|
384
|
+
}
|
|
385
|
+
return `Target: ${target}\nElapsed: ${elapsedMs}ms\n${body}`;
|
|
386
|
+
}
|
|
387
|
+
function addTransientTargetContext(error, target, elapsedMs) {
|
|
388
|
+
if (error instanceof DataikuError && error.category === "transient") {
|
|
389
|
+
throw new DataikuError(error.status, error.statusText, transientBodyWithTargetContext(error.body, target, elapsedMs), error.retry);
|
|
390
|
+
}
|
|
391
|
+
throw error;
|
|
392
|
+
}
|
|
292
393
|
function isFailedWaitResult(result) {
|
|
293
394
|
if (result === null || typeof result !== "object" || Array.isArray(result))
|
|
294
395
|
return false;
|
|
@@ -331,6 +432,7 @@ function planResult(resource, action, options) {
|
|
|
331
432
|
...(options.method ? { method: options.method, } : {}),
|
|
332
433
|
...(options.endpoint ? { endpoint: options.endpoint, } : {}),
|
|
333
434
|
...(options.payload !== undefined ? { payload: options.payload, } : {}),
|
|
435
|
+
...(options.localWrites !== undefined ? { localWrites: options.localWrites, } : {}),
|
|
334
436
|
...(options.wait !== undefined ? { wait: options.wait, } : {}),
|
|
335
437
|
idempotency: options.idempotency,
|
|
336
438
|
async: options.asyncKind,
|
|
@@ -507,6 +609,7 @@ const BOOLEAN_FLAGS = new Set([
|
|
|
507
609
|
"include-payload",
|
|
508
610
|
"no-payload",
|
|
509
611
|
"include-logs",
|
|
612
|
+
"summary",
|
|
510
613
|
"replace",
|
|
511
614
|
"dry-run",
|
|
512
615
|
"plan",
|
|
@@ -542,7 +645,9 @@ const VALUE_FLAGS = new Set([
|
|
|
542
645
|
"agent",
|
|
543
646
|
"api-key",
|
|
544
647
|
"build-mode",
|
|
648
|
+
"backup-dir",
|
|
545
649
|
"ca-cert",
|
|
650
|
+
"catalog",
|
|
546
651
|
"cell-id",
|
|
547
652
|
"allow-types",
|
|
548
653
|
"color",
|
|
@@ -568,6 +673,7 @@ const VALUE_FLAGS = new Set([
|
|
|
568
673
|
"local",
|
|
569
674
|
"max-edges",
|
|
570
675
|
"max-lines",
|
|
676
|
+
"max-log-lines",
|
|
571
677
|
"listed",
|
|
572
678
|
"max-nodes",
|
|
573
679
|
"max-rows",
|
|
@@ -575,10 +681,12 @@ const VALUE_FLAGS = new Set([
|
|
|
575
681
|
"only-monitored",
|
|
576
682
|
"min-timestamp",
|
|
577
683
|
"mode",
|
|
684
|
+
"log-filter",
|
|
578
685
|
"model-evaluation-store",
|
|
579
686
|
"name",
|
|
580
687
|
"object",
|
|
581
688
|
"output",
|
|
689
|
+
"output-file",
|
|
582
690
|
"output-connection",
|
|
583
691
|
"output-folder",
|
|
584
692
|
"page",
|
|
@@ -592,15 +700,18 @@ const VALUE_FLAGS = new Set([
|
|
|
592
700
|
"results-per-page",
|
|
593
701
|
"record-cleanup",
|
|
594
702
|
"rule-id",
|
|
703
|
+
"retries",
|
|
595
704
|
"poll-interval",
|
|
596
705
|
"python-interpreter",
|
|
597
706
|
"retain",
|
|
598
707
|
"saved-model",
|
|
599
708
|
"sql",
|
|
709
|
+
"schema",
|
|
600
710
|
"sql-file",
|
|
601
711
|
"standard",
|
|
602
712
|
"streaming-endpoint",
|
|
603
713
|
"target",
|
|
714
|
+
"target-type",
|
|
604
715
|
"timeout",
|
|
605
716
|
"type",
|
|
606
717
|
"url",
|
|
@@ -1532,6 +1643,41 @@ const commands = {
|
|
|
1532
1643
|
description: "Show the column schema of a dataset.",
|
|
1533
1644
|
examples: ["dss dataset schema orders",],
|
|
1534
1645
|
},
|
|
1646
|
+
"refresh-schema": {
|
|
1647
|
+
handler: async (c, a, f) => {
|
|
1648
|
+
const usage = "dss dataset refresh-schema <name> [--data JSON | --data-file PATH | --stdin] [--dry-run] [--project-key KEY]";
|
|
1649
|
+
requireArgs(a, 1, usage);
|
|
1650
|
+
const columns = schemaColumnsInput(f, usage);
|
|
1651
|
+
const pk = f["project-key"];
|
|
1652
|
+
if (f["dry-run"] === true) {
|
|
1653
|
+
const current = await c.datasets.schema(a[0], pk);
|
|
1654
|
+
return {
|
|
1655
|
+
dryRun: true,
|
|
1656
|
+
action: "refresh-schema",
|
|
1657
|
+
resource: "dataset",
|
|
1658
|
+
name: a[0],
|
|
1659
|
+
current,
|
|
1660
|
+
next: { columns, },
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
await c.datasets.updateSchema(a[0], columns, pk);
|
|
1664
|
+
return { updated: a[0], resource: "dataset", schema: { columns, }, };
|
|
1665
|
+
},
|
|
1666
|
+
usage: "dss dataset refresh-schema <name> [--data JSON | --data-file PATH | --stdin] [--dry-run] [--project-key KEY]",
|
|
1667
|
+
description: "Replace a dataset schema through the DSS schema endpoint.",
|
|
1668
|
+
examples: [
|
|
1669
|
+
`dss dataset refresh-schema orders --data '{"columns":[{"name":"id","type":"bigint"}]}' --dry-run`,
|
|
1670
|
+
],
|
|
1671
|
+
},
|
|
1672
|
+
"validate-build": {
|
|
1673
|
+
handler: (c, a, f) => {
|
|
1674
|
+
requireArgs(a, 1, "dss dataset validate-build <name>");
|
|
1675
|
+
return c.datasets.validateBuildSettings(a[0], f["project-key"]);
|
|
1676
|
+
},
|
|
1677
|
+
usage: "dss dataset validate-build <name> [--project-key KEY]",
|
|
1678
|
+
description: "Check common dataset settings that can make file-backed builds fail.",
|
|
1679
|
+
examples: ["dss dataset validate-build orders",],
|
|
1680
|
+
},
|
|
1535
1681
|
preview: {
|
|
1536
1682
|
handler: (c, a, f) => {
|
|
1537
1683
|
requireArgs(a, 1, "dss dataset preview <name>");
|
|
@@ -1674,6 +1820,60 @@ const commands = {
|
|
|
1674
1820
|
"dss recipe get compute_orders --include-payload",
|
|
1675
1821
|
],
|
|
1676
1822
|
},
|
|
1823
|
+
"validate-graph": {
|
|
1824
|
+
handler: (c, a, f) => {
|
|
1825
|
+
requireArgs(a, 1, "dss recipe validate-graph <name>");
|
|
1826
|
+
return c.recipes.validateGraph(a[0], {
|
|
1827
|
+
projectKey: f["project-key"],
|
|
1828
|
+
});
|
|
1829
|
+
},
|
|
1830
|
+
usage: "dss recipe validate-graph <name> [--project-key KEY]",
|
|
1831
|
+
description: "Validate declared recipe input/output graph references before building.",
|
|
1832
|
+
examples: ["dss recipe validate-graph compute_orders",],
|
|
1833
|
+
},
|
|
1834
|
+
run: {
|
|
1835
|
+
handler: async (c, a, f) => {
|
|
1836
|
+
requireArgs(a, 1, "dss recipe run <name>");
|
|
1837
|
+
const pk = f["project-key"];
|
|
1838
|
+
const wait = recipeRunShouldWait(f);
|
|
1839
|
+
const options = {
|
|
1840
|
+
buildMode: f["build-mode"],
|
|
1841
|
+
includeLogs: f["include-logs"] === true,
|
|
1842
|
+
logFilter: jobLogFilterFromFlag(f["log-filter"]),
|
|
1843
|
+
maxLogLines: maxLogLinesFromFlags(f),
|
|
1844
|
+
partition: f["partition"],
|
|
1845
|
+
pollIntervalMs: num(f["poll-interval"]),
|
|
1846
|
+
projectKey: pk,
|
|
1847
|
+
timeoutMs: num(f["timeout"]),
|
|
1848
|
+
summary: f["summary"] === true,
|
|
1849
|
+
wait,
|
|
1850
|
+
};
|
|
1851
|
+
if (f["dry-run"] === true) {
|
|
1852
|
+
const outputs = await c.recipes.resolveRunOutputs(a[0], {
|
|
1853
|
+
partition: options.partition,
|
|
1854
|
+
projectKey: pk,
|
|
1855
|
+
});
|
|
1856
|
+
return {
|
|
1857
|
+
dryRun: true,
|
|
1858
|
+
action: "run",
|
|
1859
|
+
resource: "recipe",
|
|
1860
|
+
recipe: a[0],
|
|
1861
|
+
outputs,
|
|
1862
|
+
...options,
|
|
1863
|
+
endpoint: encodedProjectEndpoint(c, pk, "/jobs/"),
|
|
1864
|
+
method: "POST",
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
return c.recipes.run(a[0], options);
|
|
1868
|
+
},
|
|
1869
|
+
usage: "dss recipe run <name> [--wait|--no-wait] [--build-mode MODE] [--include-logs] [--log-filter stdout|stderr|user|errors] [--summary] [--max-log-lines N] [--timeout MS] [--poll-interval MS] [--partition PARTITION] [--dry-run] [--project-key KEY]",
|
|
1870
|
+
description: "Run a recipe by resolving its outputs and submitting the correct dataset or managed-folder build job.",
|
|
1871
|
+
examples: [
|
|
1872
|
+
"dss recipe run compute_orders --wait",
|
|
1873
|
+
"dss recipe run compute_exports --include-logs --log-filter stdout --summary --timeout 600000",
|
|
1874
|
+
"dss recipe run compute_exports --dry-run",
|
|
1875
|
+
],
|
|
1876
|
+
},
|
|
1677
1877
|
delete: {
|
|
1678
1878
|
handler: async (c, a, f) => {
|
|
1679
1879
|
requireArgs(a, 1, "dss recipe delete <name>");
|
|
@@ -1860,6 +2060,8 @@ const commands = {
|
|
|
1860
2060
|
if (!filePath)
|
|
1861
2061
|
throw new UsageError("--file is required.");
|
|
1862
2062
|
const content = readFileSync(filePath, "utf-8");
|
|
2063
|
+
const backupDir = f["backup-dir"];
|
|
2064
|
+
const backupPath = backupDir ? recipePayloadBackupPath(a[0], backupDir) : undefined;
|
|
1863
2065
|
if (f["dry-run"] === true) {
|
|
1864
2066
|
const current = await c.recipes.get(a[0], {
|
|
1865
2067
|
projectKey: f["project-key"],
|
|
@@ -1873,16 +2075,33 @@ const commands = {
|
|
|
1873
2075
|
file: filePath,
|
|
1874
2076
|
current,
|
|
1875
2077
|
next: { ...current, payload: content, },
|
|
2078
|
+
...(backupPath ? { backupPath, } : {}),
|
|
1876
2079
|
};
|
|
1877
2080
|
}
|
|
2081
|
+
if (backupDir && backupPath) {
|
|
2082
|
+
const current = await c.recipes.get(a[0], {
|
|
2083
|
+
projectKey: f["project-key"],
|
|
2084
|
+
includePayload: true,
|
|
2085
|
+
});
|
|
2086
|
+
await mkdir(backupDir, { recursive: true, });
|
|
2087
|
+
await writeFile(backupPath, current.payload ?? "", "utf-8");
|
|
2088
|
+
}
|
|
1878
2089
|
await c.recipes.setPayload(a[0], content, {
|
|
1879
2090
|
projectKey: f["project-key"],
|
|
1880
2091
|
});
|
|
1881
|
-
return {
|
|
2092
|
+
return {
|
|
2093
|
+
updated: a[0],
|
|
2094
|
+
resource: "recipe",
|
|
2095
|
+
file: filePath,
|
|
2096
|
+
...(backupPath ? { backupPath, } : {}),
|
|
2097
|
+
};
|
|
1882
2098
|
},
|
|
1883
|
-
usage: "dss recipe set-payload <name> --file PATH [--dry-run] [--project-key KEY]",
|
|
1884
|
-
description: "Upload recipe code from a local file.",
|
|
1885
|
-
examples: [
|
|
2099
|
+
usage: "dss recipe set-payload <name> --file PATH [--backup-dir DIR] [--dry-run] [--project-key KEY]",
|
|
2100
|
+
description: "Upload recipe code from a local file, optionally backing up the remote payload first.",
|
|
2101
|
+
examples: [
|
|
2102
|
+
"dss recipe set-payload compute_orders --file code.py --dry-run",
|
|
2103
|
+
"dss recipe set-payload compute_orders --file code.py --backup-dir ./backups",
|
|
2104
|
+
],
|
|
1886
2105
|
},
|
|
1887
2106
|
},
|
|
1888
2107
|
job: {
|
|
@@ -1906,12 +2125,13 @@ const commands = {
|
|
|
1906
2125
|
requireArgs(a, 1, "dss job log <id>");
|
|
1907
2126
|
return c.jobs.log(a[0], {
|
|
1908
2127
|
activity: f["activity"],
|
|
1909
|
-
maxLogLines:
|
|
2128
|
+
maxLogLines: maxLogLinesFromFlags(f),
|
|
2129
|
+
projectKey: f["project-key"],
|
|
1910
2130
|
});
|
|
1911
2131
|
},
|
|
1912
|
-
usage: "dss job log <id> [--activity NAME] [--max-lines N]",
|
|
2132
|
+
usage: "dss job log <id> [--activity NAME] [--max-lines N|--max-log-lines N]",
|
|
1913
2133
|
description: "Get log output for a job.",
|
|
1914
|
-
examples: ["dss job log JOB_ID", "dss job log JOB_ID --activity main --max-lines 200",],
|
|
2134
|
+
examples: ["dss job log JOB_ID", "dss job log JOB_ID --activity main --max-log-lines 200",],
|
|
1915
2135
|
},
|
|
1916
2136
|
build: {
|
|
1917
2137
|
handler: async (c, a, f) => {
|
|
@@ -1919,8 +2139,9 @@ const commands = {
|
|
|
1919
2139
|
const pk = f["project-key"];
|
|
1920
2140
|
const options = {
|
|
1921
2141
|
buildMode: f["build-mode"],
|
|
2142
|
+
partition: f["partition"],
|
|
1922
2143
|
pollIntervalMs: num(f["poll-interval"]),
|
|
1923
|
-
targetType:
|
|
2144
|
+
targetType: jobBuildTargetTypeFromFlags(f),
|
|
1924
2145
|
timeoutMs: num(f["timeout"]),
|
|
1925
2146
|
};
|
|
1926
2147
|
if (f["dry-run"] === true) {
|
|
@@ -1939,12 +2160,12 @@ const commands = {
|
|
|
1939
2160
|
}
|
|
1940
2161
|
return c.jobs.build(a[0], { ...options, projectKey: pk, });
|
|
1941
2162
|
},
|
|
1942
|
-
usage: "dss job build <target> [--type DATASET|MANAGED_FOLDER] [--build-mode MODE] [--wait] [--timeout MS] [--poll-interval MS] [--dry-run] [--project-key KEY]",
|
|
2163
|
+
usage: "dss job build <target> [--target-type dataset|managed-folder] [--type DATASET|MANAGED_FOLDER] [--build-mode MODE] [--wait] [--timeout MS] [--poll-interval MS] [--partition PARTITION] [--dry-run] [--project-key KEY]",
|
|
1943
2164
|
description: "Start a dataset or managed-folder build, optionally waiting for completion.",
|
|
1944
2165
|
examples: [
|
|
1945
2166
|
"dss job build orders",
|
|
1946
2167
|
"dss job build orders --build-mode RECURSIVE_BUILD --wait",
|
|
1947
|
-
"dss job build LT7TUHJ8 --type
|
|
2168
|
+
"dss job build LT7TUHJ8 --target-type managed-folder --dry-run",
|
|
1948
2169
|
],
|
|
1949
2170
|
},
|
|
1950
2171
|
"build-and-wait": {
|
|
@@ -1954,9 +2175,13 @@ const commands = {
|
|
|
1954
2175
|
const options = {
|
|
1955
2176
|
buildMode: f["build-mode"],
|
|
1956
2177
|
includeLogs: f["include-logs"] === true,
|
|
2178
|
+
logFilter: jobLogFilterFromFlag(f["log-filter"]),
|
|
2179
|
+
maxLogLines: maxLogLinesFromFlags(f),
|
|
2180
|
+
partition: f["partition"],
|
|
1957
2181
|
pollIntervalMs: num(f["poll-interval"]),
|
|
1958
2182
|
timeoutMs: num(f["timeout"]),
|
|
1959
|
-
|
|
2183
|
+
summary: f["summary"] === true,
|
|
2184
|
+
targetType: jobBuildTargetTypeFromFlags(f),
|
|
1960
2185
|
};
|
|
1961
2186
|
if (f["dry-run"] === true) {
|
|
1962
2187
|
return {
|
|
@@ -1971,13 +2196,13 @@ const commands = {
|
|
|
1971
2196
|
}
|
|
1972
2197
|
return c.jobs.buildAndWait(a[0], { ...options, projectKey: pk, });
|
|
1973
2198
|
},
|
|
1974
|
-
usage: "dss job build-and-wait <target> [--type DATASET|MANAGED_FOLDER] [--build-mode MODE] [--include-logs] [--timeout MS] [--poll-interval MS] [--dry-run] [--project-key KEY]",
|
|
2199
|
+
usage: "dss job build-and-wait <target> [--target-type dataset|managed-folder] [--type DATASET|MANAGED_FOLDER] [--build-mode MODE] [--include-logs] [--log-filter stdout|stderr|user|errors] [--summary] [--max-log-lines N] [--timeout MS] [--poll-interval MS] [--partition PARTITION] [--dry-run] [--project-key KEY]",
|
|
1975
2200
|
description: "Build a dataset or managed folder and wait for completion.",
|
|
1976
2201
|
examples: [
|
|
1977
2202
|
"dss job build-and-wait orders",
|
|
1978
|
-
"dss job build-and-wait orders --include-logs",
|
|
2203
|
+
"dss job build-and-wait orders --include-logs --log-filter stdout --summary",
|
|
1979
2204
|
"dss job build-and-wait orders --timeout 300000",
|
|
1980
|
-
"dss job build-and-wait LT7TUHJ8 --type
|
|
2205
|
+
"dss job build-and-wait LT7TUHJ8 --target-type managed-folder --dry-run",
|
|
1981
2206
|
],
|
|
1982
2207
|
},
|
|
1983
2208
|
wait: {
|
|
@@ -1985,13 +2210,20 @@ const commands = {
|
|
|
1985
2210
|
requireArgs(a, 1, "dss job wait <id>");
|
|
1986
2211
|
return c.jobs.wait(a[0], {
|
|
1987
2212
|
includeLogs: f["include-logs"] === true,
|
|
2213
|
+
logFilter: jobLogFilterFromFlag(f["log-filter"]),
|
|
2214
|
+
maxLogLines: maxLogLinesFromFlags(f),
|
|
1988
2215
|
pollIntervalMs: num(f["poll-interval"]),
|
|
1989
2216
|
timeoutMs: num(f["timeout"]),
|
|
2217
|
+
summary: f["summary"] === true,
|
|
2218
|
+
projectKey: f["project-key"],
|
|
1990
2219
|
});
|
|
1991
2220
|
},
|
|
1992
|
-
usage: "dss job wait <id> [--include-logs] [--timeout MS] [--poll-interval MS]",
|
|
2221
|
+
usage: "dss job wait <id> [--include-logs] [--log-filter stdout|stderr|user|errors] [--summary] [--max-log-lines N] [--timeout MS] [--poll-interval MS]",
|
|
1993
2222
|
description: "Wait for an existing job to complete.",
|
|
1994
|
-
examples: [
|
|
2223
|
+
examples: [
|
|
2224
|
+
"dss job wait JOB_ID",
|
|
2225
|
+
"dss job wait JOB_ID --include-logs --log-filter stdout --summary --timeout 60000",
|
|
2226
|
+
],
|
|
1995
2227
|
},
|
|
1996
2228
|
abort: {
|
|
1997
2229
|
handler: async (c, a, f) => {
|
|
@@ -2297,13 +2529,24 @@ const commands = {
|
|
|
2297
2529
|
contents: {
|
|
2298
2530
|
handler: async (c, a, f) => {
|
|
2299
2531
|
requireArgs(a, 1, "dss folder contents <name-or-id>");
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2532
|
+
const startedAt = Date.now();
|
|
2533
|
+
let folderId = a[0];
|
|
2534
|
+
try {
|
|
2535
|
+
folderId = await resolveFolderId(c, a[0], f);
|
|
2536
|
+
return await c.folders.contents(folderId, {
|
|
2537
|
+
projectKey: f["project-key"],
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
catch (error) {
|
|
2541
|
+
addTransientTargetContext(error, `folder:${folderId}`, Date.now() - startedAt);
|
|
2542
|
+
}
|
|
2303
2543
|
},
|
|
2304
|
-
usage: "dss folder contents <name-or-id> [--project-key KEY]",
|
|
2544
|
+
usage: "dss folder contents <name-or-id> [--retries N] [--request-timeout MS] [--project-key KEY]",
|
|
2305
2545
|
description: "List files in a managed folder.",
|
|
2306
|
-
examples: [
|
|
2546
|
+
examples: [
|
|
2547
|
+
"dss folder contents my_folder",
|
|
2548
|
+
"dss folder contents my_folder --retries 8 --request-timeout 60000",
|
|
2549
|
+
],
|
|
2307
2550
|
},
|
|
2308
2551
|
download: {
|
|
2309
2552
|
handler: async (c, a, f) => {
|
|
@@ -2425,6 +2668,40 @@ const commands = {
|
|
|
2425
2668
|
description: "List connections with inferred types and metadata.",
|
|
2426
2669
|
examples: ["dss connection infer", "dss connection infer --mode rich",],
|
|
2427
2670
|
},
|
|
2671
|
+
schemas: {
|
|
2672
|
+
handler: (c, _a, f) => {
|
|
2673
|
+
const connection = f["connection"];
|
|
2674
|
+
if (!connection) {
|
|
2675
|
+
throw new UsageError("--connection is required. Usage: dss connection schemas --connection CONN");
|
|
2676
|
+
}
|
|
2677
|
+
return c.connections.schemas({
|
|
2678
|
+
connection,
|
|
2679
|
+
projectKey: f["project-key"],
|
|
2680
|
+
});
|
|
2681
|
+
},
|
|
2682
|
+
usage: "dss connection schemas --connection CONN [--project-key KEY]",
|
|
2683
|
+
description: "List schemas in a SQL connection.",
|
|
2684
|
+
examples: ["dss connection schemas --connection ATHENA_CONN --project-key MYPROJ",],
|
|
2685
|
+
},
|
|
2686
|
+
tables: {
|
|
2687
|
+
handler: (c, _a, f) => {
|
|
2688
|
+
const connection = f["connection"];
|
|
2689
|
+
if (!connection) {
|
|
2690
|
+
throw new UsageError("--connection is required. Usage: dss connection tables --connection CONN");
|
|
2691
|
+
}
|
|
2692
|
+
return c.connections.tables({
|
|
2693
|
+
connection,
|
|
2694
|
+
catalog: f["catalog"],
|
|
2695
|
+
schema: f["schema"],
|
|
2696
|
+
projectKey: f["project-key"],
|
|
2697
|
+
});
|
|
2698
|
+
},
|
|
2699
|
+
usage: "dss connection tables --connection CONN [--catalog CATALOG] [--schema SCHEMA] [--project-key KEY]",
|
|
2700
|
+
description: "List importable tables in a SQL connection, optionally scoped by catalog and schema.",
|
|
2701
|
+
examples: [
|
|
2702
|
+
"dss connection tables --connection ATHENA_CONN --schema analytics --project-key MYPROJ",
|
|
2703
|
+
],
|
|
2704
|
+
},
|
|
2428
2705
|
},
|
|
2429
2706
|
"code-env": {
|
|
2430
2707
|
list: {
|
|
@@ -2644,20 +2921,35 @@ const commands = {
|
|
|
2644
2921
|
},
|
|
2645
2922
|
sql: {
|
|
2646
2923
|
query: {
|
|
2647
|
-
handler: (c, a, f) => {
|
|
2924
|
+
handler: async (c, a, f) => {
|
|
2648
2925
|
const query = resolveSqlInput(a, f);
|
|
2649
2926
|
const connection = f["connection"];
|
|
2650
2927
|
const datasetFullName = f["dataset"];
|
|
2651
2928
|
if ((connection ? 1 : 0) + (datasetFullName ? 1 : 0) !== 1) {
|
|
2652
2929
|
throw new UsageError(`Pass exactly one of --connection or --dataset. Usage: ${SQL_QUERY_USAGE}`);
|
|
2653
2930
|
}
|
|
2654
|
-
|
|
2931
|
+
const result = await c.sql.query({
|
|
2655
2932
|
query,
|
|
2656
2933
|
connection,
|
|
2657
2934
|
datasetFullName,
|
|
2658
2935
|
database: f["database"],
|
|
2659
2936
|
projectKey: f["project-key"],
|
|
2660
2937
|
});
|
|
2938
|
+
const outputFile = f["output"]
|
|
2939
|
+
?? f["output-file"];
|
|
2940
|
+
if (!outputFile)
|
|
2941
|
+
return result;
|
|
2942
|
+
const outputPath = resolve(outputFile);
|
|
2943
|
+
await mkdir(dirname(outputPath), { recursive: true, });
|
|
2944
|
+
await writeFile(outputPath, `${JSON.stringify(result, null, 2)}\n`, "utf-8");
|
|
2945
|
+
return {
|
|
2946
|
+
queryId: result.queryId,
|
|
2947
|
+
schema: result.schema,
|
|
2948
|
+
columns: result.columns ?? result.schema,
|
|
2949
|
+
rowCount: result.rows.length,
|
|
2950
|
+
outputPath,
|
|
2951
|
+
written: outputPath,
|
|
2952
|
+
};
|
|
2661
2953
|
},
|
|
2662
2954
|
usage: SQL_QUERY_USAGE,
|
|
2663
2955
|
description: "Run a SQL query against a DSS connection or dataset.",
|
|
@@ -2665,6 +2957,7 @@ const commands = {
|
|
|
2665
2957
|
"dss sql query 'SELECT * FROM orders LIMIT 10' --connection my_pg",
|
|
2666
2958
|
"dss sql query --sql-file query.sql --connection my_pg",
|
|
2667
2959
|
"echo 'SELECT 1' | dss sql query --stdin --dataset MYPROJ.orders",
|
|
2960
|
+
"dss sql query --sql-file query.sql --connection my_pg --output results.json --request-timeout 120000",
|
|
2668
2961
|
],
|
|
2669
2962
|
},
|
|
2670
2963
|
},
|
|
@@ -2920,7 +3213,7 @@ function printTopLevelHelp() {
|
|
|
2920
3213
|
" --url URL Dataiku DSS base URL (env: DATAIKU_URL)",
|
|
2921
3214
|
" --api-key KEY API key (env: DATAIKU_API_KEY)",
|
|
2922
3215
|
" --project-key KEY Default project key (env: DATAIKU_PROJECT_KEY)",
|
|
2923
|
-
" --timeout MS Operation timeout (build-and-wait, run-and-wait)",
|
|
3216
|
+
" --timeout MS Operation timeout (build-and-wait, run-and-wait, recipe run)",
|
|
2924
3217
|
" --request-timeout MS HTTP request timeout in ms (default: 30000)",
|
|
2925
3218
|
" --dry-run Preview destructive actions without executing",
|
|
2926
3219
|
" --if-not-exists Skip create if resource already exists",
|
|
@@ -3139,7 +3432,9 @@ function doctorEnvironment(projectKey) {
|
|
|
3139
3432
|
...(projectKey ? { projectKey, } : {}),
|
|
3140
3433
|
integrationFlags: {
|
|
3141
3434
|
mutating: integrationFlag("RUN_DATAIKU_INTEGRATION_MUTATING"),
|
|
3435
|
+
adminMutating: integrationFlag("RUN_DATAIKU_ADMIN_MUTATING"),
|
|
3142
3436
|
variables: integrationFlag("RUN_DATAIKU_INTEGRATION_VARIABLES"),
|
|
3437
|
+
sqlLive: integrationFlag("RUN_DATAIKU_SQL_LIVE"),
|
|
3143
3438
|
bundles: integrationFlag("RUN_DATAIKU_INTEGRATION_BUNDLES"),
|
|
3144
3439
|
apiServices: integrationFlag("RUN_DATAIKU_INTEGRATION_API_SERVICES"),
|
|
3145
3440
|
},
|
|
@@ -3345,12 +3640,14 @@ async function runDoctor(flags) {
|
|
|
3345
3640
|
let accessibleProjects;
|
|
3346
3641
|
if (credentialsOk) {
|
|
3347
3642
|
const requestTimeoutMs = num(flags["request-timeout"]);
|
|
3643
|
+
const retryMaxAttempts = num(flags["retries"]);
|
|
3348
3644
|
const client = new DataikuClient({
|
|
3349
3645
|
url,
|
|
3350
3646
|
apiKey,
|
|
3351
3647
|
projectKey,
|
|
3352
3648
|
verbose: flags["verbose"] === true,
|
|
3353
3649
|
requestTimeoutMs,
|
|
3650
|
+
retryMaxAttempts,
|
|
3354
3651
|
tlsRejectUnauthorized,
|
|
3355
3652
|
caCertPath,
|
|
3356
3653
|
});
|
|
@@ -3398,13 +3695,14 @@ async function runDoctor(flags) {
|
|
|
3398
3695
|
const result = { ok: checks.every((check) => check.ok), checks, context, };
|
|
3399
3696
|
if (flags["capabilities"] === true && credentialsOk) {
|
|
3400
3697
|
const requestTimeoutMs = num(flags["request-timeout"]);
|
|
3698
|
+
const retryMaxAttempts = num(flags["retries"]) ?? 1;
|
|
3401
3699
|
const client = new DataikuClient({
|
|
3402
3700
|
url,
|
|
3403
3701
|
apiKey,
|
|
3404
3702
|
projectKey,
|
|
3405
3703
|
verbose: flags["verbose"] === true,
|
|
3406
3704
|
requestTimeoutMs,
|
|
3407
|
-
retryMaxAttempts
|
|
3705
|
+
retryMaxAttempts,
|
|
3408
3706
|
tlsRejectUnauthorized,
|
|
3409
3707
|
caCertPath,
|
|
3410
3708
|
});
|
|
@@ -3426,13 +3724,14 @@ async function runFixtures(flags) {
|
|
|
3426
3724
|
}
|
|
3427
3725
|
currentCommandContext.projectKey = projectKey;
|
|
3428
3726
|
const requestTimeoutMs = num(flags["request-timeout"]);
|
|
3727
|
+
const retryMaxAttempts = num(flags["retries"]) ?? 1;
|
|
3429
3728
|
const client = new DataikuClient({
|
|
3430
3729
|
url,
|
|
3431
3730
|
apiKey,
|
|
3432
3731
|
projectKey,
|
|
3433
3732
|
verbose: flags["verbose"] === true,
|
|
3434
3733
|
requestTimeoutMs,
|
|
3435
|
-
retryMaxAttempts
|
|
3734
|
+
retryMaxAttempts,
|
|
3436
3735
|
tlsRejectUnauthorized,
|
|
3437
3736
|
caCertPath,
|
|
3438
3737
|
});
|
|
@@ -3466,6 +3765,7 @@ const READ_ACTIONS = new Set([
|
|
|
3466
3765
|
"preview",
|
|
3467
3766
|
"query",
|
|
3468
3767
|
"schema",
|
|
3768
|
+
"schemas",
|
|
3469
3769
|
"sessions-jupyter",
|
|
3470
3770
|
"status",
|
|
3471
3771
|
"rules",
|
|
@@ -3490,7 +3790,14 @@ const PROJECT_SCOPED_RESOURCES = new Set([
|
|
|
3490
3790
|
"wiki",
|
|
3491
3791
|
]);
|
|
3492
3792
|
const GLOBAL_AGENT_FLAGS = ["help", "json", "report-json", "verbose",];
|
|
3493
|
-
const AUTHENTICATED_AGENT_FLAGS = [
|
|
3793
|
+
const AUTHENTICATED_AGENT_FLAGS = [
|
|
3794
|
+
"url",
|
|
3795
|
+
"api-key",
|
|
3796
|
+
"request-timeout",
|
|
3797
|
+
"retries",
|
|
3798
|
+
"insecure",
|
|
3799
|
+
"ca-cert",
|
|
3800
|
+
];
|
|
3494
3801
|
const COMMANDS_USAGE = "dss commands [--json]";
|
|
3495
3802
|
const COMMANDS_DESCRIPTION = "Print the machine-readable command registry for agent planning.";
|
|
3496
3803
|
const COMMANDS_EXAMPLES = ["dss commands", "dss commands --json",];
|
|
@@ -3584,7 +3891,7 @@ function inferSideEffect(resource, action) {
|
|
|
3584
3891
|
return "write";
|
|
3585
3892
|
if (READ_ACTIONS.has(action))
|
|
3586
3893
|
return "read";
|
|
3587
|
-
if (/^(create|update|delete|set|save|upload|run|build|abort|move|clear|unload|install|login|logout)/
|
|
3894
|
+
if (/^(create|update|delete|set|save|upload|run|build|abort|move|refresh|clear|unload|install|login|logout)/
|
|
3588
3895
|
.test(action)) {
|
|
3589
3896
|
return "write";
|
|
3590
3897
|
}
|
|
@@ -3610,6 +3917,7 @@ const ARRAY_OUTPUT_ACTIONS = new Set([
|
|
|
3610
3917
|
"list-jupyter",
|
|
3611
3918
|
"list-sql",
|
|
3612
3919
|
"rules",
|
|
3920
|
+
"schemas",
|
|
3613
3921
|
"sessions-jupyter",
|
|
3614
3922
|
"usages",
|
|
3615
3923
|
]);
|
|
@@ -3684,6 +3992,8 @@ function inferDestructiveLevel(sideEffect, action) {
|
|
|
3684
3992
|
function inferAsyncKind(resource, action) {
|
|
3685
3993
|
if (resource === "job" && ["build", "build-and-wait", "wait",].includes(action))
|
|
3686
3994
|
return "job";
|
|
3995
|
+
if (resource === "recipe" && action === "run")
|
|
3996
|
+
return "job";
|
|
3687
3997
|
if (resource === "future" && ["get", "peek", "wait", "abort",].includes(action))
|
|
3688
3998
|
return "future";
|
|
3689
3999
|
if (resource === "scenario" && ["run", "run-and-wait", "status",].includes(action)) {
|
|
@@ -3760,7 +4070,8 @@ function buildRegistryEntry(resource, action, meta) {
|
|
|
3760
4070
|
outputShape: inferOutputShape(resource, action),
|
|
3761
4071
|
inputContract,
|
|
3762
4072
|
destructive,
|
|
3763
|
-
producesLocalFile: meta.usage.includes("--output PATH")
|
|
4073
|
+
producesLocalFile: meta.usage.includes("--output PATH")
|
|
4074
|
+
|| meta.usage.includes("--output-file PATH"),
|
|
3764
4075
|
mutatesDss,
|
|
3765
4076
|
async: asyncKind,
|
|
3766
4077
|
idempotency: inferIdempotency(sideEffect, action, meta.usage),
|
|
@@ -3872,9 +4183,20 @@ function querySuffix(params) {
|
|
|
3872
4183
|
return raw ? `?${raw}` : "";
|
|
3873
4184
|
}
|
|
3874
4185
|
function jobBuildPayload(target, projectKey, flags) {
|
|
3875
|
-
const targetType =
|
|
4186
|
+
const targetType = jobBuildTargetTypeFromFlags(flags);
|
|
4187
|
+
const partition = flags["partition"];
|
|
4188
|
+
const output = { projectKey, id: target, type: targetType, };
|
|
4189
|
+
if (targetType === "DATASET") {
|
|
4190
|
+
if (partition !== undefined)
|
|
4191
|
+
output.partition = partition;
|
|
4192
|
+
}
|
|
4193
|
+
else {
|
|
4194
|
+
output.targetManagedFolderProjectKey = projectKey;
|
|
4195
|
+
output.targetManagedFolder = target;
|
|
4196
|
+
output.targetPartition = partition ?? "NP";
|
|
4197
|
+
}
|
|
3876
4198
|
const payload = {
|
|
3877
|
-
outputs: [
|
|
4199
|
+
outputs: [output,],
|
|
3878
4200
|
type: flags["build-mode"] ?? "NON_RECURSIVE_FORCED_BUILD",
|
|
3879
4201
|
};
|
|
3880
4202
|
if (flags["force-rebuild"] === true && targetType === "DATASET") {
|
|
@@ -4060,9 +4382,9 @@ function commandPlanShape(resource, action, args, flags, entry, projectKey) {
|
|
|
4060
4382
|
case "flow-zone.move":
|
|
4061
4383
|
return {
|
|
4062
4384
|
method: "POST",
|
|
4063
|
-
endpoint: projectEndpoint(`/flow/zones/${encodeURIComponent(id)}/
|
|
4385
|
+
endpoint: projectEndpoint(`/flow/zones/${encodeURIComponent(id)}/add-items`),
|
|
4064
4386
|
identifiers: { id, },
|
|
4065
|
-
payload:
|
|
4387
|
+
payload: flowZoneMoveItems(flags),
|
|
4066
4388
|
};
|
|
4067
4389
|
case "dataset.create": {
|
|
4068
4390
|
const name = requiredPlanFlag(flags, "name", entry.usage);
|
|
@@ -4081,6 +4403,15 @@ function commandPlanShape(resource, action, args, flags, entry, projectKey) {
|
|
|
4081
4403
|
endpoint: projectEndpoint(`/datasets/${encodeURIComponent(id)}`),
|
|
4082
4404
|
identifiers: { name: id, },
|
|
4083
4405
|
};
|
|
4406
|
+
case "dataset.refresh-schema": {
|
|
4407
|
+
const columns = schemaColumnsInput(flags, entry.usage);
|
|
4408
|
+
return {
|
|
4409
|
+
method: "PUT",
|
|
4410
|
+
endpoint: projectEndpoint(`/datasets/${encodeURIComponent(id)}/schema`),
|
|
4411
|
+
identifiers: { name: id, },
|
|
4412
|
+
payload: { columns, },
|
|
4413
|
+
};
|
|
4414
|
+
}
|
|
4084
4415
|
case "dataset.update":
|
|
4085
4416
|
return {
|
|
4086
4417
|
method: "PUT",
|
|
@@ -4122,6 +4453,19 @@ function commandPlanShape(resource, action, args, flags, entry, projectKey) {
|
|
|
4122
4453
|
},
|
|
4123
4454
|
};
|
|
4124
4455
|
}
|
|
4456
|
+
case "recipe.run":
|
|
4457
|
+
return {
|
|
4458
|
+
method: "POST",
|
|
4459
|
+
endpoint: projectEndpoint("/jobs/"),
|
|
4460
|
+
identifiers: { recipe: id, },
|
|
4461
|
+
payload: {
|
|
4462
|
+
recipe: id,
|
|
4463
|
+
outputResolution: "dynamic",
|
|
4464
|
+
projectKey,
|
|
4465
|
+
partition: flags["partition"],
|
|
4466
|
+
},
|
|
4467
|
+
wait: recipeRunShouldWait(flags),
|
|
4468
|
+
};
|
|
4125
4469
|
case "recipe.update":
|
|
4126
4470
|
return {
|
|
4127
4471
|
method: "PUT",
|
|
@@ -4129,13 +4473,24 @@ function commandPlanShape(resource, action, args, flags, entry, projectKey) {
|
|
|
4129
4473
|
identifiers: { name: id, },
|
|
4130
4474
|
payload: requiredPlanJsonInput(flags, entry.usage),
|
|
4131
4475
|
};
|
|
4132
|
-
case "recipe.set-payload":
|
|
4476
|
+
case "recipe.set-payload": {
|
|
4477
|
+
const file = requiredPlanFlag(flags, "file", entry.usage);
|
|
4478
|
+
const backupDir = flags["backup-dir"];
|
|
4479
|
+
const backupPath = backupDir ? recipePayloadBackupPath(id, backupDir) : undefined;
|
|
4133
4480
|
return {
|
|
4134
4481
|
method: "PUT",
|
|
4135
|
-
endpoint: projectEndpoint(`/recipes/${encodeURIComponent(id)}
|
|
4482
|
+
endpoint: projectEndpoint(`/recipes/${encodeURIComponent(id)}`),
|
|
4136
4483
|
identifiers: { name: id, },
|
|
4137
|
-
payload: {
|
|
4484
|
+
payload: {
|
|
4485
|
+
file,
|
|
4486
|
+
content: textInput(flags),
|
|
4487
|
+
...(backupPath ? { backupPath, } : {}),
|
|
4488
|
+
},
|
|
4489
|
+
...(backupPath
|
|
4490
|
+
? { localWrites: [{ path: backupPath, source: "remote recipe payload", before: "PUT", },], }
|
|
4491
|
+
: {}),
|
|
4138
4492
|
};
|
|
4493
|
+
}
|
|
4139
4494
|
case "job.build":
|
|
4140
4495
|
case "job.build-and-wait":
|
|
4141
4496
|
return {
|
|
@@ -4402,12 +4757,14 @@ async function runCleanup(flags) {
|
|
|
4402
4757
|
throw new UsageError("Missing API key. Set DATAIKU_API_KEY, pass --api-key, or run: dss auth login");
|
|
4403
4758
|
}
|
|
4404
4759
|
const requestTimeoutMs = num(flags["request-timeout"]);
|
|
4760
|
+
const retryMaxAttempts = num(flags["retries"]);
|
|
4405
4761
|
const client = new DataikuClient({
|
|
4406
4762
|
url,
|
|
4407
4763
|
apiKey,
|
|
4408
4764
|
projectKey,
|
|
4409
4765
|
verbose: flags["verbose"] === true,
|
|
4410
4766
|
requestTimeoutMs,
|
|
4767
|
+
retryMaxAttempts,
|
|
4411
4768
|
tlsRejectUnauthorized,
|
|
4412
4769
|
caCertPath,
|
|
4413
4770
|
});
|
|
@@ -4938,12 +5295,14 @@ async function main() {
|
|
|
4938
5295
|
throw new UsageError("Missing API key. Set DATAIKU_API_KEY, pass --api-key, or run: dss auth login");
|
|
4939
5296
|
}
|
|
4940
5297
|
const requestTimeoutMs = num(flags["request-timeout"]);
|
|
5298
|
+
const retryMaxAttempts = num(flags["retries"]);
|
|
4941
5299
|
const client = new DataikuClient({
|
|
4942
5300
|
url,
|
|
4943
5301
|
apiKey,
|
|
4944
5302
|
projectKey,
|
|
4945
5303
|
verbose: flags["verbose"] === true,
|
|
4946
5304
|
requestTimeoutMs,
|
|
5305
|
+
retryMaxAttempts,
|
|
4947
5306
|
tlsRejectUnauthorized,
|
|
4948
5307
|
caCertPath,
|
|
4949
5308
|
});
|