File size: 7,841 Bytes
92c4ae6 | 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 | """
Atom CLI - Enable command for upgrading Personal to Enterprise.
Enables Enterprise Edition features:
- Sets ATOM_EDITION=enterprise
- Installs enterprise dependencies
- Updates configuration
- Migrates database if needed
"""
import os
import sys
import click
import logging
import subprocess
from pathlib import Path
# Add backend to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))
logger = logging.getLogger(__name__)
@click.group()
def enable():
"""Enable Enterprise Edition features."""
pass
@enable.command()
@click.option('--workspace-id', help='Workspace ID for enterprise setup')
@click.option('--database-url', help='PostgreSQL database URL')
@click.option('--skip-deps', is_flag=True, help='Skip installing dependencies')
@click.option('--yes', '-y', is_flag=True, help='Skip confirmation')
def enterprise(workspace_id: str, database_url: str, skip_deps: bool, yes: bool):
"""
Enable Enterprise Edition features.
Upgrades Personal Edition to Enterprise:
- Sets ATOM_EDITION=enterprise
- Installs enterprise dependencies
- Prompts for PostgreSQL configuration
- Updates .env with enterprise settings
**Examples:**
atom enable enterprise # Interactive
atom enable enterprise --yes # Skip confirmation
atom enable enterprise --workspace-id acme-corp # With workspace
atom enable enterprise --database-url "postgresql://..." # Custom DB
**Post-Installation:**
- Set up PostgreSQL database
- Configure SSO providers (optional)
- Enable monitoring (optional)
"""
click.echo(click.style("Enterprise Edition Enable", bold=True))
click.echo("=" * 50)
# Check current edition
from core.package_feature_service import get_package_feature_service
service = get_package_feature_service()
if service.is_enterprise:
click.echo(click.style("Enterprise Edition already enabled!", fg="green"))
click.echo(f"Current edition: {service.edition.value}")
return
# Show what will change
click.echo("")
click.echo("This will enable Enterprise Edition features:")
click.echo(" Multi-user support")
click.echo(" Workspace isolation")
click.echo(" SSO (Okta, Auth0, SAML)")
click.echo(" Monitoring (Prometheus, Grafana)")
click.echo(" Advanced analytics")
click.echo(" Audit trail")
click.echo(" Rate limiting")
click.echo("")
# Confirm if not --yes
if not yes:
if not click.confirm("Enable Enterprise Edition?"):
click.echo("Cancelled.")
raise SystemExit(0)
# Install enterprise dependencies
if not skip_deps:
click.echo("")
click.echo("Installing Enterprise dependencies...")
try:
subprocess.run(
[sys.executable, "-m", "pip", "install", "-e", ".[enterprise]"],
check=True,
cwd=Path(__file__).parent.parent
)
click.echo(click.style(" Dependencies installed", fg="green"))
except subprocess.CalledProcessError as e:
click.echo(click.style(f" Failed to install: {e}", fg="red"), err=True)
click.echo("Run manually: pip install atom-os[enterprise]")
raise SystemExit(1)
# Update .env file
env_file = Path(".env")
if env_file.exists():
_update_env_for_enterprise(env_file, database_url, workspace_id)
else:
click.echo(click.style(".env file not found - run 'atom init' first", fg="yellow"))
raise SystemExit(1)
# Success
click.echo("")
click.echo(click.style("Enterprise Edition enabled!", fg="green", bold=True))
# Show next steps
click.echo("")
click.echo("Next steps:")
if not database_url:
click.echo(" 1. Set up PostgreSQL database:")
click.echo(" createdb atom")
click.echo(" # Or update DATABASE_URL in .env")
click.echo(" 2. Restart Atom:")
click.echo(" atom stop # If running")
click.echo(" atom start")
click.echo(" 3. Configure optional features:")
click.echo(" - SSO: Update OKTA_* or AUTH0_* variables")
click.echo(" - Monitoring: Access http://localhost:9090")
click.echo(" - Redis: Set REDIS_URL for multi-user")
def _update_env_for_enterprise(env_file: Path, database_url: str, workspace_id: str) -> None:
"""Update .env file for Enterprise Edition."""
content = env_file.read_text()
# Update edition
if "ATOM_EDITION=" in content:
content = content.replace(
"ATOM_EDITION=personal",
"ATOM_EDITION=enterprise"
)
else:
content = f"\nATOM_EDITION=enterprise\n{content}"
# Update database URL if provided
if database_url:
if "DATABASE_URL=" in content:
lines = content.split("\n")
for i, line in enumerate(lines):
if line.startswith("DATABASE_URL="):
lines[i] = f"DATABASE_URL={database_url}"
break
content = "\n".join(lines)
else:
content = f"\nDATABASE_URL={database_url}\n{content}"
# Enable multi-user
if "ATOM_MULTI_USER_ENABLED=" in content:
content = content.replace(
"ATOM_MULTI_USER_ENABLED=false",
"ATOM_MULTI_USER_ENABLED=true"
)
else:
content = "\nATOM_MULTI_USER_ENABLED=true\n" + content
# Enable monitoring
if "ATOM_MONITORING_ENABLED=" in content:
content = content.replace(
"ATOM_MONITORING_ENABLED=false",
"ATOM_MONITORING_ENABLED=true"
)
else:
content = "\nATOM_MONITORING_ENABLED=true\n" + content
# Add workspace ID if provided
if workspace_id:
if "WORKSPACE_ID=" in content:
lines = content.split("\n")
for i, line in enumerate(lines):
if line.startswith("WORKSPACE_ID="):
lines[i] = f"WORKSPACE_ID={workspace_id}"
break
content = "\n".join(lines)
else:
content = f"\nWORKSPACE_ID={workspace_id}\n{content}"
# Write updated content
env_file.write_text(content)
click.echo(" Updated .env file")
@enable.command()
def features():
"""List available features and their edition requirements."""
from core.package_feature_service import get_package_feature_service
service = get_package_feature_service()
click.echo(click.style("Atom Edition Features", bold=True))
click.echo("=" * 50)
click.echo(f"Current Edition: {service.edition.value.upper()}")
click.echo("")
# List features by edition
click.echo(click.style("Personal Edition Features:", fg="blue"))
for feature in service.get_personal_features():
info = service.get_feature_info(feature)
available = service.is_feature_enabled(feature)
status = click.style("✓", fg="green") if available else click.style("✗", fg="red")
click.echo(f" {status} {info.name}: {info.description}")
click.echo("")
click.echo(click.style("Enterprise Edition Features:", fg="yellow"))
for feature in service.get_enterprise_features():
info = service.get_feature_info(feature)
available = service.is_feature_enabled(feature)
status = click.style("✓", fg="green") if available else click.style("✗", fg="red")
click.echo(f" {status} {info.name}: {info.description}")
if not service.is_enterprise:
click.echo("")
click.echo("Enable Enterprise features:")
click.echo(" atom enable enterprise")
def register_enable_command(cli_group):
"""Register enable command with CLI group."""
cli_group.add_command(enable)
|