From 395bab657a650a5f46fbbb465a50566f2f70226e Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 19 Dec 2022 19:09:12 +0100 Subject: [PATCH] Yoloimplement support for appsv2 --- lib/default_install_args.py | 54 +++++++++++++++++++++++++++++++++++ lib/manifest_parsing.py | 56 ------------------------------------- lib/tests.sh | 42 +++++++++++++++++++++------- lib/tests_coordination.sh | 14 +++++++--- 4 files changed, 96 insertions(+), 70 deletions(-) create mode 100644 lib/default_install_args.py delete mode 100644 lib/manifest_parsing.py diff --git a/lib/default_install_args.py b/lib/default_install_args.py new file mode 100644 index 0000000..2c1e89b --- /dev/null +++ b/lib/default_install_args.py @@ -0,0 +1,54 @@ +#!/usr/bin/python3 + +import sys +import json +import toml + +def get_default_values_for_questions(manifest): + + base_default_value_per_arg_type = { + ("domain", "domain"): "domain.tld", + ("path", "path"): "/" + manifest["id"], + ("user", "admin"): "package_checker", + ("group", "init_main_permission"): "visitors", + ("group", "init_admin_permission"): "admins", + ("password", "password"): "MySuperComplexPassword" + } + + if manifest.get("packaging_format", 1) <= 1: + questions = {q["name"]:q for q in manifest["arguments"]["install"]} + else: + questions = manifest["install"] + + for name, question in questions.items(): + type_and_name = (question["type"], name) + base_default = base_default_value_per_arg_type.get(type_and_name) + if base_default: + yield (name, base_default) + elif question.get("default"): + if isinstance(question.get("default"), bool): + yield (name, str(int(question.get("default")))) + else: + yield (name, str(question.get("default"))) + elif question["type"] == "boolean": + yield (name, "1") + elif question.get("choices"): + if isinstance(question["choices"]): + choices = str(question["choices"]) + else: + choices = list(question["choices"].keys()) + yield (name, question["choices"][0]) + else: + raise Exception("No default value could be computed for arg " + name) + + +if __name__ == '__main__': + manifest_path = sys.argv[1:][0] + + if manifest_path.endswith(".json"): + manifest = json.load(open(manifest_path, "r")) + else: + manifest = toml.load(open(manifest_path, "r")) + + querystring = '&'.join([k + "=" + v for k, v in get_default_values_for_questions(manifest)]) + print(querystring) diff --git a/lib/manifest_parsing.py b/lib/manifest_parsing.py deleted file mode 100644 index 079e188..0000000 --- a/lib/manifest_parsing.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/python3 - -import sys -import json - -def argument_for_question(question, all_choices=False): - question_type = question.get("type") - - if question_type is None and question.get("choices"): - question_type = "boolean" - elif question_type in [None, "string"] and question.get("default"): - question_type = "with_default" - elif question_type is None and question["name"] == "admin": - question_type = "user" - elif question_type is None and question["name"] == "domain": - question_type = "domain" - - if question_type == "domain": - return (question["name"], "ynh.local") - elif question_type == "path": - if all_choices: - return (question["name"], question["default"], "/") - else: - return (question["name"], question["default"]) - elif question_type == "with_default": - return (question["name"], question["default"]) - elif question_type == "boolean": - if not all_choices: - if isinstance(question["default"], bool): - if question["default"]: - question["default"] = "1" - else: - question["default"] = "0" - - return (question["name"], question["default"]) - else: - if isinstance(question["default"], bool) : - return (question["name"], "1", "0") - - if question.get("choices"): - return (question["name"],) + tuple(question["choices"]) - - return (question["name"], question["default"]) - elif question_type == "password": - return (question["name"], "ynh") - elif question_type == "user": - return (question["name"], "johndoe") - else: - raise Exception("Unknow question type: %s\n" % question_type, question) - -if __name__ == '__main__': - manifest_path = sys.argv[1:][0] - manifest = json.load(open(manifest_path, "r")) - - for question in manifest["arguments"]["install"]: - print(":".join(argument_for_question(question, all_choices=True))) diff --git a/lib/tests.sh b/lib/tests.sh index 08a36c7..eecb737 100644 --- a/lib/tests.sh +++ b/lib/tests.sh @@ -76,13 +76,14 @@ _INSTALL_APP () { # We have default values for domain, admin and is_public, but these # may still be overwritten by the args ($@) - for arg_override in "domain=$SUBDOMAIN" "admin=$TEST_USER" "is_public=1" "$@" + for arg_override in "domain=$SUBDOMAIN" "admin=$TEST_USER" "is_public=1" "init_main_permission=visitors" "$@" do key="$(echo $arg_override | cut -d '=' -f 1)" value="$(echo $arg_override | cut -d '=' -f 2-)" # (Legacy stuff ... We don't override is_public if its type is not boolean) - [[ "$key" == "is_public" ]] \ + [[ -e $package_path/manifest.json ]] \ + && [[ "$key" == "is_public" ]] \ && [[ "$(jq -r '.arguments.install[] | select(.name=="is_public") | .type' $package_path/manifest.json)" != "boolean" ]] \ && continue @@ -90,14 +91,27 @@ _INSTALL_APP () { done # Note : we do this at this stage and not during the parsing of check_process - # because this also applies to upgrades ... - # For all manifest arg - for ARG in $(jq -r '.arguments.install[].name' $package_path/manifest.json) + # because this also applies to upgrades ... ie older version may have different args and default values + + # Fetch and loop over all manifest arg + if [[ -e $package_path/manifest.json ]] + then + local manifest_args="$(jq -r '.arguments.install[].name' $package_path/manifest.json)" + else + local manifest_args="$(grep '^\s*\[install\.' $package_path/manifest.toml | tr -d '[]' | awk -F. '{print $2}')" + fi + + for ARG in $manifest_args do # If the argument is not yet in install args, add its default value if ! echo "$install_args" | grep -q -E "\<$ARG=" then - local default_value=$(jq -e -r --arg ARG $ARG '.arguments.install[] | select(.name==$ARG) | .default' $package_path/manifest.json) + if [[ -e $package_path/manifest.json ]] + then + local default_value=$(jq -e -r --arg ARG $ARG '.arguments.install[] | select(.name==$ARG) | .default' $package_path/manifest.json) + else + local default_value=$(python3 -c "import toml, sys; t = toml.loads(sys.stdin.read()); d = t['install']['$ARG'].get('default'); assert d is not None, 'Missing default value'; print(d)" < manifest.toml) + fi [[ $? -eq 0 ]] || { log_error "Missing install arg $ARG ?"; return 1; } [[ ${install_args: -1} == '&' ]] || install_args+="&" install_args+="$ARG=$default_value" @@ -177,7 +191,14 @@ _VALIDATE_THAT_APP_CAN_BE_ACCESSED () { # private by default For "regular" apps (with a is_public arg) they are # installed as public, and we precisely want to check they are publicly # accessible *without* tweaking skipped_uris... - if [ "$install_type" != 'private' ] && [[ -z "$(jq -r '.arguments.install[] | select(.name=="is_public")' $package_path/manifest.json)" ]] + if [[ -e $package_path/manifest.json ]] + then + local has_public_arg=$([[ -n "$(jq -r '.arguments.install[] | select(.name=="is_public")' $package_path/manifest.json)" ]] && echo true || echo false) + else + local has_public_arg=$(grep -q '\[install.init_main_permission\]' manifest.toml && echo true || echo false) + fi + + if [ "$install_type" != 'private' ] && [[ $has_public_arg == "false" ]] then log_debug "Forcing public access using a skipped_uris setting" # Add a skipped_uris on / for the app @@ -350,10 +371,11 @@ TEST_INSTALL () { local check_path="/" local is_public="1" + local init_main_permission="visitors" [ "$install_type" = "subdir" ] && { start_test "Installation in a sub path"; local check_path=/path; } [ "$install_type" = "root" ] && { start_test "Installation on the root"; } [ "$install_type" = "nourl" ] && { start_test "Installation without URL access"; local check_path=""; } - [ "$install_type" = "private" ] && { start_test "Installation in private mode"; local is_public="0"; } + [ "$install_type" = "private" ] && { start_test "Installation in private mode"; local is_public="0"; local init_main_permission="all_users"; } local snapname=snap_${install_type}install LOAD_LXC_SNAPSHOT snap0 @@ -361,7 +383,7 @@ TEST_INSTALL () { _PREINSTALL # Install the application in a LXC container - _INSTALL_APP "path=$check_path" "is_public=$is_public" \ + _INSTALL_APP "path=$check_path" "is_public=$is_public" "init_main_permission=$init_main_permission" \ && _VALIDATE_THAT_APP_CAN_BE_ACCESSED "$SUBDOMAIN" "$check_path" "$install_type" \ local install=$? @@ -377,7 +399,7 @@ TEST_INSTALL () { # Remove and reinstall the application _REMOVE_APP \ && log_small_title "Reinstalling after removal." \ - && _INSTALL_APP "path=$check_path" "is_public=$is_public" \ + && _INSTALL_APP "path=$check_path" "is_public=$is_public" "init_main_permission=$init_main_permission" \ && _VALIDATE_THAT_APP_CAN_BE_ACCESSED "$SUBDOMAIN" "$check_path" "$install_type" return $? diff --git a/lib/tests_coordination.sh b/lib/tests_coordination.sh index 1548a75..6c4271e 100644 --- a/lib/tests_coordination.sh +++ b/lib/tests_coordination.sh @@ -87,6 +87,7 @@ parse_check_process() { echo "$install_args" | tr '&' '\n' | grep -q "^path=" ||install_args+="path=&" echo "$install_args" | tr '&' '\n' | grep -q "^admin=" ||install_args+="admin=&" echo "$install_args" | tr '&' '\n' | grep -q "^is_public=" ||install_args+="is_public=&" + echo "$install_args" | tr '&' '\n' | grep -q "^init_main_permission=" ||install_args+="init_main_permission=&" extract_check_process_section "^; Checks" "^; " $test_serie_rawconf > $TEST_CONTEXT/check_process.tests_infos @@ -193,16 +194,16 @@ guess_test_configuration() { > "$TEST_CONTEXT/tests/$test_id.json" } - local install_args=$(python3 "./lib/manifest_parsing.py" "$package_path/manifest.json" | cut -d ':' -f1,2 | tr ':' '=' | tr '\n' '&') + local install_args=$(python3 "./lib/default_install_args.py" "$package_path"/manifest.*) add_test "PACKAGE_LINTER" add_test "TEST_INSTALL" "root" add_test "TEST_INSTALL" "subdir" - if echo $install_args | grep -q "is_public=" + if echo $install_args | grep -q "is_public=\|init_main_permission=" then add_test "TEST_INSTALL" "private" fi - if grep multi_instance "$package_path/manifest.json" | grep -q true + if grep multi_instance "$package_path"/manifest.* | grep -q true then add_test "TEST_INSTALL" "multi" fi @@ -220,7 +221,12 @@ run_all_tests() { mkdir -p $TEST_CONTEXT/results mkdir -p $TEST_CONTEXT/logs - readonly app_id="$(jq -r .id $package_path/manifest.json)" + if [ -e $package_path/manifest.json ] + then + readonly app_id="$(jq -r .id $package_path/manifest.json)" + else + readonly app_id="$(grep '^id = ' $package_path/manifest.toml | tr -d '" ' | awk -F= '{print $2}')" + fi # Parse the check_process only if it's exist check_process="$package_path/check_process"