Skip to content

Commit 60936ef

Browse files
committed
feat: add resource conflict management components and enhance related functionality
1 parent 7f658c5 commit 60936ef

11 files changed

Lines changed: 212 additions & 104 deletions

src/Common/API/reactQueryHooks.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,18 @@ import {
2828
import { ServerErrors } from '@Common/ServerError'
2929
import { ResponseType } from '@Common/Types'
3030

31-
export const useQuery = <TQueryFnData = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
32-
options: UseQueryOptions<ResponseType<TQueryFnData>, ServerErrors, TData, TQueryKey>,
31+
export const useQuery = <
32+
TQueryFnData = unknown,
33+
TData = TQueryFnData,
34+
TQueryKey extends QueryKey = QueryKey,
35+
WrapWithResponseType extends boolean = true,
36+
>(
37+
options: UseQueryOptions<
38+
WrapWithResponseType extends true ? ResponseType<TQueryFnData> : TQueryFnData,
39+
ServerErrors,
40+
TData,
41+
TQueryKey
42+
>,
3343
): UseQueryResult<TData, ServerErrors> => rqUseQuery(options)
3444

3545
export const useMutation = <TData = unknown, TVariables = void, TContext = unknown>(

src/Common/Constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ export const ROUTES = {
162162
LICENSE_DATA: 'license/data',
163163
ENV: 'env',
164164
APP_METADATA: 'app-metadata',
165+
RESOURCE_CONFLICTS_LIST: 'app/template/helm-ownership-conflicts',
165166
} as const
166167

167168
export enum KEY_VALUE {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[id*="table__resource-conflict-details"] {
2+
.generic-table__row {
3+
.generic-table__cell {
4+
display: flex;
5+
align-items: center;
6+
padding: 10px 0;
7+
}
8+
}
9+
}

src/Shared/Components/CICDHistory/ConflictedResourcesTable.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { useMemo } from 'react'
22

3-
import { noop } from '@Common/Helper'
4-
53
import { FiltersTypeEnum, PaginationEnum, Table, TableViewWrapperProps } from '../Table'
64
import { RowsType } from '../Table/types'
75
import { CONFLICTED_RESOURCES_COLUMNS } from './constants'
86
import { ConflictedResourcesTableProps, ResourceConflictItemType } from './types'
97

8+
import './ConflictedResourcesTable.scss'
9+
1010
const Wrapper = ({ children }: TableViewWrapperProps<unknown, FiltersTypeEnum.STATE>) => <div>{children}</div>
11+
const filter = () => true
1112

1213
const ConflictedResourcesTable = ({ resourceConflictDetails }: ConflictedResourcesTableProps) => {
1314
const rows: RowsType<ResourceConflictItemType> = useMemo(
@@ -39,7 +40,7 @@ const ConflictedResourcesTable = ({ resourceConflictDetails }: ConflictedResourc
3940
}}
4041
filtersVariant={FiltersTypeEnum.STATE}
4142
ViewWrapper={Wrapper}
42-
filter={noop}
43+
filter={filter}
4344
/>
4445
)
4546
}

src/Shared/Components/CICDHistory/ResourceConflictDeployDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const ResourceConflictDeployDialog = ({ appName, environmentName, handleClose }:
3030
description: `Redeployment for application '${appName}' in environment '${environmentName}' has been initiated successfully.`,
3131
})
3232
handleClose()
33-
history.push(`${URLS.APPLICATION_MANAGEMENT_APP}/${appId}/details/${envId}`)
33+
history.push(`${URLS.APP}/${appId}/details/${envId}`)
3434
} catch (error) {
3535
showError(error)
3636
} finally {

src/Shared/Components/CICDHistory/ResourceConflictDetailsModal.tsx

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import { Button, ButtonStyleType, ButtonVariantType } from '../Button'
1313
import { Icon } from '../Icon'
1414
import ConflictedResourcesTable from './ConflictedResourcesTable'
1515
import { getResourceConflictDetails, resourceConflictRedeploy } from './service'
16-
import { ResourceConflictDeployDialogURLParamsType, ResourceConflictDetailsModalProps } from './types'
16+
import {
17+
ResourceConflictDeployDialogURLParamsType,
18+
ResourceConflictDetailsModalProps,
19+
ResourceConflictItemType,
20+
} from './types'
1721

1822
const ResourceConflictDetailsModal = ({ appName, environmentName, handleClose }: ResourceConflictDetailsModalProps) => {
1923
const { appId, envId, pipelineId, triggerId } = useParams<ResourceConflictDeployDialogURLParamsType>()
@@ -24,11 +28,9 @@ const ResourceConflictDetailsModal = ({ appName, environmentName, handleClose }:
2428
data: resourceConflictDetails,
2529
refetch: refetchResourceConflictDetails,
2630
error: resourceConflictDetailsError,
27-
} = useQuery({
28-
queryKey: ['getResourceConflictDetails'],
29-
// TODO: Signal
30-
queryFn: () => getResourceConflictDetails(),
31-
select: (data) => data.result,
31+
} = useQuery<ResourceConflictItemType[], ResourceConflictItemType[], [string, string, string, string], false>({
32+
queryKey: ['getResourceConflictDetails', pipelineId, triggerId, appId],
33+
queryFn: ({ signal }) => getResourceConflictDetails({ pipelineId, triggerId, appId, signal }),
3234
})
3335

3436
const [isDeploying, setIsDeploying] = useState(false)
@@ -47,7 +49,7 @@ const ResourceConflictDetailsModal = ({ appName, environmentName, handleClose }:
4749
description: `Redeployment for application '${appName}' in environment '${environmentName}' has been initiated successfully.`,
4850
})
4951
handleClose()
50-
history.push(`${URLS.APPLICATION_MANAGEMENT_APP}/${appId}/details/${envId}`)
52+
history.push(`${URLS.APP}/${appId}/details/${envId}`)
5153
} catch (error) {
5254
showError(error)
5355
} finally {
@@ -77,7 +79,7 @@ const ResourceConflictDetailsModal = ({ appName, environmentName, handleClose }:
7779
/>
7880
</div>
7981

80-
<div className="flexbox flex-grow-1 dc__overflow-auto w-100">
82+
<div className="flexbox-col flex-grow-1 dc__overflow-auto w-100">
8183
<APIResponseHandler
8284
isLoading={isLoadingResourceData}
8385
progressingProps={{
@@ -95,24 +97,32 @@ const ResourceConflictDetailsModal = ({ appName, environmentName, handleClose }:
9597
</div>
9698
</div>
9799

98-
<div className="flexbox dc__content-end dc__gap-12 py-16 px-20 border__primary--top dc__no-shrink">
99-
<Button
100-
dataTestId="footer-cancel-button"
101-
variant={ButtonVariantType.secondary}
102-
text="Cancel"
103-
style={ButtonStyleType.neutral}
104-
size={ComponentSizeType.large}
105-
onClick={handleClose}
106-
/>
107-
108-
<Button
109-
dataTestId="footer-redeploy-button"
110-
variant={ButtonVariantType.primary}
111-
size={ComponentSizeType.large}
112-
text="Re-deploy"
113-
isLoading={isDeploying}
114-
onClick={handleDeploy}
115-
/>
100+
<div className="flexbox dc__content-space dc__gap-20 py-16 px-20 border__primary--top dc__no-shrink">
101+
<div className="flexbox dc__gap-8">
102+
<Icon name="ic-warning" size={20} color={null} />
103+
<div className="flexbox-col">
104+
<span className="cn-9 fs-13 fw-6 lh-1-5">Take resource ownership and redeploy</span>
105+
<span>
106+
Ensure all resources strictly belong to the {appName} application and the&nbsp;
107+
{environmentName}
108+
environment. Any resource outside this Helm release may cause incorrect associations and
109+
potentially destructive changes.
110+
</span>
111+
</div>
112+
</div>
113+
<div className="dc__no-shrink">
114+
<Button
115+
dataTestId="footer-redeploy-button"
116+
variant={ButtonVariantType.primary}
117+
style={ButtonStyleType.warning}
118+
size={ComponentSizeType.large}
119+
text="Re-deploy"
120+
startIcon={<Icon name="ic-rocket-launch" color={null} />}
121+
isLoading={isDeploying}
122+
disabled={!!resourceConflictDetailsError || isLoadingResourceData}
123+
onClick={handleDeploy}
124+
/>
125+
</div>
116126
</div>
117127
</div>
118128
</Drawer>

src/Shared/Components/CICDHistory/TriggerDetails.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ const TriggerDetails = memo(
491491
/>
492492
&nbsp;
493493
<span className="cn-9 fw-4 fs-13 lh-20 dc__word-break">
494-
have ownership conflict. Take resource ownership and re-deploy
494+
have ownership conflicts. Resolve by taking ownership and redeploying.
495495
</span>
496496
</div>
497497
)
@@ -635,8 +635,9 @@ const TriggerDetails = memo(
635635
namespace={namespace}
636636
>
637637
{showResourceConflictInfoBlock && (
638-
<div className="py-12 pr-12">
638+
<div className="pt-12 pr-12">
639639
<InfoBlock
640+
variant="warning"
640641
description={renderInfoBlockDescription()}
641642
buttonProps={{
642643
dataTestId: 'resource-conflict-re-deploy',

src/Shared/Components/CICDHistory/constants.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { stringComparatorBySortOrder } from '@Shared/Helpers'
1718
import { WorkflowStatusEnum } from '@Shared/types'
1819

1920
import { multiSelectStyles } from '../../../Common/MultiSelectCustomization'
@@ -186,6 +187,7 @@ export const CONFLICTED_RESOURCES_COLUMNS: TableProps<ResourceConflictItemType,
186187
},
187188
},
188189
isSortable: true,
190+
comparator: stringComparatorBySortOrder,
189191
horizontallySticky: true,
190192
},
191193
{
@@ -198,6 +200,7 @@ export const CONFLICTED_RESOURCES_COLUMNS: TableProps<ResourceConflictItemType,
198200
minWidth: 100,
199201
},
200202
},
203+
comparator: stringComparatorBySortOrder,
201204
isSortable: true,
202205
},
203206
{
@@ -211,5 +214,6 @@ export const CONFLICTED_RESOURCES_COLUMNS: TableProps<ResourceConflictItemType,
211214
},
212215
},
213216
isSortable: true,
217+
comparator: stringComparatorBySortOrder,
214218
},
215219
]

src/Shared/Components/CICDHistory/service.tsx

Lines changed: 77 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
/* eslint-disable dot-notation */
1818
import moment from 'moment'
1919

20+
import { GVKType, K8S_EMPTY_GROUP } from '@Pages/ResourceBrowser'
21+
2022
import {
2123
get,
2224
getUrlWithSearchParams,
@@ -27,16 +29,20 @@ import {
2729
trash,
2830
} from '../../../Common'
2931
import { DATE_TIME_FORMAT_STRING, DEPLOYMENT_HISTORY_CONFIGURATION_LIST_MAP, EXTERNAL_TYPES } from '../../constants'
30-
import { decode, getUniqueId, isNullOrUndefined } from '../../Helpers'
32+
import { decode, getGVKTitle, getUniqueId, isNullOrUndefined } from '../../Helpers'
3133
import { ResourceKindType, ResourceVersionType } from '../../types'
3234
import {
3335
DeploymentHistoryDetail,
3436
DeploymentHistoryResult,
3537
DeploymentHistorySingleValue,
3638
DeploymentStatusDetailsResponse,
3739
FetchIdDataStatus,
40+
GetResourceConflictDetailsParamsType,
41+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
42+
GetResourceListItemPayloadType,
3843
ModuleConfigResponse,
3944
ResourceConflictItemType,
45+
ResourceConflictListItemDTO,
4046
ResourceConflictRedeployParamsType,
4147
ResourceConflictRedeployPayloadType,
4248
TriggerDetailsResponseType,
@@ -312,57 +318,78 @@ export const resourceConflictRedeploy = async ({ pipelineId, triggerId, appId }:
312318
redeployHelmReleaseWithTakeOwnership: true,
313319
})
314320

315-
export const getResourceConflictDetails = async (): Promise<ResponseType<ResourceConflictItemType[]>> => ({
316-
code: 200,
317-
result: [
318-
{
319-
name: 'resource-1',
320-
namespace: 'default',
321-
gvk: {
322-
Group: 'apps',
323-
Version: 'v1',
324-
Kind: 'Deployment',
321+
export const getResourceConflictDetails = async ({
322+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
323+
appId,
324+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
325+
pipelineId,
326+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
327+
triggerId,
328+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
329+
signal,
330+
}: GetResourceConflictDetailsParamsType): Promise<ResourceConflictItemType[]> => {
331+
// const { result } = await post<ResourceConflictListItemDTO, GetResourceListItemPayloadType>(
332+
// ROUTES.RESOURCE_CONFLICTS_LIST,
333+
// {
334+
// appId: +appId,
335+
// pipelineId: +pipelineId,
336+
// wfrId: +triggerId,
337+
// },
338+
// { signal },
339+
// )
340+
341+
const MOCK_RESULT: ResourceConflictListItemDTO = {
342+
clusterId: 1,
343+
conflictingResources: [
344+
{
345+
name: 'resource-1',
346+
namespace: 'default',
347+
groupVersionKind: {
348+
Group: 'apps',
349+
Version: 'v1',
350+
Kind: 'Deployment',
351+
},
325352
},
326-
gvkTitle: 'Deployment',
327-
clusterId: 1,
328-
id: getUniqueId(),
329-
},
330-
{
331-
name: 'resource-2',
332-
namespace: 'default',
333-
gvk: {
334-
Group: '',
335-
Version: 'v1',
336-
Kind: 'Service',
353+
{
354+
name: 'resource-2',
355+
namespace: 'default',
356+
groupVersionKind: {
357+
Group: '',
358+
Version: 'v1',
359+
Kind: 'Service',
360+
},
337361
},
338-
gvkTitle: 'Service',
339-
clusterId: 1,
340-
id: getUniqueId(),
341-
},
342-
{
343-
name: 'resource-3',
344-
namespace: 'default',
345-
gvk: {
346-
Group: 'apps',
347-
Version: 'v1',
348-
Kind: 'StatefulSet',
362+
{
363+
name: 'resource-3',
364+
namespace: 'default',
365+
groupVersionKind: {
366+
Group: 'apps',
367+
Version: 'v1',
368+
Kind: 'StatefulSet',
369+
},
349370
},
350-
gvkTitle: 'StatefulSet',
351-
clusterId: 1,
352-
id: getUniqueId(),
353-
},
354-
{
355-
name: 'resource-4',
356-
namespace: 'default',
357-
gvk: {
358-
Group: 'batch',
359-
Version: 'v1',
360-
Kind: 'Job',
371+
{
372+
name: 'resource-4',
373+
namespace: 'default',
374+
groupVersionKind: {
375+
Group: 'batch',
376+
Version: 'v1',
377+
Kind: 'Job',
378+
},
361379
},
362-
gvkTitle: 'Job',
363-
clusterId: 1,
364-
id: getUniqueId(),
380+
],
381+
}
382+
383+
return (MOCK_RESULT?.conflictingResources || []).map<ResourceConflictItemType>((resource) => ({
384+
name: resource.name || '',
385+
namespace: resource.namespace || '',
386+
gvk: {
387+
Group: resource.groupVersionKind.Group || K8S_EMPTY_GROUP,
388+
Version: resource.groupVersionKind.Version || '',
389+
Kind: resource.groupVersionKind.Kind || ('' as GVKType['Kind']),
365390
},
366-
],
367-
status: 'OK',
368-
})
391+
gvkTitle: getGVKTitle(resource.groupVersionKind),
392+
clusterId: MOCK_RESULT.clusterId,
393+
id: getUniqueId(),
394+
}))
395+
}

0 commit comments

Comments
 (0)