mirror of
https://github.com/dredx/prole.git
synced 2026-09-24 16:04:31 +00:00
Remove obsolete configurations and improve dependency handling
- Deleted `prole.cfg`, `port-mapping.cfg`, and PostgreSQL version file as part of configuration cleanup. - Enhanced Homebrew dependency resolution with `_resolve_brew_bin` and `_augment_env_for_brew` methods to manage PATH automatically. - Updated subprocess calls to respect augmented environment configurations. - Added unit tests for Homebrew PATH augmentation and dependency validation logic.
This commit is contained in:
parent
8134e27ec3
commit
c24ca728dd
@ -1,11 +1,3 @@
|
||||
# Port mappings for Prole Tools (generated).
|
||||
# Format: key: local=... remote=... ns=... svc=... address=...
|
||||
|
||||
argocd: local=8081 remote=80 ns=argocd svc=argocd-server address=0.0.0.0
|
||||
garage: local=3900 remote=3900 ns=knoe-system svc=garage address=0.0.0.0
|
||||
openbao: local=8200 remote=8200 ns=knoe-system svc=openbao address=0.0.0.0
|
||||
opentofu: local=8080 remote=8080 ns=knoe-system svc=opentofu address=0.0.0.0
|
||||
dashboard: local=8443 remote=443 ns=kubernetes-dashboard svc=kubernetes-dashboard-kong-proxy address=127.0.0.1
|
||||
postgres: local=5432 remote=5432 ns=prole-db-chrisfu-4ac8c0 svc=prole-db-rw address=0.0.0.0
|
||||
prometheus: local=9090 remote=9090 ns=monitoring svc=kps-kube-prometheus-stack-prometheus address=127.0.0.1
|
||||
grafana: local=3000 remote=80 ns=monitoring svc=kps-grafana address=0.0.0.0
|
||||
|
||||
@ -1 +0,0 @@
|
||||
18
|
||||
187
conf/prole.cfg
187
conf/prole.cfg
@ -1,187 +0,0 @@
|
||||
; Prole Master Configuration File
|
||||
; Generated by install.py on 2026-03-07 23:56:48
|
||||
; This file is used as input for Ansible deployment and k8s cluster creation.
|
||||
|
||||
[User]
|
||||
; User-editable values; derived values below reference these by default.
|
||||
NAMESPACE = knoe-db
|
||||
PROLE_CONF = ${PROLE_HOME}/conf
|
||||
PROLE_DATA = /Users/chrisfu/.prole/data
|
||||
PROLE_HOME = /Users/chrisfu/dev/prole
|
||||
PROLE_LOGS = /opt/prole/logs/chrisfu
|
||||
PROLE_SERVICE = ${PROLE_HOME}/etc
|
||||
SERVICE_NAMESPACE = knoe-system
|
||||
|
||||
[Inputs]
|
||||
; Screen-scoped inputs used for unattended replays (-S)
|
||||
build.deploy_env = Dev
|
||||
build.run_build = false
|
||||
database_options.distribution = percona
|
||||
database_options.ext.dblink = true
|
||||
database_options.ext.pg_buffercache = true
|
||||
database_options.ext.pg_freespacemap = true
|
||||
database_options.ext.pg_repack = true
|
||||
database_options.ext.pg_stat_monitor = true
|
||||
database_options.ext.pg_stat_statements = true
|
||||
database_options.ext.pgaudit = true
|
||||
database_options.ext.pgbadger = true
|
||||
database_options.ext.pgcrypto = true
|
||||
database_options.ext.pgrowlocks = true
|
||||
database_options.ext.pgvector = true
|
||||
database_options.ext.postgis = true
|
||||
database_options.ext.postgres_fdw = true
|
||||
database_options.version_type = v18
|
||||
dependencies.ansible.install = true
|
||||
dependencies.auto_install_missing = true
|
||||
dependencies.brew.install = true
|
||||
dependencies.docker.install = true
|
||||
dependencies.k3d.install = true
|
||||
dependencies.kubectl.install = true
|
||||
dependencies.kubectx.install = true
|
||||
dependencies.opentofu.install = true
|
||||
dependencies.python.install = true
|
||||
dependencies.verify_all = false
|
||||
disk_selection.disk_type = local
|
||||
disk_selection.local_path = ${PROLE_HOME}/prole-tools-app/dist
|
||||
disk_selection.removable_mount =
|
||||
env_setup.NAMESPACE = ${NAMESPACE}
|
||||
env_setup.PROLE_CONF = ${PROLE_CONF}
|
||||
env_setup.PROLE_DATA = ${PROLE_DATA}
|
||||
env_setup.PROLE_HOME = ${PROLE_HOME}
|
||||
env_setup.PROLE_LOGS = ${PROLE_LOGS}
|
||||
env_setup.PROLE_SERVICE = ${PROLE_SERVICE}
|
||||
init_cluster.at_rest_encryption_enabled = true
|
||||
init_cluster.cluster_env = service
|
||||
init_cluster.deployment_target = prole-service-cluster
|
||||
init_cluster.gitops_enabled = false
|
||||
init_cluster.k3s_server_url = https://myrddin.prole.org:6443
|
||||
init_cluster.k3s_token = ${PROLE_SECRET:v1:i1FXxxDV0iTGUprA:Esd5SwMPbXNiWB1FeAPJqDVMhaIwg6TeR7aPH-IbF3HURxH6qs89IPQWhAAOmuFYLNCG_Fc8e7y6knoe-dbTbIrV-md-fOVOZ8PbRHwGp_6u2w7O5WUf_QIdhxF30H-UQZlFZHOAHnW2l970O2zQQPGRJknoe-dbqQq6VzoK2_P6tiJ8uA==}
|
||||
init_cluster.kerberos_enabled = true
|
||||
init_cluster.mode = k3s
|
||||
init_cluster.start_cluster = true
|
||||
init_cluster.supabase_enabled = false
|
||||
init_cnpg_deploy.force_rollout = false
|
||||
init_cnpg_deploy.run_deploy = true
|
||||
init_db_build.run_build = true
|
||||
init_password.db_host_port = 5432
|
||||
init_password.db_namespace = ${NAMESPACE}
|
||||
init_password.db_password = ${PROLE_SECRET:v1:eRSi-Qb0odxbdYGH:KedZCSfHSVX6cmxyqrZG2VwA6T0aH-n1m0hSZcpCJ3T-pobLBKtb}
|
||||
init_password.db_password_confirm = ${PROLE_SECRET:v1:eRSi-Qb0odxbdYGH:KedZCSfHSVX6cmxyqrZG2VwA6T0aH-n1m0hSZcpCJ3T-pobLBKtb}
|
||||
init_password.db_username = root
|
||||
init_password.generate_ssh_key = true
|
||||
init_scripts.run_scripts = true
|
||||
kerberos_config.enabled = true
|
||||
kerberos_config.kdc = 10.0.0.3
|
||||
kerberos_config.password = ${PROLE_SECRET:v1:yXgcBJEzbAwNJ9E_:Aq6ppY9xJzN22l2FYAdVWWHyuAssQdyZKZMYm_m2SDgT6peM}
|
||||
kerberos_config.realm = PROLE.ORG
|
||||
kerberos_config.test_connection = false
|
||||
kerberos_config.user = administrator
|
||||
network_scan.run = true
|
||||
ollama_config.model =
|
||||
ollama_config.server_host =
|
||||
ollama_config.server_port = 11434
|
||||
|
||||
[Global]
|
||||
; Variables used by name in more than one place or assumed global scope
|
||||
CLUSTER_ENV = service
|
||||
DB_HOST_PORT = 5432
|
||||
DB_PASSWORD = ${PROLE_SECRET:v1:JSPYBCmth7xOrNlE:dH6t-0yLoc5qvt-sBFoQw7KRWo84LXPgUU4EIpGIRJyBMcTVFcjC}
|
||||
DEPLOYMENT_MODE = k3s
|
||||
DEPLOYMENT_TARGET = prole-service-cluster
|
||||
DOCKER_IMPORT_DIR =
|
||||
NAMESPACE = ${NAMESPACE}
|
||||
PROLE_DB_USER = root
|
||||
PROLE_HOME = ${PROLE_HOME}
|
||||
PROLE_K3S_SERVER = https://myrddin.prole.org:6443
|
||||
PROLE_K3S_TOKEN = ${PROLE_SECRET:v1:i1FXxxDV0iTGUprA:Esd5SwMPbXNiWB1FeAPJqDVMhaIwg6TeR7aPH-IbF3HURxH6qs89IPQWhAAOmuFYLNCG_Fc8e7y6knoe-dbTbIrV-md-fOVOZ8PbRHwGp_6u2w7O5WUf_QIdhxF30H-UQZlFZHOAHnW2l970O2zQQPGRJknoe-dbqQq6VzoK2_P6tiJ8uA==}
|
||||
PROLE_OPENTOFU_URL = http://127.0.0.1:8080
|
||||
SERVICE_NAMESPACE = knoe-system
|
||||
|
||||
[Welcome]
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[Dependencies]
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[Network]
|
||||
AD_DC_HOST = myrddin.prole.org
|
||||
AD_DC_IP = 10.0.0.3
|
||||
ANSIBLE_DOMAIN = prole.org
|
||||
ANSIBLE_INFRASTRUCTURE = ${PROLE_HOME}/infrastructure
|
||||
ANSIBLE_INVENTORY = ${PROLE_HOME}/infrastructure/inventory
|
||||
ANSIBLE_REALM = PROLE.ORG
|
||||
ANSIBLE_TOPOLOGY = {"domain":"prole.org","realm":"PROLE.ORG","internal_records":{"aventage.prole.org":"10.0.0.206","fairyland.prole.org":"10.0.0.208","loghost.prole.org":"10.0.0.3","merlin.prole.org":"10.0.0.6","morana.prole.org":"10.0.0.66","morgoth.prole.org":"10.0.0.204","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207","synology.prole.org":"10.0.0.203","zinfandel.prole.org":"10.0.0.205"},"ad_dc":{"host":"myrddin.prole.org","ip":"10.0.0.3"},"k3s":{"server_url":"https://myrddin.prole.org:6443","server_host":"myrddin.prole.org","token_present":true},"groups":{"iscsi":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"pihole":["pi.prole.org","raspberry.prole.org"],"ad_dc":["myrddin.prole.org"],"k3s_servers":["myrddin.prole.org"],"k3s_agents":["pi.prole.org","merlin.prole.org"],"k3s_hosts:children":["k3s_servers","k3s_agents"],"linux_hosts":["pi.prole.org","raspberry.prole.org","myrddin.prole.org","retropie.prole.org","merlin.prole.org"],"mariadb_primary":["merlin.prole.org"],"mariadb_replica":["raspberry.prole.org"],"mariadb:children":["mariadb_primary","mariadb_replica"],"merlin_bootstrap":["merlin"]},"hosts":{"merlin":"10.0.0.6","merlin.prole.org":"10.0.0.6","myrddin.prole.org":"10.0.0.3","pi.prole.org":"10.0.0.5","raspberry.prole.org":"10.0.0.4","retropie.prole.org":"10.0.0.207"},"unmapped_hosts":["k3s_agents","k3s_servers","mariadb_primary","mariadb_replica"]}
|
||||
KDC_ANSIBLE_DETECTED = 10.0.0.3
|
||||
KDC_AUTO_DETECTED = 10.0.0.3
|
||||
KERBEROS_AUTO_ENABLED = True
|
||||
|
||||
[Port Forwards]
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[System Environment]
|
||||
PROLE_CONF = ${PROLE_CONF}
|
||||
PROLE_DATA = ${PROLE_DATA}
|
||||
PROLE_HOME = ${PROLE_HOME}
|
||||
PROLE_LOGS = ${PROLE_LOGS}
|
||||
PROLE_SERVICE = ${PROLE_SERVICE}
|
||||
|
||||
[Monitoring]
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[Kerberos Authentication]
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[Ollama]
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[Optional Features]
|
||||
AT_REST_ENCRYPTION_ENABLED = True
|
||||
GITOPS_ENABLED = False
|
||||
KERBEROS_ENABLED = True
|
||||
SUPABASE_ENABLED = False
|
||||
|
||||
[GitOps]
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[Database Creation]
|
||||
NAMESPACE = ${NAMESPACE}
|
||||
|
||||
[Initialize Cluster]
|
||||
ENVIRONMENT = service
|
||||
K3S_SERVER_URL = https://myrddin.prole.org:6443
|
||||
K3S_TOKEN = ${PROLE_SECRET:v1:i1FXxxDV0iTGUprA:Esd5SwMPbXNiWB1FeAPJqDVMhaIwg6TeR7aPH-IbF3HURxH6qs89IPQWhAAOmuFYLNCG_Fc8e7y6kTbIrV-md-fOVOZ8PbRHwGp_6u2w7O5WUf_QIdhxF30H-UQZlFZHOAHnW2l970O2zQQPGRJkqQq6VzoK2_P6tiJ8uA==}
|
||||
|
||||
[Dev Cluster (k3d)]
|
||||
CLUSTER_ENV = dev
|
||||
DISPLAY_NAME = knoe-dev-cluster
|
||||
KUBECTL_CONTEXT = prole-knoe-db3s
|
||||
MODE = k3d
|
||||
|
||||
[Service Cluster (k3s)]
|
||||
CLUSTER_ENV = prole-service-cluster
|
||||
DISPLAY_NAME = prole-service-cluster
|
||||
K3S_SERVER_URL = https://myrddin.prole.org:6443
|
||||
K3S_TOKEN = ${PROLE_SECRET:v1:i1FXxxDV0iTGUprA:Esd5SwMPbXNiWB1FeAPJqDVMhaIwg6TeR7aPH-IbF3HURxH6qs89IPQWhAAOmuFYLNCG_Fc8e7y6knoe-dbTbIrV-md-fOVOZ8PbRHwGp_6u2w7O5WUf_QIdhxF30H-UQZlFZHOAHnW2l970O2zQQPGRJknoe-dbqQq6VzoK2_P6tiJ8uA==}
|
||||
MODE = k3s
|
||||
PIPELINE_URL = http://127.0.0.1:8080
|
||||
|
||||
[Prod Cluster (k8s)]
|
||||
ARTIFACTS_DIR = /Users/chrisfu/dev/prole/data/staging
|
||||
CLUSTER_ENV = prole-prod-cluster
|
||||
DISPLAY_NAME = prole-prod-cluster
|
||||
MODE = k8s
|
||||
PIPELINE_URL = http://127.0.0.1:8080
|
||||
|
||||
[Docker Build]
|
||||
LOCAL_REGISTRY = localhost:5000
|
||||
LOCAL_REGISTRY_INTERNAL = k3d-prole-registry.localhost:5000
|
||||
|
||||
[Initialization Scripts]
|
||||
; No configuration values captured yet for this section.
|
||||
|
||||
[Deployment]
|
||||
MODE = k3s
|
||||
TARGET = prole-service-cluster
|
||||
|
||||
[Install]
|
||||
; No configuration values captured yet for this section.
|
||||
@ -13,6 +13,7 @@ import json
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
@ -749,17 +750,79 @@ DEPENDENCIES = [
|
||||
]
|
||||
|
||||
|
||||
def _resolve_brew_bin() -> str | None:
|
||||
"""Return an absolute path to a `brew` binary if one is found in common locations."""
|
||||
|
||||
candidates: list[str] = [
|
||||
"/home/linuxbrew/.linuxbrew/bin/brew", # Linuxbrew (recommended)
|
||||
os.path.expanduser("~/.linuxbrew/bin/brew"), # Linuxbrew (legacy single-user)
|
||||
"/opt/homebrew/bin/brew", # macOS (Apple Silicon)
|
||||
"/usr/local/bin/brew", # macOS (Intel)
|
||||
]
|
||||
|
||||
for p in candidates:
|
||||
try:
|
||||
if os.path.isfile(p) and os.access(p, os.X_OK):
|
||||
return p
|
||||
except Exception:
|
||||
continue
|
||||
return None
|
||||
|
||||
|
||||
def _augment_env_for_brew(env: dict | None = None) -> dict:
|
||||
"""Prepend Homebrew `bin`/`sbin` to PATH when brew exists but isn't in PATH.
|
||||
|
||||
This keeps dependency checks and `brew install ...` invocations working in
|
||||
non-interactive environments where shell init files aren't sourced.
|
||||
"""
|
||||
|
||||
if env is None:
|
||||
env = os.environ.copy()
|
||||
|
||||
brew_bin = _resolve_brew_bin()
|
||||
if not brew_bin:
|
||||
return env
|
||||
|
||||
try:
|
||||
brew_bin_path = Path(brew_bin)
|
||||
prefix = brew_bin_path.parent.parent
|
||||
bin_dir = str(prefix / "bin")
|
||||
sbin_dir = str(prefix / "sbin")
|
||||
|
||||
path_val = env.get("PATH", "") or ""
|
||||
parts = [p for p in path_val.split(os.pathsep) if p]
|
||||
|
||||
prepend: list[str] = []
|
||||
if bin_dir and bin_dir not in parts:
|
||||
prepend.append(bin_dir)
|
||||
try:
|
||||
if os.path.isdir(sbin_dir) and sbin_dir not in parts:
|
||||
prepend.append(sbin_dir)
|
||||
except Exception:
|
||||
# sbin is optional
|
||||
pass
|
||||
|
||||
if prepend:
|
||||
env["PATH"] = os.pathsep.join(prepend + parts)
|
||||
except Exception:
|
||||
return env
|
||||
|
||||
return env
|
||||
|
||||
|
||||
def get_dep_info(dep: dict) -> Tuple[bool, Optional[str], Optional[str]]:
|
||||
bin_name = dep.get("bin") or dep["name"]
|
||||
location = None
|
||||
version = None
|
||||
installed = False
|
||||
try:
|
||||
env = _augment_env_for_brew(os.environ.copy())
|
||||
if bin_name:
|
||||
res = subprocess.run(
|
||||
["bash", "-lc", f"command -v {bin_name}"],
|
||||
["bash", "-lc", f"command -v -- {shlex.quote(bin_name)}"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
env=env,
|
||||
)
|
||||
if res.returncode == 0:
|
||||
location = res.stdout.strip()
|
||||
@ -768,7 +831,10 @@ def get_dep_info(dep: dict) -> Tuple[bool, Optional[str], Optional[str]]:
|
||||
check_cmd = dep.get("check_cmd")
|
||||
if check_cmd:
|
||||
res2 = subprocess.run(
|
||||
["bash", "-lc", check_cmd], capture_output=True, text=True
|
||||
["bash", "-lc", check_cmd],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
env=env,
|
||||
)
|
||||
if res2.returncode == 0:
|
||||
installed = True
|
||||
@ -781,7 +847,10 @@ def get_dep_info(dep: dict) -> Tuple[bool, Optional[str], Optional[str]]:
|
||||
version_cmd = dep.get("version_cmd")
|
||||
if version_cmd:
|
||||
res3 = subprocess.run(
|
||||
["bash", "-lc", version_cmd], capture_output=True, text=True
|
||||
["bash", "-lc", version_cmd],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
env=env,
|
||||
)
|
||||
if res3.returncode == 0:
|
||||
v_out = res3.stdout.strip()
|
||||
|
||||
@ -53,9 +53,11 @@ class Milestone(ABC):
|
||||
if isinstance(cmd, str):
|
||||
cmd = ["bash", "-c", cmd]
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
env = inst_config._augment_env_for_brew(os.environ.copy())
|
||||
proc = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
@ -63,6 +65,7 @@ class Milestone(ABC):
|
||||
text=True,
|
||||
bufsize=1,
|
||||
cwd=cwd,
|
||||
env=env,
|
||||
)
|
||||
for line in iter(proc.stdout.readline, ""):
|
||||
if on_stdout:
|
||||
|
||||
@ -270,6 +270,42 @@ def test_get_dep_info_check_cmd_success():
|
||||
assert "Docker" in (ver or "")
|
||||
|
||||
|
||||
def test_get_dep_info_prepends_linuxbrew_to_path_when_present():
|
||||
dep = {
|
||||
"id": "brew",
|
||||
"name": "Homebrew",
|
||||
"bin": "brew",
|
||||
"check_cmd": "brew --version",
|
||||
}
|
||||
|
||||
def _run(args, capture_output=False, text=False, env=None, **kwargs):
|
||||
assert env is not None
|
||||
path_parts = (env.get("PATH") or "").split(os.pathsep)
|
||||
assert path_parts[0] == "/home/linuxbrew/.linuxbrew/bin"
|
||||
assert "/home/linuxbrew/.linuxbrew/sbin" in path_parts[:2]
|
||||
|
||||
m = MagicMock()
|
||||
cmd = " ".join(args)
|
||||
if "command -v" in cmd:
|
||||
m.returncode = 0
|
||||
m.stdout = "/home/linuxbrew/.linuxbrew/bin/brew\n"
|
||||
else:
|
||||
m.returncode = 0
|
||||
m.stdout = "Homebrew 5.0.0\n"
|
||||
return m
|
||||
|
||||
with patch.dict(os.environ, {"PATH": "/usr/bin:/bin"}, clear=False), \
|
||||
patch("installer.config.os.path.isfile", side_effect=lambda p: p == "/home/linuxbrew/.linuxbrew/bin/brew"), \
|
||||
patch("installer.config.os.access", return_value=True), \
|
||||
patch("installer.config.os.path.isdir", side_effect=lambda p: p == "/home/linuxbrew/.linuxbrew/sbin"), \
|
||||
patch("installer.config.subprocess.run", side_effect=_run):
|
||||
ok, loc, ver = get_dep_info(dep)
|
||||
|
||||
assert ok is True
|
||||
assert loc == "/home/linuxbrew/.linuxbrew/bin/brew"
|
||||
assert ver == "Homebrew 5.0.0"
|
||||
|
||||
|
||||
def test_get_dep_info_version_cmd_success():
|
||||
dep = {"id": "kubectl", "name": "kubectl", "bin": "kubectl",
|
||||
"version_cmd": "kubectl version --client --short"}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user