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

Feat: LazyLibrarian #772

Open
wants to merge 63 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
94df860
Update .gitignore
Aethaeran Aug 18, 2021
965e0f7
Create lazylibrarian.sh
Aethaeran Aug 19, 2021
08a33a7
added reference to jdownloader script
Aethaeran Aug 19, 2021
d31a18e
add `box list` description
Aethaeran Aug 19, 2021
512f655
Create remove/lazylibrarian.sh
Aethaeran Aug 19, 2021
dbde969
Create nginx/lazylibrarian.sh
Aethaeran Aug 19, 2021
25d5a03
Update lazylibrarian.sh
Aethaeran Aug 19, 2021
4f97338
Update lazylibrarian.sh
Aethaeran Aug 19, 2021
9d8e226
Update remove/jdownloader.sh
Aethaeran Aug 19, 2021
17b2434
Update install/lazylibrarian.sh
Aethaeran Aug 19, 2021
a7ecd1e
Update lazylibrarian.sh
Aethaeran Aug 19, 2021
92ac221
Update lazylibrarian.sh
Aethaeran Aug 19, 2021
ad38aa2
not gonna configure multi-users after all. Toss that
Aethaeran Aug 19, 2021
ba1728b
add todo about venv. Looks like it has some dependencies after all
Aethaeran Aug 19, 2021
700547b
Update nginx
Aethaeran Aug 20, 2021
67ac363
Update remove
Aethaeran Aug 20, 2021
5c210bf
Update install
Aethaeran Aug 20, 2021
b9d45c1
Don't expand variables plox
Aethaeran Aug 20, 2021
5d28586
add "Web Root" aka "Base URL" setting
Aethaeran Aug 20, 2021
696b66c
Create test
Aethaeran Aug 20, 2021
46a7437
Update remove
Aethaeran Aug 20, 2021
9ea9d18
Update install
Aethaeran Aug 20, 2021
9933aae
some shellcheck diables, some TODOs, some TODOnes.
Aethaeran Aug 20, 2021
bea9534
add git auto_update to initial config
Aethaeran Aug 20, 2021
a56fee6
added simple logic to remove/lazylibrarian
Aethaeran Aug 20, 2021
fe3991f
simple logic to verify nginx conf needs creating in nginx/lazylibrari…
Aethaeran Aug 20, 2021
d8bc91e
add logic to exit if git clone fails
Aethaeran Aug 20, 2021
8c8c844
save database and config to master user's .config for easier backup\r…
Aethaeran Aug 20, 2021
3749dbb
now utilizes venv
Aethaeran Aug 20, 2021
93447ae
remove making vev_dir ahead of time. Unnecessary
Aethaeran Aug 21, 2021
e46c27f
Update imports to include shellcheck source directive
Aethaeran Aug 21, 2021
2d650e8
$PIP -> $pip_reqs, as per review
Aethaeran Aug 21, 2021
a17c1d0
add a non-recusrive chown on config_dir so it won't be owned by root,…
Aethaeran Aug 21, 2021
18d5fe0
feat: environment variables, formatting
flying-sausages Aug 22, 2021
b979a12
fix: double-slash
flying-sausages Aug 22, 2021
de05d97
fix: echos
flying-sausages Aug 22, 2021
c24d268
fix: one-line ExecStart so we can run `sed` on it later
flying-sausages Aug 22, 2021
2784b8a
style: clean up comments
flying-sausages Aug 22, 2021
2401dde
fix: perms
flying-sausages Aug 22, 2021
a79210e
fix: shfmt
flying-sausages Aug 22, 2021
6015bac
fix: entire remover
flying-sausages Aug 22, 2021
8b5d2b1
fix: nginx script
flying-sausages Aug 22, 2021
374ee9a
fix: test
flying-sausages Aug 22, 2021
847ac42
Revert "fix: test"
Aethaeran Aug 22, 2021
ec31166
Revert "fix: nginx script"
Aethaeran Aug 22, 2021
e84d184
Revert "fix: entire remover"
Aethaeran Aug 22, 2021
68194cb
Revert "style: clean up comments"
Aethaeran Aug 22, 2021
e615feb
Revert "fix: one-line ExecStart so we can run `sed` on it later"
Aethaeran Aug 22, 2021
f2888fe
added journalctl test
Aethaeran Aug 24, 2021
7a2a291
Update test/lazylibrarian.sh
Aethaeran Aug 24, 2021
972e44b
Update test
Aethaeran Aug 24, 2021
62df1c9
Fix missing pip, and add download_dir
Aethaeran Aug 24, 2021
e1d9283
general restructuring
Aethaeran Aug 24, 2021
f854bd8
Moved _get_app_owner logic to sources/functions/users
Aethaeran Aug 24, 2021
8e8b385
Fix useless cat
Aethaeran Aug 24, 2021
d039401
fix typo
Aethaeran Aug 24, 2021
0013c1c
Update users
Aethaeran Aug 25, 2021
e1fa9fa
Added PIDFile to service
Aethaeran Aug 25, 2021
54cbadd
Maybe that cat wasn't useless after all
Aethaeran Aug 25, 2021
8d5f874
couple comments
Aethaeran Aug 31, 2021
594a4a8
Removed TODOones. shortend references.
Aethaeran Aug 31, 2021
8f71be7
Merge branch 'develop' into feat/lazy-librarian
Aethaeran Aug 31, 2021
3f4ea11
add TODOs
Aethaeran Aug 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.dev.lock
.idea/**
.test.lock
dev.env
147 changes: 147 additions & 0 deletions scripts/install/lazylibrarian.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#!/bin/bash
# LazyLibrarian install script for swizzin
# Author: Aethaeran

##########################################################################
# References
##########################################################################

# https://lazylibrarian.gitlab.io/install/
# https://lazylibrarian.gitlab.io/config_commandline/
# https://www.reddit.com/r/LazyLibrarian/comments/jw5e22/lazylibrarian_calibre_calibreweb_booksonic/

##########################################################################
# Import Sources
##########################################################################

#shellcheck source=sources/functions/pyenv
. /etc/swizzin/sources/functions/pyenv
#shellcheck source=sources/functions/users
. /etc/swizzin/sources/functions/users
#shellcheck source=sources/functions/tests
. /etc/swizzin/sources/functions/tests
#shellcheck source=sources/functions/swizdb
. /etc/swizzin/sources/functions/swizdb

##########################################################################
# Variables
##########################################################################

app_name="lazylibrarian"
user="$(_get_app_owner "$app_name" "$LAZYLIB_OWNER")"
pretty_name="LazyLibrarian"
default_port="5299"
config_dir="/home/$user/.config"
data_dir="$config_dir/lazylibrarian"
app_dir="/opt/$app_name"
venv_dir="/opt/.venv/$app_name"
pip_reqs='urllib3 apprise Pillow pyOpenSSL'
# TODO: This should probably use swizdb and an ENV_VAR as well.
download_dir="/home/$user/Downloads/$pretty_name"

##########################################################################
# Functions
##########################################################################

function _dependencies() {
apt_install "python3-venv" # Ensure pip is installed. Required for Ubuntu Focal.
python3_venv "$user" "$app_name" # Create venv
chown -R "$user": "$venv_dir" # Ensure venv's owner is app's owner
echo_progress_start "Installing pip dependencies for $pretty_name"
# shellcheck disable=2154 # log variable is inherited from box itself.
"$venv_dir/bin/pip" install --upgrade pip >>"${log}" 2>&1 # Ensure pip is updated.
# shellcheck disable=2086 # We want the $pip_reqs variable to expand. So 2086's warning is invalid here.
"$venv_dir/bin/pip" install $pip_reqs >>"${log}" 2>&1 # Add required/wanted Python libraries
echo_progress_done
}

function _install() {
echo_progress_start "Cloning $pretty_name source"
mkdir -p "$app_dir" # Ensure app dir exists.
mkdir -p "$data_dir" # Ensure data dir exists.
# shellcheck disable=2154 # log variable is inherited from box itself.
git clone "https://gitlab.com/LazyLibrarian/LazyLibrarian.git" "$app_dir" >>"$log" 2>&1
if [[ ! -e "$app_dir/LazyLibrarian.py" ]]; then # Check if git clone failed.
echo_error "Git clone unsuccessful."
exit 1
fi
chown "$user": "$config_dir" # Ensure correct owner\group on config_dir
chown -R "$user": "$app_dir" # Change owner\group recursively for new dirs.
chown -R "$user": "$data_dir"
echo_progress_done "Source cloned"
}

function _configure() {
echo_info "Creating $download_dir as $pretty_name's default download directory."
mkdir -p "$download_dir" # Ensure download dir exists
chown -R "$user": "$download_dir" # Ensure download dir has the correct owner
echo_progress_done

echo_progress_start "Configuring $pretty_name"
cat >"$data_dir/config.ini" <<EOF
[General]
http_root = /$app_name
download_dir = $download_dir

[Git]
auto_update = 1
EOF
echo_progress_done
}

function _systemd() {
echo_progress_start "Creating $pretty_name systemd service"
cat >"/etc/systemd/system/$app_name.service" <<EOF
[Unit]
Description=LazyLibrarian
After=network.target

[Service]
User=$user
Group=$user
Type=forking
ExecStart=$venv_dir/bin/python3 \
$app_dir/LazyLibrarian.py \
--daemon \
--pidfile $data_dir/pidfile \
--nolaunch \
--datadir $data_dir
PIDFile=$data_dir/pidfile
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload # Reload daemons whenever a systemd service is changed
systemctl enable --quiet --now "$app_name" # Enable systemd service for app
echo_progress_done
}

function _nginx() {
if [[ -f /install/.nginx.lock ]]; then
echo_progress_start "Installing $app_name's nginx configuration"
bash "/usr/local/bin/swizzin/nginx/$app_name.sh"
# shellcheck disable=2154 # log variable is inherited from box itself.
systemctl reload nginx >>"$log" 2>&1
echo_progress_done
else
echo_info "$pretty_name will run on port $default_port"
echo_info "Please make sure to finalize $pretty_name's configuration in it's web interface\nhttp://127.0.0.1:$(get_port "$app_name")/$app_name"
fi
}

function _finishing_touch() {
touch "/install/.$app_name.lock" # Create lock file so that swizzin knows the app is installed.
echo_success "$pretty_name installed." # Winner winner. Chicken dinner.
}

##########################################################################
# Main
##########################################################################

_dependencies
_install
_configure
_systemd
_nginx
_finishing_touch
36 changes: 36 additions & 0 deletions scripts/nginx/lazylibrarian.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash
# LazyLibrarian nginx script for swizzin
# Author: Aethaeran

##########################################################################
# Import Sources
##########################################################################

. /etc/swizzin/sources/functions/utils

##########################################################################
# Variables
##########################################################################

app_name="lazylibrarian"
pretty_name="LazyLibrarian"
nginx_conf="/etc/nginx/apps/$app_name.conf"

##########################################################################
# Main
##########################################################################

if [[ ! -e "$nginx_conf" ]]; then
cat > "$nginx_conf" << 'EOF'
location /lazylibrarian {
proxy_bind $server_addr;
proxy_pass http://127.0.0.1:5299;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Script-Name /lazylibrarian; # IMPORTANT: path has NO trailing slash
}
EOF
else
echo_info "$pretty_name's nginx configuration already existed."
fi
82 changes: 82 additions & 0 deletions scripts/remove/lazylibrarian.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/bin/bash
# LazyLibrarian remove script for swizzin
# Author: Aethaeran

##########################################################################
# Import Sources
##########################################################################

. /etc/swizzin/sources/functions/utils

##########################################################################
# Variables
##########################################################################

app_name="lazylibrarian"
pretty_name="LazyLibrarian"
app_dir="/opt/$app_name"
user="$(_get_app_owner "$app_name" "$LAZYLIB_OWNER")"
config_dir="/home/$user/.config/$app_name"
venv_dir="/opt/.venv/$app_name"

##########################################################################
# Main
##########################################################################

# TODO: Make sure these haven't changed since installation, as to avoid removing custom configs

if [[ -e "$venv_dir" ]]; then
echo_progress_start "Removing $pretty_name venv..."
# shellcheck disable=2154 # log variable is inherited from box itself.
rm -rv "$venv_dir" >> "$log" 2>&1
echo_progress_done
else
echo_info "$pretty_name venv_dir didn't exist."
fi

if [[ -e "$app_dir" ]]; then
echo_progress_start "Removing $pretty_name installation..."
# shellcheck disable=2154 # log variable is inherited from box itself.
rm -rv "$app_dir" >> "$log" 2>&1
echo_progress_done
else
echo_info "$pretty_name app_dir didn't exist."
fi

if [[ -e "$config_dir" ]]; then
echo_progress_start "Removing $pretty_name configuration..."
rm -rv "$config_dir" >> "$log" 2>&1
echo_progress_done
else
echo_info "$pretty_name config_dir didn't exist."
fi

if [[ -e "/etc/systemd/system/$app_name.service" ]]; then
echo_progress_start "Removing $pretty_name systemd service..."
if [[ $(systemctl is-active "$app_name") == "active" ]]; then
systemctl stop "$app_name" --quiet
fi
if [[ $(systemctl is-enabled "$app_name") == "enabled" ]]; then
systemctl disable "$app_name" --quiet
fi
rm -v "/etc/systemd/system/$app_name.service" >> "$log" 2>&1
echo_progress_done
else
echo_info "$pretty_name systemd service didn't exist."
fi

if [[ -e "/etc/nginx/apps/$app_name.conf" ]]; then
echo_progress_start "Removing $pretty_name nginx configuration..."
rm -v "/etc/nginx/apps/$app_name.conf" >> "$log" 2>&1
echo_progress_done
else
echo_info "$pretty_name nginx configuration didn't exist."
fi

if [[ -e "/install/.$app_name.lock" ]]; then
echo_progress_start "Removing $pretty_name lock..."
rm -v "/install/.$app_name.lock" >> "$log" 2>&1
echo_progress_done
else
echo_info "$pretty_name lock didn't exist."
fi
87 changes: 87 additions & 0 deletions scripts/tests/lazylibrarian.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/env bash
# LazyLibrarian test script for swizzin
# Author: Aethaeran

# box remove lazylibrarian && box install lazylibrarian && sleep 10 && box test lazylibrarian

##########################################################################
# References
##########################################################################

# https://github.com/swizzin/swizzin/blob/master/scripts/tests/_basetest.sh

##########################################################################
# Import Sources
##########################################################################

#shellcheck source=sources/functions/tests
. /etc/swizzin/sources/functions/tests

##########################################################################
# Variables
##########################################################################

app_name="lazylibrarian"
pretty_name="LazyLibrarian"

##########################################################################
# Functions
##########################################################################

# TODO: Is this curl change necessary? Maybe I just did the nginx configuration incorrectly.

function _check_port_curl() {
echo_progress_start "Checking if port $1 is reachable via curl"
if [ "$1" -eq "$1" ] 2>/dev/null; then
port=$1
else
port=$(get_port "$1") || {
echo_warn "Couldn't guess port"
return 1
}
fi
extra_params="$2"
# shellcheck disable=SC2086 # We want splitting on the extra params variable. So the warning is void here.
curl -sSfLk $extra_params http://127.0.0.1:"$port/$app_name" -o /dev/null || {
echo_warn "Querying http://127.0.0.1:$port/$app_name failed"
echo
return 1
}
echo_progress_done
}

function _check_journalctl() {
echo_progress_start "Checking if $pretty_name is throwing errors in it's service log."
journal_log="$(journalctl -xeu $app_name)"
found="false"
if [[ "$journal_log" == *"WARNING"* ]]; then
echo_warn "$pretty_name systemd service is throwing the following WARNINGs:"
journalctl -xeu $app_name | grep "WARNING"
found="true"
fi
if [[ "$journal_log" == *"ERROR"* ]]; then
echo_warn "$pretty_name systemd service is throwing an ERRORs:"
journalctl -xeu $app_name | grep "ERROR"
found="true"
fi
if [[ "$found" == "true" ]]; then
return 1
else
echo_info "$pretty_name service is NOT throwing any warnings or errors."
fi
echo_progress_done
}

##########################################################################
# Main
##########################################################################

# run all functions, if one fails, mark as bad
check_service "$app_name" || BAD="true"
check_port "$app_name" || BAD="true"
_check_port_curl "$app_name" || BAD="true"
check_nginx "$app_name" || BAD="true"
# shellcheck disable=SC2034 # $BAD is used in evaluate_bad. So the warning is void here.
_check_journalctl || BAD="true"

evaluate_bad
24 changes: 23 additions & 1 deletion sources/functions/users
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function _get_user_password() {
export -f _get_user_password

# OLD way to get users from htpasswd
# Rather wouldn't use this as 3rd party applications migh be playing with this as well
# Rather wouldn't use this as 3rd party applications might be playing with this as well
# function _get_user_list () {
# users=($(cut -d: -f1 < /etc/htpasswd))
# }
Expand Down Expand Up @@ -186,3 +186,25 @@ function username_check() {
fi
echo_log_only "Username_check returned"
}

# 1=app_name
# 2=app_owner
_set_app_owner() {
echo_log_only "Setting ${1^} owner = $2"
swizdb set "$1/owner" "$2"
}

# 1=app_name
# 2=ENV_VAR
# _get_app_owner $app_name something
_get_app_owner() {
if [ -z "$2" ]; then # If ENV_VAR isn't set
if [[ -z "$(swizdb get "$1/owner")" ]]; then # and if swizdb doesn't already have an owner
master="$(_get_master_username)" # Get master swizzin username
_set_app_owner "$1" "$master" # Set master as owner of app in swizdb
fi
else # If ENV_VAR is set
_set_app_owner "$1" "$2" # Save ENV_VAR as app owner in swizdb
fi
swizdb get "$1/owner" # Return swizdb entry
}