2022-02-14 00:43:48 -06:00
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import gettext from 'sources/gettext' ;
import url _for from 'sources/url_for' ;
import React from 'react' ;
2022-04-26 06:11:10 -05:00
import { Box , Paper } from '@material-ui/core' ;
2022-02-14 00:43:48 -06:00
import { makeStyles } from '@material-ui/core/styles' ;
import Wizard from '../../../../static/js/helpers/wizard/Wizard' ;
import WizardStep from '../../../../static/js/helpers/wizard/WizardStep' ;
2022-04-26 06:11:10 -05:00
import { FormFooterMessage , MESSAGE _TYPE } from '../../../../static/js/components/FormComponents' ;
2022-02-14 00:43:48 -06:00
import getApiInstance from '../../../../static/js/api_instance' ;
import Alertify from 'pgadmin.alertifyjs' ;
import PropTypes from 'prop-types' ;
import pgAdmin from 'sources/pgadmin' ;
2022-04-26 06:11:10 -05:00
import { ToggleButtons , FinalSummary } from './cloud_components' ;
import { PrimaryButton } from '../../../../static/js/components/Buttons' ;
import { AwsCredentials , AwsInstanceDetails , AwsDatabaseDetails , validateCloudStep1 ,
validateCloudStep2 , validateCloudStep3 } from './aws' ;
import { BigAnimalInstance , BigAnimalDatabase , validateBigAnimal ,
validateBigAnimalStep2 , validateBigAnimalStep3 } from './biganimal' ;
2022-02-14 00:43:48 -06:00
const useStyles = makeStyles ( ( ) =>
( {
messageBox : {
marginBottom : '1em' ,
display : 'flex' ,
} ,
messagePadding : {
2022-04-26 06:11:10 -05:00
paddingTop : '10px' ,
flex : 2.5 ,
} ,
buttonMarginEDB : {
position : 'relative' ,
top : '20%' ,
2022-02-14 00:43:48 -06:00
} ,
toggleButton : {
height : '100px' ,
} ,
2022-04-26 06:11:10 -05:00
summaryContainer : {
flexGrow : 1 ,
minHeight : 0 ,
overflow : 'auto' ,
2022-02-14 00:43:48 -06:00
} ,
2022-04-26 06:11:10 -05:00
boxText : {
paddingBottom : '5px'
2022-02-14 00:43:48 -06:00
} ,
} ) ,
) ;
export default function CloudWizard ( { nodeInfo , nodeData } ) {
const classes = useStyles ( ) ;
var steps = [ 'Cloud Provider' , 'Credentials' , 'Instance Specification' , 'Database Details' , 'Review' ] ;
const [ currentStep , setCurrentStep ] = React . useState ( '' ) ;
const [ selectionVal , setCloudSelection ] = React . useState ( '' ) ;
const [ errMsg , setErrMsg ] = React . useState ( '' ) ;
const [ cloudInstanceDetails , setCloudInstanceDetails ] = React . useState ( { } ) ;
const [ cloudDBCred , setCloudDBCred ] = React . useState ( { } ) ;
const [ cloudDBDetails , setCloudDBDetails ] = React . useState ( { } ) ;
const [ callRDSAPI , setCallRDSAPI ] = React . useState ( { } ) ;
2022-02-28 06:49:18 -06:00
const [ hostIP , setHostIP ] = React . useState ( '127.0.0.1/32' ) ;
2022-04-26 06:11:10 -05:00
const [ cloudProvider , setCloudProvider ] = React . useState ( '' ) ;
const [ verificationIntiated , setVerificationIntiated ] = React . useState ( false ) ;
const [ bigAnimalInstanceData , setBigAnimalInstanceData ] = React . useState ( { } ) ;
const [ bigAnimalDatabaseData , setBigAnimalDatabaseData ] = React . useState ( { } ) ;
2022-02-14 00:43:48 -06:00
const axiosApi = getApiInstance ( ) ;
2022-04-26 06:11:10 -05:00
const [ verificationURI , setVerificationURI ] = React . useState ( '' ) ;
const [ verificationCode , setVerificationCode ] = React . useState ( '' ) ;
2022-02-28 06:49:18 -06:00
React . useEffect ( ( ) => {
let _url = url _for ( 'cloud.get_host_ip' ) ;
axiosApi . get ( _url )
. then ( ( res ) => {
if ( res . data . data ) {
setHostIP ( res . data . data ) ;
}
} )
. catch ( ( error ) => {
Alertify . error ( gettext ( ` Error while getting the host ip: ${ error . response . data . errormsg } ` ) ) ;
} ) ;
2022-04-26 06:11:10 -05:00
} , [ cloudProvider ] ) ;
2022-02-14 00:43:48 -06:00
const wizardStepChange = ( data ) => {
setCurrentStep ( data . currentStep ) ;
} ;
2022-04-26 06:11:10 -05:00
const onSave = ( ) => {
var _url = url _for ( 'cloud.deploy_on_cloud' ) ,
post _data = { } ;
if ( cloudProvider == 'rds' ) {
post _data = {
gid : nodeInfo . server _group . _id ,
cloud : cloudProvider ,
secret : cloudDBCred ,
instance _details : cloudInstanceDetails ,
db _details : cloudDBDetails
} ;
} else {
post _data = {
gid : nodeInfo . server _group . _id ,
cloud : cloudProvider ,
instance _details : bigAnimalInstanceData ,
db _details : bigAnimalDatabaseData
} ;
2022-02-14 00:43:48 -06:00
}
axiosApi . post ( _url , post _data )
. then ( ( res ) => {
pgAdmin . Browser . Events . trigger ( 'pgadmin:browser:tree:add' , res . data . data . node , { 'server_group' : nodeInfo [ 'server_group' ] } ) ;
pgAdmin . Browser . Events . trigger ( 'pgadmin-bgprocess:created' , Alertify . cloudWizardDialog ( ) ) ;
Alertify . cloudWizardDialog ( ) . close ( ) ;
} )
. catch ( ( error ) => {
Alertify . error ( gettext ( ` Error while saving cloud wizard data: ${ error . response . data . errormsg } ` ) ) ;
} ) ;
} ;
const disableNextCheck = ( ) => {
setCallRDSAPI ( currentStep ) ;
2022-04-26 06:11:10 -05:00
let isError = ( cloudProvider == '' ) ;
switch ( cloudProvider ) {
case 'rds' :
switch ( currentStep ) {
case 0 :
setCloudSelection ( 'rds' ) ;
break ;
case 1 :
isError = validateCloudStep1 ( cloudDBCred ) ;
break ;
case 2 :
isError = validateCloudStep2 ( cloudInstanceDetails , hostIP ) ;
break ;
case 3 :
isError = validateCloudStep3 ( cloudDBDetails , nodeInfo ) ;
break ;
default :
break ;
}
2022-02-14 00:43:48 -06:00
break ;
2022-04-26 06:11:10 -05:00
case 'biganimal' :
switch ( currentStep ) {
case 0 :
setCloudSelection ( 'biganimal' ) ;
break ;
case 1 :
isError = ! verificationIntiated ;
break ;
case 2 :
isError = validateBigAnimalStep2 ( bigAnimalInstanceData ) ;
break ;
case 3 :
isError = validateBigAnimalStep3 ( bigAnimalDatabaseData , nodeInfo ) ;
break ;
default :
break ;
}
2022-02-14 00:43:48 -06:00
break ;
}
return isError ;
} ;
const onBeforeNext = ( activeStep ) => {
return new Promise ( ( resolve , reject ) => {
2022-04-26 06:11:10 -05:00
if ( activeStep == 1 && cloudProvider == 'rds' ) {
2022-02-14 00:43:48 -06:00
setErrMsg ( [ MESSAGE _TYPE . INFO , 'Validating credentials...' ] ) ;
2022-04-26 06:11:10 -05:00
var _url = url _for ( 'rds.verify_credentials' ) ;
2022-02-14 00:43:48 -06:00
const post _data = {
cloud : selectionVal ,
secret : cloudDBCred ,
} ;
axiosApi . post ( _url , post _data )
. then ( ( res ) => {
if ( ! res . data . success ) {
setErrMsg ( [ MESSAGE _TYPE . ERROR , res . data . info ] ) ;
reject ( ) ;
} else {
setErrMsg ( [ '' , '' ] ) ;
resolve ( ) ;
}
} )
. catch ( ( ) => {
setErrMsg ( [ MESSAGE _TYPE . ERROR , 'Error while checking cloud credentials' ] ) ;
reject ( ) ;
} ) ;
2022-04-26 06:11:10 -05:00
} else if ( activeStep == 0 && cloudProvider == 'biganimal' ) {
setErrMsg ( [ MESSAGE _TYPE . INFO , 'Getting EDB BigAnimal verification URL...' ] ) ;
validateBigAnimal ( )
. then ( ( res ) => {
setVerificationURI ( res ) ;
setVerificationCode ( res . substring ( res . indexOf ( '=' ) + 1 ) ) ;
setErrMsg ( [ '' , '' ] ) ;
resolve ( ) ;
} )
. catch ( ( error ) => {
setErrMsg ( [ MESSAGE _TYPE . ERROR , gettext ( error ) ] ) ;
reject ( ) ;
} ) ;
}
else {
2022-02-14 00:43:48 -06:00
resolve ( ) ;
}
} ) ;
} ;
2022-04-26 06:11:10 -05:00
const authenticateBigAnimal = ( ) => {
var loading _icon _url = url _for (
'static' , { 'filename' : 'img/loading.gif' }
) ;
2022-02-14 00:43:48 -06:00
2022-04-26 06:11:10 -05:00
setErrMsg ( [ MESSAGE _TYPE . INFO , 'EDB BigAnimal authentication process is in progress...<img src="' + loading _icon _url + '" alt="' + gettext ( 'Loading...' ) + '">' ] ) ;
window . open ( verificationURI , 'edb_biganimal_authentication' ) ;
let _url = url _for ( 'biganimal.verification_ack' ) ;
const myInterval = setInterval ( ( ) => {
axiosApi . get ( _url )
. then ( ( res ) => {
if ( res . data && res . data . success == 1 ) {
setErrMsg ( [ MESSAGE _TYPE . SUCCESS , 'Authentication completed successfully. Click the Next button to proceed.' ] ) ;
setVerificationIntiated ( true ) ;
clearInterval ( myInterval ) ;
}
else if ( res . data && res . data . success == 0 && res . data . errormsg == 'access_denied' ) {
setErrMsg ( [ MESSAGE _TYPE . INFO , 'Verification failed. Access Denied...' ] ) ;
setVerificationIntiated ( false ) ;
clearInterval ( myInterval ) ;
}
else if ( res . data && res . data . success == 0 && res . data . errormsg == 'forbidden' ) {
setErrMsg ( [ MESSAGE _TYPE . INFO , 'Authentication completed successfully but you do not have permission to create the cluster.' ] ) ;
setVerificationIntiated ( false ) ;
clearInterval ( myInterval ) ;
}
} )
. catch ( ( error ) => {
setErrMsg ( [ MESSAGE _TYPE . ERROR , gettext ( ` Error while verification EDB BigAnimal: ${ error . response . data . errormsg } ` ) ] ) ;
} ) ;
} , 1000 ) ;
2022-02-14 00:43:48 -06:00
2022-04-26 06:11:10 -05:00
} ;
2022-02-14 00:43:48 -06:00
2022-04-26 06:11:10 -05:00
const onDialogHelp = ( ) => {
window . open ( url _for ( 'help.static' , { 'filename' : 'cloud_deployment.html' } ) , 'pgadmin_help' ) ;
} ;
2022-02-14 00:43:48 -06:00
const onErrClose = React . useCallback ( ( ) => {
setErrMsg ( [ ] ) ;
} ) ;
return (
< >
< Wizard
title = { gettext ( 'Deploy Cloud Instance' ) }
stepList = { steps }
disableNextStep = { disableNextCheck }
onStepChange = { wizardStepChange }
onSave = { onSave }
onHelp = { onDialogHelp }
beforeNext = { onBeforeNext } >
< WizardStep stepId = { 0 } >
< Box className = { classes . messageBox } >
2022-04-26 06:11:10 -05:00
< Box className = { classes . messagePadding } > { gettext ( 'Select any option to deploy on cloud.' ) } < / Box >
2022-02-14 00:43:48 -06:00
< / Box >
< Box className = { classes . messageBox } >
2022-04-26 06:11:10 -05:00
< ToggleButtons cloudProvider = { cloudProvider } setCloudProvider = { setCloudProvider }
options = { [ { 'label' : 'Amazon RDS' , value : 'rds' } , { 'label' : 'EDB BigAnimal' , value : 'biganimal' } ] }
> < / ToggleButtons >
2022-02-14 00:43:48 -06:00
< / Box >
< Box className = { classes . messageBox } >
< Box className = { classes . messagePadding } > { gettext ( 'More cloud providers are coming soon...' ) } < / Box >
< / Box >
2022-04-26 06:11:10 -05:00
< FormFooterMessage type = { errMsg [ 0 ] } message = { errMsg [ 1 ] } onClose = { onErrClose } / >
2022-02-14 00:43:48 -06:00
< / WizardStep >
< WizardStep stepId = { 1 } >
2022-04-26 06:11:10 -05:00
< Box className = { classes . buttonMarginEDB } >
{ cloudProvider == 'biganimal' && < Box className = { classes . messageBox } >
< Box > { gettext ( 'The verification code to authenticate the pgAdmin to EDB BigAnimal is: ' ) } < strong > { verificationCode } < / strong >
< br / > { gettext ( 'By clicking the below button, you will be redirected to the EDB BigAnimal authentication page in a new tab.' ) }
< / Box >
< / Box > }
{ cloudProvider == 'biganimal' && < PrimaryButton onClick = { authenticateBigAnimal } >
{ gettext ( 'Click here to authenticate yourself to EDB BigAnimal' ) }
< / PrimaryButton > }
{ cloudProvider == 'biganimal' && < Box className = { classes . messageBox } >
< Box > < / Box >
< / Box > }
< / Box >
{ cloudProvider == 'rds' && < AwsCredentials cloudProvider = { cloudProvider } nodeInfo = { nodeInfo } nodeData = { nodeData } setCloudDBCred = { setCloudDBCred } / > }
2022-02-14 00:43:48 -06:00
< FormFooterMessage type = { errMsg [ 0 ] } message = { errMsg [ 1 ] } onClose = { onErrClose } / >
< / WizardStep >
< WizardStep stepId = { 2 } >
2022-04-26 06:11:10 -05:00
{ cloudProvider == 'rds' && callRDSAPI == 2 && < AwsInstanceDetails
cloudProvider = { cloudProvider }
nodeInfo = { nodeInfo }
nodeData = { nodeData }
setCloudInstanceDetails = { setCloudInstanceDetails }
hostIP = { hostIP } / > }
{ cloudProvider == 'biganimal' && callRDSAPI == 2 && < BigAnimalInstance
cloudProvider = { cloudProvider }
nodeInfo = { nodeInfo }
nodeData = { nodeData }
setBigAnimalInstanceData = { setBigAnimalInstanceData }
hostIP = { hostIP }
/ > }
2022-02-14 00:43:48 -06:00
< / WizardStep >
< WizardStep stepId = { 3 } >
2022-04-26 06:11:10 -05:00
{ cloudProvider == 'rds' && < AwsDatabaseDetails
cloudProvider = { cloudProvider }
nodeInfo = { nodeInfo }
nodeData = { nodeData }
setCloudDBDetails = { setCloudDBDetails }
/ >
}
{ cloudProvider == 'biganimal' && callRDSAPI == 3 && < BigAnimalDatabase
cloudProvider = { cloudProvider }
nodeInfo = { nodeInfo }
nodeData = { nodeData }
setBigAnimalDatabaseData = { setBigAnimalDatabaseData }
/ >
2022-02-14 00:43:48 -06:00
}
< / WizardStep >
< WizardStep stepId = { 4 } >
< Box className = { classes . boxText } > { gettext ( 'Please review the details before creating the cloud instance.' ) } < / Box >
< Paper variant = "outlined" elevation = { 0 } className = { classes . summaryContainer } >
2022-04-26 06:11:10 -05:00
{ cloudProvider == 'rds' && callRDSAPI == 4 && < FinalSummary
cloudProvider = { cloudProvider }
instanceData = { cloudInstanceDetails }
databaseData = { cloudDBDetails }
/ >
}
{ cloudProvider == 'biganimal' && callRDSAPI == 4 && < FinalSummary
cloudProvider = { cloudProvider }
instanceData = { bigAnimalInstanceData }
databaseData = { bigAnimalDatabaseData }
/ >
}
2022-02-14 00:43:48 -06:00
< / Paper >
< / WizardStep >
< / Wizard >
< / >
) ;
}
CloudWizard . propTypes = {
nodeInfo : PropTypes . object ,
nodeData : PropTypes . object ,
} ;