2786 lines
137 KiB
HTML
2786 lines
137 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
<title>ArgoBox | Ansible Sandbox</title>
|
|
|
|
<!-- SEO Meta Tags -->
|
|
<meta name="description" content="Interactive Ansible playbook testing environment. Deploy test configurations and see infrastructure automation in action.">
|
|
|
|
<!-- Favicon -->
|
|
<link rel="icon" href="images/favicon.ico" type="image/x-icon">
|
|
|
|
<!-- CSS -->
|
|
<link rel="stylesheet" href="styles.css">
|
|
|
|
<!-- Google Fonts -->
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
|
|
<!-- Font Awesome -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
|
|
|
|
<style>
|
|
:root {
|
|
/* Main Colors */
|
|
--primary-bg: #0f172a;
|
|
--secondary-bg: #1e293b;
|
|
--accent: #3b82f6;
|
|
--accent-darker: #2563eb;
|
|
--accent-gradient: linear-gradient(135deg, #2563eb, #3b82f6);
|
|
--accent-red: #ef4444;
|
|
--accent-green: #10b981;
|
|
--accent-yellow: #f59e0b;
|
|
--accent-glow: 0 0 15px rgba(59, 130, 246, 0.5);
|
|
|
|
/* Text Colors */
|
|
--text-primary: #e2e8f0;
|
|
--text-secondary: #94a3b8;
|
|
--text-accent: #3b82f6;
|
|
|
|
/* Status Colors */
|
|
--success: #10b981;
|
|
--warning: #f59e0b;
|
|
--error: #ef4444;
|
|
--info: #0ea5e9;
|
|
|
|
/* UI Elements */
|
|
--border: rgba(71, 85, 105, 0.5);
|
|
--card-bg: rgba(30, 41, 59, 0.8);
|
|
--card-hover-bg: rgba(30, 41, 59, 0.95);
|
|
--card-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
|
|
--glass-effect: saturate(180%) blur(10px);
|
|
|
|
/* Animation Timing */
|
|
--transition-fast: 0.2s ease;
|
|
--transition-normal: 0.3s ease;
|
|
--transition-slow: 0.5s ease;
|
|
}
|
|
|
|
/* Reset & Base Styles */
|
|
*, *::before, *::after {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html {
|
|
scroll-behavior: smooth;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
|
background-color: var(--primary-bg);
|
|
color: var(--text-primary);
|
|
line-height: 1.6;
|
|
overflow-x: hidden;
|
|
min-height: 100vh;
|
|
background-image:
|
|
radial-gradient(circle at 20% 35%, rgba(29, 78, 216, 0.15) 0%, transparent 50%),
|
|
radial-gradient(circle at 75% 60%, rgba(14, 165, 233, 0.1) 0%, transparent 50%);
|
|
}
|
|
|
|
.container {
|
|
max-width: 1400px;
|
|
margin: 0 auto;
|
|
padding: 0 1.5rem;
|
|
}
|
|
|
|
/* Sandbox Specific Styles */
|
|
.sandbox-container {
|
|
padding: 6rem 0 2rem;
|
|
}
|
|
|
|
.sandbox-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.sandbox-title {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.sandbox-title h1 {
|
|
font-size: 1.75rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.sandbox-actions {
|
|
display: flex;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.sandbox-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
border-radius: 0.5rem;
|
|
background-color: var(--card-bg);
|
|
border: 1px solid var(--border);
|
|
color: var(--text-primary);
|
|
font-size: 0.9rem;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all var(--transition-normal);
|
|
}
|
|
|
|
.sandbox-btn:hover {
|
|
background-color: var(--card-hover-bg);
|
|
border-color: var(--accent);
|
|
}
|
|
|
|
.sandbox-btn i {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.btn-primary {
|
|
background: var(--accent-gradient);
|
|
color: white;
|
|
border: none;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
box-shadow: var(--accent-glow);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.sandbox-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 2fr;
|
|
gap: 1.5rem;
|
|
}
|
|
|
|
.playbook-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
max-height: 80vh;
|
|
overflow-y: auto;
|
|
padding-right: 0.5rem;
|
|
scrollbar-width: thin;
|
|
scrollbar-color: var(--border) transparent;
|
|
}
|
|
|
|
.playbook-list::-webkit-scrollbar {
|
|
width: 6px;
|
|
}
|
|
|
|
.playbook-list::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
.playbook-list::-webkit-scrollbar-thumb {
|
|
background-color: var(--border);
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.playbook-card {
|
|
background-color: var(--card-bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 0.75rem;
|
|
padding: 1.25rem;
|
|
cursor: pointer;
|
|
transition: all var(--transition-normal);
|
|
}
|
|
|
|
.playbook-card:hover {
|
|
transform: translateY(-3px);
|
|
border-color: var(--accent);
|
|
box-shadow: var(--card-shadow);
|
|
}
|
|
|
|
.playbook-card.active {
|
|
border-color: var(--accent);
|
|
background-color: rgba(59, 130, 246, 0.1);
|
|
}
|
|
|
|
.playbook-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.playbook-title {
|
|
font-weight: 600;
|
|
font-size: 1.1rem;
|
|
}
|
|
|
|
.playbook-tag {
|
|
font-size: 0.75rem;
|
|
padding: 0.15rem 0.5rem;
|
|
border-radius: 9999px;
|
|
background-color: rgba(59, 130, 246, 0.1);
|
|
color: var(--accent);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.playbook-description {
|
|
font-size: 0.9rem;
|
|
color: var(--text-secondary);
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.playbook-details {
|
|
display: flex;
|
|
gap: 1rem;
|
|
font-size: 0.8rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.playbook-detail {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.35rem;
|
|
}
|
|
|
|
.playbook-detail i {
|
|
font-size: 0.85rem;
|
|
color: var(--accent);
|
|
}
|
|
|
|
.sandbox-preview {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 80vh;
|
|
}
|
|
|
|
.preview-container {
|
|
background-color: var(--card-bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 0.75rem;
|
|
flex: 1;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.preview-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 1rem 1.5rem;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.preview-title {
|
|
font-weight: 600;
|
|
font-size: 1.1rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
}
|
|
|
|
.preview-tabs {
|
|
display: flex;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.preview-tab {
|
|
color: var(--text-secondary);
|
|
font-size: 0.9rem;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
padding-bottom: 0.25rem;
|
|
border-bottom: 2px solid transparent;
|
|
transition: all var(--transition-normal);
|
|
}
|
|
|
|
.preview-tab:hover {
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.preview-tab.active {
|
|
color: var(--accent);
|
|
border-bottom-color: var(--accent);
|
|
}
|
|
|
|
.preview-content {
|
|
flex: 1;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.tab-content {
|
|
display: none;
|
|
flex: 1;
|
|
overflow: auto;
|
|
padding: 1.5rem;
|
|
}
|
|
|
|
.tab-content.active {
|
|
display: block;
|
|
}
|
|
|
|
.code-editor {
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-size: 0.9rem;
|
|
line-height: 1.5;
|
|
overflow: auto;
|
|
height: 100%;
|
|
}
|
|
|
|
.code-line {
|
|
display: flex;
|
|
}
|
|
|
|
.line-number {
|
|
width: 3rem;
|
|
text-align: right;
|
|
padding-right: 1rem;
|
|
user-select: none;
|
|
color: var(--text-secondary);
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.line-content {
|
|
flex: 1;
|
|
}
|
|
|
|
.code-comment {
|
|
color: #6b7280;
|
|
font-style: italic;
|
|
}
|
|
|
|
.code-key {
|
|
color: #93c5fd;
|
|
}
|
|
|
|
.code-value {
|
|
color: #fbbf24;
|
|
}
|
|
|
|
.code-string {
|
|
color: #a3be8c;
|
|
}
|
|
|
|
.preview-form {
|
|
padding: 1.5rem;
|
|
overflow: auto;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.form-label {
|
|
display: block;
|
|
margin-bottom: 0.5rem;
|
|
font-weight: 500;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.form-control {
|
|
width: 100%;
|
|
padding: 0.75rem 1rem;
|
|
background-color: var(--primary-bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 0.5rem;
|
|
color: var(--text-primary);
|
|
font-family: 'Inter', sans-serif;
|
|
font-size: 0.9rem;
|
|
transition: all var(--transition-normal);
|
|
}
|
|
|
|
.form-control:focus {
|
|
outline: none;
|
|
border-color: var(--accent);
|
|
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
|
|
}
|
|
|
|
.form-select {
|
|
appearance: none;
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2394a3b8'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");
|
|
background-repeat: no-repeat;
|
|
background-position: right 1rem center;
|
|
background-size: 1em;
|
|
}
|
|
|
|
.form-text {
|
|
font-size: 0.8rem;
|
|
color: var(--text-secondary);
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
.form-check {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
|
|
.form-check-input {
|
|
margin-right: 0.75rem;
|
|
appearance: none;
|
|
width: 1.25rem;
|
|
height: 1.25rem;
|
|
background-color: var(--primary-bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 0.25rem;
|
|
cursor: pointer;
|
|
transition: all var(--transition-normal);
|
|
position: relative;
|
|
}
|
|
|
|
.form-check-input:checked {
|
|
background-color: var(--accent);
|
|
border-color: var(--accent);
|
|
}
|
|
|
|
.form-check-input:checked::after {
|
|
content: '✓';
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
color: white;
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.form-check-label {
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.terminal {
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-size: 0.85rem;
|
|
line-height: 1.5;
|
|
padding: 1.5rem;
|
|
background-color: #1a1a1a;
|
|
color: #e2e8f0;
|
|
overflow: auto;
|
|
height: 100%;
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
.terminal-line {
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.terminal-success {
|
|
color: var(--success);
|
|
}
|
|
|
|
.terminal-error {
|
|
color: var(--error);
|
|
}
|
|
|
|
.terminal-warning {
|
|
color: var(--warning);
|
|
}
|
|
|
|
.terminal-command {
|
|
color: var(--accent);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.preview-actions {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 1rem 1.5rem;
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
|
|
.preview-status {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.status-dot {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.status-ready {
|
|
background-color: var(--info);
|
|
}
|
|
|
|
.status-running {
|
|
background-color: var(--warning);
|
|
animation: pulse 1s infinite;
|
|
}
|
|
|
|
.status-success {
|
|
background-color: var(--success);
|
|
}
|
|
|
|
.status-error {
|
|
background-color: var(--error);
|
|
}
|
|
|
|
.preview-buttons {
|
|
display: flex;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.vm-status {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.75rem;
|
|
padding: 1.5rem;
|
|
display: none;
|
|
}
|
|
|
|
.vm-status.active {
|
|
display: flex;
|
|
}
|
|
|
|
.vm-card {
|
|
background-color: rgba(30, 41, 59, 0.5);
|
|
border-radius: 0.5rem;
|
|
padding: 1rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.vm-icon {
|
|
width: 3rem;
|
|
height: 3rem;
|
|
background-color: var(--secondary-bg);
|
|
border-radius: 0.5rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 1.5rem;
|
|
color: var(--accent);
|
|
}
|
|
|
|
.vm-info {
|
|
flex: 1;
|
|
}
|
|
|
|
.vm-name {
|
|
font-weight: 600;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.vm-details {
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.vm-progress {
|
|
flex: 1;
|
|
height: 4px;
|
|
background-color: rgba(255, 255, 255, 0.1);
|
|
border-radius: 2px;
|
|
overflow: hidden;
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
.vm-progress-bar {
|
|
height: 100%;
|
|
background-color: var(--accent);
|
|
border-radius: 2px;
|
|
transition: width 0.3s ease;
|
|
}
|
|
|
|
.vm-state {
|
|
padding: 0.25rem 0.75rem;
|
|
border-radius: 9999px;
|
|
font-size: 0.75rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.vm-state-provisioning {
|
|
background-color: rgba(245, 158, 11, 0.1);
|
|
color: var(--warning);
|
|
}
|
|
|
|
.vm-state-running {
|
|
background-color: rgba(16, 185, 129, 0.1);
|
|
color: var(--success);
|
|
}
|
|
|
|
.vm-state-stopping {
|
|
background-color: rgba(239, 68, 68, 0.1);
|
|
color: var(--error);
|
|
}
|
|
|
|
.time-remaining {
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
text-align: center;
|
|
margin-top: 1.5rem;
|
|
}
|
|
|
|
.time-progress {
|
|
width: 100%;
|
|
height: 4px;
|
|
background-color: rgba(255, 255, 255, 0.1);
|
|
border-radius: 2px;
|
|
overflow: hidden;
|
|
margin-top: 0.75rem;
|
|
}
|
|
|
|
.time-progress-bar {
|
|
height: 100%;
|
|
background-color: var(--accent);
|
|
border-radius: 2px;
|
|
transition: width 1s linear;
|
|
}
|
|
|
|
/* Footer */
|
|
.sandbox-footer {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-top: 2rem;
|
|
padding-top: 1.5rem;
|
|
border-top: 1px solid var(--border);
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.back-to-site {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
color: var(--accent);
|
|
font-weight: 500;
|
|
transition: all var(--transition-normal);
|
|
}
|
|
|
|
.back-to-site:hover {
|
|
color: var(--accent-darker);
|
|
transform: translateX(-3px);
|
|
}
|
|
|
|
/* Animation */
|
|
@keyframes pulse {
|
|
0% {
|
|
opacity: 1;
|
|
}
|
|
50% {
|
|
opacity: 0.5;
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 992px) {
|
|
.sandbox-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.playbook-list {
|
|
max-height: initial;
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.sandbox-header {
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.sandbox-actions {
|
|
width: 100%;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.preview-tabs {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
.offline-notice {
|
|
background-color: rgba(239, 68, 68, 0.1);
|
|
border: 1px solid rgba(239, 68, 68, 0.3);
|
|
border-radius: 0.5rem;
|
|
padding: 1rem;
|
|
margin-bottom: 2rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.offline-notice-icon {
|
|
font-size: 1.5rem;
|
|
color: var(--error);
|
|
}
|
|
|
|
.offline-notice-text {
|
|
flex: 1;
|
|
}
|
|
|
|
.offline-notice h3 {
|
|
color: var(--error);
|
|
margin-bottom: 0.5rem;
|
|
font-size: 1.1rem;
|
|
}
|
|
|
|
.offline-notice p {
|
|
color: var(--text-secondary);
|
|
font-size: 0.9rem;
|
|
margin: 0;
|
|
}
|
|
|
|
/* View tab placeholders */
|
|
.view-placeholder {
|
|
display: none;
|
|
padding: 0;
|
|
height: 100%;
|
|
overflow: auto;
|
|
}
|
|
|
|
.view-placeholder.active {
|
|
display: block;
|
|
}
|
|
|
|
.deployed-site {
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background-color: var(--primary-bg);
|
|
}
|
|
|
|
.deployed-header {
|
|
padding: 1.5rem;
|
|
background: linear-gradient(to right, rgba(30, 41, 59, 0.8), rgba(15, 23, 42, 0.9));
|
|
color: white;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.deployed-header h1 {
|
|
font-size: 1.5rem;
|
|
margin: 0 0 0.5rem 0;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.deployed-header p {
|
|
margin: 0;
|
|
font-size: 0.9rem;
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.deployed-main {
|
|
flex: 1;
|
|
padding: 1.5rem;
|
|
overflow: auto;
|
|
}
|
|
|
|
.deployed-actions {
|
|
padding: 1rem 1.5rem;
|
|
display: flex;
|
|
gap: 0.75rem;
|
|
border-top: 1px solid var(--border);
|
|
background-color: rgba(15, 23, 42, 0.3);
|
|
}
|
|
|
|
.btn-action {
|
|
background-color: var(--secondary-bg);
|
|
color: var(--text-primary);
|
|
border: 1px solid var(--border);
|
|
border-radius: 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
font-size: 0.85rem;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all var(--transition-normal);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.btn-action:hover {
|
|
background-color: var(--accent);
|
|
color: white;
|
|
border-color: var(--accent);
|
|
}
|
|
|
|
/* Container items for Docker Compose */
|
|
.container-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.75rem;
|
|
}
|
|
|
|
.container-item {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 1rem;
|
|
background-color: rgba(15, 23, 42, 0.3);
|
|
border-radius: 0.5rem;
|
|
border-left: 4px solid var(--border);
|
|
}
|
|
|
|
.container-item.running {
|
|
border-left-color: var(--success);
|
|
}
|
|
|
|
.container-item.stopped {
|
|
border-left-color: var(--error);
|
|
}
|
|
|
|
.container-item.restarting {
|
|
border-left-color: var(--warning);
|
|
}
|
|
|
|
.container-icon {
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
background-color: var(--secondary-bg);
|
|
border-radius: 0.5rem;
|
|
font-size: 1.25rem;
|
|
margin-right: 1rem;
|
|
color: var(--accent);
|
|
}
|
|
|
|
.container-name {
|
|
font-weight: 600;
|
|
font-size: 1rem;
|
|
flex: 1;
|
|
}
|
|
|
|
.container-status {
|
|
margin-right: 1.5rem;
|
|
font-size: 0.85rem;
|
|
padding: 0.25rem 0.75rem;
|
|
border-radius: 9999px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.running .container-status {
|
|
background-color: rgba(16, 185, 129, 0.1);
|
|
color: var(--success);
|
|
}
|
|
|
|
.stopped .container-status {
|
|
background-color: rgba(239, 68, 68,.1);
|
|
color: var(--error);
|
|
}
|
|
|
|
.restarting .container-status {
|
|
background-color: rgba(245, 158, 11, 0.1);
|
|
color: var(--warning);
|
|
}
|
|
|
|
.container-ports {
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
font-family: 'JetBrains Mono', monospace;
|
|
}
|
|
|
|
/* K8s cluster styles */
|
|
.cluster-overview {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2rem;
|
|
}
|
|
|
|
.cluster-section {
|
|
background-color: rgba(15, 23, 42, 0.3);
|
|
border-radius: 0.5rem;
|
|
padding: 1.25rem;
|
|
}
|
|
|
|
.cluster-section h3 {
|
|
margin: 0 0 1rem 0;
|
|
font-size: 1.1rem;
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.k8s-items {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.k8s-item {
|
|
display: flex;
|
|
background-color: rgba(15, 23, 42, 0.5);
|
|
padding: 0.75rem 1rem;
|
|
border-radius: 0.35rem;
|
|
font-size: 0.9rem;
|
|
align-items: center;
|
|
}
|
|
|
|
.k8s-name {
|
|
flex: 1;
|
|
font-weight: 500;
|
|
font-family: 'JetBrains Mono', monospace;
|
|
}
|
|
|
|
.k8s-ready {
|
|
width: 5rem;
|
|
color: var(--success);
|
|
}
|
|
|
|
.k8s-role, .k8s-type {
|
|
width: 8rem;
|
|
color: var(--accent);
|
|
}
|
|
|
|
.k8s-version, .k8s-age {
|
|
color: var(--text-secondary);
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
/* LAMP Stack styles */
|
|
.lamp-status {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.75rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.lamp-component {
|
|
display: flex;
|
|
background-color: rgba(15, 23, 42, 0.3);
|
|
border-radius: 0.5rem;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.lamp-icon {
|
|
width: 3rem;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
font-size: 1.25rem;
|
|
padding: 1rem 0;
|
|
}
|
|
|
|
.lamp-icon.running {
|
|
background-color: rgba(16, 185, 129, 0.1);
|
|
color: var(--success);
|
|
}
|
|
|
|
.lamp-details {
|
|
padding: 0.75rem 1rem;
|
|
flex: 1;
|
|
}
|
|
|
|
.lamp-name {
|
|
font-weight: 500;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.lamp-info {
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.php-info-preview {
|
|
background-color: rgba(15, 23, 42, 0.3);
|
|
border-radius: 0.5rem;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.php-header {
|
|
background-color: rgba(15, 23, 42, 0.5);
|
|
padding: 0.75rem 1rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.php-content {
|
|
padding: 0.75rem 1rem;
|
|
}
|
|
|
|
.php-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.php-table td {
|
|
padding: 0.5rem;
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.php-table tr:last-child td {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.php-table td:first-child {
|
|
font-weight: 500;
|
|
width: 30%;
|
|
}
|
|
|
|
/* Security check styles */
|
|
.security-checks {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1.5rem;
|
|
}
|
|
|
|
.security-section {
|
|
background-color: rgba(15, 23, 42, 0.3);
|
|
border-radius: 0.5rem;
|
|
padding: 1.25rem;
|
|
}
|
|
|
|
.security-section h3 {
|
|
margin: 0 0 1rem 0;
|
|
font-size: 1.1rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.security-item {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 0.75rem;
|
|
background-color: rgba(15, 23, 42, 0.5);
|
|
border-radius: 0.35rem;
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
|
|
.security-item:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.security-icon {
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border-radius: 0.5rem;
|
|
font-size: 1.25rem;
|
|
margin-right: 1rem;
|
|
}
|
|
|
|
.security-icon.passed {
|
|
background-color: rgba(16, 185, 129, 0.1);
|
|
color: var(--success);
|
|
}
|
|
|
|
.security-icon.warning {
|
|
background-color: rgba(245, 158, 11, 0.1);
|
|
color: var(--warning);
|
|
}
|
|
|
|
.security-icon.failed {
|
|
background-color: rgba(239, 68, 68, 0.1);
|
|
color: var(--error);
|
|
}
|
|
|
|
.security-details {
|
|
flex: 1;
|
|
}
|
|
|
|
.security-name {
|
|
font-weight: 500;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.security-info {
|
|
font-size: 0.85rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.security-status {
|
|
padding: 0.25rem 0.75rem;
|
|
border-radius: 9999px;
|
|
background-color: rgba(16, 185, 129, 0.1);
|
|
color: var(--success);
|
|
font-size: 0.8rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* Web Server view styles */
|
|
.server-metrics {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.75rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.metric-item {
|
|
background-color: rgba(15, 23, 42, 0.3);
|
|
border-radius: 0.5rem;
|
|
padding: 1rem;
|
|
}
|
|
|
|
.metric-label {
|
|
font-size: 0.9rem;
|
|
margin-bottom: 0.5rem;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.metric-bar {
|
|
height: 0.5rem;
|
|
background-color: rgba(255, 255, 255, 0.1);
|
|
border-radius: 0.25rem;
|
|
overflow: hidden;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.metric-fill {
|
|
height: 100%;
|
|
background-color: var(--accent);
|
|
border-radius: 0.25rem;
|
|
}
|
|
|
|
.metric-value {
|
|
font-size: 0.8rem;
|
|
color: var(--text-secondary);
|
|
text-align: right;
|
|
}
|
|
|
|
/* Simulation mode toggle */
|
|
.simulation-toggle {
|
|
position: fixed;
|
|
top: 20px;
|
|
right: 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
background-color: var(--bg-card);
|
|
padding: 8px 12px;
|
|
border-radius: 6px;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
z-index: 100;
|
|
border: 1px solid var(--border-color);
|
|
}
|
|
|
|
.toggle-label {
|
|
margin-right: 8px;
|
|
font-weight: 500;
|
|
color: var(--text-primary);
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.toggle-status {
|
|
margin-left: 8px;
|
|
color: var(--primary);
|
|
font-weight: 500;
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.toggle-switch {
|
|
position: relative;
|
|
display: inline-block;
|
|
width: 46px;
|
|
height: 24px;
|
|
}
|
|
|
|
.toggle-switch input {
|
|
opacity: 0;
|
|
width: 0;
|
|
height: 0;
|
|
}
|
|
|
|
.toggle-slider {
|
|
position: absolute;
|
|
cursor: pointer;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: #ccc;
|
|
transition: .4s;
|
|
border-radius: 24px;
|
|
}
|
|
|
|
.toggle-slider:before {
|
|
position: absolute;
|
|
content: "";
|
|
height: 18px;
|
|
width: 18px;
|
|
left: 3px;
|
|
bottom: 3px;
|
|
background-color: white;
|
|
transition: .4s;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
input:checked + .toggle-slider {
|
|
background-color: var(--primary);
|
|
}
|
|
|
|
input:checked + .toggle-slider:before {
|
|
transform: translateX(22px);
|
|
}
|
|
|
|
/* Web server styles */
|
|
.website-preview {
|
|
background-color: rgba(15, 23, 42, 0.3);
|
|
border-radius: 0.5rem;
|
|
overflow: hidden;
|
|
height: 300px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.website-header {
|
|
display: flex;
|
|
align-items: center;
|
|
background-color: rgba(15, 23, 42, 0.5);
|
|
padding: 0.5rem 1rem;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.website-controls {
|
|
display: flex;
|
|
gap: 0.25rem;
|
|
}
|
|
|
|
.website-control {
|
|
width: 12px;
|
|
height: 12px;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.website-control.close {
|
|
background-color: #ff5f56;
|
|
}
|
|
|
|
.website-control.minimize {
|
|
background-color: #ffbd2e;
|
|
}
|
|
|
|
.website-control.expand {
|
|
background-color: #27c93f;
|
|
}
|
|
|
|
.website-address {
|
|
flex: 1;
|
|
background-color: rgba(15, 23, 42, 0.7);
|
|
border-radius: 0.25rem;
|
|
padding: 0.25rem 0.5rem;
|
|
font-size: 0.8rem;
|
|
font-family: 'JetBrains Mono', monospace;
|
|
color: var(--text-secondary);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.website-address i {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.website-content {
|
|
flex: 1;
|
|
padding: 1.5rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
text-align: center;
|
|
}
|
|
|
|
.nginx-welcome {
|
|
width: 80px;
|
|
height: 80px;
|
|
margin-bottom: 1rem;
|
|
color: var(--accent);
|
|
opacity: 0.9;
|
|
}
|
|
|
|
.web-title {
|
|
font-size: 1.5rem;
|
|
font-weight: 600;
|
|
margin-bottom: 0.5rem;
|
|
background: linear-gradient(90deg, var(--accent), #3b82f6);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
}
|
|
|
|
.web-subtitle {
|
|
color: var(--text-secondary);
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
/* Additional styles for simulation toggle */
|
|
.simulation-toggle {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 15px;
|
|
padding: 8px 15px;
|
|
background-color: #f1f8ff;
|
|
border-radius: 4px;
|
|
border-left: 3px solid #0078d7;
|
|
}
|
|
|
|
.toggle-label {
|
|
font-weight: 500;
|
|
margin-right: 10px;
|
|
color: #333;
|
|
}
|
|
|
|
.toggle-switch {
|
|
position: relative;
|
|
display: inline-block;
|
|
width: 50px;
|
|
height: 24px;
|
|
}
|
|
|
|
.toggle-switch input {
|
|
opacity: 0;
|
|
width: 0;
|
|
height: 0;
|
|
}
|
|
|
|
.toggle-slider {
|
|
position: absolute;
|
|
cursor: pointer;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: #ccc;
|
|
transition: .4s;
|
|
border-radius: 24px;
|
|
}
|
|
|
|
.toggle-slider:before {
|
|
position: absolute;
|
|
content: "";
|
|
height: 16px;
|
|
width: 16px;
|
|
left: 4px;
|
|
bottom: 4px;
|
|
background-color: white;
|
|
transition: .4s;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
input:checked + .toggle-slider {
|
|
background-color: #2196F3;
|
|
}
|
|
|
|
input:focus + .toggle-slider {
|
|
box-shadow: 0 0 1px #2196F3;
|
|
}
|
|
|
|
input:checked + .toggle-slider:before {
|
|
transform: translateX(26px);
|
|
}
|
|
|
|
.toggle-status {
|
|
margin-left: 10px;
|
|
font-weight: 500;
|
|
color: #2196F3;
|
|
}
|
|
|
|
.simulation-mode .preview-view {
|
|
position: relative;
|
|
}
|
|
|
|
.simulation-mode .preview-view:after {
|
|
content: "Simulation Mode";
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
background-color: #ffbf00;
|
|
color: #333;
|
|
padding: 3px 8px;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<!-- Navigation Bar -->
|
|
<nav class="navbar">
|
|
<div class="container">
|
|
<div class="logo">
|
|
<a href="index.html">
|
|
<span class="logo-text-glow">ArgoBox</span><span class="logo-dot-glow">.com</span>
|
|
</a>
|
|
</div>
|
|
<div class="nav-menu">
|
|
<a href="index.html#home" class="nav-link">Home</a>
|
|
<a href="index.html#technologies" class="nav-link">Technologies</a>
|
|
<a href="index.html#services" class="nav-link">Services</a>
|
|
<a href="index.html#projects" class="nav-link">Projects</a>
|
|
<a href="index.html#dashboards" class="nav-link">Dashboards</a>
|
|
<a href="index.html#contact" class="nav-link">Contact</a>
|
|
</div>
|
|
<div class="nav-buttons">
|
|
<a href="https://dashboard.argobox.com" class="dashboard-link" target="_blank">
|
|
<span class="live-indicator"></span>
|
|
<span>Live Dashboard</span>
|
|
</a>
|
|
<button class="menu-toggle" aria-label="Toggle menu">
|
|
<i class="fas fa-bars"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Top Links -->
|
|
<div class="top-links">
|
|
<a href="https://laforceit.com" class="laforceit-link">
|
|
<span class="logo-text-glow">LaForceIT</span><span class="logo-dot-glow">.com</span>
|
|
</a>
|
|
<a href="construction.html" class="signin-button" target="_blank">
|
|
<i class="fas fa-sign-in-alt"></i>
|
|
<span>Sign In</span>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Sandbox Content -->
|
|
<div class="sandbox-container">
|
|
<div class="container">
|
|
<!-- Simulation Mode Toggle -->
|
|
<div class="simulation-toggle">
|
|
<span class="toggle-label">Simulation Mode</span>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" checked>
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
<span class="toggle-status">Active</span>
|
|
</div>
|
|
|
|
<!-- Offline Notice -->
|
|
<div class="offline-notice">
|
|
<div class="offline-notice-icon">
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
</div>
|
|
<div class="offline-notice-text">
|
|
<h3>Ansible Sandbox is Currently Offline</h3>
|
|
<p>The Ansible Sandbox environment is currently in simulation mode. You can explore the interface, but actual deployments are not available at this time. We're working to bring the full functionality online soon.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sandbox-header">
|
|
<div class="sandbox-title">
|
|
<h1>Ansible Sandbox</h1>
|
|
</div>
|
|
|
|
<div class="sandbox-actions">
|
|
<a href="ansible-help.html" class="sandbox-btn">
|
|
<i class="fas fa-question-circle"></i>
|
|
<span>Help</span>
|
|
</a>
|
|
<a href="ansible-docs.html" class="sandbox-btn">
|
|
<i class="fas fa-book"></i>
|
|
<span>Documentation</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sandbox-grid">
|
|
<div class="playbook-list">
|
|
<div class="playbook-card active" data-playbook="web-server">
|
|
<div class="playbook-header">
|
|
<h3 class="playbook-title">Web Server Deployment</h3>
|
|
<span class="playbook-tag">Basic</span>
|
|
</div>
|
|
<p class="playbook-description">
|
|
Deploy a Nginx web server with a sample website in a controlled environment.
|
|
</p>
|
|
<div class="playbook-details">
|
|
<div class="playbook-detail">
|
|
<i class="fas fa-clock"></i>
|
|
<span>Runtime: ~3 min</span>
|
|
</div>
|
|
<div class="playbook-detail">
|
|
<i class="fas fa-server"></i>
|
|
<span>1 VM</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="playbook-card" data-playbook="docker-compose">
|
|
<div class="playbook-header">
|
|
<h3 class="playbook-title">Docker Compose Stack</h3>
|
|
<span class="playbook-tag">Intermediate</span>
|
|
</div>
|
|
<p class="playbook-description">
|
|
Deploy a multi-container application using Docker Compose with automatic configuration.
|
|
</p>
|
|
<div class="playbook-details">
|
|
<div class="playbook-detail">
|
|
<i class="fas fa-clock"></i>
|
|
<span>Runtime: ~5 min</span>
|
|
</div>
|
|
<div class="playbook-detail">
|
|
<i class="fas fa-server"></i>
|
|
<span>1 VM</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="playbook-card" data-playbook="k3s-cluster">
|
|
<div class="playbook-header">
|
|
<h3 class="playbook-title">K3s Kubernetes Cluster</h3>
|
|
<span class="playbook-tag">Advanced</span>
|
|
</div>
|
|
<p class="playbook-description">
|
|
Deploy a lightweight Kubernetes cluster with basic services and sample application.
|
|
</p>
|
|
<div class="playbook-details">
|
|
<div class="playbook-detail">
|
|
<i class="fas fa-clock"></i>
|
|
<span>Runtime: ~8 min</span>
|
|
</div>
|
|
<div class="playbook-detail">
|
|
<i class="fas fa-server"></i>
|
|
<span>3 VMs</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="playbook-card" data-playbook="lamp-stack">
|
|
<div class="playbook-header">
|
|
<h3 class="playbook-title">LAMP Stack</h3>
|
|
<span class="playbook-tag">Intermediate</span>
|
|
</div>
|
|
<p class="playbook-description">
|
|
Deploy a Linux, Apache, MySQL, and PHP stack with a sample application.
|
|
</p>
|
|
<div class="playbook-details">
|
|
<div class="playbook-detail">
|
|
<i class="fas fa-clock"></i>
|
|
<span>Runtime: ~4 min</span>
|
|
</div>
|
|
<div class="playbook-detail">
|
|
<i class="fas fa-server"></i>
|
|
<span>1 VM</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="playbook-card" data-playbook="security-hardening">
|
|
<div class="playbook-header">
|
|
<h3 class="playbook-title">Security Hardening</h3>
|
|
<span class="playbook-tag">Advanced</span>
|
|
</div>
|
|
<p class="playbook-description">
|
|
Apply security best practices to a Linux server including firewall, SSH hardening, and more.
|
|
</p>
|
|
<div class="playbook-details">
|
|
<div class="playbook-detail">
|
|
<i class="fas fa-clock"></i>
|
|
<span>Runtime: ~6 min</span>
|
|
</div>
|
|
<div class="playbook-detail">
|
|
<i class="fas fa-server"></i>
|
|
<span>1 VM</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sandbox-preview">
|
|
<div class="preview-container">
|
|
<div class="preview-header">
|
|
<div class="preview-title">
|
|
<i class="fas fa-file-code"></i>
|
|
<span>Web Server Deployment</span>
|
|
</div>
|
|
<div class="preview-tabs">
|
|
<div class="preview-tab active" data-tab="code">Playbook</div>
|
|
<div class="preview-tab" data-tab="config">Configuration</div>
|
|
<div class="preview-tab" data-tab="output">Output</div>
|
|
<div class="preview-tab" data-tab="status">VM Status</div>
|
|
<div class="preview-tab" data-tab="view">View</div>
|
|
</div>
|
|
</div>
|
|
<div class="preview-content">
|
|
<div class="tab-content active" id="code-tab">
|
|
<div class="code-editor">
|
|
<div class="code-line">
|
|
<span class="line-number">1</span>
|
|
<span class="line-content code-comment">---</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">2</span>
|
|
<span class="line-content code-comment"># Web Server Deployment Playbook</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">3</span>
|
|
<span class="line-content code-comment"># This playbook installs and configures a basic Nginx web server</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">4</span>
|
|
<span class="line-content"></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">5</span>
|
|
<span class="line-content">- <span class="code-key">name</span>: <span class="code-string">Deploy Web Server</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">6</span>
|
|
<span class="line-content"> <span class="code-key">hosts</span>: <span class="code-value">all</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">7</span>
|
|
<span class="line-content"> <span class="code-key">become</span>: <span class="code-value">yes</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">8</span>
|
|
<span class="line-content"> <span class="code-key">vars</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">9</span>
|
|
<span class="line-content"> <span class="code-key">web_domain</span>: <span class="code-string">example.local</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">10</span>
|
|
<span class="line-content"> <span class="code-key">web_root</span>: <span class="code-string">/var/www/html</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">11</span>
|
|
<span class="line-content"> <span class="code-key">enable_https</span>: <span class="code-value">false</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">12</span>
|
|
<span class="line-content"> <span class="code-key">web_color</span>: <span class="code-string">blue</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">13</span>
|
|
<span class="line-content"></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">14</span>
|
|
<span class="line-content"> <span class="code-key">tasks</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">15</span>
|
|
<span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Update apt cache</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">16</span>
|
|
<span class="line-content"> <span class="code-key">apt</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">17</span>
|
|
<span class="line-content"> <span class="code-key">update_cache</span>: <span class="code-value">yes</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">18</span>
|
|
<span class="line-content"> <span class="code-key">cache_valid_time</span>: <span class="code-value">3600</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">19</span>
|
|
<span class="line-content"></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">20</span>
|
|
<span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Install Nginx and required packages</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">21</span>
|
|
<span class="line-content"> <span class="code-key">apt</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">22</span>
|
|
<span class="line-content"> <span class="code-key">name</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">23</span>
|
|
<span class="line-content"> - <span class="code-string">nginx</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">24</span>
|
|
<span class="line-content"> - <span class="code-string">curl</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">25</span>
|
|
<span class="line-content"> <span class="code-key">state</span>: <span class="code-string">present</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">26</span>
|
|
<span class="line-content"></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">27</span>
|
|
<span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Create web root directory</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">28</span>
|
|
<span class="line-content"> <span class="code-key">file</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">29</span>
|
|
<span class="line-content"> <span class="code-key">path</span>: <span class="code-string">"{{ web_root }}"</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">30</span>
|
|
<span class="line-content"> <span class="code-key">state</span>: <span class="code-string">directory</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">31</span>
|
|
<span class="line-content"> <span class="code-key">mode</span>: <span class="code-string">'0755'</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">32</span>
|
|
<span class="line-content"></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">33</span>
|
|
<span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Create sample website</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">34</span>
|
|
<span class="line-content"> <span class="code-key">template</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">35</span>
|
|
<span class="line-content"> <span class="code-key">src</span>: <span class="code-string">templates/index.html.j2</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">36</span>
|
|
<span class="line-content"> <span class="code-key">dest</span>: <span class="code-string">"{{ web_root }}/index.html"</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">37</span>
|
|
<span class="line-content"> <span class="code-key">mode</span>: <span class="code-string">'0644'</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">38</span>
|
|
<span class="line-content"></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">39</span>
|
|
<span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Configure Nginx virtual host</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">40</span>
|
|
<span class="line-content"> <span class="code-key">template</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">41</span>
|
|
<span class="line-content"> <span class="code-key">src</span>: <span class="code-string">templates/nginx.conf.j2</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">42</span>
|
|
<span class="line-content"> <span class="code-key">dest</span>: <span class="code-string">/etc/nginx/sites-available/{{ web_domain }}</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">43</span>
|
|
<span class="line-content"> <span class="code-key">notify</span>: <span class="code-string">restart nginx</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">44</span>
|
|
<span class="line-content"></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">45</span>
|
|
<span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Enable Nginx virtual host</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">46</span>
|
|
<span class="line-content"> <span class="code-key">file</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">47</span>
|
|
<span class="line-content"> <span class="code-key">src</span>: <span class="code-string">/etc/nginx/sites-available/{{ web_domain }}</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">48</span>
|
|
<span class="line-content"> <span class="code-key">dest</span>: <span class="code-string">/etc/nginx/sites-enabled/{{ web_domain }}</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">49</span>
|
|
<span class="line-content"> <span class="code-key">state</span>: <span class="code-string">link</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">50</span>
|
|
<span class="line-content"> <span class="code-key">notify</span>: <span class="code-string">restart nginx</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">51</span>
|
|
<span class="line-content"></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">52</span>
|
|
<span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Start Nginx</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">53</span>
|
|
<span class="line-content"> <span class="code-key">service</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">54</span>
|
|
<span class="line-content"> <span class="code-key">name</span>: <span class="code-string">nginx</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">55</span>
|
|
<span class="line-content"> <span class="code-key">state</span>: <span class="code-string">started</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">56</span>
|
|
<span class="line-content"> <span class="code-key">enabled</span>: <span class="code-value">yes</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">57</span>
|
|
<span class="line-content"></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">58</span>
|
|
<span class="line-content"> <span class="code-key">handlers</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">59</span>
|
|
<span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">restart nginx</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">60</span>
|
|
<span class="line-content"> <span class="code-key">service</span>:</span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">61</span>
|
|
<span class="line-content"> <span class="code-key">name</span>: <span class="code-string">nginx</span></span>
|
|
</div>
|
|
<div class="code-line">
|
|
<span class="line-number">62</span>
|
|
<span class="line-content"> <span class="code-key">state</span>: <span class="code-string">restarted</span></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-content" id="config-tab">
|
|
<div class="preview-form">
|
|
<div class="form-group">
|
|
<label class="form-label" for="web_domain">Web Domain</label>
|
|
<input type="text" id="web_domain" class="form-control" value="example.local">
|
|
<div class="form-text">Domain name for the Nginx virtual host.</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="web_root">Web Root</label>
|
|
<input type="text" id="web_root" class="form-control" value="/var/www/html">
|
|
<div class="form-text">Directory path where website files will be stored.</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Enable HTTPS</label>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="enable_https">
|
|
<label class="form-check-label" for="enable_https">
|
|
Configure HTTPS with self-signed certificate
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="web_color">Theme Color</label>
|
|
<select id="web_color" class="form-control form-select">
|
|
<option value="blue" selected>Blue</option>
|
|
<option value="green">Green</option>
|
|
<option value="red">Red</option>
|
|
<option value="purple">Purple</option>
|
|
</select>
|
|
<div class="form-text">Color theme for the sample website.</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="vm_template">VM Template</label>
|
|
<select id="vm_template" class="form-control form-select">
|
|
<option value="ubuntu-22.04" selected>Ubuntu 22.04 LTS</option>
|
|
<option value="debian-11">Debian 11</option>
|
|
<option value="centos-stream-9">CentOS Stream 9</option>
|
|
</select>
|
|
<div class="form-text">Operating system for the virtual machine.</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="vm_resources">VM Resources</label>
|
|
<select id="vm_resources" class="form-control form-select">
|
|
<option value="small" selected>Small (1 vCPU, 1GB RAM)</option>
|
|
<option value="medium">Medium (2 vCPU, 2GB RAM)</option>
|
|
<option value="large">Large (4 vCPU, 4GB RAM)</option>
|
|
</select>
|
|
<div class="form-text">Resource allocation for the virtual machine.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-content" id="output-tab">
|
|
<div class="terminal">
|
|
<span class="terminal-line">PLAY [Deploy Web Server] ***************************************************</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">TASK [Gathering Facts] *****************************************************</span>
|
|
<span class="terminal-line terminal-success">ok: [webserver]</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">TASK [Update apt cache] ****************************************************</span>
|
|
<span class="terminal-line terminal-success">ok: [webserver]</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">TASK [Install Nginx and required packages] ********************************</span>
|
|
<span class="terminal-line terminal-success">ok: [webserver]</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">TASK [Create web root directory] *******************************************</span>
|
|
<span class="terminal-line terminal-success">ok: [webserver]</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">TASK [Create sample website] ***********************************************</span>
|
|
<span class="terminal-line terminal-success">changed: [webserver]</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">TASK [Configure Nginx virtual host] ****************************************</span>
|
|
<span class="terminal-line terminal-success">changed: [webserver]</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">TASK [Enable Nginx virtual host] *******************************************</span>
|
|
<span class="terminal-line terminal-success">changed: [webserver]</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">TASK [Start Nginx] *********************************************************</span>
|
|
<span class="terminal-line terminal-success">ok: [webserver]</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">RUNNING HANDLER [restart nginx] ********************************************</span>
|
|
<span class="terminal-line terminal-success">changed: [webserver]</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">PLAY RECAP *****************************************************************</span>
|
|
<span class="terminal-line terminal-success">webserver : ok=9 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0</span>
|
|
<span class="terminal-line"></span>
|
|
<span class="terminal-line">VERIFICATION **************************************************************</span>
|
|
<span class="terminal-line">Testing website availability...</span>
|
|
<span class="terminal-line terminal-success">Website is accessible at: http://192.168.122.10</span>
|
|
<span class="terminal-line terminal-success">Website deployed successfully!</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-content" id="status-tab">
|
|
<div class="vm-status active">
|
|
<div class="vm-card">
|
|
<div class="vm-icon">
|
|
<i class="fas fa-server"></i>
|
|
</div>
|
|
<div class="vm-info">
|
|
<div class="vm-name">webserver (Ubuntu 22.04 LTS)</div>
|
|
<div class="vm-details">1 vCPU, 1GB RAM, 20GB Storage</div>
|
|
<div class="vm-progress">
|
|
<div class="vm-progress-bar" style="width: 100%;"></div>
|
|
</div>
|
|
</div>
|
|
<div class="vm-state vm-state-running">Running</div>
|
|
</div>
|
|
|
|
<div class="time-remaining">
|
|
<div>Sandbox environment active for 15 more minutes</div>
|
|
<div class="time-progress">
|
|
<div class="time-progress-bar" style="width: 75%;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add new View tab -->
|
|
<div class="tab-content" id="view-tab">
|
|
<!-- Web Server View Placeholder -->
|
|
<div class="view-placeholder" id="web-server-view">
|
|
<div class="deployed-site">
|
|
<div class="deployed-header">
|
|
<h1>Deployed Web Server</h1>
|
|
<p>Your Nginx web server has been successfully deployed and is now running</p>
|
|
</div>
|
|
<div class="deployed-main">
|
|
<div class="server-metrics">
|
|
<div class="metric-item">
|
|
<div class="metric-label">
|
|
<div>CPU Usage</div>
|
|
<div>15%</div>
|
|
</div>
|
|
<div class="metric-bar">
|
|
<div class="metric-fill" style="width: 15%"></div>
|
|
</div>
|
|
<div class="metric-value">59MB / 1GB</div>
|
|
</div>
|
|
<div class="metric-item">
|
|
<div class="metric-label">
|
|
<div>Memory Usage</div>
|
|
<div>23%</div>
|
|
</div>
|
|
<div class="metric-bar">
|
|
<div class="metric-fill" style="width: 23%"></div>
|
|
</div>
|
|
<div class="metric-value">241MB / 1GB</div>
|
|
</div>
|
|
<div class="metric-item">
|
|
<div class="metric-label">
|
|
<div>Disk Usage</div>
|
|
<div>8%</div>
|
|
</div>
|
|
<div class="metric-bar">
|
|
<div class="metric-fill" style="width: 8%"></div>
|
|
</div>
|
|
<div class="metric-value">1.6GB / 20GB</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="website-preview">
|
|
<div class="website-header">
|
|
<div class="website-controls">
|
|
<div class="website-control close"></div>
|
|
<div class="website-control minimize"></div>
|
|
<div class="website-control expand"></div>
|
|
</div>
|
|
<div class="website-address">
|
|
<i class="fas fa-lock"></i>
|
|
http://192.168.122.10
|
|
</div>
|
|
</div>
|
|
<div class="website-content">
|
|
<i class="fas fa-server nginx-welcome"></i>
|
|
<div class="web-title">Welcome to nginx!</div>
|
|
<div class="web-subtitle">Deployed with Ansible automation</div>
|
|
<p>If you see this page, the nginx web server is successfully installed and working.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="deployed-actions">
|
|
<button class="btn-action">
|
|
<i class="fas fa-sync-alt"></i>
|
|
Refresh Status
|
|
</button>
|
|
<button class="btn-action">
|
|
<i class="fas fa-external-link-alt"></i>
|
|
Open in New Tab
|
|
</button>
|
|
<button class="btn-action">
|
|
<i class="fas fa-terminal"></i>
|
|
SSH to Server
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Docker Compose View Placeholder -->
|
|
<div class="view-placeholder" id="docker-compose-view">
|
|
<div class="deployed-site">
|
|
<div class="deployed-header">
|
|
<h1>Deployed Docker Compose Stack</h1>
|
|
<p>Your multi-container application has been successfully deployed with Docker Compose</p>
|
|
</div>
|
|
<div class="deployed-main">
|
|
<h3>Running Containers (4)</h3>
|
|
<div class="container-list">
|
|
<div class="container-item running">
|
|
<div class="container-icon">
|
|
<i class="fab fa-node-js"></i>
|
|
</div>
|
|
<div class="container-name">app-nodejs</div>
|
|
<div class="container-status">Running</div>
|
|
<div class="container-ports">:3000→3000/tcp</div>
|
|
</div>
|
|
<div class="container-item running">
|
|
<div class="container-icon">
|
|
<i class="fas fa-database"></i>
|
|
</div>
|
|
<div class="container-name">app-db</div>
|
|
<div class="container-status">Running</div>
|
|
<div class="container-ports">:5432→5432/tcp</div>
|
|
</div>
|
|
<div class="container-item running">
|
|
<div class="container-icon">
|
|
<i class="fas fa-server"></i>
|
|
</div>
|
|
<div class="container-name">app-nginx</div>
|
|
<div class="container-status">Running</div>
|
|
<div class="container-ports">:80→80/tcp</div>
|
|
</div>
|
|
<div class="container-item running">
|
|
<div class="container-icon">
|
|
<i class="fas fa-exchange-alt"></i>
|
|
</div>
|
|
<div class="container-name">app-redis</div>
|
|
<div class="container-status">Running</div>
|
|
<div class="container-ports">:6379→6379/tcp</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 style="margin-top: 2rem;">Container Networks</h3>
|
|
<div class="container-list">
|
|
<div class="container-item">
|
|
<div class="container-icon">
|
|
<i class="fas fa-network-wired"></i>
|
|
</div>
|
|
<div class="container-name">app-network</div>
|
|
<div style="color: var(--text-secondary); font-size: 0.85rem;">bridge</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="deployed-actions">
|
|
<button class="btn-action">
|
|
<i class="fas fa-sync-alt"></i>
|
|
Refresh Status
|
|
</button>
|
|
<button class="btn-action">
|
|
<i class="fas fa-external-link-alt"></i>
|
|
Open Web App
|
|
</button>
|
|
<button class="btn-action">
|
|
<i class="fas fa-terminal"></i>
|
|
Container Logs
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- K3s Kubernetes View Placeholder -->
|
|
<div class="view-placeholder" id="k3s-cluster-view">
|
|
<div class="deployed-site">
|
|
<div class="deployed-header">
|
|
<h1>K3s Kubernetes Cluster</h1>
|
|
<p>Your lightweight Kubernetes cluster has been successfully deployed</p>
|
|
</div>
|
|
<div class="deployed-main">
|
|
<div class="cluster-overview">
|
|
<div class="cluster-section">
|
|
<h3>Cluster Nodes</h3>
|
|
<div class="k8s-items">
|
|
<div class="k8s-item">
|
|
<div class="k8s-name">k3s-master</div>
|
|
<div class="k8s-ready">Ready</div>
|
|
<div class="k8s-role">control-plane</div>
|
|
<div class="k8s-version">v1.25.9+k3s1</div>
|
|
</div>
|
|
<div class="k8s-item">
|
|
<div class="k8s-name">k3s-worker-1</div>
|
|
<div class="k8s-ready">Ready</div>
|
|
<div class="k8s-role">worker</div>
|
|
<div class="k8s-version">v1.25.9+k3s1</div>
|
|
</div>
|
|
<div class="k8s-item">
|
|
<div class="k8s-name">k3s-worker-2</div>
|
|
<div class="k8s-ready">Ready</div>
|
|
<div class="k8s-role">worker</div>
|
|
<div class="k8s-version">v1.25.9+k3s1</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="cluster-section">
|
|
<h3>Namespaces</h3>
|
|
<div class="k8s-items">
|
|
<div class="k8s-item">
|
|
<div class="k8s-name">default</div>
|
|
<div class="k8s-type">Active</div>
|
|
<div class="k8s-age">5m</div>
|
|
</div>
|
|
<div class="k8s-item">
|
|
<div class="k8s-name">kube-system</div>
|
|
<div class="k8s-type">Active</div>
|
|
<div class="k8s-age">5m</div>
|
|
</div>
|
|
<div class="k8s-item">
|
|
<div class="k8s-name">kube-public</div>
|
|
<div class="k8s-type">Active</div>
|
|
<div class="k8s-age">5m</div>
|
|
</div>
|
|
<div class="k8s-item">
|
|
<div class="k8s-name">kube-node-lease</div>
|
|
<div class="k8s-type">Active</div>
|
|
<div class="k8s-age">5m</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="cluster-section">
|
|
<h3>Workloads</h3>
|
|
<div class="k8s-items">
|
|
<div class="k8s-item">
|
|
<div class="k8s-name">traefik-78bcf47b8b-z4nx6</div>
|
|
<div class="k8s-ready">1/1</div>
|
|
<div class="k8s-type">Pod</div>
|
|
<div class="k8s-age">4m</div>
|
|
</div>
|
|
<div class="k8s-item">
|
|
<div class="k8s-name">metrics-server-7d7f69dc4f-9rkcj</div>
|
|
<div class="k8s-ready">1/1</div>
|
|
<div class="k8s-type">Pod</div>
|
|
<div class="k8s-age">4m</div>
|
|
</div>
|
|
<div class="k8s-item">
|
|
<div class="k8s-name">local-path-provisioner</div>
|
|
<div class="k8s-ready">1/1</div>
|
|
<div class="k8s-type">Pod</div>
|
|
<div class="k8s-age">4m</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="deployed-actions">
|
|
<button class="btn-action">
|
|
<i class="fas fa-sync-alt"></i>
|
|
Refresh Status
|
|
</button>
|
|
<button class="btn-action">
|
|
<i class="fas fa-external-link-alt"></i>
|
|
Open Dashboard
|
|
</button>
|
|
<button class="btn-action">
|
|
<i class="fas fa-terminal"></i>
|
|
Kubectl Terminal
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- LAMP Stack View Placeholder -->
|
|
<div class="view-placeholder" id="lamp-stack-view">
|
|
<div class="deployed-site">
|
|
<div class="deployed-header">
|
|
<h1>Deployed LAMP Stack</h1>
|
|
<p>Your Linux, Apache, MySQL, and PHP stack has been successfully deployed</p>
|
|
</div>
|
|
<div class="deployed-main">
|
|
<h3>LAMP Stack Components</h3>
|
|
<div class="lamp-status">
|
|
<div class="lamp-component">
|
|
<div class="lamp-icon running">
|
|
<i class="fas fa-server"></i>
|
|
</div>
|
|
<div class="lamp-details">
|
|
<div class="lamp-name">Apache Web Server</div>
|
|
<div class="lamp-info">
|
|
Version: 2.4.52 • Status: Running • Port: 80
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="lamp-component">
|
|
<div class="lamp-icon running">
|
|
<i class="fas fa-database"></i>
|
|
</div>
|
|
<div class="lamp-details">
|
|
<div class="lamp-name">MySQL Database</div>
|
|
<div class="lamp-info">
|
|
Version: 8.0.28 • Status: Running • Port: 3306
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="lamp-component">
|
|
<div class="lamp-icon running">
|
|
<i class="fab fa-php"></i>
|
|
</div>
|
|
<div class="lamp-details">
|
|
<div class="lamp-name">PHP</div>
|
|
<div class="lamp-info">
|
|
Version: 8.1.2 • Status: Running • Extensions: 20
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h3>PHP Configuration</h3>
|
|
<div class="php-info-preview">
|
|
<div class="php-header">PHP Information</div>
|
|
<div class="php-content">
|
|
<table class="php-table">
|
|
<tr>
|
|
<td>PHP Version</td>
|
|
<td>8.1.2-1ubuntu2.14</td>
|
|
</tr>
|
|
<tr>
|
|
<td>System</td>
|
|
<td>Linux lamp-server 5.15.0-70-generic #77-Ubuntu SMP</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Server API</td>
|
|
<td>Apache 2.0 Handler</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Virtual Directory Support</td>
|
|
<td>enabled</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Configuration File</td>
|
|
<td>/etc/php/8.1/apache2/php.ini</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Max Execution Time</td>
|
|
<td>30 seconds</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Memory Limit</td>
|
|
<td>128M</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="deployed-actions">
|
|
<button class="btn-action">
|
|
<i class="fas fa-sync-alt"></i>
|
|
Refresh Status
|
|
</button>
|
|
<button class="btn-action">
|
|
<i class="fas fa-external-link-alt"></i>
|
|
View Website
|
|
</button>
|
|
<button class="btn-action">
|
|
<i class="fas fa-database"></i>
|
|
Database Admin
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Security Hardening View Placeholder -->
|
|
<div class="view-placeholder" id="security-hardening-view">
|
|
<div class="deployed-site">
|
|
<div class="deployed-header">
|
|
<h1>Security Hardened Server</h1>
|
|
<p>Your server has been successfully hardened with multiple security configurations</p>
|
|
</div>
|
|
<div class="deployed-main">
|
|
<div class="security-checks">
|
|
<div class="security-section">
|
|
<h3>System Security Verification</h3>
|
|
<div class="security-item">
|
|
<div class="security-icon passed">
|
|
<i class="fas fa-check"></i>
|
|
</div>
|
|
<div class="security-details">
|
|
<div class="security-name">Updated Packages</div>
|
|
<div class="security-info">All system packages are updated to latest secure versions</div>
|
|
</div>
|
|
<div class="security-status">Passed</div>
|
|
</div>
|
|
<div class="security-item">
|
|
<div class="security-icon passed">
|
|
<i class="fas fa-check"></i>
|
|
</div>
|
|
<div class="security-details">
|
|
<div class="security-name">SSH Hardening</div>
|
|
<div class="security-info">Password authentication disabled, key-based auth only</div>
|
|
</div>
|
|
<div class="security-status">Passed</div>
|
|
</div>
|
|
<div class="security-item">
|
|
<div class="security-icon passed">
|
|
<i class="fas fa-check"></i>
|
|
</div>
|
|
<div class="security-details">
|
|
<div class="security-name">Firewall Configuration</div>
|
|
<div class="security-info">UFW enabled with proper rule configuration</div>
|
|
</div>
|
|
<div class="security-status">Passed</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="security-section">
|
|
<h3>System Audit Results</h3>
|
|
<div class="security-item">
|
|
<div class="security-icon passed">
|
|
<i class="fas fa-check"></i>
|
|
</div>
|
|
<div class="security-details">
|
|
<div class="security-name">File Permissions</div>
|
|
<div class="security-info">Sensitive file permissions verified and secured</div>
|
|
</div>
|
|
<div class="security-status">Passed</div>
|
|
</div>
|
|
<div class="security-item">
|
|
<div class="security-icon warning">
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
</div>
|
|
<div class="security-details">
|
|
<div class="security-name">Password Policy</div>
|
|
<div class="security-info">Basic password requirements configured, could be strengthened</div>
|
|
</div>
|
|
<div class="security-status" style="background-color: rgba(245, 158, 11, 0.1); color: var(--warning);">Warning</div>
|
|
</div>
|
|
<div class="security-item">
|
|
<div class="security-icon passed">
|
|
<i class="fas fa-check"></i>
|
|
</div>
|
|
<div class="security-details">
|
|
<div class="security-name">Running Services</div>
|
|
<div class="security-info">Only essential services are running, all others disabled</div>
|
|
</div>
|
|
<div class="security-status">Passed</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="security-section">
|
|
<h3>Security Monitoring</h3>
|
|
<div class="security-item">
|
|
<div class="security-icon passed">
|
|
<i class="fas fa-check"></i>
|
|
</div>
|
|
<div class="security-details">
|
|
<div class="security-name">Log Monitoring</div>
|
|
<div class="security-info">Log analysis and alerting system configured</div>
|
|
</div>
|
|
<div class="security-status">Passed</div>
|
|
</div>
|
|
<div class="security-item">
|
|
<div class="security-icon passed">
|
|
<i class="fas fa-check"></i>
|
|
</div>
|
|
<div class="security-details">
|
|
<div class="security-name">Intrusion Detection</div>
|
|
<div class="security-info">Fail2ban configured with proper jail rules</div>
|
|
</div>
|
|
<div class="security-status">Passed</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="deployed-actions">
|
|
<button class="btn-action">
|
|
<i class="fas fa-sync-alt"></i>
|
|
Refresh Status
|
|
</button>
|
|
<button class="btn-action">
|
|
<i class="fas fa-shield-alt"></i>
|
|
Run Security Scan
|
|
</button>
|
|
<button class="btn-action">
|
|
<i class="fas fa-file-alt"></i>
|
|
View Security Report
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="preview-actions">
|
|
<div class="preview-status">
|
|
<div class="status-dot status-ready"></div>
|
|
<span>Ready to deploy</span>
|
|
</div>
|
|
<div class="preview-buttons">
|
|
<button class="sandbox-btn" id="reset-btn">
|
|
<i class="fas fa-undo"></i>
|
|
<span>Reset</span>
|
|
</button>
|
|
<button class="sandbox-btn btn-primary" id="deploy-btn">
|
|
<i class="fas fa-play"></i>
|
|
<span>Deploy</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sandbox-footer">
|
|
<a href="index.html" class="back-to-site">
|
|
<i class="fas fa-arrow-left"></i>
|
|
<span>Back to Main Site</span>
|
|
</a>
|
|
<div class="footer-info">Sandbox environments automatically shut down after 30 minutes</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Footer -->
|
|
<footer class="footer">
|
|
<div class="container">
|
|
<div class="footer-content">
|
|
<div class="footer-info">
|
|
<div class="footer-logo">
|
|
<span class="logo-text-glow">ArgoBox</span>
|
|
<span class="logo-dot-glow">.com</span>
|
|
</div>
|
|
<p class="footer-description">
|
|
Enterprise-grade home lab environment for DevOps experimentation, infrastructure automation, and containerized application deployment.
|
|
</p>
|
|
<div class="footer-evolution">
|
|
<i class="fas fa-code-branch evolution-icon"></i>
|
|
<span>Continuously evolving since 2011</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="footer-links">
|
|
<div class="footer-links-column">
|
|
<h3 class="footer-heading">Platforms</h3>
|
|
<a href="https://dashboard.argobox.com" class="footer-link">Dashboard</a>
|
|
<a href="ansible-sandbox.html" class="footer-link">Ansible Sandbox</a>
|
|
<a href="https://git.argobox.com" class="footer-link">Gitea</a>
|
|
<a href="https://ai.argobox.com" class="footer-link">OpenWebUI</a>
|
|
</div>
|
|
|
|
<div class="footer-links-column">
|
|
<h3 class="footer-heading">Documentation</h3>
|
|
<a href="construction.html" class="footer-link">Architecture</a>
|
|
<a href="construction.html" class="footer-link">Kubernetes</a>
|
|
<a href="construction.html" class="footer-link">Ansible</a>
|
|
<a href="construction.html" class="footer-link">Network</a>
|
|
</div>
|
|
|
|
<div class="footer-links-column">
|
|
<h3 class="footer-heading">Resources</h3>
|
|
<a href="construction.html" class="footer-link">Ansible Playbooks</a>
|
|
<a href="construction.html" class="footer-link">K8s Manifests</a>
|
|
<a href="construction.html" class="footer-link">Shell Scripts</a>
|
|
<a href="construction.html" class="footer-link">Configuration Files</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="footer-bottom">
|
|
<p>© <span id="current-year">2025</span> All rights reserved. Inovin LLC</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<!-- JavaScript -->
|
|
<script src="script.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Tab switching
|
|
const tabs = document.querySelectorAll('.preview-tab');
|
|
const tabContents = document.querySelectorAll('.tab-content');
|
|
|
|
tabs.forEach(tab => {
|
|
tab.addEventListener('click', function() {
|
|
const tabId = this.getAttribute('data-tab');
|
|
|
|
tabs.forEach(t => t.classList.remove('active'));
|
|
tabContents.forEach(tc => tc.classList.remove('active'));
|
|
|
|
this.classList.add('active');
|
|
document.getElementById(`${tabId}-tab`).classList.add('active');
|
|
});
|
|
});
|
|
|
|
// Playbook selection
|
|
const playbooks = document.querySelectorAll('.playbook-card');
|
|
const previewTitle = document.querySelector('.preview-title span');
|
|
const codeEditor = document.querySelector('.code-editor');
|
|
|
|
// Define a content mapper for different playbooks
|
|
const playbookContents = {
|
|
'web-server': codeEditor.innerHTML, // Save the current web server content as default
|
|
'docker-compose': `
|
|
<div class="code-line"><span class="line-number">1</span><span class="line-content code-comment">---</span></div>
|
|
<div class="code-line"><span class="line-number">2</span><span class="line-content code-comment"># Docker Compose Stack Playbook</span></div>
|
|
<div class="code-line"><span class="line-number">3</span><span class="line-content">- <span class="code-key">name</span>: <span class="code-string">Deploy Docker Compose Stack</span></span></div>
|
|
<div class="code-line"><span class="line-number">4</span><span class="line-content"> <span class="code-key">hosts</span>: <span class="code-value">all</span></span></div>
|
|
<div class="code-line"><span class="line-number">5</span><span class="line-content"> <span class="code-key">become</span>: <span class="code-value">yes</span></span></div>
|
|
<div class="code-line"><span class="line-number">6</span><span class="line-content"> <span class="code-key">vars</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">7</span><span class="line-content"> <span class="code-key">app_name</span>: <span class="code-string">webapp</span></span></div>
|
|
<div class="code-line"><span class="line-number">8</span><span class="line-content"> <span class="code-key">app_domain</span>: <span class="code-string">webapp.local</span></span></div>
|
|
<div class="code-line"><span class="line-number">9</span><span class="line-content"> <span class="code-key">docker_compose_version</span>: <span class="code-string">2.20.2</span></span></div>
|
|
<div class="code-line"><span class="line-number">10</span><span class="line-content"> <span class="code-key">project_dir</span>: <span class="code-string">/opt/{{ app_name }}</span></span></div>
|
|
<div class="code-line"><span class="line-number">11</span><span class="line-content"></span></div>
|
|
<div class="code-line"><span class="line-number">12</span><span class="line-content"> <span class="code-key">tasks</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">13</span><span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Install Docker and dependencies</span></span></div>
|
|
<div class="code-line"><span class="line-number">14</span><span class="line-content"> <span class="code-key">apt</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">15</span><span class="line-content"> <span class="code-key">name</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">16</span><span class="line-content"> - <span class="code-string">docker-ce</span></span></div>
|
|
<div class="code-line"><span class="line-number">17</span><span class="line-content"> - <span class="code-string">docker-ce-cli</span></span></div>
|
|
<div class="code-line"><span class="line-number">18</span><span class="line-content"> <span class="code-key">state</span>: <span class="code-string">present</span></span></div>
|
|
<div class="code-line"><span class="line-number">19</span><span class="line-content"></span></div>
|
|
<div class="code-line"><span class="line-number">20</span><span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Deploy MERN stack application</span></span></div>
|
|
<div class="code-line"><span class="line-number">21</span><span class="line-content"> <span class="code-key">community.docker.docker_compose</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">22</span><span class="line-content"> <span class="code-key">project_src</span>: <span class="code-string">{{ project_dir }}</span></span></div>
|
|
<div class="code-line"><span class="line-number">23</span><span class="line-content"> <span class="code-key">state</span>: <span class="code-string">present</span></span></div>
|
|
`,
|
|
'k3s-cluster': `
|
|
<div class="code-line"><span class="line-number">1</span><span class="line-content code-comment">---</span></div>
|
|
<div class="code-line"><span class="line-number">2</span><span class="line-content code-comment"># K3s Kubernetes Cluster Playbook</span></div>
|
|
<div class="code-line"><span class="line-number">3</span><span class="line-content">- <span class="code-key">name</span>: <span class="code-string">Deploy K3s Cluster</span></span></div>
|
|
<div class="code-line"><span class="line-number">4</span><span class="line-content"> <span class="code-key">hosts</span>: <span class="code-value">all</span></span></div>
|
|
<div class="code-line"><span class="line-number">5</span><span class="line-content"> <span class="code-key">become</span>: <span class="code-value">yes</span></span></div>
|
|
<div class="code-line"><span class="line-number">6</span><span class="line-content"> <span class="code-key">vars</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">7</span><span class="line-content"> <span class="code-key">k3s_version</span>: <span class="code-string">v1.27.3+k3s1</span></span></div>
|
|
<div class="code-line"><span class="line-number">8</span><span class="line-content"> <span class="code-key">k3s_token</span>: <span class="code-string">secure-cluster-token</span></span></div>
|
|
<div class="code-line"><span class="line-number">9</span><span class="line-content"></span></div>
|
|
<div class="code-line"><span class="line-number">10</span><span class="line-content"> <span class="code-key">tasks</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">11</span><span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Install K3s master node</span></span></div>
|
|
<div class="code-line"><span class="line-number">12</span><span class="line-content"> <span class="code-key">shell</span>: curl -sfL https://get.k3s.io | sh -s - --token={{ k3s_token }}</span></div>
|
|
<div class="code-line"><span class="line-number">13</span><span class="line-content"> <span class="code-key">when</span>: inventory_hostname in groups['master']</span></div>
|
|
<div class="code-line"><span class="line-number">14</span><span class="line-content"></span></div>
|
|
<div class="code-line"><span class="line-number">15</span><span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Get master node IP</span></span></div>
|
|
<div class="code-line"><span class="line-number">16</span><span class="line-content"> <span class="code-key">set_fact</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">17</span><span class="line-content"> <span class="code-key">master_ip</span>: "{{ hostvars[groups['master'][0]]['ansible_default_ipv4']['address'] }}"</span></div>
|
|
<div class="code-line"><span class="line-number">18</span><span class="line-content"></span></div>
|
|
<div class="code-line"><span class="line-number">19</span><span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Install K3s worker nodes</span></span></div>
|
|
<div class="code-line"><span class="line-number">20</span><span class="line-content"> <span class="code-key">shell</span>: curl -sfL https://get.k3s.io | K3S_URL=https://{{ master_ip }}:6443 K3S_TOKEN={{ k3s_token }} sh -</span></div>
|
|
<div class="code-line"><span class="line-number">21</span><span class="line-content"> <span class="code-key">when</span>: inventory_hostname in groups['workers']</span></div>
|
|
`,
|
|
'lamp-stack': `
|
|
<div class="code-line"><span class="line-number">1</span><span class="line-content code-comment">---</span></div>
|
|
<div class="code-line"><span class="line-number">2</span><span class="line-content code-comment"># LAMP Stack Installation Playbook</span></div>
|
|
<div class="code-line"><span class="line-number">3</span><span class="line-content">- <span class="code-key">name</span>: <span class="code-string">Install LAMP Stack</span></span></div>
|
|
<div class="code-line"><span class="line-number">4</span><span class="line-content"> <span class="code-key">hosts</span>: <span class="code-value">all</span></span></div>
|
|
<div class="code-line"><span class="line-number">5</span><span class="line-content"> <span class="code-key">become</span>: <span class="code-value">yes</span></span></div>
|
|
<div class="code-line"><span class="line-number">6</span><span class="line-content"> <span class="code-key">vars</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">7</span><span class="line-content"> <span class="code-key">mysql_root_password</span>: <span class="code-string">SecurePassword123</span></span></div>
|
|
<div class="code-line"><span class="line-number">8</span><span class="line-content"> <span class="code-key">app_db_name</span>: <span class="code-string">webapp</span></span></div>
|
|
<div class="code-line"><span class="line-number">9</span><span class="line-content"> <span class="code-key">app_db_user</span>: <span class="code-string">webappuser</span></span></div>
|
|
<div class="code-line"><span class="line-number">10</span><span class="line-content"> <span class="code-key">app_db_password</span>: <span class="code-string">userpass123</span></span></div>
|
|
<div class="code-line"><span class="line-number">11</span><span class="line-content"></span></div>
|
|
<div class="code-line"><span class="line-number">12</span><span class="line-content"> <span class="code-key">tasks</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">13</span><span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Install Apache, MySQL, PHP</span></span></div>
|
|
<div class="code-line"><span class="line-number">14</span><span class="line-content"> <span class="code-key">apt</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">15</span><span class="line-content"> <span class="code-key">name</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">16</span><span class="line-content"> - <span class="code-string">apache2</span></span></div>
|
|
<div class="code-line"><span class="line-number">17</span><span class="line-content"> - <span class="code-string">mysql-server</span></span></div>
|
|
<div class="code-line"><span class="line-number">18</span><span class="line-content"> - <span class="code-string">php</span></span></div>
|
|
<div class="code-line"><span class="line-number">19</span><span class="line-content"> - <span class="code-string">php-mysql</span></span></div>
|
|
<div class="code-line"><span class="line-number">20</span><span class="line-content"> - <span class="code-string">libapache2-mod-php</span></span></div>
|
|
<div class="code-line"><span class="line-number">21</span><span class="line-content"> - <span class="code-string">php-cli</span></span></div>
|
|
<div class="code-line"><span class="line-number">22</span><span class="line-content"> <span class="code-key">state</span>: <span class="code-string">present</span></span></div>
|
|
<div class="code-line"><span class="line-number">23</span><span class="line-content"> <span class="code-key">update_cache</span>: <span class="code-value">yes</span></span></div>
|
|
`,
|
|
'security-hardening': `
|
|
<div class="code-line"><span class="line-number">1</span><span class="line-content code-comment">---</span></div>
|
|
<div class="code-line"><span class="line-number">2</span><span class="line-content code-comment"># Security Hardening Playbook</span></div>
|
|
<div class="code-line"><span class="line-number">3</span><span class="line-content">- <span class="code-key">name</span>: <span class="code-string">Harden Linux Server</span></span></div>
|
|
<div class="code-line"><span class="line-number">4</span><span class="line-content"> <span class="code-key">hosts</span>: <span class="code-value">all</span></span></div>
|
|
<div class="code-line"><span class="line-number">5</span><span class="line-content"> <span class="code-key">become</span>: <span class="code-value">yes</span></span></div>
|
|
<div class="code-line"><span class="line-number">6</span><span class="line-content"> <span class="code-key">vars</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">7</span><span class="line-content"> <span class="code-key">ssh_port</span>: <span class="code-value">2222</span></span></div>
|
|
<div class="code-line"><span class="line-number">8</span><span class="line-content"> <span class="code-key">admin_user</span>: <span class="code-string">secadmin</span></span></div>
|
|
<div class="code-line"><span class="line-number">9</span><span class="line-content"> <span class="code-key">admin_ssh_key</span>: <span class="code-string">ssh-rsa AAAAB3NzaC1yc2EAAAADAQ...</span></span></div>
|
|
<div class="code-line"><span class="line-number">10</span><span class="line-content"></span></div>
|
|
<div class="code-line"><span class="line-number">11</span><span class="line-content"> <span class="code-key">tasks</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">12</span><span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Update all packages</span></span></div>
|
|
<div class="code-line"><span class="line-number">13</span><span class="line-content"> <span class="code-key">apt</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">14</span><span class="line-content"> <span class="code-key">upgrade</span>: <span class="code-string">dist</span></span></div>
|
|
<div class="code-line"><span class="line-number">15</span><span class="line-content"> <span class="code-key">update_cache</span>: <span class="code-value">yes</span></span></div>
|
|
<div class="code-line"><span class="line-number">16</span><span class="line-content"></span></div>
|
|
<div class="code-line"><span class="line-number">17</span><span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Install security packages</span></span></div>
|
|
<div class="code-line"><span class="line-number">18</span><span class="line-content"> <span class="code-key">apt</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">19</span><span class="line-content"> <span class="code-key">name</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">20</span><span class="line-content"> - <span class="code-string">ufw</span></span></div>
|
|
<div class="code-line"><span class="line-number">21</span><span class="line-content"> - <span class="code-string">fail2ban</span></span></div>
|
|
<div class="code-line"><span class="line-number">22</span><span class="line-content"> - <span class="code-string">unattended-upgrades</span></span></div>
|
|
<div class="code-line"><span class="line-number">23</span><span class="line-content"> <span class="code-key">state</span>: <span class="code-string">present</span></span></div>
|
|
<div class="code-line"><span class="line-number">24</span><span class="line-content"></span></div>
|
|
<div class="code-line"><span class="line-number">25</span><span class="line-content"> - <span class="code-key">name</span>: <span class="code-string">Secure SSH configuration</span></span></div>
|
|
<div class="code-line"><span class="line-number">26</span><span class="line-content"> <span class="code-key">lineinfile</span>:</span></div>
|
|
<div class="code-line"><span class="line-number">27</span><span class="line-content"> <span class="code-key">dest</span>: <span class="code-string">/etc/ssh/sshd_config</span></span></div>
|
|
<div class="code-line"><span class="line-number">28</span><span class="line-content"> <span class="code-key">regexp</span>: <span class="code-string">{{ item.regexp }}</span></span></div>
|
|
<div class="code-line"><span class="line-number">29</span><span class="line-content"> <span class="code-key">line</span>: <span class="code-string">{{ item.line }}</span></span></div>
|
|
<div class="code-line"><span class="line-number">30</span><span class="line-content"> <span class="code-key">state</span>: <span class="code-string">present</span></span></div>
|
|
`
|
|
};
|
|
|
|
playbooks.forEach(playbook => {
|
|
playbook.addEventListener('click', function() {
|
|
// Get current playbook type
|
|
const playbookType = this.getAttribute('data-playbook');
|
|
|
|
// Reset all playbooks to inactive
|
|
playbooks.forEach(p => p.classList.remove('active'));
|
|
|
|
// Set this playbook to active
|
|
this.classList.add('active');
|
|
|
|
// Update title
|
|
const playbookName = this.querySelector('.playbook-title').textContent;
|
|
previewTitle.textContent = playbookName;
|
|
|
|
// Update code editor content if we have content for this playbook
|
|
if (playbookContents[playbookType]) {
|
|
codeEditor.innerHTML = playbookContents[playbookType];
|
|
}
|
|
|
|
// Reset the status to "Ready to deploy"
|
|
const statusIndicator = document.querySelector('.preview-status');
|
|
if (statusIndicator) {
|
|
statusIndicator.innerHTML = '<div class="status-dot status-ready"></div><span>Ready to deploy</span>';
|
|
}
|
|
|
|
// Update View tab to show the correct view placeholder
|
|
const viewPlaceholders = document.querySelectorAll('.view-placeholder');
|
|
viewPlaceholders.forEach(vp => vp.classList.remove('active'));
|
|
const currentViewPlaceholder = document.getElementById(`${playbookType}-view`);
|
|
if (currentViewPlaceholder) {
|
|
currentViewPlaceholder.classList.add('active');
|
|
}
|
|
|
|
// Switch to code tab
|
|
tabs.forEach(t => t.classList.remove('active'));
|
|
tabContents.forEach(tc => tc.classList.remove('active'));
|
|
|
|
const codeTabButton = document.querySelector('[data-tab="code"]');
|
|
const codeTabContent = document.getElementById('code-tab');
|
|
|
|
if (codeTabButton && codeTabContent) {
|
|
codeTabButton.classList.add('active');
|
|
codeTabContent.classList.add('active');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Deploy button functionality
|
|
const deployBtn = document.getElementById('deploy-btn');
|
|
if (deployBtn) {
|
|
deployBtn.addEventListener('click', function() {
|
|
// Update status indicator to "Running"
|
|
const statusIndicator = document.querySelector('.preview-status');
|
|
if (statusIndicator) {
|
|
statusIndicator.innerHTML = '<div class="status-dot status-running"></div><span>Deploying...</span>';
|
|
}
|
|
|
|
// Simulate deployment process
|
|
setTimeout(function() {
|
|
// After "deployment", update status to success
|
|
if (statusIndicator) {
|
|
statusIndicator.innerHTML = '<div class="status-dot status-success"></div><span>Deployed successfully</span>';
|
|
}
|
|
|
|
// Auto-switch to the "View" tab to show the result
|
|
const viewTab = document.querySelector('[data-tab="view"]');
|
|
if (viewTab) {
|
|
// Trigger the tab click event
|
|
viewTab.click();
|
|
}
|
|
}, 3000); // 3 second simulated deployment
|
|
});
|
|
}
|
|
|
|
// Reset button functionality
|
|
const resetBtn = document.getElementById('reset-btn');
|
|
if (resetBtn) {
|
|
resetBtn.addEventListener('click', function() {
|
|
// Reset status to "Ready to deploy"
|
|
const statusIndicator = document.querySelector('.preview-status');
|
|
if (statusIndicator) {
|
|
statusIndicator.innerHTML = '<div class="status-dot status-ready"></div><span>Ready to deploy</span>';
|
|
}
|
|
|
|
// Switch back to code tab
|
|
const codeTab = document.querySelector('[data-tab="code"]');
|
|
if (codeTab) {
|
|
codeTab.click();
|
|
}
|
|
});
|
|
}
|
|
|
|
// Set the current year in footer
|
|
const currentYearElem = document.getElementById('current-year');
|
|
if (currentYearElem) {
|
|
currentYearElem.textContent = new Date().getFullYear();
|
|
}
|
|
});
|
|
</script>
|
|
<!-- Custom JavaScript -->
|
|
<script>
|
|
// Initialize simulation mode toggle
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const toggleInput = document.querySelector('.toggle-switch input');
|
|
const toggleStatus = document.querySelector('.toggle-status');
|
|
|
|
toggleInput.addEventListener('change', function() {
|
|
if(this.checked) {
|
|
toggleStatus.textContent = 'Active';
|
|
document.body.classList.add('simulation-mode');
|
|
} else {
|
|
toggleStatus.textContent = 'Inactive';
|
|
document.body.classList.remove('simulation-mode');
|
|
}
|
|
});
|
|
|
|
// Trigger the initial state
|
|
toggleInput.dispatchEvent(new Event('change'));
|
|
});
|
|
|
|
// Existing JavaScript
|
|
// ... existing code ...
|
|
</script>
|
|
</body>
|
|
</html> |