1515 */
1616
1717import { useEffect , useState } from 'react'
18+ import { useLocation } from 'react-router-dom'
1819
1920import {
2021 AuthenticationType ,
2122 Button ,
2223 ButtonStyleType ,
2324 ButtonVariantType ,
25+ ClusterCostModuleConfigDTO ,
26+ ClusterDetailListType ,
2427 DEFAULT_SECRET_PLACEHOLDER ,
2528 Icon ,
2629 ModalSidebarPanel ,
@@ -32,6 +35,7 @@ import {
3235 showError ,
3336 ToastManager ,
3437 ToastVariantType ,
38+ URLS ,
3539 useAsync ,
3640} from '@devtron-labs/devtron-fe-common-lib'
3741
@@ -76,10 +80,29 @@ const ClusterForm = ({
7680 isTlsConnection : initialIsTlsConnection = false ,
7781 installationId,
7882 category,
83+ clusterProvider,
84+ costModuleConfig,
7985} : ClusterFormProps ) => {
80- const [ clusterConfigTab , setClusterConfigTab ] = useState < ClusterConfigTabEnum > ( ClusterConfigTabEnum . CLUSTER_CONFIG )
86+ const location = useLocation ( )
8187
82- const [ costModuleEnabled , setCostModuleEnabled ] = useState ( false )
88+ const [ clusterConfigTab , setClusterConfigTab ] = useState < ClusterConfigTabEnum > (
89+ id && location . pathname . includes ( URLS . COST_VISIBILITY )
90+ ? ClusterConfigTabEnum . COST_VISIBILITY
91+ : ClusterConfigTabEnum . CLUSTER_CONFIG ,
92+ )
93+
94+ const [ costModuleState , setCostModuleState ] = useState <
95+ Pick < ClusterDetailListType [ 'costModuleConfig' ] , 'config' | 'enabled' >
96+ > ( {
97+ enabled : costModuleConfig ?. enabled || false ,
98+ config : {
99+ cloudProviderApiKey : costModuleConfig ?. config ?. cloudProviderApiKey || '' ,
100+ } ,
101+ } )
102+
103+ const [ costModuleErrorState , setCostModuleErrorState ] = useState < { cloudProviderApiKey : string } > ( {
104+ cloudProviderApiKey : '' ,
105+ } )
83106 const [ prometheusToggleEnabled , setPrometheusToggleEnabled ] = useState ( ! ! prometheusUrl )
84107 const [ prometheusAuthenticationType , setPrometheusAuthenticationType ] = useState ( {
85108 type : prometheusAuth ?. userName ? AuthenticationType . BASIC : AuthenticationType . ANONYMOUS ,
@@ -159,6 +182,27 @@ const ClusterForm = ({
159182 setIsConnectedViaSSHTunnelTemp ( false )
160183 }
161184
185+ const getCostModulePayload = ( ) : ClusterCostModuleConfigDTO | null => {
186+ if ( ! costModuleState . enabled ) {
187+ return {
188+ enabled : false ,
189+ }
190+ }
191+
192+ if ( clusterProvider === 'GCP' && costModuleState . config . cloudProviderApiKey ) {
193+ return {
194+ enabled : true ,
195+ config : {
196+ cloudProviderApiKey : costModuleState . config . cloudProviderApiKey ,
197+ } ,
198+ }
199+ }
200+
201+ return {
202+ enabled : true ,
203+ }
204+ }
205+
162206 const getClusterPayload = ( state ) => ( {
163207 id,
164208 insecureSkipTlsVerify : ! isTlsConnection ,
@@ -189,6 +233,7 @@ const ClusterForm = ({
189233 } ,
190234 server_url : '' ,
191235 ...( getCategoryPayload ? getCategoryPayload ( selectedCategory ) : null ) ,
236+ ...( clusterProvider ? { costModuleConfig : getCostModulePayload ( ) } : null ) ,
192237 } )
193238
194239 const onValidation = async ( state ) => {
@@ -199,6 +244,19 @@ const ClusterForm = ({
199244 } else {
200245 payload . server_url = urlValue
201246 }
247+
248+ if ( clusterProvider === 'GCP' && costModuleState . enabled && ! costModuleState . config . cloudProviderApiKey ) {
249+ setCostModuleErrorState ( ( prev ) => ( {
250+ ...prev ,
251+ cloudProviderApiKey : 'Cloud Provider API Key is required' ,
252+ } ) )
253+ ToastManager . showToast ( {
254+ variant : ToastVariantType . error ,
255+ description : 'Please provide Cloud Provider API Key to enable cost tracking' ,
256+ } )
257+ return
258+ }
259+
202260 if ( remoteConnectionMethod === RemoteConnectionType . Proxy ) {
203261 let proxyUrlValue = state . proxyUrl ?. value ?. trim ( ) ?? ''
204262 if ( proxyUrlValue . endsWith ( '/' ) ) {
@@ -404,6 +462,27 @@ const ClusterForm = ({
404462 setClusterConfigTab ( tab )
405463 }
406464
465+ const toggleCostModule = ( ) => {
466+ setCostModuleState ( ( prev ) => ( {
467+ ...prev ,
468+ enabled : ! prev . enabled ,
469+ } ) )
470+ }
471+
472+ const handleProviderAPIKeyChange = ( apiKey : string ) => {
473+ setCostModuleState ( ( prev ) => ( {
474+ ...prev ,
475+ config : {
476+ cloudProviderApiKey : apiKey ,
477+ } ,
478+ } ) )
479+
480+ setCostModuleErrorState ( ( prev ) => ( {
481+ ...prev ,
482+ cloudProviderApiKey : apiKey ? '' : 'Cloud Provider API Key is required' ,
483+ } ) )
484+ }
485+
407486 const renderFooter = ( ) => (
408487 < div className = { `border__primary--top flexbox py-12 px-20 ${ id ? 'dc__content-space' : 'dc__content-end' } ` } >
409488 { id && (
@@ -490,8 +569,14 @@ const ClusterForm = ({
490569 handleOnChange = { handleOnChange }
491570 onPrometheusAuthTypeChange = { onPrometheusAuthTypeChange }
492571 isGrafanaModuleInstalled = { isGrafanaModuleInstalled }
493- costModuleEnabled = { costModuleEnabled }
494- setCostModuleEnabled = { setCostModuleEnabled }
572+ costModuleEnabled = { costModuleState . enabled }
573+ toggleCostModule = { toggleCostModule }
574+ installationStatus = { costModuleConfig . installationStatus }
575+ installationError = { costModuleConfig . installationError }
576+ clusterProvider = { clusterProvider }
577+ handleProviderAPIKeyChange = { handleProviderAPIKeyChange }
578+ providerAPIKey = { costModuleState . config . cloudProviderApiKey || '' }
579+ providerAPIKeyError = { costModuleErrorState . cloudProviderApiKey }
495580 />
496581 </ div >
497582 ) : null
@@ -517,7 +602,7 @@ const ClusterForm = ({
517602 title = "Cluster Configurations"
518603 onClick = { getTabSwitchHandler ( ClusterConfigTabEnum . CLUSTER_CONFIG ) }
519604 />
520- < div className = "divder__secondary --horizontal" />
605+ < div className = "divider__secondary --horizontal" />
521606 < div className = "flexbox-col" >
522607 < div className = "px-8 py-4 fs-12 fw-6 lh-20 cn-7" > INTEGRATIONS</ div >
523608 < ClusterFormNavButton
@@ -526,11 +611,11 @@ const ClusterForm = ({
526611 subtitle = { prometheusToggleEnabled ? 'Enabled' : 'Off' }
527612 onClick = { getTabSwitchHandler ( ClusterConfigTabEnum . APPLICATION_MONITORING ) }
528613 />
529- { ClusterCostConfig && (
614+ { ClusterCostConfig && id && (
530615 < ClusterFormNavButton
531616 isActive = { clusterConfigTab === ClusterConfigTabEnum . COST_VISIBILITY }
532617 title = "Cost Visibility"
533- subtitle = { costModuleEnabled ? 'Enabled' : 'Off' }
618+ subtitle = { costModuleState . enabled ? 'Enabled' : 'Off' }
534619 onClick = { getTabSwitchHandler ( ClusterConfigTabEnum . COST_VISIBILITY ) }
535620 />
536621 ) }
0 commit comments