Files
metabuilder/deployment/cli/nexus_init.py
johndoe6345789 695b26d5d2 fix(deployment): resolve run() name shadowing in CLI modules
The module entry point `run = run_cmd` shadowed the imported subprocess
helper `run` from cli.helpers, causing TypeError on dispatch. Import as
`run_proc` and use a proper wrapper function for the module entry point.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 01:42:10 +00:00

135 lines
5.7 KiB
Python

"""Initialize Nexus repositories (Docker + npm, or npm-only for CI)."""
import argparse
import json
import os
import subprocess
from cli.helpers import curl_status, log_err, run as run_proc
def run_cmd(args: argparse.Namespace, config: dict) -> int:
nexus_url = os.environ.get("NEXUS_URL", "http://localhost:8091" if args.ci else "http://nexus:8081")
new_pass = os.environ.get("NEXUS_ADMIN_NEW_PASS", "nexus")
docker_port = os.environ.get("DOCKER_REPO_PORT", "5000")
pass_file = "/tmp/nexus-data/admin.password" if args.ci else "/nexus-data/admin.password"
prefix = "nexus-ci-init" if args.ci else "nexus-init"
def nlog(msg: str) -> None:
print(f"[{prefix}] {msg}")
auth = f"admin:{new_pass}"
# Resolve admin password
status = curl_status(f"{nexus_url}/service/rest/v1/status", auth)
if status == 200:
nlog(f"Already initialised with password '{new_pass}'")
elif os.path.exists(pass_file):
with open(pass_file) as f:
init_pass = f.read().strip()
nlog("First run: changing admin password...")
result = subprocess.run([
"curl", "-s", "-o", os.devnull, "-w", "%{http_code}", "-X", "PUT",
f"{nexus_url}/service/rest/v1/security/users/admin/change-password",
"-u", f"admin:{init_pass}", "-H", "Content-Type: text/plain", "-d", new_pass,
], capture_output=True, text=True)
if result.stdout.strip() == "204":
nlog(f"Admin password set to '{new_pass}'")
else:
nlog(f"ERROR: password change returned HTTP {result.stdout.strip()}")
return 1
else:
nlog("ERROR: cannot authenticate — is NEXUS_ADMIN_NEW_PASS correct?")
return 1
# Enable anonymous access
run_proc(["curl", "-sf", "-X", "PUT", f"{nexus_url}/service/rest/v1/security/anonymous",
"-u", auth, "-H", "Content-Type: application/json",
"-d", '{"enabled":true,"userId":"anonymous","realmName":"NexusAuthorizingRealm"}'])
nlog("Anonymous access enabled")
if not args.ci:
# Docker + npm token realms
run_proc(["curl", "-sf", "-X", "PUT", f"{nexus_url}/service/rest/v1/security/realms/active",
"-u", auth, "-H", "Content-Type: application/json",
"-d", '["NexusAuthenticatingRealm","DockerToken","NpmToken"]'])
nlog("Docker + npm Bearer Token realms enabled")
# Docker hosted repo
docker_repo = json.dumps({
"name": "local", "online": True,
"storage": {"blobStoreName": "default", "strictContentTypeValidation": True, "writePolicy": "allow"},
"docker": {"v1Enabled": False, "forceBasicAuth": False, "httpPort": int(docker_port)},
})
result = subprocess.run([
"curl", "-s", "-o", os.devnull, "-w", "%{http_code}", "-X", "POST",
f"{nexus_url}/service/rest/v1/repositories/docker/hosted",
"-u", auth, "-H", "Content-Type: application/json", "-d", docker_repo,
], capture_output=True, text=True)
code = result.stdout.strip()
if code == "201":
nlog(f"Docker hosted repo 'local' created on port {docker_port}")
elif code == "400":
nlog("Docker repo 'local' already exists, skipping")
else:
nlog(f"ERROR: Docker repo creation returned HTTP {code}")
return 1
else:
# CI: npm token realm only
run_proc(["curl", "-sf", "-X", "PUT", f"{nexus_url}/service/rest/v1/security/realms/active",
"-u", auth, "-H", "Content-Type: application/json",
"-d", '["NexusAuthenticatingRealm","NpmToken"]'])
# npm repos (hosted, proxy, group)
npm_repos = [
("npm/hosted", "npm-hosted", {
"name": "npm-hosted", "online": True,
"storage": {"blobStoreName": "default", "strictContentTypeValidation": True,
"writePolicy": "allow" if args.ci else "allow_once"},
}),
("npm/proxy", "npm-proxy", {
"name": "npm-proxy", "online": True,
"storage": {"blobStoreName": "default", "strictContentTypeValidation": True},
"proxy": {"remoteUrl": "https://registry.npmjs.org", "contentMaxAge": 1440, "metadataMaxAge": 1440},
"httpClient": {"blocked": False, "autoBlock": True},
"negativeCache": {"enabled": True, "timeToLive": 1440},
}),
("npm/group", "npm-group", {
"name": "npm-group", "online": True,
"storage": {"blobStoreName": "default", "strictContentTypeValidation": True},
"group": {"memberNames": ["npm-hosted", "npm-proxy"]},
}),
]
for repo_type, label, body in npm_repos:
result = subprocess.run([
"curl", "-s", "-o", os.devnull, "-w", "%{http_code}", "-X", "POST",
f"{nexus_url}/service/rest/v1/repositories/{repo_type}",
"-u", auth, "-H", "Content-Type: application/json", "-d", json.dumps(body),
], capture_output=True, text=True)
code = result.stdout.strip()
if code == "201":
nlog(f"{label} repo created")
elif code == "400":
nlog(f"{label} repo already exists, skipping")
else:
nlog(f"ERROR creating {label}: HTTP {code}")
return 1
if args.ci:
nlog("Nexus CI init complete")
else:
nlog("")
nlog("=" * 46)
nlog(" Nexus ready!")
nlog(f" Registry : localhost:{docker_port}")
nlog(f" Web UI : http://localhost:8091")
nlog(f" Login : admin / {new_pass}")
nlog(f" npm group: {nexus_url}/repository/npm-group/")
nlog("=" * 46)
return 0
def run(args, config):
return run_cmd(args, config)