Skip to content

Commit

Permalink
feat(ui): networks-services view (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
decleaver authored Jul 25, 2024
1 parent f52ea3d commit 1d0b68a
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 1 deletion.
1 change: 1 addition & 0 deletions ui/src/lib/features/k8s/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export { default as UDSExemptionTable } from './configs/uds-exemptions/component
export { default as UDSPackageTable } from './configs/uds-packages/component.svelte'

export { default as PriorityClassesTable } from './cluster-ops/priority-classes/component.svelte'
export { default as ServiceTable } from './networks/services/component.svelte'
20 changes: 20 additions & 0 deletions ui/src/lib/features/k8s/networks/services/component.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!-- SPDX-License-Identifier: Apache-2.0 -->
<!-- SPDX-FileCopyrightText: 2024-Present The UDS Authors -->

<script lang="ts">
import { DataTable } from '$components'
import { createStore, type Columns } from './store'
export let columns: Columns = [
['name', 'emphasize'],
['namespace'],
['type'],
['cluster_ip'],
['external_ip'],
['ports'],
['age'],
['status'],
]
</script>

<DataTable {columns} {createStore} />
30 changes: 30 additions & 0 deletions ui/src/lib/features/k8s/networks/services/component.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2024-Present The UDS Authors

import '@testing-library/jest-dom'

import { testK8sTableWithCustomColumns, testK8sTableWithDefaults } from '$features/k8s/test-helper'
import Component from './component.svelte'
import { createStore } from './store'

suite('ServiceTable Component', () => {
beforeEach(() => {
vi.clearAllMocks()
})

testK8sTableWithDefaults(Component, {
createStore,
columns: [
['name', 'emphasize'],
['namespace'],
['type'],
['cluster_ip'],
['external_ip'],
['ports'],
['age'],
['status'],
],
})

testK8sTableWithCustomColumns(Component, { createStore })
})
66 changes: 66 additions & 0 deletions ui/src/lib/features/k8s/networks/services/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2024-Present The UDS Authors

import type { V1Service as Resource } from '@kubernetes/client-node'

import { ResourceStore, transformResource } from '$features/k8s/store'
import { type ColumnWrapper, type CommonRow, type ResourceStoreInterface } from '$features/k8s/types'

interface Row extends CommonRow {
type: string
cluster_ip: string
external_ip: string
ports: string
status: string
}

export type Columns = ColumnWrapper<Row>

export function createStore(): ResourceStoreInterface<Resource, Row> {
const url = `/api/v1/resources/networks/services`

const transform = transformResource<Resource, Row>((r) => ({
type: r.spec?.type ?? '',
cluster_ip: r.spec?.clusterIP ?? '',
external_ip: r.status?.loadBalancer?.ingress?.map((p) => `${p.ip}`).join(', ') ?? '-',
ports:
r.spec?.ports
?.map((p) => (p.nodePort ? `${p.port}:${p.nodePort}/${p.protocol}` : `${p.port}/${p.protocol}`))
.join(', ') ?? '',
status: isInSuccessState(r) ? 'Succeeded' : 'Pending',
}))

const store = new ResourceStore<Resource, Row>('name')

return {
...store,
start: () => store.start(url, transform),
sortByKey: store.sortByKey.bind(store),
}
}

/**
* Success state of a Service depends on the type of service
* https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
* ClusterIP: ClusterIP is defined
* NodePort: ClusterIP is defined
* LoadBalancer: ClusterIP is defined __and__ external endpoints exist
* ExternalName: true
*/
function isInSuccessState(resource: Resource): boolean {
const resourceType = resource.spec?.type
switch (resourceType) {
case 'ExternalName':
return true
case 'LoadBalancer':
if (resource.status?.loadBalancer?.ingress?.length === 0) {
return false
}
break
case 'ClusterIP':
case 'NodePort':
default:
break
}
return resource.spec?.clusterIPs?.length ? resource.spec?.clusterIPs?.length > 0 : false
}
6 changes: 5 additions & 1 deletion ui/src/routes/(resources)/networks/services/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<!-- SPDX-License-Identifier: Apache-2.0 -->
<!-- SPDX-FileCopyrightText: 2024-Present The UDS Authors -->

<h1 class="text-white text-5xl">Services</h1>
<script lang="ts">
import { ServiceTable } from '$features/k8s'
</script>

<ServiceTable />

0 comments on commit 1d0b68a

Please sign in to comment.