Jelajahi Sumber

Input sliders and Bounds for CPU and RAM (#3354)

Co-authored-by: Feroze Mohideen <feroze@porter.run>
sdess09 2 tahun lalu
induk
melakukan
8f789baf3f

+ 216 - 0
dashboard/src/components/porter/InputSlider.tsx

@@ -0,0 +1,216 @@
+import React from 'react';
+import Slider, { Mark } from '@material-ui/core/Slider';
+import Tooltip from '@material-ui/core/Tooltip';
+import Typography from '@material-ui/core/Typography';
+import styled from 'styled-components';
+import { withStyles } from '@material-ui/core/styles';
+import Container from './Container';
+
+
+type InputSliderProps = {
+  label?: string;
+  unit?: string;
+  min: number;
+  max: number;
+  value: string;
+  setValue: (value: number) => void;
+  disabled?: boolean;
+  disabledTooltip?: string;
+  color?: string;
+  width?: string;
+  step?: number;
+};
+
+const ValueLabelComponent: React.FC<any> = (props) => {
+  const { children, value } = props;
+
+  return (
+    <StyledTooltip
+      placement="bottom"
+      title={value}
+      arrow
+    >
+      {children}
+    </StyledTooltip>
+  );
+}
+
+const InputSlider: React.FC<InputSliderProps> = ({
+  label,
+  unit,
+  min,
+  max,
+  value,
+  setValue,
+  disabled,
+  disabledTooltip,
+  color,
+  step,
+  width,
+
+}) => {
+  const marks: Mark[] = [
+
+    {
+      value: max,
+      label: max.toString(),
+    },
+  ];
+
+  return (
+    <SliderContainer width={width}>
+      <LabelContainer>
+        {label && <Label>{label}</Label>}
+        <Value>{`${value} ${unit}`}</Value>
+      </LabelContainer>
+      <DisabledTooltip title={disabled ? disabledTooltip || '' : ''} arrow>
+
+        <div style={{ position: 'relative' }}>
+          <StyledSlider
+            ValueLabelComponent={ValueLabelComponent}
+            aria-label="input slider"
+            min={min}
+            max={max}
+            value={Number(value)}
+            onChange={(event, newValue) => {
+              setValue(newValue as number);
+            }}
+            disabled={disabled}
+            marks={marks}
+            step={step ? step : 1}
+            style={{
+              color: disabled ? "gray" : color,
+            }}
+          />
+          {disabled && (
+            <div
+              style={{
+                position: 'absolute',
+                top: 0,
+                left: 0,
+                right: 0,
+                bottom: 0,
+                cursor: 'not-allowed',
+                zIndex: 1
+              }}
+            />
+          )}
+        </div>
+      </DisabledTooltip>
+
+    </SliderContainer >
+  );
+};
+
+
+export default InputSlider;
+
+const SliderContainer = styled.div<{ width?: string }>`
+  width: ${({ width }) => width || '300px'};
+  margin: 1px 0;
+`;
+
+const Label = styled.div<{ color?: string }>`
+  font-size: 13px;
+  margin-right: 5px;
+  margin-bottom: 10px;
+  color: #aaaabb;
+`;
+
+const Value = styled.div<{ color?: string }>`
+  font-size: 13px;
+  margin-bottom: 10px;
+  color: #ffff;
+`;
+
+const DisabledTooltip = withStyles(theme => ({
+  tooltip: {
+    backgroundColor: '#333',
+    color: '#fff',
+    padding: '8px',
+    borderRadius: '4px',
+    fontSize: '14px',
+    textAlign: 'center',
+    whiteSpace: 'pre-wrap',
+    wordWrap: 'break-word',
+    maxWidth: '200px',
+    width: '200px',
+    [theme.breakpoints.up('sm')]: {
+      margin: '0 14px',
+    },
+  },
+  arrow: {
+    color: '#333',
+  },
+}))(Tooltip);
+
+
+const StyledSlider = withStyles({
+  root: {
+    height: '8px', //height of the track
+  },
+  mark: {
+    backgroundColor: '#fff',  // mark color
+    height: 4, // size of the mark
+    width: 1, // size of the mark
+    borderRadius: '50%',
+    marginTop: 6,
+    marginLeft: -1,
+  },
+  markActive: {
+    backgroundColor: '#fff',
+  },
+  markLabel: {
+    color: '#6e717d',
+    fontSize: '12px',
+    marginRight: 5,
+
+  },
+  markLabelActive: {
+    color: '#6e717d',
+    marginRight: 5,
+  },
+  thumb: {
+    height: 16, // Size of the thumb
+    width: 16, // Size of the thumb
+    backgroundColor: '#fff',
+    border: '2px solid currentColor',
+    '&:focus, &:hover, &$active': {
+      boxShadow: 'inherit',
+    },
+    '&$disabled': { // Targeting the thumb when the slider is disabled
+      height: 16,
+      width: 16,
+    },
+  },
+  track: {
+    height: 8, // Same as root height for consistency
+    borderRadius: 4,
+  },
+  rail: {
+    height: 8, // Same as root height for consistency
+    borderRadius: 4,
+  },
+  valueLabel: {
+    top: -22,
+    '& *': {
+      background: 'transparent',
+      border: 'none', // remove the default border
+    },
+  },
+  disabled: {},
+})(Slider);
+
+
+const StyledTooltip = withStyles({
+  tooltip: {
+    fontSize: 12,
+    padding: "5px 10px",
+
+  }
+})(Tooltip);
+
+const LabelContainer = styled.div`
+  display: flex;
+  align-items: center;
+`;

+ 80 - 1
dashboard/src/main/home/app-dashboard/new-app-flow/ServiceContainer.tsx

@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useContext, useEffect, useState } from "react";
 import AnimateHeight, { Height } from "react-animate-height";
 import styled from "styled-components";
 import _ from "lodash";
@@ -14,6 +14,9 @@ import JobTabs from "./tabs/JobTabs";
 import { Service } from "./serviceTypes";
 import StatusFooter from "../expanded-app/StatusFooter";
 import ReleaseTabs from "./tabs/ReleaseTabs";
+import { Context } from "shared/Context";
+import { AWS_INSTANCE_LIMITS } from "./tabs/utils";
+import api from "shared/api";
 
 interface ServiceProps {
   service: Service;
@@ -32,6 +35,74 @@ const ServiceContainer: React.FC<ServiceProps> = ({
 }) => {
   const [height, setHeight] = React.useState<Height>("auto");
 
+  const UPPER_BOUND = .75;
+
+  const [maxCPU, setMaxCPU] = useState(2 * UPPER_BOUND); //default is set to a t3 medium 
+  const [maxRAM, setMaxRAM] = useState(4 * UPPER_BOUND); //default is set to a t3 medium
+  const context = useContext(Context);
+
+  useEffect(() => {
+    const { currentCluster, currentProject } = context;
+    if (!currentCluster || !currentProject) {
+      return;
+    }
+    var instanceType = "";
+
+
+    if (service) {
+      const serviceName = service.name;
+
+      //first check if there is a nodeSelector for the given application (Can be null)
+      if (chart?.config?.[`${serviceName}-${service.type}`]?.nodeSelector?.["beta.kubernetes.io/instance-type"]) {
+        instanceType = chart?.config?.[`${serviceName}-${service.type}`]?.nodeSelector?.["beta.kubernetes.io/instance-type"]
+        const [instanceClass, instanceSize] = instanceType.split('.');
+        const currentInstance = AWS_INSTANCE_LIMITS[instanceClass][instanceSize];
+        setMaxCPU(currentInstance.vCPU * UPPER_BOUND);
+        setMaxRAM(currentInstance.RAM * UPPER_BOUND);
+      }
+    }
+    //Query the given nodes if no instance type is specified
+    if (instanceType == "") {
+      api
+        .getClusterNodes(
+          "<token>",
+          {},
+          {
+            cluster_id: currentCluster.id,
+            project_id: currentProject.id,
+          }
+        )
+        .then(({ data }) => {
+          if (data) {
+
+            let largestInstanceType = {
+              vCPUs: 2,
+              RAM: 4,
+            };
+
+            data.forEach(node => {
+              if (node.labels['porter.run/workload-kind']) {
+                var instanceType: string = node.labels['beta.kubernetes.io/instance-type'];
+                const [instanceClass, instanceSize] = instanceType.split('.');
+                if (instanceClass && instanceSize) {
+                  if (AWS_INSTANCE_LIMITS[instanceClass] && AWS_INSTANCE_LIMITS[instanceClass][instanceSize]) {
+                    let currentInstance = AWS_INSTANCE_LIMITS[instanceClass][instanceSize];
+                    largestInstanceType.vCPUs = currentInstance.vCPU;
+                    largestInstanceType.RAM = currentInstance.RAM;
+
+                  }
+                }
+              }
+            });
+
+            setMaxCPU(largestInstanceType.vCPUs * UPPER_BOUND);
+            setMaxRAM(largestInstanceType.RAM * UPPER_BOUND);
+          }
+        }).catch((error) => {
+
+        });
+    }
+  }, []);
   // TODO: calculate heights instead of hardcoding them
   const renderTabs = (service: Service) => {
     switch (service.type) {
@@ -41,6 +112,8 @@ const ServiceContainer: React.FC<ServiceProps> = ({
             service={service}
             editService={editService}
             setHeight={setHeight}
+            maxCPU={maxCPU}
+            maxRAM={maxRAM}
           />
         );
       case "worker":
@@ -49,6 +122,8 @@ const ServiceContainer: React.FC<ServiceProps> = ({
             service={service}
             editService={editService}
             setHeight={setHeight}
+            maxCPU={maxCPU}
+            maxRAM={maxRAM}
           />
         );
       case "job":
@@ -57,6 +132,8 @@ const ServiceContainer: React.FC<ServiceProps> = ({
             service={service}
             editService={editService}
             setHeight={setHeight}
+            maxCPU={maxCPU}
+            maxRAM={maxRAM}
           />
         );
       case "release":
@@ -65,6 +142,8 @@ const ServiceContainer: React.FC<ServiceProps> = ({
             service={service}
             editService={editService}
             setHeight={setHeight}
+            maxCPU={maxCPU}
+            maxRAM={maxRAM}
           />
         );
     }

+ 29 - 14
dashboard/src/main/home/app-dashboard/new-app-flow/tabs/JobTabs.tsx

@@ -9,18 +9,23 @@ import AnimateHeight, { Height } from "react-animate-height";
 import cronstrue from 'cronstrue';
 import Link from "components/porter/Link";
 import { Context } from "shared/Context";
-import { DATABASE_HEIGHT_DISABLED, DATABASE_HEIGHT_ENABLED } from "./utils";
+import { DATABASE_HEIGHT_DISABLED, DATABASE_HEIGHT_ENABLED, MIB_TO_GIB, MILI_TO_CORE } from "./utils";
+import InputSlider from "components/porter/InputSlider";
 
 interface Props {
   service: JobService;
   editService: (service: JobService) => void;
   setHeight: (height: Height) => void;
+  maxRAM: number;
+  maxCPU: number;
 }
 
 const JobTabs: React.FC<Props> = ({
   service,
   editService,
   setHeight,
+  maxRAM,
+  maxCPU,
 }) => {
   const [currentTab, setCurrentTab] = React.useState<string>('main');
   const { currentCluster } = useContext(Context);
@@ -73,27 +78,37 @@ const JobTabs: React.FC<Props> = ({
   };
 
   const renderResources = () => {
-    setHeight(244);
+    setHeight(292);
     return (
       <>
         <Spacer y={1} />
-        <Input
-          label="CPUs (Millicores)"
-          placeholder="ex: 0.5"
-          value={service.cpu.value}
+        <InputSlider
+          label="CPUs: "
+          unit="Cores"
+          min={0}
+          max={maxCPU}
+          color={"#3a48ca"}
+          value={(service.cpu.value / MILI_TO_CORE).toString()}
+          setValue={(e) => {
+            editService({ ...service, cpu: { readOnly: false, value: e * MILI_TO_CORE } });
+          }}
+          step={0.01}
           disabled={service.cpu.readOnly}
-          width="300px"
-          setValue={(e) => { editService({ ...service, cpu: { readOnly: false, value: e } }) }}
           disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
-        <Input
-          label="RAM (MB)"
-          placeholder="ex: 1"
-          value={service.ram.value}
+        <InputSlider
+          label="RAM: "
+          unit="GiB"
+          min={0}
+          max={maxRAM}
+          color={"#3a48ca"}
+          value={(service.ram.value / MIB_TO_GIB).toString()}
+          setValue={(e) => {
+            editService({ ...service, ram: { readOnly: false, value: e * MIB_TO_GIB } });
+          }}
           disabled={service.ram.readOnly}
-          width="300px"
-          setValue={(e) => { editService({ ...service, ram: { readOnly: false, value: e } }) }}
+          step={0.01}
           disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
       </>

+ 29 - 14
dashboard/src/main/home/app-dashboard/new-app-flow/tabs/ReleaseTabs.tsx

@@ -7,18 +7,23 @@ import AnimateHeight, { Height } from "react-animate-height";
 import { Context } from "shared/Context";
 import Checkbox from "components/porter/Checkbox";
 import Text from "components/porter/Text";
-import { DATABASE_HEIGHT_DISABLED, DATABASE_HEIGHT_ENABLED } from "./utils";
+import { DATABASE_HEIGHT_DISABLED, DATABASE_HEIGHT_ENABLED, MIB_TO_GIB, MILI_TO_CORE } from "./utils";
+import InputSlider from "components/porter/InputSlider";
 
 interface Props {
     service: ReleaseService;
     editService: (service: ReleaseService) => void;
     setHeight: (height: Height) => void;
+    maxRAM: number;
+    maxCPU: number;
 }
 
 const ReleaseTabs: React.FC<Props> = ({
     service,
     editService,
     setHeight,
+    maxRAM,
+    maxCPU,
 }) => {
     const [currentTab, setCurrentTab] = React.useState<string>('main');
     const { currentCluster } = useContext(Context);
@@ -42,27 +47,37 @@ const ReleaseTabs: React.FC<Props> = ({
     };
 
     const renderResources = () => {
-        setHeight(244);
+        setHeight(292);
         return (
             <>
                 <Spacer y={1} />
-                <Input
-                    label="CPU (Millicores)"
-                    placeholder="ex: 0.5"
-                    value={service.cpu.value}
+                <InputSlider
+                    label="CPUs: "
+                    unit="Cores"
+                    min={0}
+                    max={maxCPU}
+                    color={"#3a48ca"}
+                    value={(service.cpu.value / MILI_TO_CORE).toString()}
+                    setValue={(e) => {
+                        editService({ ...service, cpu: { readOnly: false, value: e * MILI_TO_CORE } });
+                    }}
+                    step={0.01}
                     disabled={service.cpu.readOnly}
-                    width="300px"
-                    setValue={(e) => { editService({ ...service, cpu: { readOnly: false, value: e } }) }}
                     disabledTooltip={"You may only edit this field in your porter.yaml."}
                 />
                 <Spacer y={1} />
-                <Input
-                    label="RAM (MB)"
-                    placeholder="ex: 1"
-                    value={service.ram.value}
+                <InputSlider
+                    label="RAM: "
+                    unit="GiB"
+                    min={0}
+                    max={maxRAM}
+                    color={"#3a48ca"}
+                    value={(service.ram.value / MIB_TO_GIB).toString()}
+                    setValue={(e) => {
+                        editService({ ...service, ram: { readOnly: false, value: e * MIB_TO_GIB } });
+                    }}
                     disabled={service.ram.readOnly}
-                    width="300px"
-                    setValue={(e) => { editService({ ...service, ram: { readOnly: false, value: e } }) }}
+                    step={0.01}
                     disabledTooltip={"You may only edit this field in your porter.yaml."}
                 />
             </>

+ 39 - 23
dashboard/src/main/home/app-dashboard/new-app-flow/tabs/WebTabs.tsx

@@ -1,5 +1,5 @@
 import Input from "components/porter/Input";
-import React, { useContext } from "react";
+import React, { useContext, useEffect, useState } from "react";
 import Text from "components/porter/Text";
 import Spacer from "components/porter/Spacer";
 import TabSelector from "components/TabSelector";
@@ -7,17 +7,21 @@ import Checkbox from "components/porter/Checkbox";
 import { Service, WebService } from "../serviceTypes";
 import AnimateHeight, { Height } from "react-animate-height";
 import { Context } from "shared/Context";
-import { DATABASE_HEIGHT_DISABLED, DATABASE_HEIGHT_ENABLED, RESOURCE_HEIGHT_WITHOUT_AUTOSCALING, RESOURCE_HEIGHT_WITH_AUTOSCALING } from "./utils";
+import { DATABASE_HEIGHT_DISABLED, DATABASE_HEIGHT_ENABLED, RESOURCE_HEIGHT_WITHOUT_AUTOSCALING, RESOURCE_HEIGHT_WITH_AUTOSCALING, AWS_INSTANCE_LIMITS, MILI_TO_CORE, MIB_TO_GIB } from "./utils";
 import IngressCustomAnnotations from "./IngressCustomAnnotations";
 import CustomDomains from "./CustomDomains";
+import InputSlider from "components/porter/InputSlider";
+import api from "shared/api";
 
 interface Props {
   service: WebService;
   editService: (service: WebService) => void;
   setHeight: (height: Height) => void;
+  chart?: any;
+  maxRAM: number;
+  maxCPU: number;
 }
 
-
 const NETWORKING_HEIGHT_WITHOUT_INGRESS = 204;
 const NETWORKING_HEIGHT_WITH_INGRESS = 395;
 const ADVANCED_BASE_HEIGHT = 215;
@@ -28,6 +32,8 @@ const WebTabs: React.FC<Props> = ({
   service,
   editService,
   setHeight,
+  maxRAM,
+  maxCPU,
 }) => {
   const [currentTab, setCurrentTab] = React.useState<string>("main");
   const { currentCluster } = useContext(Context);
@@ -243,27 +249,33 @@ const WebTabs: React.FC<Props> = ({
     return (
       <>
         <Spacer y={1} />
-        <Input
-          label="CPUs (Millicores)"
-          placeholder="ex: 500"
-          value={service.cpu.value}
-          disabled={service.cpu.readOnly}
-          width="300px"
+        <InputSlider
+          label="CPUs: "
+          unit="Cores"
+          min={0}
+          max={maxCPU}
+          color={"#3a48ca"}
+          value={(service.cpu.value / MILI_TO_CORE).toString()}
           setValue={(e) => {
-            editService({ ...service, cpu: { readOnly: false, value: e } });
+            editService({ ...service, cpu: { readOnly: false, value: e * MILI_TO_CORE } });
           }}
+          step={0.01}
+          disabled={service.cpu.readOnly}
           disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
-        <Input
-          label="RAM (MB)"
-          placeholder="ex: 1"
-          value={service.ram.value}
-          disabled={service.ram.readOnly}
-          width="300px"
+        <InputSlider
+          label="RAM: "
+          unit="GiB"
+          min={0}
+          max={maxRAM}
+          color={"#3a48ca"}
+          value={(service.ram.value / MIB_TO_GIB).toString()}
           setValue={(e) => {
-            editService({ ...service, ram: { readOnly: false, value: e } });
+            editService({ ...service, ram: { readOnly: false, value: e * MIB_TO_GIB } });
           }}
+          disabled={service.ram.readOnly}
+          step={0.01}
           disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
@@ -360,9 +372,11 @@ const WebTabs: React.FC<Props> = ({
             }
           />
           <Spacer y={1} />
-          <Input
-            label="Target CPU utilization (%)"
-            placeholder="ex: 50"
+          <InputSlider
+            label="Target CPU utilization: "
+            unit="%"
+            min={0}
+            max={100}
             value={service.autoscaling.targetCPUUtilizationPercentage.value}
             disabled={
               service.autoscaling.targetCPUUtilizationPercentage.readOnly ||
@@ -385,9 +399,11 @@ const WebTabs: React.FC<Props> = ({
             }
           />
           <Spacer y={1} />
-          <Input
-            label="Target RAM utilization (%)"
-            placeholder="ex: 50"
+          <InputSlider
+            label="Target RAM utilization: "
+            unit="%"
+            min={0}
+            max={100}
             value={service.autoscaling.targetMemoryUtilizationPercentage.value}
             disabled={
               service.autoscaling.targetMemoryUtilizationPercentage.readOnly ||

+ 38 - 19
dashboard/src/main/home/app-dashboard/new-app-flow/tabs/WorkerTabs.tsx

@@ -6,19 +6,24 @@ import TabSelector from "components/TabSelector";
 import Checkbox from "components/porter/Checkbox";
 import { WorkerService } from "../serviceTypes";
 import AnimateHeight, { Height } from "react-animate-height";
-import { DATABASE_HEIGHT_DISABLED, DATABASE_HEIGHT_ENABLED, RESOURCE_HEIGHT_WITHOUT_AUTOSCALING, RESOURCE_HEIGHT_WITH_AUTOSCALING } from "./utils";
+import { DATABASE_HEIGHT_DISABLED, DATABASE_HEIGHT_ENABLED, MIB_TO_GIB, MILI_TO_CORE, RESOURCE_HEIGHT_WITHOUT_AUTOSCALING, RESOURCE_HEIGHT_WITH_AUTOSCALING } from "./utils";
 import { Context } from "shared/Context";
+import InputSlider from "components/porter/InputSlider";
 
 interface Props {
   service: WorkerService;
   editService: (service: WorkerService) => void;
   setHeight: (height: Height) => void;
+  maxRAM: number;
+  maxCPU: number;
 }
 
 const WorkerTabs: React.FC<Props> = ({
   service,
   editService,
   setHeight,
+  maxCPU,
+  maxRAM,
 }) => {
   const [currentTab, setCurrentTab] = React.useState<string>('main');
   const { currentCluster } = useContext(Context);
@@ -46,23 +51,33 @@ const WorkerTabs: React.FC<Props> = ({
     return (
       <>
         <Spacer y={1} />
-        <Input
-          label="CPUs (Millicores)"
-          placeholder="ex: 500"
-          value={service.cpu.value}
+        <InputSlider
+          label="CPUs: "
+          unit="Cores"
+          min={0}
+          max={maxCPU}
+          color={"#3a48ca"}
+          value={(service.cpu.value / MILI_TO_CORE).toString()}
+          setValue={(e) => {
+            editService({ ...service, cpu: { readOnly: false, value: e * MILI_TO_CORE } });
+          }}
+          step={0.01}
           disabled={service.cpu.readOnly}
-          width="300px"
-          setValue={(e) => { editService({ ...service, cpu: { readOnly: false, value: e } }) }}
           disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
-        <Input
-          label="RAM (MB)"
-          placeholder="ex: 1"
-          value={service.ram.value}
+        <InputSlider
+          label="RAM: "
+          unit="GiB"
+          min={0}
+          max={maxRAM}
+          color={"#3a48ca"}
+          value={(service.ram.value / MIB_TO_GIB).toString()}
+          setValue={(e) => {
+            editService({ ...service, ram: { readOnly: false, value: e * MIB_TO_GIB } });
+          }}
           disabled={service.ram.readOnly}
-          width="300px"
-          setValue={(e) => { editService({ ...service, ram: { readOnly: false, value: e } }) }}
+          step={0.01}
           disabledTooltip={"You may only edit this field in your porter.yaml."}
         />
         <Spacer y={1} />
@@ -136,9 +151,11 @@ const WorkerTabs: React.FC<Props> = ({
             }
           />
           <Spacer y={1} />
-          <Input
-            label="Target CPU utilization (%)"
-            placeholder="ex: 50"
+          <InputSlider
+            label="Target CPU utilization: "
+            unit="%"
+            min={0}
+            max={100}
             value={service.autoscaling.targetCPUUtilizationPercentage.value}
             disabled={
               service.autoscaling.targetCPUUtilizationPercentage.readOnly ||
@@ -161,9 +178,11 @@ const WorkerTabs: React.FC<Props> = ({
             }
           />
           <Spacer y={1} />
-          <Input
-            label="Target RAM utilization (%)"
-            placeholder="ex: 50"
+          <InputSlider
+            label="Target RAM utilization: "
+            unit="%"
+            min={0}
+            max={100}
             value={service.autoscaling.targetMemoryUtilizationPercentage.value}
             disabled={
               service.autoscaling.targetMemoryUtilizationPercentage.readOnly ||

+ 82 - 2
dashboard/src/main/home/app-dashboard/new-app-flow/tabs/utils.ts

@@ -1,4 +1,84 @@
 export const DATABASE_HEIGHT_ENABLED = 374;
 export const DATABASE_HEIGHT_DISABLED = 119;
-export const RESOURCE_HEIGHT_WITHOUT_AUTOSCALING = 373;
-export const RESOURCE_HEIGHT_WITH_AUTOSCALING = 713;
+export const RESOURCE_HEIGHT_WITHOUT_AUTOSCALING = 422;
+export const RESOURCE_HEIGHT_WITH_AUTOSCALING = 809;
+export const MIB_TO_GIB = 1024;
+export const MILI_TO_CORE = 1000;
+interface InstanceDetails {
+    vCPU: number;
+    "RAM": number;
+}
+
+interface InstanceTypes {
+    [key: string]: {
+        [size: string]: InstanceDetails;
+    };
+}
+
+export const AWS_INSTANCE_LIMITS: InstanceTypes = {
+    "t3a": {
+        "nano": { "vCPU": 2, "RAM": 0.5 },
+        "micro": { "vCPU": 2, "RAM": 1 },
+        "small": { "vCPU": 2, "RAM": 2 },
+        "medium": { "vCPU": 2, "RAM": 4 },
+        "large": { "vCPU": 2, "RAM": 8 },
+        "xlarge": { "vCPU": 4, "RAM": 16 },
+        "2xlarge": { "vCPU": 8, "RAM": 32 }
+    },
+    "t3": {
+        "nano": { "vCPU": 2, "RAM": 0.5 },
+        "micro": { "vCPU": 2, "RAM": 1 },
+        "small": { "vCPU": 2, "RAM": 2 },
+        "medium": { "vCPU": 2, "RAM": 4 },
+        "large": { "vCPU": 2, "RAM": 8 },
+        "xlarge": { "vCPU": 4, "RAM": 16 },
+        "2xlarge": { "vCPU": 8, "RAM": 32 }
+    },
+    "t2": {
+        "nano": { "vCPU": 1, "RAM": 0.5 },
+        "micro": { "vCPU": 1, "RAM": 1 },
+        "small": { "vCPU": 1, "RAM": 2 },
+        "medium": { "vCPU": 2, "RAM": 4 },
+        "large": { "vCPU": 2, "RAM": 8 },
+        "xlarge": { "vCPU": 4, "RAM": 16 },
+        "2xlarge": { "vCPU": 8, "RAM": 32 }
+    },
+    "c6i": {
+        "large": { "vCPU": 2, "RAM": 4 },
+        "xlarge": { "vCPU": 4, "RAM": 8 },
+        "2xlarge": { "vCPU": 8, "RAM": 16 },
+        "4xlarge": { "vCPU": 16, "RAM": 32 },
+        "8xlarge": { "vCPU": 32, "RAM": 64 },
+        "12xlarge": { "vCPU": 48, "RAM": 96 },
+    },
+    "g4dn": {
+        "xlarge": { "vCPU": 4, "RAM": 16 },
+        "2xlarge": { "vCPU": 8, "RAM": 32 },
+        "4xlarge": { "vCPU": 16, "RAM": 64 },
+        "8xlarge": { "vCPU": 32, "RAM": 128 },
+    },
+    "r6a": {
+        "large": { "vCPU": 2, "RAM": 16 },
+        "xlarge": { "vCPU": 4, "RAM": 32 },
+        "2xlarge": { "vCPU": 8, "RAM": 64 },
+        "4xlarge": { "vCPU": 16, "RAM": 128 },
+        "8xlarge": { "vCPU": 32, "RAM": 256 },
+    },
+    "c5": {
+        "large": { "vCPU": 2, "RAM": 4 },
+        "xlarge": { "vCPU": 4, "RAM": 8 },
+        "2xlarge": { "vCPU": 8, "RAM": 16 },
+        "4xlarge": { "vCPU": 16, "RAM": 32 },
+    },
+    "m5": {
+        "large": { "vCPU": 2, "RAM": 8 },
+        "xlarge": { "vCPU": 4, "RAM": 16 },
+        "2xlarge": { "vCPU": 8, "RAM": 32 },
+        "4xlarge": { "vCPU": 16, "RAM": 64 },
+    },
+    "x2gd": {
+        "medium": { "vCPU": 1, "RAM": 16 },
+        "large": { "vCPU": 2, "RAM": 32 },
+        "xlarge": { "vCPU": 4, "RAM": 64 },
+    }
+}