فهرست منبع

dgtown/azure machines (#4544)

d-g-town 2 سال پیش
والد
کامیت
8300b60201

+ 68 - 0
dashboard/src/lib/hooks/useNodeGroups.ts

@@ -0,0 +1,68 @@
+import { useQuery } from "@tanstack/react-query";
+
+import { useClusterFormContext } from "../../main/home/infrastructure-dashboard/ClusterFormContextProvider";
+import { CloudProviderAzure } from "../clusters/constants";
+import type {
+  AWSRegion,
+  AzureRegion,
+  ClientMachineType,
+  GCPRegion,
+} from "../clusters/types";
+
+type TUseMachineTypeList = {
+  machineTypes: ClientMachineType[];
+  isLoading: boolean;
+};
+export const useMachineTypeList = ({
+  cloudProvider,
+  cloudProviderCredentialIdentifier,
+  region,
+}: {
+  cloudProvider?: string;
+  cloudProviderCredentialIdentifier?: string;
+  region?: AWSRegion | GCPRegion | AzureRegion;
+}): TUseMachineTypeList => {
+  const { availableMachineTypes } = useClusterFormContext();
+
+  const { data: machineTypes = [], isLoading } = useQuery(
+    [
+      "availableMachineTypes",
+      region,
+      cloudProvider,
+      cloudProviderCredentialIdentifier,
+    ],
+    async () => {
+      if (!cloudProvider || !cloudProviderCredentialIdentifier || !region) {
+        return [];
+      }
+      try {
+        const machineTypes = await availableMachineTypes(
+          cloudProvider,
+          cloudProviderCredentialIdentifier,
+          region
+        );
+        const machineTypesNames = machineTypes.map(
+          (machineType) => machineType.name
+        );
+
+        return CloudProviderAzure.machineTypes.filter((mt) =>
+          machineTypesNames.includes(mt.name)
+        );
+      } catch (err) {
+        // fallback to default machine types if api call fails
+        return CloudProviderAzure.machineTypes.filter((mt) =>
+          mt.supportedRegions.includes(region)
+        );
+      }
+    },
+    {
+      enabled:
+        !!cloudProvider && !!cloudProviderCredentialIdentifier && !!region,
+    }
+  );
+
+  return {
+    machineTypes,
+    isLoading,
+  };
+};

+ 16 - 32
dashboard/src/main/home/infrastructure-dashboard/forms/azure/ConfigureAKSCluster.tsx

@@ -1,5 +1,4 @@
 import React, { useContext, useEffect, useState } from "react";
-import { useQuery } from "@tanstack/react-query";
 import { Controller, useFormContext } from "react-hook-form";
 
 import Loading from "components/Loading";
@@ -14,10 +13,10 @@ import { CloudProviderAzure } from "lib/clusters/constants";
 import type {
   ClientClusterContract,
   ClientMachineType,
-  MachineType,
   NodeGroupType,
 } from "lib/clusters/types";
 import { useIntercom } from "lib/hooks/useIntercom";
+import { useMachineTypeList } from "lib/hooks/useNodeGroups";
 
 import { Context } from "shared/Context";
 import { valueExists } from "shared/util";
@@ -29,13 +28,9 @@ import { BackButton, Img } from "../CreateClusterForm";
 
 type Props = {
   goBack: () => void;
-  availableMachineTypes: (region: string) => Promise<MachineType[]>;
 };
 
-const ConfigureAKSCluster: React.FC<Props> = ({
-  goBack,
-  availableMachineTypes,
-}) => {
+const ConfigureAKSCluster: React.FC<Props> = ({ goBack }) => {
   const [currentStep, _setCurrentStep] = useState<number>(100); // hack to show all steps
   const [customSetupRequired, setCustomSetupRequired] =
     useState<boolean>(false);
@@ -63,6 +58,16 @@ const ConfigureAKSCluster: React.FC<Props> = ({
   const region = watch("cluster.config.region");
   const clusterId = watch("cluster.clusterId");
   const nodeGroups = watch("cluster.config.nodeGroups");
+  const cloudProviderCredentialIdentifier = watch(
+    "cluster.cloudProviderCredentialsId"
+  );
+
+  const { machineTypes, isLoading: areMachineTypesLoading } =
+    useMachineTypeList({
+      cloudProvider: "azure",
+      cloudProviderCredentialIdentifier,
+      region,
+    });
 
   const defaultNodeGroupType = (
     nodeGroupType: NodeGroupType,
@@ -124,36 +129,15 @@ const ConfigureAKSCluster: React.FC<Props> = ({
     };
   };
 
-  const { data: machineTypes, status: machineTypesStatus } = useQuery(
-    ["availableMachineTypes", region],
-    async () => {
-      try {
-        const machineTypes = await availableMachineTypes(region);
-        const machineTypesNames = machineTypes.map(
-          (machineType) => machineType.name
-        );
-
-        return CloudProviderAzure.machineTypes.filter((mt) =>
-          machineTypesNames.includes(mt.name)
-        );
-      } catch (err) {
-        // fallback to default machine types if api call fails
-        return CloudProviderAzure.machineTypes.filter((mt) =>
-          mt.supportedRegions.includes(region)
-        );
-      }
-    }
-  );
-
   const regionValid =
-    machineTypesStatus !== "loading" &&
+    !areMachineTypesLoading &&
     machineTypes &&
     (!customSetupRequired || user?.isPorterUser);
 
   useEffect(() => {
     if (
       clusterId || // if cluster has already been provisioned, don't change instance types that have been set
-      machineTypesStatus === "loading" ||
+      areMachineTypesLoading ||
       !machineTypes || // if machine types are still loading, don't change instance types
       !nodeGroups ||
       nodeGroups.length === 0 // wait until node groups are loaded
@@ -188,7 +172,7 @@ const ConfigureAKSCluster: React.FC<Props> = ({
 
     instanceTypeReplaced &&
       setValue(`cluster.config.nodeGroups`, substituteBadInstanceTypes);
-  }, [machineTypes, machineTypesStatus, region]);
+  }, [machineTypes, areMachineTypesLoading, region]);
 
   return (
     <div>
@@ -248,7 +232,7 @@ const ConfigureAKSCluster: React.FC<Props> = ({
                 </Container>
               )}
             />
-            {machineTypesStatus === "loading" ? (
+            {areMachineTypesLoading ? (
               <Container style={{ width: "300px" }}>
                 <Spacer y={1} />
                 <Loading />

+ 1 - 16
dashboard/src/main/home/infrastructure-dashboard/forms/azure/CreateAKSClusterForm.tsx

@@ -3,7 +3,7 @@ import { useFormContext } from "react-hook-form";
 import { match } from "ts-pattern";
 
 import { CloudProviderAzure } from "lib/clusters/constants";
-import { MachineType, type ClientClusterContract } from "lib/clusters/types";
+import { type ClientClusterContract } from "lib/clusters/types";
 import { useClusterAnalytics } from "lib/hooks/useClusterAnalytics";
 
 import { useClusterFormContext } from "../../ClusterFormContextProvider";
@@ -20,20 +20,12 @@ const CreateAKSClusterForm: React.FC<Props> = ({
   projectId,
   projectName,
 }) => {
-  const { availableMachineTypes } = useClusterFormContext();
-
   const [step, setStep] = useState<"permissions" | "cluster">("permissions");
 
   const { setValue, reset } = useFormContext<ClientClusterContract>();
   const { setCurrentContract } = useClusterFormContext();
   const { reportToAnalytics } = useClusterAnalytics();
 
-  const { watch } = useFormContext<ClientClusterContract>();
-
-  const cloudProviderCredentialIdentifier = watch(
-    "cluster.cloudProviderCredentialsId"
-  );
-
   useEffect(() => {
     const truncatedProjectName = projectName
       .substring(0, 24)
@@ -110,13 +102,6 @@ const CreateAKSClusterForm: React.FC<Props> = ({
           setStep("permissions");
           setValue("cluster.cloudProviderCredentialsId", "");
         }}
-        availableMachineTypes={async (region: string) => {
-          return await availableMachineTypes(
-            "azure",
-            cloudProviderCredentialIdentifier,
-            region
-          );
-        }}
       />
     ))
     .exhaustive();

+ 21 - 6
dashboard/src/main/home/infrastructure-dashboard/tabs/overview/AKSClusterOverview.tsx

@@ -1,21 +1,32 @@
 import React from "react";
 import { Controller, useFormContext } from "react-hook-form";
 
+import Loading from "components/Loading";
 import Container from "components/porter/Container";
 import Select from "components/porter/Select";
 import Spacer from "components/porter/Spacer";
 import Text from "components/porter/Text";
 import { CloudProviderAzure } from "lib/clusters/constants";
 import { type ClientClusterContract } from "lib/clusters/types";
+import { useMachineTypeList } from "lib/hooks/useNodeGroups";
 
 import NodeGroups from "../../shared/NodeGroups";
 
 const AKSClusterOverview: React.FC = () => {
   const { control, watch } = useFormContext<ClientClusterContract>();
 
+  const cloudProviderCredentialIdentifier = watch(
+    "cluster.cloudProviderCredentialsId"
+  );
   const region = watch("cluster.config.region");
   const cidrRange = watch("cluster.config.cidrRange");
 
+  const { machineTypes, isLoading } = useMachineTypeList({
+    cloudProvider: "azure",
+    cloudProviderCredentialIdentifier,
+    region,
+  });
+
   return (
     <>
       <Container style={{ width: "300px" }}>
@@ -73,12 +84,16 @@ const AKSClusterOverview: React.FC = () => {
         </a>
       </Text>
       <Spacer y={1} />
-      <NodeGroups
-        availableMachineTypes={CloudProviderAzure.machineTypes.filter((mt) =>
-          mt.supportedRegions.includes(region)
-        )}
-        isDefaultExpanded={false}
-      />
+      {isLoading || !machineTypes ? (
+        <Container style={{ width: "300px" }}>
+          <Loading />
+        </Container>
+      ) : (
+        <NodeGroups
+          availableMachineTypes={machineTypes}
+          isDefaultExpanded={false}
+        />
+      )}
     </>
   );
 };