Skip to content

feature: add EKS create cluster #2631

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 51 commits into from
May 15, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
7f7ce6c
feat: add environment column in namespace list
Elessar1802 Apr 3, 2025
c33683c
Merge pull request #2624 from devtron-labs/feat/add-environment-ns-list
Elessar1802 Apr 3, 2025
7b854ec
feat: add cluster name to modal header
Elessar1802 Apr 4, 2025
183aab0
fix: add cluster button in cluster list
Elessar1802 Apr 4, 2025
e8b3919
feat: CreateCluster in ClustersAndEnvironments
Elessar1802 Apr 6, 2025
2872262
Merge branch 'feature/create-cluster' of github.com:devtron-labs/dash…
Elessar1802 Apr 7, 2025
628c25e
feat: add ClusterConfig in cluster overview & integrate create cluste…
Elessar1802 Apr 7, 2025
82e0342
feat: show installation clusters in cluster list
Elessar1802 Apr 8, 2025
eedce6f
Merge branch 'feat/edit-cluster' of https://github.com/devtron-labs/d…
arunjaindev Apr 8, 2025
ff2103c
feat: add support for category label filters in chart listing
arunjaindev Apr 8, 2025
d4c3bb1
feat: add RESOURCE_BROWSER_INSTALLATION_CLUSTER to RB router
Elessar1802 Apr 8, 2025
f54785d
Merge branch 'feat/edit-cluster' of https://github.com/devtron-labs/d…
arunjaindev Apr 8, 2025
126d069
feat: add cluster installation page
arunjaindev Apr 8, 2025
5272ac4
feat: incorporate connect cluster & isolated cluster
Elessar1802 Apr 8, 2025
861cdd6
Merge branch 'feat/edit-cluster' of https://github.com/devtron-labs/d…
arunjaindev Apr 8, 2025
85ae37e
chore(text): change connect cluster to new cluster in RB page header
Elessar1802 Apr 8, 2025
7f420c4
fix: show all installation clusters not found in cluster list
Elessar1802 Apr 9, 2025
e8b73db
feat: add page header on cluster installation status page
arunjaindev Apr 9, 2025
34361a0
feat: update filter empty state
arunjaindev Apr 9, 2025
9b15d0f
fix: redirect to installation status after cluster creation
Elessar1802 Apr 9, 2025
6895d52
Merge branch 'feat/chart-category-filters' of github.com:devtron-labs…
Elessar1802 Apr 9, 2025
69e02df
Merge branch 'main' of https://github.com/devtron-labs/dashboard into…
arunjaindev Apr 9, 2025
009161a
Merge branch 'feature/create-cluster' of github.com:devtron-labs/dash…
Elessar1802 Apr 9, 2025
7a2d1f8
Merge branch 'feat/edit-cluster' of github.com:devtron-labs/dashboard…
Elessar1802 Apr 9, 2025
f3b52ae
chore: update common-lib version
Elessar1802 Apr 9, 2025
dc27867
fix: polling in cluster overview
Elessar1802 Apr 9, 2025
2cc2f8a
chore: update common-lib version
Elessar1802 Apr 10, 2025
0377d54
Merge pull request #2635 from devtron-labs/feat/edit-cluster
Elessar1802 Apr 11, 2025
5481073
Merge branch 'feat/eks-demo' into feature/create-cluster
Elessar1802 Apr 11, 2025
a6390d2
feat: add enterprise feature dialog
arunjaindev Apr 11, 2025
6556258
Merge branch 'develop' of github.com:devtron-labs/dashboard into feat…
Elessar1802 Apr 16, 2025
95a6174
fix: review comments
Elessar1802 Apr 16, 2025
9a4027d
fix: review comment
Elessar1802 Apr 16, 2025
e70370a
fix: review comment
Elessar1802 Apr 16, 2025
473d780
refactor: cluster form & open create cluster drawer in RB
Elessar1802 Apr 22, 2025
26dd52f
fix(text|style): cluster form
Elessar1802 Apr 22, 2025
dd4e830
refactor: cluster overview & don't fail on capacity api fail
Elessar1802 Apr 22, 2025
e43f596
feat: add DeleteClusterConfirmationModal & use in RB page header
Elessar1802 Apr 24, 2025
7f154a9
fix: self review
Elessar1802 Apr 24, 2025
3980e5f
fix: cluster form styles
Elessar1802 Apr 25, 2025
1ee2cbb
chore: conserve data testids of create cluster form in sidebar
Elessar1802 Apr 28, 2025
e60631a
Merge branch 'develop' of github.com:devtron-labs/dashboard into feat…
Elessar1802 Apr 28, 2025
7602733
fix: review comments
Elessar1802 Apr 30, 2025
1737460
Merge branch 'develop' of github.com:devtron-labs/dashboard into feat…
Elessar1802 Apr 30, 2025
ff3db79
chore: remove unneeded comment
Elessar1802 Apr 30, 2025
0e22a7c
chore: add data-testid
Elessar1802 May 9, 2025
e695fad
fix: update cluster config poll interval
Elessar1802 May 13, 2025
279b2f3
fix: add missing mb-16
Elessar1802 May 13, 2025
ac8a548
Merge branch 'develop' of github.com:devtron-labs/dashboard into feat…
Elessar1802 May 15, 2025
5d6de68
chore: bump common-lib version
Elessar1802 May 15, 2025
54d7a9f
Merge branch 'develop' of github.com:devtron-labs/dashboard into feat…
Elessar1802 May 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const ClusterEnvironmentDrawer = ({
reload,
hideClusterDrawer,
isVirtual,
clusterName,
}: ClusterEnvironmentDrawerProps) => {
// STATES
// Manages the loading state for create and update actions
Expand Down Expand Up @@ -400,7 +401,9 @@ export const ClusterEnvironmentDrawer = ({
<Drawer position="right" width="800px" onEscape={hideClusterDrawer} onClose={hideClusterDrawer}>
<div className="h-100 bg__primary flexbox-col" onClick={stopPropagation}>
<div className="flexbox dc__align-items-center dc__content-space dc__border-bottom bg__primary py-12 px-20">
<h3 className="m-0 fs-16 fw-6 lh-1-43">{id ? 'Edit Environment' : 'Add Environment'}</h3>
<h3 className="m-0 fs-16 fw-6 lh-1-43">
{id ? 'Edit Environment' : `Add Environment in '${clusterName}'`}
</h3>
<button
type="button"
aria-label="close-btn"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface ClusterEnvironmentDrawerProps extends ClusterEnvironmentDrawerF
reload: () => void
hideClusterDrawer: () => void
isVirtual: boolean
clusterName: string
}

export type GetClusterEnvironmentUpdatePayloadType = Pick<
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import {
Button,
ButtonComponentType,
ButtonStyleType,
ButtonVariantType,
ComponentSizeType,
DEFAULT_ROUTE_PROMPT_MESSAGE,
Drawer,
stopPropagation,
} from '@devtron-labs/devtron-fe-common-lib'
import { Prompt, Redirect, useHistory, useParams } from 'react-router-dom'
import { useState } from 'react'
import { ReactComponent as ICClose } from '@Icons/ic-close.svg'
import { URLS } from '@Config/routes'
import { importComponentFromFELibrary } from '@Components/common'

import { CreateClusterParams, CreateClusterTypeEnum } from './types'
import Sidebar from './Sidebar'
import FooterComponent from './FooterComponent'

const CreateClusterForm = importComponentFromFELibrary('CreateClusterForm', null, 'function')

const CreateCluster = () => {
const { type } = useParams<CreateClusterParams>()

const [apiCallInProgress, setApiCallInProgress] = useState(false)

const { push } = useHistory()

const handleRedirectToClusterList = () => {
push(URLS.GLOBAL_CONFIG_CLUSTER)
}

const renderContent = () => {
switch (type) {
case CreateClusterTypeEnum.CONNECT_CLUSTER:
return 'connect cluster'
case CreateClusterTypeEnum.CREATE_EKS_CLUSTER:
return (
<CreateClusterForm
apiCallInProgress={apiCallInProgress}
setApiCallInProgress={setApiCallInProgress}
handleModalClose={handleRedirectToClusterList}
FooterComponent={FooterComponent}
/>
)
case CreateClusterTypeEnum.ADD_ISOLATED_CLUSTER:
return 'create isolated cluster'
default:
return <Redirect to={URLS.GLOBAL_CONFIG_CLUSTER} />
}
}

return (
<Drawer
position="right"
width="1024px"
onEscape={handleRedirectToClusterList}
onClose={handleRedirectToClusterList}
>
<dialog
className="bg__primary h-100 cn-9 w-100 flexbox-col dc__overflow-hidden p-0"
onClick={stopPropagation}
>
<header className="px-20 py-12 lh-24 flexbox dc__content-space dc__align-items-center dc__border-bottom">
<span className="fs-16 fw-6 dc__first-letter-capitalize">New Cluster</span>

<Button
icon={<ICClose />}
dataTestId="close-create-cluster-modal-button"
component={ButtonComponentType.button}
style={ButtonStyleType.negativeGrey}
size={ComponentSizeType.xs}
variant={ButtonVariantType.borderLess}
ariaLabel="Close new cluster drawer"
showTooltip={apiCallInProgress}
tooltipProps={{
content: DEFAULT_ROUTE_PROMPT_MESSAGE,
}}
disabled={apiCallInProgress}
onClick={handleRedirectToClusterList}
showAriaLabelInTippy={false}
/>
</header>

<div className="flexbox flex-grow-1 dc__overflow-hidden">
<Sidebar />

<div className="bg__tertiary flex-grow-1 flexbox-col dc__overflow-auto p-20 dc__gap-16">
{renderContent()}
</div>
</div>

<Prompt when={apiCallInProgress} message={DEFAULT_ROUTE_PROMPT_MESSAGE} />
</dialog>
</Drawer>
)
}

export default CreateCluster
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Button, ButtonVariantType, NewClusterFormFooterProps } from '@devtron-labs/devtron-fe-common-lib'

Check failure on line 1 in src/Pages/GlobalConfigurations/ClustersAndEnvironments/CreateCluster/FooterComponent.tsx

View workflow job for this annotation

GitHub Actions / ci

Module '"@devtron-labs/devtron-fe-common-lib"' has no exported member 'NewClusterFormFooterProps'.

Check failure on line 1 in src/Pages/GlobalConfigurations/ClustersAndEnvironments/CreateCluster/FooterComponent.tsx

View workflow job for this annotation

GitHub Actions / ci

Module '"@devtron-labs/devtron-fe-common-lib"' has no exported member 'NewClusterFormFooterProps'.
import { PropsWithChildren } from 'react'

const FooterComponent = ({
apiCallInProgress,
handleModalClose,
children,
}: PropsWithChildren<NewClusterFormFooterProps>) => (
<footer className="dc__position-abs dc__bottom-0 dc__left-0 w-100 dc__zi-1 bg__primary flexbox dc__content-end dc__border-top-n1 px-20 py-16 dc__gap-12 dc__no-shrink">
<Button
dataTestId="cancel-create-cluster-button"
onClick={handleModalClose}
disabled={apiCallInProgress}
text="Cancel"
variant={ButtonVariantType.secondary}
/>

{children}
</footer>
)

export default FooterComponent
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2024. Devtron Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Icon, IconName, ModalSidebarPanel } from '@devtron-labs/devtron-fe-common-lib'
import { DOCUMENTATION } from '@Config/constants'
import { generatePath, NavLink, useParams } from 'react-router-dom'
import { URLS } from '@Config/routes'

import { CreateClusterParams } from './types'
import { SIDEBAR_CONFIG } from './constants'

const Sidebar = () => {
const { type } = useParams<CreateClusterParams>()

const selectedSidebarElement = SIDEBAR_CONFIG[type]

return (
<div className="w-250 p-20 flexbox-col dc__gap-24 dc__no-shrink dc__overflow-auto">
<div className="flexbox-col">
{Object.entries(SIDEBAR_CONFIG).map(([key, { title, iconName }]) => {
const isSelected = type.toLowerCase() === key.toLowerCase()

return (
<NavLink
className={`dc__transparent flex left dc__gap-8 py-6 px-8 br-4 ${isSelected ? 'bcb-1' : 'dc__hover-n50'}`}
to={generatePath(URLS.GLOBAL_CONFIG_CREATE_CLUSTER, { type: key })}
>
<span className="dc__fill-available-space dc__no-shrink icon-dim-16">
<Icon name={iconName as IconName} color={isSelected ? 'B500' : 'N600'} />
</span>

<span className={`fs-13 lh-20 dc__truncate ${isSelected ? 'cb-5 fw-6' : 'cn-9'}`}>
{title}
</span>
</NavLink>
)
})}
</div>

<div className="divider__secondary--horizontal" />

<ModalSidebarPanel
heading={selectedSidebarElement.documentationHeader ?? selectedSidebarElement.title}
documentationLink={DOCUMENTATION.CLUSTER_AND_ENVIRONMENT}
rootClassName="w-100 dc__no-background-imp"
>
<div className="flexbox-col dc__gap-24">{selectedSidebarElement.body}</div>
</ModalSidebarPanel>
</div>
)
}

export default Sidebar
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { IconName } from '@devtron-labs/devtron-fe-common-lib'
import { CreateClusterTypeEnum, SidebarConfigType } from './types'

export const SIDEBAR_CONFIG: SidebarConfigType = {
[CreateClusterTypeEnum.CONNECT_CLUSTER]: {
title: 'Connect cluster',
iconName: 'ic-ci-linked' as IconName,
body: (
<p className="m-0">
Connect an existing Kubernetes cluster to manage Kubernetes resources and deploy containerized
applications using Devtron.
</p>
),
},
[CreateClusterTypeEnum.CREATE_EKS_CLUSTER]: {
title: 'Create EKS cluster',
iconName: 'ic-cluster' as IconName,
body: (
<>
<p className="m-0">With Devtron, you can effortlessly create an Amazon EKS cluster.</p>
<p className="m-0">
Amazon Elastic Kubernetes Service (Amazon EKS) is a fully managed Kubernetes service that enables
you to run Kubernetes seamlessly in both AWS Cloud and on-premises data centers.
</p>
</>
),
isEnterprise: true,
},
[CreateClusterTypeEnum.ADD_ISOLATED_CLUSTER]: {
title: 'Add Isolated Cluster',
iconName: 'ic-add' as IconName,
documentationHeader: 'Isolated Cluster',
body: (
<>
<p className="m-0">
An isolated cluster in Devtron is an air-gapped Kubernetes cluster with restricted network access.
</p>
<p className="m-0">
Since Devtron does not have connectivity to these clusters, deployments are managed by packaging
manifests and images for manual installation or retrieval from an OCI registry (if enabled).
</p>
</>
),
isEnterprise: true,
},
} as const
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as CreateClusterDrawer } from './CreateCluster.component'
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export enum CreateClusterTypeEnum {
CONNECT_CLUSTER = 'connect-cluster',
CREATE_EKS_CLUSTER = 'create-eks-cluster',
ADD_ISOLATED_CLUSTER = 'add-isolated-cluster',
}

export type SidebarConfigType = Record<
CreateClusterTypeEnum,
{
title: string
iconName: string
body: React.ReactElement
documentationHeader?: string
isEnterprise?: true
}
>

export interface CreateClusterParams {
type: CreateClusterTypeEnum
}
7 changes: 2 additions & 5 deletions src/assets/icons/ic-link.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 12 additions & 9 deletions src/components/ResourceBrowser/PageHeader.buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
*/

import React, { useState } from 'react'
import { NavLink } from 'react-router-dom'
import { Button, ComponentSizeType } from '@devtron-labs/devtron-fe-common-lib'
import { Button, ButtonComponentType, ComponentSizeType } from '@devtron-labs/devtron-fe-common-lib'
import { URLS } from '../../config'
import { CreateResource } from './ResourceList/CreateResource'
import { CreateResourceButtonType, CreateResourceType } from './Types'
Expand Down Expand Up @@ -52,13 +51,17 @@ export const renderCreateResourceButton = (clusterId: string, callback: CreateRe

export const AddClusterButton = (): JSX.Element => (
<div>
<NavLink
className="flex dc__no-decor cta small h-28 pl-8 pr-10 pt-5 pb-5 lh-n fcb-5"
to={URLS.GLOBAL_CONFIG_CLUSTER}
>
<Add data-testid="add_cluster_button" className="icon-dim-16 mr-4 fcb-5 dc__vertical-align-middle" />
Add cluster
</NavLink>
<Button
dataTestId="add_cluster_button"
text="Connect Cluster"
component={ButtonComponentType.link}
size={ComponentSizeType.small}
startIcon={<Add />}
linkProps={{
to: URLS.GLOBAL_CONFIG_CREATE_CLUSTER,
target: '_blank',
}}
/>
<span className="dc__divider" />
</div>
)
36 changes: 36 additions & 0 deletions src/components/ResourceBrowser/ResourceBrowser.service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
getUrlWithSearchParams,
getK8sResourceListPayload,
stringComparatorBySortOrder,
Nodes,
getNamespaceListMin,
} from '@devtron-labs/devtron-fe-common-lib'
import { RefObject } from 'react'
import { Routes } from '../../config'
Expand Down Expand Up @@ -77,6 +79,40 @@ export const getResourceData = async ({
return parseNodeList(response)
}

if (selectedResource.gvk.Kind.toLowerCase() === Nodes.Namespace.toLowerCase()) {
const { result } = await getNamespaceListMin(clusterId)
const [{ environments }] = result

const response = await getK8sResourceList(
getK8sResourceListPayload(clusterId, selectedNamespace.value.toLowerCase(), selectedResource, filters),
abortControllerRef.current.signal,
)

const namespaceToEnvironmentMap = environments.reduce(
(acc, { environmentName, namespace, environmentId }) => {
if (environmentId === 0) {
return acc
}

acc[namespace] = environmentName
return acc
},
{},
)

return {
...response,
result: {
...response.result,
headers: [...response.result.headers, 'environment'],
data: response.result.data.map((data) => ({
...data,
environment: namespaceToEnvironmentMap[data.name as string],
})),
},
}
}

return await getK8sResourceList(
getK8sResourceListPayload(clusterId, selectedNamespace.value.toLowerCase(), selectedResource, filters),
abortControllerRef.current.signal,
Expand Down
Loading
Loading