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

features/rent-gpu-form #43

Merged
merged 31 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
293362d
added rent gpus form + page
baktun14 Oct 23, 2023
c6ac7bc
added form with gpu
baktun14 Oct 23, 2023
6d13a96
added resources + region + token
baktun14 Oct 23, 2023
f656ab1
ant region select
baktun14 Oct 24, 2023
a24b6ba
added advanced config + refactor env var list
baktun14 Oct 24, 2023
08f3f2b
added expose + commands
baktun14 Oct 25, 2023
3e45ca9
added persistent storage
baktun14 Oct 25, 2023
0430ede
refactor gpu control
baktun14 Oct 25, 2023
e996363
refactor cpu form control
baktun14 Oct 25, 2023
93e5e7c
refactor ram + storage
baktun14 Oct 25, 2023
15a478f
remove imports
baktun14 Oct 26, 2023
a04567a
create deployment from rent gpu form
baktun14 Oct 27, 2023
9dda5c5
only show user settings tabs for current user
baktun14 Oct 27, 2023
e0fecaa
better display bid row provider
baktun14 Oct 27, 2023
5a45066
added warning for unaudited providers
baktun14 Oct 30, 2023
b0e6fcf
fix deploying gpu
baktun14 Oct 30, 2023
590caae
verified icon for audited bids
baktun14 Oct 30, 2023
f473192
persist values
baktun14 Oct 30, 2023
4164868
patch gpu models set value mount
baktun14 Oct 30, 2023
668d486
added custom image/template select component
baktun14 Nov 1, 2023
af44b58
fix width of image select
baktun14 Nov 2, 2023
bc8e318
fix bug with empty sdl builder
baktun14 Nov 3, 2023
a716986
added link to rent gpu in select template list
baktun14 Nov 3, 2023
d5f0694
improved env list
baktun14 Nov 3, 2023
45b31d2
pr fixes
baktun14 Nov 6, 2023
0bdd336
fix hydration bug
baktun14 Nov 6, 2023
ab60167
added provider regions endpoint
baktun14 Nov 7, 2023
47e1235
added region filtering based on the amount of providers
baktun14 Nov 7, 2023
3978d46
added env warning + fix bug env form modal
baktun14 Nov 7, 2023
5428416
remove log
baktun14 Nov 7, 2023
041f180
pr fixes
baktun14 Nov 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/src/caching/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const cacheKeys = {
getAuditors: "getAuditors",
getProviderList: "getProviderList",
getChainStats: "getChainStats",
getProviderRegions: "getProviderRegions",
getMainnetNodes: "getMainnetNodes",
getTestnetNodes: "getTestnetNodes",
getSandboxNodes: "getSandboxNodes",
Expand Down
24 changes: 24 additions & 0 deletions api/src/providers/githubProvider.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Octokit } from "@octokit/rest";
import { cacheKeys, cacheResponse } from "@src/caching/helpers";
import { chainDb } from "@src/db/dbConnection";
import { ProviderAttributesSchema } from "@src/types/provider";
import { env } from "@src/utils/env";
import axios from "axios";
import { QueryTypes } from "sequelize";

export function getOctokit() {
const githubPAT = env.AkashlyticsGithubPAT;
Expand Down Expand Up @@ -37,3 +39,25 @@ export async function getAuditors() {

return response;
}

export async function getProviderRegions() {
baktun14 marked this conversation as resolved.
Show resolved Hide resolved
const providerAttributesSchema = await getProviderAttributesSchema();
const regions = providerAttributesSchema["location-region"].values;

let result: { owner: string; location_region: string }[] = await chainDb.query(
`SELECT p.owner, pa.value AS location_region
FROM public."provider" p
JOIN public."providerAttribute" pa ON p.owner = pa.provider
WHERE pa.key = 'location-region';`,
{
type: QueryTypes.SELECT
}
);
baktun14 marked this conversation as resolved.
Show resolved Hide resolved

const res = regions.map((region) => {
const providers = result.filter((provider) => provider.location_region === region.key).map((provider) => provider.owner);
return { ...region, providers };
});

return res;
}
18 changes: 17 additions & 1 deletion api/src/routers/apiRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { ProviderStatsKey } from "@src/types/graph";
import { cacheKeys, cacheResponse } from "@src/caching/helpers";
import axios from "axios";
import { getMarketData } from "@src/providers/marketDataProvider";
import { getAuditors, getProviderAttributesSchema } from "@src/providers/githubProvider";
import { getAuditors, getProviderAttributesSchema, getProviderRegions } from "@src/providers/githubProvider";

export const apiRouter = express.Router();

Expand Down Expand Up @@ -336,6 +336,14 @@ apiRouter.get(
})
);

apiRouter.get(
"/provider-regions",
asyncHandler(async (req, res) => {
const response = await cacheResponse(60 * 5, cacheKeys.getProviderRegions, getProviderRegions);
res.send(response);
})
);

apiRouter.post(
"/pricing",
express.json(),
Expand Down Expand Up @@ -381,6 +389,14 @@ apiRouter.get(
})
);

apiRouter.get(
"/regions",
asyncHandler(async (req, res) => {
const regions = await getProviderRegions();
res.send(regions);
})
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the same as /provider-regions?


apiRouter.get(
"/getAuditors",
asyncHandler(async (req, res) => {
Expand Down
15 changes: 11 additions & 4 deletions deploy-web/src/components/newDeploymentWizard/BidRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { cx } from "@emotion/css";
import { Uptime } from "../providers/Uptime";
import { udenomToDenom } from "@src/utils/mathHelpers";
import { hasSomeParentTheClass } from "@src/utils/domUtils";
import WarningIcon from "@mui/icons-material/Warning";

const useStyles = makeStyles()(theme => ({
root: {
Expand Down Expand Up @@ -149,9 +150,9 @@ export const BidRow: React.FunctionComponent<Props> = ({ bid, selectedBid, handl
<TableCell align="center">
{provider.name ? (
<Link href={UrlService.providerDetail(provider.owner)} onClick={e => e.stopPropagation()}>
{provider.name?.length > 25 ? (
{provider.name?.length > 20 ? (
<CustomTooltip title={provider.name}>
<span>{getSplitText(provider.name, 10, 10)}</span>
<span>{getSplitText(provider.name, 4, 13)}</span>
</CustomTooltip>
) : (
provider.name
Expand All @@ -160,7 +161,7 @@ export const BidRow: React.FunctionComponent<Props> = ({ bid, selectedBid, handl
) : (
<div>
<CustomTooltip title={provider.hostUri}>
<div>{getSplitText(provider.hostUri, 15, 15)}</div>
<div>{getSplitText(provider.hostUri, 4, 13)}</div>
</CustomTooltip>
</div>
)}
Expand All @@ -177,7 +178,13 @@ export const BidRow: React.FunctionComponent<Props> = ({ bid, selectedBid, handl
<AuditorButton provider={provider} />
</Box>
) : (
<Typography variant="caption">No</Typography>
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "center" }}>
<Typography variant="caption">No</Typography>

<CustomTooltip title={<>This provider is not audited, which may result in a lesser quality experience.</>}>
<WarningIcon color="warning" fontSize="small" sx={{ marginLeft: ".5rem" }} />
</CustomTooltip>
</Box>
)}
</TableCell>

Expand Down
10 changes: 8 additions & 2 deletions deploy-web/src/components/newDeploymentWizard/CreateLease.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { BidDto } from "@src/types/deployment";
import { BidCountdownTimer } from "./BidCountdownTimer";
import { CustomNextSeo } from "../shared/CustomNextSeo";
import { RouteStepKeys } from "@src/utils/constants";
import VerifiedUserIcon from "@mui/icons-material/VerifiedUser";
import { useProviderList } from "@src/queries/useProvidersQuery";

const yaml = require("js-yaml");
Expand Down Expand Up @@ -134,7 +135,7 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq }) => {
}
});

if (!isAdded && provider.hostUri.includes(search)) {
if (!isAdded && provider?.hostUri.includes(search)) {
fBids.push(bid.id);
}
}
Expand Down Expand Up @@ -401,7 +402,12 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq }) => {

<FormControlLabel
control={<Checkbox checked={isFilteringAudited} onChange={(ev, value) => setIsFilteringAudited(value)} color="secondary" size="small" />}
label="Audited"
label={
<Box sx={{ display: "flex", alignItems: "center" }}>
Audited
<VerifiedUserIcon fontSize="small" color="success" sx={{ marginLeft: ".5rem" }} />
</Box>
}
/>

{!isLoadingBids && allClosed && (
Expand Down
42 changes: 11 additions & 31 deletions deploy-web/src/components/newDeploymentWizard/ManifestEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import ViewPanel from "../shared/ViewPanel";
import { DeploymentDepositModal } from "../deploymentDetail/DeploymentDepositModal";
import { TransactionMessageData } from "@src/utils/TransactionMessageData";
import { saveDeploymentManifestAndName } from "@src/utils/deploymentLocalDataUtils";
import { UrlService } from "@src/utils/urlUtils";
import { UrlService, handleDocClick } from "@src/utils/urlUtils";
import { event } from "nextjs-google-analytics";
import { AnalyticsEvents } from "@src/utils/analytics";
import { PrerequisiteList } from "./PrerequisiteList";
Expand All @@ -27,6 +27,7 @@ import { updateWallet } from "@src/utils/walletUtils";
import sdlStore from "@src/store/sdlStore";
import { useAtom } from "jotai";
import { SdlBuilder, SdlBuilderRefType } from "./SdlBuilder";
import { validateDeploymentData } from "@src/utils/deploymentUtils";

const yaml = require("js-yaml");

Expand Down Expand Up @@ -101,7 +102,7 @@ export const ManifestEdit: React.FunctionComponent<Props> = ({ editedManifest, s

const doc = yaml.load(yamlStr);
const dd = await deploymentData.NewDeploymentData(settings.apiEndpoint, doc, dseq, address, deposit, depositorAddress);
validateDeploymentData(dd);
validateDeploymentData(dd, selectedTemplate);

setSdlDenom(dd.deposit.denom);

Expand All @@ -120,35 +121,14 @@ export const ManifestEdit: React.FunctionComponent<Props> = ({ editedManifest, s
}
}

function handleDocClick(ev, url) {
ev.preventDefault();

window.open(url, "_blank");
}

/**
* Validate values to change in the template
*/
function validateDeploymentData(deploymentData) {
if (selectedTemplate?.valuesToChange) {
for (const valueToChange of selectedTemplate.valuesToChange) {
if (valueToChange.field === "accept" || valueToChange.field === "env") {
const serviceNames = Object.keys(deploymentData.sdl.services);
for (const serviceName of serviceNames) {
if (
deploymentData.sdl.services[serviceName].expose?.some(e => e.accept?.includes(valueToChange.initialValue)) ||
deploymentData.sdl.services[serviceName].env?.some(e => e?.includes(valueToChange.initialValue))
) {
let error = new Error(`Template value of "${valueToChange.initialValue}" needs to be changed`);
error.name = "TemplateValidation";

throw error;
}
}
}
}
const handleCreateDeployment = async () => {
if (selectedSdlEditMode === "builder") {
const valid = await sdlBuilderRef.current.validate();
if (!valid) return;
}
}

setIsCheckingPrerequisites(true);
};

const onPrerequisiteContinue = () => {
setIsCheckingPrerequisites(false);
Expand Down Expand Up @@ -287,7 +267,7 @@ export const ManifestEdit: React.FunctionComponent<Props> = ({ editedManifest, s
variant="contained"
color="secondary"
disabled={isCreatingDeployment || !!parsingError || !editedManifest}
onClick={() => setIsCheckingPrerequisites(true)}
onClick={() => handleCreateDeployment()}
sx={{ whiteSpace: "nowrap", width: { xs: "100%", sm: "auto" } }}
>
{isCreatingDeployment ? (
Expand Down
17 changes: 11 additions & 6 deletions deploy-web/src/components/newDeploymentWizard/SdlBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface Props {

export type SdlBuilderRefType = {
getSdl: () => string;
validate: () => Promise<boolean>;
};

export const SdlBuilder = React.forwardRef<SdlBuilderRefType, Props>(({ sdlString, setEditedManifest }, ref) => {
Expand All @@ -42,18 +43,23 @@ export const SdlBuilder = React.forwardRef<SdlBuilderRefType, Props>(({ sdlStrin
const [serviceCollapsed, setServiceCollapsed] = useState([]);

React.useImperativeHandle(ref, () => ({
getSdl: getSdl
getSdl: getSdl,
validate: async () => {
return await trigger();
}
}));

useEffect(() => {
const { unsubscribe } = watch(data => {
const sdl = generateSdl({ services: data.services as Service[] });
const sdl = generateSdl(data.services as Service[]);
setEditedManifest(sdl);
});

try {
const services = createAndValidateSdl(sdlString);
setValue("services", services as Service[]);
if (!!sdlString) {
const services = createAndValidateSdl(sdlString);
setValue("services", services as Service[]);
}
} catch (error) {
setError("Error importing SDL");
}
Expand All @@ -66,7 +72,7 @@ export const SdlBuilder = React.forwardRef<SdlBuilderRefType, Props>(({ sdlStrin
}, [watch]);

const getSdl = () => {
return generateSdl({ services: _services });
return generateSdl(_services);
};

const createAndValidateSdl = (yamlStr: string) => {
Expand Down Expand Up @@ -110,7 +116,6 @@ export const SdlBuilder = React.forwardRef<SdlBuilderRefType, Props>(({ sdlStrin
{services.map((service, serviceIndex) => (
<SimpleServiceFormControl
key={service.id}
service={service}
serviceIndex={serviceIndex}
_services={_services}
providerAttributesSchema={providerAttributesSchema}
Expand Down
23 changes: 14 additions & 9 deletions deploy-web/src/components/newDeploymentWizard/TemplateList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ import { DeployOptionBox } from "./DeployOptionBox";
import Link from "next/link";
import { BuildCircleTwoTone } from "@mui/icons-material";
import { TemplateCreation } from "@src/types";
import { emptyTemplate, helloWorldTemplate, ubuntuTemplate } from "@src/utils/templates";
import { helloWorldTemplate, ubuntuTemplate } from "@src/utils/templates";
import { CustomNextSeo } from "../shared/CustomNextSeo";
import { useAtom } from "jotai";
import sdlStore from "@src/store/sdlStore";
import ShutterSpeedIcon from "@mui/icons-material/ShutterSpeed";

const useStyles = makeStyles()(theme => ({}));

Expand Down Expand Up @@ -43,6 +46,7 @@ export const TemplateList: React.FunctionComponent<Props> = ({ setSelectedTempla
const router = useRouter();
const fileUploadRef = useRef(null);
const [previewTemplates, setPreviewTemplates] = useState([]);
const [, setSdlEditMode] = useAtom(sdlStore.selectedSdlEditMode);

useEffect(() => {
if (templates) {
Expand Down Expand Up @@ -81,7 +85,8 @@ export const TemplateList: React.FunctionComponent<Props> = ({ setSelectedTempla
};

function onSDLBuilderClick() {
router.push(UrlService.sdlBuilder());
setSdlEditMode("builder");
router.push(UrlService.newDeployment({ step: RouteStepKeys.editDeployment }));
}

return (
Expand Down Expand Up @@ -110,6 +115,13 @@ export const TemplateList: React.FunctionComponent<Props> = ({ setSelectedTempla
onClick={() => router.push(UrlService.newDeployment({ step: RouteStepKeys.editDeployment, templateId: helloWorldTemplate.code }))}
/>

<DeployOptionBox
title="Rent GPUs"
description="Rent GPUs from the Akash Network providers to run your AI workloads."
icon={<ShutterSpeedIcon />}
onClick={() => router.push(UrlService.rentGpus())}
/>

<DeployOptionBox
title={"Build your template"}
description={"With our new SDL Builder, you can create your own SDL from scratch in a few clicks!"}
Expand All @@ -124,13 +136,6 @@ export const TemplateList: React.FunctionComponent<Props> = ({ setSelectedTempla
icon={<DescriptionIcon />}
onClick={() => fromFile()}
/>

<DeployOptionBox
title={emptyTemplate.title}
description={emptyTemplate.description}
icon={<InsertDriveFileIcon />}
onClick={() => selectTemplate(emptyTemplate)}
/>
</Box>
</Box>

Expand Down
4 changes: 2 additions & 2 deletions deploy-web/src/components/providers/AuditorButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState, MouseEvent } from "react";
import SecurityIcon from "@mui/icons-material/Security";
import VerifiedUserIcon from '@mui/icons-material/VerifiedUser';
import { IconButton } from "@mui/material";
import { AuditorsModal } from "./AuditorsModal";
import { ClientProviderDetailWithStatus, ClientProviderList } from "@src/types/provider";
Expand Down Expand Up @@ -28,7 +28,7 @@ export const AuditorButton: React.FunctionComponent<Props> = ({ provider }) => {
return (
<>
<IconButton onClick={onAuditorClick} size="small">
<SecurityIcon fontSize="small" color="secondary" />
<VerifiedUserIcon fontSize="small" color="success" />
</IconButton>

{isViewingAuditors && <AuditorsModal attributes={provider.attributes} onClose={onClose} />}
Expand Down
4 changes: 2 additions & 2 deletions deploy-web/src/components/providers/AuditorsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ export const AuditorsModal: React.FunctionComponent<Props> = ({ attributes, onCl
<TableCell>{a.value}</TableCell>
<TableCell>
{a.auditedBy
.filter(x => auditors.some(y => y.address === x))
.filter(x => auditors?.some(y => y.address === x))
.map(x => {
const auditor = auditors.find(y => y.address === x);
const auditor = auditors?.find(y => y.address === x);
return (
<div key={x}>
<CustomTooltip
Expand Down
Loading