dataiku-sdk 3.2.0 → 3.4.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 +151 -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/code.js +1 -1
- 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 +162 -33
- 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/job.js +4 -2
- 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 +15 -55
- 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 +139 -2
- 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 +1098 -297
- 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-schemas.d.ts +24 -0
- package/dist/src/cli/output-schemas.js +233 -0
- 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 +92 -5
- package/dist/src/client.js +202 -31
- package/dist/src/errors.d.ts +3 -0
- package/dist/src/errors.js +8 -4
- package/dist/src/generated/action-output-schemas.json +1735 -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 +136 -5
- package/dist/src/resources/flow-zones.d.ts +6 -2
- package/dist/src/resources/flow-zones.js +6 -3
- package/dist/src/resources/futures.d.ts +6 -1
- package/dist/src/resources/futures.js +68 -22
- 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 +71 -34
- 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 +109 -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 +263 -0
- package/dist/src/resources/plugins.js +455 -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 +12 -12
- package/dist/src/resources/project-git.js +84 -82
- 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 +23 -3
- package/dist/src/resources/projects.js +60 -34
- 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/git-reference.d.ts +12 -0
- package/dist/src/utils/git-reference.js +38 -0
- 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 +9 -8
- 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 +11 -7
- package/skills/dataiku-dss/references/app-releases.md +8 -8
- package/skills/dataiku-dss/references/authentication.md +6 -6
- package/skills/dataiku-dss/references/discovery.md +4 -4
- package/skills/dataiku-dss/references/mutations.md +1 -1
- package/skills/dataiku-dss/references/troubleshooting.md +2 -2
|
@@ -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
|
+
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { buildDatasetCloneSettings, } from "../../resources/datasets.js";
|
|
2
1
|
import { deepMerge, } from "../../utils/deep-merge.js";
|
|
3
2
|
import { compareStrings, stableHash, } from "../../utils/stable-hash.js";
|
|
4
3
|
import { jsonInput, num, schemaColumnsInput, unknownJsonInput, } from "../coerce.js";
|
|
@@ -308,43 +307,38 @@ export const datasetCommands = {
|
|
|
308
307
|
description: "Get dataset-level metadata.",
|
|
309
308
|
examples: ["dss dataset metadata orders",],
|
|
310
309
|
},
|
|
311
|
-
|
|
310
|
+
"metadata-set": {
|
|
312
311
|
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
|
-
});
|
|
312
|
+
const usage = "dss dataset metadata-set <name> (--data JSON | --data-file PATH | --stdin) [--dry-run] [--project-key KEY]";
|
|
313
|
+
requireArgs(a, 1, usage);
|
|
314
|
+
// Validated identically for live, --plan, and --dry-run: the JSON
|
|
315
|
+
// input replaces the server metadata object verbatim (faithful PUT;
|
|
316
|
+
// no client-side merge).
|
|
317
|
+
const metadata = jsonInput(f);
|
|
318
|
+
if (metadata === undefined) {
|
|
319
|
+
throw new UsageError(`--data, --data-file, or --stdin is required. Usage: ${usage}`);
|
|
330
320
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
321
|
+
const pk = f["project-key"];
|
|
322
|
+
if (executionMode(f).dryRun) {
|
|
323
|
+
// Zero HTTP: the replacement JSON is validated and echoed as-is;
|
|
324
|
+
// current server state is intentionally not fetched (faithful
|
|
325
|
+
// replace means the PUT body is exactly this object).
|
|
326
|
+
return {
|
|
327
|
+
dryRun: true,
|
|
328
|
+
action: "metadata-set",
|
|
329
|
+
resource: "dataset",
|
|
330
|
+
name: a[0],
|
|
331
|
+
next: metadata,
|
|
332
|
+
};
|
|
339
333
|
}
|
|
340
|
-
|
|
334
|
+
const updated = await c.datasets.updateMetadata(a[0], metadata, pk);
|
|
335
|
+
return { updated: a[0], resource: "dataset", metadata: updated, };
|
|
341
336
|
},
|
|
342
|
-
usage: "dss dataset
|
|
343
|
-
description: "
|
|
337
|
+
usage: "dss dataset metadata-set <name> (--data JSON | --data-file PATH | --stdin) [--dry-run] [--project-key KEY]",
|
|
338
|
+
description: "Replace dataset-level metadata with the given JSON object (faithful PUT: GET, edit, PUT full object; no merge).",
|
|
344
339
|
examples: [
|
|
345
|
-
|
|
346
|
-
"dss dataset
|
|
347
|
-
"dss dataset download orders --raw-data",
|
|
340
|
+
`dss dataset metadata-set orders --data '{"label":"Orders","tags":["prod"]}' --dry-run`,
|
|
341
|
+
'echo \'{"label":"Orders"}\' | dss dataset metadata-set orders --stdin',
|
|
348
342
|
],
|
|
349
343
|
},
|
|
350
344
|
create: {
|
|
@@ -396,6 +390,140 @@ export const datasetCommands = {
|
|
|
396
390
|
"dss dataset create --name orders --connection filesystem --type Filesystem --zone Experiments --dry-run",
|
|
397
391
|
],
|
|
398
392
|
},
|
|
393
|
+
"create-managed": {
|
|
394
|
+
handler: async (c, _a, f) => {
|
|
395
|
+
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]";
|
|
396
|
+
const name = f["name"];
|
|
397
|
+
if (!name || name.trim() === "") {
|
|
398
|
+
throw new UsageError(`--name is required. Usage: ${usage}`);
|
|
399
|
+
}
|
|
400
|
+
const connection = f["connection"];
|
|
401
|
+
if (!connection || connection.trim() === "") {
|
|
402
|
+
throw new UsageError(`--connection is required. Usage: ${usage}`);
|
|
403
|
+
}
|
|
404
|
+
const pk = f["project-key"];
|
|
405
|
+
// Server-derived settings only: no fabricated defaults are merged in.
|
|
406
|
+
const payload = {
|
|
407
|
+
name,
|
|
408
|
+
connection,
|
|
409
|
+
...(typeof f["type-option-id"] === "string" ? { typeOptionId: f["type-option-id"], } : {}),
|
|
410
|
+
...(typeof f["format-option-id"] === "string"
|
|
411
|
+
? { formatOptionId: f["format-option-id"], }
|
|
412
|
+
: {}),
|
|
413
|
+
...(typeof f["copy-partitioning-from"] === "string"
|
|
414
|
+
? {
|
|
415
|
+
copyPartitioningFrom: {
|
|
416
|
+
ref: f["copy-partitioning-from"],
|
|
417
|
+
...(f["partitioning-folder"] === true ? { type: "FOLDER", } : {}),
|
|
418
|
+
},
|
|
419
|
+
}
|
|
420
|
+
: {}),
|
|
421
|
+
};
|
|
422
|
+
if (executionMode(f).dryRun) {
|
|
423
|
+
return { dryRun: true, action: "create-managed", resource: "dataset", ...payload, };
|
|
424
|
+
}
|
|
425
|
+
const created = await c.datasets.createManaged({
|
|
426
|
+
name,
|
|
427
|
+
connection,
|
|
428
|
+
...(typeof f["type-option-id"] === "string" ? { typeOptionId: f["type-option-id"], } : {}),
|
|
429
|
+
...(typeof f["format-option-id"] === "string"
|
|
430
|
+
? { formatOptionId: f["format-option-id"], }
|
|
431
|
+
: {}),
|
|
432
|
+
...(typeof f["copy-partitioning-from"] === "string"
|
|
433
|
+
? {
|
|
434
|
+
copyPartitioningFrom: {
|
|
435
|
+
ref: f["copy-partitioning-from"],
|
|
436
|
+
...(f["partitioning-folder"] === true ? { type: "FOLDER", } : {}),
|
|
437
|
+
},
|
|
438
|
+
}
|
|
439
|
+
: {}),
|
|
440
|
+
}, pk);
|
|
441
|
+
return {
|
|
442
|
+
created: created.datasetName,
|
|
443
|
+
resource: "dataset",
|
|
444
|
+
managed: true,
|
|
445
|
+
projectKey: created.projectKey,
|
|
446
|
+
creationSettings: created.creationSettings,
|
|
447
|
+
};
|
|
448
|
+
},
|
|
449
|
+
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]",
|
|
450
|
+
description: "Create a managed dataset via the dedicated endpoint: DSS derives storage/format details; you pick name, connection, and optional type/format/partitioning options.",
|
|
451
|
+
examples: [
|
|
452
|
+
"dss dataset create-managed --name orders_copy --connection filesystem_managed",
|
|
453
|
+
"dss dataset create-managed --name events_parquet --connection s3_conn --format-option-id PARQUET_HIVE --dry-run",
|
|
454
|
+
"dss dataset create-managed --name partitioned --connection s3_conn --copy-partitioning-from raw_events",
|
|
455
|
+
],
|
|
456
|
+
},
|
|
457
|
+
info: {
|
|
458
|
+
handler: (c, a, f) => {
|
|
459
|
+
requireArgs(a, 1, "dss dataset info <name>");
|
|
460
|
+
return c.datasets.info(a[0], f["project-key"]);
|
|
461
|
+
},
|
|
462
|
+
usage: "dss dataset info <name> [--project-key KEY]",
|
|
463
|
+
description: "Get the full info object for a dataset (type, parameters, last build information, schema, etc.).",
|
|
464
|
+
examples: ["dss dataset info orders", "dss dataset info orders --project-key MYPROJ",],
|
|
465
|
+
},
|
|
466
|
+
"column-lineage": {
|
|
467
|
+
handler: (c, a, f) => {
|
|
468
|
+
const usage = "dss dataset column-lineage <name> <column> [--max-dataset-count N] [--project-key KEY]";
|
|
469
|
+
requireArgs(a, 2, usage);
|
|
470
|
+
const maxDatasetCount = num(f["max-dataset-count"], "--max-dataset-count");
|
|
471
|
+
if (maxDatasetCount !== undefined
|
|
472
|
+
&& (!Number.isSafeInteger(maxDatasetCount) || maxDatasetCount <= 0)) {
|
|
473
|
+
throw new UsageError(`--max-dataset-count must be a positive integer (got "${String(f["max-dataset-count"])}"). `
|
|
474
|
+
+ `Usage: ${usage}`, "validation_failed");
|
|
475
|
+
}
|
|
476
|
+
return c.datasets.getColumnLineage(a[0], a[1], {
|
|
477
|
+
maxDatasetCount,
|
|
478
|
+
projectKey: f["project-key"],
|
|
479
|
+
});
|
|
480
|
+
},
|
|
481
|
+
usage: "dss dataset column-lineage <name> <column> [--max-dataset-count N] [--project-key KEY]",
|
|
482
|
+
description: "Get the full column lineage (auto-computed and manual) of a column; includes local and foreign project relations.",
|
|
483
|
+
examples: [
|
|
484
|
+
"dss dataset column-lineage orders customer_id",
|
|
485
|
+
"dss dataset column-lineage orders customer_id --max-dataset-count 2000",
|
|
486
|
+
],
|
|
487
|
+
},
|
|
488
|
+
download: {
|
|
489
|
+
handler: async (c, a, f) => {
|
|
490
|
+
requireArgs(a, 1, "dss dataset download <name>");
|
|
491
|
+
const result = await c.datasets.download(a[0], {
|
|
492
|
+
outputPath: f["output"],
|
|
493
|
+
projectKey: f["project-key"],
|
|
494
|
+
limit: num(f["limit"], "--limit"),
|
|
495
|
+
rawData: f["raw-data"] === true,
|
|
496
|
+
});
|
|
497
|
+
if (result.truncated) {
|
|
498
|
+
enqueueCliWarning({
|
|
499
|
+
code: "dataset_download_truncated",
|
|
500
|
+
message: `Download of '${a[0]}' stopped at the ${result.limit}-row cap; the dataset has more rows. `
|
|
501
|
+
+ "Re-run with --limit N for more, or read inside a recipe (get_dataframe) for the full data.",
|
|
502
|
+
dataset: a[0],
|
|
503
|
+
rows: result.rows,
|
|
504
|
+
limit: result.limit,
|
|
505
|
+
path: result.path,
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
if (!f["output"]) {
|
|
509
|
+
enqueueCliWarning({
|
|
510
|
+
code: "dataset_download_default_location",
|
|
511
|
+
message: `No --output was given, so '${a[0]}' was written to '${result.path}' in the current directory. `
|
|
512
|
+
+ "Pass --output PATH to control the destination and avoid writing into your working tree.",
|
|
513
|
+
dataset: a[0],
|
|
514
|
+
path: result.path,
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
return result;
|
|
518
|
+
},
|
|
519
|
+
usage: "dss dataset download <name> [--output PATH] [--limit N] [--raw-data] [--project-key KEY]",
|
|
520
|
+
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.",
|
|
521
|
+
examples: [
|
|
522
|
+
"dss dataset download orders",
|
|
523
|
+
"dss dataset download orders --output ./data/",
|
|
524
|
+
"dss dataset download orders --raw-data",
|
|
525
|
+
],
|
|
526
|
+
},
|
|
399
527
|
clone: {
|
|
400
528
|
handler: async (c, a, f) => {
|
|
401
529
|
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]";
|
|
@@ -409,6 +537,7 @@ export const datasetCommands = {
|
|
|
409
537
|
allowSamePath: f["allow-same-path"] === true,
|
|
410
538
|
};
|
|
411
539
|
const current = await c.datasets.get(a[0], pk);
|
|
540
|
+
const { buildDatasetCloneSettings, } = await import("../../resources/datasets.js");
|
|
412
541
|
const next = buildDatasetCloneSettings(current, a[1], pk ?? c.resolveProjectKey(pk), opts);
|
|
413
542
|
const zoneId = await resolveFlowZoneIdFromFlags(c, f, pk);
|
|
414
543
|
if (executionMode(f).dryRun) {
|
|
@@ -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
|
+
};
|