""" Extra databases (Memcached, SQLite, Elasticsearch, ClickHouse). """ from . import register, Generator, Field from . import bash_header, quote, bool_str, yes # ========================== Memcached ========================== class Memcached(Generator): id = "memcached" title = "Memcached" category = "databases" icon = "🧠" tags = ["memcached", "cache"] description = "安装 memcached 并配置监听地址/内存限制/连接数。" fields = [ Field("port", "端口", "number", default="11211", min_=1, max_=65535), Field("memory_mb", "最大内存 (MB)", "number", default="256"), Field("max_connections", "最大连接数", "number", default="1024"), Field("listen", "监听地址", "text", default="0.0.0.0"), ] def render(self, p): port = str(p.get("port", "11211")) mem = str(p.get("memory_mb", "256")) conn = str(p.get("max_connections", "1024")) listen = p.get("listen", "0.0.0.0") out = [bash_header(self.title)] out.append('log "Installing memcached..."') out.append('PKG_INSTALL memcached') out.append('cp /etc/memcached.conf /etc/memcached.conf.bak.$(date +%s) || true') out.append('sed -i "s/^-m .*/-m ' + mem + '/" /etc/memcached.conf') out.append('sed -i "s/^-p .*/-p ' + port + '/" /etc/memcached.conf') out.append('sed -i "s/^-l .*/-l ' + listen + '/" /etc/memcached.conf') out.append('sed -i "s/^-c .*/-c ' + conn + '/" /etc/memcached.conf') out.append('systemctl enable --now memcached') out.append('echo "stats" | nc -q1 127.0.0.1 ' + port + ' | head -5') return "\n".join(out) + "\n" # ========================== SQLite3 (system tools, no server) ========================== class SqliteTools(Generator): id = "sqlite" title = "SQLite 命令行工具" category = "databases" icon = "📁" tags = ["sqlite"] description = "安装最新版 sqlite3 + sqlite-utils。" fields = [ Field("install_python_bindings", "安装 Python sqlite-utils", "checkbox", default="yes"), ] def render(self, p): pyb = bool_str(p.get("install_python_bindings", True)) out = [bash_header(self.title)] out.append('log "Installing sqlite3..."') out.append('PKG_INSTALL sqlite3 libsqlite3-dev || PKG_INSTALL sqlite sqlite-devel') if pyb: out.append('command -v pip3 >/dev/null || PKG_INSTALL python3-pip') out.append('pip3 install --break-system-packages sqlite-utils || pip3 install sqlite-utils') out.append('sqlite3 --version') return "\n".join(out) + "\n" # ========================== Elasticsearch ========================== class Elasticsearch(Generator): id = "elasticsearch" title = "Elasticsearch" category = "databases" icon = "🔍" tags = ["elasticsearch", "es", "search"] description = "安装 Elasticsearch (单节点开发模式)。" warnings = [ "ES JVM 默认 1G,小内存机器请调小 -Xms -Xmx。", "生产环境必须设置 xpack.security.enabled=true。", ] fields = [ Field("version", "版本", "select", default="8.13.4", options=["7.17.20", "8.11.4", "8.13.4", "8.14.3"]), Field("port", "HTTP 端口", "number", default="9200", min_=1, max_=65535), Field("jvm_heap", "JVM 堆", "text", default="1g"), Field("discovery", "discovery.type", "select", default="single-node", options=["single-node"]), Field("enable_security", "启用 xpack security", "checkbox", default="no"), ] def render(self, p): ver = p.get("version", "8.13.4") port = str(p.get("port", "9200")) heap = p.get("jvm_heap", "1g") sec = bool_str(p.get("enable_security")) out = [bash_header(self.title)] out.append('log "Installing Elasticsearch ' + ver + '..."') out.append('useradd -r -s /bin/false elasticsearch 2>/dev/null || true') out.append('cd /tmp') out.append('curl -fsSL -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-' + ver + '-linux-x86_64.tar.gz') out.append('rm -rf /opt/elasticsearch') out.append('tar -xzf elasticsearch-' + ver + '-linux-x86_64.tar.gz -C /opt/') out.append('mv /opt/elasticsearch-' + ver + ' /opt/elasticsearch') out.append('rm -f elasticsearch-' + ver + '-linux-x86_64.tar.gz') out.append('chown -R elasticsearch:elasticsearch /opt/elasticsearch') out.append('sed -i "s/^-Xms.*/-Xms' + heap + '/" /opt/elasticsearch/config/jvm.options') out.append('sed -i "s/^-Xmx.*/-Xmx' + heap + '/" /opt/elasticsearch/config/jvm.options') out.append('sed -i "s/^#http.port.*/http.port: ' + port + '/" /opt/elasticsearch/config/elasticsearch.yml') out.append('echo "discovery.type: single-node" >> /opt/elasticsearch/config/elasticsearch.yml') out.append('echo "network.host: 0.0.0.0" >> /opt/elasticsearch/config/elasticsearch.yml') out.append('echo "xpack.security.enabled: ' + ('true' if sec else 'false') + '" >> /opt/elasticsearch/config/elasticsearch.yml') out.append('cat > /etc/systemd/system/elasticsearch.service < /etc/apt/sources.list.d/clickhouse.list') out.append('apt-get update') out.append('DEBIAN_FRONTEND=noninteractive apt-get install -y clickhouse-server clickhouse-client') out.append('mkdir -p ' + dp) out.append('chown -R clickhouse:clickhouse ' + dp) out.append('sed -i "s|.*|' + tcp + '|" /etc/clickhouse-server/config.xml') out.append('sed -i "s|.*|' + http + '|" /etc/clickhouse-server/config.xml') out.append('sed -i "s|.*|' + lh + '|" /etc/clickhouse-server/config.xml') out.append('sed -i "s|.*|' + dp + '|" /etc/clickhouse-server/config.xml') out.append('systemctl enable --now clickhouse-server') out.append('sleep 3') out.append('clickhouse-client -q "SELECT version()"') return "\n".join(out) + "\n" # ========================== Consul (service mesh) ========================== class Consul(Generator): id = "consul" title = "HashiCorp Consul" category = "middleware" icon = "🌐" tags = ["consul", "service-discovery"] description = "安装 Consul 单节点开发模式。" fields = [ Field("version", "Consul 版本", "text", default="1.18.1"), Field("datacenter", "Datacenter", "text", default="dc1"), Field("ui", "启用 Web UI", "checkbox", default="yes"), ] def render(self, p): ver = p.get("version", "1.18.1") dc = p.get("datacenter", "dc1") ui = bool_str(p.get("ui", True)) out = [bash_header(self.title)] out.append('useradd -r -s /bin/false consul 2>/dev/null || true') out.append('mkdir -p /etc/consul.d /var/lib/consul') out.append('cd /tmp') out.append('curl -fsSL -O https://releases.hashicorp.com/consul/' + ver + '/consul_' + ver + '_linux_amd64.zip') out.append('unzip -o consul_' + ver + '_linux_amd64.zip -d /usr/local/bin/') out.append('rm -f consul_' + ver + '_linux_amd64.zip') out.append('chown -R consul:consul /etc/consul.d /var/lib/consul') out.append('cat > /etc/consul.d/consul.hcl < /etc/systemd/system/consul.service <