Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
CloudWizard.jsx585 linesDownload Raw Back to js
1/////////////////////////////////////////////////////////////2//3// pgAdmin 4 - PostgreSQL Tools4//5// Copyright (C) 2013 - 2024, The pgAdmin Development Team6// This software is released under the PostgreSQL Licence7//8//////////////////////////////////////////////////////////////9 10import gettext from 'sources/gettext';11import url_for from 'sources/url_for';12import React from 'react';13import { Box, Paper } from '@mui/material';14import { makeStyles } from '@mui/styles';15import Wizard from '../../../../static/js/helpers/wizard/Wizard';16import WizardStep from '../../../../static/js/helpers/wizard/WizardStep';17import {FormFooterMessage, MESSAGE_TYPE } from '../../../../static/js/components/FormComponents';18import getApiInstance from '../../../../static/js/api_instance';19import PropTypes from 'prop-types';20import pgAdmin from 'sources/pgadmin';21import {ToggleButtons, FinalSummary} from './cloud_components';22import { PrimaryButton } from '../../../../static/js/components/Buttons';23import {AwsCredentials, AwsInstanceDetails, AwsDatabaseDetails, validateCloudStep1, validateCloudStep2, validateCloudStep3} from './aws';24import {BigAnimalInstance, BigAnimalDatabase, BigAnimalClusterType, validateBigAnimal, validateBigAnimalStep2, validateBigAnimalStep3, validateBigAnimalStep4} from './biganimal';25import { isEmptyString } from 'sources/validators';26import { AWSIcon, BigAnimalIcon, AzureIcon, GoogleCloudIcon } from '../../../../static/js/components/ExternalIcon';27import {AzureCredentials, AzureInstanceDetails, AzureDatabaseDetails, checkClusternameAvailbility, validateAzureStep2, validateAzureStep3} from './azure';28import { GoogleCredentials, GoogleInstanceDetails, GoogleDatabaseDetails, validateGoogleStep2, validateGoogleStep3 } from './google';29import EventBus from '../../../../static/js/helpers/EventBus';30import { CLOUD_PROVIDERS, CLOUD_PROVIDERS_LABELS } from './cloud_constants';31import { LAYOUT_EVENTS } from '../../../../static/js/helpers/Layout';32 33 34const useStyles = makeStyles(() =>35  ({36    messageBox: {37      marginBottom: '1em',38      display: 'flex',39    },40    messagePadding: {41      paddingTop: '10px',42      flex: 2.5,43    },44    buttonMarginEDB: {45      position: 'relative',46      top: '20%',47    },48    toggleButton: {49      height: '100px',50    },51    summaryContainer: {52      flexGrow: 1,53      minHeight: 0,54      overflow: 'auto',55    },56    boxText: {57      paddingBottom: '5px'58    },59    authButton: {60      marginLeft: '12em'61    }62  }),63);64 65export const CloudWizardEventsContext = React.createContext();66 67export default function CloudWizard({ nodeInfo, nodeData, onClose, cloudPanelId}) {68  const classes = useStyles();69  const eventBus = React.useRef(new EventBus());70 71  let steps = [gettext('Cloud Provider'), gettext('Credentials'), gettext('Cluster Type'),72    gettext('Instance Specification'), gettext('Database Details'), gettext('Review')];73  const [currentStep, setCurrentStep] = React.useState('');74  const [cloudSelection, setCloudSelection] = React.useState('');75  const [errMsg, setErrMsg] = React.useState('');76  const [cloudInstanceDetails, setCloudInstanceDetails] = React.useState({});77  const [cloudDBCred, setCloudDBCred] = React.useState({});78  const [cloudDBDetails, setCloudDBDetails] = React.useState({});79  const [callRDSAPI, setCallRDSAPI] = React.useState({});80  const [hostIP, setHostIP] = React.useState('127.0.0.1/32');81  const [cloudProvider, setCloudProvider] = React.useState('');82  const [verificationIntiated, setVerificationIntiated] = React.useState(false);83 84  const [bigAnimalInstanceData, setBigAnimalInstanceData] = React.useState({});85  const [bigAnimalDatabaseData, setBigAnimalDatabaseData] = React.useState({});86  const [bigAnimalClusterTypeData, setBigAnimalClusterTypeData] = React.useState({});87 88  const [azureCredData, setAzureCredData] = React.useState({});89  const [azureInstanceData, setAzureInstanceData] = React.useState({});90  const [azureDatabaseData, setAzureDatabaseData] = React.useState({});91 92  const [googleCredData, setGoogleCredData] = React.useState({});93  const [googleInstanceData, setGoogleInstanceData] = React.useState({});94  const [googleDatabaseData, setGoogleDatabaseData] = React.useState({});95 96  const axiosApi = getApiInstance();97 98  const [verificationURI, setVerificationURI] = React.useState('');99  const [verificationCode, setVerificationCode] = React.useState('');100 101  const authInterval = React.useRef();102 103  React.useEffect(()=>{104    eventBus.current.registerListener('SET_ERROR_MESSAGE_FOR_CLOUD_WIZARD', (msg) => {105      setErrMsg(msg);106    });107 108    eventBus.current.registerListener('SET_CRED_VERIFICATION_INITIATED', (initiated) => {109      setVerificationIntiated(initiated);110    });111 112    const onWizardClosing = (panelId)=>{113      if(panelId == cloudPanelId) {114        clearInterval(authInterval.current);115        onClose();116      }117    };118    pgAdmin.Browser.docker.eventBus.registerListener(LAYOUT_EVENTS.CLOSING, onWizardClosing);119    return ()=>{120      pgAdmin.Browser.docker.eventBus.deregisterListener(LAYOUT_EVENTS.CLOSING, onWizardClosing);121    };122  }, []);123 124  React.useEffect(() => {125    let _url = url_for('cloud.get_host_ip') ;126    axiosApi.get(_url)127      .then((res) => {128        if (res.data.data) {129          setHostIP(res.data.data);130        }131      })132      .catch((error) => {133        pgAdmin.Browser.notifier.error(gettext(`Error while getting the host ip: ${error.response.data.errormsg}`));134      });135  }, [cloudProvider]);136 137  const wizardStepChange = (data) => {138    setCurrentStep(data.currentStep);139  };140 141  const onSave = () => {142    let _url = url_for('cloud.deploy_on_cloud'),143      post_data = {};144 145    if (cloudProvider == CLOUD_PROVIDERS.AWS) {146      post_data = {147        gid: nodeInfo.server_group._id,148        cloud: cloudProvider,149        secret: cloudDBCred,150        instance_details:cloudInstanceDetails,151        db_details: cloudDBDetails152      };153    } else if(cloudProvider == CLOUD_PROVIDERS.AZURE){154      post_data = {155        gid: nodeInfo.server_group._id,156        secret: azureCredData,157        cloud: cloudProvider,158        instance_details:azureInstanceData,159        db_details: azureDatabaseData160      };161    }else if(cloudProvider == CLOUD_PROVIDERS.GOOGLE){162      post_data = {163        gid: nodeInfo.server_group._id,164        secret: googleCredData,165        cloud: cloudProvider,166        instance_details:googleInstanceData,167        db_details: googleDatabaseData168      };169 170    }else {171      post_data = {172        gid: nodeInfo.server_group._id,173        cloud: cloudProvider,174        cluster_details: bigAnimalClusterTypeData,175        instance_details: bigAnimalInstanceData,176        db_details: bigAnimalDatabaseData177      };178    }179 180    axiosApi.post(_url, post_data)181      .then((res) => {182        pgAdmin.Browser.Events.trigger('pgadmin:browser:tree:add', res.data.data.node, {'server_group': nodeInfo['server_group']});183        pgAdmin.Browser.BgProcessManager.startProcess(res.data.data.job_id, res.data.data.desc);184        onClose();185      })186      .catch((error) => {187        pgAdmin.Browser.notifier.error(gettext(`Error while saving cloud wizard data: ${error.response.data.errormsg}`));188      });189  };190 191  const disableNextCheck = () => {192    setCallRDSAPI(currentStep);193    let isError = (cloudProvider == '');194    switch(cloudProvider) {195    case CLOUD_PROVIDERS.AWS:196      switch (currentStep) {197      case 0:198        setCloudSelection(CLOUD_PROVIDERS.AWS);199        break;200      case 1:201        isError = validateCloudStep1(cloudDBCred);202        break;203      case 2:204        break;205      case 3:206        isError = validateCloudStep2(cloudInstanceDetails, hostIP);207        break;208      case 4:209        isError = validateCloudStep3(cloudDBDetails, nodeInfo);210        break;211      default:212        break;213      }214      break;215    case CLOUD_PROVIDERS.BIGANIMAL:216      switch (currentStep) {217      case 0:218        setCloudSelection(CLOUD_PROVIDERS.BIGANIMAL);219        break;220      case 1:221        isError = !verificationIntiated;222        break;223      case 2:224        isError = validateBigAnimalStep2(bigAnimalClusterTypeData);225        break;226      case 3:227        isError = validateBigAnimalStep3(bigAnimalInstanceData);228        break;229      case 4:230        isError = validateBigAnimalStep4(bigAnimalDatabaseData, nodeInfo);231        break;232      default:233        break;234      }235      break;236    case CLOUD_PROVIDERS.AZURE:237      switch (currentStep) {238      case 0:239        setCloudSelection(CLOUD_PROVIDERS.AZURE);240        break;241      case 1:242        isError = !verificationIntiated;243        break;244      case 2:245        break;246      case 3:247        isError = validateAzureStep2(azureInstanceData);248        break;249      case 4:250        isError = validateAzureStep3(azureDatabaseData, nodeInfo);251        break;252      default:253        break;254      }255      break;256    case CLOUD_PROVIDERS.GOOGLE:257      switch (currentStep) {258      case 0:259        setCloudSelection(CLOUD_PROVIDERS.GOOGLE);260        break;261      case 1:262        isError = !verificationIntiated;263        break;264      case 2:265        break;266      case 3:267        isError = validateGoogleStep2(googleInstanceData);268        break;269      case 4:270        isError = validateGoogleStep3(googleDatabaseData, nodeInfo);271        break;272      default:273        break;274      }275    }276    return isError;277  };278 279  const onBeforeBack = (activeStep) => {280    return new Promise((resolve)=>{281      if(activeStep == 3 && (cloudProvider == CLOUD_PROVIDERS.AWS || cloudProvider == CLOUD_PROVIDERS.AZURE || cloudProvider == CLOUD_PROVIDERS.GOOGLE)) {282        resolve(true);283      }284      else if(activeStep == 1  && (cloudProvider == CLOUD_PROVIDERS.AWS || cloudProvider == CLOUD_PROVIDERS.AZURE || cloudProvider == CLOUD_PROVIDERS.GOOGLE)) {285        setVerificationIntiated(false);286      }287      setErrMsg(['', '']);288      resolve();289    });290  };291 292  const onBeforeNext = (activeStep) => {293    return new Promise((resolve, reject)=>{294      if(activeStep == 1 && cloudProvider == CLOUD_PROVIDERS.AWS) {295        setErrMsg([MESSAGE_TYPE.INFO, gettext('Validating credentials...')]);296        let _url = url_for('rds.verify_credentials');297        const post_data = {298          cloud: cloudSelection,299          secret: cloudDBCred,300        };301        axiosApi.post(_url, post_data)302          .then((res) => {303            if(!res.data.success) {304              setErrMsg([MESSAGE_TYPE.ERROR, res.data.info]);305              reject(new Error(res.data.info));306            } else {307              setErrMsg(['', '']);308              if (activeStep == 1) {309                resolve(true);310              } else {311                resolve(false);312              }313            }314          })315          .catch(() => {316            setErrMsg([MESSAGE_TYPE.ERROR, gettext('Error while checking cloud credentials')]);317            reject(new Error(gettext('Error while checking cloud credentials')));318          });319      } else if(activeStep == 0 && cloudProvider == CLOUD_PROVIDERS.BIGANIMAL) {320        if (!isEmptyString(verificationURI)) { resolve(); return; }321        setErrMsg([MESSAGE_TYPE.INFO, gettext('Getting EDB BigAnimal verification URL...')]);322        validateBigAnimal()323          .then((res) => {324            setVerificationURI(res);325            setVerificationCode(res.substring(res.indexOf('=')+1));326            setErrMsg(['', '']);327            resolve();328          })329          .catch((error) => {330            setErrMsg([MESSAGE_TYPE.ERROR, gettext(error)]);331            reject(new Error(gettext(error)));332          });333      } else if (cloudProvider == CLOUD_PROVIDERS.AZURE) {334        if (activeStep == 1) {335          // Skip the current step336          setErrMsg(['', '']);337          resolve(true);338        } else if (activeStep == 2) {339          setErrMsg([MESSAGE_TYPE.INFO, gettext('Checking cluster name availability...')]);340          checkClusternameAvailbility(azureInstanceData.name)341            .then((res)=>{342              if (res.data && res.data.success == 0 ) {343                setErrMsg([MESSAGE_TYPE.ERROR, gettext('Specified cluster name is already used.')]);344              }else{345                setErrMsg(['', '']);346              }347              resolve();348            }).catch((error)=>{349              setErrMsg([MESSAGE_TYPE.ERROR, gettext(error)]);350              reject(new Error(gettext(error)));351            });352        } else {353          resolve();354        }355      }else if (cloudProvider == CLOUD_PROVIDERS.GOOGLE) {356        if (activeStep == 1) {357          // Skip the current step358          setErrMsg(['', '']);359          resolve(true);360        } else if (activeStep == 2) { resolve(true);} else {361          resolve();362        }363      }364      else {365        setErrMsg(['', '']);366        resolve();367      }368    });369  };370 371  const authenticateBigAnimal = () => {372    let loading_icon_url = url_for(373      'static', { 'filename': 'img/loading.gif'}374    );375 376    setErrMsg([MESSAGE_TYPE.INFO, gettext('EDB BigAnimal authentication process is in progress...') + '<img src="' + loading_icon_url + '" alt="' + gettext('Loading...') + '">']);377    let child = window.open(verificationURI, 'edb_biganimal_authentication');378    let _url = url_for('biganimal.verification_ack') ;379    let countdown = 60;380    authInterval.current = setInterval(() => {381      axiosApi.get(_url)382        .then((res) => {383          if (res.data && res.data.success == 1 ) {384            setErrMsg([MESSAGE_TYPE.SUCCESS, gettext('Authentication completed successfully. Click the Next button to proceed.')]);385            setVerificationIntiated(true);386            clearInterval(authInterval.current);387          } else if (res.data && res.data.success == 0 &&  res.data.errormsg == 'access_denied') {388            setErrMsg([MESSAGE_TYPE.INFO, gettext('Verification failed. Access Denied...')]);389            setVerificationIntiated(false);390            clearInterval(authInterval.current);391          } else if (res.data && res.data.success == 0 &&  res.data.errormsg == 'forbidden') {392            setErrMsg([MESSAGE_TYPE.INFO, gettext('Authentication completed successfully but you do not have permission to create the cluster.')]);393            setVerificationIntiated(false);394            clearInterval(authInterval.current);395          } else if (child.closed && !verificationIntiated && countdown <= 0) {396            setVerificationIntiated(false);397            setErrMsg([MESSAGE_TYPE.ERROR, gettext('Authentication is aborted.')]);398            clearInterval(authInterval.current);399          }400          authInterval.current = null;401        })402        .catch((error) => {403          setErrMsg([MESSAGE_TYPE.ERROR, gettext(`Error while verifying EDB BigAnimal: ${error.response.data.errormsg}`)]);404        });405      countdown = countdown - 1;406    }, 1000);407  };408 409 410  const onDialogHelp = () => {411    window.open(url_for('help.static', { 'filename': 'cloud_deployment.html' }), 'pgadmin_help');412  };413 414  const onErrClose = React.useCallback(()=>{415    setErrMsg([]);416  });417 418  let cloud_providers = [419    {label: gettext(CLOUD_PROVIDERS_LABELS.AWS), value: CLOUD_PROVIDERS.AWS, icon: <AWSIcon className={classes.icon} />},420    {label: gettext(CLOUD_PROVIDERS_LABELS.BIGANIMAL), value: CLOUD_PROVIDERS.BIGANIMAL, icon: <BigAnimalIcon className={classes.icon} />},421    {label: gettext(CLOUD_PROVIDERS_LABELS.AZURE), value: CLOUD_PROVIDERS.AZURE, icon: <AzureIcon className={classes.icon} /> },422    {label: gettext(CLOUD_PROVIDERS_LABELS.GOOGLE), value: CLOUD_PROVIDERS.GOOGLE, icon: <GoogleCloudIcon className={classes.icon} /> }];423 424  return (425    <CloudWizardEventsContext.Provider value={eventBus.current}>426      <Wizard427        title={gettext('Deploy Cloud Instance')}428        stepList={steps}429        disableNextStep={disableNextCheck}430        onStepChange={wizardStepChange}431        onSave={onSave}432        onHelp={onDialogHelp}433        beforeNext={onBeforeNext}434        beforeBack={onBeforeBack}>435        <WizardStep stepId={0}>436          <Box className={classes.messageBox}>437            <Box className={classes.messagePadding}>{gettext('Select a cloud provider for PostgreSQL database.')}</Box>438          </Box>439          <Box className={classes.messageBox}>440            <ToggleButtons cloudProvider={cloudProvider} setCloudProvider={setCloudProvider}441              options={cloud_providers}442            ></ToggleButtons>443          </Box>444          <FormFooterMessage type={errMsg[0]} message={errMsg[1]} onClose={onErrClose} />445        </WizardStep>446        <WizardStep stepId={1} >447          <Box className={classes.buttonMarginEDB}>448            {cloudProvider == CLOUD_PROVIDERS.BIGANIMAL && <Box className={classes.messageBox}>449              <Box>{gettext('The verification code to authenticate the pgAdmin to EDB BigAnimal is: ')} <strong>{verificationCode}</strong>450                <br/>{gettext('By clicking the below button, you will be redirected to the EDB BigAnimal authentication page in a new tab.')}451              </Box>452            </Box>}453            {cloudProvider == CLOUD_PROVIDERS.BIGANIMAL && <PrimaryButton onClick={authenticateBigAnimal} disabled={verificationIntiated}>454              {gettext('Click here to authenticate yourself to EDB BigAnimal')}455            </PrimaryButton>}456            {cloudProvider == CLOUD_PROVIDERS.BIGANIMAL && <Box className={classes.messageBox}>457              <Box ></Box>458            </Box>}459          </Box>460          {cloudProvider == CLOUD_PROVIDERS.AWS && <AwsCredentials cloudProvider={cloudProvider} nodeInfo={nodeInfo} nodeData={nodeData} setCloudDBCred={setCloudDBCred}/>}461          { cloudProvider == CLOUD_PROVIDERS.AZURE &&462            <Box flexGrow={1}>463              <AzureCredentials cloudProvider={cloudProvider} setAzureCredData={setAzureCredData}/>464            </Box>}465          <Box flexGrow={1}>466            {cloudProvider == CLOUD_PROVIDERS.GOOGLE && <GoogleCredentials cloudProvider={cloudProvider} setGoogleCredData={setGoogleCredData}/>}467          </Box>468          <FormFooterMessage type={errMsg[0]} message={errMsg[1]} onClose={onErrClose} />469        </WizardStep>470        <WizardStep stepId={2} >471          {cloudProvider == CLOUD_PROVIDERS.BIGANIMAL && callRDSAPI == 2 && <BigAnimalClusterType472            cloudProvider={cloudProvider}473            nodeInfo={nodeInfo}474            nodeData={nodeData}475            setBigAnimalClusterTypeData={setBigAnimalClusterTypeData}476            hostIP={hostIP}477          /> }478          <FormFooterMessage type={errMsg[0]} message={errMsg[1]} onClose={onErrClose} />479        </WizardStep>480        <WizardStep stepId={3} >481          {cloudProvider == CLOUD_PROVIDERS.AWS && callRDSAPI == 3 && <AwsInstanceDetails482            cloudProvider={cloudProvider}483            nodeInfo={nodeInfo}484            nodeData={nodeData}485            setCloudInstanceDetails={setCloudInstanceDetails}486            hostIP={hostIP} /> }487          {cloudProvider == CLOUD_PROVIDERS.BIGANIMAL && callRDSAPI == 3 && <BigAnimalInstance488            cloudProvider={cloudProvider}489            nodeInfo={nodeInfo}490            nodeData={nodeData}491            setBigAnimalInstanceData={setBigAnimalInstanceData}492            hostIP={hostIP}493            bigAnimalClusterTypeData={bigAnimalClusterTypeData}494          /> }495          {cloudProvider == CLOUD_PROVIDERS.AZURE && callRDSAPI == 3 && <AzureInstanceDetails496            cloudProvider={cloudProvider}497            nodeInfo={nodeInfo}498            nodeData={nodeData}499            setAzureInstanceData={setAzureInstanceData}500            hostIP={hostIP}501            azureInstanceData = {azureInstanceData}502          /> }503          {cloudProvider == CLOUD_PROVIDERS.GOOGLE && callRDSAPI == 3 && <GoogleInstanceDetails504            cloudProvider={cloudProvider}505            nodeInfo={nodeInfo}506            nodeData={nodeData}507            setGoogleInstanceData={setGoogleInstanceData}508            hostIP={hostIP}509            googleInstanceData = {googleInstanceData}510          /> }511          <FormFooterMessage type={errMsg[0]} message={errMsg[1]} onClose={onErrClose} />512        </WizardStep>513        <WizardStep stepId={4} >514          {cloudProvider == CLOUD_PROVIDERS.AWS && <AwsDatabaseDetails515            cloudProvider={cloudProvider}516            nodeInfo={nodeInfo}517            nodeData={nodeData}518            setCloudDBDetails={setCloudDBDetails}519          />520          }521          {cloudProvider == CLOUD_PROVIDERS.BIGANIMAL && callRDSAPI == 4 && <BigAnimalDatabase522            cloudProvider={cloudProvider}523            nodeInfo={nodeInfo}524            nodeData={nodeData}525            setBigAnimalDatabaseData={setBigAnimalDatabaseData}526            bigAnimalClusterTypeData={bigAnimalClusterTypeData}527          />528          }529          {cloudProvider == CLOUD_PROVIDERS.AZURE && <AzureDatabaseDetails530            cloudProvider={cloudProvider}531            nodeInfo={nodeInfo}532            nodeData={nodeData}533            setAzureDatabaseData={setAzureDatabaseData}534          />535          }536          {cloudProvider == CLOUD_PROVIDERS.GOOGLE && <GoogleDatabaseDetails537            cloudProvider={cloudProvider}538            nodeInfo={nodeInfo}539            nodeData={nodeData}540            setGoogleDatabaseData={setGoogleDatabaseData}541          />542          }543        </WizardStep>544        <WizardStep stepId={5} >545          <Box className={classes.boxText}>{gettext('Please review the details before creating the cloud instance.')}</Box>546          <Paper variant="outlined" elevation={0} className={classes.summaryContainer}>547            {cloudProvider == CLOUD_PROVIDERS.AWS && callRDSAPI == 5 && <FinalSummary548              cloudProvider={cloudProvider}549              instanceData={cloudInstanceDetails}550              databaseData={cloudDBDetails}551            />552            }553            {cloudProvider == CLOUD_PROVIDERS.BIGANIMAL && callRDSAPI == 5 && <FinalSummary554              cloudProvider={cloudProvider}555              instanceData={bigAnimalInstanceData}556              databaseData={bigAnimalDatabaseData}557              clusterTypeData={bigAnimalClusterTypeData}558            />559            }560            {cloudProvider == CLOUD_PROVIDERS.AZURE && callRDSAPI == 5 && <FinalSummary561              cloudProvider={cloudProvider}562              instanceData={azureInstanceData}563              databaseData={azureDatabaseData}564            />565            }566            {cloudProvider == CLOUD_PROVIDERS.GOOGLE && callRDSAPI == 5 && <FinalSummary567              cloudProvider={cloudProvider}568              instanceData={googleInstanceData}569              databaseData={googleDatabaseData}570            />571            }572          </Paper>573        </WizardStep>574      </Wizard>575    </CloudWizardEventsContext.Provider>576  );577}578 579CloudWizard.propTypes = {580  nodeInfo: PropTypes.object,581  nodeData: PropTypes.object,582  onClose: PropTypes.func,583  cloudPanelId: PropTypes.string,584};585 
codekingpro/portable-devtools · Team Ai