Skip to content

Commit

Permalink
feat: improve access to the EMUI 'ports' fields (#2201)
Browse files Browse the repository at this point in the history
## Description:
This PR improves the accessibility of service ports per #2188.
Specifically it shows (clickable) named ports on the enclave list and
enclave overview screens. Additionally the services in an enclave are
shown once the enclave logs have successfully finished.

### Screenshots

![Screenshot from 2024-02-21
14-40-18](https://github.com/kurtosis-tech/kurtosis/assets/4419574/d94e8872-30ee-4a25-ad7a-9c10c1a6c711)
![Screenshot from 2024-02-21
14-59-02](https://github.com/kurtosis-tech/kurtosis/assets/4419574/32072fec-9cc7-41ea-8c71-4db0dc733c43)
![Screenshot from 2024-02-21
15-13-28](https://github.com/kurtosis-tech/kurtosis/assets/4419574/3994637e-9b41-4e44-a412-8a474b30fdcb)

## Is this change user facing?
YES

## References (if applicable):
* Fixes #2188

Co-authored-by: Anders Schwartz <[email protected]>
  • Loading branch information
Dartoxian and adschwartz authored Feb 22, 2024
1 parent 0c71e5c commit 486ea2e
Show file tree
Hide file tree
Showing 17 changed files with 162 additions and 173 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Flex, Heading, Spinner } from "@chakra-ui/react";
import Cookies from "js-cookie";
import { assertDefined, isDefined, KurtosisAlert, stringifyError } from "kurtosis-ui-components";
import { createContext, PropsWithChildren, useContext, useEffect, useMemo, useState } from "react";
import { jwtToken } from "../../cookies";
import { KURTOSIS_CLOUD_EM_PAGE, KURTOSIS_CLOUD_EM_URL } from "../constants";
import { AuthenticatedKurtosisClient } from "./AuthenticatedKurtosisClient";
import { KurtosisClient } from "./KurtosisClient";
Expand Down Expand Up @@ -69,8 +69,6 @@ export const KurtosisClientProvider = ({ children }: PropsWithChildren) => {
throw Error(`Port ${port} is not a number.`);
}

const jwtToken = Cookies.get("_kurtosis_jwt_token");

if (isDefined(jwtToken)) {
newClient = new AuthenticatedKurtosisClient(
`${gatewayHost}`,
Expand Down
5 changes: 5 additions & 0 deletions enclave-manager/web/packages/app/src/cookies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Cookies from "js-cookie";

export const instanceUUID = Cookies.get("_kurtosis_instance_id") || "";
export const apiKey = Cookies.get("_kurtosis_api_key") || "";
export const jwtToken = Cookies.get("_kurtosis_jwt_token");
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@ import {
ModalOverlay,
} from "@chakra-ui/react";
import { FileDisplay } from "kurtosis-ui-components";
import { apiKey, instanceUUID } from "../../../../cookies";
import { EnclaveFullInfo } from "../../types";

export type ConnectEnclaveModalProps = {
enclave: EnclaveFullInfo;
instanceUUID: string;
apiKey: string;
isOpen: boolean;
onClose: () => void;
};

export const ConnectEnclaveModal = ({ isOpen, onClose, enclave, instanceUUID, apiKey }: ConnectEnclaveModalProps) => {
export const ConnectEnclaveModal = ({ isOpen, onClose, enclave }: ConnectEnclaveModalProps) => {
const commands = `
export KURTOSIS_CLOUD_API_KEY="${apiKey}"
kurtosis cloud load ${instanceUUID}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Button, Checkbox, Text } from "@chakra-ui/react";
import { ColumnDef, createColumnHelper } from "@tanstack/react-table";
import { FilesArtifactNameAndUuid, ServiceInfo } from "enclave-manager-sdk/build/api_container_service_pb";
import { ServiceInfo } from "enclave-manager-sdk/build/api_container_service_pb";
import { EnclaveContainersStatus } from "enclave-manager-sdk/build/engine_service_pb";
import { GetPackagesResponse, KurtosisPackage } from "kurtosis-cloud-indexer-sdk";
import { DataTable, FormatDateTime, isDefined } from "kurtosis-ui-components";
Expand All @@ -10,10 +10,11 @@ import { Link } from "react-router-dom";
import { Result } from "true-myth";
import { useKurtosisPackageIndexerClient } from "../../../../client/packageIndexer/KurtosisPackageIndexerClientContext";
import { EnclaveFullInfo } from "../../types";
import { EnclaveArtifactsSummary } from "../widgets/EnclaveArtifactsSummary";
import { EnclaveServicesSummary } from "../widgets/EnclaveServicesSummary";
import { EnclaveStatus } from "../widgets/EnclaveStatus";
import { PackageLinkButton } from "../widgets/PackageLinkButton";
import { PortsSummary } from "../widgets/PortsSummary";
import { getPortTableRows, PortsTableRow } from "./PortsTable";

type EnclaveTableRow = {
uuid: string;
Expand All @@ -22,7 +23,7 @@ type EnclaveTableRow = {
created: DateTime | null;
source: "loading" | KurtosisPackage | null;
services: "loading" | ServiceInfo[] | null;
artifacts: "loading" | FilesArtifactNameAndUuid[] | null;
ports: "loading" | PortsTableRow[] | null;
};

const enclaveToRow = (enclave: EnclaveFullInfo, catalog?: Result<GetPackagesResponse, string>): EnclaveTableRow => {
Expand All @@ -43,10 +44,18 @@ const enclaveToRow = (enclave: EnclaveFullInfo, catalog?: Result<GetPackagesResp
: enclave.services.isOk
? Object.values(enclave.services.value.serviceInfo)
: null,
artifacts: !isDefined(enclave.filesAndArtifacts)
ports: !isDefined(enclave.services)
? "loading"
: enclave.filesAndArtifacts.isOk
? enclave.filesAndArtifacts.value.fileNamesAndUuids
: enclave.services.isOk
? Object.values(enclave.services.value.serviceInfo).flatMap((service) =>
getPortTableRows(
enclave.enclaveUuid,
service.serviceUuid,
service.privatePorts,
service.maybePublicPorts,
service.maybePublicIpAddr,
),
)
: null,
};
};
Expand Down Expand Up @@ -128,9 +137,9 @@ export const EnclavesTable = ({ enclavesData, selection, onSelectionChange }: En
cell: (servicesCell) => <EnclaveServicesSummary services={servicesCell.getValue()} />,
meta: { centerAligned: true },
}),
columnHelper.accessor("artifacts", {
header: "File artifacts",
cell: (artifactsCell) => <EnclaveArtifactsSummary artifacts={artifactsCell.getValue()} />,
columnHelper.accessor("ports", {
header: "Ports",
cell: (portsCell) => <PortsSummary ports={portsCell.getValue()} />,
meta: { centerAligned: true },
}),
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { ExternalLinkIcon } from "@chakra-ui/icons";
import { Flex, Link, Text } from "@chakra-ui/react";
import { Flex, Text } from "@chakra-ui/react";
import { ColumnDef, createColumnHelper } from "@tanstack/react-table";
import { Port } from "enclave-manager-sdk/build/api_container_service_pb";
import { DataTable, isDefined } from "kurtosis-ui-components";
import { useMemo } from "react";
import { KURTOSIS_CLOUD_HOST, KURTOSIS_CLOUD_PROTOCOL } from "../../../../client/constants";
import { instanceUUID } from "../../../../cookies";
import { transportProtocolToString } from "../utils";
import { PortMaybeLink } from "../widgets/PortMaybeLink";

type PortsTableRow = {
export type PortsTableRow = {
port: {
transportProtocol: string;
privatePort: number;
Expand All @@ -19,8 +20,7 @@ type PortsTableRow = {
};
const shortUUID = (fullUUID: string) => fullUUID.substring(0, 12);

const getPortTableRows = (
instanceUUID: string,
export const getPortTableRows = (
enclaveUUID: string,
serviceUUID: string,
privatePorts: Record<string, Port>,
Expand Down Expand Up @@ -55,39 +55,22 @@ const getPortTableRows = (
const columnHelper = createColumnHelper<PortsTableRow>();

type PortsTableProps = {
instanceUUID: string;
enclaveUUID: string;
serviceUUID: string;
privatePorts: Record<string, Port>;
publicPorts: Record<string, Port>;
publicIp: string;
};

export const PortsTable = ({
instanceUUID,
enclaveUUID,
serviceUUID,
privatePorts,
publicPorts,
publicIp,
}: PortsTableProps) => {
export const PortsTable = ({ enclaveUUID, serviceUUID, privatePorts, publicPorts, publicIp }: PortsTableProps) => {
const columns = useMemo<ColumnDef<PortsTableRow, any>[]>(
() => [
columnHelper.accessor("port", {
id: "port_name",
header: "Name",
cell: ({ row, getValue }) => (
<Flex flexDirection={"column"} gap={"10px"}>
<Text>
{row.original.port.applicationProtocol?.startsWith("http") ? (
<Link href={row.original.link} isExternal>
{row.original.port.name}&nbsp;
<ExternalLinkIcon mx="2px" />
</Link>
) : (
row.original.port.name
)}
</Text>
<PortMaybeLink port={row.original} />
</Flex>
),
}),
Expand Down Expand Up @@ -127,7 +110,7 @@ export const PortsTable = ({
return (
<DataTable
columns={columns}
data={getPortTableRows(instanceUUID, enclaveUUID, serviceUUID, privatePorts, publicPorts, publicIp)}
data={getPortTableRows(enclaveUUID, serviceUUID, privatePorts, publicPorts, publicIp)}
defaultSorting={[{ id: "port_name", desc: true }]}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,49 @@
import { Button } from "@chakra-ui/react";
import { ColumnDef, createColumnHelper } from "@tanstack/react-table";
import {
GetServicesResponse,
Port,
ServiceInfo,
ServiceStatus,
} from "enclave-manager-sdk/build/api_container_service_pb";
import { GetServicesResponse, ServiceInfo, ServiceStatus } from "enclave-manager-sdk/build/api_container_service_pb";
import { DataTable, RemoveFunctions } from "kurtosis-ui-components";
import { useMemo } from "react";
import { Link } from "react-router-dom";
import { ImageButton } from "../widgets/ImageButton";
import { PortsSummary } from "../widgets/PortsSummary";
import { ServiceStatusTag } from "../widgets/ServiceStatus";
import { getPortTableRows, PortsTableRow } from "./PortsTable";

type ServicesTableRow = {
serviceUUID: string;
name: string;
status: ServiceStatus;
// started: DateTime | null; TODO: The api needs to support this field
image?: string;
ports: { privatePorts: Record<string, Port>; publicPorts: Record<string, Port> };
ports: PortsTableRow[];
};

const serviceToRow = (service: ServiceInfo): ServicesTableRow => {
const serviceToRow = (enclaveUUID: string, service: ServiceInfo): ServicesTableRow => {
return {
serviceUUID: service.shortenedUuid,
name: service.name,
status: service.serviceStatus,
image: service.container?.imageName,
ports: {
privatePorts: service.privatePorts,
publicPorts: service.maybePublicPorts,
},
ports: getPortTableRows(
enclaveUUID,
service.serviceUuid,
service.privatePorts,
service.maybePublicPorts,
service.maybePublicIpAddr,
),
};
};

const columnHelper = createColumnHelper<ServicesTableRow>();

type ServicesTableProps = {
enclaveUUID: string;
enclaveShortUUID: string;
servicesResponse: RemoveFunctions<GetServicesResponse>;
};

export const ServicesTable = ({ enclaveShortUUID, servicesResponse }: ServicesTableProps) => {
const services = Object.values(servicesResponse.serviceInfo).map(serviceToRow);
export const ServicesTable = ({ enclaveUUID, enclaveShortUUID, servicesResponse }: ServicesTableProps) => {
const services = Object.values(servicesResponse.serviceInfo).map((service) => serviceToRow(enclaveUUID, service));

const columns = useMemo<ColumnDef<ServicesTableRow, any>[]>(
() => [
Expand All @@ -67,14 +67,8 @@ export const ServicesTable = ({ enclaveShortUUID, servicesResponse }: ServicesTa
}),
columnHelper.accessor("ports", {
header: "Ports",
cell: (portsCell) => (
<PortsSummary
privatePorts={portsCell.getValue().privatePorts}
publicPorts={portsCell.getValue().publicPorts}
/>
),
sortingFn: (a, b) =>
Object.keys(a.original.ports.publicPorts).length - Object.keys(b.original.ports.publicPorts).length,
cell: (portsCell) => <PortsSummary ports={portsCell.getValue()} />,
meta: { centerAligned: true },
}),
columnHelper.accessor("serviceUUID", {
header: "Logs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import { ConnectEnclaveModal } from "../modals/ConnectEnclaveModal";

type ConnectEnclaveButtonProps = ButtonProps & {
enclave: EnclaveFullInfo;
instanceUUID: string;
apiKey: string;
};

export const ConnectEnclaveButton = ({ enclave, instanceUUID, apiKey, ...buttonProps }: ConnectEnclaveButtonProps) => {
export const ConnectEnclaveButton = ({ enclave, ...buttonProps }: ConnectEnclaveButtonProps) => {
const [showModal, setShowModal] = useState(false);

return (
Expand All @@ -27,13 +25,7 @@ export const ConnectEnclaveButton = ({ enclave, instanceUUID, apiKey, ...buttonP
Connect
</Button>
</Tooltip>
<ConnectEnclaveModal
enclave={enclave}
instanceUUID={instanceUUID}
apiKey={apiKey}
isOpen={showModal}
onClose={() => setShowModal(false)}
/>
<ConnectEnclaveModal enclave={enclave} isOpen={showModal} onClose={() => setShowModal(false)} />
</>
);
};

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ExternalLinkIcon } from "@chakra-ui/icons";
import { Link, Text } from "@chakra-ui/react";
import { PortsTableRow } from "../tables/PortsTable";

type PortMaybeLinkProps = {
port: PortsTableRow;
};
export const PortMaybeLink = ({ port }: PortMaybeLinkProps) => {
return (
<Text>
{port.port.applicationProtocol?.startsWith("http") ? (
<Link href={port.link} isExternal>
{port.port.name}&nbsp;
<ExternalLinkIcon mx="2px" />
</Link>
) : (
port.port.name
)}
</Text>
);
};
Loading

0 comments on commit 486ea2e

Please sign in to comment.