Skip to content

Commit 279de8e

Browse files
authored
Merge pull request #2062 from devtron-labs/feat/airgapped-release
feat: add support for air gapped installation in release
2 parents 161cd88 + b1d9c64 commit 279de8e

24 files changed

+798
-2970
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"homepage": "/dashboard",
66
"dependencies": {
7-
"@devtron-labs/devtron-fe-common-lib": "0.3.21",
7+
"@devtron-labs/devtron-fe-common-lib": "0.3.22",
88
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
99
"@rjsf/core": "^5.13.3",
1010
"@rjsf/utils": "^5.13.3",

src/assets/icons/ic-camera.svg

Lines changed: 4 additions & 0 deletions
Loading

src/components/app/details/appDetails/AppDetails.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
ReleaseMode,
3535
ToastVariantType,
3636
ToastManager,
37+
handleUTCTime,
3738
} from '@devtron-labs/devtron-fe-common-lib'
3839
import { Link, useParams, useHistory, useRouteMatch, generatePath, Route, useLocation } from 'react-router-dom'
3940
import Tippy from '@tippyjs/react'
@@ -295,6 +296,7 @@ export const Details: React.FC<DetailsType> = ({
295296
const appDetailsAbortRef = useRef(null)
296297
const shouldFetchTimelineRef = useRef(false)
297298

299+
298300
const [deploymentStatusDetailsBreakdownData, setDeploymentStatusDetailsBreakdownData] =
299301
useState<DeploymentStatusDetailsBreakdownDataType>({
300302
...(isVirtualEnvRef.current && processVirtualEnvironmentDeploymentData
@@ -355,6 +357,7 @@ export const Details: React.FC<DetailsType> = ({
355357
],
356358
)
357359

360+
// This is called only when timeline modal is open
358361
const getDeploymentDetailStepsData = useCallback(
359362
(showTimeline?: boolean): void => {
360363
const shouldFetchTimeline = showTimeline ?? shouldFetchTimelineRef.current
@@ -424,7 +427,10 @@ export const Details: React.FC<DetailsType> = ({
424427
}
425428
IndexStore.publishAppDetails(appDetailsRef.current, AppType.DEVTRON_APP)
426429
setAppDetails(appDetailsRef.current)
427-
_getDeploymentStatusDetail(appDetailsRef.current.deploymentAppType)
430+
431+
const isIsolatedEnv = isVirtualEnvRef.current && !!appDetailsRef.current.resourceTree
432+
433+
_getDeploymentStatusDetail(appDetailsRef.current.deploymentAppType, isIsolatedEnv, isIsolatedEnv ? appDetailsRef.current?.resourceTree?.wfrId : null)
428434

429435
if (fetchExternalLinks && response.result?.clusterId) {
430436
getExternalLinksAndTools(response.result.clusterId)
@@ -469,13 +475,15 @@ export const Details: React.FC<DetailsType> = ({
469475
})
470476
}
471477

472-
function _getDeploymentStatusDetail(deploymentAppType: DeploymentAppTypes) {
478+
function _getDeploymentStatusDetail(deploymentAppType: DeploymentAppTypes, isIsolatedEnv: boolean, triggerIdToFetch?: number) {
473479
const shouldFetchTimeline = shouldFetchTimelineRef.current
474480

475-
getDeploymentStatusDetail(params.appId, params.envId, shouldFetchTimeline)
481+
// triggerIdToFetch represents the wfrId to fetch for any specific deployment
482+
getDeploymentStatusDetail(params.appId, params.envId, shouldFetchTimeline, triggerIdToFetch?.toString())
476483
.then((deploymentStatusDetailRes) => {
477484
if (deploymentStatusDetailRes.result) {
478-
if (deploymentAppType === DeploymentAppTypes.HELM) {
485+
// Timelines are not applicable for helm deployments and air gapped envs
486+
if (deploymentAppType === DeploymentAppTypes.HELM || isIsolatedEnv) {
479487
setDeploymentStatusDetailsBreakdownData({
480488
...deploymentStatusDetailsBreakdownData,
481489
deploymentStatus:
@@ -616,7 +624,7 @@ export const Details: React.FC<DetailsType> = ({
616624
const environmentName = environmentsMap[+envId]
617625

618626
const renderAppDetails = (): JSX.Element => {
619-
if (isVirtualEnvRef.current && VirtualAppDetailsEmptyState) {
627+
if (!appDetails.resourceTree && isVirtualEnvRef.current && VirtualAppDetailsEmptyState) {
620628
return <VirtualAppDetailsEmptyState environmentName={environmentName} />
621629
}
622630
return (
@@ -626,6 +634,7 @@ export const Details: React.FC<DetailsType> = ({
626634
monitoringTools={externalLinksAndTools.monitoringTools}
627635
isDevtronApp
628636
isDeploymentBlocked={isDeploymentBlocked}
637+
isVirtualEnvironment={isVirtualEnvRef.current}
629638
/>
630639
)
631640
}

src/components/app/details/appDetails/SourceInfo.tsx

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,21 @@
1414
* limitations under the License.
1515
*/
1616

17-
// @ts-nocheck - @TODO: Remove this by fixing the type issues
18-
import React, { useEffect, useMemo, useState } from 'react'
19-
import { useParams } from 'react-router-dom'
17+
import { useEffect, useMemo, useState } from 'react'
18+
import { Link, useParams } from 'react-router-dom'
2019
import Tippy from '@tippyjs/react'
20+
import moment from 'moment'
2121
import {
2222
ConditionalWrap,
23+
DATE_TIME_FORMATS,
2324
DeploymentAppTypes,
2425
getIsManualApprovalConfigured,
26+
handleUTCTime,
2527
ReleaseMode,
2628
showError,
29+
Tooltip,
2730
} from '@devtron-labs/devtron-fe-common-lib'
31+
import { ReactComponent as ICCamera } from '@Icons/ic-camera.svg'
2832
import { URLS } from '../../../../config'
2933
import { EnvSelector } from './AppDetails'
3034
import { DeploymentAppTypeNameMapping } from '../../../../config/constantMessaging'
@@ -43,6 +47,7 @@ import { ReactComponent as RotateIcon } from '../../../../assets/icons/ic-arrows
4347
import { ReactComponent as LinkIcon } from '../../../../assets/icons/ic-link.svg'
4448
import { ReactComponent as Trash } from '../../../../assets/icons/ic-delete-dots.svg'
4549
import { ReactComponent as ScaleDown } from '../../../../assets/icons/ic-scale-down.svg'
50+
import HelmAppConfigApplyStatusCard from '@Components/v2/appDetails/sourceInfo/environmentStatus/HelmAppConfigApplyStatusCard'
4651

4752
const AppDetailsDownloadCard = importComponentFromFELibrary('AppDetailsDownloadCard')
4853
const DeploymentWindowStatusCard = importComponentFromFELibrary('DeploymentWindowStatusCard')
@@ -79,6 +84,7 @@ export const SourceInfo = ({
7984
// helmMigratedAppNotTriggered means the app is migrated from a helm release and has not been deployed yet i.e. CD Pipeline has not been triggered
8085
const helmMigratedAppNotTriggered =
8186
appDetails?.releaseMode === ReleaseMode.MIGRATE_HELM && !appDetails?.isPipelineTriggered
87+
const isIsolatedEnv = isVirtualEnvironment && !!appDetails?.resourceTree
8288

8389
if (
8490
['progressing', 'degraded'].includes(status?.toLowerCase()) &&
@@ -139,6 +145,10 @@ export const SourceInfo = ({
139145
const renderDevtronAppsEnvironmentSelector = (environment) => {
140146
// If moving to a component then move getIsApprovalConfigured with it as well with memoization.
141147
const isApprovalConfigured = getIsApprovalConfigured()
148+
const relativeSnapshotTime = appDetails?.resourceTree?.lastSnapshotTime ? handleUTCTime(
149+
appDetails.resourceTree.lastSnapshotTime,
150+
true,
151+
) : ''
142152

143153
return (
144154
<div className="flex left w-100">
@@ -147,26 +157,50 @@ export const SourceInfo = ({
147157
disabled={loadingDetails || loadingResourceTree || (params.envId && !showCommitInfo)}
148158
/>
149159
{appDetails?.deploymentAppType && (
150-
<Tippy
151-
className="default-tt"
152-
arrow={false}
160+
<Tooltip
153161
placement="top"
162+
alwaysShowTippyOnHover={!appDetails.isVirtualEnvironment}
154163
content={`Deployed using ${
155164
isArgoCdApp ? DeploymentAppTypeNameMapping.GitOps : DeploymentAppTypeNameMapping.Helm
156165
}`}
157166
>
158-
<div className="flex">
159-
<DeploymentTypeIcon deploymentAppType={appDetails?.deploymentAppType} />
167+
<div className={`flex ${!appDetails.isVirtualEnvironment ? 'ml-16' : ''}`}>
168+
{/* TODO: verify what appType needs to be passed */}
169+
<DeploymentTypeIcon deploymentAppType={appDetails?.deploymentAppType} appType={null} />
160170
</div>
161-
</Tippy>
171+
</Tooltip>
162172
)}
163173
{isdeploymentAppDeleting && (
164-
<div data-testid="deleteing-argocd-pipeline">
174+
<div data-testid="deleteing-argocd-pipeline" className="flex left">
165175
<Trash className="icon-dim-16 mr-8 ml-12" />
166176
<span className="cr-5 fw-6">Deleting deployment pipeline </span>
167177
<span className="dc__loading-dots cr-5" />
168178
</div>
169179
)}
180+
{/* Last snapshot time */}
181+
{isIsolatedEnv && relativeSnapshotTime && (
182+
<Tooltip
183+
content={
184+
<div className="fw-4 lh-18 flexbox-col dc__ga-2">
185+
<h6 className="fs-12 fw-6 cn-0 m-0">Last snapshot received</h6>
186+
<p className="m-0 fs-12 cn-50">
187+
{moment(appDetails.resourceTree.lastSnapshotTime).format(
188+
DATE_TIME_FORMATS.TWELVE_HOURS_FORMAT,
189+
)}
190+
</p>
191+
</div>
192+
}
193+
alwaysShowTippyOnHover
194+
>
195+
<div className="flex left">
196+
<div className="dc__divider h-20 mr-8 ml-8" />
197+
<div className="flex left dc__gap-6 px-8 py-4">
198+
<ICCamera className="scn-9 dc__no-shrink icon-dim-16" />
199+
<p className="m-0 fs-13 fw-4 lh-20 cn-9 dc__truncate">{relativeSnapshotTime}</p>
200+
</div>
201+
</div>
202+
</Tooltip>
203+
)}
170204
{!loadingResourceTree && environment && (
171205
<>
172206
{!isdeploymentAppDeleting && (
@@ -204,7 +238,7 @@ export const SourceInfo = ({
204238
<button
205239
data-testid="app-details-rotate-pods-modal-button"
206240
className="cta cta-with-img small cancel fs-12 fw-6 mr-6"
207-
onClick={setRotateModal}
241+
onClick={() => setRotateModal(true)}
208242
disabled={isApprovalConfigured}
209243
>
210244
<RotateIcon className="icon-dim-16 mr-6 icon-color-n7 scn-4" />
@@ -258,16 +292,17 @@ export const SourceInfo = ({
258292
: !isdeploymentAppDeleting &&
259293
environment && (
260294
<div className="flex left w-100">
261-
{!isVirtualEnvironment && (
262-
<AppStatusCard
263-
appDetails={appDetails}
264-
status={status}
265-
cardLoading={cardLoading}
266-
setDetailed={setDetailed}
267-
message={message}
268-
/>
295+
{status && (
296+
<AppStatusCard
297+
// TODO: Fix and remove
298+
// @ts-ignore
299+
appDetails={appDetails}
300+
status={status}
301+
cardLoading={cardLoading}
302+
setDetailed={setDetailed}
303+
message={message}
304+
/>
269305
)}
270-
{isVirtualEnvironment && renderGeneratedManifestDownloadCard()}
271306
{!helmMigratedAppNotTriggered && (
272307
<>
273308
{!loadingResourceTree && (
@@ -278,10 +313,24 @@ export const SourceInfo = ({
278313
setDetailed={setDetailed}
279314
/>
280315
)}
316+
{isIsolatedEnv && (
317+
<HelmAppConfigApplyStatusCard
318+
cardLoading={cardLoading}
319+
releaseStatus={appDetails.resourceTree.releaseStatus}
320+
/>
321+
)}
322+
</>
323+
)}
324+
{isVirtualEnvironment && !isIsolatedEnv && renderGeneratedManifestDownloadCard()}
325+
{!helmMigratedAppNotTriggered && (
326+
<>
281327
<DeploymentStatusCard
282328
deploymentStatusDetailsBreakdownData={deploymentStatusDetailsBreakdownData}
283329
cardLoading={cardLoading}
284-
hideDetails={appDetails?.deploymentAppType === DeploymentAppTypes.HELM}
330+
hideDetails={
331+
appDetails?.deploymentAppType === DeploymentAppTypes.HELM ||
332+
isIsolatedEnv
333+
}
285334
isVirtualEnvironment={isVirtualEnvironment}
286335
refetchDeploymentStatus={refetchDeploymentStatus}
287336
/>

src/components/app/details/appDetails/appDetails.scss

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1927,11 +1927,6 @@ table.resource-tree {
19271927
margin-left: 8px !important;
19281928
}
19291929

1930-
.app-details-manifest-download-card {
1931-
overflow: hidden;
1932-
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2);
1933-
}
1934-
19351930
.app-details-info-card {
19361931
align-items: flex-start;
19371932
flex-direction: column;

src/components/app/details/appDetails/appDetails.type.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ export interface SecurityVulnerabilityCardType {
239239
}
240240

241241
export interface DeployedCommitCardType {
242-
showCommitInfoDrawer: () => void
242+
showCommitInfoDrawer: (e) => void
243243
cardLoading?: boolean
244244
envId: number | string
245245
ciArtifactId: number

src/components/app/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
RuntimeParamsListItemType,
2626
RuntimeParamsTriggerPayloadType,
2727
ReleaseMode,
28+
HelmReleaseStatus,
2829
} from '@devtron-labs/devtron-fe-common-lib'
2930
import { RouteComponentProps } from 'react-router'
3031
import { AppEnvironment } from '../../services/service.types'
@@ -90,9 +91,14 @@ export interface CDModalProps {
9091
parentEnvironmentName: string
9192
ciPipelineId?: number
9293
isRedirectedFromAppDetails?: boolean
94+
deploymentUserActionState?: ACTION_STATE
9395
}
9496

9597
export interface AppDetails extends CDModalProps {
98+
appStoreChartId: number
99+
appStoreChartName: string
100+
appStoreAppVersion: string
101+
appStoreAppName: string
96102
appId: number
97103
deploymentAppType?: DeploymentAppTypes
98104
externalCi?: boolean
@@ -187,6 +193,10 @@ interface ResourceTree {
187193
status: string
188194
podMetadata: PodMetadatum[]
189195
conditions?: any
196+
releaseStatus?: HelmReleaseStatus
197+
// lastSnapshotTime and wfrId are only available for isolated
198+
lastSnapshotTime?: string
199+
wfrId?: number
190200
}
191201

192202
interface Node {

0 commit comments

Comments
 (0)