Просмотр исходного кода

Merge pull request #1066 from porter-dev/0.8.0-provisioning-cost-info

[0.8.0] Provision Cost Info
abelanger5 4 лет назад
Родитель
Сommit
e40a1ca55d

+ 63 - 0
dashboard/src/main/home/provisioner/AWSFormSection.tsx

@@ -16,12 +16,14 @@ import Heading from "components/form-components/Heading";
 import SaveButton from "components/SaveButton";
 import CheckboxList from "components/form-components/CheckboxList";
 import { RouteComponentProps, withRouter } from "react-router";
+import Tooltip from "@material-ui/core/Tooltip";
 
 type PropsType = RouteComponentProps & {
   setSelectedProvisioner: (x: string | null) => void;
   handleError: () => void;
   projectName: string;
   infras: InfraType[];
+  highlightCosts?: boolean;
 };
 
 type StateType = {
@@ -73,6 +75,15 @@ const machineTypeOptions = [
   { value: "t3.2xlarge", label: "t3.2xlarge" },
 ];
 
+const costMapping: Record<string, number> = {
+  "t2.medium": 35,
+  "t2.xlarge": 135,
+  "t2.2xlarge": 270,
+  "t3.medium": 30,
+  "t3.xlarge": 120,
+  "t3.2xlarge": 240,
+};
+
 // TODO: Consolidate across forms w/ HOC
 class AWSFormSection extends Component<PropsType, StateType> {
   state = {
@@ -393,6 +404,36 @@ class AWSFormSection extends Component<PropsType, StateType> {
             setActiveValue={(x: string) => this.setState({ awsMachineType: x })}
             label="⚙️ AWS Machine Type"
           />
+          <Helper>
+            Estimated Cost:{" "}
+            <CostHighlight highlight={this.props.highlightCosts}>
+              {`\$${
+                70 + 3 * costMapping[this.state.awsMachineType] + 30
+              }/Month`}
+            </CostHighlight>
+            <Tooltip
+              title={
+                <div
+                  style={{
+                    fontFamily: "Work Sans, sans-serif",
+                    fontSize: "12px",
+                    fontWeight: "normal",
+                    padding: "5px 6px",
+                  }}
+                >
+                  EKS cost: ~$70/month <br />
+                  Machine (x3) cost: ~$
+                  {`${3 * costMapping[this.state.awsMachineType]}`}/month <br />
+                  Networking cost: ~$30/month
+                </div>
+              }
+              placement="top"
+            >
+              <StyledInfoTooltip>
+                <i className="material-icons">help_outline</i>
+              </StyledInfoTooltip>
+            </Tooltip>
+          </Helper>
           <InputRow
             type="text"
             value={awsAccessId}
@@ -551,3 +592,25 @@ const CloseButtonImg = styled.img`
   width: 14px;
   margin: 0 auto;
 `;
+
+const CostHighlight = styled.span<{ highlight: boolean }>`
+  background-color: ${(props) => props.highlight && "yellow"};
+`;
+
+const StyledInfoTooltip = styled.div`
+  display: inline-block;
+  position: relative;
+  margin-right: 2px;
+  > i {
+    display: flex;
+    align-items: center;
+    position: absolute;
+    top: -10px;
+    font-size: 10px;
+    color: #858faaaa;
+    cursor: pointer;
+    :hover {
+      color: #aaaabb;
+    }
+  }
+`;

+ 52 - 0
dashboard/src/main/home/provisioner/DOFormSection.tsx

@@ -14,11 +14,14 @@ import Helper from "components/form-components/Helper";
 import Heading from "components/form-components/Heading";
 import SaveButton from "components/SaveButton";
 import CheckboxList from "components/form-components/CheckboxList";
+import InfoTooltip from "../../../components/InfoTooltip";
+import Tooltip from "@material-ui/core/Tooltip";
 
 type PropsType = {
   setSelectedProvisioner: (x: string | null) => void;
   handleError: () => void;
   projectName: string;
+  highlightCosts?: boolean;
   infras: InfraType[];
 };
 
@@ -277,6 +280,33 @@ export default class DOFormSection extends Component<PropsType, StateType> {
             </Highlight>
             .
           </Helper>
+          <Helper>
+            Estimated Cost:{" "}
+            <CostHighlight highlight={this.props.highlightCosts}>
+              $90/Month
+            </CostHighlight>
+            <Tooltip
+              title={
+                <div
+                  style={{
+                    fontFamily: "Work Sans, sans-serif",
+                    fontSize: "12px",
+                    fontWeight: "normal",
+                    padding: "5px 6px",
+                  }}
+                >
+                  Cluster cost: ~$10/month <br />
+                  Machine (x3) cost: ~$60/month <br />
+                  Networking cost: ~$20/month
+                </div>
+              }
+              placement="top"
+            >
+              <StyledInfoTooltip>
+                <i className="material-icons">help_outline</i>
+              </StyledInfoTooltip>
+            </Tooltip>
+          </Helper>
           <CheckboxRow
             isRequired={true}
             checked={this.state.provisionConfirmed}
@@ -388,3 +418,25 @@ const CloseButtonImg = styled.img`
   width: 14px;
   margin: 0 auto;
 `;
+
+const CostHighlight = styled.span<{ highlight: boolean }>`
+  background-color: ${(props) => props.highlight && "yellow"};
+`;
+
+const StyledInfoTooltip = styled.div`
+  display: inline-block;
+  position: relative;
+  margin-right: 2px;
+  > i {
+    display: flex;
+    align-items: center;
+    position: absolute;
+    top: -10px;
+    font-size: 10px;
+    color: #858faaaa;
+    cursor: pointer;
+    :hover {
+      color: #aaaabb;
+    }
+  }
+`;

+ 53 - 2
dashboard/src/main/home/provisioner/GCPFormSection.tsx

@@ -17,11 +17,13 @@ import Heading from "components/form-components/Heading";
 import SaveButton from "components/SaveButton";
 import CheckboxList from "components/form-components/CheckboxList";
 import { RouteComponentProps, withRouter } from "react-router";
+import Tooltip from "@material-ui/core/Tooltip";
 
 type PropsType = RouteComponentProps & {
   setSelectedProvisioner: (x: string | null) => void;
   handleError: () => void;
   projectName: string;
+  highlightCosts?: boolean;
   infras: InfraType[];
 };
 
@@ -377,8 +379,8 @@ class GCPFormSection extends Component<PropsType, StateType> {
           />
           {this.renderClusterNameSection()}
           <Helper>
-            By default, Porter creates a cluster with three e2-medium instances
-            (2vCPUs and 4GB RAM each). Google Cloud will bill you for any
+            By default, Porter creates a cluster with three custom-2-4096
+            instances (2 CPU, 4 GB RAM each). Google Cloud will bill you for any
             provisioned resources. Learn more about GKE pricing
             <Highlight
               href="https://cloud.google.com/kubernetes-engine/pricing"
@@ -388,6 +390,33 @@ class GCPFormSection extends Component<PropsType, StateType> {
             </Highlight>
             .
           </Helper>
+          <Helper>
+            Estimated Cost:{" "}
+            <CostHighlight highlight={this.props.highlightCosts}>
+              $250/Month
+            </CostHighlight>
+            <Tooltip
+              title={
+                <div
+                  style={{
+                    fontFamily: "Work Sans, sans-serif",
+                    fontSize: "12px",
+                    fontWeight: "normal",
+                    padding: "5px 6px",
+                  }}
+                >
+                  GKE cost: ~$70/month <br />
+                  Machine (x3) cost: ~$150/month <br />
+                  Networking cost: ~$30/month
+                </div>
+              }
+              placement="top"
+            >
+              <StyledInfoTooltip>
+                <i className="material-icons">help_outline</i>
+              </StyledInfoTooltip>
+            </Tooltip>
+          </Helper>
           <CheckboxRow
             isRequired={true}
             checked={this.state.provisionConfirmed}
@@ -503,3 +532,25 @@ const CloseButtonImg = styled.img`
   width: 14px;
   margin: 0 auto;
 `;
+
+const CostHighlight = styled.span<{ highlight: boolean }>`
+  background-color: ${(props) => props.highlight && "yellow"};
+`;
+
+const StyledInfoTooltip = styled.div`
+  display: inline-block;
+  position: relative;
+  margin-right: 2px;
+  > i {
+    display: flex;
+    align-items: center;
+    position: absolute;
+    top: -10px;
+    font-size: 10px;
+    color: #858faaaa;
+    cursor: pointer;
+    :hover {
+      color: #aaaabb;
+    }
+  }
+`;

+ 29 - 1
dashboard/src/main/home/provisioner/ProvisionerSettings.tsx

@@ -13,6 +13,7 @@ import SaveButton from "components/SaveButton";
 import ExistingClusterSection from "./ExistingClusterSection";
 import { RouteComponentProps, withRouter } from "react-router";
 import { pushFiltered } from "shared/routing";
+import InfoTooltip from "../../../components/InfoTooltip";
 
 type PropsType = RouteComponentProps & {
   isInNewProject?: boolean;
@@ -23,6 +24,7 @@ type PropsType = RouteComponentProps & {
 
 type StateType = {
   selectedProvider: string | null;
+  highlightCosts: boolean;
   infras: InfraType[];
 };
 
@@ -31,6 +33,7 @@ const providers = ["aws", "gcp", "do"];
 class NewProject extends Component<PropsType, StateType> {
   state = {
     selectedProvider: null as string | null,
+    highlightCosts: true,
     infras: [] as InfraType[],
   };
 
@@ -95,6 +98,7 @@ class NewProject extends Component<PropsType, StateType> {
             handleError={this.handleError}
             projectName={projectName}
             infras={infras}
+            highlightCosts={this.state.highlightCosts}
             setSelectedProvisioner={(x: string | null) => {
               this.setState({ selectedProvider: x });
             }}
@@ -108,6 +112,7 @@ class NewProject extends Component<PropsType, StateType> {
             handleError={this.handleError}
             projectName={projectName}
             infras={infras}
+            highlightCosts={this.state.highlightCosts}
             setSelectedProvisioner={(x: string | null) => {
               this.setState({ selectedProvider: x });
             }}
@@ -121,6 +126,7 @@ class NewProject extends Component<PropsType, StateType> {
             handleError={this.handleError}
             projectName={projectName}
             infras={infras}
+            highlightCosts={this.state.highlightCosts}
             setSelectedProvisioner={(x: string | null) => {
               this.setState({ selectedProvider: x });
             }}
@@ -214,11 +220,28 @@ class NewProject extends Component<PropsType, StateType> {
                 <Block
                   key={i}
                   onClick={() => {
-                    this.setState({ selectedProvider: provider });
+                    this.setState({
+                      selectedProvider: provider,
+                      highlightCosts: false,
+                    });
                   }}
                 >
                   <Icon src={providerInfo.icon} />
                   <BlockTitle>{providerInfo.label}</BlockTitle>
+                  <CostSection
+                    onClick={(e) => {
+                      e.stopPropagation();
+                      this.setState({
+                        selectedProvider: provider,
+                        highlightCosts: true,
+                      });
+                    }}
+                  >
+                    {provider == "aws" && "$205/Month"}
+                    {provider == "gcp" && "$250/Month"}
+                    {provider == "do" && "$90/Month"}
+                    <InfoTooltip text={""} />
+                  </CostSection>
                   <BlockDescription>Hosted in your own cloud.</BlockDescription>
                 </Block>
               );
@@ -335,3 +358,8 @@ const Block = styled.div<{ disabled?: boolean }>`
     }
   }
 `;
+
+const CostSection = styled.p`
+  position: absolute;
+  left: 0;
+`;