Allow updating only one app

This commit is contained in:
Aaron Dewes 2022-02-01 18:50:59 +01:00
parent 6ec999dd97
commit 6330fa7352
9 changed files with 45 additions and 43 deletions

View File

@ -5,7 +5,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import json
from lib.manage import compose, createDataDir, deleteData, getUserData, setInstalled, setRemoved, startInstalled, stopInstalled, update, deriveEntropy, updateRepos
from lib.manage import compose, createDataDir, deleteData, getUserData, setInstalled, setRemoved, startInstalled, stopInstalled, update, deriveEntropy, updateRepos, download
from lib.validate import findAndValidateApps
import os
import argparse
@ -25,7 +25,7 @@ legacyScript = os.path.join(nodeRoot, "scripts", "app")
parser = argparse.ArgumentParser(description="Manage apps on your Citadel")
parser.add_argument('action', help='What to do with the app database.', choices=[
"list", "download", "update", "update-online", "ls-installed", "install", "uninstall", "stop", "start", "compose", "restart", "entropy"])
"list", "download", "generate", "update", "ls-installed", "install", "uninstall", "stop", "start", "compose", "restart", "entropy"])
# Add the --invoked-by-configure option, which is hidden from the user in --help
parser.add_argument('--invoked-by-configure',
action='store_true', help=argparse.SUPPRESS)
@ -48,7 +48,7 @@ if args.action == 'list':
elif args.action == 'download':
updateRepos()
exit(0)
elif args.action == 'update':
elif args.action == 'generate':
if args.invoked_by_configure:
update(args.app)
else:
@ -61,11 +61,15 @@ elif args.action == 'update':
os.system("docker compose stop app-3-tor")
os.system("docker compose start app-3-tor")
exit(0)
elif args.action == 'update-online':
updateRepos()
print("Downloaded all updates")
elif args.action == 'update':
if args.app is None:
updateRepos()
print("Downloaded all updates")
else:
download(args.app)
print("Downloaded latest {} version".format(args.app))
if args.invoked_by_configure:
update(args.app)
update(args.verbose)
else:
os.system(os.path.join(nodeRoot, "scripts", "configure"))
os.chdir(nodeRoot)

View File

@ -50,25 +50,24 @@ def getArguments():
def getAppYml(name):
url = 'https://raw.githubusercontent.com/runcitadel/core/main/apps/' + \
name + '/' + 'app.yml'
with open(os.path.join(appsDir, "sourceMap.json"), "r") as f:
sourceMap = json.load(f)
if not name in sourceMap:
print("Warning: App {} can't be updated because it is not in the source map".format(name))
return False
url = 'https://raw.githubusercontent.com/{}/{}/apps/{}/app.yml'.format(sourceMap[name]["githubRepo"], sourceMap[name]["branch"], name)
response = requests.get(url)
if response.status_code == 200:
return response.text
else:
return False
def getAppYmlPath(app):
return os.path.join(appsDir, app, 'app.yml')
def update(verbose: bool = False):
apps = findAndValidateApps(appsDir)
# The compose generation process updates the registry, so we need to get it set up with the basics before that
registry = getAppRegistry(apps, appsDir)
with open(os.path.join(appsDir, "registry.json"), "w") as f:
json.dump(registry, f, indent=4, sort_keys=True)
json.dump(registry, f, sort_keys=True)
print("Wrote registry to registry.json")
# Loop through the apps and generate valid compose files from them, then put these into the app dir
@ -84,23 +83,13 @@ def update(verbose: bool = False):
print("Generated configuration successfully")
def download(app: str = None):
if app is None:
apps = findAndValidateApps(appsDir)
for app in apps:
data = getAppYml(app)
if data:
with open(getAppYmlPath(app), 'w') as f:
f.write(data)
else:
print("Warning: Could not download " + app)
def download(app: str):
data = getAppYml(app)
if data:
with open(os.path.join(appsDir, app, "app.yml"), 'w') as f:
f.write(data)
else:
data = getAppYml(app)
if data:
with open(getAppYmlPath(app), 'w') as f:
f.write(data)
else:
print("Warning: Could not download " + app)
print("Warning: Could not download " + app)
def getUserData():
@ -273,6 +262,8 @@ def updateRepos():
# For each repo, clone the repo to a temporary dir, checkout the branch,
# and overwrite the current app dir with the contents of the temporary dir/apps/app
alreadyInstalled = []
# A map of apps to their source repo
sourceMap = {}
for repo in repos:
repo = repo.strip()
if repo == "":
@ -298,6 +289,11 @@ def updateRepos():
# if the app is already installed, don't overwrite it
if app in alreadyInstalled:
continue
if gitUrl.startswith("https://github.com"):
sourceMap[app] = {
"githubRepo": gitUrl.removeprefix("https://github.com/").removesuffix(".git").removesuffix("/"),
"branch": branch,
}
if os.path.isdir(os.path.join(appsDir, app)):
shutil.rmtree(os.path.join(appsDir, app), onerror=remove_readonly)
if os.path.isdir(os.path.join(tempDir, "apps", app)):
@ -306,3 +302,5 @@ def updateRepos():
alreadyInstalled.append(app)
# Remove the temporary dir
shutil.rmtree(tempDir)
with open(os.path.join(appsDir, "sourceMap.json"), "w") as f:
json.dump(sourceMap, f)

View File

@ -10,4 +10,4 @@ signal="${1}"
command=${signal%%"-"*}
app=${signal#*"-"}
"${CITADEL_ROOT}/app/app-manager.py" "${command}" "${app}"
"${CITADEL_ROOT}/scripts/app" "${command}" "${app}"

View File

@ -6,5 +6,5 @@
CITADEL_ROOT="$(readlink -f $(dirname "${BASH_SOURCE[0]}")/../..)"
"${CITADEL_ROOT}/app/app-manager.py" update-online
"${CITADEL_ROOT}/app/app-manager.py" start installed
"${CITADEL_ROOT}/scripts/app" update
"${CITADEL_ROOT}/scripts/app" start installed

4
scripts/configure vendored
View File

@ -360,11 +360,11 @@ download_docker_compose()
if not reconfiguring:
print("Updating apps...")
print()
os.system('./app/app-manager.py --invoked-by-configure update-online')
os.system('./scripts/app --invoked-by-configure update')
elif not updating:
print("Updating apps...")
print()
os.system('./app/app-manager.py --invoked-by-configure update')
os.system('./scripts/app --invoked-by-configure generate')
print("Configuring permissions")
print()
os.system('chown -R 1000:1000 {}'.format(CITADEL_ROOT))

View File

@ -153,7 +153,7 @@ if [[ "${1}" == "--run" ]]; then
echo
docker compose logs --tail=30 tor
installed_apps=$(./app/app-manager.py ls-installed)
installed_apps=$(./scripts/app ls-installed)
if [[ ! -z "${installed_apps:-}" ]]; then
echo
echo "App logs"

View File

@ -35,7 +35,7 @@ get_total_used_mem() {
# To get the containers of the app, list every container whose name starts with the name of the app
get_app_containers () {
local app_name="$1"
"${CITADEL_ROOT}/app/app-manager.py" compose "${app_name}" ps | awk '{print $1}' | grep -v 'Name\|-----'
"${CITADEL_ROOT}/scripts/app" compose "${app_name}" ps | awk '{print $1}' | grep -v 'Name\|-----'
}
# Get the memory usage of the whole system, excluding docker containers
@ -52,7 +52,7 @@ main() {
for service in bitcoin lnd electrs tor; do
echo "${service}: $(get_memory_usage "$service")%" &
done
for app in $("${CITADEL_ROOT}/app/app-manager.py" ls-installed); do
for app in $("${CITADEL_ROOT}/scripts/app" ls-installed); do
# For every container of the app, get the mem usage, save it, and at the end, print the total mem usage of the app
local mem_usage=0
for container in $(get_app_containers "$app"); do

View File

@ -126,7 +126,7 @@ fi
echo
echo "Starting installed apps..."
echo
./app/app-manager.py start installed
./scripts/app start installed
echo
echo "Citadel is now accessible at"

View File

@ -124,11 +124,11 @@ echo "Updating installed apps"
cat <<EOF > "$CITADEL_ROOT"/statuses/update-status.json
{"state": "installing", "progress": 70, "description": "Updating installed apps", "updateTo": "$RELEASE"}
EOF
"${CITADEL_ROOT}/app/app-manager.py" update-online
for app in $("$CITADEL_ROOT/app/app-manager.py" ls-installed); do
"${CITADEL_ROOT}/scripts/app" --invoked-by-configure update
for app in $("$CITADEL_ROOT/scripts/app" ls-installed); do
if [[ "${app}" != "" ]]; then
echo "${app}..."
"${CITADEL_ROOT}/app/app-manager.py" compose "${app}" pull
"${CITADEL_ROOT}/scripts/app" compose "${app}" pull
fi
done
wait