1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
//! # Containerization Module
//!
//! This module provides functionality for setting up and managing containerization
//! technologies, specifically Docker and Kubernetes, on a Linux server. It includes
//! functions for installation, configuration, and deployment of containerized applications.
//!
//! The module is designed to work across different Linux distributions by leveraging
//! the appropriate package manager and installation methods for each system.
use crate::config::Config;
use crate::distro::{get_package_manager, PackageManager};
use crate::rollback::RollbackManager;
use crate::utils::run_command;
use log::info;
use std::error::Error;
/// Sets up Docker on the system.
///
/// This function installs Docker, configures it, and ensures it's running and enabled on boot.
/// It creates a snapshot before installation for potential rollback.
///
/// # Arguments
///
/// * `rollback` - A reference to the `RollbackManager` for creating snapshots
///
/// # Returns
///
/// Returns `Ok(())` if Docker is set up successfully, or an error if setup fails.
pub fn setup_docker(rollback: &RollbackManager) -> Result<(), Box<dyn Error>> {
info!("Setting up Docker...");
let snapshot = rollback.create_snapshot()?;
install_docker()?;
configure_docker()?;
rollback.commit_snapshot(snapshot)?;
info!("Docker setup completed");
Ok(())
}
/// Sets up Kubernetes on the system.
///
/// This function installs Kubernetes tools (kubectl and minikube), configures them,
/// and ensures they're ready for use. It creates a snapshot before installation for potential rollback.
///
/// # Arguments
///
/// * `rollback` - A reference to the `RollbackManager` for creating snapshots
///
/// # Returns
///
/// Returns `Ok(())` if Kubernetes is set up successfully, or an error if setup fails.
pub fn setup_kubernetes(rollback: &RollbackManager) -> Result<(), Box<dyn Error>> {
info!("Setting up Kubernetes...");
let snapshot = rollback.create_snapshot()?;
install_kubernetes()?;
configure_kubernetes()?;
rollback.commit_snapshot(snapshot)?;
info!("Kubernetes setup completed");
Ok(())
}
/// Deploys containers for all applications specified in the configuration.
///
/// This function iterates through the list of applications in the configuration
/// and deploys each as a container, either using Docker or Kubernetes based on the configuration.
///
/// # Arguments
///
/// * `config` - A reference to the `Config` struct containing deployment information
/// * `rollback` - A reference to the `RollbackManager` for creating snapshots
///
/// # Returns
///
/// Returns `Ok(())` if all containers are deployed successfully, or an error if any deployment fails.
pub fn deploy_containers(
config: &Config,
rollback: &RollbackManager,
) -> Result<(), Box<dyn Error>> {
info!("Deploying containers...");
let snapshot = rollback.create_snapshot()?;
for app in &config.deployed_apps {
deploy_container(app, config.use_kubernetes)?;
}
rollback.commit_snapshot(snapshot)?;
info!("Container deployment completed");
Ok(())
}
/// Installs Docker on the system.
///
/// This function installs Docker using the appropriate method for the current Linux distribution.
/// It adds the Docker repository, installs necessary dependencies, and installs Docker components.
///
/// # Returns
///
/// Returns `Ok(())` if Docker is installed successfully, or an error if installation fails.
pub fn install_docker() -> Result<(), Box<dyn Error>> {
let package_manager = get_package_manager()?;
match package_manager {
PackageManager::Apt => {
run_command("apt", &["update"])?;
run_command(
"apt",
&[
"install",
"-y",
"apt-transport-https",
"ca-certificates",
"curl",
"gnupg",
"lsb-release",
],
)?;
run_command(
"curl",
&[
"-fsSL",
"https://download.docker.com/linux/ubuntu/gpg",
"|",
"gpg",
"--dearmor",
"-o",
"/usr/share/keyrings/docker-archive-keyring.gpg",
],
)?;
run_command("echo", &["\"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\"", "|", "tee", "/etc/apt/sources.list.d/docker.list", ">", "/dev/null"])?;
run_command("apt", &["update"])?;
run_command(
"apt",
&[
"install",
"-y",
"docker-ce",
"docker-ce-cli",
"containerd.io",
],
)?;
}
PackageManager::Yum => {
run_command("yum", &["install", "-y", "yum-utils"])?;
run_command(
"yum-config-manager",
&[
"--add-repo",
"https://download.docker.com/linux/centos/docker-ce.repo",
],
)?;
run_command(
"yum",
&[
"install",
"-y",
"docker-ce",
"docker-ce-cli",
"containerd.io",
],
)?;
}
PackageManager::Dnf => {
run_command("dnf", &["install", "-y", "dnf-plugins-core"])?;
run_command(
"dnf",
&[
"config-manager",
"--add-repo",
"https://download.docker.com/linux/fedora/docker-ce.repo",
],
)?;
run_command(
"dnf",
&[
"install",
"-y",
"docker-ce",
"docker-ce-cli",
"containerd.io",
],
)?;
}
}
run_command("systemctl", &["start", "docker"])?;
run_command("systemctl", &["enable", "docker"])?;
Ok(())
}
/// Configures Docker after installation.
///
/// This function sets up the Docker daemon with optimal settings, creates a Docker group,
/// adds the current user to the Docker group, and restarts the Docker service to apply changes.
///
/// # Returns
///
/// Returns `Ok(())` if Docker is configured successfully, or an error if configuration fails.
pub fn configure_docker() -> Result<(), Box<dyn Error>> {
// Create docker group if it doesn't exist
run_command("groupadd", &["docker"])?;
// Add current user to docker group
run_command("usermod", &["-aG", "docker", "$USER"])?;
// Set up Docker daemon configuration
let daemon_config = r#"
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 64000,
"Soft": 64000
}
}
}
"#;
std::fs::write("/etc/docker/daemon.json", daemon_config)?;
// Restart Docker to apply changes
run_command("systemctl", &["restart", "docker"])?;
Ok(())
}
/// Installs Kubernetes tools (kubectl and minikube) on the system.
///
/// This function downloads and installs kubectl and minikube, and installs a virtualization
/// driver (VirtualBox in this implementation) required for running Kubernetes locally.
///
/// # Returns
///
/// Returns `Ok(())` if Kubernetes tools are installed successfully, or an error if installation fails.
pub fn install_kubernetes() -> Result<(), Box<dyn Error>> {
let package_manager = get_package_manager()?;
// Install kubectl
run_command("curl", &["-LO", "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"])?;
run_command("chmod", &["+x", "./kubectl"])?;
run_command("mv", &["./kubectl", "/usr/local/bin/kubectl"])?;
// Install minikube
run_command(
"curl",
&[
"-Lo",
"minikube",
"https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64",
],
)?;
run_command("chmod", &["+x", "minikube"])?;
run_command("mv", &["minikube", "/usr/local/bin/"])?;
// Install required virtualization driver (using VirtualBox in this example)
match package_manager {
PackageManager::Apt => run_command("apt", &["install", "-y", "virtualbox"])?,
PackageManager::Yum => run_command("yum", &["install", "-y", "VirtualBox"])?,
PackageManager::Dnf => run_command("dnf", &["install", "-y", "VirtualBox"])?,
}
Ok(())
}
/// Configures Kubernetes after installation.
///
/// This function starts minikube, enables necessary addons (ingress and dashboard),
/// and sets up kubectl autocomplete for easier use.
///
/// # Returns
///
/// Returns `Ok(())` if Kubernetes is configured successfully, or an error if configuration fails.
pub fn configure_kubernetes() -> Result<(), Box<dyn Error>> {
// Start minikube
run_command("minikube", &["start"])?;
// Enable necessary addons
run_command("minikube", &["addons", "enable", "ingress"])?;
run_command("minikube", &["addons", "enable", "dashboard"])?;
// Set up kubectl autocomplete
run_command(
"kubectl",
&["completion", "bash", ">", "/etc/bash_completion.d/kubectl"],
)?;
Ok(())
}
/// Deploys a single container for the specified application.
///
/// This function deploys the application either to Kubernetes or directly to Docker,
/// based on the `use_kubernetes` flag.
///
/// # Arguments
///
/// * `app` - A string slice representing the application to deploy
/// * `use_kubernetes` - A boolean indicating whether to use Kubernetes for deployment
///
/// # Returns
///
/// Returns `Ok(())` if the container is deployed successfully, or an error if deployment fails.
pub fn deploy_container(app: &str, use_kubernetes: bool) -> Result<(), Box<dyn Error>> {
if use_kubernetes {
deploy_to_kubernetes(app)?;
} else {
deploy_to_docker(app)?;
}
Ok(())
}
/// Deploys a single container for the specified application.
///
/// This function deploys the application either to Kubernetes or directly to Docker,
/// based on the `use_kubernetes` flag.
///
/// # Arguments
///
/// * `app` - A string slice representing the application to deploy
/// * `use_kubernetes` - A boolean indicating whether to use Kubernetes for deployment
///
/// # Returns
///
/// Returns `Ok(())` if the container is deployed successfully, or an error if deployment fails.
pub fn deploy_to_kubernetes(app: &str) -> Result<(), Box<dyn Error>> {
// Create a basic deployment YAML
let deployment_yaml = format!(
r#"
apiVersion: apps/v1
kind: Deployment
metadata:
name: {}
spec:
replicas: 1
selector:
matchLabels:
app: {}
template:
metadata:
labels:
app: {}
spec:
containers:
- name: {}
image: {}:latest
ports:
- containerPort: 80
"#,
app, app, app, app, app
);
// Write the deployment YAML to a file
std::fs::write(format!("{}-deployment.yaml", app), deployment_yaml)?;
// Apply the deployment
run_command(
"kubectl",
&["apply", "-f", &format!("{}-deployment.yaml", app)],
)?;
// Expose the deployment as a service
run_command(
"kubectl",
&[
"expose",
"deployment",
app,
"--type=LoadBalancer",
"--port=80",
],
)?;
Ok(())
}
/// Deploys an application to Kubernetes.
///
/// This function creates a Kubernetes Deployment and Service for the specified application.
/// It generates a basic YAML configuration, applies it to the cluster, and exposes the deployment as a service.
///
/// # Arguments
///
/// * `app` - A string slice representing the application to deploy
///
/// # Returns
///
/// Returns `Ok(())` if the application is deployed to Kubernetes successfully, or an error if deployment fails.
pub fn deploy_to_docker(app: &str) -> Result<(), Box<dyn Error>> {
// Pull the latest image
run_command("docker", &["pull", app])?;
// Stop and remove any existing container with the same name
run_command("docker", &["stop", app]).ok();
run_command("docker", &["rm", app]).ok();
// Run the new container
run_command("docker", &["run", "-d", "--name", app, "-p", "80:80", app])?;
Ok(())
}