Parcourir la source

Fix GCP Preflight Checks (#3613)

sdess09 il y a 2 ans
Parent
commit
5057b95f82

+ 59 - 39
dashboard/src/components/GCPCredentialsForm.tsx

@@ -12,6 +12,9 @@ import Text from "components/porter/Text";
 import Button from "components/porter/Button";
 import Spacer from "./porter/Spacer";
 import Container from "./porter/Container";
+import VerticalSteps from "./porter/VerticalSteps";
+import Link from "./porter/Link";
+import { Flex } from "main/home/cluster-dashboard/stacks/components/styles";
 
 
 type Props = {
@@ -28,8 +31,7 @@ const GCPCredentialsForm: React.FC<Props> = ({ goBack, proceed }) => {
   const [errorMessage, setErrorMessage] = useState("");
   const [detected, setDetected] = useState<Detected | undefined>(undefined);
   const [gcpCloudProviderCredentialID, setGCPCloudProviderCredentialId] = useState<string>("")
-
-
+  const [step, setStep] = useState(0);
   useEffect(() => {
     setDetected(undefined);
   }, []);
@@ -133,7 +135,9 @@ const GCPCredentialsForm: React.FC<Props> = ({ goBack, proceed }) => {
     setIsContinueEnabled(true);
   }
 
-
+  const incrementStep = () => {
+    setStep(step + 1)
+  }
 
   return (
     <>
@@ -146,44 +150,59 @@ const GCPCredentialsForm: React.FC<Props> = ({ goBack, proceed }) => {
         <Img src={gcp} />
         Set GKE credentials
       </Container>
-      <Helper>Service account credentials for GCP permissions.</Helper>
-      <UploadArea
-        setValue={(x: string) => handleLoadJSON(x)}
-        label="🔒 GCP Key Data (JSON)"
-        placeholder="Drag a GCP Service Account JSON here, or click to browse."
-        width="100%"
-        height="100%"
-        isRequired={true}
-      />
-
-      {detected && serviceAccountKey && (<>
-
-
-        <>
-          <AppearingDiv color={projectId ? "#8590ff" : "#fcba03"}>
-            {detected.detected ? (
+      <Spacer y={1} />
+      <VerticalSteps
+        currentStep={step}
+        steps={[
+          <>
+            <Text size={16}> Create the service account </Text>
+            <Spacer y={.5} />
+            <Link onClick={incrementStep} to="https://docs.porter.run/standard/getting-started/provisioning-on-gcp" target="_blank">
+              Follow the steps in the Porter docs to generate your service account credentials
+            </Link>
+            <Spacer y={.5} />
+            <Button onClick={incrementStep} height={"15px"} disabled={step > 1}>Continue</Button>
+          </>,
+          <>
+            <Text size={16}>Upload service account credentials</Text>
+            <Spacer y={1} />
+            <UploadArea
+              setValue={(x: string) => handleLoadJSON(x)}
+              label="🔒 GCP Key Data (JSON)"
+              placeholder="Drag a GCP Service Account JSON here, or click to browse."
+              width="100%"
+              height="100%"
+              isRequired={true}
+            />
+
+            {detected && serviceAccountKey && (<>
               <>
-                <I className="material-icons">check</I>
+                <AppearingDiv color={projectId ? "#8590ff" : "#fcba03"}>
+                  {detected.detected ? (
+                    <>
+                      {incrementStep}
+                      <I className="material-icons">check</I>
+                    </>
+                  ) : (
+                    <I className="material-icons">error</I>
+                  )}
+
+                  <Text color={detected.detected ? "#8590ff" : "#fcba03"}>
+                    {detected.message}
+                  </Text>
+                </AppearingDiv>
+                <Spacer y={1} />
               </>
-            ) : (
-              <I className="material-icons">error</I>
+            </>
             )}
-
-            <Text color={detected.detected ? "#8590ff" : "#fcba03"}>
-              {detected.message}
-            </Text>
-          </AppearingDiv>
-          <Spacer y={1} />
-        </>
-      </>
-      )}
-
-      <Spacer y={0.5} />
-      <Button
-        disabled={!isContinueEnabled || isLoading}
-        onClick={saveCredentials}
-      >Continue</Button>
-
+            <Spacer y={0.5} />
+            <Button
+              disabled={!isContinueEnabled || isLoading}
+              onClick={saveCredentials}
+            >Continue</Button>
+          </>
+        ].filter((x) => x)}
+      />
     </>
   );
 };
@@ -266,4 +285,5 @@ const StatusIcon = styled.img`
         top: 20px;
         right: 20px;
         height: 18px;
-        `;
+        `;
+

+ 56 - 47
dashboard/src/components/GCPProvisionerSettings.tsx

@@ -90,6 +90,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
   const [preflightFailed, setPreflightFailed] = useState<boolean>(true)
   const [isLoading, setIsLoading] = useState(false);
   const [isExpanded, setIsExpanded] = useState(false);
+  const [preflightError, setPreflightError] = useState<string>("")
 
   const markStepStarted = async (step: string, region?: string) => {
     try {
@@ -218,7 +219,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
     setIsLoading(true);
 
     setIsClicked(true);
-    
+
 
     try {
       window.dataLayer?.push({
@@ -231,7 +232,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
     } catch (err) {
       console.log(err);
     }
-    
+
     var data = new Contract({
       cluster: new Cluster({
         projectId: currentProject.id,
@@ -384,57 +385,65 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
   useEffect(() => {
     if (statusPreflight() == "" && !props.clusterId) {
       setStep(1)
-      setPreflightData(null)
+
       preflightChecks()
     }
 
   }, [props.selectedClusterVersion, clusterNetworking, region]);
 
   const preflightChecks = async () => {
-    setIsLoading(true);
-    setPreflightData(null);
-    var data = new PreflightCheckRequest({
-      projectId: BigInt(currentProject.id),
-      cloudProvider: EnumCloudProvider.GCP,
-      cloudProviderCredentialsId: props.credentialId,
-      preflightValues: {
-        case: "gkePreflightValues",
-        value: new GKEPreflightValues({
-          network: new GKENetwork({
-            cidrRange: clusterNetworking.cidrRange || defaultClusterNetworking.cidrRange,
-            controlPlaneCidr: defaultClusterNetworking.controlPlaneCidr,
-            podCidr: defaultClusterNetworking.podCidr,
-            serviceCidr: defaultClusterNetworking.serviceCidr,
+
+    try {
+      setIsLoading(true);
+      setPreflightData(null);
+      setPreflightFailed(true)
+      setPreflightError("");
+      var data = new PreflightCheckRequest({
+        projectId: BigInt(currentProject.id),
+        cloudProvider: EnumCloudProvider.GCP,
+        cloudProviderCredentialsId: props.credentialId,
+        preflightValues: {
+          case: "gkePreflightValues",
+          value: new GKEPreflightValues({
+            network: new GKENetwork({
+              cidrRange: clusterNetworking.cidrRange || defaultClusterNetworking.cidrRange,
+              controlPlaneCidr: defaultClusterNetworking.controlPlaneCidr,
+              podCidr: defaultClusterNetworking.podCidr,
+              serviceCidr: defaultClusterNetworking.serviceCidr,
+            })
           })
-        })
+        }
+      });
+      const preflightDataResp = await api.preflightCheck(
+        "<token>", data,
+        {
+          id: currentProject.id,
+        }
+      )
+      // Check if any of the preflight checks has a message
+      let hasMessage = false;
+      let errors = "Preflight Checks Failed : ";
+      for (let check in preflightDataResp?.data?.Msg.preflight_checks) {
+        if (preflightDataResp?.data?.Msg.preflight_checks[check]?.message) {
+          hasMessage = true;
+          errors = errors + check + ", "
+        }
       }
-    });
-    const preflightDataResp = await api.preflightCheck(
-      "<token>", data,
-      {
-        id: currentProject.id,
+      // If none of the checks have a message, set setPreflightFailed to false
+      if (hasMessage) {
+        markStepStarted("provisioning-failed", errors);
       }
-    )
-    // Check if any of the preflight checks has a message
-    let hasMessage = false;
-    let errors = "Preflight Checks Failed : ";
-    for (let check in preflightDataResp?.data?.Msg.preflight_checks) {
-      if (preflightDataResp?.data?.Msg.preflight_checks[check]?.message) {
-        hasMessage = true;
-        errors = errors + check + ", "
+      if (!hasMessage) {
+        setPreflightFailed(false);
+        setStep(2);
       }
+      setPreflightData(preflightDataResp?.data?.Msg);
+      setIsLoading(false)
+    } catch (err) {
+      setPreflightError(err)
+      setIsLoading(false)
+      setPreflightFailed(true);
     }
-    // If none of the checks have a message, set setPreflightFailed to false
-    if (hasMessage) {
-      markStepStarted("provisioning-failed", errors);
-    }
-    if (!hasMessage) {
-      setPreflightFailed(false);
-      setStep(2);
-    }
-    setPreflightData(preflightDataResp?.data?.Msg);
-    setIsLoading(false)
-
   }
 
   const renderForm = () => {
@@ -465,13 +474,13 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
 
             </>,
             <>
-              <PreflightChecks provider="GCP" preflightData={preflightData} />
+              <PreflightChecks provider='GCP' preflightData={preflightData} error={preflightError} />
               <Spacer y={.5} />
-              {(preflightFailed && preflightData) &&
+              {(preflightFailed && preflightData || preflightError) &&
                 <>
-                  <Text color="helper">
+                  {!preflightError && <Text color="helper">
                     Preflight checks for the account didn't pass. Please fix the issues and retry.
-                  </Text>
+                  </Text>}
                   < Button
                     // disabled={isDisabled()}
                     disabled={isLoading}
@@ -505,7 +514,7 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
           <SelectRow
             options={locationOptions}
             width="350px"
-            disabled={isReadOnly || true}
+            disabled={isReadOnly || isLoading}
             value={region}
             scrollBuffer={true}
             dropdownMaxHeight="240px"

+ 10 - 1
dashboard/src/components/PreflightChecks.tsx

@@ -100,7 +100,16 @@ const PreflightChecks: React.FC<Props> = (props) => {
       <Spacer y={1} />
       {
         props.error ?
-          <Error message="Selected region is not available for your account. Please select another region" />
+          props.provider === 'AWS' ?
+            <Error message="Selected region is not available for your account. Please select another region" /> :
+            <>
+              <Error message="There is an error with your account. Please ensure billing is enabled or contact Porter Support: support@porter.run" />
+              <Spacer y={.5} />
+              <Link to="https://support.google.com/googleapi/answer/6158867?hl=en" target="_blank">
+                Check to see if billing is enabled on your account
+              </Link>
+              <Spacer y={.5} />
+            </>
           :
           Object.keys(currentMessageConst).map((checkKey) => (
             <PreflightCheckItem key={checkKey} checkKey={checkKey} />

+ 1 - 0
dashboard/src/shared/util.ts

@@ -31,4 +31,5 @@ export const PREFLIGHT_MESSAGE_CONST_AWS = {
 export const PREFLIGHT_MESSAGE_CONST_GCP = {
   "apiEnabled": "APIs enabled on service account",
   "cidrAvailability": "CIDR availability",
+  "iamPermissions:": "IAM permissions",
 }