dataiku-sdk 3.2.0 → 3.3.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/README.md +149 -46
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +102 -0
- package/dist/packages/types/src/index.js +76 -0
- package/dist/src/cli/commands/app.js +57 -15
- package/dist/src/cli/commands/bundle.js +1 -1
- package/dist/src/cli/commands/code-env.js +13 -7
- package/dist/src/cli/commands/connection.d.ts +9 -0
- package/dist/src/cli/commands/connection.js +267 -1
- package/dist/src/cli/commands/data-collection.d.ts +2 -0
- package/dist/src/cli/commands/data-collection.js +164 -0
- package/dist/src/cli/commands/dataset.js +161 -32
- package/dist/src/cli/commands/future.js +2 -2
- package/dist/src/cli/commands/group.d.ts +2 -0
- package/dist/src/cli/commands/group.js +109 -0
- package/dist/src/cli/commands/index.js +151 -78
- package/dist/src/cli/commands/knowledge-bank.d.ts +2 -0
- package/dist/src/cli/commands/knowledge-bank.js +80 -0
- package/dist/src/cli/commands/llm.d.ts +2 -0
- package/dist/src/cli/commands/llm.js +93 -0
- package/dist/src/cli/commands/macro.d.ts +2 -0
- package/dist/src/cli/commands/macro.js +221 -0
- package/dist/src/cli/commands/ml-task.js +18 -6
- package/dist/src/cli/commands/notebook.js +6 -2
- package/dist/src/cli/commands/plugin.d.ts +2 -0
- package/dist/src/cli/commands/plugin.js +799 -0
- package/dist/src/cli/commands/project-folder.d.ts +2 -0
- package/dist/src/cli/commands/project-folder.js +197 -0
- package/dist/src/cli/commands/project-git.js +14 -54
- package/dist/src/cli/commands/project.js +52 -6
- package/dist/src/cli/commands/recipe.js +36 -1
- package/dist/src/cli/commands/saved-model.d.ts +5 -0
- package/dist/src/cli/commands/saved-model.js +388 -1
- package/dist/src/cli/commands/scenario.js +138 -1
- package/dist/src/cli/commands/user.d.ts +8 -0
- package/dist/src/cli/commands/user.js +296 -0
- package/dist/src/cli/contract.d.ts +1 -2
- package/dist/src/cli/contract.js +1089 -103
- package/dist/src/cli/flags.js +30 -1
- package/dist/src/cli/helpers/app-successor.d.ts +19 -4
- package/dist/src/cli/helpers/app-successor.js +90 -30
- package/dist/src/cli/helpers/cleanup.js +3 -1
- package/dist/src/cli/helpers/flow-zone.js +1 -2
- package/dist/src/cli/output.d.ts +1 -1
- package/dist/src/cli/output.js +23 -10
- package/dist/src/cli/usage.d.ts +1 -0
- package/dist/src/cli/usage.js +47 -1
- package/dist/src/cli.js +147 -41
- package/dist/src/client.d.ts +83 -5
- package/dist/src/client.js +185 -29
- package/dist/src/errors.d.ts +3 -0
- package/dist/src/errors.js +2 -0
- package/dist/src/index.d.ts +16 -7
- package/dist/src/index.js +11 -2
- package/dist/src/resources/analyses.js +1 -8
- package/dist/src/resources/applications.d.ts +8 -6
- package/dist/src/resources/applications.js +21 -21
- package/dist/src/resources/base.d.ts +4 -0
- package/dist/src/resources/base.js +15 -0
- package/dist/src/resources/bundles.d.ts +9 -4
- package/dist/src/resources/bundles.js +10 -5
- package/dist/src/resources/connections.d.ts +78 -1
- package/dist/src/resources/connections.js +132 -1
- package/dist/src/resources/data-collections.d.ts +118 -0
- package/dist/src/resources/data-collections.js +49 -0
- package/dist/src/resources/datasets.d.ts +69 -0
- package/dist/src/resources/datasets.js +99 -1
- package/dist/src/resources/futures.d.ts +4 -1
- package/dist/src/resources/futures.js +38 -6
- package/dist/src/resources/groups.d.ts +47 -0
- package/dist/src/resources/groups.js +56 -0
- package/dist/src/resources/jobs.d.ts +8 -13
- package/dist/src/resources/jobs.js +41 -16
- package/dist/src/resources/knowledge-banks.d.ts +58 -0
- package/dist/src/resources/knowledge-banks.js +61 -0
- package/dist/src/resources/llms.d.ts +92 -0
- package/dist/src/resources/llms.js +62 -0
- package/dist/src/resources/macros.d.ts +121 -0
- package/dist/src/resources/macros.js +231 -0
- package/dist/src/resources/ml-tasks.d.ts +37 -2
- package/dist/src/resources/ml-tasks.js +100 -20
- package/dist/src/resources/model-evaluation-stores.js +1 -8
- package/dist/src/resources/notebooks.d.ts +43 -7
- package/dist/src/resources/notebooks.js +53 -13
- package/dist/src/resources/plugins.d.ts +265 -0
- package/dist/src/resources/plugins.js +458 -0
- package/dist/src/resources/project-folders.d.ts +71 -0
- package/dist/src/resources/project-folders.js +57 -0
- package/dist/src/resources/project-git.d.ts +6 -0
- package/dist/src/resources/project-git.js +69 -42
- package/dist/src/resources/project-library.d.ts +0 -1
- package/dist/src/resources/project-library.js +1 -17
- package/dist/src/resources/projects.d.ts +19 -1
- package/dist/src/resources/projects.js +27 -1
- package/dist/src/resources/recipes.d.ts +15 -1
- package/dist/src/resources/recipes.js +73 -6
- package/dist/src/resources/saved-models.d.ts +134 -1
- package/dist/src/resources/saved-models.js +214 -6
- package/dist/src/resources/scenarios.d.ts +105 -0
- package/dist/src/resources/scenarios.js +232 -106
- package/dist/src/resources/sql.js +5 -1
- package/dist/src/resources/users.d.ts +129 -0
- package/dist/src/resources/users.js +128 -0
- package/dist/src/resources/webapps.d.ts +15 -2
- package/dist/src/resources/webapps.js +18 -4
- package/dist/src/schemas.d.ts +2 -2
- package/dist/src/schemas.js +1 -1
- package/dist/src/utils/deep-merge.d.ts +1 -1
- package/dist/src/utils/polling.d.ts +20 -0
- package/dist/src/utils/polling.js +27 -0
- package/dist/src/utils/response-file.js +1 -1
- package/dist/src/utils/secret-sanitize.d.ts +54 -0
- package/dist/src/utils/secret-sanitize.js +101 -0
- package/package.json +6 -5
- package/packages/types/dist/index.d.ts +102 -0
- package/packages/types/dist/index.js +76 -0
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +7 -5
- package/skills/dataiku-dss/references/app-releases.md +8 -7
- package/skills/dataiku-dss/references/discovery.md +4 -4
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { requiredJsonInput, } from "../coerce.js";
|
|
2
|
+
import { executionMode, } from "../flags.js";
|
|
3
|
+
import { planResult, } from "../output.js";
|
|
4
|
+
import { requireArgs, UsageError, } from "../usage.js";
|
|
5
|
+
const PLAN_FAILURE_CODES = { usage: 1, error: 2, transient: 3, };
|
|
6
|
+
function collectionEndpoint(dataCollectionId, suffix = "") {
|
|
7
|
+
return `/public/api/data-collections/${encodeURIComponent(dataCollectionId)}${suffix}`;
|
|
8
|
+
}
|
|
9
|
+
export const dataCollectionCommands = {
|
|
10
|
+
list: {
|
|
11
|
+
handler: (c) => c.dataCollections.list(),
|
|
12
|
+
usage: "dss data-collection list",
|
|
13
|
+
description: "List data collections on which the API key has READ privilege.",
|
|
14
|
+
examples: ["dss data-collection list",],
|
|
15
|
+
},
|
|
16
|
+
get: {
|
|
17
|
+
handler: (c, a) => {
|
|
18
|
+
requireArgs(a, 1, "dss data-collection get <dataCollectionId>");
|
|
19
|
+
return c.dataCollections.get(a[0]);
|
|
20
|
+
},
|
|
21
|
+
usage: "dss data-collection get <dataCollectionId>",
|
|
22
|
+
description: "Get collection settings. Permissions are omitted for non-admins.",
|
|
23
|
+
examples: ["dss data-collection get OjVsTQ3O",],
|
|
24
|
+
},
|
|
25
|
+
create: {
|
|
26
|
+
handler: async (c, _a, f) => {
|
|
27
|
+
const body = requiredJsonInput(f, "--data, --data-file, or --stdin is required (collection definition).");
|
|
28
|
+
if (executionMode(f).dryRun) {
|
|
29
|
+
return planResult("data-collection", "create", {
|
|
30
|
+
asyncKind: "none",
|
|
31
|
+
method: "POST",
|
|
32
|
+
endpoint: "/public/api/data-collections/",
|
|
33
|
+
payload: body,
|
|
34
|
+
idempotency: "none",
|
|
35
|
+
exitCodesOnFailure: PLAN_FAILURE_CODES,
|
|
36
|
+
plannedAndDryRun: true,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return c.dataCollections.create(body);
|
|
40
|
+
},
|
|
41
|
+
usage: "dss data-collection create (--data JSON|--data-file PATH|--stdin) [--dry-run]",
|
|
42
|
+
description: "Create a collection (creator becomes admin; requires mayCreateDataCollections).",
|
|
43
|
+
examples: [
|
|
44
|
+
'dss data-collection create --data \'{"displayName":"My Collection"}\'',
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
"settings-set": {
|
|
48
|
+
handler: async (c, a, f) => {
|
|
49
|
+
requireArgs(a, 1, "dss data-collection settings-set <dataCollectionId> (--data JSON|--data-file PATH|--stdin) [--dry-run]");
|
|
50
|
+
const settings = requiredJsonInput(f, "--data, --data-file, or --stdin is required (collection settings).");
|
|
51
|
+
if (executionMode(f).dryRun) {
|
|
52
|
+
return planResult("data-collection", "settings-set", {
|
|
53
|
+
asyncKind: "none",
|
|
54
|
+
method: "PUT",
|
|
55
|
+
endpoint: collectionEndpoint(a[0]),
|
|
56
|
+
identifiers: { dataCollectionId: a[0], },
|
|
57
|
+
payload: settings,
|
|
58
|
+
idempotency: "none",
|
|
59
|
+
exitCodesOnFailure: PLAN_FAILURE_CODES,
|
|
60
|
+
plannedAndDryRun: true,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const updated = await c.dataCollections.update(a[0], settings);
|
|
64
|
+
return { updated: a[0], resource: "data-collection", ...updated, };
|
|
65
|
+
},
|
|
66
|
+
usage: "dss data-collection settings-set <dataCollectionId> (--data JSON|--data-file PATH|--stdin) [--dry-run]",
|
|
67
|
+
description: "Update collection settings; only send settings obtained through get. Admin required.",
|
|
68
|
+
examples: [
|
|
69
|
+
"dss data-collection settings-set OjVsTQ3O --data-file settings.json",
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
delete: {
|
|
73
|
+
validate: (a) => {
|
|
74
|
+
const usage = "dss data-collection delete <dataCollectionId> [--dry-run]";
|
|
75
|
+
requireArgs(a, 1, usage);
|
|
76
|
+
if (a[0].trim().length === 0) {
|
|
77
|
+
throw new UsageError(`<dataCollectionId> must be a non-empty identifier. Usage: ${usage}`);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
handler: async (c, a, f) => {
|
|
81
|
+
if (executionMode(f).dryRun) {
|
|
82
|
+
return planResult("data-collection", "delete", {
|
|
83
|
+
asyncKind: "none",
|
|
84
|
+
method: "DELETE",
|
|
85
|
+
endpoint: collectionEndpoint(a[0]),
|
|
86
|
+
identifiers: { dataCollectionId: a[0], },
|
|
87
|
+
idempotency: "none",
|
|
88
|
+
exitCodesOnFailure: PLAN_FAILURE_CODES,
|
|
89
|
+
plannedAndDryRun: true,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
await c.dataCollections.delete(a[0]);
|
|
93
|
+
return { deleted: a[0], resource: "data-collection", };
|
|
94
|
+
},
|
|
95
|
+
usage: "dss data-collection delete <dataCollectionId> [--dry-run]",
|
|
96
|
+
description: "Permanently delete a collection. Admin required.",
|
|
97
|
+
examples: ["dss data-collection delete OjVsTQ3O --dry-run",],
|
|
98
|
+
},
|
|
99
|
+
"list-objects": {
|
|
100
|
+
handler: (c, a) => {
|
|
101
|
+
requireArgs(a, 1, "dss data-collection list-objects <dataCollectionId>");
|
|
102
|
+
return c.dataCollections.listObjects(a[0]);
|
|
103
|
+
},
|
|
104
|
+
usage: "dss data-collection list-objects <dataCollectionId>",
|
|
105
|
+
description: "List the objects in a collection.",
|
|
106
|
+
examples: ["dss data-collection list-objects OjVsTQ3O",],
|
|
107
|
+
},
|
|
108
|
+
"add-object": {
|
|
109
|
+
handler: async (c, a, f) => {
|
|
110
|
+
const object = requiredJsonInput(f, "--data, --data-file, or --stdin is required (collection object reference).");
|
|
111
|
+
const collectionId = a[0]
|
|
112
|
+
?? (typeof object.dataCollectionId === "string" ? object.dataCollectionId : undefined);
|
|
113
|
+
if (!collectionId) {
|
|
114
|
+
throw new UsageError("Usage: dss data-collection add-object <dataCollectionId> (--data JSON|--data-file PATH|--stdin)");
|
|
115
|
+
}
|
|
116
|
+
const reference = { ...object, };
|
|
117
|
+
delete reference.dataCollectionId;
|
|
118
|
+
if (executionMode(f).dryRun) {
|
|
119
|
+
return planResult("data-collection", "add-object", {
|
|
120
|
+
asyncKind: "none",
|
|
121
|
+
method: "POST",
|
|
122
|
+
endpoint: `${collectionEndpoint(collectionId)}/objects`,
|
|
123
|
+
identifiers: { dataCollectionId: collectionId, },
|
|
124
|
+
payload: reference,
|
|
125
|
+
idempotency: "none",
|
|
126
|
+
exitCodesOnFailure: PLAN_FAILURE_CODES,
|
|
127
|
+
plannedAndDryRun: true,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
await c.dataCollections.addObject(collectionId, reference);
|
|
131
|
+
return { added: reference.id, dataCollectionId: collectionId, resource: "data-collection", };
|
|
132
|
+
},
|
|
133
|
+
usage: "dss data-collection add-object <dataCollectionId> (--data JSON|--data-file PATH|--stdin) [--dry-run]",
|
|
134
|
+
description: "Add an object (e.g. {type:'DATASET',projectKey:'K',id:'name'}) to a collection. Contributor required.",
|
|
135
|
+
examples: [
|
|
136
|
+
'dss data-collection add-object OjVsTQ3O --data \'{"type":"DATASET","projectKey":"MYPROJECT","id":"orders"}\'',
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
"remove-dataset": {
|
|
140
|
+
handler: async (c, a, f) => {
|
|
141
|
+
requireArgs(a, 3, "dss data-collection remove-dataset <dataCollectionId> <projectKey> <datasetName> [--dry-run]");
|
|
142
|
+
if (executionMode(f).dryRun) {
|
|
143
|
+
return planResult("data-collection", "remove-dataset", {
|
|
144
|
+
asyncKind: "none",
|
|
145
|
+
method: "DELETE",
|
|
146
|
+
endpoint: `${collectionEndpoint(a[0])}/objects/dataset/${encodeURIComponent(a[1])}/${encodeURIComponent(a[2])}`,
|
|
147
|
+
identifiers: {
|
|
148
|
+
dataCollectionId: a[0],
|
|
149
|
+
projectKey: a[1],
|
|
150
|
+
datasetName: a[2],
|
|
151
|
+
},
|
|
152
|
+
idempotency: "none",
|
|
153
|
+
exitCodesOnFailure: PLAN_FAILURE_CODES,
|
|
154
|
+
plannedAndDryRun: true,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
await c.dataCollections.removeDataset(a[0], a[1], a[2]);
|
|
158
|
+
return { removed: a[2], projectKey: a[1], dataCollectionId: a[0], resource: "data-collection", };
|
|
159
|
+
},
|
|
160
|
+
usage: "dss data-collection remove-dataset <dataCollectionId> <projectKey> <datasetName> [--dry-run]",
|
|
161
|
+
description: "Remove a dataset from a collection. Contributor required.",
|
|
162
|
+
examples: ["dss data-collection remove-dataset OjVsTQ3O MYPROJECT DATASET1",],
|
|
163
|
+
},
|
|
164
|
+
};
|
|
@@ -308,43 +308,38 @@ export const datasetCommands = {
|
|
|
308
308
|
description: "Get dataset-level metadata.",
|
|
309
309
|
examples: ["dss dataset metadata orders",],
|
|
310
310
|
},
|
|
311
|
-
|
|
311
|
+
"metadata-set": {
|
|
312
312
|
handler: async (c, a, f) => {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
enqueueCliWarning({
|
|
322
|
-
code: "dataset_download_truncated",
|
|
323
|
-
message: `Download of '${a[0]}' stopped at the ${result.limit}-row cap; the dataset has more rows. `
|
|
324
|
-
+ "Re-run with --limit N for more, or read inside a recipe (get_dataframe) for the full data.",
|
|
325
|
-
dataset: a[0],
|
|
326
|
-
rows: result.rows,
|
|
327
|
-
limit: result.limit,
|
|
328
|
-
path: result.path,
|
|
329
|
-
});
|
|
313
|
+
const usage = "dss dataset metadata-set <name> (--data JSON | --data-file PATH | --stdin) [--dry-run] [--project-key KEY]";
|
|
314
|
+
requireArgs(a, 1, usage);
|
|
315
|
+
// Validated identically for live, --plan, and --dry-run: the JSON
|
|
316
|
+
// input replaces the server metadata object verbatim (faithful PUT;
|
|
317
|
+
// no client-side merge).
|
|
318
|
+
const metadata = jsonInput(f);
|
|
319
|
+
if (metadata === undefined) {
|
|
320
|
+
throw new UsageError(`--data, --data-file, or --stdin is required. Usage: ${usage}`);
|
|
330
321
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
322
|
+
const pk = f["project-key"];
|
|
323
|
+
if (executionMode(f).dryRun) {
|
|
324
|
+
// Zero HTTP: the replacement JSON is validated and echoed as-is;
|
|
325
|
+
// current server state is intentionally not fetched (faithful
|
|
326
|
+
// replace means the PUT body is exactly this object).
|
|
327
|
+
return {
|
|
328
|
+
dryRun: true,
|
|
329
|
+
action: "metadata-set",
|
|
330
|
+
resource: "dataset",
|
|
331
|
+
name: a[0],
|
|
332
|
+
next: metadata,
|
|
333
|
+
};
|
|
339
334
|
}
|
|
340
|
-
|
|
335
|
+
const updated = await c.datasets.updateMetadata(a[0], metadata, pk);
|
|
336
|
+
return { updated: a[0], resource: "dataset", metadata: updated, };
|
|
341
337
|
},
|
|
342
|
-
usage: "dss dataset
|
|
343
|
-
description: "
|
|
338
|
+
usage: "dss dataset metadata-set <name> (--data JSON | --data-file PATH | --stdin) [--dry-run] [--project-key KEY]",
|
|
339
|
+
description: "Replace dataset-level metadata with the given JSON object (faithful PUT: GET, edit, PUT full object; no merge).",
|
|
344
340
|
examples: [
|
|
345
|
-
|
|
346
|
-
"dss dataset
|
|
347
|
-
"dss dataset download orders --raw-data",
|
|
341
|
+
`dss dataset metadata-set orders --data '{"label":"Orders","tags":["prod"]}' --dry-run`,
|
|
342
|
+
'echo \'{"label":"Orders"}\' | dss dataset metadata-set orders --stdin',
|
|
348
343
|
],
|
|
349
344
|
},
|
|
350
345
|
create: {
|
|
@@ -396,6 +391,140 @@ export const datasetCommands = {
|
|
|
396
391
|
"dss dataset create --name orders --connection filesystem --type Filesystem --zone Experiments --dry-run",
|
|
397
392
|
],
|
|
398
393
|
},
|
|
394
|
+
"create-managed": {
|
|
395
|
+
handler: async (c, _a, f) => {
|
|
396
|
+
const usage = "dss dataset create-managed --name NAME --connection CONN [--type-option-id ID] [--format-option-id ID] [--copy-partitioning-from REF] [--partitioning-folder] [--dry-run] [--project-key KEY]";
|
|
397
|
+
const name = f["name"];
|
|
398
|
+
if (!name || name.trim() === "") {
|
|
399
|
+
throw new UsageError(`--name is required. Usage: ${usage}`);
|
|
400
|
+
}
|
|
401
|
+
const connection = f["connection"];
|
|
402
|
+
if (!connection || connection.trim() === "") {
|
|
403
|
+
throw new UsageError(`--connection is required. Usage: ${usage}`);
|
|
404
|
+
}
|
|
405
|
+
const pk = f["project-key"];
|
|
406
|
+
// Server-derived settings only: no fabricated defaults are merged in.
|
|
407
|
+
const payload = {
|
|
408
|
+
name,
|
|
409
|
+
connection,
|
|
410
|
+
...(typeof f["type-option-id"] === "string" ? { typeOptionId: f["type-option-id"], } : {}),
|
|
411
|
+
...(typeof f["format-option-id"] === "string"
|
|
412
|
+
? { formatOptionId: f["format-option-id"], }
|
|
413
|
+
: {}),
|
|
414
|
+
...(typeof f["copy-partitioning-from"] === "string"
|
|
415
|
+
? {
|
|
416
|
+
copyPartitioningFrom: {
|
|
417
|
+
ref: f["copy-partitioning-from"],
|
|
418
|
+
...(f["partitioning-folder"] === true ? { type: "FOLDER", } : {}),
|
|
419
|
+
},
|
|
420
|
+
}
|
|
421
|
+
: {}),
|
|
422
|
+
};
|
|
423
|
+
if (executionMode(f).dryRun) {
|
|
424
|
+
return { dryRun: true, action: "create-managed", resource: "dataset", ...payload, };
|
|
425
|
+
}
|
|
426
|
+
const created = await c.datasets.createManaged({
|
|
427
|
+
name,
|
|
428
|
+
connection,
|
|
429
|
+
...(typeof f["type-option-id"] === "string" ? { typeOptionId: f["type-option-id"], } : {}),
|
|
430
|
+
...(typeof f["format-option-id"] === "string"
|
|
431
|
+
? { formatOptionId: f["format-option-id"], }
|
|
432
|
+
: {}),
|
|
433
|
+
...(typeof f["copy-partitioning-from"] === "string"
|
|
434
|
+
? {
|
|
435
|
+
copyPartitioningFrom: {
|
|
436
|
+
ref: f["copy-partitioning-from"],
|
|
437
|
+
...(f["partitioning-folder"] === true ? { type: "FOLDER", } : {}),
|
|
438
|
+
},
|
|
439
|
+
}
|
|
440
|
+
: {}),
|
|
441
|
+
}, pk);
|
|
442
|
+
return {
|
|
443
|
+
created: created.datasetName,
|
|
444
|
+
resource: "dataset",
|
|
445
|
+
managed: true,
|
|
446
|
+
projectKey: created.projectKey,
|
|
447
|
+
creationSettings: created.creationSettings,
|
|
448
|
+
};
|
|
449
|
+
},
|
|
450
|
+
usage: "dss dataset create-managed --name NAME --connection CONN [--type-option-id ID] [--format-option-id ID] [--copy-partitioning-from REF] [--partitioning-folder] [--dry-run] [--project-key KEY]",
|
|
451
|
+
description: "Create a managed dataset via the dedicated endpoint: DSS derives storage/format details; you pick name, connection, and optional type/format/partitioning options.",
|
|
452
|
+
examples: [
|
|
453
|
+
"dss dataset create-managed --name orders_copy --connection filesystem_managed",
|
|
454
|
+
"dss dataset create-managed --name events_parquet --connection s3_conn --format-option-id PARQUET_HIVE --dry-run",
|
|
455
|
+
"dss dataset create-managed --name partitioned --connection s3_conn --copy-partitioning-from raw_events",
|
|
456
|
+
],
|
|
457
|
+
},
|
|
458
|
+
info: {
|
|
459
|
+
handler: (c, a, f) => {
|
|
460
|
+
requireArgs(a, 1, "dss dataset info <name>");
|
|
461
|
+
return c.datasets.info(a[0], f["project-key"]);
|
|
462
|
+
},
|
|
463
|
+
usage: "dss dataset info <name> [--project-key KEY]",
|
|
464
|
+
description: "Get the full info object for a dataset (type, parameters, last build information, schema, etc.).",
|
|
465
|
+
examples: ["dss dataset info orders", "dss dataset info orders --project-key MYPROJ",],
|
|
466
|
+
},
|
|
467
|
+
"column-lineage": {
|
|
468
|
+
handler: (c, a, f) => {
|
|
469
|
+
const usage = "dss dataset column-lineage <name> <column> [--max-dataset-count N] [--project-key KEY]";
|
|
470
|
+
requireArgs(a, 2, usage);
|
|
471
|
+
const maxDatasetCount = num(f["max-dataset-count"], "--max-dataset-count");
|
|
472
|
+
if (maxDatasetCount !== undefined
|
|
473
|
+
&& (!Number.isSafeInteger(maxDatasetCount) || maxDatasetCount <= 0)) {
|
|
474
|
+
throw new UsageError(`--max-dataset-count must be a positive integer (got "${String(f["max-dataset-count"])}"). `
|
|
475
|
+
+ `Usage: ${usage}`, "validation_failed");
|
|
476
|
+
}
|
|
477
|
+
return c.datasets.getColumnLineage(a[0], a[1], {
|
|
478
|
+
maxDatasetCount,
|
|
479
|
+
projectKey: f["project-key"],
|
|
480
|
+
});
|
|
481
|
+
},
|
|
482
|
+
usage: "dss dataset column-lineage <name> <column> [--max-dataset-count N] [--project-key KEY]",
|
|
483
|
+
description: "Get the full column lineage (auto-computed and manual) of a column; includes local and foreign project relations.",
|
|
484
|
+
examples: [
|
|
485
|
+
"dss dataset column-lineage orders customer_id",
|
|
486
|
+
"dss dataset column-lineage orders customer_id --max-dataset-count 2000",
|
|
487
|
+
],
|
|
488
|
+
},
|
|
489
|
+
download: {
|
|
490
|
+
handler: async (c, a, f) => {
|
|
491
|
+
requireArgs(a, 1, "dss dataset download <name>");
|
|
492
|
+
const result = await c.datasets.download(a[0], {
|
|
493
|
+
outputPath: f["output"],
|
|
494
|
+
projectKey: f["project-key"],
|
|
495
|
+
limit: num(f["limit"], "--limit"),
|
|
496
|
+
rawData: f["raw-data"] === true,
|
|
497
|
+
});
|
|
498
|
+
if (result.truncated) {
|
|
499
|
+
enqueueCliWarning({
|
|
500
|
+
code: "dataset_download_truncated",
|
|
501
|
+
message: `Download of '${a[0]}' stopped at the ${result.limit}-row cap; the dataset has more rows. `
|
|
502
|
+
+ "Re-run with --limit N for more, or read inside a recipe (get_dataframe) for the full data.",
|
|
503
|
+
dataset: a[0],
|
|
504
|
+
rows: result.rows,
|
|
505
|
+
limit: result.limit,
|
|
506
|
+
path: result.path,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
if (!f["output"]) {
|
|
510
|
+
enqueueCliWarning({
|
|
511
|
+
code: "dataset_download_default_location",
|
|
512
|
+
message: `No --output was given, so '${a[0]}' was written to '${result.path}' in the current directory. `
|
|
513
|
+
+ "Pass --output PATH to control the destination and avoid writing into your working tree.",
|
|
514
|
+
dataset: a[0],
|
|
515
|
+
path: result.path,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
return result;
|
|
519
|
+
},
|
|
520
|
+
usage: "dss dataset download <name> [--output PATH] [--limit N] [--raw-data] [--project-key KEY]",
|
|
521
|
+
description: "Download up to --limit rows (default 100k) as CSV and return { path, rows, truncated, limit }. Formula-like cells are neutralized for spreadsheets; --raw-data preserves exact bytes. Warnings report truncation and the default output path.",
|
|
522
|
+
examples: [
|
|
523
|
+
"dss dataset download orders",
|
|
524
|
+
"dss dataset download orders --output ./data/",
|
|
525
|
+
"dss dataset download orders --raw-data",
|
|
526
|
+
],
|
|
527
|
+
},
|
|
399
528
|
clone: {
|
|
400
529
|
handler: async (c, a, f) => {
|
|
401
530
|
const usage = "dss dataset clone <source> <target> [--path PATH] [--table TABLE] [--metastore-table TABLE] [--allow-same-path] [--zone ZONE|--zone-id ID] [--dry-run] [--project-key KEY]";
|
|
@@ -39,8 +39,8 @@ export const futureCommands = {
|
|
|
39
39
|
const id = a[0];
|
|
40
40
|
if (executionMode(f).dryRun) {
|
|
41
41
|
return planResult("future", "abort", {
|
|
42
|
-
method: "
|
|
43
|
-
endpoint: `/public/api/futures/${encodeURIComponent(id)}
|
|
42
|
+
method: "DELETE",
|
|
43
|
+
endpoint: `/public/api/futures/${encodeURIComponent(id)}`,
|
|
44
44
|
identifiers: { id, },
|
|
45
45
|
idempotency: "none",
|
|
46
46
|
asyncKind: "future",
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { requiredJsonInput, } from "../coerce.js";
|
|
2
|
+
import { executionMode, } from "../flags.js";
|
|
3
|
+
import { readIfExists, skipResult, } from "../output.js";
|
|
4
|
+
import { requireArgs, UsageError, } from "../usage.js";
|
|
5
|
+
/** Group identifiers must be non-empty before any request or dry-run preview. */
|
|
6
|
+
function requireGroupName(value, usage) {
|
|
7
|
+
const trimmed = value?.trim() ?? "";
|
|
8
|
+
if (trimmed.length === 0) {
|
|
9
|
+
throw new UsageError(`group name must be a non-empty string.\nUsage: ${usage}`, "validation_failed");
|
|
10
|
+
}
|
|
11
|
+
return trimmed;
|
|
12
|
+
}
|
|
13
|
+
export const groupCommands = {
|
|
14
|
+
list: {
|
|
15
|
+
handler: (c) => c.groups.list(),
|
|
16
|
+
usage: "dss group list",
|
|
17
|
+
description: "List DSS groups (admin).",
|
|
18
|
+
examples: ["dss group list",],
|
|
19
|
+
},
|
|
20
|
+
get: {
|
|
21
|
+
handler: (c, a) => {
|
|
22
|
+
const usage = "dss group get <name>";
|
|
23
|
+
requireArgs(a, 1, usage);
|
|
24
|
+
return c.groups.get(requireGroupName(a[0], usage));
|
|
25
|
+
},
|
|
26
|
+
usage: "dss group get <name>",
|
|
27
|
+
description: "Get a DSS group (admin).",
|
|
28
|
+
examples: ["dss group get administrators",],
|
|
29
|
+
},
|
|
30
|
+
create: {
|
|
31
|
+
handler: async (c, _a, f) => {
|
|
32
|
+
const usage = "dss group create (--data JSON|--data-file PATH|--stdin)";
|
|
33
|
+
const body = requiredJsonInput(f, `--data, --data-file, or --stdin is required (group definition). Usage: ${usage}`);
|
|
34
|
+
if (executionMode(f).dryRun) {
|
|
35
|
+
return {
|
|
36
|
+
dryRun: true,
|
|
37
|
+
action: "create",
|
|
38
|
+
resource: "group",
|
|
39
|
+
name: typeof body.name === "string" ? body.name : undefined,
|
|
40
|
+
method: "POST",
|
|
41
|
+
endpoint: "/public/api/admin/groups",
|
|
42
|
+
payload: body,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return c.groups.create(body);
|
|
46
|
+
},
|
|
47
|
+
usage: "dss group create (--data JSON|--data-file PATH|--stdin) [--dry-run]",
|
|
48
|
+
description: 'Create a DSS group (admin). Body follows the DSS Group schema, e.g. {"name":"analysts","admin":false,"description":"..."}.',
|
|
49
|
+
examples: [
|
|
50
|
+
`dss group create --data '{"name":"analysts","admin":false,"description":"Business analysts"}'`,
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
update: {
|
|
54
|
+
handler: async (c, a, f) => {
|
|
55
|
+
const usage = "dss group update <name> (--data JSON|--data-file PATH|--stdin) [--dry-run]";
|
|
56
|
+
requireArgs(a, 1, usage);
|
|
57
|
+
const name = requireGroupName(a[0], usage);
|
|
58
|
+
const body = requiredJsonInput(f, `--data, --data-file, or --stdin is required (group definition). Usage: ${usage}`);
|
|
59
|
+
if (executionMode(f).dryRun) {
|
|
60
|
+
return {
|
|
61
|
+
dryRun: true,
|
|
62
|
+
action: "update",
|
|
63
|
+
resource: "group",
|
|
64
|
+
name,
|
|
65
|
+
method: "PUT",
|
|
66
|
+
endpoint: `/public/api/admin/groups/${encodeURIComponent(name)}`,
|
|
67
|
+
payload: body,
|
|
68
|
+
note: "PUT replaces the whole Group object; the body must come from `dss group get`. No GET was issued in dry-run.",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
await c.groups.update(name, body);
|
|
72
|
+
return { updated: name, };
|
|
73
|
+
},
|
|
74
|
+
usage: "dss group update <name> (--data JSON|--data-file PATH|--stdin) [--dry-run]",
|
|
75
|
+
description: "Update a DSS group (admin). The body MUST be the Group object obtained from `dss group get` (PUT semantics); pass undocumented attributes through unchanged. Use --dry-run to preview the merged result without writing.",
|
|
76
|
+
examples: [
|
|
77
|
+
`dss group update analysts --data '{"name":"ANALYSTS","admin":false,"description":"Business analysts"}'`,
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
delete: {
|
|
81
|
+
handler: async (c, a, f) => {
|
|
82
|
+
const usage = "dss group delete <name> [--if-exists] [--dry-run]";
|
|
83
|
+
requireArgs(a, 1, usage);
|
|
84
|
+
const name = requireGroupName(a[0], usage);
|
|
85
|
+
if (executionMode(f).dryRun) {
|
|
86
|
+
return {
|
|
87
|
+
dryRun: true,
|
|
88
|
+
action: "delete",
|
|
89
|
+
resource: "group",
|
|
90
|
+
name,
|
|
91
|
+
method: "DELETE",
|
|
92
|
+
endpoint: `/public/api/admin/groups/${encodeURIComponent(name)}`,
|
|
93
|
+
...(f["if-exists"] === true
|
|
94
|
+
? { note: "Existence not checked in dry-run; live --if-exists issues a GET probe first.", }
|
|
95
|
+
: {}),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (f["if-exists"] === true) {
|
|
99
|
+
const current = await readIfExists(() => c.groups.get(name));
|
|
100
|
+
if (!current)
|
|
101
|
+
return skipResult("group", name, "missing");
|
|
102
|
+
}
|
|
103
|
+
return c.groups.delete(name);
|
|
104
|
+
},
|
|
105
|
+
usage: "dss group delete <name> [--if-exists] [--dry-run]",
|
|
106
|
+
description: "Delete a DSS group (admin). Destructive and irreversible.",
|
|
107
|
+
examples: ["dss group delete analysts", "dss group delete analysts --if-exists",],
|
|
108
|
+
},
|
|
109
|
+
};
|