Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite core scripts in ./scripts in a more robust language #560

Open
christophertubbs opened this issue Mar 26, 2024 · 0 comments
Open
Assignees

Comments

@christophertubbs
Copy link
Contributor

We currently have bash scripts tying a lot of our functionality together, from package updating, to testing, to deployment. Unfortunately, the scripts are complicated, hard to read, and aren't posix compatible.

Consider the following error:

(venv) owpal-mbook0586:DMOD christopher.tubbs$ ./scripts/create_env_config.sh 
./scripts/create_env_config.sh: line 18: nproc: command not found
./scripts/create_env_config.sh: line 19: [: -lt: unary operator expected
./scripts/create_env_config.sh: line 21: [: -lt: unary operator expected
Created environment config at '/path/to/DMOD/.env'

It's relying on non-universal programs and invalid if statements for one of the very first steps when it comes to deploying the software.

The cli parsing is also fairly arcane. From scripts/run_tests.sh:

while [ ${#} -gt 0 ]; do
    case "${1}" in
        -h|--help|-help)
            usage
            exit
            ;;
        --integration|-it)
            [ -n "${IT_ARG:-}" ] && usage && exit 1
            IT_ARG="-it"
            ;;
        --list-packages|-l)
            [ -n "${DO_LIST:-}" ] && usage && exit 1
            DO_LIST='true'
            ;;
        --quiet|-q)
            [ -n "${DO_QUIET:-}" ] && usage && exit 1
            [ -n "${SET_VERBOSE:-}" ] && usage && exit 1
            DO_QUIET='true'
            ;;
        --service-packages|-srv)
            [ -n "${DO_SERVICE_PACKAGES:-}" ] && usage && exit 1
            DO_SERVICE_PACKAGES='true'
            ;;
        --django|-d)
            [ -n "${TEST_DJANGO_SERVICES:-}" ] && usage && exit 1;
            TEST_DJANGO_SERVICES='true';
            ;;
        --venv)
            [ -n "${VENV_DIR:-}" ] && usage && exit 1
            VENV_DIR="$(py_dev_validate_venv_dir "${2}")"
            [ -z "${VENV_DIR:-}" ] && echo "Error: provided arg ${2} is not a valid virtual env directory" && exit 1
            shift
            ;;
        -v|-vv)
            [ -n "${SET_VERBOSE:-}" ] && usage && exit 1
            [ -n "${DO_QUIET:-}" ] && usage && exit 1
            SET_VERBOSE='true'
            if [ "${1}" == "-vv" ]; then
                VERBOSE_ARG="-v"
            fi
            ;;
        *)
            usage
            exit 1
            ;;
    esac
    shift
done

That's valid and well written bash, but it's hard to follow and uses implicit if statements.

I'm more familiar with how to do this sort of thing in python, so I'd suggest this be written in that, but golang apparently has quite a few utilities that make this easy to do.

Bash scripts can and should be used for coordination, but some of the more involved logic, such as:

cat example.env | \
    sed "s|##* *DMOD_SSL_DIR=.*|DMOD_SSL_DIR=${REPO_ROOT_DIR}/ssl/|" | \
    sed "s|##* *DMOD_OBJECT_STORE_MINIO_1_SSL_KEY=.*|DMOD_OBJECT_STORE_MINIO_1_SSL_KEY=${REPO_ROOT_DIR}/ssl/object_store/minio1/private.key|" | \
    sed "s|##* *DMOD_OBJECT_STORE_MINIO_1_SSL_CERT=.*|DMOD_OBJECT_STORE_MINIO_1_SSL_CERT=${REPO_ROOT_DIR}/ssl/object_store/minio1/public.crt|" | \
    sed "s|##* *DMOD_OBJECT_STORE_MINIO_2_SSL_KEY=.*|DMOD_OBJECT_STORE_MINIO_2_SSL_KEY=${REPO_ROOT_DIR}/ssl/object_store/minio2/private.key|" | \
    sed "s|##* *DMOD_OBJECT_STORE_MINIO_2_SSL_CERT=.*|DMOD_OBJECT_STORE_MINIO_2_SSL_CERT=${REPO_ROOT_DIR}/ssl/object_store/minio2/public.crt|" | \
    sed "s|##* *DMOD_OBJECT_STORE_MINIO_PROXY_SSL_KEY=.*|DMOD_OBJECT_STORE_MINIO_PROXY_SSL_KEY=${REPO_ROOT_DIR}/ssl/object_store/minio_proxy/private.key|" | \
    sed "s|##* *DMOD_OBJECT_STORE_MINIO_PROXY_SSL_CERT=.*|DMOD_OBJECT_STORE_MINIO_PROXY_SSL_CERT=${REPO_ROOT_DIR}/ssl/object_store/minio_proxy/public.crt|" | \
    sed "s|##* *DOCKER_HOST_IMAGE_STORE=.*|DOCKER_HOST_IMAGE_STORE=${REPO_ROOT_DIR}/docker_host_volumes/images|" | \
    sed "s|##* *DOCKER_VOL_DOMAINS=.*|DOCKER_VOL_DOMAINS=${REPO_ROOT_DIR}/docker_host_volumes/domains|" | \
    sed "s|##* *DOCKER_GUI_HOST_VENV_DIR=.*|DOCKER_GUI_HOST_VENV_DIR=${REPO_ROOT_DIR}/docker_host_volumes/virtual_envs/gui_venv|" | \
    sed "s|##* *DOCKER_INTERNAL_REGISTRY_STACK_CONFIG=.*|DOCKER_INTERNAL_REGISTRY_STACK_CONFIG=${REPO_ROOT_DIR}/docker/dev_registry_stack/docker-registry.yml|" | \
    sed "s|##* *DOCKER_GUI_WEB_SERVER_CONFIG_FILE=.*|DOCKER_GUI_WEB_SERVER_CONFIG_FILE=${REPO_ROOT_DIR}/docker/nwm_gui/web_server/nginx/default.conf|" | \
    sed "s|##* *REDIS_CONF_DIR=.*|REDIS_CONF_DIR=${REPO_ROOT_DIR}/docker/main/myredis|" | \
    sed "s|##* *DOCKER_REDIS_SECRET_FILE=.*|DOCKER_REDIS_SECRET_FILE=${REPO_ROOT_DIR}/docker/secrets/myredis_password.txt|" | \
    sed "s|##* *DMOD_OBJECT_STORE_ADMIN_USER_NAME_SECRET_FILE=.*|DMOD_OBJECT_STORE_ADMIN_USER_NAME_SECRET_FILE=${REPO_ROOT_DIR}/docker/secrets/object_store/access_key|" | \
    sed "s|##* *DMOD_OBJECT_STORE_ADMIN_USER_PASSWD_SECRET_FILE=.*|DMOD_OBJECT_STORE_ADMIN_USER_PASSWD_SECRET_FILE=${REPO_ROOT_DIR}/docker/secrets/object_store/secret_key|" | \
    sed "s|##* *DMOD_OBJECT_STORE_EXEC_USER_NAME_SECRET_FILE=.*|DMOD_OBJECT_STORE_EXEC_USER_NAME_SECRET_FILE=${REPO_ROOT_DIR}/docker/secrets/object_store/model_exec_access_key|" | \
    sed "s|##* *DMOD_OBJECT_STORE_EXEC_USER_PASSWD_SECRET_FILE=.*|DMOD_OBJECT_STORE_EXEC_USER_PASSWD_SECRET_FILE=${REPO_ROOT_DIR}/docker/secrets/object_store/model_exec_secret_key|" | \
    sed "s|##* *DOCKER_REDIS_SECRET_FILE=.*|DOCKER_REDIS_SECRET_FILE=${REPO_ROOT_DIR}/docker/secrets/myredis_password.txt|" | \
    sed "s|##* *DMOD_OBJECT_STORE_PROXY_TEMPLATES_DIR=.*|DMOD_OBJECT_STORE_PROXY_TEMPLATES_DIR=${REPO_ROOT_DIR}/docker/object_store/nginx_config_templates|" | \
    sed "s|##* *DMOD_OBJECT_STORE_PROXY_CONFIG=.*|DMOD_OBJECT_STORE_PROXY_CONFIG=${REPO_ROOT_DIR}/docker/object_store/nginx-docker-desktop.conf|" | \
    sed "s|##* *DMOD_APP_STATIC=.*|DMOD_APP_STATIC=${REPO_ROOT_DIR}/python/gui/static|" | \
    sed "s|##* *NGEN_BUILD_PARALLEL_JOBS=.*|NGEN_BUILD_PARALLEL_JOBS=${JOBS_CPU_COUNT?Missing jobs CPU count}|" | \
    sed "s|##* *SCHEDULER_RESOURCE_DIR=.*|SCHEDULER_RESOURCE_DIR=${REPO_ROOT_DIR}/data/scheduler_service|" | \
    sed "s|##* *DMOD_OBJECT_STORE_SINGLE_NODE_HOST_DIR=.*|DMOD_OBJECT_STORE_SINGLE_NODE_HOST_DIR=${REPO_ROOT_DIR}/docker_host_volumes/dmod_object_store|" > ${OUTPUT_ENV}


source ${OUTPUT_ENV}

should find its way into a language that doesn't rely on things such as output streams and redirection and more closely matches the language that all of this project is built on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants