Browse Source

refactor preflight checks so we can call them elsewhere (#4653)

Feroze Mohideen 2 years ago
parent
commit
e2fe66dcac

+ 85 - 70
dashboard/src/lib/hooks/useCluster.ts

@@ -1,5 +1,9 @@
 import { useContext, useState } from "react";
-import { Contract, PreflightCheckRequest } from "@porter-dev/api-contracts";
+import {
+  Contract,
+  EnumCloudProvider,
+  PreflightCheckRequest,
+} from "@porter-dev/api-contracts";
 import { useQuery } from "@tanstack/react-query";
 import axios from "axios";
 import { match } from "ts-pattern";
@@ -334,6 +338,80 @@ export const useClusterState = ({
   };
 };
 
+export const preflightChecks = async (
+  contract: Contract,
+  projectId: number
+): Promise<UpdateClusterResponse["preflightChecks"]> => {
+  if (!contract.cluster) {
+    throw new Error("Cluster is missing");
+  }
+
+  let preflightCheckResp;
+  if (
+    contract.cluster.cloudProvider === EnumCloudProvider.AWS ||
+    contract.cluster.cloudProvider === EnumCloudProvider.AZURE
+  ) {
+    preflightCheckResp = await api.cloudContractPreflightCheck(
+      "<token>",
+      contract,
+      {
+        project_id: projectId,
+      }
+    );
+  } else {
+    preflightCheckResp = await api.legacyPreflightCheck(
+      "<token>",
+      new PreflightCheckRequest({
+        contract,
+      }),
+      {
+        id: projectId,
+      }
+    );
+  }
+
+  const parsed = await preflightCheckValidator.parseAsync(
+    preflightCheckResp.data
+  );
+
+  if (parsed.errors.length > 0) {
+    const cloudProviderSpecificChecks = match(contract.cluster.cloudProvider)
+      .with(EnumCloudProvider.AWS, () => CloudProviderAWS.preflightChecks)
+      .with(EnumCloudProvider.GCP, () => CloudProviderGCP.preflightChecks)
+      .with(EnumCloudProvider.AZURE, () => CloudProviderAzure.preflightChecks)
+      .otherwise(() => []);
+
+    return parsed.errors.map((e) => {
+      return match(
+        cloudProviderSpecificChecks.find(
+          (cloudProviderCheck) => e.name === cloudProviderCheck.name
+        )
+      )
+        .returnType<ClientPreflightCheck>()
+        .with(undefined, () => ({
+          title: "Unknown preflight check",
+          status: "failure" as const,
+          name: "UNKNOWN" as const,
+          error: {
+            detail:
+              "Your cloud provider returned an unknown error. Please reach out to Porter support.",
+            metadata: {},
+          },
+        }))
+        .otherwise((preflightCheckMatch) => ({
+          title: preflightCheckMatch.displayName,
+          status: "failure" as const,
+          name: preflightCheckMatch.name,
+          error: {
+            detail: e.error.message,
+            metadata: e.error.metadata,
+            resolution: preflightCheckMatch.resolution,
+          },
+        }));
+    });
+  }
+};
+
 type TUseUpdateCluster = {
   updateCluster: (
     clientContract: ClientClusterContract,
@@ -343,6 +421,7 @@ type TUseUpdateCluster = {
   isHandlingPreflightChecks: boolean;
   isCreatingContract: boolean;
 };
+
 export const useUpdateCluster = ({
   projectId,
 }: {
@@ -374,76 +453,12 @@ export const useUpdateCluster = ({
     if (!skipPreflightChecks) {
       setIsHandlingPreflightChecks(true);
       try {
-        let preflightCheckResp;
-        if (
-          clientContract.cluster.cloudProvider === "AWS" ||
-          clientContract.cluster.cloudProvider === "Azure"
-        ) {
-          preflightCheckResp = await api.cloudContractPreflightCheck(
-            "<token>",
-            newContract,
-            {
-              project_id: projectId,
-            }
-          );
-        } else {
-          preflightCheckResp = await api.legacyPreflightCheck(
-            "<token>",
-            new PreflightCheckRequest({
-              contract: newContract,
-            }),
-            {
-              id: projectId,
-            }
-          );
-        }
-
-        const parsed = await preflightCheckValidator.parseAsync(
-          preflightCheckResp.data
+        const preflightCheckResults = await preflightChecks(
+          newContract,
+          projectId
         );
-
-        if (parsed.errors.length > 0) {
-          const cloudProviderSpecificChecks = match(
-            clientContract.cluster.cloudProvider
-          )
-            .with("AWS", () => CloudProviderAWS.preflightChecks)
-            .with("GCP", () => CloudProviderGCP.preflightChecks)
-            .with("Azure", () => CloudProviderAzure.preflightChecks)
-            .otherwise(() => []);
-
-          const clientPreflightChecks: ClientPreflightCheck[] = parsed.errors
-            .map((e) => {
-              const preflightCheckMatch = cloudProviderSpecificChecks.find(
-                (cloudProviderCheck) => e.name === cloudProviderCheck.name
-              );
-              if (!preflightCheckMatch) {
-                return {
-                  title: "Unknown preflight check",
-                  status: "failure" as const,
-                  name: "UNKNOWN" as const,
-                  error: {
-                    detail:
-                      "Your cloud provider returned an unknown error. Please reach out to Porter support.",
-                    metadata: {},
-                  },
-                };
-              }
-              return {
-                title: preflightCheckMatch.displayName,
-                status: "failure" as const,
-                name: preflightCheckMatch.name,
-                error: {
-                  detail: e.error.message,
-                  metadata: e.error.metadata,
-                  resolution: preflightCheckMatch.resolution,
-                },
-              };
-            })
-            .filter(valueExists);
-
-          return {
-            preflightChecks: clientPreflightChecks,
-          };
+        if (preflightCheckResults) {
+          return { preflightChecks: preflightCheckResults };
         }
         // otherwise, continue to create the contract
       } catch (err) {

+ 5 - 5
dashboard/src/main/home/infrastructure-dashboard/modals/PreflightChecksModal.tsx

@@ -122,7 +122,7 @@ const PreflightChecksModal: React.FC<Props> = ({
   );
 
   const acceptChanges = async (): Promise<void> => {
-    void submitAndPatchCheckSuggestions({
+    await submitAndPatchCheckSuggestions({
       preflightChecks: checksWithSuggestions,
     });
     onClose();
@@ -140,8 +140,8 @@ const PreflightChecksModal: React.FC<Props> = ({
         </Text>
         <PorterOperatorComponent>
           <Button
-            onClick={async () => {
-              await submitSkippingPreflightChecks();
+            onClick={() => {
+              void submitSkippingPreflightChecks();
             }}
             color="red"
           >
@@ -162,8 +162,8 @@ const PreflightChecksModal: React.FC<Props> = ({
         <ButtonContainer>
           {allHaveSuggestions ? (
             <Button
-              onClick={async () => {
-                await acceptChanges();
+              onClick={() => {
+                void acceptChanges();
               }}
             >
               <Icon src={file_diff} height={"15px"} />