Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
165 changes: 147 additions & 18 deletions infrastructure/control-panel/README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,167 @@
# sv
# Control Panel

Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
A SvelteKit-based control panel for monitoring and managing various services and platforms.

## Creating a project
## Features

If you're seeing this, you've probably already done this step. Congrats!
### eVault Monitoring

- **Real-time eVault Discovery**: Automatically discovers eVault pods across all Kubernetes namespaces
- **Pod Information**: Displays comprehensive pod details including status, readiness, restarts, age, IP, and node
- **Live Logs**: View real-time logs from eVault pods with automatic refresh
- **Pod Details**: Access detailed pod information including YAML configuration and resource usage
- **Metrics**: View pod performance metrics (when metrics-server is available)

## Prerequisites

### Kubernetes Access

- `kubectl` must be installed and configured
- Access to the Kubernetes cluster where eVaults are running
- Proper RBAC permissions to list and describe pods

### System Requirements

- Node.js 18+
- Access to execute `kubectl` commands

## Installation

1. Install dependencies:

```bash
# create a new project in the current directory
npx sv create
npm install
```

2. Ensure kubectl is configured:

# create a new project in my-app
npx sv create my-app
```bash
kubectl cluster-info
```

## Developing
## Usage

Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
### Development

```bash
npm run dev

# or start the server and open the app in a new browser tab
npm run dev -- --open
```

## Building

To create a production version of your app:
### Building

```bash
npm run build
```

You can preview the production build with `npm run preview`.
## eVault Monitoring

### Main Dashboard

The main page displays a table of all eVault pods found across your Kubernetes cluster:

- **Name**: Clickable link to detailed pod view
- **Namespace**: Kubernetes namespace where the pod is running
- **Status**: Current pod status (Running, Pending, Failed, etc.)
- **Ready**: Number of ready containers vs total containers
- **Restarts**: Number of container restarts
- **Age**: How long the pod has been running
- **IP**: Pod IP address
- **Node**: Kubernetes node where the pod is scheduled

### Detailed Pod View

Click on any eVault name to access detailed monitoring:

#### Logs Tab

- Real-time pod logs with automatic refresh
- Configurable log tail length
- Terminal-style display for easy reading

#### Details Tab

- Complete pod description from `kubectl describe pod`
- YAML configuration from `kubectl get pod -o yaml`
- Resource requests and limits
- Environment variables and volume mounts

#### Metrics Tab

- CPU and memory usage (requires metrics-server)
- Resource consumption trends
- Performance monitoring data

### API Endpoints

#### GET /api/evaults

Returns a list of all eVault pods across all namespaces.

#### GET /api/evaults/[namespace]/[pod]/logs?tail=[number]

Returns the most recent logs from a specific pod.

#### GET /api/evaults/[namespace]/[pod]/details

Returns detailed information about a specific pod.

## Configuration

### eVault Detection

The system automatically detects eVault pods by filtering for pods with names containing:

- `evault`
- `vault`
- `web3`

You can modify the filter in `src/routes/api/evaults/+server.ts` to adjust detection criteria.

### Log Tail Length

Default log tail length is 100 lines. This can be configured via the `tail` query parameter.

## Troubleshooting

### No eVaults Found

1. Verify kubectl is configured: `kubectl cluster-info`
2. Check if eVault pods are running: `kubectl get pods --all-namespaces`
3. Verify pod names contain expected keywords
4. Check RBAC permissions for pod listing

### Permission Denied

Ensure your kubectl context has permissions to:

- List pods across namespaces
- Describe pods
- Access pod logs
- View pod metrics (if using metrics-server)

### Metrics Not Available

If the metrics tab shows no data:

1. Verify metrics-server is installed: `kubectl get pods -n kube-system | grep metrics`
2. Check metrics-server logs for errors
3. Ensure HPA (Horizontal Pod Autoscaler) is configured if needed

## Security Considerations

- The control panel executes kubectl commands on the server
- Ensure proper access controls and authentication
- Consider implementing role-based access control
- Monitor and audit kubectl command execution

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests if applicable
5. Submit a pull request

## License

> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
[Add your license information here]
1 change: 1 addition & 0 deletions infrastructure/control-panel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"flowbite": "^3.1.2",
"flowbite-svelte": "^1.10.7",
"flowbite-svelte-icons": "^2.2.1",
"lucide-svelte": "^0.539.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify lucide-svelte compatibility with Svelte 5 and lock if needed

Adding lucide-svelte looks fine, but please confirm peer compatibility with your Svelte version and consider pinning if you see downstream breakage (icons libs sometimes ship breaking changes).

You can quickly check the latest version and peer deps:


🏁 Script executed:

#!/bin/bash
# Check latest lucide-svelte and peer requirements
npm view lucide-svelte version peerDependencies engines | jq .

Length of output: 121


I wasn’t able to parse the peer info from the previous command—let’s try explicitly requesting JSON for both peerDependencies and engines:


🏁 Script executed:

#!/bin/bash
# Get peerDependencies and engines for the latest lucide-svelte release
npm view lucide-svelte@latest peerDependencies --json
npm view lucide-svelte@latest engines --json

Length of output: 147


Confirm lucide-svelte peer dependency supports your Svelte version

The current [email protected] lists

"peerDependencies": {
  "svelte": "^3 || ^4 || ^5.0.0-next.42"
}

– it does not include stable Svelte 5.x releases. If this control-panel is upgraded to Svelte 5.0.0 (or higher), you’ll encounter peer-dependency warnings or runtime breakage.

Please verify your Svelte version in infrastructure/control-panel/package.json and choose one of the following:

  • If you’re on Svelte 5.x stable, wait for (or upgrade to) the next lucide-svelte release that adds "^5" support.
  • If you need icons now, pin your project to Svelte 4 or the 5.0.0-next.42 prerelease.
  • Lock or pin lucide-svelte to 0.539.0 and test thoroughly before upgrading Svelte.

File: infrastructure/control-panel/package.json
Line: 53

  "dependencies": {
-   "lucide-svelte": "^0.539.0",
+   "lucide-svelte": "^0.539.0",  // peer requires Svelte "^3 || ^4 || ^5.0.0-next.42"
  }

"tailwind-merge": "^3.0.2"
}
}
57 changes: 57 additions & 0 deletions infrastructure/control-panel/src/lib/services/evaultService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type { EVault } from '../../routes/api/evaults/+server';

export class EVaultService {
static async getEVaults(): Promise<EVault[]> {
try {
const response = await fetch('/api/evaults');
if (!response.ok) {
throw new Error('Failed to fetch eVaults');
}
const data = await response.json();
return data.evaults || [];
} catch (error) {
console.error('Error fetching eVaults:', error);
return [];
}
}

static async getEVaultLogs(namespace: string, podName: string, tail: number = 100): Promise<string[]> {
try {
const response = await fetch(`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/logs?tail=${tail}`);
if (!response.ok) {
throw new Error('Failed to fetch logs');
}
const data = await response.json();
return data.logs || [];
} catch (error) {
console.error('Error fetching logs:', error);
return [];
}
}

static async getEVaultDetails(namespace: string, podName: string): Promise<any> {
try {
const response = await fetch(`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/details`);
if (!response.ok) {
throw new Error('Failed to fetch eVault details');
}
return await response.json();
} catch (error) {
console.error('Error fetching eVault details:', error);
return null;
}
}
Comment on lines +32 to +43
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding return type definition for better type safety

The methods getEVaultDetails and getEVaultMetrics return Promise<any>, which loses type safety benefits. Consider defining proper interfaces for the response data structures to ensure type safety throughout the application.

+interface EVaultDetails {
+  // Define the structure based on your API response
+  namespace: string;
+  podName: string;
+  // Add other relevant fields
+}
+
+interface EVaultMetrics {
+  resources?: {
+    cpu?: string;
+    memory?: string;
+    note?: string;
+  };
+  status?: {
+    podStatus?: string;
+    podAge?: string;
+    events?: string[];
+    conditions?: string[];
+  };
+  logs?: {
+    totalLines?: number;
+    errorCount?: number;
+    warningCount?: number;
+    lastUpdate?: string;
+  };
+}

-static async getEVaultDetails(namespace: string, podName: string): Promise<any> {
+static async getEVaultDetails(namespace: string, podName: string): Promise<EVaultDetails | null> {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
static async getEVaultDetails(namespace: string, podName: string): Promise<any> {
try {
const response = await fetch(`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/details`);
if (!response.ok) {
throw new Error('Failed to fetch eVault details');
}
return await response.json();
} catch (error) {
console.error('Error fetching eVault details:', error);
return null;
}
}
// Add these at the top of the file (above your service class)
interface EVaultDetails {
// Define the structure based on your API response
namespace: string;
podName: string;
// Add other relevant fields
}
interface EVaultMetrics {
resources?: {
cpu?: string;
memory?: string;
note?: string;
};
status?: {
podStatus?: string;
podAge?: string;
events?: string[];
conditions?: string[];
};
logs?: {
totalLines?: number;
errorCount?: number;
warningCount?: number;
lastUpdate?: string;
};
}
// Then update the method signature:
static async getEVaultDetails(namespace: string, podName: string): Promise<EVaultDetails | null> {
try {
const response = await fetch(
`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/details`
);
if (!response.ok) {
throw new Error('Failed to fetch eVault details');
}
return await response.json();
} catch (error) {
console.error('Error fetching eVault details:', error);
return null;
}
}
🤖 Prompt for AI Agents
in infrastructure/control-panel/src/lib/services/evaultService.ts around lines
32 to 43, the method currently returns Promise<any> which loses type safety;
define and export interfaces (e.g., EVaultDetails and EVaultMetrics) that model
the expected JSON shape, update the method signatures to return
Promise<EVaultDetails | null> (or appropriate nullable/union types),
cast/validate the fetched JSON to that interface before returning (or use a
lightweight runtime assertion/mapper), and update any callers to use the new
types; keep error handling the same but ensure the declared return type matches
what you actually return on error (null or throw).


static async getEVaultMetrics(namespace: string, podName: string): Promise<any> {
try {
const response = await fetch(`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/metrics`);
if (!response.ok) {
throw new Error('Failed to fetch metrics');
}
return await response.json();
} catch (error) {
console.error('Error fetching eVault metrics:', error);
return null;
}
}
Comment on lines +45 to +56
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Apply consistent return type definition

Similar to the getEVaultDetails method, define a proper interface for the metrics response.

-static async getEVaultMetrics(namespace: string, podName: string): Promise<any> {
+static async getEVaultMetrics(namespace: string, podName: string): Promise<EVaultMetrics | null> {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
static async getEVaultMetrics(namespace: string, podName: string): Promise<any> {
try {
const response = await fetch(`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/metrics`);
if (!response.ok) {
throw new Error('Failed to fetch metrics');
}
return await response.json();
} catch (error) {
console.error('Error fetching eVault metrics:', error);
return null;
}
}
static async getEVaultMetrics(namespace: string, podName: string): Promise<EVaultMetrics | null> {
try {
const response = await fetch(`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/metrics`);
if (!response.ok) {
throw new Error('Failed to fetch metrics');
}
return await response.json();
} catch (error) {
console.error('Error fetching eVault metrics:', error);
return null;
}
}
🤖 Prompt for AI Agents
in infrastructure/control-panel/src/lib/services/evaultService.ts around lines
45 to 56, the getEVaultMetrics method currently returns Promise<any>; declare
and use a proper interface (e.g., EVaultMetrics) matching the expected metrics
shape (or reuse the existing EVaultDetails-style interface), change the method
signature to Promise<EVaultMetrics | null>, cast/validate the parsed JSON to
EVaultMetrics before returning (or use a runtime check), and update any callers
to handle the typed response/null. Ensure the new interface is exported/placed
alongside other types for consistency.

}
Loading