Ver Fonte

Update Provisioning Buttons (#3479)

sdess09 há 2 anos atrás
pai
commit
b871f57dab

+ 30 - 9
dashboard/src/components/AzureProvisionerSettings.tsx

@@ -37,7 +37,7 @@ const machineTypeOptions = [
   { value: "Standard_A4_v2", label: "Standard_A4_v2" },
 ];
 
-const clusterVersionOptions = [{ value: "v1.26.6", label: "v1.26.6" },{ value: "v1.24.9", label: "v1.24.9" }];
+const clusterVersionOptions = [{ value: "v1.26.6", label: "v1.26.6" }, { value: "v1.24.9", label: "v1.24.9" }];
 
 type Props = RouteComponentProps & {
   selectedClusterVersion?: Contract;
@@ -102,15 +102,15 @@ const AzureProvisionerSettings: React.FC<Props> = (props) => {
 
   const isDisabled = () => {
     return (
-      !user.email.endsWith("porter.run") &&
-      ((!clusterName && true) ||
-        (isReadOnly && props.provisionerError === "") ||
-        props.provisionerError === "" ||
-        currentCluster?.status === "UPDATING" ||
-        isClicked)
-    );
+      (!clusterName && true)
+      || (isReadOnly && props.provisionerError === "")
+      || currentCluster?.status === "UPDATING"
+      || isClicked
+      || (!currentProject?.enable_reprovision && props.clusterId)
+    )
   };
 
+
   const validateInputs = (): string => {
     if (!clusterName) {
       return "Cluster name is required";
@@ -128,7 +128,7 @@ const AzureProvisionerSettings: React.FC<Props> = (props) => {
       return "VPC CIDR range must be in the format of [0-255].[0-255].0.0/16";
     }
     if (clusterVersion == "v1.24.9") {
-        return "Cluster version v1.24.9 is no longer supported";
+      return "Cluster version v1.24.9 is no longer supported";
     }
 
     return "";
@@ -381,6 +381,27 @@ const AzureProvisionerSettings: React.FC<Props> = (props) => {
       >
         Provision
       </Button>
+      {
+        (!currentProject?.enable_reprovision && currentCluster) &&
+        <>
+          <Spacer y={1} />
+          <Text>Updates to the cluster are disabled on this project. Enable re-provisioning by contacting <a href="mailto:support@porter.run">Porter Support</a>.</Text>
+        </>
+      }
+      {user.isPorterUser &&
+        <>
+
+          <Spacer y={1} />
+          <Text color="yellow">Visible to Admin Only</Text>
+          <Button
+            color="red"
+            onClick={createCluster}
+            status={getStatus()}
+          >
+            Override Provision
+          </Button>
+        </>
+      }
     </>
   );
 };

+ 59 - 74
dashboard/src/components/GCPProvisionerSettings.tsx

@@ -38,6 +38,7 @@ import Fieldset from "./porter/Fieldset";
 import ExpandableSection from "./porter/ExpandableSection";
 import PreflightChecks from "./PreflightChecks";
 
+
 const locationOptions = [
   { value: "us-east1", label: "us-east1" },
 ];
@@ -98,6 +99,9 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
   };
 
   const getStatus = () => {
+    if (isLoading) {
+      return <Loading />
+    }
     if (isReadOnly && props.provisionerError == "") {
       return "Provisioning is still in progress...";
     } else if (errorMessage !== "") {
@@ -118,13 +122,12 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
 
   const isDisabled = () => {
     return (
-      !user.email.endsWith("porter.run") &&
-      ((!clusterName && true) ||
-        (isReadOnly && props.provisionerError === "") ||
-        props.provisionerError === "" ||
-        currentCluster?.status === "UPDATING" ||
-        isClicked)
-    );
+      (!clusterName && true)
+      || (isReadOnly && props.provisionerError === "")
+      || currentCluster?.status === "UPDATING"
+      || isClicked
+      || (!currentProject?.enable_reprovision && props.clusterId)
+    )
   };
 
   const validateInputs = (): string => {
@@ -192,12 +195,14 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
   }
 
   const createCluster = async () => {
+
     const err = validateInputs();
     if (err !== "") {
       setErrorMessage(err)
       setErrorDetails("")
       return;
     }
+    setIsLoading(true);
 
     setIsClicked(true);
     var data = new Contract({
@@ -290,15 +295,21 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
       } catch (err) {
         const errMessage = err.response.data.error.replace("unknown: ", "");
         setIsClicked(false);
+        setIsLoading(true);
+
         // TODO: handle different error conditions here from preflights
         setErrorMessage(DEFAULT_ERROR_MESSAGE);
         setErrorDetails(errMessage)
       } finally {
         setIsReadOnly(false);
         setIsClicked(false);
+        setIsLoading(true);
+
       }
     } else {
       setIsClicked(false);
+      setIsLoading(true);
+
       // TODO: handle different error conditions here from preflights
       setErrorMessage(DEFAULT_ERROR_MESSAGE);
       setErrorDetails("Could not perform Preflight Checks ")
@@ -321,8 +332,8 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
   useEffect(() => {
     const contract = props.selectedClusterVersion as any;
     if (contract?.cluster) {
-      if (contract.cluster.gkeKind.nodePools) {
-        contract.cluster.gkeKind.nodePools.map((nodePool: any) => {
+      if (contract.cluster?.gkeKind?.nodePools) {
+        contract.cluster?.gkeKind?.nodePools.map((nodePool: any) => {
           if (nodePool.nodePoolType === "NODE_POOL_TYPE_APPLICATION") {
             setMinInstances(nodePool.minInstances);
             setMaxInstances(nodePool.maxInstances);
@@ -330,11 +341,11 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
         });
       }
       setCreateStatus("");
-      setClusterName(contract.cluster.gkeKind.clusterName);
-      setRegion(contract.cluster.gkeKind.region);
-      setClusterVersion(contract.cluster.gkeKind.clusterVersion);
+      setClusterName(contract.cluster.gkeKind?.clusterName);
+      setRegion(contract.cluster.gkeKind?.region);
+      setClusterVersion(contract.cluster.gkeKind?.clusterVersion);
       let cn = new GKENetwork({
-        cidrRange: contract.cluster.gkeKind.clusterNetworking?.cidrRange || defaultClusterNetworking.cidrRange,
+        cidrRange: contract.cluster.gkeKind?.clusterNetworking?.cidrRange || defaultClusterNetworking.cidrRange,
         controlPlaneCidr: defaultClusterNetworking.controlPlaneCidr,
         podCidr: defaultClusterNetworking.podCidr,
         serviceCidr: defaultClusterNetworking.serviceCidr,
@@ -461,6 +472,30 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
       >
         Provision
       </Button>
+
+      {
+        (!currentProject?.enable_reprovision && props.clusterId) &&
+        <>
+          <Spacer y={1} />
+          <Text>Updates to the cluster are disabled on this project. Enable re-provisioning by contacting <a href="mailto:support@porter.run">Porter Support</a>.</Text>
+        </>
+      }
+
+      {user.isPorterUser &&
+        <>
+
+          <Spacer y={1} />
+          <Text color="yellow">Visible to Admin Only</Text>
+          <Button
+            color="red"
+            onClick={createCluster}
+            status={getStatus()}
+          >
+            Override Provision
+          </Button>
+        </>
+      }
+
     </>
   );
 };
@@ -488,65 +523,15 @@ const errorMessageToModal = (errorMessage: string) => {
   }
 };
 
-const AppearingDiv = styled.div<{ color?: string }>`
-        animation: floatIn 0.5s;
-        animation-fill-mode: forwards;
-        display: flex;
-        flex-direction: column;
-        color: ${(props) => props.color || "#ffffff44"};
-        margin-left: 10px;
-        @keyframes floatIn {
-          from {
-          opacity: 0;
-        transform: translateY(20px);
-    }
-        to {
-          opacity: 1;
-        transform: translateY(0px);
-    }
-  }
-        `;
-const StatusIcon = styled.img`
-        height: 14px;
-        `;
-
-const CheckItemContainer = styled.div`
-        display: flex;
-        flex-direction: column;
-        border: 1px solid ${props => props.theme.border};
-        border-radius: 5px;
-        font-size: 13px;
-        width: 100%;
-        margin-bottom: 10px;
-        padding-left: 10px;
-        cursor: ${props => (props.hasMessage ? 'pointer' : 'default')};
-        background: ${props => props.theme.clickable.bg};
-
-        `;
-
-const CheckItemTop = styled.div`
-        display: flex;
-        align-items: center;
-        padding: 10px;
-        background: ${props => props.theme.clickable.bg};
-        `;
-
-const ExpandIcon = styled.i<{ isExpanded: boolean }>`
-        margin-left: 8px;
-        color: #ffffff66;
-        font-size: 20px;
-        cursor: pointer;
-        border-radius: 20px;
-        transform: ${props => props.isExpanded ? "" : "rotate(-90deg)"};
-        `; const ExpandHeader = styled.div<{ isExpanded: boolean }>`
-        display: flex;
-        align-items: center;
-        cursor: pointer;
-        > i {
-          margin-right: 7px;
-          margin-left: -7px;
-          transform: ${(props) =>
+const ExpandHeader = styled.div<{ isExpanded: boolean }>`
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+  > i {
+    margin-right: 7px;
+    margin-left: -7px;
+    transform: ${(props) =>
     props.isExpanded ? "rotate(0deg)" : "rotate(-90deg)"};
-          transition: transform 0.1s ease;
-        }
-      `;
+    transition: transform 0.1s ease;
+  }
+`;

+ 27 - 9
dashboard/src/components/ProvisionerSettings.tsx

@@ -39,6 +39,7 @@ import Tooltip from "./porter/Tooltip";
 import Icon from "./porter/Icon";
 import { set } from "traverse";
 import { load } from "js-yaml";
+import Loading from "./Loading";
 const regionOptions = [
   { value: "us-east-1", label: "US East (N. Virginia) us-east-1" },
   { value: "us-east-2", label: "US East (Ohio) us-east-2" },
@@ -130,6 +131,8 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
   const [isReadOnly, setIsReadOnly] = useState(false);
   const [errorMessage, setErrorMessage] = useState<string>(undefined);
   const [isClicked, setIsClicked] = useState(false);
+  const [isLoading, setIsLoading] = useState(false);
+
   const markStepStarted = async (step: string, errMessage?: string) => {
     try {
       await api.updateOnboardingStep(
@@ -149,6 +152,9 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
   };
 
   const getStatus = () => {
+    if (isLoading) {
+      return <Loading />
+    }
     if (isReadOnly && props.provisionerError == "") {
       return "Provisioning is still in progress...";
     } else if (errorMessage) {
@@ -218,9 +224,8 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
 
   const isDisabled = () => {
     return (
-      !user?.isPorterUser &&
-      (clusterNameDoesNotExist() || userProvisioning() || isClicked)
-    );
+      (clusterNameDoesNotExist() || userProvisioning() || isClicked || (currentCluster && !currentProject?.enable_reprovision)
+      ))
   };
   function convertStringToTags(tagString) {
     if (typeof tagString !== "string" || tagString.trim() === "") {
@@ -239,6 +244,7 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
     return tags;
   }
   const createCluster = async () => {
+    setIsLoading(true);
     setIsClicked(true);
 
     let loadBalancerObj = new LoadBalancer({});
@@ -371,6 +377,7 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
       const errMessage = err.response.data?.error.replace("unknown: ", "");
       // hacky, need to standardize error contract with backend
       setIsClicked(false);
+      setIsLoading(false)
       if (errMessage.includes("elastic IP")) {
         setErrorMessage(AWS_EIP_QUOTA_ERROR_MESSAGE);
       } else if (errMessage.includes("VPC")) {
@@ -387,6 +394,8 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
       markStepStarted("provisioning-failed", errMessage);
     } finally {
       setIsReadOnly(false);
+      setIsLoading(false);
+
       setIsClicked(false);
     }
   };
@@ -963,18 +972,27 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
       <Button
         // disabled={isDisabled()}
         disabled={
-          user?.email === "admin@porter.run" ||
-            currentProject?.enable_reprovision
-            ? false
-            : currentCluster
-              ? true
-              : isDisabled()
+          isDisabled()
         }
         onClick={createCluster}
         status={getStatus()}
       >
         Provision
       </Button>
+      {user.isPorterUser &&
+        <>
+
+          <Spacer y={1} />
+          <Text color="yellow">Visible to Admin Only</Text>
+          <Button
+            color="red"
+            onClick={createCluster}
+            status={getStatus()}
+          >
+            Override Provision
+          </Button>
+        </>
+      }
     </>
   );
 };

+ 3 - 2
dashboard/src/main/home/sidebar/ProjectSelectionModal.tsx

@@ -105,13 +105,14 @@ const ProjectSelectionModal: React.FC<Props> = ({
             if (clusters_list?.length > 0) {
               setCurrentCluster(clusters_list[0]);
               if (project.simplified_view_enabled) {
-                pushFiltered(props, "/onboarding/source", ["project_id"], {});
+                console.log("HERE BITCH")
+                pushFiltered(props, "/apps", ["project_id"], {});
               }
               else {
                 pushFiltered(props, "/applications", ["project_id"], {});
               }
             } else {
-              pushFiltered(props, "/onboarding", ["project_id"], {});
+              pushFiltered(props, "/apps", ["project_id"], {});
             }
             closeModal();
           }}