Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support package nodes in enclave builder ui #2283

Merged
merged 87 commits into from Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
400f08b
setup plan yaml generator
tedim52 Feb 15, 2024
ffdf6cc
checkpoint
tedim52 Feb 15, 2024
d22b7d2
add scaffolding
tedim52 Feb 15, 2024
46fae9d
add get arguments to kurtosis instruction interface
tedim52 Feb 16, 2024
1b437e4
adjust plan yaml generator to get service config
tedim52 Feb 16, 2024
f4b3152
add postgres package test
tedim52 Feb 16, 2024
908ad7d
start render templates impl
tedim52 Feb 17, 2024
a4e7031
finish render templates impl
tedim52 Feb 17, 2024
03a7535
fix render templates impl
tedim52 Feb 17, 2024
aef291e
impl upload files
tedim52 Feb 17, 2024
458fd75
start impl run sh
tedim52 Feb 17, 2024
9f5f442
adjust task yaml def
tedim52 Feb 20, 2024
52f003c
impl run sh checkpoint
tedim52 Feb 20, 2024
eff877f
finish run sh impl
tedim52 Feb 21, 2024
32b53b1
impl run python
tedim52 Feb 21, 2024
ee35dda
commento out tests for now
tedim52 Feb 21, 2024
f8c6939
impl store service
tedim52 Feb 21, 2024
5ecf11a
change order of name and uuid
tedim52 Feb 21, 2024
6146fc1
catch service config err
tedim52 Feb 21, 2024
9daaabc
add plan yaml endpoint to protobuf
tedim52 Feb 22, 2024
29b3f2c
regenerate proto bindings
tedim52 Feb 22, 2024
27acec6
implement plan yaml retrieval
tedim52 Feb 22, 2024
247f6cc
impl plan yaml endpoint in enclave mngr
tedim52 Feb 22, 2024
316f182
fix protobuf
tedim52 Feb 22, 2024
4ab95ea
impl endpoints in gateway
tedim52 Feb 22, 2024
fd8ac0c
Merge branch 'main' into tedi/dryrun
tedim52 Feb 22, 2024
8a67c71
fmt
tedim52 Feb 22, 2024
1972b43
tidy
tedim52 Feb 22, 2024
5397fe6
lint
tedim52 Feb 22, 2024
b7fa08b
Merge branch 'main' into tedi/dryrun
tedim52 Feb 22, 2024
d710813
Merge branch 'main' into tedi/dryrun
Dartoxian Feb 23, 2024
88d4d68
minor fixes
tedim52 Feb 23, 2024
cf83190
use switch statement for image conversion
tedim52 Feb 23, 2024
2aa7e6e
add exec test
tedim52 Feb 23, 2024
ea4dfa0
checkpoint
tedim52 Feb 26, 2024
ae9f7ce
support image build spec
tedim52 Feb 26, 2024
8c7a419
remove locator of module var
tedim52 Feb 26, 2024
579a432
remove service
tedim52 Feb 26, 2024
679ed73
fix plan gen calls
tedim52 Feb 28, 2024
8c2ecc4
Merge branch 'main' into tedi/dryrun
tedim52 Feb 28, 2024
e85af57
lint
tedim52 Feb 28, 2024
9109cac
add exec task type
tedim52 Feb 28, 2024
31a1be6
assign monotonically increasing uuids
tedim52 Feb 29, 2024
56d9331
save and detect future references on service
tedim52 Feb 29, 2024
323ac97
fix exec cmd list
tedim52 Feb 29, 2024
80ace33
finish swapping future ref mostly
tedim52 Feb 29, 2024
603281f
change uuid from int to string type
tedim52 Feb 29, 2024
0544d1b
fix future ref swapping
tedim52 Mar 1, 2024
745d695
Merge branch 'main' into tedi/dryrun
tedim52 Mar 1, 2024
ccc256b
store future references from tasks
tedim52 Mar 1, 2024
a30d67e
comment out tests
tedim52 Mar 1, 2024
21e4ead
fix exec
tedim52 Mar 4, 2024
61db9ed
start refactor
tedim52 Mar 5, 2024
2c70e5f
continue refactor
tedim52 Mar 5, 2024
f842cfa
continue refactor
tedim52 Mar 5, 2024
d661d5f
checkpoint
tedim52 Mar 6, 2024
3998b57
create private plan yaml
tedim52 Mar 7, 2024
5334082
add update plan to interfaces
tedim52 Mar 7, 2024
76da141
refactor add service
tedim52 Mar 8, 2024
6e1388b
add test
tedim52 Mar 8, 2024
306f625
test add service
tedim52 Mar 9, 2024
3c0c578
add run sh
tedim52 Mar 9, 2024
9095f7a
run sh
tedim52 Mar 9, 2024
d190067
refactor run python
tedim52 Mar 10, 2024
ec3cf48
add exec
tedim52 Mar 11, 2024
23d3ffd
refactor remaining instructions
tedim52 Mar 11, 2024
13a5cba
remove old files
tedim52 Mar 11, 2024
4857aed
separate into a file
tedim52 Mar 11, 2024
f69701f
deterministically sort env vars
tedim52 Mar 11, 2024
5f6ca5d
move plan yaml object
tedim52 Mar 11, 2024
6d5d8cc
adjust remove service
tedim52 Mar 11, 2024
2ed0774
lint
tedim52 Mar 11, 2024
b254a49
add test for future reference swapping
tedim52 Mar 11, 2024
cdd9ceb
fix images
tedim52 Mar 11, 2024
f9a4985
remove warnings
tedim52 Mar 11, 2024
aad10f9
lint
tedim52 Mar 11, 2024
4a9343a
Merge branch 'main' into tedi/dryrun
tedim52 Mar 11, 2024
321ad2f
touch up
tedim52 Mar 11, 2024
97ddc8f
Merge branch 'main' into tedi/dryrun
tedim52 Mar 12, 2024
a6a13b3
fix duplicate field
tedim52 Mar 12, 2024
4cad9bb
Merge branch 'main' into tedi/dryrun
tedim52 Mar 12, 2024
5a8a6f2
address comments and fix merge conflicts
tedim52 Mar 13, 2024
3ca4954
Merge branch 'main' into tedi/dryrun
tedim52 Mar 13, 2024
6cfc873
refactor files artifacts expansion to file mount logic
tedim52 Mar 13, 2024
159eee9
Merge branch 'main' into tedi/dryrun
tedim52 Mar 13, 2024
a34742d
feat: support package nodes in the enclave builder ui (#2250)
Dartoxian Mar 13, 2024
c9518c0
remove unused var
tedim52 Mar 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion enclave-manager/web/packages/app/package.json
Expand Up @@ -9,7 +9,7 @@
"enclave-manager-sdk": "file:../../../api/typescript",
"html-react-parser": "^4.2.2",
"js-cookie": "^3.0.5",
"kurtosis-cloud-indexer-sdk": "^0.0.2",
"kurtosis-cloud-indexer-sdk": "^0.0.31",
"kurtosis-ui-components": "0.88.5",
"react-error-boundary": "^4.0.11",
"react-hook-form": "^7.47.0",
Expand Down
Expand Up @@ -5,6 +5,7 @@ import {
RunStarlarkPackageArgs,
RunStarlarkScriptArgs,
ServiceInfo,
StarlarkPackagePlanYamlArgs,
} from "enclave-manager-sdk/build/api_container_service_pb";
import {
CreateEnclaveArgs,
Expand All @@ -24,6 +25,7 @@ import {
InspectFilesArtifactContentsRequest,
RunStarlarkPackageRequest,
RunStarlarkScriptRequest,
StarlarkPackagePlanYamlArgs as StarlarkPackagePlanYamlArgsRequest,
} from "enclave-manager-sdk/build/kurtosis_enclave_manager_api_pb";
import { assertDefined, asyncResult, isDefined, RemoveFunctions } from "kurtosis-ui-components";
import { EnclaveFullInfo } from "../../emui/enclaves/types";
Expand Down Expand Up @@ -184,15 +186,15 @@ export abstract class KurtosisClient {
}

async createEnclave(
enclaveName: string,
apiContainerLogLevel: string,
enclaveName?: string,
apiContainerLogLevel?: string,
productionMode?: boolean,
apiContainerVersionTag?: string,
) {
return asyncResult(() => {
const request = new CreateEnclaveArgs({
enclaveName,
apiContainerLogLevel,
enclaveName: enclaveName || "",
apiContainerLogLevel: apiContainerLogLevel || "info",
mode: productionMode ? EnclaveMode.PRODUCTION : EnclaveMode.TEST,
apiContainerVersionTag: apiContainerVersionTag || "",
});
Expand Down Expand Up @@ -237,4 +239,22 @@ export abstract class KurtosisClient {
});
return this.client.runStarlarkScript(request, this.getHeaderOptions());
}

async getStarlarkPackagePlanYaml(
apicInfo: RemoveFunctions<EnclaveAPIContainerInfo>,
packageId: string,
args: Record<string, any>,
) {
return asyncResult(() => {
const request = new StarlarkPackagePlanYamlArgsRequest({
apicIpAddress: apicInfo.bridgeIpAddress,
apicPort: apicInfo.grpcPortInsideEnclave,
starlarkPackagePlanYamlArgs: new StarlarkPackagePlanYamlArgs({
packageId: packageId,
serializedParams: JSON.stringify(args),
}),
});
return this.client.getStarlarkPackagePlanYaml(request, this.getHeaderOptions());
});
}
}
@@ -0,0 +1,193 @@
import { SmallCloseIcon } from "@chakra-ui/icons";
import {
Button,
Flex,
Icon,
Input,
InputGroup,
InputLeftElement,
InputRightElement,
Spinner,
Text,
} from "@chakra-ui/react";
import { KurtosisPackage } from "kurtosis-cloud-indexer-sdk";
import {
FindCommand,
isDefined,
KurtosisAlert,
KurtosisPackageCardHorizontal,
parsePackageUrl,
useKeyboardAction,
useSavedPackages,
} from "kurtosis-ui-components";
import { debounce } from "lodash";
import { ChangeEvent, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { FiSearch } from "react-icons/fi";
import { useCatalogContext } from "../../../catalog/CatalogContext";

type ExactMatchState =
| { type: "loading"; url: string }
| { type: "loaded"; package: KurtosisPackage }
| { type: "error"; error: string };

type PackageSelectorProps = {
onPackageSelected: (kurtosisPackage: KurtosisPackage) => void;
};
export const PackageSelector = ({ onPackageSelected }: PackageSelectorProps) => {
const searchRef = useRef<HTMLInputElement>(null);
const [searchTerm, setSearchTerm] = useState("");

const [exactMatch, setExactMatch] = useState<ExactMatchState>();
const { catalog, getSinglePackage } = useCatalogContext();

const checkSinglePackageDebounced = useMemo(
() =>
debounce(
async (packageName: string) => {
const singlePackageResult = await getSinglePackage(packageName);
if (singlePackageResult.isErr) {
setExactMatch({ type: "error", error: singlePackageResult.error });
return;
}
if (isDefined(singlePackageResult.value.package)) {
setExactMatch({ type: "loaded", package: singlePackageResult.value.package });
}
},
1000,
{ trailing: true, leading: false },
),
[getSinglePackage],
);

const startCheckSinglePackage = useCallback(
async (packageName: string) => {
let isKurtosisPackageName = false;
try {
parsePackageUrl(packageName);
isKurtosisPackageName = true;
} catch (error: any) {
// This packageName isn't a kurtosis package url
}
if (isKurtosisPackageName) {
setExactMatch({ type: "loading", url: packageName });
checkSinglePackageDebounced(packageName);
} else {
setExactMatch(undefined);
}
},
[checkSinglePackageDebounced],
);

const searchResults = useMemo(
() =>
catalog.map((catalog) =>
catalog.packages.filter(
(kurtosisPackage) => kurtosisPackage.name.toLowerCase().indexOf(searchTerm.toLowerCase()) >= 0,
),
),
[catalog, searchTerm],
);

const { savedPackages } = useSavedPackages();

const handleSearchTermChange = async (e: ChangeEvent<HTMLInputElement>) => {
setSearchTerm(e.target.value);
};

useKeyboardAction(useMemo(() => ({ find: () => searchRef.current?.focus() }), [searchRef]));

useEffect(() => {
startCheckSinglePackage(searchTerm);
}, [startCheckSinglePackage, searchTerm]);

if (searchResults.isErr) {
return <KurtosisAlert message={"Unable to load kurtosis packages"} details={searchResults.error} />;
}

return (
<>
<InputGroup variant={"solid"} width={"100%"} color={"gray.150"}>
<InputLeftElement>
<Icon as={FiSearch} />
</InputLeftElement>
<Input
ref={searchRef}
value={searchTerm}
bgColor={"gray.850"}
onChange={handleSearchTermChange}
placeholder={"Search"}
autoFocus
/>
<InputRightElement w={"unset"} mr={"8px"}>
{searchTerm.length > 0 ? (
<Button variant="ghost" size={"xs"} rightIcon={<SmallCloseIcon />} onClick={() => setSearchTerm("")}>
Clear
</Button>
) : (
<FindCommand whiteSpace={"nowrap"} pr={"10px"} />
)}
</InputRightElement>
</InputGroup>
{isDefined(exactMatch) && (
<Flex flexDirection={"column"} gap={"10px"}>
<Text fontWeight={"semibold"} pt={"16px"} pb={"6px"}>
Exact Match
</Text>
{exactMatch.type === "loading" && (
<Flex flexDirection={"column"} alignItems={"center"}>
<Spinner />
<Text>Looking for a Kurtosis Package at {exactMatch.url}</Text>
</Flex>
)}
{exactMatch.type === "loaded" && (
<KurtosisPackageCardHorizontal
kurtosisPackage={exactMatch.package}
onClick={() => onPackageSelected(exactMatch.package)}
/>
)}
{exactMatch.type === "error" && (
<KurtosisAlert message={"Error looking up package"} details={exactMatch.error} />
)}
</Flex>
)}
{(searchTerm.length > 0 || savedPackages.length === 0) && (
<Flex flexDirection={"column"} gap={"10px"}>
<Text fontWeight={"semibold"} pt={"16px"} pb={"6px"}>
{searchTerm.length === 0 ? "All Packages" : "Search Results"}
</Text>
{searchResults.value.map((kurtosisPackage) => (
<KurtosisPackageCardHorizontal
key={kurtosisPackage.name}
kurtosisPackage={kurtosisPackage}
onClick={() => onPackageSelected(kurtosisPackage)}
/>
))}
</Flex>
)}
{searchTerm.length === 0 && savedPackages.length > 0 && (
<Flex flexDirection={"column"} gap={"10px"}>
<Text fontWeight={"semibold"} pt={"16px"} pb={"6px"}>
Saved
</Text>
{savedPackages.map((kurtosisPackage) => (
<KurtosisPackageCardHorizontal
key={kurtosisPackage.name}
kurtosisPackage={kurtosisPackage}
onClick={() => onPackageSelected(kurtosisPackage)}
/>
))}
<Text fontWeight={"semibold"} pt={"16px"} pb={"6px"}>
All Packages
</Text>
{searchResults.value.map((kurtosisPackage) => (
<KurtosisPackageCardHorizontal
key={kurtosisPackage.name}
kurtosisPackage={kurtosisPackage}
onClick={() => onPackageSelected(kurtosisPackage)}
/>
))}
</Flex>
)}
</>
);
};