Skip to content

Commit

Permalink
feat: add basic authentication for dashboard (#955)
Browse files Browse the repository at this point in the history
Signed-off-by: Xuhui zhang <[email protected]>
  • Loading branch information
zxh326 authored Jun 3, 2024
1 parent 30de505 commit 618d371
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 81 deletions.
15 changes: 15 additions & 0 deletions cmd/dashboard/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ var (
leaderElection bool
leaderElectionNamespace string
leaderElectionLeaseDuration time.Duration

// for basic auth
USERNAME string
PASSWORD string
)

func main() {
Expand All @@ -78,6 +82,12 @@ func main() {
},
}

if v := os.Getenv("USERNAME"); v != "" {
USERNAME = v
}
if v := os.Getenv("PASSWORD"); v != "" {
PASSWORD = v
}
cmd.PersistentFlags().Uint16Var(&port, "port", 8088, "port to listen on")
cmd.PersistentFlags().BoolVar(&devMode, "dev", false, "enable dev mode")
cmd.PersistentFlags().StringVar(&staticDir, "static-dir", "", "static files to serve")
Expand Down Expand Up @@ -150,6 +160,11 @@ func run() {
c.File(filepath.Join(staticDir, path))
})
}
if USERNAME != "" && PASSWORD != "" {
router.Use(gin.BasicAuth(gin.Accounts{
USERNAME: PASSWORD,
}))
}
podApi.Handle(router.Group("/api/v1"))
addr := fmt.Sprintf(":%d", port)
srv := &http.Server{
Expand Down
4 changes: 3 additions & 1 deletion dashboard-ui/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

import { DarkMode, Question, SelectLang } from '@/components/RightContent'
import { Flex } from 'antd'
import { RuntimeConfig } from 'umi'
import { RequestConfig, RuntimeConfig } from 'umi'

export const request: RequestConfig = {}

// 运行时配置

Expand Down
98 changes: 44 additions & 54 deletions dashboard-ui/src/services/pod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
Node as RawNode,
Pod as RawPod,
} from 'kubernetes-types/core/v1'
import { request } from 'umi'

export type Pod = RawPod & {
mountPods?: RawPod[]
Expand Down Expand Up @@ -251,10 +252,12 @@ export const listAppPods = async (args: AppPagingListArgs) => {
const mountPod = args.mountPod || ''
const pageSize = args.pageSize || 20
const current = args.current || 1
const pods = await fetch(
data = await request<{
pods: Pod[]
total: number
}>(
`${host}/api/v1/pods?order=${order}&namespace=${namespace}&name=${name}&pv=${pv}&mountpod=${mountPod}&csinode=${csiNode}&pageSize=${pageSize}&current=${current}`,
)
data = JSON.parse(await pods.text())
} catch (e) {
console.log(`fail to list pods: ${e}`)
return { data: null, success: false }
Expand All @@ -275,74 +278,59 @@ export const listAppPods = async (args: AppPagingListArgs) => {
export const getPod = async (namespace: string, podName: string) => {
let pod: Pod
try {
const rawPod = await fetch(`${host}/api/v1/pod/${namespace}/${podName}/`)
pod = JSON.parse(await rawPod.text())
pod = await request<Pod>(`${host}/api/v1/pod/${namespace}/${podName}/`)
} catch (e) {
console.log(`fail to get pod(${namespace}/${podName}): ${e}`)
return null
}
try {
const mountPods = await fetch(
`${host}/api/v1/pod/${pod.metadata?.namespace}/${pod.metadata?.name}/mountpods`,
)
pod.mountPods = JSON.parse(await mountPods.text())
} catch (e) {
console.log(`fail to get mount pod for pod(${namespace}/${podName}): ${e}`)
}
try {
const appPods = await fetch(
`${host}/api/v1/pod/${pod.metadata?.namespace}/${pod.metadata?.name}/apppods`,
)
pod.appPods = JSON.parse(await appPods.text())
} catch (e) {
console.log(`fail to get app pod for pod(${namespace}/${podName}): ${e}`)
}

if (pod.spec?.nodeName) {
try {
const csiNode = await fetch(
`${host}/api/v1/csi-node/${pod.spec?.nodeName}`,
)
pod.csiNode = JSON.parse(await csiNode.text())
} catch (e) {
console.log(`fail to get csi node for pod(${namespace}/${podName}): ${e}`)
}
try {
const node = await fetch(
`${host}/api/v1/pod/${pod.metadata?.namespace}/${pod.metadata?.name}/node`,
)
pod.node = JSON.parse(await node.text())
} catch (e) {
console.log(`fail to get node for pod(${namespace}/${podName}): ${e}`)
}
}

try {
const events = await fetch(
`${host}/api/v1/pod/${pod.metadata?.namespace}/${pod.metadata?.name}/events`,
)
let podEvents: Event[] = JSON.parse(await events.text()) || []
podEvents.sort((a, b) => {
const aTime = new Date(a.firstTimestamp || a.eventTime || 0).getTime()
const bTime = new Date(b.firstTimestamp || b.eventTime || 0).getTime()
return bTime - aTime
})
pod.events = podEvents
const [mountPods, appPods, csiNodePod, node, events] = await Promise.all([
request<Pod[]>(
`${host}/api/v1/pod/${pod.metadata?.namespace}/${pod.metadata?.name}/mountpods`,
),
request<Pod[]>(
`${host}/api/v1/pod/${pod.metadata?.namespace}/${pod.metadata?.name}/apppods`,
),
pod.spec?.nodeName
? request<Pod>(`${host}/api/v1/csi-node/${pod.spec?.nodeName}`)
: undefined,
pod.spec?.nodeName
? request<RawNode>(
`${host}/api/v1/pod/${pod.metadata?.namespace}/${pod.metadata?.name}/node`,
)
: undefined,
request<Event[]>(
`${host}/api/v1/pod/${pod.metadata?.namespace}/${pod.metadata?.name}/events`,
).then((podEvents) => {
podEvents.sort((a, b) => {
const aTime = new Date(a.firstTimestamp || a.eventTime || 0).getTime()
const bTime = new Date(b.firstTimestamp || b.eventTime || 0).getTime()
return bTime - aTime
})
return podEvents
}),
])

pod.mountPods = mountPods
pod.appPods = appPods
pod.csiNode = csiNodePod
pod.node = node
pod.events = events
pod.logs = new Map()
pod.finalStatus = podStatus(pod) || 'Unknown'
} catch (e) {
console.log(`fail to get events for pod(${namespace}/${podName}): ${e}`)
console.log(`fail to get pod(${namespace}/${podName}): ${e}`)
}

return pod
}

export const getLog = async (pod: Pod, container: string) => {
try {
const log = await fetch(
return await request(
`${host}/api/v1/pod/${pod.metadata?.namespace}/${pod.metadata?.name}/logs/${container}`,
)
return await log.text()
} catch (e) {
console.log(
`fail to get log of pod(${pod.metadata?.namespace}/${pod.metadata?.name}/${container}): ${e}`,
Expand Down Expand Up @@ -374,10 +362,12 @@ export const listSystemPods = async (args: SysPagingListArgs) => {
const node = args.node || ''
const pageSize = args.pageSize || 20
const current = args.current || 1
const podList = await fetch(
data = await request<{
pods: Pod[]
total: number
}>(
`${host}/api/v1/syspods?namespace=${namespace}&name=${name}&node=${node}&order=${order}&pageSize=${pageSize}&current=${current}`,
)
data = JSON.parse(await podList.text())
} catch (e) {
console.log(`fail to list sys pods: ${e}`)
return { data: null, success: false }
Expand Down
44 changes: 18 additions & 26 deletions dashboard-ui/src/services/pv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
PersistentVolumeClaim,
} from 'kubernetes-types/core/v1'
import { StorageClass } from 'kubernetes-types/storage/v1'
import { request } from 'umi'

export type PV = PersistentVolume & {
Pod: {
Expand Down Expand Up @@ -82,10 +83,12 @@ export const listPV = async (args: PVPagingListArgs) => {
const sc = args.sc || ''
const pageSize = args.pageSize || 20
const current = args.current || 1
const rawPV = await fetch(
data = await request<{
pvs: PV[]
total: number
}>(
`${host}/api/v1/pvs?order=${order}&name=${name}&pvc=${pvc}&sc=${sc}&pageSize=${pageSize}&current=${current}`,
)
data = JSON.parse(await rawPV.text())
} catch (e) {
console.log(`fail to list pv`)
return { data: null, success: false }
Expand Down Expand Up @@ -124,10 +127,12 @@ export const listPVC = async (args: PVCPagingListArgs) => {
const sc = args.sc || ''
const pageSize = args.pageSize || 20
const current = args.current || 1
const rawPVC = await fetch(
data = await request<{
pvcs: PVC[]
total: number
}>(
`${host}/api/v1/pvcs?order=${order}&namespace=${namespace}&name=${name}&pv=${pv}&sc=${sc}&pageSize=${pageSize}&current=${current}`,
)
data = JSON.parse(await rawPVC.text())
} catch (e) {
console.log(`fail to list pvc`)
return { data: null, success: false }
Expand All @@ -150,8 +155,7 @@ export interface SCPagingListArgs {
export const listStorageClass = async (args: SCPagingListArgs) => {
let data: StorageClass[] = []
try {
const rawSC = await fetch(`${host}/api/v1/storageclasses`)
data = JSON.parse(await rawSC.text())
data = await request<StorageClass[]>(`${host}/api/v1/storageclasses`)
} catch (e) {
console.log(`fail to list sc`)
return { data: [], success: false }
Expand Down Expand Up @@ -186,8 +190,7 @@ export const listStorageClass = async (args: SCPagingListArgs) => {

export const getPV = async (pvName: string) => {
try {
const rawPV = await fetch(`${host}/api/v1/pv/${pvName}/`)
return JSON.parse(await rawPV.text())
return await fetch(`${host}/api/v1/pv/${pvName}/`)
} catch (e) {
console.log(`fail to get pv(${pvName}): ${e}`)
return null
Expand All @@ -196,8 +199,7 @@ export const getPV = async (pvName: string) => {

export const getPVEvents = async (pvName: string) => {
try {
const events = await fetch(`${host}/api/v1/pv/${pvName}/events`)
return JSON.parse(await events.text())
return await fetch(`${host}/api/v1/pv/${pvName}/events`)
} catch (e) {
console.log(`fail to get pv events (${pvName}): ${e}`)
return null
Expand All @@ -206,8 +208,7 @@ export const getPVEvents = async (pvName: string) => {

export const getPVC = async (namespace: string, pvcName: string) => {
try {
const rawPV = await fetch(`${host}/api/v1/pvc/${namespace}/${pvcName}/`)
return JSON.parse(await rawPV.text())
return await request(`${host}/api/v1/pvc/${namespace}/${pvcName}/`)
} catch (e) {
console.log(`fail to get pvc(${namespace}/${pvcName}): ${e}`)
return null
Expand All @@ -216,10 +217,7 @@ export const getPVC = async (namespace: string, pvcName: string) => {

export const getPVCEvents = async (namespace: string, pvcName: string) => {
try {
const events = await fetch(
`${host}/api/v1/pvc/${namespace}/${pvcName}/events`,
)
return JSON.parse(await events.text())
return await request(`${host}/api/v1/pvc/${namespace}/${pvcName}/events`)
} catch (e) {
console.log(`fail to get pvc(${namespace}/${pvcName}): ${e}`)
return null
Expand All @@ -228,8 +226,7 @@ export const getPVCEvents = async (namespace: string, pvcName: string) => {

export const getSC = async (scName: string) => {
try {
const rawSC = await fetch(`${host}/api/v1/storageclass/${scName}/`)
return JSON.parse(await rawSC.text())
return await request(`${host}/api/v1/storageclass/${scName}/`)
} catch (e) {
console.log(`fail to get sc (${scName}): ${e}`)
return null
Expand All @@ -238,10 +235,7 @@ export const getSC = async (scName: string) => {

export const getMountPodOfPVC = async (namespace: string, pvcName: string) => {
try {
const rawPod = await fetch(
`${host}/api/v1/pvc/${namespace}/${pvcName}/mountpods`,
)
return JSON.parse(await rawPod.text())
return await request(`${host}/api/v1/pvc/${namespace}/${pvcName}/mountpods`)
} catch (e) {
console.log(`fail to get mountpod of pvc(${namespace}/${pvcName}): ${e}`)
return null
Expand All @@ -250,8 +244,7 @@ export const getMountPodOfPVC = async (namespace: string, pvcName: string) => {

export const getMountPodOfPV = async (pvName: string) => {
try {
const rawPod = await fetch(`${host}/api/v1/pv/${pvName}/mountpods`)
return JSON.parse(await rawPod.text())
return await request(`${host}/api/v1/pv/${pvName}/mountpods`)
} catch (e) {
console.log(`fail to get mountpod of pv (${pvName}): ${e}`)
return null
Expand All @@ -260,8 +253,7 @@ export const getMountPodOfPV = async (pvName: string) => {

export const getPVOfSC = async (scName: string) => {
try {
const pvs = await fetch(`${host}/api/v1/storageclass/${scName}/pvs`)
return JSON.parse(await pvs.text())
return await request(`${host}/api/v1/storageclass/${scName}/pvs`)
} catch (e) {
console.log(`fail to get pvs of sc (${scName}): ${e}`)
return null
Expand Down

0 comments on commit 618d371

Please sign in to comment.