diff --git a/src/pages/infrastructure/InfrastructurePages.tsx b/src/pages/infrastructure/InfrastructurePages.tsx index c98367b..3177d42 100644 --- a/src/pages/infrastructure/InfrastructurePages.tsx +++ b/src/pages/infrastructure/InfrastructurePages.tsx @@ -1,12 +1,12 @@ -import { RotateCcw } from 'lucide-react'; +import { Braces, RotateCcw } from 'lucide-react'; import { useCallback, useEffect, useMemo, useState, type ReactNode } from 'react'; import { DataTableCard, type DataTableColumn, type DataTableFilter } from '../../components/data-table'; -import { Badge, Button, Card, CardHeader } from '../../components/ui'; +import { Badge, Button, Card, CardHeader, Modal } from '../../components/ui'; import { PageTitle } from '../../layout/AppLayout'; import { runtimeStatusDotClass } from '../../lib/status-dot'; import { cn } from '../../lib/utils'; import type { RuntimePodMetric, RuntimeResource, RuntimeResourceResponse } from '../../types/runtime'; -import { loadApps, loadRuntimeEvents, loadRuntimePodMetrics, loadRuntimeResources } from '../runtime/runtime-api'; +import { loadApps, loadRuntimePodMetrics, loadRuntimeResourceYaml, loadRuntimeResources } from '../runtime/runtime-api'; import { LoadingModal, useMinimumLoading } from '../operations/operation-utils'; const defaultNamespaces = ['studio-system', 'stdo-lms', 'stdo-ads-ide']; @@ -40,7 +40,7 @@ function isNetwork(resource: RuntimeResource) { } function isStorage(resource: RuntimeResource) { - return ['PersistentVolumeClaim', 'PersistentVolume', 'StorageClass'].includes(resource.kind); + return ['PersistentVolumeClaim', 'PVC', 'PersistentVolume', 'StorageClass'].includes(resource.kind); } function resourceStatusTone(status: string): 'neutral' | 'green' | 'amber' | 'red' | 'blue' { @@ -191,6 +191,22 @@ function ResourceTable({ loading: boolean; emptyMessage: string; }) { + const [yamlTarget, setYamlTarget] = useState(null); + const [yaml, setYaml] = useState(''); + const [yamlLoading, setYamlLoading] = useState(false); + const [yamlError, setYamlError] = useState(''); + + const openYaml = (row: ResourceRow) => { + setYamlTarget(row); + setYaml(''); + setYamlError(''); + setYamlLoading(true); + loadRuntimeResourceYaml(row.namespace, row.kind, row.name) + .then((response) => setYaml(response.yaml)) + .catch((error: unknown) => setYamlError(error instanceof Error ? error.message : 'YAML을 불러오지 못했습니다.')) + .finally(() => setYamlLoading(false)); + }; + const columns = useMemo>>( () => [ { key: 'namespace', header: '네임스페이스', className: 'w-44 px-5 py-3', cell: (row) => {row.namespace} }, @@ -201,7 +217,23 @@ function ResourceTable({ { key: 'restarts', header: '재시작', className: 'w-24 px-5 py-3', cell: (row) => {row.restarts ?? '-'} }, { key: 'metric', header: '사용량', className: 'w-40 px-5 py-3', cell: (row) => {row.metric ? `${row.metric.cpu} / ${row.metric.memory}` : '-'} }, { key: 'age', header: 'Age', className: 'w-28 px-5 py-3', cell: (row) => {row.age || '-'} }, - { key: 'detail', header: '상세', className: 'min-w-[260px] px-5 py-3', cell: (row) => {row.detail || '-'} } + { key: 'detail', header: '상세', className: 'min-w-[220px] px-5 py-3', cell: (row) => {row.detail || '-'} }, + { + key: 'yaml', + header: '', + className: 'w-14 px-3 py-3 text-right', + cell: (row) => ( + + ) + } ], [] ); @@ -209,20 +241,34 @@ function ResourceTable({ const filters = useMemo(() => [NamespaceFilter(rows), KindFilter(rows)], [rows]); return ( - `${row.namespace} ${row.kind} ${row.name} ${row.status} ${row.detail}`} - getRowKey={(row) => row.id} - pageSize={10} - minWidth={1280} - loading={loading} - emptyMessage={emptyMessage} - /> + <> + `${row.namespace} ${row.kind} ${row.name} ${row.status} ${row.detail}`} + getRowKey={(row) => row.id} + pageSize={10} + minWidth={1320} + loading={loading} + emptyMessage={emptyMessage} + /> + setYamlTarget(null)} + className="!max-w-5xl" + > + {yamlLoading ?

불러오는 중...

: null} + {yamlError ?

{yamlError}

: null} + {!yamlLoading && !yamlError ? ( +
{yaml}
+ ) : null} +
+ ); } diff --git a/src/pages/runtime/runtime-api.ts b/src/pages/runtime/runtime-api.ts index b3f4d5d..090528e 100644 --- a/src/pages/runtime/runtime-api.ts +++ b/src/pages/runtime/runtime-api.ts @@ -66,6 +66,12 @@ export function loadRuntimeResources(namespace: string) { return apiRequest(`/apps/runtime-namespaces/${encodeURIComponent(namespace)}/resources`); } +export function loadRuntimeResourceYaml(namespace: string, kind: string, name: string) { + return apiRequest<{ namespace: string; kind: string; name: string; yaml: string }>( + `/apps/runtime-namespaces/${encodeURIComponent(namespace)}/resources/${encodeURIComponent(kind)}/${encodeURIComponent(name)}/yaml` + ); +} + export function loadRuntimePodMetrics(namespace?: string) { const query = namespace ? `?namespace=${encodeURIComponent(namespace)}` : ''; return apiRequest(`/runtime/metrics/pods${query}`);