Skip to content

Commit

Permalink
feat: added create enclave flow (#962)
Browse files Browse the repository at this point in the history
User can create enclave from the ui. The frontend only supports creating remote
packages at the moment.
  • Loading branch information
Peeeekay authored Jul 24, 2023
1 parent 9e2ad5b commit 4c931b8
Show file tree
Hide file tree
Showing 47 changed files with 695 additions and 63 deletions.
2 changes: 1 addition & 1 deletion cli/cli/commands/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var WebCmd = &lowlevel.LowlevelKurtosisCommand{
}

const (
webUiLink = "http://localhost:9711"
webUiLink = "http://localhost:9711/enclaves"
)

func run(_ context.Context, _ *flags.ParsedFlags, _ *args.ParsedArgs) error {
Expand Down
3 changes: 1 addition & 2 deletions engine/frontend/src/api/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {ApiContainerServicePromiseClient} from 'kurtosis-sdk/build/core/kurtosis
const TransportProtocolEnum = ["tcp", "sctp", "udp"];

export const runStarlarkPackage = async (url, packageId, args) => {
console.log(typeof args)
const containerClient = new ApiContainerServicePromiseClient(url);
const runStarlarkPackageArgs = new RunStarlarkPackageArgs();

Expand All @@ -23,7 +22,6 @@ const getDataFromApiContainer = async (request, process) => {
}

export const getEnclaveInformation = async (url) => {
console.log("url ", url)
if (url === "") {
return {
services: [],
Expand Down Expand Up @@ -83,5 +81,6 @@ export const getEnclaveInformation = async (url) => {
const fileArtifactsPromise = getDataFromApiContainer(makeFileArtifactRequest, processFileArtifactRequest)

const [services, artifacts] = await Promise.all([servicesPromise, fileArtifactsPromise])
console.log("sa", services, artifacts)
return { services, artifacts}
}
9 changes: 7 additions & 2 deletions engine/frontend/src/api/enclave.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,13 @@ export const createEnclave = async () => {
enclaveArgs.setIsPartitioningEnabled(false);
const enclaveGRPC = await engineClient.createEnclave(enclaveArgs, null)
const enclave = enclaveGRPC.toObject().enclaveInfo;
const apiClient = createApiPromiseClient(enclave.apiContainerHostMachineInfo);
return {enclave, apiClient}
return {
uuid: enclave.uuid,
name: enclave.name,
created: enclave.creationTime.seconds,
status: enclave.apiContainerStatus,
apiClient: createApiPromiseClient(enclave.apiContainerHostMachineInfo)
}
}

export const runStarlark = async(apiClient, packageId, args) => {
Expand Down
12 changes: 6 additions & 6 deletions engine/frontend/src/component/CreateEnclave.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ import {CreateEnclaveModal} from "./CreateEnclaveModal";
import {CreateEnclaveView} from "./CreateEnclaveView";
import { Route, Routes, useNavigate } from 'react-router-dom';

const CreateEnclave = () => {
const CreateEnclave = ({addEnclave}) => {
const navigate = useNavigate()
const [name, setName] = useState('');
const [args, setArgs] = useState('{}')
const [enclaveInfo, setEnlaveInfo] = useState(null);
const [enclave, setEnlave] = useState(null);

const handleModalSubmit = (enclaveInfo) => {
setEnlaveInfo(enclaveInfo)
const handleModalSubmit = (enclave) => {
setEnlave(enclave)
navigate("/enclave/progress")
}

return (
<div className='h-full w-full flex'>
<Routes>
<Route path="/create" element={<CreateEnclaveModal name={name} setName={setName} args={args} setArgs={setArgs} handleSubmit={handleModalSubmit}/>}/>
<Route path="/progress" element={<CreateEnclaveView args={args} packageId={name} enclaveInfo={enclaveInfo}/>} />
<Route path="/create" element={<CreateEnclaveModal addEnclave={addEnclave} name={name} setName={setName} args={args} setArgs={setArgs} handleSubmit={handleModalSubmit}/>}/>
<Route path="/progress" element={<CreateEnclaveView args={args} packageId={name} enclave={enclave}/>} />
</Routes>
</div>
)
Expand Down
7 changes: 4 additions & 3 deletions engine/frontend/src/component/CreateEnclaveModal.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React, {useState}from 'react';
import {createEnclave} from "../api/enclave";

export const CreateEnclaveModal = ({handleSubmit, name, setName, args, setArgs}) => {
export const CreateEnclaveModal = ({handleSubmit, name, setName, args, setArgs, addEnclave}) => {
const [jsonError, setJsonError] = useState("")

const handleFormSubmit = (e) => {
e.preventDefault();
const fetch = async () => {
const enclaveInfo = await createEnclave();
handleSubmit(enclaveInfo);
const enclave = await createEnclave();
addEnclave(enclave)
handleSubmit(enclave);
}

try {
Expand Down
30 changes: 12 additions & 18 deletions engine/frontend/src/component/CreateEnclaveView.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import { LogView } from "./LogView";
import {useNavigate} from "react-router-dom";
import {runStarlark} from "../api/enclave";
import {getEnclaveInformation} from "../api/container";
import LoadingOverlay from "./LoadingOverflow";

const SERVICE_IS_ADDED = "added with service";

export const CreateEnclaveView = ({packageId, enclaveInfo, args}) => {
export const CreateEnclaveView = ({packageId, enclave, args}) => {
const navigate = useNavigate();
const [loading, setLoading] = useState(false)
const [logs, setLogs] = useState([])
const [enclave, setEnclave] = useState("")
const [services, setServices] = useState([])

const getServices = async (apiClient) => {
Expand All @@ -29,8 +29,7 @@ export const CreateEnclaveView = ({packageId, enclaveInfo, args}) => {
setLoading(true)
let stream;
const fetch = async () => {
stream = await runStarlark(enclaveInfo.apiClient, packageId, args);
setEnclave(enclave);
stream = await runStarlark(enclave.apiClient, packageId, args);
stream.on("data", data => {
const result = data.toObject();
if (result.instruction && result.instruction.executableInstruction) {
Expand All @@ -44,7 +43,7 @@ export const CreateEnclaveView = ({packageId, enclaveInfo, args}) => {

if (result.instructionResult && result.instructionResult.serializedInstructionResult) {
if (result.instructionResult.serializedInstructionResult.includes(SERVICE_IS_ADDED)) {
getServices(enclaveInfo.apiClient)
getServices(enclave.apiClient)
}
setLogs(logs => [...logs, result.instructionResult.serializedInstructionResult])
}
Expand All @@ -70,15 +69,10 @@ export const CreateEnclaveView = ({packageId, enclaveInfo, args}) => {
}

fetch();
return () => {
if (stream) {
stream.cancel();
};
};
}, [packageId])

const handleServiceClick = (service) => {
navigate(`/enclaves/${enclaveInfo.enclave.name}/services/${service.uuid}`, {state: {services, selected: service}})
navigate(`/enclaves/${enclave.name}/services/${service.uuid}`, {state: {services, selected: service}})
}

const renderServices = (services, handleClick) => {
Expand All @@ -90,26 +84,26 @@ export const CreateEnclaveView = ({packageId, enclaveInfo, args}) => {
)
})
}

return (
<div className="flex h-full w-full bg-white">
<div className="flex h-full bg-white">
<div className="flex h-full">
<LeftPanel
home={false}
heading={"Services"}
isServiceInfo={true}
renderList={ ()=> renderServices(services, handleServiceClick)}
/>
<div className="flex h-full w-[calc(100vw-24rem)] flex-col space-y-5">
<div className="flex h-full w-[calc(100vw-39rem)] flex-col space-y-5">
<div className='flex flex-col h-full space-y-1 bg-white'>
<LogView
heading={`Starlark Logs: ${enclaveInfo.enclave.name}`}
{ (loading && logs.length === 0) ? <LoadingOverlay /> : <LogView
heading={`Starlark Logs: ${enclave.name}`}
logs={logs}
size={"h-full"}
/>
/>}
</div>
</div>
<RightPanel home={false} isServiceInfo={true} enclaveName={enclaveInfo.enclave.name}/>
<RightPanel home={false} isServiceInfo={!loading} enclaveName={enclave.name}/>
</div>
</div>
)
Expand Down
13 changes: 6 additions & 7 deletions engine/frontend/src/component/EnclaveInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ const renderServices = (services, handleClick) => {
if (services.length === 0) {
return (
<NoData
text={`No Data Available:
This occurs because either enclave is stopped or there was error while executing
the package.`}
text={`There are no running services in this enclave`}
size={`text-xl`}
color={`text-red-400`}
/>
Expand All @@ -46,7 +44,7 @@ const renderFileArtifacts = (file_artifacts) => {
if (file_artifacts.length === 0) {
return (
<NoData
text={`No Data Available`}
text={`There are no file artifacts in this enclave`}
size={`text-xl`}
color={`text-red-400`}
/>
Expand All @@ -73,6 +71,7 @@ const EncalveInfo = ({enclaves}) => {
const [encalveInfoLoading, setEnclaveInfoLoading] = useState(false)

useEffect(() => {
console.log("EnclaveInfo: ", enclaves)
setEnclaveInfoLoading(true)
const fetch = async () => {
const selected = enclaves.filter(enclave => enclave.name === name);
Expand All @@ -97,14 +96,14 @@ const EncalveInfo = ({enclaves}) => {


const EnclaveInfoCompoenent = ({services, fileArtifacts, handleServiceClick}) => (
<div className='flex flex-col flew h-[calc(100vh-3rem)] space-y-1'>
<div className='flex flex-col h-[calc(100vh-3rem)] space-y-1 overflow-auto'>
<div className="flex flex-col h-1/2 min-h-1/2 border-8">
<Heading content={"Services"} size={"text-xl"} />
<div className="overflow-auto space-y-2">
{renderServices(services, handleServiceClick)}
</div>
</div>
<div className="flex flex-col grow border-8">
<div className="flex flex-col h-[46%] border-8">
<Heading content={"File Artifacts"} size={"text-xl"} padding={"p-1"}/>
<div className="overflow-auto space-y-2">
{renderFileArtifacts(fileArtifacts)}
Expand All @@ -117,7 +116,7 @@ const EncalveInfo = ({enclaves}) => {
<div className="flex h-full">
<LeftPanel
home={false}
heading={"Environments"}
heading={"Enclaves"}
renderList={ ()=> renderEnclaves(enclaves, handleLeftPanelClick)}
/>

Expand Down
25 changes: 22 additions & 3 deletions engine/frontend/src/component/Enclaves.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,44 @@ const EnclaveMainComponent = ({enclaves, handleClick}) => (
</div>
)

const EnclaveComponent = ({enclaves, handleClick}) => {
const EnclaveComponent = ({enclaves, handleClick, handleCreateEnvClick}) => {
return (
<div className="flex-1 bg-slate-800 overflow-auto">
{
(enclaves.length === 0) ? <NoData /> : <EnclaveMainComponent enclaves={enclaves} handleClick={handleClick} />
(enclaves.length === 0) ?
<div>
<NoData text={"No Enclaves Created"}/>
<div className="flex flex-row w-full">
<div className="w-1/3"> </div>
<div className="mb-4 bg-green-600 h-16 rounded w-1/3" >
<div className='text-center w-full'>
<div className='cursor-default text-3xl text-slate-800 p-2' onClick={handleCreateEnvClick}>
Create Enclave
</div>
</div>
</div>
</div>
</div>
:
<EnclaveMainComponent enclaves={enclaves} handleClick={handleClick} />
}
</div>
)
}

const Enclaves = ({enclaves, isLoading}) => {
const navigate = useNavigate()

const handleCreateEnvClick = () => {
navigate("/enclave/create")
}
const handleClick = (enclaveName) => {
navigate(`/enclaves/${enclaveName}`)
}
return (
<div className="flex h-full flex-grow">
{
(isLoading) ? <LoadingOverlay/> : <EnclaveComponent enclaves={enclaves} handleClick={handleClick}/>
(isLoading) ? <LoadingOverlay/> : <EnclaveComponent enclaves={enclaves} handleClick={handleClick} handleCreateEnvClick={handleCreateEnvClick}/>
}
</div>
)
Expand Down
5 changes: 5 additions & 0 deletions engine/frontend/src/component/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ const Home = () => {
fetch()
}, [])

const addEnclave = (enclave) => {
setEnclaves(enclaves => [...enclaves, enclave])
}

return (
<div className="h-screen flex flex-col bg-slate-800">
<TitleBar />
<div className="flex h-[calc(100vh-4rem)]">
<Routes>
<Route exact path="/" element={<Main totalEnclaves={enclaves.length}/>} />
<Route exact path="/enclave/*" element={<CreateEnclave addEnclave={addEnclave}/>} />
<Route exact path="/enclaves" element={<Enclaves enclaves={enclaves} isLoading={encalveLoading}/>} />
<Route path="/enclaves/:name" element={<EnclaveInfo enclaves={enclaves}/>} />
<Route path="/enclaves/:name/services/:uuid" element={<ServiceInfo/>} />
Expand Down
2 changes: 1 addition & 1 deletion engine/frontend/src/component/LoadingOverflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';

const LoadingOverlay = () => {
return (
<div className="fixed top-0 left-0 right-0 bottom-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
<div className="h-full w-full flex items-center justify-center">
<div className="border-4 border-gray-200 border-t-blue-500 rounded-full w-20 h-20 animate-spin"></div>
</div>
);
Expand Down
14 changes: 7 additions & 7 deletions engine/frontend/src/component/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import NoData from './NoData';

const Main = ({totalEnclaves}) => {
const navigate = useNavigate()
// const handleCreateEnvClick = () => {
// navigate("/enclaves/create")
// }
const handleCreateEnvClick = () => {
navigate("/enclave/create")
}
const handleViewEnvsClick = () => {
navigate("/enclaves")
}
Expand All @@ -18,12 +18,12 @@ const Main = ({totalEnclaves}) => {
<div className='text-center w-full'>
{
totalEnclaves > 0 ? <div className="mb-4 bg-green-600 h-16 rounded" onClick={handleViewEnvsClick}>
<div className='cursor-default text-3xl text-slate-800 p-2'> View Environments </div>
<div className='cursor-default text-3xl text-slate-800 p-2'> View Enclave </div>
</div> : <NoData text={"No Enclaves Created"}/>
}
{/* <div className="mb-4 bg-green-600 h-16 rounded" onClick={handleCreateEnvClick}>
<div className='cursor-default text-3xl text-slate-800 p-2'> Create Environment </div>
</div> */}
<div className="mb-4 bg-green-600 h-16 rounded" onClick={handleCreateEnvClick}>
<div className='cursor-default text-3xl text-slate-800 p-2'> Create Enclave </div>
</div>
</div>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions engine/frontend/src/component/RightPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ const RightPanel = ({isServiceInfo, enclaveName}) => {
}
<button className="w-full bg-green-600 text-slate-800 h-14" onClick={handleGotoMenu}> Home </button>

{/* <svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18" onClick={handleCreateEnclave}>
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18" onClick={handleCreateEnclave}>
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 1v16M1 9h16"/>
</svg> */}
</svg>
</div>
</div>
)
Expand Down
1 change: 0 additions & 1 deletion engine/frontend/src/component/ServiceInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ const ServiceInfo = ({enclaves}) => {
stream = await getServiceLogs(enclaveName, serviceUuid);
stream.on("data", data => {
const log = data.toObject().serviceLogsByServiceUuidMap[0][1].lineList
console.log(log[0])
setLogs(logs => [...logs, log[0]])
})
}
Expand Down
4 changes: 1 addition & 3 deletions engine/frontend/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<StrictMode>
<App />
</StrictMode>
<App />
);

// If you want to start measuring performance in your app, pass a function
Expand Down
12 changes: 6 additions & 6 deletions engine/server/webapp/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"files": {
"main.css": "/static/css/main.1fada45f.css",
"main.js": "/static/js/main.9d338fd2.js",
"main.css": "/static/css/main.a48af3f9.css",
"main.js": "/static/js/main.4ec82f07.js",
"index.html": "/index.html",
"main.1fada45f.css.map": "/static/css/main.1fada45f.css.map",
"main.9d338fd2.js.map": "/static/js/main.9d338fd2.js.map"
"main.a48af3f9.css.map": "/static/css/main.a48af3f9.css.map",
"main.4ec82f07.js.map": "/static/js/main.4ec82f07.js.map"
},
"entrypoints": [
"static/css/main.1fada45f.css",
"static/js/main.9d338fd2.js"
"static/css/main.a48af3f9.css",
"static/js/main.4ec82f07.js"
]
}
2 changes: 1 addition & 1 deletion engine/server/webapp/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><title>Kurtosis Frontend</title><script defer="defer" src="/static/js/main.9d338fd2.js"></script><link href="/static/css/main.1fada45f.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><title>Kurtosis Frontend</title><script defer="defer" src="/static/js/main.4ec82f07.js"></script><link href="/static/css/main.a48af3f9.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
Loading

0 comments on commit 4c931b8

Please sign in to comment.