Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.vscode
__pycache__
189 changes: 189 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# Server Inventory Management API

A Flask-based REST API for managing server inventory with PostgreSQL backend.

## Quick Start

### Prerequisites
- Docker and Docker Compose
- Python 3.9+ (for CLI and tests)

### Start the Service

```bash
docker compose up --build -d
```

The API will be available at `http://localhost:5001`

The database is automatically initialized with the schema from `init_db.sql`.

### Stop the Service

```bash
docker compose down
```

## Running Tests

### All Tests
```bash
make test # From the root directory
```

### Unit Tests
```bash
make unit-test # From the root directory
```

![alt text](assets/image.png)

### Integration Tests
```bash
make integration-test # From the root directory
```

![alt text](assets/image-1.png)

### CLI Tests
```bash
make cli-test # From the root directory
```

![alt text](assets/image-2.png)

## API Endpoints

Base URL: `http://localhost:5001`

### List Servers
```bash
GET /servers

# Example
curl http://localhost:5001/servers

# Response
[
{
"id": 1,
"hostname": "web-server-01",
"ip_address": "192.168.1.10",
"server_state": "active"
},
{
"id": 2,
"hostname": "web-server-02",
"ip_address": "192.168.1.10",
"server_state": "active"
}
]
```

### Get Server
```bash
GET /servers/{id}

# Example
curl http://localhost:5001/servers/1

# Response
{
"id": 1,
"hostname": "web-server-01",
"ip_address": "192.168.1.10",
"server_state": "active"
}
```

### Create Server
```bash
POST /servers
Content-Type: application/json

# Example
curl -X POST http://localhost:5001/servers \
-H "Content-Type: application/json" \
-d '{
"hostname": "web-server-01",
"ip_address": "192.168.1.10",
"server_state": "active"
}'

# Response (201 Created)
{
"server_id": 1
}
```

**Validation:**
- `hostname`: Required, must be unique
- `ip_address`: Required, valid IPv4 format
- `server_state`: Required, one of: `active`, `offline`, `retired`

### Update Server
```bash
PUT /servers/{id}
Content-Type: application/json

# Example
curl -X PUT http://localhost:5001/servers/1 \
-H "Content-Type: application/json" \
-d '{
"hostname": "updated-hostname",
"ip_address": "10.0.0.1",
"server_state": "offline"
}'

# Response (200 OK)
{
"id": 1,
"hostname": "updated-hostname",
"ip_address": "10.0.0.1",
"server_state": "offline"
}
```

**Note:** At least one field must be provided. Omitted fields remain unchanged. The updated hostname must also still be unique.

### Delete Server
```bash
DELETE /servers/{id}

# Example
curl -X DELETE http://localhost:5001/servers/1

# Response (200 OK)
{
"message": "Server deleted"
}
```

## Error Responses

- `400 Bad Request`: Validation error or invalid input
- `404 Not Found`: Server ID not found
- `500 Internal Server Error`: Server error

## Development

### Install Dependencies
```bash
pip install -r requirements.txt
```

### Database Schema
The database schema is defined in `init_db.sql` and is automatically applied when the PostgreSQL container starts.

### Project Structure
```
.
├── flask_api/
│ ├── app.py # Flask API application
│ ├── cli.py # CLI tool
| |__ Dockerfile # Docker image file.
│ ├── requirements.txt # Python dependencies
│ └── tests/ # Test suite
├── init_db.sql # Database schema
├── docker-compose.yml # Docker Compose configuration
└── scripts/ # Test scripts
121 changes: 121 additions & 0 deletions CLI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Server Inventory Management CLI

A command-line interface for managing servers in the inventory system via the REST API.

## Prerequisites

- The Flask API and Postgres database must be running (see API.md for setup instructions)
- Docker and Docker Compose
- Python 3.9+ (for CLI and tests)

## Use the CLI

The CLI connects to the REST API to perform all operations.

### Basic Usage

- Launch the API and database
` docker compose up --build -d `

- Create a virtual environment and install dependencies

```bash
python3 -m venv challenge-env
source challenge-env/bin/activate
pip install -r requirements.txt
```


```bash
python flask_api/cli.py list
python flask_api/cli.py get <server_id>
python flask_api/cli.py create --hostname <name> --ip-address <ip> --state <state>
python flask_api/cli.py update <server_id> [options]
python flask_api/cli.py delete <server_id>
```

### Commands

#### List Servers
List all servers in the inventory.

```bash
python flask_api/cli.py list
```

#### Get Server
Get details of a specific server by ID.

```bash
python flask_api/cli.py get 1
```

#### Create Server
Create a new server in the inventory.

```bash
python flask_api/cli.py create --hostname "web-server-01" --ip-address "192.168.1.10" --state active
```

Valid states: `active`, `offline`, `retired`

#### Update Server
Update an existing server. You can update one or more fields.

```bash
# Update hostname only
python flask_api/cli.py update 1 --hostname "new-hostname"

# Update multiple fields
python flask_api/cli.py update 1 --hostname "new-hostname" --ip-address "10.0.0.1" --state offline
```

#### Delete Server
Delete a server from the inventory (requires confirmation).

```bash
python flask_api/cli.py delete 1
```

### Options

#### Global Options

- `--api-url <url>`: Specify API base URL (default: http://localhost:5001)

### Examples

```bash
# List all servers
python flask_api/cli.py list

# Create a server
python flask_api/cli.py create --hostname "db-server-01" --ip-address "10.0.0.5" --state active

# Update server state only
python flask_api/cli.py update 2 --state offline

# Get server details
python flask_api/cli.py get 1

# Delete a server (will prompt for confirmation)
python flask_api/cli.py delete 3

# Use custom API URL
python flask_api/cli.py --api-url http://api.example.com:8080 list
```

### Error Handling

The CLI provides clear error messages for:
- Invalid IP address formats
- Invalid server states
- Missing required fields
- Server not found (404)
- Duplicate hostnames
- API connection errors

### Exit Codes

- `0`: Success
- `1`: Error (validation error, not found, connection error, etc.)
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
unit-test:
./scripts/unit-test.sh

integration-test:
./scripts/integration-test.sh

cli-test:
./scripts/cli-test.sh

test: unit-test integration-test cli-test

3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,5 @@ Requirements:
Validate that:
- hostname is unique
- IP address looks like an IP

State is one of: active, offline, retired
- State is one of: active, offline, retired

Binary file added assets/image-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/image-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
services:
postgres:
image: postgres:latest
container_name: postgres_container
environment:
POSTGRES_USER: your_username
POSTGRES_PASSWORD: your_password
POSTGRES_DB: your_database
ports:
- "5432:5432"
volumes:
- ./init_db.sql:/docker-entrypoint-initdb.d/init_db.sql

flask_api:
build:
context: ./flask_api
container_name: flask_api_container
ports:
- "5001:5000"
depends_on:
- postgres



11 changes: 11 additions & 0 deletions flask_api/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["flask", "run", "--host=0.0.0.0", "--port=5000"]
Loading