Przeglądaj źródła

make contract optional (#4372)

Feroze Mohideen 2 lat temu
rodzic
commit
3a1bf2a769

+ 2 - 1
dashboard/src/lib/clusters/types.ts

@@ -292,7 +292,8 @@ export const clusterValidator = z.object({
 export type SerializedCluster = z.infer<typeof clusterValidator>;
 export type ClientCluster = Omit<SerializedCluster, "cloud_provider"> & {
   cloud_provider: ClientCloudProvider;
-  contract: APIContract & {
+  // Contract is optional because some clusters seem to not have one
+  contract?: APIContract & {
     config: ClientClusterContract;
   };
   state?: ClusterState;

+ 12 - 23
dashboard/src/lib/hooks/useCluster.ts

@@ -78,18 +78,18 @@ export const useClusterList = (): TUseClusterList => {
           const latestContract = latestContracts.find(
             (contract) => contract.cluster_id === c.id
           );
-          // if this cluster has no latest contract, don't include it
+          // if this cluster has no latest contract, don't include it in the response
           if (!latestContract) {
-            return undefined;
+            return c;
           }
           const latestClientContract = clientClusterContractFromProto(
             Contract.fromJsonString(atob(latestContract.base64_contract), {
               ignoreUnknownFields: true,
             })
           );
-          // if we can't parse the latest contract, don't include it
+          // if we can't parse the latest contract, don't include it in the response
           if (!latestClientContract) {
-            return undefined;
+            return c;
           }
           return {
             ...c,
@@ -152,23 +152,6 @@ export const useCluster = ({
         return;
       }
 
-      // TODO: refactor this
-      if (currentProject?.sandbox_enabled) {
-        return {
-          ...parsed,
-          cloud_provider: cloudProviderMatch,
-          contract: {
-            config: {
-              cluster: {
-                config: {
-                  kind: "Hosted",
-                },
-              },
-            },
-          },
-        };
-      }
-
       // get the latest contract
       const latestContractsRes = await api.getContracts(
         "<token>",
@@ -180,7 +163,10 @@ export const useCluster = ({
         .parseAsync(latestContractsRes.data);
 
       if (latestContracts.length !== 1) {
-        return;
+        return {
+          ...parsed,
+          cloud_provider: cloudProviderMatch,
+        };
       }
       const latestClientContract = clientClusterContractFromProto(
         Contract.fromJsonString(atob(latestContracts[0].base64_contract), {
@@ -188,7 +174,10 @@ export const useCluster = ({
         })
       );
       if (!latestClientContract) {
-        return;
+        return {
+          ...parsed,
+          cloud_provider: cloudProviderMatch,
+        };
       }
 
       // get the latest state

+ 2 - 2
dashboard/src/main/home/app-dashboard/validate-apply/services-settings/tabs/GPUResources.tsx

@@ -34,14 +34,14 @@ const GPUResources: React.FC<Props> = ({ index }) => {
 
   const canEnableGPU = useMemo(() => {
     return (
-      cluster.contract.config.cluster.config.nodeGroups.some(
+      cluster.contract?.config.cluster.config.nodeGroups.some(
         (ng) => ng.nodeGroupType === "CUSTOM"
       ) && cluster.contract.condition === "SUCCESS"
     );
   }, [cluster]);
 
   const clusterIsUpdating = useMemo(() => {
-    return cluster.contract.condition === "";
+    return cluster.contract?.condition === "";
   }, [cluster]);
 
   return (

+ 1 - 1
dashboard/src/main/home/app-dashboard/validate-apply/services-settings/tabs/Networking.tsx

@@ -39,7 +39,7 @@ const Networking: React.FC<NetworkingProps> = ({
 
   const showDisableTls = useMemo(() => {
     return (
-      cluster.contract.config.cluster.config.kind === "EKS" &&
+      cluster.contract?.config.cluster.config.kind === "EKS" &&
       cluster.contract.config.cluster.config.loadBalancer.type === "ALB"
     );
   }, [cluster]);

+ 1 - 1
dashboard/src/main/home/infrastructure-dashboard/ClusterContextProvider.tsx

@@ -150,7 +150,7 @@ const ClusterContextProvider: React.FC<ClusterContextProviderProps> = ({
   }, [paramsExist, clusterId, currentProject?.id]);
   const isClusterUpdating = useMemo(() => {
     return cluster?.contract?.condition === "" ?? false;
-  }, [cluster?.contract.condition]);
+  }, [cluster?.contract?.condition]);
 
   if (isLoading || !paramsExist) {
     return <Loading />;

+ 40 - 34
dashboard/src/main/home/infrastructure-dashboard/ClusterDashboard.tsx

@@ -171,32 +171,36 @@ const ClusterDashboard: React.FC = () => {
                     <Spacer inline width="11px" />
                     <Text size={14}>{cluster.vanity_name}</Text>
                   </Container>
-                  <Container row>
-                    <Tag hoverable={false}>
+                  {cluster.contract != null && (
+                    <>
+                      <Container row>
+                        <Tag hoverable={false}>
+                          <Container row>
+                            <Icon src={globe} height="13px" />
+                            <Spacer inline x={0.5} />
+                            {cluster.contract.config.cluster.config?.region}
+                          </Container>
+                        </Tag>
+                      </Container>
                       <Container row>
-                        <Icon src={globe} height="13px" />
+                        <StatusDot
+                          status={
+                            cluster.status === "READY" ? "available" : "pending"
+                          }
+                          heightPixels={8}
+                        />
                         <Spacer inline x={0.5} />
-                        {cluster.contract.config.cluster.config?.region}
+                        <Text color="helper">
+                          {cluster.status === "READY" ? "Running" : "Updating"}
+                        </Text>
+                        <Spacer inline x={1} />
+                        <SmallIcon opacity="0.3" src={time} />
+                        <Text size={13} color="#ffffff44">
+                          {readableDate(cluster.contract.updated_at)}
+                        </Text>
                       </Container>
-                    </Tag>
-                  </Container>
-                  <Container row>
-                    <StatusDot
-                      status={
-                        cluster.status === "READY" ? "available" : "pending"
-                      }
-                      heightPixels={8}
-                    />
-                    <Spacer inline x={0.5} />
-                    <Text color="helper">
-                      {cluster.status === "READY" ? "Running" : "Updating"}
-                    </Text>
-                    <Spacer inline x={1} />
-                    <SmallIcon opacity="0.3" src={time} />
-                    <Text size={13} color="#ffffff44">
-                      {readableDate(cluster.contract.updated_at)}
-                    </Text>
-                  </Container>
+                    </>
+                  )}
                 </Block>
               </Link>
             );
@@ -226,19 +230,21 @@ const ClusterDashboard: React.FC = () => {
                   </Container>
                 </Container>
                 <Spacer y={0.5} />
-                <Container row>
+                {cluster.contract != null && (
                   <Container row>
-                    <SmallIcon opacity="0.3" src={globe} />
-                    <Text size={13} color="#ffffff44">
-                      {cluster.contract.config.cluster.config.region}
-                    </Text>
-                    <Spacer inline x={1} />
-                    <SmallIcon opacity="0.3" src={time} />
-                    <Text size={13} color="#ffffff44">
-                      {readableDate(cluster.contract.updated_at)}
-                    </Text>
+                    <Container row>
+                      <SmallIcon opacity="0.3" src={globe} />
+                      <Text size={13} color="#ffffff44">
+                        {cluster.contract.config.cluster.config.region}
+                      </Text>
+                      <Spacer inline x={1} />
+                      <SmallIcon opacity="0.3" src={time} />
+                      <Text size={13} color="#ffffff44">
+                        {readableDate(cluster.contract.updated_at)}
+                      </Text>
+                    </Container>
                   </Container>
-                </Container>
+                )}
               </Row>
             );
           })}

+ 10 - 8
dashboard/src/main/home/infrastructure-dashboard/ClusterHeader.tsx

@@ -26,14 +26,16 @@ const ClusterHeader: React.FC = () => {
         <Text size={21}>{cluster.vanity_name}</Text>
       </Container>
       <Spacer y={0.5} />
-      <CreatedAtContainer>
-        <div style={{ flexShrink: 0 }}>
-          <Text color="#aaaabb66">
-            Updated {readableDate(cluster.contract.updated_at)}
-          </Text>
-        </div>
-        <Spacer y={0.5} />
-      </CreatedAtContainer>
+      {cluster.contract != null && (
+        <CreatedAtContainer>
+          <div style={{ flexShrink: 0 }}>
+            <Text color="#aaaabb66">
+              Updated {readableDate(cluster.contract.updated_at)}
+            </Text>
+          </div>
+          <Spacer y={0.5} />
+        </CreatedAtContainer>
+      )}
       {isClusterUpdating ||
         (applicationNodes.length !== 0 && (
           <>

+ 8 - 6
dashboard/src/main/home/infrastructure-dashboard/ClusterTabs.tsx

@@ -42,12 +42,14 @@ const ClusterTabs: React.FC<Props> = ({ tabParam }) => {
     useClusterFormContext();
 
   useEffect(() => {
-    reset(cluster.contract.config);
-    setCurrentContract(
-      Contract.fromJsonString(atob(cluster.contract.base64_contract), {
-        ignoreUnknownFields: true,
-      })
-    );
+    if (cluster.contract) {
+      reset(cluster.contract.config);
+      setCurrentContract(
+        Contract.fromJsonString(atob(cluster.contract.base64_contract), {
+          ignoreUnknownFields: true,
+        })
+      );
+    }
   }, [cluster]);
 
   const tabs = useMemo(() => {

+ 4 - 0
dashboard/src/main/home/infrastructure-dashboard/tabs/overview/ClusterOverview.tsx

@@ -1,6 +1,7 @@
 import React from "react";
 import { match } from "ts-pattern";
 
+import Fieldset from "components/porter/Fieldset";
 import Spacer from "components/porter/Spacer";
 
 import { useClusterContext } from "../../ClusterContextProvider";
@@ -12,6 +13,9 @@ import GKEClusterOverview from "./GKEClusterOverview";
 const ClusterOverview: React.FC = () => {
   const { cluster, isClusterUpdating } = useClusterContext();
 
+  if (!cluster.contract) {
+    return <Fieldset>Unable to load overview for this cluster.</Fieldset>;
+  }
   return (
     <>
       {match(cluster.contract.config.cluster.config)