Skip to content

Commit 1ba60dd

Browse files
authored
Merge pull request #32 from PelionIoT/add-k8s-at-edge-example
Added k8s-at-the-edge example
2 parents 0d5265f + fd6a4d2 commit 1ba60dd

File tree

90 files changed

+26445
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+26445
-1
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ GTAGS
8181

8282
### Javascript + node.js
8383
node_modules
84-
package-lock.json
8584

8685
### Eclipse IDE ###
8786
.cproject

k8s-at-the-edge-example/DEV.md

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
2+
# Local Development
3+
4+
This guide will help you set up and run the Virtual Device Server locally for development.
5+
6+
## Prerequisites
7+
8+
Make sure you have the following installed:
9+
- [Docker](https://docs.docker.com/get-docker/) and Docker Compose
10+
- [Rust](https://rustup.rs/) toolchain (for the backend)
11+
- [Node.js](https://nodejs.org/) (v16 or later, for the frontend)
12+
- [Git](https://git-scm.com/) (to clone the repository)
13+
14+
### Step 1: Clone and Setup
15+
16+
```bash
17+
# Clone the repository
18+
git clone <repository-url>
19+
cd virtual-device-server
20+
21+
# Verify the structure
22+
ls -la
23+
# Should show: dummy-device-app/, web-portal/, k8s/, README.md
24+
```
25+
26+
### Step 2: Start PostgreSQL Database
27+
28+
```bash
29+
# Start PostgreSQL in Docker
30+
docker run -d --name postgres-dev \
31+
-e POSTGRES_DB=device_db \
32+
-e POSTGRES_USER=postgres \
33+
-e POSTGRES_PASSWORD=password \
34+
-p 5432:5432 \
35+
postgres:15-alpine
36+
37+
# Verify the database is running
38+
docker ps | grep postgres-dev
39+
40+
# Optional: Check database logs
41+
docker logs postgres-dev
42+
```
43+
44+
**Alternative: Use Docker Compose (recommended)**
45+
46+
Create a `docker-compose.yml` file in the root directory:
47+
48+
```yaml
49+
version: '3.8'
50+
services:
51+
postgres:
52+
image: postgres:15-alpine
53+
container_name: postgres-dev
54+
environment:
55+
POSTGRES_DB: device_db
56+
POSTGRES_USER: postgres
57+
POSTGRES_PASSWORD: password
58+
ports:
59+
- "5432:5432"
60+
volumes:
61+
- postgres_data:/var/lib/postgresql/data
62+
healthcheck:
63+
test: ["CMD-SHELL", "pg_isready -U postgres"]
64+
interval: 10s
65+
timeout: 5s
66+
retries: 5
67+
68+
volumes:
69+
postgres_data:
70+
```
71+
72+
Then run:
73+
```bash
74+
docker-compose up -d postgres
75+
```
76+
77+
### Step 3: Run the Rust Backend
78+
79+
```bash
80+
# Navigate to the backend directory
81+
cd dummy-device-app
82+
83+
# Install Rust dependencies (if not already done)
84+
cargo check
85+
86+
# Set environment variables
87+
export DATABASE_URL="postgres://postgres:password@localhost:5432/device_db"
88+
export RUST_LOG=info
89+
90+
# Run the application
91+
cargo run
92+
```
93+
94+
You should see output like:
95+
```
96+
2024-01-15T10:30:00.000Z INFO Initializing dummy device server
97+
2024-01-15T10:30:00.100Z INFO Successfully connected to database
98+
2024-01-15T10:30:00.200Z INFO Database migrations completed successfully
99+
2024-01-15T10:30:00.300Z INFO No devices found, initializing default devices
100+
2024-01-15T10:30:00.400Z INFO Successfully initialized 4 default devices
101+
2024-01-15T10:30:00.500Z INFO Starting server on 0.0.0.0:3000
102+
```
103+
104+
**Troubleshooting Backend:**
105+
- If you get database connection errors, ensure PostgreSQL is running: `docker ps | grep postgres`
106+
- If migrations fail, check the database logs: `docker logs postgres-dev`
107+
- For more detailed logs, set `RUST_LOG=debug`
108+
109+
### Step 4: Run the React Frontend
110+
111+
Open a new terminal window and navigate to the frontend directory:
112+
113+
```bash
114+
# Navigate to the frontend directory
115+
cd web-portal
116+
117+
# Install Node.js dependencies
118+
npm install
119+
120+
# Start the development server
121+
npm start
122+
```
123+
124+
You should see output like:
125+
```
126+
Compiled successfully!
127+
128+
You can now view web-portal in the browser.
129+
130+
Local: http://localhost:3001
131+
On Your Network: http://192.168.1.100:3001
132+
133+
Note that the development build is not optimized.
134+
To create a production build, use npm run build.
135+
```
136+
137+
**Note:** The frontend runs on port 3001 to avoid conflicts with the backend (port 3000).
138+
139+
### Step 5: Access the Application
140+
141+
Once both services are running:
142+
143+
- **Web UI**: http://localhost:3001
144+
- **Backend API**: http://localhost:3000
145+
- **Health Check**: http://localhost:3000/health
146+
- **API Documentation**: See the API Endpoints section below
147+
148+
### Step 6: Test the Setup
149+
150+
1. **Test the Health Check:**
151+
```bash
152+
curl http://localhost:3000/health
153+
# Should return: {"success":true,"data":"OK","error":null}
154+
```
155+
156+
2. **Test the API:**
157+
```bash
158+
# List all devices
159+
curl http://localhost:3000/devices
160+
161+
# Create a new device
162+
curl -X POST http://localhost:3000/devices \
163+
-H "Content-Type: application/json" \
164+
-d '{"name": "Test Light", "device_type": "LightBulb"}'
165+
```
166+
167+
3. **Test the Web UI:**
168+
- Open http://localhost:3001 in your browser
169+
- You should see the device management interface
170+
- Try creating, viewing, and updating devices
171+
172+
#### Development Workflow
173+
174+
1. **Backend Development:**
175+
```bash
176+
cd dummy-device-app
177+
# Make changes to src/main.rs
178+
cargo run # Automatically recompiles and restarts
179+
```
180+
181+
2. **Frontend Development:**
182+
```bash
183+
cd web-portal
184+
# Make changes to src/App.js
185+
# The development server automatically reloads
186+
```
187+
188+
3. **Database Changes:**
189+
```bash
190+
cd dummy-device-app
191+
# Create a new migration
192+
sqlx migrate add <migration_name>
193+
# Edit the generated migration file
194+
cargo run # Applies the migration
195+
```
196+
197+
#### Stopping the Services
198+
199+
```bash
200+
# Stop the backend (Ctrl+C in the terminal)
201+
# Stop the frontend (Ctrl+C in the terminal)
202+
203+
# Stop PostgreSQL
204+
docker stop postgres-dev
205+
docker rm postgres-dev
206+
207+
# Or if using Docker Compose
208+
docker-compose down
209+
```
210+
211+
#### Environment Variables
212+
213+
Create a `.env` file in the `dummy-device-app` directory for easier development:
214+
215+
```bash
216+
# dummy-device-app/.env
217+
DATABASE_URL=postgres://postgres:password@localhost:5432/device_db
218+
RUST_LOG=info
219+
PORT=3000
220+
```
221+
222+
Then you can run the backend with:
223+
```bash
224+
cd dummy-device-app
225+
cargo run
226+
```
227+
228+
#### Logging
229+
230+
The backend includes comprehensive logging. To see different log levels:
231+
232+
```bash
233+
# Info level (default)
234+
RUST_LOG=info cargo run
235+
236+
# Debug level (more verbose)
237+
RUST_LOG=debug cargo run
238+
239+
# Error only
240+
RUST_LOG=error cargo run
241+
```
242+
243+
See `dummy-device-app/LOGGING.md` for detailed logging documentation.
244+
245+
### Adding New Device Types
246+
247+
1. Update the `DeviceType` enum in `dummy-device-app/src/main.rs`
248+
2. Add the new type to the database migration
249+
3. Update the default state logic in the `create_device` function
250+
4. Add the device icon and control logic in `web-portal/src/App.js`
251+
252+
### Testing
253+
254+
```bash
255+
# Test the Rust backend
256+
cd dummy-device-app
257+
cargo test
258+
259+
# Test the React frontend
260+
cd web-portal
261+
npm test
262+
```
263+
264+
## API Endpoints
265+
266+
### Health Check
267+
- `GET /health` - Service health status
268+
269+
### Devices
270+
- `GET /devices` - List all devices
271+
- `POST /devices` - Create a new device
272+
- `GET /devices/{id}` - Get device details
273+
- `PUT /devices/{id}/state` - Update device state
274+
275+
### Example API Usage
276+
277+
```bash
278+
# List all devices
279+
curl http://localhost:3000/devices
280+
281+
# Create a new light bulb
282+
curl -X POST http://localhost:3000/devices \
283+
-H "Content-Type: application/json" \
284+
-d '{"name": "Living Room Light", "device_type": "LightBulb"}'
285+
286+
# Update device state
287+
curl -X PUT http://localhost:3000/devices/{device-id}/state \
288+
-H "Content-Type: application/json" \
289+
-d '{"state": {"on": true}}'
290+
```
291+
292+
## Features
293+
294+
- **Real-time Device Management**: View and control device states through a modern web interface
295+
- **Persistent Storage**: All device states are stored in PostgreSQL
296+
- **Scalable Architecture**: Microservices architecture with separate pods for each component
297+
- **Health Monitoring**: Built-in health checks for all services
298+
- **RESTful API**: Clean, documented API for device management
299+
- **Responsive UI**: Modern React interface with Tailwind CSS
300+

k8s-at-the-edge-example/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# K8s at the edge example
2+
3+
A comprehensive IoT device management system built with Rust, React, and Kubernetes. It will showcase [Izuma's Kubernetes at the edge features](https://developer.izumanetworks.com/docs/device-management-edge/2.6/container/index.html). You will run applications in a pod on your edge device that will communicate with each other through service discovery. You will also create config maps and persistent volume claims.
4+
5+
## Architecture
6+
7+
- **dummy-device-app**: Rust service simulating IoT devices (light bulb, switch, temperature/humidity sensor), exposes REST API to view/modify state. Stores state in PostgreSQL.
8+
- **web-portal**: React web UI for device management with modern, responsive design
9+
- **nginx**: Reverse proxy and load balancer for the web portal and API
10+
- **postgres**: PostgreSQL database for persistent device state storage
11+
12+
## Device Types
13+
14+
- **Light Bulb**: `{ "on": true/false }`
15+
- **Switch**: `{ "on": true/false }`
16+
- **Temperature Sensor**: `{ "temperature": 22.5 }`
17+
- **Humidity Sensor**: `{ "humidity": 44.1 }`
18+
19+
## Deployment
20+
21+
1. **Build Docker images:** Clone the repository on the device and run the following commands
22+
```bash
23+
# Build Rust application
24+
cd dummy-device-app
25+
docker build -t dummy-device-app:latest .
26+
27+
# Build React application
28+
cd ../web-portal
29+
docker build -t web-portal:latest .
30+
```
31+
32+
2. **Deploy to Kubernetes:**
33+
```bash
34+
cd k8s
35+
36+
# Update the render.sh to add DeviceIDs to the variable NODE_NAMES and then run
37+
./render.sh
38+
39+
# Create namespace and deploy all components
40+
kubectl apply -f rendered/<device_id>
41+
42+
# Check deployment status
43+
kubectl get pods -o wide | grep <device_id>
44+
45+
# Example
46+
+ kubectl get pods -o wide
47+
dummy-device-app-0197b36304082e89295467ae00000000 1/1 Running 2 29m 172.21.2.45 0197b36304082e89295467ae00000000 <none>
48+
nginx-0197b36304082e89295467ae00000000 1/1 Running 0 15s 172.21.2.49 0197b36304082e89295467ae00000000 <none>
49+
postgres-0197b36304082e89295467ae00000000 1/1 Running 0 29m 172.21.2.47 0197b36304082e89295467ae00000000 <none>
50+
web-portal-0197b36304082e89295467ae00000000 1/1 Running 0 29m 172.21.2.46 0197b36304082e89295467ae00000000 <none>
51+
```
52+
53+
![web-portal](assets/device-mgmt-portal.png)
130 KB
Loading

0 commit comments

Comments
 (0)