Skip to content
Merged
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
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ KUBERNETES_NAMESPACE=container-engine
DOMAIN_SUFFIX=container-engine.app

# Logging
RUST_LOG=container_engine=debug,tower_http=debug
RUST_LOG=container_engine=debug,tower_http=debug
# Front end path
FRONTEND_PATH=./apps/container-engine-frontend/dist
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license = "MIT"
repository = "https://github.com/ngocbd/Open-Container-Engine"

[dependencies]

open = "5"
# Web framework
axum = { version = "0.7", features = ["macros", "tracing"] }
tokio = { version = "1.0", features = ["full"] }
Expand Down
2 changes: 1 addition & 1 deletion apps/container-engine-frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import DeploymentDetailPage from './pages/DeploymentDetailPage';
import ApiKeysPage from './pages/ApiKeysPage';
import AccountSettingsPage from './pages/AccountSettingsPage';
import ProtectedRoute from './components/ProtectedRoute';
import { ToastContainer, toast } from 'react-toastify';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

function App() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
ClipboardDocumentListIcon,
GlobeAltIcon,
ArrowLeftIcon,
PlayIcon,
StopIcon,
ArrowPathIcon,
ExclamationTriangleIcon,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ const NewDeploymentPage: React.FC = () => {
replicas,
});
setSuccess(`Deployment '${response.data.app_name}' created! URL: ${response.data.url}`);
if(response.data.id){
navigate(`/deployments/${response.data.id}`);
}
if (response.data.id) {
navigate(`/deployments/${response.data.id}`);
} else return;
} catch (err: any) {
setError(err.response?.data || 'An unexpected error occurred.');
} finally {
Expand Down
139 changes: 131 additions & 8 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,74 @@ log_warning() {
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Function to open browser
open_browser() {
local url="${1:-http://localhost:3000}"

log_info "Opening browser at: $url"

# Detect OS and open browser accordingly
case "$OSTYPE" in
linux-gnu*)
# Linux
if command_exists xdg-open; then
xdg-open "$url" 2>/dev/null &
elif command_exists gnome-open; then
gnome-open "$url" 2>/dev/null &
elif command_exists kde-open; then
kde-open "$url" 2>/dev/null &
else
log_warning "Could not detect browser opener. Please open manually: $url"
return 1
fi
;;
darwin*)
# macOS
open "$url" 2>/dev/null &
;;
msys*|cygwin*|mingw*)
# Windows (Git Bash/MinGW)
start "$url" 2>/dev/null &
;;
*)
log_warning "Unknown OS type: $OSTYPE. Please open manually: $url"
return 1
;;
esac

log_success "Browser opened successfully"
}

# Function to wait for server and open browser
wait_and_open_browser() {
local port="${1:-3000}"
local path="${2:-}"
local max_retries=30
local retry_count=0

log_info "Waiting for server to be ready..."

while [ $retry_count -lt $max_retries ]; do
if curl -s -o /dev/null "http://localhost:$port/health" 2>/dev/null; then
log_success "Server is ready!"
open_browser "http://localhost:$port$path"
return 0
fi

sleep 1
retry_count=$((retry_count + 1))

if [ $((retry_count % 5)) -eq 0 ]; then
log_info "Still waiting for server... ($retry_count/$max_retries)"
fi
done

log_warning "Server did not become ready within 30 seconds"
return 1
}
start_dev_no_browser() {
AUTO_OPEN_BROWSER=false start_dev
}

# Show help
show_help() {
Expand All @@ -63,7 +131,9 @@ COMMANDS:
db-reset Reset database and volumes
migrate Run database migrations
sqlx-prepare Prepare SQLx queries for offline compilation
dev Start development server
dev Start development server (auto-opens browser)
dev-no-browser Start development server without opening browser
open Open browser to development server
build Build the project
test Run tests
format Format code
Expand All @@ -73,12 +143,14 @@ COMMANDS:
docker-up Start all services with Docker
docker-down Stop all Docker services

ENVIRONMENT VARIABLES:
AUTO_OPEN_BROWSER Set to 'false' to disable auto-opening browser (default: true)

EXAMPLES:
./setup.sh setup # Full initial setup
./setup.sh setup-k8s # Setup with Kubernetes support
./setup.sh install-minikube # Install Minikube only
./setup.sh dev # Start development server
./setup.sh db-reset # Reset database
./setup.sh dev # Start dev server with browser
AUTO_OPEN_BROWSER=false ./setup.sh dev # Start without browser
./setup.sh open # Open browser to running server
EOF
}

Expand Down Expand Up @@ -806,13 +878,54 @@ start_dev() {

# Run migrations if needed
export DATABASE_URL="$DATABASE_URL"
export REDIS_URL="$REDIS_URL"

if ! sqlx migrate info >/dev/null 2>&1; then
run_migrations
fi

log_info "Starting server at http://localhost:3000"
log_info "API documentation available at http://localhost:3000/api-docs/openapi.json"
cargo run
# Check if we should auto-open browser
local auto_open_browser="${AUTO_OPEN_BROWSER:-true}"

# Start the server in background if auto-opening browser
if [ "$auto_open_browser" = "true" ]; then
log_info "Starting server with auto-browser opening..."

# Start server in background
cargo run &
local server_pid=$!

# Wait for server to be ready and open browser
if wait_and_open_browser 3000 "/auth"; then
log_info "Server is running at http://localhost:3000"
log_info "API documentation available at http://localhost:3000/swagger-ui"

# Wait for the server process
wait $server_pid
else
# Kill the server if browser opening failed
kill $server_pid 2>/dev/null
log_error "Failed to start server properly"
return 1
fi
else
# Normal server start without browser opening
log_info "Starting server at http://localhost:3000"
log_info "API documentation available at http://localhost:3000/swagger-ui"
cargo run
fi
}
# New command to just open browser
open_dev_browser() {
log_info "Opening development browser..."

# Check if server is running
if curl -s -o /dev/null "http://localhost:3000/health" 2>/dev/null; then
open_browser "http://localhost:3000/auth"
else
log_warning "Server is not running. Start it first with: ./setup.sh dev"
return 1
fi
}

build_project() {
Expand Down Expand Up @@ -924,6 +1037,10 @@ case "${1:-help}" in
setup)
full_setup
;;
setup-k8s)
full_setup
install_minikube
;;
check)
check_dependencies
;;
Expand Down Expand Up @@ -960,6 +1077,12 @@ case "${1:-help}" in
dev)
start_dev
;;
dev-no-browser)
start_dev_no_browser
;;
open)
open_dev_browser
;;
build)
build_project
;;
Expand Down
2 changes: 1 addition & 1 deletion src/deployment/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub struct DeploymentResponse {
pub app_name: String,
pub image: String,
pub status: String,
pub url: String,
pub url: Option<String>,
pub created_at: DateTime<Utc>,
pub message: String,
}
Expand Down
49 changes: 25 additions & 24 deletions src/handlers/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,38 +49,38 @@ pub async fn create_deployment(
.health_check
.map(|hc| serde_json::to_value(hc))
.transpose()?;
tracing::debug!("Inserting deployment record into database");

sqlx::query!(
r#"
r#"
INSERT INTO deployments (
id, user_id, app_name, image, port, env_vars, replicas,
resources, health_check, status, url, created_at, updated_at,
deployed_at, error_message
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
"#,
deployment_id,
user.user_id,
payload.app_name,
payload.image,
payload.port,
env_vars_json,
payload.replicas.unwrap_or(1),
resources,
health_check,
"pending",
url,
now,
now,
Option::<chrono::DateTime<chrono::Utc>>::None, // deployed_at - null initially
None::<String> // error_message
)
.execute(&state.db.pool)
.await?;

println!("Inserted deployment record into database");

deployment_id,
user.user_id,
payload.app_name,
payload.image,
payload.port,
env_vars_json,
payload.replicas.unwrap_or(1),
resources,
health_check,
"pending",
"".to_string(), // url will be set after deployment
now,
now,
Option::<chrono::DateTime<chrono::Utc>>::None, // deployed_at - null initially
None::<String> // error_message
)
.execute(&state.db.pool)
.await?;
tracing::info!("Successfully inserted deployment record into database");
// TODO: Implement Kubernetes deployment logic here
tracing::debug!("Creating deployment job");
let job = DeploymentJob::new(
deployment_id,
user.user_id,
Expand All @@ -92,7 +92,7 @@ pub async fn create_deployment(
resources,
health_check,
);

tracing::debug!("Sending job to deployment queue");
if let Err(_) = state.deployment_sender.send(job).await {
// Rollback the database record
let _ = sqlx::query!("DELETE FROM deployments WHERE id = $1", deployment_id)
Expand All @@ -101,6 +101,7 @@ pub async fn create_deployment(

return Err(AppError::internal("Failed to queue deployment"));
}
tracing::info!("Deployment system initialized successfully");

// For now, we'll just return the response

Expand All @@ -109,7 +110,7 @@ pub async fn create_deployment(
app_name: payload.app_name,
image: payload.image,
status: "pending".to_string(),
url,
url: None,
created_at: now,
message: "Deployment is being processed".to_string(),
}))
Expand Down
Loading