@marimo-team/islands 0.23.16-dev18 → 0.23.16-dev19
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/{code-visibility-CIsYEq5p.js → code-visibility-GWCaZTEW.js} +1 -1
- package/dist/main.js +2 -2
- package/dist/{reveal-component-qr0dHIjX.js → reveal-component-CfZAMesi.js} +1 -1
- package/package.json +1 -1
- package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap +50 -0
- package/src/components/editor/connections/storage/__tests__/as-code.test.ts +87 -8
- package/src/components/editor/connections/storage/as-code.ts +40 -21
- package/src/components/editor/connections/storage/schemas.ts +83 -42
|
@@ -36313,7 +36313,7 @@ ${d}`,
|
|
|
36313
36313
|
return Logger.warn("Failed to get version from mount config"), null;
|
|
36314
36314
|
}
|
|
36315
36315
|
}
|
|
36316
|
-
marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.16-
|
|
36316
|
+
marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.16-dev19");
|
|
36317
36317
|
showCodeInRunModeAtom = atom(true);
|
|
36318
36318
|
atom(null);
|
|
36319
36319
|
var import_compiler_runtime = require_compiler_runtime();
|
package/dist/main.js
CHANGED
|
@@ -26,7 +26,7 @@ import { $ as notebookOutline, A as ChevronDownIcon, Bn as Eye, Bt as DATA_TYPE_
|
|
|
26
26
|
import { __tla as __tla_1 } from "./chunk-5FQGJX7Z-B9WoXK1R.js";
|
|
27
27
|
import { o as useSize, s as Root$1, u as createLucideIcon } from "./dist-DIlxLFXG.js";
|
|
28
28
|
import { A as SquareFunction, C as DEFAULT_COLOR_SCHEME, D as SCALE_TYPE_DESCRIPTIONS, E as EMPTY_VALUE$1, O as TIME_UNIT_DESCRIPTIONS, S as DEFAULT_AGGREGATION, T as DEFAULT_TIME_UNIT, _ as AGGREGATION_TYPE_DESCRIPTIONS, a as AGGREGATION_FNS$1, b as COLOR_SCHEMES, c as COLOR_BY_FIELDS, d as NONE_VALUE, f as SELECTABLE_DATA_TYPES, g as TIME_UNITS, h as STRING_AGGREGATION_FNS, i as convertDataTypeToSelectable, j as ChartColumn, k as escapeFieldName, l as COMBINED_TIME_UNITS, m as SORT_TYPES, n as createSpecWithoutData, o as BIN_AGGREGATION, p as SINGLE_TIME_UNITS, r as isFieldSet, s as CHART_TYPES, t as augmentSpecWithData, u as ChartType, v as AGGREGATION_TYPE_ICON, w as DEFAULT_MAX_BINS_FACET, x as COUNT_FIELD, y as CHART_TYPE_ICON } from "./spec-CQKL_D3i.js";
|
|
29
|
-
import { $ as ContextAwarePanelItem, $t as EmotionCacheProvider, A as prettifyRowColumnCount, At as loadTableData, B as useSelectList, Bt as dateToLocalISOTime, C as Filenames, Ct as ColumnChartContext, D as EmptyState, Dt as usePrevious$1, E as ColumnPreviewContainer, Et as useIntersectionObserver, F as ContextMenuContent, Ft as getMimeValues, G as ComboboxItem, Gt as ChartErrorState, H as DatePicker, Ht as TabsContent, I as ContextMenuItem, It as isNullishFilter, J as CommandInput, Jt as LazyVegaEmbed, K as Command, Kt as ChartInfoState, L as ContextMenuSeparator, Lt as Maps, M as getColumnCountForDisplay, Mt as SELECT_COLUMN_ID, N as getUserColumnVisibilityCounts, Nt as TOO_MANY_ROWS, O as ErrorState, Ot as getPageIndexForRow, P as ContextMenu, Pt as toFieldTypes, Q as smartMatch, Qt as HtmlOutput, R as ContextMenuTrigger, Rt as dateToLocalISODate, S as Progress, St as renderCellValue, T as ColumnName, Tt as DelayMount, U as DateRangePicker, Ut as TabsList, V as CompactChipRow, Vt as Tabs, W as Combobox, Wt as TabsTrigger, X as CommandList, Xt as RenderTextWithLinks, Y as CommandItem, Yt as useOverflowDetection, Z as CommandSeparator, Zt as Kbd, _ as InstallPackageButton, _n as ChevronLeft, _t as TableHeader, an as TextWrap, at as SlotNames, b as downloadByURL, bt as generateColumns, cn as EyeOff, d as RadioGroup, dn as Download, dt as Fill, en as safeLocale, et as PANEL_TYPES, f as RadioGroupItem, fn as Code, ft as Provider$1, g as DataTable, gn as ChevronsDownUp, gt as TableHead, h as OutputRenderer, hn as ChevronsLeft, ht as TableCell, in as $fae977aafc393c5c$export$6b862160d295c8e, it as isCellAwareAtom, j as prettifyRowCount, jt as INDEX_COLUMN_NAME, k as LoadingState, kt as loadTableAndRawData, l as Slide, m as OutputArea, mn as ChevronsRight, mt as TableBody, n as marimoVersionAtom, nn as isRecord, nt as contextAwarePanelOwner, on as GripHorizontal, ot as slotsController, p as JsonOutput, pn as ChevronsUpDown, pt as Table, q as CommandEmpty, qt as ChartLoadingState, r as showCodeInRunModeAtom, rn as $fae977aafc393c5c$export$588937bcd60ade55, rt as contextAwarePanelType, s as SLIDE_TYPE_OPTIONS_BY_VALUE, sn as Funnel, st as Toggle, t as useNotebookCodeAvailable, tn as hasFunctionProperty, tt as contextAwarePanelOpen, u as Switch, un as Ellipsis, v as ADD_PRINTING_CLASS, vn as ArrowDownWideNarrow, vt as TableRow, w as downloadSizeLimitAtom, wt as ColumnChartSpecModel, x as downloadHTMLAsImage, xt as inferFieldTypes, y as downloadBlob, yt as NAMELESS_COLUMN_PREFIX, z as useInternalStateWithSync, zt as dateToLocalISODateTime, __tla as __tla_2 } from "./code-visibility-
|
|
29
|
+
import { $ as ContextAwarePanelItem, $t as EmotionCacheProvider, A as prettifyRowColumnCount, At as loadTableData, B as useSelectList, Bt as dateToLocalISOTime, C as Filenames, Ct as ColumnChartContext, D as EmptyState, Dt as usePrevious$1, E as ColumnPreviewContainer, Et as useIntersectionObserver, F as ContextMenuContent, Ft as getMimeValues, G as ComboboxItem, Gt as ChartErrorState, H as DatePicker, Ht as TabsContent, I as ContextMenuItem, It as isNullishFilter, J as CommandInput, Jt as LazyVegaEmbed, K as Command, Kt as ChartInfoState, L as ContextMenuSeparator, Lt as Maps, M as getColumnCountForDisplay, Mt as SELECT_COLUMN_ID, N as getUserColumnVisibilityCounts, Nt as TOO_MANY_ROWS, O as ErrorState, Ot as getPageIndexForRow, P as ContextMenu, Pt as toFieldTypes, Q as smartMatch, Qt as HtmlOutput, R as ContextMenuTrigger, Rt as dateToLocalISODate, S as Progress, St as renderCellValue, T as ColumnName, Tt as DelayMount, U as DateRangePicker, Ut as TabsList, V as CompactChipRow, Vt as Tabs, W as Combobox, Wt as TabsTrigger, X as CommandList, Xt as RenderTextWithLinks, Y as CommandItem, Yt as useOverflowDetection, Z as CommandSeparator, Zt as Kbd, _ as InstallPackageButton, _n as ChevronLeft, _t as TableHeader, an as TextWrap, at as SlotNames, b as downloadByURL, bt as generateColumns, cn as EyeOff, d as RadioGroup, dn as Download, dt as Fill, en as safeLocale, et as PANEL_TYPES, f as RadioGroupItem, fn as Code, ft as Provider$1, g as DataTable, gn as ChevronsDownUp, gt as TableHead, h as OutputRenderer, hn as ChevronsLeft, ht as TableCell, in as $fae977aafc393c5c$export$6b862160d295c8e, it as isCellAwareAtom, j as prettifyRowCount, jt as INDEX_COLUMN_NAME, k as LoadingState, kt as loadTableAndRawData, l as Slide, m as OutputArea, mn as ChevronsRight, mt as TableBody, n as marimoVersionAtom, nn as isRecord, nt as contextAwarePanelOwner, on as GripHorizontal, ot as slotsController, p as JsonOutput, pn as ChevronsUpDown, pt as Table, q as CommandEmpty, qt as ChartLoadingState, r as showCodeInRunModeAtom, rn as $fae977aafc393c5c$export$588937bcd60ade55, rt as contextAwarePanelType, s as SLIDE_TYPE_OPTIONS_BY_VALUE, sn as Funnel, st as Toggle, t as useNotebookCodeAvailable, tn as hasFunctionProperty, tt as contextAwarePanelOpen, u as Switch, un as Ellipsis, v as ADD_PRINTING_CLASS, vn as ArrowDownWideNarrow, vt as TableRow, w as downloadSizeLimitAtom, wt as ColumnChartSpecModel, x as downloadHTMLAsImage, xt as inferFieldTypes, y as downloadBlob, yt as NAMELESS_COLUMN_PREFIX, z as useInternalStateWithSync, zt as dateToLocalISODateTime, __tla as __tla_2 } from "./code-visibility-GWCaZTEW.js";
|
|
30
30
|
import { c as Calendar, i as createReducerAndAtoms, n as useOnUnmount, o as ToggleLeft, t as useOnMount } from "./useLifecycle-CMJGqBaY.js";
|
|
31
31
|
import { t as Check } from "./check-DP7U0H0G.js";
|
|
32
32
|
import { A as Icon, C as logNever, D as $18f2051aff69b9bf$export$a54013f0d02a8f82, E as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7, F as createCollection, I as X, M as clamp$2, N as usePrevious$2, P as useDirection, R as ChevronDown, S as assertNever, a as SelectGroup, c as SelectSeparator, d as NativeSelect, i as SelectContent, j as Trigger$1, l as SelectTrigger, n as capitalize, o as SelectItem, r as Select, s as SelectLabel, t as Strings, u as SelectValue, w as $a916eb452884faea$export$b7a616150fdb9f44 } from "./strings-DIy9NAmg.js";
|
|
@@ -38147,7 +38147,7 @@ ${c}
|
|
|
38147
38147
|
function _temp2$2(e) {
|
|
38148
38148
|
e.target === e.currentTarget && e.key === "Enter" && (e.preventDefault(), e.stopPropagation(), e.currentTarget.click());
|
|
38149
38149
|
}
|
|
38150
|
-
var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-
|
|
38150
|
+
var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-CfZAMesi.js"));
|
|
38151
38151
|
const SlidesLayoutRenderer = ({ layout: e, setLayout: r, cells: c, mode: l }) => {
|
|
38152
38152
|
var _a5;
|
|
38153
38153
|
let u = useAtomValue(kioskModeAtom), d = l === "read" || u, f = useAtomValue(numColumnsAtom) > 1, [p, m] = (0, import_react.useState)(null), { slideCells: h, skippedIds: g, noOutputIds: _, slideTypes: v, startCellIndex: y } = (0, import_react.useMemo)(() => computeSlideCellsInfo(c, e), [
|
|
@@ -9,7 +9,7 @@ import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
|
9
9
|
import { ut as outputIsStale } from "./html-to-image-27MFfyOf.js";
|
|
10
10
|
import "./chunk-5FQGJX7Z-B9WoXK1R.js";
|
|
11
11
|
import { u as createLucideIcon } from "./dist-DIlxLFXG.js";
|
|
12
|
-
import { a as DEFAULT_DECK_VERTICAL_ALIGN, c as SlideSidebar, cn as EyeOff, ct as Panel, fn as Code, i as DEFAULT_DECK_TRANSITION, l as Slide, ln as Expand, lt as PanelGroup, o as DEFAULT_SLIDE_TYPE, t as useNotebookCodeAvailable, ut as PanelResizeHandle } from "./code-visibility-
|
|
12
|
+
import { a as DEFAULT_DECK_VERTICAL_ALIGN, c as SlideSidebar, cn as EyeOff, ct as Panel, fn as Code, i as DEFAULT_DECK_TRANSITION, l as Slide, ln as Expand, lt as PanelGroup, o as DEFAULT_SLIDE_TYPE, t as useNotebookCodeAvailable, ut as PanelResizeHandle } from "./code-visibility-GWCaZTEW.js";
|
|
13
13
|
import { R as ChevronDown } from "./strings-DIy9NAmg.js";
|
|
14
14
|
import { X as useDebouncedCallback } from "./input-C5K4VBvB.js";
|
|
15
15
|
import { v as kioskModeAtom } from "./toDate-CqhBWjvO.js";
|
package/package.json
CHANGED
package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap
CHANGED
|
@@ -51,6 +51,21 @@ store = S3Store("operator-bucket",
|
|
|
51
51
|
)"
|
|
52
52
|
`;
|
|
53
53
|
|
|
54
|
+
exports[`generateStorageCode > CoreWeave > with container credentials 1`] = `
|
|
55
|
+
"from obstore.store import S3Store
|
|
56
|
+
import os
|
|
57
|
+
|
|
58
|
+
_container_credentials_full_uri = os.environ.get("AWS_CONTAINER_CREDENTIALS_FULL_URI")
|
|
59
|
+
_container_authorization_token_file = os.environ.get("AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE")
|
|
60
|
+
store = S3Store("operator-bucket",
|
|
61
|
+
region="US-EAST-04A",
|
|
62
|
+
container_credentials_full_uri=_container_credentials_full_uri,
|
|
63
|
+
container_authorization_token_file=_container_authorization_token_file,
|
|
64
|
+
endpoint="https://operator-bucket.cwobject.com",
|
|
65
|
+
virtual_hosted_style_request=True,
|
|
66
|
+
)"
|
|
67
|
+
`;
|
|
68
|
+
|
|
54
69
|
exports[`generateStorageCode > CoreWeave > with secrets 1`] = `
|
|
55
70
|
"from obstore.store import S3Store
|
|
56
71
|
import os
|
|
@@ -119,6 +134,29 @@ exports[`generateStorageCode > S3 > minimal connection (bucket only) 1`] = `
|
|
|
119
134
|
store = S3Store("my-bucket",)"
|
|
120
135
|
`;
|
|
121
136
|
|
|
137
|
+
exports[`generateStorageCode > S3 > with container credentials 1`] = `
|
|
138
|
+
"from obstore.store import S3Store
|
|
139
|
+
|
|
140
|
+
store = S3Store("my-bucket",
|
|
141
|
+
region="us-east-1",
|
|
142
|
+
container_credentials_full_uri="http://169.254.170.23/v1/credentials",
|
|
143
|
+
container_authorization_token_file="/var/run/secrets/token",
|
|
144
|
+
)"
|
|
145
|
+
`;
|
|
146
|
+
|
|
147
|
+
exports[`generateStorageCode > S3 > with container credentials from secrets 1`] = `
|
|
148
|
+
"from obstore.store import S3Store
|
|
149
|
+
import os
|
|
150
|
+
|
|
151
|
+
_container_credentials_full_uri = os.environ.get("AWS_CONTAINER_CREDENTIALS_FULL_URI")
|
|
152
|
+
_container_authorization_token_file = os.environ.get("AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE")
|
|
153
|
+
store = S3Store("my-bucket",
|
|
154
|
+
region="us-east-1",
|
|
155
|
+
container_credentials_full_uri=_container_credentials_full_uri,
|
|
156
|
+
container_authorization_token_file=_container_authorization_token_file,
|
|
157
|
+
)"
|
|
158
|
+
`;
|
|
159
|
+
|
|
122
160
|
exports[`generateStorageCode > S3 > with custom endpoint 1`] = `
|
|
123
161
|
"from obstore.store import S3Store
|
|
124
162
|
|
|
@@ -130,6 +168,18 @@ store = S3Store("my-bucket",
|
|
|
130
168
|
)"
|
|
131
169
|
`;
|
|
132
170
|
|
|
171
|
+
exports[`generateStorageCode > S3 > with plain-http endpoint 1`] = `
|
|
172
|
+
"from obstore.store import S3Store
|
|
173
|
+
|
|
174
|
+
store = S3Store("my-bucket",
|
|
175
|
+
region="us-east-1",
|
|
176
|
+
access_key_id="AKIAIOSFODNN7EXAMPLE",
|
|
177
|
+
secret_access_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
178
|
+
endpoint_url="http://cwlota.com",
|
|
179
|
+
allow_http=True,
|
|
180
|
+
)"
|
|
181
|
+
`;
|
|
182
|
+
|
|
133
183
|
exports[`generateStorageCode > S3 > with secrets 1`] = `
|
|
134
184
|
"from obstore.store import S3Store
|
|
135
185
|
import os
|
|
@@ -9,9 +9,13 @@ describe("generateStorageCode", () => {
|
|
|
9
9
|
type: "s3",
|
|
10
10
|
bucket: "my-bucket",
|
|
11
11
|
region: "us-east-1",
|
|
12
|
-
access_key_id: "AKIAIOSFODNN7EXAMPLE",
|
|
13
|
-
secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
14
12
|
endpoint_url: undefined,
|
|
13
|
+
allow_http: false,
|
|
14
|
+
auth: {
|
|
15
|
+
type: "Access keys",
|
|
16
|
+
access_key_id: "AKIAIOSFODNN7EXAMPLE",
|
|
17
|
+
secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
18
|
+
},
|
|
15
19
|
};
|
|
16
20
|
|
|
17
21
|
const baseGCS: StorageConnection = {
|
|
@@ -31,8 +35,11 @@ describe("generateStorageCode", () => {
|
|
|
31
35
|
type: "coreweave",
|
|
32
36
|
bucket: "operator-bucket",
|
|
33
37
|
region: "US-EAST-04A",
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
auth: {
|
|
39
|
+
type: "Access keys",
|
|
40
|
+
access_key_id: "AKIAIOSFODNN7EXAMPLE",
|
|
41
|
+
secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
42
|
+
},
|
|
36
43
|
};
|
|
37
44
|
|
|
38
45
|
const baseGDrive: StorageConnection = {
|
|
@@ -52,6 +59,8 @@ describe("generateStorageCode", () => {
|
|
|
52
59
|
const conn: StorageConnection = {
|
|
53
60
|
type: "s3",
|
|
54
61
|
bucket: "my-bucket",
|
|
62
|
+
allow_http: false,
|
|
63
|
+
auth: { type: "Access keys" },
|
|
55
64
|
};
|
|
56
65
|
expect(
|
|
57
66
|
generateStorageCode(conn, { library: "obstore" }),
|
|
@@ -68,13 +77,61 @@ describe("generateStorageCode", () => {
|
|
|
68
77
|
).toMatchSnapshot();
|
|
69
78
|
});
|
|
70
79
|
|
|
80
|
+
it("with plain-http endpoint", () => {
|
|
81
|
+
const conn: StorageConnection = {
|
|
82
|
+
...baseS3,
|
|
83
|
+
endpoint_url: "http://cwlota.com",
|
|
84
|
+
allow_http: true,
|
|
85
|
+
};
|
|
86
|
+
expect(
|
|
87
|
+
generateStorageCode(conn, { library: "obstore" }),
|
|
88
|
+
).toMatchSnapshot();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("with container credentials", () => {
|
|
92
|
+
const conn: StorageConnection = {
|
|
93
|
+
...baseS3,
|
|
94
|
+
auth: {
|
|
95
|
+
type: "Container credentials",
|
|
96
|
+
container_credentials_full_uri:
|
|
97
|
+
"http://169.254.170.23/v1/credentials",
|
|
98
|
+
container_authorization_token_file: "/var/run/secrets/token",
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
expect(
|
|
102
|
+
generateStorageCode(conn, { library: "obstore" }),
|
|
103
|
+
).toMatchSnapshot();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("with container credentials from secrets", () => {
|
|
107
|
+
const conn: StorageConnection = {
|
|
108
|
+
...baseS3,
|
|
109
|
+
auth: {
|
|
110
|
+
type: "Container credentials",
|
|
111
|
+
container_credentials_full_uri: prefixSecret(
|
|
112
|
+
"AWS_CONTAINER_CREDENTIALS_FULL_URI",
|
|
113
|
+
),
|
|
114
|
+
container_authorization_token_file: prefixSecret(
|
|
115
|
+
"AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE",
|
|
116
|
+
),
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
expect(
|
|
120
|
+
generateStorageCode(conn, { library: "obstore" }),
|
|
121
|
+
).toMatchSnapshot();
|
|
122
|
+
});
|
|
123
|
+
|
|
71
124
|
it("with secrets", () => {
|
|
72
125
|
const conn: StorageConnection = {
|
|
73
126
|
type: "s3",
|
|
74
127
|
bucket: "my-bucket",
|
|
75
128
|
region: "us-east-1",
|
|
76
|
-
|
|
77
|
-
|
|
129
|
+
allow_http: false,
|
|
130
|
+
auth: {
|
|
131
|
+
type: "Access keys",
|
|
132
|
+
access_key_id: prefixSecret("AWS_ACCESS_KEY_ID"),
|
|
133
|
+
secret_access_key: prefixSecret("AWS_SECRET_ACCESS_KEY"),
|
|
134
|
+
},
|
|
78
135
|
};
|
|
79
136
|
expect(
|
|
80
137
|
generateStorageCode(conn, { library: "obstore" }),
|
|
@@ -143,6 +200,25 @@ describe("generateStorageCode", () => {
|
|
|
143
200
|
type: "coreweave",
|
|
144
201
|
bucket: "operator-bucket",
|
|
145
202
|
region: "US-EAST-04A",
|
|
203
|
+
auth: { type: "Access keys" },
|
|
204
|
+
};
|
|
205
|
+
expect(
|
|
206
|
+
generateStorageCode(conn, { library: "obstore" }),
|
|
207
|
+
).toMatchSnapshot();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it("with container credentials", () => {
|
|
211
|
+
const conn: StorageConnection = {
|
|
212
|
+
...baseCoreWeave,
|
|
213
|
+
auth: {
|
|
214
|
+
type: "Container credentials",
|
|
215
|
+
container_credentials_full_uri: prefixSecret(
|
|
216
|
+
"AWS_CONTAINER_CREDENTIALS_FULL_URI",
|
|
217
|
+
),
|
|
218
|
+
container_authorization_token_file: prefixSecret(
|
|
219
|
+
"AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE",
|
|
220
|
+
),
|
|
221
|
+
},
|
|
146
222
|
};
|
|
147
223
|
expect(
|
|
148
224
|
generateStorageCode(conn, { library: "obstore" }),
|
|
@@ -154,8 +230,11 @@ describe("generateStorageCode", () => {
|
|
|
154
230
|
type: "coreweave",
|
|
155
231
|
bucket: "operator-bucket",
|
|
156
232
|
region: "US-EAST-04A",
|
|
157
|
-
|
|
158
|
-
|
|
233
|
+
auth: {
|
|
234
|
+
type: "Access keys",
|
|
235
|
+
access_key_id: prefixSecret("COREWEAVE_OBJECT_STORAGE_KEY"),
|
|
236
|
+
secret_access_key: prefixSecret("COREWEAVE_OBJECT_STORAGE_SECRET"),
|
|
237
|
+
},
|
|
159
238
|
};
|
|
160
239
|
expect(
|
|
161
240
|
generateStorageCode(conn, { library: "obstore" }),
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
import dedent from "string-dedent";
|
|
4
4
|
import { assertNever } from "@/utils/assertNever";
|
|
5
5
|
import { isSecret, unprefixSecret } from "../secrets";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
type S3Auth,
|
|
8
|
+
type StorageConnection,
|
|
9
|
+
StorageConnectionSchema,
|
|
10
|
+
} from "./schemas";
|
|
7
11
|
|
|
8
12
|
export type StorageLibrary = "obstore" | "fsspec";
|
|
9
13
|
|
|
@@ -50,6 +54,36 @@ class SecretContainer {
|
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Credential kwargs shared by every S3-compatible store.
|
|
59
|
+
*/
|
|
60
|
+
function s3AuthParams(
|
|
61
|
+
auth: S3Auth | undefined,
|
|
62
|
+
secrets: SecretContainer,
|
|
63
|
+
): string[] {
|
|
64
|
+
// obstore polls the credential endpoint with the token read from the file,
|
|
65
|
+
// refreshing credentials for the lifetime of the store.
|
|
66
|
+
if (auth?.type === "Container credentials") {
|
|
67
|
+
return [
|
|
68
|
+
` container_credentials_full_uri=${secrets.print("container_credentials_full_uri", auth.container_credentials_full_uri)},`,
|
|
69
|
+
` container_authorization_token_file=${secrets.print("container_authorization_token_file", auth.container_authorization_token_file)},`,
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const params: string[] = [];
|
|
74
|
+
if (auth?.access_key_id) {
|
|
75
|
+
params.push(
|
|
76
|
+
` access_key_id=${secrets.print("access_key_id", auth.access_key_id)},`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
if (auth?.secret_access_key) {
|
|
80
|
+
params.push(
|
|
81
|
+
` secret_access_key=${secrets.print("secret_access_key", auth.secret_access_key)},`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
return params;
|
|
85
|
+
}
|
|
86
|
+
|
|
53
87
|
function generateS3Code(
|
|
54
88
|
connection: Extract<StorageConnection, { type: "s3" }>,
|
|
55
89
|
secrets: SecretContainer,
|
|
@@ -61,21 +95,15 @@ function generateS3Code(
|
|
|
61
95
|
if (connection.region) {
|
|
62
96
|
params.push(` region=${secrets.print("region", connection.region)},`);
|
|
63
97
|
}
|
|
64
|
-
|
|
65
|
-
params.push(
|
|
66
|
-
` access_key_id=${secrets.print("access_key_id", connection.access_key_id)},`,
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
if (connection.secret_access_key) {
|
|
70
|
-
params.push(
|
|
71
|
-
` secret_access_key=${secrets.print("secret_access_key", connection.secret_access_key)},`,
|
|
72
|
-
);
|
|
73
|
-
}
|
|
98
|
+
params.push(...s3AuthParams(connection.auth, secrets));
|
|
74
99
|
if (connection.endpoint_url) {
|
|
75
100
|
params.push(
|
|
76
101
|
` endpoint_url=${secrets.print("endpoint_url", connection.endpoint_url)},`,
|
|
77
102
|
);
|
|
78
103
|
}
|
|
104
|
+
if (connection.allow_http) {
|
|
105
|
+
params.push(" allow_http=True,");
|
|
106
|
+
}
|
|
79
107
|
|
|
80
108
|
const paramsStr = params.length > 0 ? `\n${params.join("\n")}\n` : "";
|
|
81
109
|
|
|
@@ -140,16 +168,7 @@ function generateCoreWeaveCode(
|
|
|
140
168
|
` region=${secrets.print("region", connection.region)},`,
|
|
141
169
|
];
|
|
142
170
|
|
|
143
|
-
|
|
144
|
-
params.push(
|
|
145
|
-
` access_key_id=${secrets.print("access_key_id", connection.access_key_id)},`,
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
if (connection.secret_access_key) {
|
|
149
|
-
params.push(
|
|
150
|
-
` secret_access_key=${secrets.print("secret_access_key", connection.secret_access_key)},`,
|
|
151
|
-
);
|
|
152
|
-
}
|
|
171
|
+
params.push(...s3AuthParams(connection.auth, secrets));
|
|
153
172
|
|
|
154
173
|
params.push(
|
|
155
174
|
` endpoint="https://${connection.bucket}.cwobject.com",`,
|
|
@@ -2,6 +2,83 @@
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { FieldOptions } from "@/components/forms/options";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Credentials shared by every S3-compatible store (Amazon S3, CoreWeave, ...).
|
|
7
|
+
*
|
|
8
|
+
* Rendered as tabs: either long-lived access keys, or a credential-vending
|
|
9
|
+
* endpoint (ECS/EKS task roles, CoreWeave sandboxes, ...) that obstore polls
|
|
10
|
+
* with a bearer token read from disk.
|
|
11
|
+
*/
|
|
12
|
+
const s3AuthField = () =>
|
|
13
|
+
z
|
|
14
|
+
.discriminatedUnion("type", [
|
|
15
|
+
z.object({
|
|
16
|
+
type: z.literal("Access keys"),
|
|
17
|
+
access_key_id: z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe(
|
|
21
|
+
FieldOptions.of({
|
|
22
|
+
label: "Access Key ID",
|
|
23
|
+
description: "Leave empty to use the default credential chain",
|
|
24
|
+
inputType: "password",
|
|
25
|
+
optionRegex:
|
|
26
|
+
"(access.?key.?id|object.?storage.?key|aws.?access.?key)",
|
|
27
|
+
}),
|
|
28
|
+
),
|
|
29
|
+
secret_access_key: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe(
|
|
33
|
+
FieldOptions.of({
|
|
34
|
+
label: "Secret Access Key",
|
|
35
|
+
inputType: "password",
|
|
36
|
+
optionRegex:
|
|
37
|
+
"(secret.?access.?key|object.?storage.?secret|aws.?secret)",
|
|
38
|
+
}),
|
|
39
|
+
),
|
|
40
|
+
}),
|
|
41
|
+
z.object({
|
|
42
|
+
type: z.literal("Container credentials"),
|
|
43
|
+
container_credentials_full_uri: z
|
|
44
|
+
.string()
|
|
45
|
+
.nonempty()
|
|
46
|
+
.describe(
|
|
47
|
+
FieldOptions.of({
|
|
48
|
+
label: "Credentials URI",
|
|
49
|
+
description: "Endpoint that vends credentials to the container",
|
|
50
|
+
placeholder: "http://169.254.170.23/v1/credentials",
|
|
51
|
+
optionRegex: "container.?credentials",
|
|
52
|
+
}),
|
|
53
|
+
),
|
|
54
|
+
container_authorization_token_file: z
|
|
55
|
+
.string()
|
|
56
|
+
.nonempty()
|
|
57
|
+
.describe(
|
|
58
|
+
FieldOptions.of({
|
|
59
|
+
label: "Authorization Token File",
|
|
60
|
+
description: "File holding the token sent to the credentials URI",
|
|
61
|
+
placeholder: "/var/run/secrets/token",
|
|
62
|
+
optionRegex:
|
|
63
|
+
"(container.?authorization.?token.?file|container.?auth.?token)",
|
|
64
|
+
}),
|
|
65
|
+
),
|
|
66
|
+
}),
|
|
67
|
+
])
|
|
68
|
+
.default({ type: "Access keys" })
|
|
69
|
+
.describe(FieldOptions.of({ label: "Credentials", special: "tabs" }));
|
|
70
|
+
|
|
71
|
+
const allowHttpField = () =>
|
|
72
|
+
z
|
|
73
|
+
.boolean()
|
|
74
|
+
.default(false)
|
|
75
|
+
.describe(
|
|
76
|
+
FieldOptions.of({
|
|
77
|
+
label: "Allow HTTP",
|
|
78
|
+
description: "Required for plain-http (non-TLS) endpoints",
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
|
|
5
82
|
export const S3StorageSchema = z
|
|
6
83
|
.object({
|
|
7
84
|
type: z.literal("s3"),
|
|
@@ -25,36 +102,20 @@ export const S3StorageSchema = z
|
|
|
25
102
|
optionRegex: "(region|aws.?region)",
|
|
26
103
|
}),
|
|
27
104
|
),
|
|
28
|
-
access_key_id: z
|
|
29
|
-
.string()
|
|
30
|
-
.optional()
|
|
31
|
-
.describe(
|
|
32
|
-
FieldOptions.of({
|
|
33
|
-
label: "Access Key ID",
|
|
34
|
-
inputType: "password",
|
|
35
|
-
optionRegex: "(access.?key.?id|aws.?access.?key)",
|
|
36
|
-
}),
|
|
37
|
-
),
|
|
38
|
-
secret_access_key: z
|
|
39
|
-
.string()
|
|
40
|
-
.optional()
|
|
41
|
-
.describe(
|
|
42
|
-
FieldOptions.of({
|
|
43
|
-
label: "Secret Access Key",
|
|
44
|
-
inputType: "password",
|
|
45
|
-
optionRegex: "(secret.?access.?key|aws.?secret)",
|
|
46
|
-
}),
|
|
47
|
-
),
|
|
48
105
|
endpoint_url: z
|
|
49
106
|
.string()
|
|
50
107
|
.optional()
|
|
51
108
|
.describe(
|
|
52
109
|
FieldOptions.of({
|
|
53
110
|
label: "Endpoint URL",
|
|
111
|
+
description:
|
|
112
|
+
"Ignored if the AWS_ENDPOINT_URL_S3 environment variable is set",
|
|
54
113
|
placeholder: "https://s3.amazonaws.com",
|
|
55
114
|
optionRegex: "(endpoint|s3.?url|s3.?endpoint)",
|
|
56
115
|
}),
|
|
57
116
|
),
|
|
117
|
+
allow_http: allowHttpField(),
|
|
118
|
+
auth: s3AuthField(),
|
|
58
119
|
})
|
|
59
120
|
.describe(FieldOptions.of({ direction: "two-columns" }));
|
|
60
121
|
|
|
@@ -139,28 +200,7 @@ export const CoreWeaveStorageSchema = z
|
|
|
139
200
|
placeholder: "US-EAST-04A",
|
|
140
201
|
}),
|
|
141
202
|
),
|
|
142
|
-
|
|
143
|
-
.string()
|
|
144
|
-
.optional()
|
|
145
|
-
.describe(
|
|
146
|
-
FieldOptions.of({
|
|
147
|
-
label: "Access Key ID",
|
|
148
|
-
inputType: "password",
|
|
149
|
-
optionRegex:
|
|
150
|
-
"(access.?key.?id|object.?storage.?key|aws.?access.?key)",
|
|
151
|
-
}),
|
|
152
|
-
),
|
|
153
|
-
secret_access_key: z
|
|
154
|
-
.string()
|
|
155
|
-
.optional()
|
|
156
|
-
.describe(
|
|
157
|
-
FieldOptions.of({
|
|
158
|
-
label: "Secret Access Key",
|
|
159
|
-
inputType: "password",
|
|
160
|
-
optionRegex:
|
|
161
|
-
"(secret.?access.?key|object.?storage.?secret|aws.?secret)",
|
|
162
|
-
}),
|
|
163
|
-
),
|
|
203
|
+
auth: s3AuthField(),
|
|
164
204
|
})
|
|
165
205
|
.describe(FieldOptions.of({ direction: "two-columns" }));
|
|
166
206
|
|
|
@@ -189,3 +229,4 @@ export const StorageConnectionSchema = z.discriminatedUnion("type", [
|
|
|
189
229
|
]);
|
|
190
230
|
|
|
191
231
|
export type StorageConnection = z.infer<typeof StorageConnectionSchema>;
|
|
232
|
+
export type S3Auth = Extract<StorageConnection, { type: "s3" }>["auth"];
|