mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-04 22:39:46 +00:00
Merge branch 'next/minor' of github.com:Start9Labs/start-os into next/major
This commit is contained in:
@@ -1,5 +1,33 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Wireguard VPS Proxy Setup
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# This script automates the setup of a WireGuard VPN server on a remote VPS
|
||||||
|
# for StartOS Clearnet functionality. It handles:
|
||||||
|
#
|
||||||
|
# 1. SSH key-based authentication setup
|
||||||
|
# 2. Root access configuration (if needed)
|
||||||
|
# 3. WireGuard server installation
|
||||||
|
# 4. Configuration file generation and import
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# wireguard-vps-proxy-setup [-h] [-i IP] [-u USERNAME] [-p PORT] [-k SSH_KEY]
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# -h Show help message
|
||||||
|
# -i VPS IP address
|
||||||
|
# -u SSH username (default: root)
|
||||||
|
# -p SSH port (default: 22)
|
||||||
|
# -k Path to custom SSH private key
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# wireguard-vps-proxy-setup -i 110.18.1.1 -u debian
|
||||||
|
#
|
||||||
|
# Note: This script requires root privileges and will auto-elevate if needed.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
# Colors for better output
|
# Colors for better output
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
@@ -8,7 +36,7 @@ YELLOW='\033[1;33m'
|
|||||||
NC='\033[0;37m' # No Color
|
NC='\033[0;37m' # No Color
|
||||||
|
|
||||||
# --- Constants ---
|
# --- Constants ---
|
||||||
readonly WIREGUARD_INSTALL_URL="https://raw.githubusercontent.com/start9labs/wg-vps-setup/master/wireguard-install.sh"
|
readonly WIREGUARD_INSTALL_URL="https://raw.githubusercontent.com/start9labs/wireguard-vps-proxy-setup/master/wireguard-install.sh"
|
||||||
readonly SSH_KEY_DIR="/home/start9/.ssh"
|
readonly SSH_KEY_DIR="/home/start9/.ssh"
|
||||||
readonly SSH_KEY_NAME="id_ed25519"
|
readonly SSH_KEY_NAME="id_ed25519"
|
||||||
readonly SSH_PRIVATE_KEY="$SSH_KEY_DIR/$SSH_KEY_NAME"
|
readonly SSH_PRIVATE_KEY="$SSH_KEY_DIR/$SSH_KEY_NAME"
|
||||||
@@ -31,7 +59,7 @@ check_root() {
|
|||||||
print_banner() {
|
print_banner() {
|
||||||
echo -e "${BLUE}"
|
echo -e "${BLUE}"
|
||||||
echo "================================================"
|
echo "================================================"
|
||||||
echo -e " ${NC}StartOS WireGuard VPS Setup Tool${BLUE} "
|
echo -e " ${NC}Wireguard VPS Proxy Setup${BLUE} "
|
||||||
echo "================================================"
|
echo "================================================"
|
||||||
echo -e "${NC}"
|
echo -e "${NC}"
|
||||||
}
|
}
|
||||||
@@ -51,23 +79,53 @@ print_usage() {
|
|||||||
# Function to display end message
|
# Function to display end message
|
||||||
display_end_message() {
|
display_end_message() {
|
||||||
echo -e "\n${BLUE}------------------------------------------------------------------${NC}"
|
echo -e "\n${BLUE}------------------------------------------------------------------${NC}"
|
||||||
echo -e "${NC}WireGuard server setup complete!"
|
echo -e "${GREEN}Wireguard VPS Proxy server setup complete!${NC}"
|
||||||
echo -e "${BLUE}------------------------------------------------------------------${NC}"
|
|
||||||
echo -e "\n${YELLOW}To expose your services to the Clearnet, use the following commands on your StartOS system (replace placeholders):${NC}"
|
|
||||||
echo -e "\n ${YELLOW}1. Initialize ACME (This only needs to be done once):${NC}"
|
|
||||||
echo " start-cli net acme init --provider=letsencrypt --contact=mailto:your-email@example.com"
|
|
||||||
echo -e "\n ${YELLOW}2. Expose 'hello-world' on port 80 through VPS:${NC}"
|
|
||||||
echo " start-cli package host hello-world binding ui-multi set-public 80"
|
|
||||||
echo -e "\n ${YELLOW}3. Add a domain to your 'hello-world' service:${NC}"
|
|
||||||
echo " start-cli package host hello-world address ui-multi domain add your-domain.example.com --acme=letsencrypt"
|
|
||||||
echo -e "\n ${YELLOW}Replace '${NC}your-email@example.com${YELLOW}' with your actual email address, '${NC}your-domain.example.com${YELLOW}' with your actual domain and '${NC}hello-world${YELLOW}' with your actual service id.${NC}"
|
|
||||||
echo -e "${BLUE}------------------------------------------------------------------${NC}"
|
echo -e "${BLUE}------------------------------------------------------------------${NC}"
|
||||||
|
echo -e "\n${GREEN}Clearnet functionality has been enabled via VPS (${VPS_IP})${NC}"
|
||||||
|
echo -e "\n${YELLOW}Next steps:${NC}"
|
||||||
|
echo -e "Visit https://docs.start9.com to complete the Clearnet setup"
|
||||||
|
echo -e "\n${BLUE}------------------------------------------------------------------${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to validate IP address
|
# Function to validate IP address
|
||||||
validate_ip() {
|
validate_ip() {
|
||||||
local ip=$1
|
local ip=$1
|
||||||
|
# IPv4 validation
|
||||||
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||||
|
# Additional IPv4 validation to ensure each octet is <= 255
|
||||||
|
local IFS='.'
|
||||||
|
read -ra ADDR <<< "$ip"
|
||||||
|
for i in "${ADDR[@]}"; do
|
||||||
|
if [ "$i" -gt 255 ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
# IPv6 validation
|
||||||
|
elif [[ $ip =~ ^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){6}:[0-9a-fA-F]{1,4}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){5}(:[0-9a-fA-F]{1,4}){1,2}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){4}(:[0-9a-fA-F]{1,4}){1,3}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){3}(:[0-9a-fA-F]{1,4}){1,4}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){2}(:[0-9a-fA-F]{1,4}){1,5}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1}(:[0-9a-fA-F]{1,4}){1,6}$ ]] || \
|
||||||
|
[[ $ip =~ ^::([0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$ ]] || \
|
||||||
|
[[ $ip =~ ^[0-9a-fA-F]{1,4}::([0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,4}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,3}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,2}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,1}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,7}:$ ]] || \
|
||||||
|
[[ $ip =~ ^::([0-9a-fA-F]{1,4}:){0,7}[0-9a-fA-F]{1,4}$ ]] || \
|
||||||
|
[[ $ip =~ ^[0-9a-fA-F]{1,4}::([0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,6}(:[0-9a-fA-F]{1,4}){1,1}$ ]] || \
|
||||||
|
[[ $ip =~ ^([0-9a-fA-F]{1,4}:){1,7}:$ ]] || \
|
||||||
|
[[ $ip =~ ^::$ ]]; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
@@ -90,6 +148,15 @@ configure_ssh_key_auth() {
|
|||||||
echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config
|
echo "PubkeyAuthentication yes" >> /etc/ssh/sshd_config
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Enable root login
|
||||||
|
if grep -q "^#PermitRootLogin" /etc/ssh/sshd_config; then
|
||||||
|
sed -i "s/^#PermitRootLogin.*/PermitRootLogin yes/" /etc/ssh/sshd_config
|
||||||
|
elif grep -q "^PermitRootLogin" /etc/ssh/sshd_config; then
|
||||||
|
sed -i "s/^PermitRootLogin.*/PermitRootLogin yes/" /etc/ssh/sshd_config
|
||||||
|
else
|
||||||
|
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
|
||||||
|
fi
|
||||||
|
|
||||||
# Configure AuthorizedKeysFile if needed
|
# Configure AuthorizedKeysFile if needed
|
||||||
if grep -q "^#AuthorizedKeysFile" /etc/ssh/sshd_config; then
|
if grep -q "^#AuthorizedKeysFile" /etc/ssh/sshd_config; then
|
||||||
sed -i "s/^#AuthorizedKeysFile.*/AuthorizedKeysFile .ssh\/authorized_keys .ssh\/authorized_keys2/" /etc/ssh/sshd_config
|
sed -i "s/^#AuthorizedKeysFile.*/AuthorizedKeysFile .ssh\/authorized_keys .ssh\/authorized_keys2/" /etc/ssh/sshd_config
|
||||||
@@ -203,7 +270,7 @@ install_wireguard() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Run the remote install script and let it complete
|
# Run the remote install script and let it complete
|
||||||
if ! ssh -o ConnectTimeout=60 -i "$SSH_PRIVATE_KEY" -o StrictHostKeyChecking=no -p "$SSH_PORT" -t "$SSH_USER@$VPS_IP" "bash -c 'export TERM=xterm-256color; export STARTOS_HOSTNAME=$(hostname); bash ~/wireguard-install.sh'"; then
|
if ! ssh -o ConnectTimeout=60 -i "$SSH_PRIVATE_KEY" -o StrictHostKeyChecking=no -p "$SSH_PORT" -t "$SSH_USER@$VPS_IP" "bash -c 'export TERM=xterm-256color; export STARTOS_HOSTNAME=clearnet; bash ~/wireguard-install.sh'"; then
|
||||||
echo -e "${RED}WireGuard installation failed on remote server.${NC}"
|
echo -e "${RED}WireGuard installation failed on remote server.${NC}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -218,6 +285,74 @@ install_wireguard() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Function to enable root login via SSH
|
||||||
|
enable_root_login() {
|
||||||
|
echo -e "${BLUE}Checking and configuring root SSH access...${NC}"
|
||||||
|
|
||||||
|
# Try to modify sshd config using sudo
|
||||||
|
if ! ssh -i "$SSH_PRIVATE_KEY" -o StrictHostKeyChecking=no -p "$SSH_PORT" "$SSH_USER@$VPS_IP" '
|
||||||
|
# Check if we can use sudo without password
|
||||||
|
if ! sudo -n true 2>/dev/null; then
|
||||||
|
echo -e "\033[1;33mNOTE: You may be prompted for your sudo password.\033[0m"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if user is in sudo group
|
||||||
|
if ! groups | grep -q sudo; then
|
||||||
|
echo -e "\033[1;31mError: Your user is not in the sudo group. Root access cannot be configured.\033[0m"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup sshd config
|
||||||
|
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
|
||||||
|
|
||||||
|
# Enable root login with SSH keys only
|
||||||
|
if sudo grep -q "^PermitRootLogin" /etc/ssh/sshd_config; then
|
||||||
|
sudo sed -i "s/^PermitRootLogin.*/PermitRootLogin prohibit-password/" /etc/ssh/sshd_config
|
||||||
|
else
|
||||||
|
echo "PermitRootLogin prohibit-password" | sudo tee -a /etc/ssh/sshd_config
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure password authentication is disabled
|
||||||
|
if sudo grep -q "^PasswordAuthentication" /etc/ssh/sshd_config; then
|
||||||
|
sudo sed -i "s/^PasswordAuthentication.*/PasswordAuthentication no/" /etc/ssh/sshd_config
|
||||||
|
else
|
||||||
|
echo "PasswordAuthentication no" | sudo tee -a /etc/ssh/sshd_config
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set up root SSH directory and keys
|
||||||
|
echo -e "\033[1;33mSetting up root SSH access...\033[0m"
|
||||||
|
sudo mkdir -p /root/.ssh
|
||||||
|
sudo cp ~/.ssh/authorized_keys /root/.ssh/
|
||||||
|
sudo chown -R root:root /root/.ssh
|
||||||
|
sudo chmod 700 /root/.ssh
|
||||||
|
sudo chmod 600 /root/.ssh/authorized_keys
|
||||||
|
|
||||||
|
# Reload SSH service
|
||||||
|
sudo systemctl reload sshd
|
||||||
|
|
||||||
|
# Verify the changes
|
||||||
|
if ! sudo grep -q "^PermitRootLogin prohibit-password" /etc/ssh/sshd_config; then
|
||||||
|
echo -e "\033[1;31mError: Failed to verify root login configuration.\033[0m"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test root SSH access
|
||||||
|
if ! sudo -n true 2>/dev/null; then
|
||||||
|
echo -e "\033[1;33mNOTE: Please try to log in as root now using your SSH key.\033[0m"
|
||||||
|
echo -e "\033[1;33mIf successful, run this script again without the -u parameter.\033[0m"
|
||||||
|
else
|
||||||
|
echo -e "\033[1;32mRoot SSH access has been configured successfully!\033[0m"
|
||||||
|
fi
|
||||||
|
'; then
|
||||||
|
echo -e "${RED}Failed to configure root SSH access.${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Root SSH access has been configured successfully!${NC}"
|
||||||
|
echo -e "${YELLOW}Please try to log in as root now using your SSH key. If successful, run this script again without the -u parameter.${NC}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# --- Main Script ---
|
# --- Main Script ---
|
||||||
# Initialize variables
|
# Initialize variables
|
||||||
VPS_IP=""
|
VPS_IP=""
|
||||||
@@ -311,27 +446,80 @@ echo -e "${GREEN}SSH key-based authentication configured successfully!${NC}"
|
|||||||
|
|
||||||
# Test SSH connection using key-based authentication
|
# Test SSH connection using key-based authentication
|
||||||
echo -e "\nTesting SSH connection with key-based authentication..."
|
echo -e "\nTesting SSH connection with key-based authentication..."
|
||||||
if ! ssh -q -o BatchMode=yes -o ConnectTimeout=5 -i "$SSH_PRIVATE_KEY" -o StrictHostKeyChecking=no -p "$SSH_PORT" "$SSH_USER@$VPS_IP" 'grep -q "^PubkeyAuthentication yes" /etc/ssh/sshd_config'; then
|
if ! ssh -q -o BatchMode=yes -o ConnectTimeout=5 -i "$SSH_PRIVATE_KEY" -o StrictHostKeyChecking=no -p "$SSH_PORT" "$SSH_USER@$VPS_IP" 'exit'; then
|
||||||
echo -e "\n${RED}SSH key-based authentication is not enabled on your VPS.${NC}"
|
echo -e "${RED}SSH connection test failed. Please check your credentials and try again.${NC}"
|
||||||
echo -e "\n${YELLOW}Would you like this script to automatically enable SSH key authentication? (y/N):${NC} "
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If we're connecting as a non-root user, set up root access first
|
||||||
|
if [ "$SSH_USER" != "root" ]; then
|
||||||
|
echo -e "\n${YELLOW}You are connecting as a non-root user. This script needs to enable root SSH access.${NC}"
|
||||||
|
echo -e "${YELLOW}This is a one-time setup that will allow direct root login for WireGuard installation.${NC}"
|
||||||
|
echo -n -e "${YELLOW}Would you like to proceed? (y/N): ${NC}"
|
||||||
read -r answer
|
read -r answer
|
||||||
|
|
||||||
if [[ "$answer" =~ ^[Yy]$ ]]; then
|
if [[ "$answer" =~ ^[Yy]$ ]]; then
|
||||||
configure_ssh_key_auth
|
if enable_root_login; then
|
||||||
|
echo -e "\n${BLUE}------------------------------------------------------------------${NC}"
|
||||||
|
echo -e "${GREEN}Root SSH access has been configured successfully!${NC}"
|
||||||
|
echo -e "${YELLOW}Please run this script again without the -u parameter to continue setup.${NC}"
|
||||||
|
echo -e "${BLUE}------------------------------------------------------------------${NC}"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}Failed to configure root SSH access. Please check your sudo privileges and try again.${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "\n${BLUE}------------------------------------------------------------------${NC}"
|
echo -e "\n${BLUE}------------------------------------------------------------------${NC}"
|
||||||
echo -e "${YELLOW}To manually enable SSH key authentication:${NC}"
|
echo -e "${YELLOW}To manually configure SSH for root access:${NC}"
|
||||||
echo -e "\n ${YELLOW}1. Connect to your VPS and edit sshd_config:${NC}"
|
echo -e "\n ${YELLOW}1. Connect to your VPS and edit sshd_config:${NC}"
|
||||||
echo " nano /etc/ssh/sshd_config"
|
echo " sudo nano /etc/ssh/sshd_config"
|
||||||
echo -e "\n ${YELLOW}2. Find and uncomment or add the line:${NC}"
|
echo -e "\n ${YELLOW}2. Find and uncomment or add these lines:${NC}"
|
||||||
echo " PubkeyAuthentication yes"
|
echo " PubkeyAuthentication yes"
|
||||||
|
echo " PermitRootLogin yes"
|
||||||
|
echo " AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2"
|
||||||
echo -e "\n ${YELLOW}3. Restart the SSH service:${NC}"
|
echo -e "\n ${YELLOW}3. Restart the SSH service:${NC}"
|
||||||
echo " systemctl restart sshd"
|
echo " sudo systemctl restart sshd"
|
||||||
|
echo -e "\n ${YELLOW}4. Copy your SSH key to root user:${NC}"
|
||||||
|
echo " sudo mkdir -p /root/.ssh"
|
||||||
|
echo " sudo cp ~/.ssh/authorized_keys /root/.ssh/"
|
||||||
|
echo " sudo chown -R root:root /root/.ssh"
|
||||||
|
echo " sudo chmod 700 /root/.ssh"
|
||||||
|
echo " sudo chmod 600 /root/.ssh/authorized_keys"
|
||||||
echo -e "${BLUE}------------------------------------------------------------------${NC}"
|
echo -e "${BLUE}------------------------------------------------------------------${NC}"
|
||||||
echo -e "\n${YELLOW}Please enable SSH key authentication and run this script again.${NC}"
|
echo -e "\n${YELLOW}After completing these steps, run this script again without the -u parameter.${NC}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check if root login is permitted when connecting as root
|
||||||
|
if [ "$SSH_USER" = "root" ]; then
|
||||||
|
# Check for both "yes" and "prohibit-password" as valid root login settings
|
||||||
|
if ! ssh -q -o BatchMode=yes -o ConnectTimeout=5 -i "$SSH_PRIVATE_KEY" -o StrictHostKeyChecking=no -p "$SSH_PORT" "$SSH_USER@$VPS_IP" 'grep -q "^PermitRootLogin.*\(yes\|prohibit-password\)" /etc/ssh/sshd_config'; then
|
||||||
|
echo -e "\n${RED}Root SSH login is not enabled on your VPS.${NC}"
|
||||||
|
echo -e "\n${YELLOW}Would you like this script to automatically enable root SSH access? (y/N):${NC} "
|
||||||
|
read -r answer
|
||||||
|
|
||||||
|
if [[ "$answer" =~ ^[Yy]$ ]]; then
|
||||||
|
configure_ssh_key_auth
|
||||||
|
else
|
||||||
|
echo -e "\n${BLUE}------------------------------------------------------------------${NC}"
|
||||||
|
echo -e "${YELLOW}To manually configure SSH for root access:${NC}"
|
||||||
|
echo -e "\n ${YELLOW}1. Connect to your VPS and edit sshd_config:${NC}"
|
||||||
|
echo " sudo nano /etc/ssh/sshd_config"
|
||||||
|
echo -e "\n ${YELLOW}2. Find and uncomment or add these lines:${NC}"
|
||||||
|
echo " PubkeyAuthentication yes"
|
||||||
|
echo " PermitRootLogin prohibit-password"
|
||||||
|
echo " AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2"
|
||||||
|
echo -e "\n ${YELLOW}3. Restart the SSH service:${NC}"
|
||||||
|
echo " sudo systemctl restart sshd"
|
||||||
|
echo -e "${BLUE}------------------------------------------------------------------${NC}"
|
||||||
|
echo -e "\n${YELLOW}Please enable root SSH access and run this script again.${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo -e "${GREEN}SSH connection successful with key-based authentication!${NC}"
|
echo -e "${GREEN}SSH connection successful with key-based authentication!${NC}"
|
||||||
|
|
||||||
# Download the WireGuard install script locally
|
# Download the WireGuard install script locally
|
||||||
@@ -193,8 +193,8 @@ export function makeEffects(context: EffectContext): Effects {
|
|||||||
T.Effects["exposeForDependents"]
|
T.Effects["exposeForDependents"]
|
||||||
>
|
>
|
||||||
},
|
},
|
||||||
getContainerIp(...[]: Parameters<T.Effects["getContainerIp"]>) {
|
getContainerIp(...[options]: Parameters<T.Effects["getContainerIp"]>) {
|
||||||
return rpcRound("get-container-ip", {}) as ReturnType<
|
return rpcRound("get-container-ip", options) as ReturnType<
|
||||||
T.Effects["getContainerIp"]
|
T.Effects["getContainerIp"]
|
||||||
>
|
>
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { Manifest } from "./matchManifest"
|
|||||||
import { DockerProcedureContainer } from "./DockerProcedureContainer"
|
import { DockerProcedureContainer } from "./DockerProcedureContainer"
|
||||||
import * as cp from "child_process"
|
import * as cp from "child_process"
|
||||||
import { Effects } from "../../../Models/Effects"
|
import { Effects } from "../../../Models/Effects"
|
||||||
|
import { Mounts } from "@start9labs/start-sdk/package/lib/mainFn/Mounts"
|
||||||
export const execFile = promisify(cp.execFile)
|
export const execFile = promisify(cp.execFile)
|
||||||
export const polyfillEffects = (
|
export const polyfillEffects = (
|
||||||
effects: Effects,
|
effects: Effects,
|
||||||
@@ -111,7 +112,7 @@ export const polyfillEffects = (
|
|||||||
effects,
|
effects,
|
||||||
{ imageId: manifest.main.image },
|
{ imageId: manifest.main.image },
|
||||||
commands,
|
commands,
|
||||||
{},
|
{ mounts: Mounts.of() },
|
||||||
commands.join(" "),
|
commands.join(" "),
|
||||||
)
|
)
|
||||||
.then((x: any) => ({
|
.then((x: any) => ({
|
||||||
@@ -168,17 +169,12 @@ export const polyfillEffects = (
|
|||||||
{ imageId: manifest.main.image },
|
{ imageId: manifest.main.image },
|
||||||
commands,
|
commands,
|
||||||
{
|
{
|
||||||
mounts: [
|
mounts: Mounts.of().addVolume(
|
||||||
{
|
input.volumeId,
|
||||||
mountpoint: "/drive",
|
null,
|
||||||
options: {
|
"/drive",
|
||||||
type: "volume",
|
false,
|
||||||
id: input.volumeId,
|
),
|
||||||
subpath: null,
|
|
||||||
readonly: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
commands.join(" "),
|
commands.join(" "),
|
||||||
)
|
)
|
||||||
@@ -210,17 +206,12 @@ export const polyfillEffects = (
|
|||||||
{ imageId: manifest.main.image },
|
{ imageId: manifest.main.image },
|
||||||
commands,
|
commands,
|
||||||
{
|
{
|
||||||
mounts: [
|
mounts: Mounts.of().addVolume(
|
||||||
{
|
input.volumeId,
|
||||||
mountpoint: "/drive",
|
null,
|
||||||
options: {
|
"/drive",
|
||||||
type: "volume",
|
false,
|
||||||
id: input.volumeId,
|
),
|
||||||
subpath: null,
|
|
||||||
readonly: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
commands.join(" "),
|
commands.join(" "),
|
||||||
)
|
)
|
||||||
|
|||||||
906
core/Cargo.lock
generated
906
core/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@ pub use service_interface::ServiceInterfaceId;
|
|||||||
pub use volume::VolumeId;
|
pub use volume::VolumeId;
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref ID_REGEX: Regex = Regex::new("^[a-z]+(-[a-z0-9]+)*$").unwrap();
|
static ref ID_REGEX: Regex = Regex::new("^[a-z0-9]+(-[a-z0-9]+)*$").unwrap();
|
||||||
pub static ref SYSTEM_ID: Id = Id(InternedString::intern("x_system"));
|
pub static ref SYSTEM_ID: Id = Id(InternedString::intern("x_system"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ pub async fn login_impl(
|
|||||||
Ok(hash_token.to_login_res())
|
Ok(hash_token.to_login_res())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,6 +477,7 @@ pub async fn reset_password_impl(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ impl BackupStatusGuard {
|
|||||||
.as_backup_progress_mut()
|
.as_backup_progress_mut()
|
||||||
.ser(&None)
|
.ser(&None)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
}
|
}
|
||||||
if let Some(db) = self.0.take() {
|
if let Some(db) = self.0.take() {
|
||||||
match result {
|
match result {
|
||||||
@@ -124,7 +125,8 @@ impl BackupStatusGuard {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}?;
|
}
|
||||||
|
.result?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -141,6 +143,7 @@ impl Drop for BackupStatusGuard {
|
|||||||
.ser(&None)
|
.ser(&None)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
.log_err()
|
.log_err()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -187,7 +190,8 @@ pub async fn backup_all(
|
|||||||
db.as_public().as_server_info().as_id().de()?,
|
db.as_public().as_server_info().as_id().de()?,
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.await?,
|
.await
|
||||||
|
.result?,
|
||||||
BackupStatusGuard::new(ctx.db.clone()),
|
BackupStatusGuard::new(ctx.db.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -348,7 +352,8 @@ async fn perform_backup(
|
|||||||
.as_last_backup_mut()
|
.as_last_backup_mut()
|
||||||
.ser(&Some(timestamp))
|
.ser(&Some(timestamp))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
Ok(backup_report)
|
Ok(backup_report)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,8 @@ pub async fn add(
|
|||||||
db.as_private_mut().as_cifs_mut().insert(&id, &cifs)?;
|
db.as_private_mut().as_cifs_mut().insert(&id, &cifs)?;
|
||||||
Ok(id)
|
Ok(id)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(KeyVal {
|
Ok(KeyVal {
|
||||||
key: BackupTargetId::Cifs { id },
|
key: BackupTargetId::Cifs { id },
|
||||||
value: BackupTarget::Cifs(CifsBackupTarget {
|
value: BackupTarget::Cifs(CifsBackupTarget {
|
||||||
@@ -176,7 +177,8 @@ pub async fn update(
|
|||||||
})?
|
})?
|
||||||
.ser(&cifs)
|
.ser(&cifs)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(KeyVal {
|
Ok(KeyVal {
|
||||||
key: BackupTargetId::Cifs { id },
|
key: BackupTargetId::Cifs { id },
|
||||||
value: BackupTarget::Cifs(CifsBackupTarget {
|
value: BackupTarget::Cifs(CifsBackupTarget {
|
||||||
@@ -207,7 +209,8 @@ pub async fn remove(ctx: RpcContext, RemoveParams { id }: RemoveParams) -> Resul
|
|||||||
};
|
};
|
||||||
ctx.db
|
ctx.db
|
||||||
.mutate(|db| db.as_private_mut().as_cifs_mut().remove(&id))
|
.mutate(|db| db.as_private_mut().as_cifs_mut().remove(&id))
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ pub struct RpcContextSeed {
|
|||||||
pub lxc_manager: Arc<LxcManager>,
|
pub lxc_manager: Arc<LxcManager>,
|
||||||
pub open_authed_continuations: OpenAuthedContinuations<Option<InternedString>>,
|
pub open_authed_continuations: OpenAuthedContinuations<Option<InternedString>>,
|
||||||
pub rpc_continuations: RpcContinuations,
|
pub rpc_continuations: RpcContinuations,
|
||||||
pub callbacks: ServiceCallbacks,
|
pub callbacks: Arc<ServiceCallbacks>,
|
||||||
pub wifi_manager: Arc<RwLock<Option<WpaCli>>>,
|
pub wifi_manager: Arc<RwLock<Option<WpaCli>>>,
|
||||||
pub current_secret: Arc<Jwk>,
|
pub current_secret: Arc<Jwk>,
|
||||||
pub client: Client,
|
pub client: Client,
|
||||||
@@ -201,7 +201,8 @@ impl RpcContext {
|
|||||||
.ser(&true)
|
.ser(&true)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.result
|
||||||
|
.log_err();
|
||||||
})
|
})
|
||||||
.into(),
|
.into(),
|
||||||
)
|
)
|
||||||
@@ -229,6 +230,7 @@ impl RpcContext {
|
|||||||
sync_db: watch::Sender::new(db.sequence().await),
|
sync_db: watch::Sender::new(db.sequence().await),
|
||||||
db,
|
db,
|
||||||
account: RwLock::new(account),
|
account: RwLock::new(account),
|
||||||
|
callbacks: net_controller.callbacks.clone(),
|
||||||
net_controller,
|
net_controller,
|
||||||
os_net_service,
|
os_net_service,
|
||||||
s9pk_arch: if config.multi_arch_s9pks.unwrap_or(false) {
|
s9pk_arch: if config.multi_arch_s9pks.unwrap_or(false) {
|
||||||
@@ -243,7 +245,6 @@ impl RpcContext {
|
|||||||
lxc_manager: Arc::new(LxcManager::new()),
|
lxc_manager: Arc::new(LxcManager::new()),
|
||||||
open_authed_continuations: OpenAuthedContinuations::new(),
|
open_authed_continuations: OpenAuthedContinuations::new(),
|
||||||
rpc_continuations: RpcContinuations::new(),
|
rpc_continuations: RpcContinuations::new(),
|
||||||
callbacks: Default::default(),
|
|
||||||
wifi_manager: Arc::new(RwLock::new(wifi_interface.clone().map(|i| WpaCli::init(i)))),
|
wifi_manager: Arc::new(RwLock::new(wifi_interface.clone().map(|i| WpaCli::init(i)))),
|
||||||
current_secret: Arc::new(
|
current_secret: Arc::new(
|
||||||
Jwk::generate_ec_key(josekit::jwk::alg::ec::EcCurve::P256).map_err(|e| {
|
Jwk::generate_ec_key(josekit::jwk::alg::ec::EcCurve::P256).map_err(|e| {
|
||||||
@@ -327,7 +328,8 @@ impl RpcContext {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
let db = self.db.clone();
|
let db = self.db.clone();
|
||||||
self.add_cron(async move {
|
self.add_cron(async move {
|
||||||
loop {
|
loop {
|
||||||
@@ -352,6 +354,7 @@ impl RpcContext {
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
{
|
{
|
||||||
tracing::error!("Error in session cleanup cron: {e}");
|
tracing::error!("Error in session cleanup cron: {e}");
|
||||||
tracing::debug!("{e:?}");
|
tracing::debug!("{e:?}");
|
||||||
@@ -421,7 +424,8 @@ impl RpcContext {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
check_requested_actions.complete();
|
check_requested_actions.complete();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -290,7 +290,8 @@ async fn cli_apply(
|
|||||||
};
|
};
|
||||||
Ok::<_, Error>((value, ()))
|
Ok::<_, Error>((value, ()))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
} else {
|
} else {
|
||||||
let method = parent_method.into_iter().chain(method).join(".");
|
let method = parent_method.into_iter().chain(method).join(".");
|
||||||
context
|
context
|
||||||
@@ -328,6 +329,7 @@ pub async fn apply(ctx: RpcContext, ApplyParams { expr }: ApplyParams) -> Result
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put<C: Context>() -> ParentHandler<C> {
|
pub fn put<C: Context>() -> ParentHandler<C> {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::str::FromStr;
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
pub use imbl_value::Value;
|
pub use imbl_value::Value;
|
||||||
use patch_db::value::InternedString;
|
use patch_db::value::InternedString;
|
||||||
pub use patch_db::{HasModel, PatchDb};
|
pub use patch_db::{HasModel, MutateResult, PatchDb};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|||||||
@@ -423,7 +423,8 @@ pub async fn init(
|
|||||||
wifi.as_interface_mut().ser(&wifi_interface)?;
|
wifi.as_interface_mut().ser(&wifi_interface)?;
|
||||||
wifi.de()
|
wifi.de()
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
crate::net::wifi::synchronize_network_manager(MAIN_DATA, &wifi).await?;
|
crate::net::wifi::synchronize_network_manager(MAIN_DATA, &wifi).await?;
|
||||||
load_wifi.complete();
|
load_wifi.complete();
|
||||||
tracing::info!("Synchronized WiFi");
|
tracing::info!("Synchronized WiFi");
|
||||||
@@ -526,7 +527,8 @@ pub async fn init(
|
|||||||
server_info.as_status_info_mut().ser(&status_info)?;
|
server_info.as_status_info_mut().ser(&status_info)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
tracing::info!("Updated server info");
|
tracing::info!("Updated server info");
|
||||||
update_server_info.complete();
|
update_server_info.complete();
|
||||||
|
|
||||||
@@ -544,7 +546,8 @@ pub async fn init(
|
|||||||
let model = d.de()?;
|
let model = d.de()?;
|
||||||
d.ser(&model)
|
d.ser(&model)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
tracing::info!("Validated database");
|
tracing::info!("Validated database");
|
||||||
validate_db.complete();
|
validate_db.complete();
|
||||||
|
|
||||||
|
|||||||
@@ -541,7 +541,8 @@ pub async fn uninstall(
|
|||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
let return_id = id.clone();
|
let return_id = id.clone();
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ impl HasLoggedOutSessions {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(HasLoggedOutSessions(()))
|
Ok(HasLoggedOutSessions(()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,7 +137,8 @@ impl HasValidSession {
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
}
|
}
|
||||||
Ok(Self(SessionType::Session(session_token)))
|
Ok(Self(SessionType::Session(session_token)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,8 @@ impl<'a> async_acme::cache::AcmeCache for AcmeCertCache<'a> {
|
|||||||
.as_accounts_mut()
|
.as_accounts_mut()
|
||||||
.insert(&contacts, &Pem::new(key))
|
.insert(&contacts, &Pem::new(key))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +167,8 @@ impl<'a> async_acme::cache::AcmeCache for AcmeCertCache<'a> {
|
|||||||
.upsert(&directory_url, || Ok(BTreeMap::new()))?
|
.upsert(&directory_url, || Ok(BTreeMap::new()))?
|
||||||
.insert(&identifiers, &cert)
|
.insert(&identifiers, &cert)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -259,7 +261,8 @@ pub async fn init(
|
|||||||
.as_acme_mut()
|
.as_acme_mut()
|
||||||
.insert(&provider, &AcmeSettings { contact })
|
.insert(&provider, &AcmeSettings { contact })
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,6 +283,7 @@ pub async fn remove(
|
|||||||
.as_acme_mut()
|
.as_acme_mut()
|
||||||
.remove(&provider)
|
.remove(&provider)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ pub async fn add_domain<Kind: HostApiKind>(
|
|||||||
)?;
|
)?;
|
||||||
check_duplicates(db)
|
check_duplicates(db)
|
||||||
})
|
})
|
||||||
.await?;
|
.await.result?;
|
||||||
Kind::sync_host(&ctx, inheritance).await?;
|
Kind::sync_host(&ctx, inheritance).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -224,7 +224,8 @@ pub async fn remove_domain<Kind: HostApiKind>(
|
|||||||
.as_domains_mut()
|
.as_domains_mut()
|
||||||
.remove(&domain)
|
.remove(&domain)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Kind::sync_host(&ctx, inheritance).await?;
|
Kind::sync_host(&ctx, inheritance).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -258,7 +259,8 @@ pub async fn add_onion<Kind: HostApiKind>(
|
|||||||
.mutate(|a| Ok(a.insert(onion)))?;
|
.mutate(|a| Ok(a.insert(onion)))?;
|
||||||
check_duplicates(db)
|
check_duplicates(db)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
Kind::sync_host(&ctx, inheritance).await?;
|
Kind::sync_host(&ctx, inheritance).await?;
|
||||||
|
|
||||||
@@ -285,7 +287,8 @@ pub async fn remove_onion<Kind: HostApiKind>(
|
|||||||
.as_onions_mut()
|
.as_onions_mut()
|
||||||
.mutate(|a| Ok(a.remove(&onion)))
|
.mutate(|a| Ok(a.remove(&onion)))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
Kind::sync_host(&ctx, inheritance).await?;
|
Kind::sync_host(&ctx, inheritance).await?;
|
||||||
|
|
||||||
|
|||||||
@@ -239,6 +239,7 @@ pub async fn set_public<Kind: HostApiKind>(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Kind::sync_host(&ctx, inheritance).await
|
Kind::sync_host(&ctx, inheritance).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::net::{Ipv4Addr, SocketAddr};
|
|||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
use color_eyre::eyre::eyre;
|
use color_eyre::eyre::eyre;
|
||||||
use imbl::OrdMap;
|
use imbl::{vector, OrdMap};
|
||||||
use imbl_value::InternedString;
|
use imbl_value::InternedString;
|
||||||
use ipnet::IpNet;
|
use ipnet::IpNet;
|
||||||
use models::{HostId, OptionExt, PackageId};
|
use models::{HostId, OptionExt, PackageId};
|
||||||
@@ -26,6 +26,7 @@ use crate::net::tor::TorController;
|
|||||||
use crate::net::utils::ipv6_is_local;
|
use crate::net::utils::ipv6_is_local;
|
||||||
use crate::net::vhost::{AlpnInfo, TargetInfo, VHostController};
|
use crate::net::vhost::{AlpnInfo, TargetInfo, VHostController};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::service::effects::callbacks::ServiceCallbacks;
|
||||||
use crate::util::serde::MaybeUtf8String;
|
use crate::util::serde::MaybeUtf8String;
|
||||||
use crate::HOST_IP;
|
use crate::HOST_IP;
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ pub struct NetController {
|
|||||||
pub(super) dns: DnsController,
|
pub(super) dns: DnsController,
|
||||||
pub(super) forward: LanPortForwardController,
|
pub(super) forward: LanPortForwardController,
|
||||||
pub(super) server_hostnames: Vec<Option<InternedString>>,
|
pub(super) server_hostnames: Vec<Option<InternedString>>,
|
||||||
|
pub(crate) callbacks: Arc<ServiceCallbacks>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetController {
|
impl NetController {
|
||||||
@@ -66,6 +68,7 @@ impl NetController {
|
|||||||
// LAN mDNS
|
// LAN mDNS
|
||||||
Some(hostname.local_domain_name()),
|
Some(hostname.local_domain_name()),
|
||||||
],
|
],
|
||||||
|
callbacks: Arc::new(ServiceCallbacks::default()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +83,7 @@ impl NetController {
|
|||||||
let res = NetService::new(NetServiceData {
|
let res = NetService::new(NetServiceData {
|
||||||
id: Some(package),
|
id: Some(package),
|
||||||
ip,
|
ip,
|
||||||
dns,
|
_dns: dns,
|
||||||
controller: Arc::downgrade(self),
|
controller: Arc::downgrade(self),
|
||||||
binds: BTreeMap::new(),
|
binds: BTreeMap::new(),
|
||||||
})?;
|
})?;
|
||||||
@@ -94,7 +97,7 @@ impl NetController {
|
|||||||
let service = NetService::new(NetServiceData {
|
let service = NetService::new(NetServiceData {
|
||||||
id: None,
|
id: None,
|
||||||
ip: [127, 0, 0, 1].into(),
|
ip: [127, 0, 0, 1].into(),
|
||||||
dns,
|
_dns: dns,
|
||||||
controller: Arc::downgrade(self),
|
controller: Arc::downgrade(self),
|
||||||
binds: BTreeMap::new(),
|
binds: BTreeMap::new(),
|
||||||
})?;
|
})?;
|
||||||
@@ -131,7 +134,7 @@ struct HostBinds {
|
|||||||
pub struct NetServiceData {
|
pub struct NetServiceData {
|
||||||
id: Option<PackageId>,
|
id: Option<PackageId>,
|
||||||
ip: Ipv4Addr,
|
ip: Ipv4Addr,
|
||||||
dns: Arc<()>,
|
_dns: Arc<()>,
|
||||||
controller: Weak<NetController>,
|
controller: Weak<NetController>,
|
||||||
binds: BTreeMap<HostId, HostBinds>,
|
binds: BTreeMap<HostId, HostBinds>,
|
||||||
}
|
}
|
||||||
@@ -178,7 +181,8 @@ impl NetServiceData {
|
|||||||
}
|
}
|
||||||
Ok(res)
|
Ok(res)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
let mut errors = ErrorCollection::new();
|
let mut errors = ErrorCollection::new();
|
||||||
for (id, host) in hosts.0 {
|
for (id, host) in hosts.0 {
|
||||||
errors.handle(self.update(ctrl, id, host).await);
|
errors.handle(self.update(ctrl, id, host).await);
|
||||||
@@ -206,7 +210,8 @@ impl NetServiceData {
|
|||||||
})?;
|
})?;
|
||||||
host.de()
|
host.de()
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
self.update(ctrl, HostId::default(), host).await
|
self.update(ctrl, HostId::default(), host).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -578,13 +583,22 @@ impl NetServiceData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrl.db
|
let res = ctrl
|
||||||
|
.db
|
||||||
.mutate(|db| {
|
.mutate(|db| {
|
||||||
host_for(db, self.id.as_ref(), &id)?
|
host_for(db, self.id.as_ref(), &id)?
|
||||||
.as_hostname_info_mut()
|
.as_hostname_info_mut()
|
||||||
.ser(&hostname_info)
|
.ser(&hostname_info)
|
||||||
})
|
})
|
||||||
.await?;
|
.await;
|
||||||
|
res.result?;
|
||||||
|
if let Some(pkg_id) = self.id.as_ref() {
|
||||||
|
if res.revision.is_some() {
|
||||||
|
if let Some(cbs) = ctrl.callbacks.get_host_info(&(pkg_id.clone(), id)) {
|
||||||
|
cbs.call(vector![]).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +653,7 @@ impl NetService {
|
|||||||
data: Arc::new(Mutex::new(NetServiceData {
|
data: Arc::new(Mutex::new(NetServiceData {
|
||||||
id: None,
|
id: None,
|
||||||
ip: Ipv4Addr::new(0, 0, 0, 0),
|
ip: Ipv4Addr::new(0, 0, 0, 0),
|
||||||
dns: Default::default(),
|
_dns: Default::default(),
|
||||||
controller: Default::default(),
|
controller: Default::default(),
|
||||||
binds: BTreeMap::new(),
|
binds: BTreeMap::new(),
|
||||||
})),
|
})),
|
||||||
@@ -686,7 +700,8 @@ impl NetService {
|
|||||||
db.as_private_mut().as_available_ports_mut().ser(&ports)?;
|
db.as_private_mut().as_available_ports_mut().ser(&ports)?;
|
||||||
Ok(host)
|
Ok(host)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
data.update(&*ctrl, id, host).await
|
data.update(&*ctrl, id, host).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -676,7 +676,8 @@ impl NetworkInterfaceController {
|
|||||||
.as_network_interfaces_mut()
|
.as_network_interfaces_mut()
|
||||||
.ser(info)
|
.ser(info)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
let ntp: BTreeSet<_> = info
|
let ntp: BTreeSet<_> = info
|
||||||
.values()
|
.values()
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ pub async fn generate_key(ctx: RpcContext) -> Result<OnionAddressV3, Error> {
|
|||||||
.get_onion_address())
|
.get_onion_address())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Parser)]
|
#[derive(Deserialize, Serialize, Parser)]
|
||||||
@@ -175,7 +176,8 @@ pub async fn add_key(
|
|||||||
.as_onion_mut()
|
.as_onion_mut()
|
||||||
.insert_key(&key)
|
.insert_key(&key)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(key.public().get_onion_address())
|
Ok(key.public().get_onion_address())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -500,7 +500,8 @@ impl VHostServer {
|
|||||||
.as_local_certs_mut()
|
.as_local_certs_mut()
|
||||||
.cert_for(&hostnames)
|
.cert_for(&hostnames)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
let cfg = ServerConfig::builder_with_provider(crypto_provider.clone())
|
let cfg = ServerConfig::builder_with_provider(crypto_provider.clone())
|
||||||
.with_safe_default_protocol_versions()
|
.with_safe_default_protocol_versions()
|
||||||
.with_kind(crate::ErrorKind::OpenSsl)?
|
.with_kind(crate::ErrorKind::OpenSsl)?
|
||||||
|
|||||||
@@ -125,7 +125,8 @@ pub async fn set_enabled(
|
|||||||
.as_interface_mut()
|
.as_interface_mut()
|
||||||
.ser(&iface)
|
.ser(&iface)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +217,8 @@ pub async fn add(ctx: RpcContext, AddParams { ssid, password }: AddParams) -> Re
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[derive(Deserialize, Serialize, Parser, TS)]
|
#[derive(Deserialize, Serialize, Parser, TS)]
|
||||||
@@ -288,7 +290,8 @@ pub async fn connect(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result
|
|||||||
})?;
|
})?;
|
||||||
wifi.as_selected_mut().ser(&Some(ssid))
|
wifi.as_selected_mut().ser(&Some(ssid))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +337,8 @@ pub async fn remove(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result<
|
|||||||
wifi.as_selected_mut()
|
wifi.as_selected_mut()
|
||||||
.map_mutate(|s| Ok(s.filter(|s| s == &ssid.0)))
|
.map_mutate(|s| Ok(s.filter(|s| s == &ssid.0)))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
@@ -830,6 +834,7 @@ impl WpaCli {
|
|||||||
.ser(&new_country)
|
.ser(&new_country)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
async fn check_active_network(&self, ssid: &Ssid) -> Result<Option<NetworkId>, Error> {
|
async fn check_active_network(&self, ssid: &Ssid) -> Result<Option<NetworkId>, Error> {
|
||||||
Ok(self
|
Ok(self
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ pub async fn list(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Parser, TS)]
|
#[derive(Deserialize, Serialize, Parser, TS)]
|
||||||
@@ -161,6 +162,7 @@ pub async fn remove(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Parser, TS)]
|
#[derive(Deserialize, Serialize, Parser, TS)]
|
||||||
@@ -264,6 +266,7 @@ pub async fn mark_unseen(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Parser, TS)]
|
#[derive(Deserialize, Serialize, Parser, TS)]
|
||||||
@@ -288,6 +291,7 @@ pub async fn create(
|
|||||||
ctx.db
|
ctx.db
|
||||||
.mutate(|db| notify(db, package, level, title, message, ()))
|
.mutate(|db| notify(db, package, level, title, message, ()))
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, TS)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, TS)]
|
||||||
|
|||||||
@@ -294,7 +294,8 @@ impl FullProgressTracker {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?
|
.await
|
||||||
|
.result?
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ pub async fn add_signer(ctx: RegistryContext, signer: SignerInfo) -> Result<Guid
|
|||||||
ctx.db
|
ctx.db
|
||||||
.mutate(|db| db.as_index_mut().as_signers_mut().add_signer(&signer))
|
.mutate(|db| db.as_index_mut().as_signers_mut().add_signer(&signer))
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
||||||
@@ -206,6 +207,7 @@ pub async fn edit_signer(
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Parser)]
|
#[derive(Debug, Deserialize, Serialize, Parser)]
|
||||||
@@ -246,6 +248,7 @@ pub async fn cli_add_signer(
|
|||||||
.await?
|
.await?
|
||||||
.mutate(|db| db.as_index_mut().as_signers_mut().add_signer(&signer))
|
.mutate(|db| db.as_index_mut().as_signers_mut().add_signer(&signer))
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
} else {
|
} else {
|
||||||
from_value(
|
from_value(
|
||||||
ctx.call_remote::<RegistryContext>(
|
ctx.call_remote::<RegistryContext>(
|
||||||
@@ -279,6 +282,7 @@ pub async fn add_admin(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Parser)]
|
#[derive(Debug, Deserialize, Serialize, Parser)]
|
||||||
@@ -310,7 +314,8 @@ pub async fn cli_add_admin(
|
|||||||
db.as_admins_mut().mutate(|a| Ok(a.insert(signer)))?;
|
db.as_admins_mut().mutate(|a| Ok(a.insert(signer)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
} else {
|
} else {
|
||||||
ctx.call_remote::<RegistryContext>(
|
ctx.call_remote::<RegistryContext>(
|
||||||
&parent_method.into_iter().chain(method).join("."),
|
&parent_method.into_iter().chain(method).join("."),
|
||||||
|
|||||||
@@ -136,7 +136,8 @@ async fn cli_apply(
|
|||||||
(),
|
(),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
} else {
|
} else {
|
||||||
let method = parent_method.into_iter().chain(method).join(".");
|
let method = parent_method.into_iter().chain(method).join(".");
|
||||||
context
|
context
|
||||||
@@ -178,4 +179,5 @@ pub async fn apply(
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ pub async fn set_name(
|
|||||||
ctx.db
|
ctx.db
|
||||||
.mutate(|db| db.as_index_mut().as_name_mut().ser(&Some(name)))
|
.mutate(|db| db.as_index_mut().as_name_mut().ser(&Some(name)))
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, TS)]
|
#[derive(Debug, Deserialize, Serialize, TS)]
|
||||||
@@ -95,6 +96,7 @@ pub async fn set_icon(
|
|||||||
ctx.db
|
ctx.db
|
||||||
.mutate(|db| db.as_index_mut().as_icon_mut().ser(&Some(icon)))
|
.mutate(|db| db.as_index_mut().as_icon_mut().ser(&Some(icon)))
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
||||||
|
|||||||
@@ -131,7 +131,8 @@ async fn add_asset(
|
|||||||
Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization))
|
Err(Error::new(eyre!("UNAUTHORIZED"), ErrorKind::Authorization))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ async fn sign_asset(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn sign_iso(ctx: RegistryContext, params: SignAssetParams) -> Result<(), Error> {
|
pub async fn sign_iso(ctx: RegistryContext, params: SignAssetParams) -> Result<(), Error> {
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ pub async fn add_version(
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
||||||
@@ -122,6 +123,7 @@ pub async fn remove_version(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ pub async fn add_version_signer(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn remove_version_signer(
|
pub async fn remove_version_signer(
|
||||||
@@ -101,6 +102,7 @@ pub async fn remove_version_signer(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ pub async fn add_package(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Parser)]
|
#[derive(Debug, Deserialize, Serialize, Parser)]
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ pub async fn add_category(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +103,8 @@ pub async fn remove_category(
|
|||||||
.as_categories_mut()
|
.as_categories_mut()
|
||||||
.remove(&id)
|
.remove(&id)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ pub async fn add_package_signer(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn remove_package_signer(
|
pub async fn remove_package_signer(
|
||||||
@@ -100,6 +101,7 @@ pub async fn remove_package_signer(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
|
||||||
|
|||||||
@@ -139,18 +139,20 @@ impl From<PackSource> for DynFileSource {
|
|||||||
#[derive(Deserialize, Serialize, Parser)]
|
#[derive(Deserialize, Serialize, Parser)]
|
||||||
pub struct PackParams {
|
pub struct PackParams {
|
||||||
pub path: Option<PathBuf>,
|
pub path: Option<PathBuf>,
|
||||||
#[arg(short = 'o', long = "output")]
|
#[arg(short, long)]
|
||||||
pub output: Option<PathBuf>,
|
pub output: Option<PathBuf>,
|
||||||
#[arg(long = "javascript")]
|
#[arg(long)]
|
||||||
pub javascript: Option<PathBuf>,
|
pub javascript: Option<PathBuf>,
|
||||||
#[arg(long = "icon")]
|
#[arg(long)]
|
||||||
pub icon: Option<PathBuf>,
|
pub icon: Option<PathBuf>,
|
||||||
#[arg(long = "license")]
|
#[arg(long)]
|
||||||
pub license: Option<PathBuf>,
|
pub license: Option<PathBuf>,
|
||||||
#[arg(long = "instructions")]
|
#[arg(long)]
|
||||||
pub instructions: Option<PathBuf>,
|
pub instructions: Option<PathBuf>,
|
||||||
#[arg(long = "assets")]
|
#[arg(long, conflicts_with = "no-assets")]
|
||||||
pub assets: Option<PathBuf>,
|
pub assets: Option<PathBuf>,
|
||||||
|
#[arg(long, conflicts_with = "assets")]
|
||||||
|
pub no_assets: bool,
|
||||||
}
|
}
|
||||||
impl PackParams {
|
impl PackParams {
|
||||||
fn path(&self) -> &Path {
|
fn path(&self) -> &Path {
|
||||||
@@ -693,14 +695,16 @@ pub async fn pack(ctx: CliContext, params: PackParams) -> Result<(), Error> {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let assets_dir = params.assets();
|
if !params.no_assets {
|
||||||
s9pk.as_archive_mut().contents_mut().insert_path(
|
let assets_dir = params.assets();
|
||||||
"assets.squashfs",
|
s9pk.as_archive_mut().contents_mut().insert_path(
|
||||||
Entry::file(TmpSource::new(
|
"assets.squashfs",
|
||||||
tmp_dir.clone(),
|
Entry::file(TmpSource::new(
|
||||||
PackSource::Squashfs(Arc::new(SqfsDir::new(assets_dir, tmp_dir.clone()))),
|
tmp_dir.clone(),
|
||||||
)),
|
PackSource::Squashfs(Arc::new(SqfsDir::new(assets_dir, tmp_dir.clone()))),
|
||||||
)?;
|
)),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
s9pk.load_images(tmp_dir.clone()).await?;
|
s9pk.load_images(tmp_dir.clone()).await?;
|
||||||
|
|
||||||
@@ -810,8 +814,10 @@ pub async fn list_ingredients(_: CliContext, params: PackParams) -> Result<Vec<P
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let assets_dir = params.assets();
|
if !params.no_assets {
|
||||||
ingredients.push(assets_dir);
|
let assets_dir = params.assets();
|
||||||
|
ingredients.push(assets_dir);
|
||||||
|
}
|
||||||
|
|
||||||
for image in manifest.images.values() {
|
for image in manifest.images.values() {
|
||||||
ingredients.extend(image.source.ingredients());
|
ingredients.extend(image.source.ingredients());
|
||||||
|
|||||||
@@ -158,7 +158,8 @@ impl Handler<RunAction> for ServiceActor {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ pub async fn export_action(
|
|||||||
value.insert(id, metadata);
|
value.insert(id, metadata);
|
||||||
model.ser(&value)
|
model.ser(&value)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +103,8 @@ async fn clear_actions(
|
|||||||
.as_actions_mut()
|
.as_actions_mut()
|
||||||
.mutate(|a| Ok(a.retain(|e, _| except.contains(e))))
|
.mutate(|a| Ok(a.retain(|e, _| except.contains(e))))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +273,8 @@ async fn request_action(
|
|||||||
.as_requested_actions_mut()
|
.as_requested_actions_mut()
|
||||||
.insert(&replay_id, &ActionRequestEntry { active, request })
|
.insert(&replay_id, &ActionRequestEntry { active, request })
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,6 +313,7 @@ async fn clear_action_requests(
|
|||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ use futures::future::join_all;
|
|||||||
use helpers::NonDetachingJoinHandle;
|
use helpers::NonDetachingJoinHandle;
|
||||||
use imbl::{vector, Vector};
|
use imbl::{vector, Vector};
|
||||||
use imbl_value::InternedString;
|
use imbl_value::InternedString;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use models::{HostId, PackageId, ServiceInterfaceId};
|
use models::{HostId, PackageId, ServiceInterfaceId};
|
||||||
use patch_db::json_ptr::JsonPointer;
|
use patch_db::json_ptr::JsonPointer;
|
||||||
|
use patch_db::Revision;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
@@ -37,6 +39,7 @@ struct ServiceCallbackMap {
|
|||||||
>,
|
>,
|
||||||
get_store: BTreeMap<PackageId, BTreeMap<JsonPointer, Vec<CallbackHandler>>>,
|
get_store: BTreeMap<PackageId, BTreeMap<JsonPointer, Vec<CallbackHandler>>>,
|
||||||
get_status: BTreeMap<PackageId, Vec<CallbackHandler>>,
|
get_status: BTreeMap<PackageId, Vec<CallbackHandler>>,
|
||||||
|
get_container_ip: BTreeMap<PackageId, Vec<CallbackHandler>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceCallbacks {
|
impl ServiceCallbacks {
|
||||||
@@ -260,13 +263,19 @@ impl ServiceCallbacks {
|
|||||||
pub fn get_store(
|
pub fn get_store(
|
||||||
&self,
|
&self,
|
||||||
package_id: &PackageId,
|
package_id: &PackageId,
|
||||||
path: &JsonPointer,
|
revision: &Revision,
|
||||||
) -> Option<CallbackHandlers> {
|
) -> Option<CallbackHandlers> {
|
||||||
|
lazy_static! {
|
||||||
|
static ref BASE: JsonPointer = "/private/packageStores".parse().unwrap();
|
||||||
|
}
|
||||||
|
let for_pkg = BASE.clone().join_end(&**package_id);
|
||||||
self.mutate(|this| {
|
self.mutate(|this| {
|
||||||
if let Some(watched) = this.get_store.get_mut(package_id) {
|
if let Some(watched) = this.get_store.get_mut(package_id) {
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
watched.retain(|ptr, cbs| {
|
watched.retain(|ptr, cbs| {
|
||||||
if ptr.starts_with(path) || path.starts_with(ptr) {
|
let mut full_ptr = for_pkg.clone();
|
||||||
|
full_ptr.append(ptr);
|
||||||
|
if revision.patch.affects_path(&full_ptr) {
|
||||||
res.append(cbs);
|
res.append(cbs);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@@ -280,6 +289,25 @@ impl ServiceCallbacks {
|
|||||||
.filter(|cb| !cb.0.is_empty())
|
.filter(|cb| !cb.0.is_empty())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn add_get_container_ip(&self, package_id: PackageId, handler: CallbackHandler) {
|
||||||
|
self.mutate(|this| {
|
||||||
|
this.get_container_ip
|
||||||
|
.entry(package_id)
|
||||||
|
.or_default()
|
||||||
|
.push(handler)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn get_container_ip(&self, package_id: &PackageId) -> Option<CallbackHandlers> {
|
||||||
|
self.mutate(|this| {
|
||||||
|
this.get_container_ip
|
||||||
|
.remove(package_id)
|
||||||
|
.map(CallbackHandlers)
|
||||||
|
.filter(|cb| !cb.0.is_empty())
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CallbackHandler {
|
pub struct CallbackHandler {
|
||||||
|
|||||||
@@ -46,6 +46,15 @@ pub async fn get_status(
|
|||||||
let context = context.deref()?;
|
let context = context.deref()?;
|
||||||
let id = package_id.unwrap_or_else(|| context.seed.id.clone());
|
let id = package_id.unwrap_or_else(|| context.seed.id.clone());
|
||||||
let db = context.seed.ctx.db.peek().await;
|
let db = context.seed.ctx.db.peek().await;
|
||||||
|
|
||||||
|
if let Some(callback) = callback {
|
||||||
|
let callback = callback.register(&context.seed.persistent_container);
|
||||||
|
context.seed.ctx.callbacks.add_get_status(
|
||||||
|
id.clone(),
|
||||||
|
super::callbacks::CallbackHandler::new(&context, callback),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let status = db
|
let status = db
|
||||||
.as_public()
|
.as_public()
|
||||||
.as_package_data()
|
.as_package_data()
|
||||||
@@ -54,14 +63,6 @@ pub async fn get_status(
|
|||||||
.as_status()
|
.as_status()
|
||||||
.de()?;
|
.de()?;
|
||||||
|
|
||||||
if let Some(callback) = callback {
|
|
||||||
let callback = callback.register(&context.seed.persistent_container);
|
|
||||||
context.seed.ctx.callbacks.add_get_status(
|
|
||||||
id,
|
|
||||||
super::callbacks::CallbackHandler::new(&context, callback),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(status)
|
Ok(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ pub async fn set_dependencies(
|
|||||||
.ser(&CurrentDependencies(deps))
|
.ser(&CurrentDependencies(deps))
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
.result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_dependencies(context: EffectContext) -> Result<Vec<DependencyRequirement>, Error> {
|
pub async fn get_dependencies(context: EffectContext) -> Result<Vec<DependencyRequirement>, Error> {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ pub async fn set_health(
|
|||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,6 +192,4 @@ pub fn handler<C: Context>() -> ParentHandler<C> {
|
|||||||
"get-system-smtp",
|
"get-system-smtp",
|
||||||
from_fn_async(system::get_system_smtp).no_cli(),
|
from_fn_async(system::get_system_smtp).no_cli(),
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO Callbacks
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,15 @@ pub async fn get_host_info(
|
|||||||
let db = context.seed.ctx.db.peek().await;
|
let db = context.seed.ctx.db.peek().await;
|
||||||
let package_id = package_id.unwrap_or_else(|| context.seed.id.clone());
|
let package_id = package_id.unwrap_or_else(|| context.seed.id.clone());
|
||||||
|
|
||||||
|
if let Some(callback) = callback {
|
||||||
|
let callback = callback.register(&context.seed.persistent_container);
|
||||||
|
context.seed.ctx.callbacks.add_get_host_info(
|
||||||
|
package_id.clone(),
|
||||||
|
host_id.clone(),
|
||||||
|
CallbackHandler::new(&context, callback),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let res = db
|
let res = db
|
||||||
.as_public()
|
.as_public()
|
||||||
.as_package_data()
|
.as_package_data()
|
||||||
@@ -35,14 +44,5 @@ pub async fn get_host_info(
|
|||||||
.map(|m| m.de())
|
.map(|m| m.de())
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
if let Some(callback) = callback {
|
|
||||||
let callback = callback.register(&context.seed.persistent_container);
|
|
||||||
context.seed.ctx.callbacks.add_get_host_info(
|
|
||||||
package_id,
|
|
||||||
host_id,
|
|
||||||
CallbackHandler::new(&context, callback),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,55 @@
|
|||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
|
use models::PackageId;
|
||||||
|
|
||||||
|
use crate::service::effects::callbacks::CallbackHandler;
|
||||||
use crate::service::effects::prelude::*;
|
use crate::service::effects::prelude::*;
|
||||||
|
use crate::service::rpc::CallbackId;
|
||||||
use crate::HOST_IP;
|
use crate::HOST_IP;
|
||||||
|
|
||||||
pub async fn get_container_ip(context: EffectContext) -> Result<Ipv4Addr, Error> {
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
|
||||||
let context = context.deref()?;
|
#[serde(rename_all = "camelCase")]
|
||||||
Ok(context.seed.persistent_container.net_service.get_ip().await)
|
#[ts(export)]
|
||||||
|
pub struct GetContainerIpParams {
|
||||||
|
#[ts(optional)]
|
||||||
|
package_id: Option<PackageId>,
|
||||||
|
#[ts(optional)]
|
||||||
|
callback: Option<CallbackId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_container_ip(
|
||||||
|
context: EffectContext,
|
||||||
|
GetContainerIpParams {
|
||||||
|
package_id,
|
||||||
|
callback,
|
||||||
|
}: GetContainerIpParams,
|
||||||
|
) -> Result<Option<Ipv4Addr>, Error> {
|
||||||
|
let context = context.deref()?;
|
||||||
|
|
||||||
|
if let Some(package_id) = package_id.filter(|id| id != &context.seed.id) {
|
||||||
|
if let Some(callback) = callback {
|
||||||
|
// ip is static for the lifetime of the container, so callback unnecessary for self
|
||||||
|
let callback = callback.register(&context.seed.persistent_container);
|
||||||
|
context
|
||||||
|
.seed
|
||||||
|
.ctx
|
||||||
|
.callbacks
|
||||||
|
.add_get_container_ip(package_id.clone(), CallbackHandler::new(&context, callback));
|
||||||
|
}
|
||||||
|
let Some(svc) = &*context.seed.ctx.services.get(&package_id).await else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(lxc) = svc.seed.persistent_container.lxc_container.get() else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
let res = lxc.ip().await?;
|
||||||
|
|
||||||
|
Ok(Some(res))
|
||||||
|
} else {
|
||||||
|
let Some(lxc) = context.seed.persistent_container.lxc_container.get() else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
lxc.ip().await.map(Some)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,35 +42,40 @@ pub async fn export_service_interface(
|
|||||||
interface_type: r#type,
|
interface_type: r#type,
|
||||||
};
|
};
|
||||||
|
|
||||||
context
|
let res = context
|
||||||
.seed
|
.seed
|
||||||
.ctx
|
.ctx
|
||||||
.db
|
.db
|
||||||
.mutate(|db| {
|
.mutate(|db| {
|
||||||
db.as_public_mut()
|
let ifaces = db
|
||||||
|
.as_public_mut()
|
||||||
.as_package_data_mut()
|
.as_package_data_mut()
|
||||||
.as_idx_mut(&package_id)
|
.as_idx_mut(&package_id)
|
||||||
.or_not_found(&package_id)?
|
.or_not_found(&package_id)?
|
||||||
.as_service_interfaces_mut()
|
.as_service_interfaces_mut();
|
||||||
.insert(&id, &service_interface)?;
|
ifaces.insert(&id, &service_interface)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await;
|
||||||
if let Some(callbacks) = context
|
res.result?;
|
||||||
.seed
|
|
||||||
.ctx
|
if res.revision.is_some() {
|
||||||
.callbacks
|
if let Some(callbacks) = context
|
||||||
.get_service_interface(&(package_id.clone(), id))
|
.seed
|
||||||
{
|
.ctx
|
||||||
callbacks.call(vector![]).await?;
|
.callbacks
|
||||||
}
|
.get_service_interface(&(package_id.clone(), id))
|
||||||
if let Some(callbacks) = context
|
{
|
||||||
.seed
|
callbacks.call(vector![]).await?;
|
||||||
.ctx
|
}
|
||||||
.callbacks
|
if let Some(callbacks) = context
|
||||||
.list_service_interfaces(&package_id)
|
.seed
|
||||||
{
|
.ctx
|
||||||
callbacks.call(vector![]).await?;
|
.callbacks
|
||||||
|
.list_service_interfaces(&package_id)
|
||||||
|
{
|
||||||
|
callbacks.call(vector![]).await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -98,6 +103,15 @@ pub async fn get_service_interface(
|
|||||||
let package_id = package_id.unwrap_or_else(|| context.seed.id.clone());
|
let package_id = package_id.unwrap_or_else(|| context.seed.id.clone());
|
||||||
let db = context.seed.ctx.db.peek().await;
|
let db = context.seed.ctx.db.peek().await;
|
||||||
|
|
||||||
|
if let Some(callback) = callback {
|
||||||
|
let callback = callback.register(&context.seed.persistent_container);
|
||||||
|
context.seed.ctx.callbacks.add_get_service_interface(
|
||||||
|
package_id.clone(),
|
||||||
|
service_interface_id.clone(),
|
||||||
|
CallbackHandler::new(&context, callback),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let interface = db
|
let interface = db
|
||||||
.as_public()
|
.as_public()
|
||||||
.as_package_data()
|
.as_package_data()
|
||||||
@@ -106,15 +120,6 @@ pub async fn get_service_interface(
|
|||||||
.map(|m| m.de())
|
.map(|m| m.de())
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
if let Some(callback) = callback {
|
|
||||||
let callback = callback.register(&context.seed.persistent_container);
|
|
||||||
context.seed.ctx.callbacks.add_get_service_interface(
|
|
||||||
package_id,
|
|
||||||
service_interface_id,
|
|
||||||
CallbackHandler::new(&context, callback),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(interface)
|
Ok(interface)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,6 +142,14 @@ pub async fn list_service_interfaces(
|
|||||||
let context = context.deref()?;
|
let context = context.deref()?;
|
||||||
let package_id = package_id.unwrap_or_else(|| context.seed.id.clone());
|
let package_id = package_id.unwrap_or_else(|| context.seed.id.clone());
|
||||||
|
|
||||||
|
if let Some(callback) = callback {
|
||||||
|
let callback = callback.register(&context.seed.persistent_container);
|
||||||
|
context.seed.ctx.callbacks.add_list_service_interfaces(
|
||||||
|
package_id.clone(),
|
||||||
|
CallbackHandler::new(&context, callback),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let res = context
|
let res = context
|
||||||
.seed
|
.seed
|
||||||
.ctx
|
.ctx
|
||||||
@@ -150,15 +163,6 @@ pub async fn list_service_interfaces(
|
|||||||
.transpose()?
|
.transpose()?
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
if let Some(callback) = callback {
|
|
||||||
let callback = callback.register(&context.seed.persistent_container);
|
|
||||||
context
|
|
||||||
.seed
|
|
||||||
.ctx
|
|
||||||
.callbacks
|
|
||||||
.add_list_service_interfaces(package_id, CallbackHandler::new(&context, callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,17 +180,52 @@ pub async fn clear_service_interfaces(
|
|||||||
let context = context.deref()?;
|
let context = context.deref()?;
|
||||||
let package_id = context.seed.id.clone();
|
let package_id = context.seed.id.clone();
|
||||||
|
|
||||||
context
|
let res = context
|
||||||
.seed
|
.seed
|
||||||
.ctx
|
.ctx
|
||||||
.db
|
.db
|
||||||
.mutate(|db| {
|
.mutate(|db| {
|
||||||
|
let mut removed = Vec::new();
|
||||||
db.as_public_mut()
|
db.as_public_mut()
|
||||||
.as_package_data_mut()
|
.as_package_data_mut()
|
||||||
.as_idx_mut(&package_id)
|
.as_idx_mut(&package_id)
|
||||||
.or_not_found(&package_id)?
|
.or_not_found(&package_id)?
|
||||||
.as_service_interfaces_mut()
|
.as_service_interfaces_mut()
|
||||||
.mutate(|s| Ok(s.retain(|id, _| except.contains(id))))
|
.mutate(|s| {
|
||||||
|
Ok(s.retain(|id, _| {
|
||||||
|
if except.contains(id) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
removed.push(id.clone());
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
})?;
|
||||||
|
Ok(removed)
|
||||||
})
|
})
|
||||||
.await
|
.await;
|
||||||
|
let removed = res.result?;
|
||||||
|
|
||||||
|
if res.revision.is_some() {
|
||||||
|
for id in removed {
|
||||||
|
if let Some(callbacks) = context
|
||||||
|
.seed
|
||||||
|
.ctx
|
||||||
|
.callbacks
|
||||||
|
.get_service_interface(&(package_id.clone(), id))
|
||||||
|
{
|
||||||
|
callbacks.call(vector![]).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(callbacks) = context
|
||||||
|
.seed
|
||||||
|
.ctx
|
||||||
|
.callbacks
|
||||||
|
.list_service_interfaces(&package_id)
|
||||||
|
{
|
||||||
|
callbacks.call(vector![]).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,8 @@ pub async fn get_ssl_certificate(
|
|||||||
.as_local_certs_mut()
|
.as_local_certs_mut()
|
||||||
.cert_for(&hostnames)
|
.cert_for(&hostnames)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
let fullchain = match algorithm {
|
let fullchain = match algorithm {
|
||||||
Algorithm::Ecdsa => cert.fullchain_nistp256(),
|
Algorithm::Ecdsa => cert.fullchain_nistp256(),
|
||||||
Algorithm::Ed25519 => cert.fullchain_ed25519(),
|
Algorithm::Ed25519 => cert.fullchain_ed25519(),
|
||||||
@@ -171,7 +172,8 @@ pub async fn get_ssl_key(
|
|||||||
.as_local_certs_mut()
|
.as_local_certs_mut()
|
||||||
.cert_for(&hostnames)
|
.cert_for(&hostnames)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
let key = match algorithm {
|
let key = match algorithm {
|
||||||
Algorithm::Ecdsa => cert.leaf.keys.nistp256,
|
Algorithm::Ecdsa => cert.leaf.keys.nistp256,
|
||||||
Algorithm::Ed25519 => cert.leaf.keys.ed25519,
|
Algorithm::Ed25519 => cert.leaf.keys.ed25519,
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ pub async fn set_store(
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let context = context.deref()?;
|
let context = context.deref()?;
|
||||||
let package_id = &context.seed.id;
|
let package_id = &context.seed.id;
|
||||||
context
|
let res = context
|
||||||
.seed
|
.seed
|
||||||
.ctx
|
.ctx
|
||||||
.db
|
.db
|
||||||
@@ -82,10 +82,13 @@ pub async fn set_store(
|
|||||||
.with_kind(ErrorKind::ParseDbField)?;
|
.with_kind(ErrorKind::ParseDbField)?;
|
||||||
model.ser(&model_value)
|
model.ser(&model_value)
|
||||||
})
|
})
|
||||||
.await?;
|
.await;
|
||||||
|
res.result?;
|
||||||
|
|
||||||
if let Some(callbacks) = context.seed.ctx.callbacks.get_store(package_id, &path) {
|
if let Some(revision) = res.revision {
|
||||||
callbacks.call(vector![]).await?;
|
if let Some(callbacks) = context.seed.ctx.callbacks.get_store(package_id, &revision) {
|
||||||
|
callbacks.call(vector![]).await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -116,7 +119,8 @@ pub async fn set_data_version(
|
|||||||
.as_data_version_mut()
|
.as_data_version_mut()
|
||||||
.ser(&Some(version))
|
.ser(&Some(version))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,16 @@ pub async fn get_system_smtp(
|
|||||||
GetSystemSmtpParams { callback }: GetSystemSmtpParams,
|
GetSystemSmtpParams { callback }: GetSystemSmtpParams,
|
||||||
) -> Result<Option<SmtpValue>, Error> {
|
) -> Result<Option<SmtpValue>, Error> {
|
||||||
let context = context.deref()?;
|
let context = context.deref()?;
|
||||||
|
|
||||||
|
if let Some(callback) = callback {
|
||||||
|
let callback = callback.register(&context.seed.persistent_container);
|
||||||
|
context
|
||||||
|
.seed
|
||||||
|
.ctx
|
||||||
|
.callbacks
|
||||||
|
.add_get_system_smtp(CallbackHandler::new(&context, callback));
|
||||||
|
}
|
||||||
|
|
||||||
let res = context
|
let res = context
|
||||||
.seed
|
.seed
|
||||||
.ctx
|
.ctx
|
||||||
@@ -26,14 +36,5 @@ pub async fn get_system_smtp(
|
|||||||
.into_smtp()
|
.into_smtp()
|
||||||
.de()?;
|
.de()?;
|
||||||
|
|
||||||
if let Some(callback) = callback {
|
|
||||||
let callback = callback.register(&context.seed.persistent_container);
|
|
||||||
context
|
|
||||||
.seed
|
|
||||||
.ctx
|
|
||||||
.callbacks
|
|
||||||
.add_get_system_smtp(CallbackHandler::new(&context, callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,8 @@ impl ServiceRef {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?
|
.await
|
||||||
|
.result?
|
||||||
{
|
{
|
||||||
let state = pde.state_info.expect_removing()?;
|
let state = pde.state_info.expect_removing()?;
|
||||||
if !soft {
|
if !soft {
|
||||||
@@ -336,7 +337,8 @@ impl Service {
|
|||||||
// TODO: delete s9pk?
|
// TODO: delete s9pk?
|
||||||
ctx.db
|
ctx.db
|
||||||
.mutate(|v| v.as_public_mut().as_package_data_mut().remove(id))
|
.mutate(|v| v.as_public_mut().as_package_data_mut().remove(id))
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
PackageStateMatchModelRef::Updating(s) => {
|
PackageStateMatchModelRef::Updating(s) => {
|
||||||
@@ -392,7 +394,7 @@ impl Service {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?;
|
.await.result?;
|
||||||
handle_installed(s9pk, entry).await
|
handle_installed(s9pk, entry).await
|
||||||
}
|
}
|
||||||
PackageStateMatchModelRef::Removing(_) | PackageStateMatchModelRef::Restoring(_) => {
|
PackageStateMatchModelRef::Removing(_) | PackageStateMatchModelRef::Restoring(_) => {
|
||||||
@@ -419,7 +421,8 @@ impl Service {
|
|||||||
|
|
||||||
ctx.db
|
ctx.db
|
||||||
.mutate(|v| v.as_public_mut().as_package_data_mut().remove(id))
|
.mutate(|v| v.as_public_mut().as_package_data_mut().remove(id))
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@@ -550,7 +553,8 @@ impl Service {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
Ok(service)
|
Ok(service)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::time::Duration;
|
|||||||
use futures::future::ready;
|
use futures::future::ready;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use helpers::NonDetachingJoinHandle;
|
use helpers::NonDetachingJoinHandle;
|
||||||
use imbl::Vector;
|
use imbl::{vector, Vector};
|
||||||
use imbl_value::InternedString;
|
use imbl_value::InternedString;
|
||||||
use models::{ImageId, ProcedureName, VolumeId};
|
use models::{ImageId, ProcedureName, VolumeId};
|
||||||
use rpc_toolkit::{Empty, Server, ShutdownHandle};
|
use rpc_toolkit::{Empty, Server, ShutdownHandle};
|
||||||
@@ -297,10 +297,16 @@ impl PersistentContainer {
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let ip = lxc_container.ip().await?;
|
||||||
let net_service = ctx
|
let net_service = ctx
|
||||||
.net_controller
|
.net_controller
|
||||||
.create_service(s9pk.as_manifest().id.clone(), lxc_container.ip().await?)
|
.create_service(s9pk.as_manifest().id.clone(), ip)
|
||||||
.await?;
|
.await?;
|
||||||
|
if let Some(callbacks) = ctx.callbacks.get_container_ip(&s9pk.as_manifest().id) {
|
||||||
|
callbacks
|
||||||
|
.call(vector![Value::String(Arc::new(ip.to_string()))])
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
s9pk,
|
s9pk,
|
||||||
lxc_container: OnceCell::new_with(Some(lxc_container)),
|
lxc_container: OnceCell::new_with(Some(lxc_container)),
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ async fn service_actor_loop(
|
|||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
if let Some((previous, new_state)) = major_changes_state {
|
if let Some((previous, new_state)) = major_changes_state {
|
||||||
if let Some(callbacks) = seed.ctx.callbacks.get_status(id) {
|
if let Some(callbacks) = seed.ctx.callbacks.get_status(id) {
|
||||||
callbacks
|
callbacks
|
||||||
|
|||||||
@@ -117,7 +117,8 @@ impl ServiceMap {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shutdown_err?;
|
shutdown_err?;
|
||||||
@@ -174,54 +175,62 @@ impl ServiceMap {
|
|||||||
let mut reload_guard = ServiceRefReloadGuard::new(ctx.clone(), id.clone(), op_name);
|
let mut reload_guard = ServiceRefReloadGuard::new(ctx.clone(), id.clone(), op_name);
|
||||||
|
|
||||||
reload_guard
|
reload_guard
|
||||||
.handle(ctx.db.mutate({
|
.handle(async {
|
||||||
let manifest = manifest.clone();
|
ctx.db
|
||||||
let id = id.clone();
|
.mutate({
|
||||||
let install_progress = progress.snapshot();
|
let manifest = manifest.clone();
|
||||||
move |db| {
|
let id = id.clone();
|
||||||
if let Some(pde) = db.as_public_mut().as_package_data_mut().as_idx_mut(&id) {
|
let install_progress = progress.snapshot();
|
||||||
let prev = pde.as_state_info().expect_installed()?.de()?;
|
move |db| {
|
||||||
pde.as_state_info_mut()
|
if let Some(pde) =
|
||||||
.ser(&PackageState::Updating(UpdatingState {
|
db.as_public_mut().as_package_data_mut().as_idx_mut(&id)
|
||||||
manifest: prev.manifest,
|
{
|
||||||
installing_info: InstallingInfo {
|
let prev = pde.as_state_info().expect_installed()?.de()?;
|
||||||
new_manifest: manifest,
|
pde.as_state_info_mut().ser(&PackageState::Updating(
|
||||||
progress: install_progress,
|
UpdatingState {
|
||||||
},
|
manifest: prev.manifest,
|
||||||
}))?;
|
installing_info: InstallingInfo {
|
||||||
} else {
|
new_manifest: manifest,
|
||||||
let installing = InstallingState {
|
progress: install_progress,
|
||||||
installing_info: InstallingInfo {
|
},
|
||||||
new_manifest: manifest,
|
},
|
||||||
progress: install_progress,
|
))?;
|
||||||
},
|
} else {
|
||||||
};
|
let installing = InstallingState {
|
||||||
db.as_public_mut().as_package_data_mut().insert(
|
installing_info: InstallingInfo {
|
||||||
&id,
|
new_manifest: manifest,
|
||||||
&PackageDataEntry {
|
progress: install_progress,
|
||||||
state_info: if restoring {
|
},
|
||||||
PackageState::Restoring(installing)
|
};
|
||||||
} else {
|
db.as_public_mut().as_package_data_mut().insert(
|
||||||
PackageState::Installing(installing)
|
&id,
|
||||||
},
|
&PackageDataEntry {
|
||||||
data_version: None,
|
state_info: if restoring {
|
||||||
status: MainStatus::Stopped,
|
PackageState::Restoring(installing)
|
||||||
registry: None,
|
} else {
|
||||||
developer_key: Pem::new(developer_key),
|
PackageState::Installing(installing)
|
||||||
icon,
|
},
|
||||||
last_backup: None,
|
data_version: None,
|
||||||
current_dependencies: Default::default(),
|
status: MainStatus::Stopped,
|
||||||
actions: Default::default(),
|
registry: None,
|
||||||
requested_actions: Default::default(),
|
developer_key: Pem::new(developer_key),
|
||||||
service_interfaces: Default::default(),
|
icon,
|
||||||
hosts: Default::default(),
|
last_backup: None,
|
||||||
store_exposed_dependents: Default::default(),
|
current_dependencies: Default::default(),
|
||||||
},
|
actions: Default::default(),
|
||||||
)?;
|
requested_actions: Default::default(),
|
||||||
};
|
service_interfaces: Default::default(),
|
||||||
Ok(())
|
hosts: Default::default(),
|
||||||
}
|
store_exposed_dependents: Default::default(),
|
||||||
}))
|
},
|
||||||
|
)?;
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.result
|
||||||
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(async move {
|
Ok(async move {
|
||||||
@@ -425,7 +434,8 @@ impl ServiceRefReloadInfo {
|
|||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,8 @@ async fn setup_init(
|
|||||||
.ser(&account.password)?;
|
.ser(&account.password)?;
|
||||||
Ok(account)
|
Ok(account)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
Ok((account, init_result))
|
Ok((account, init_result))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ pub async fn shutdown(ctx: RpcContext) -> Result<(), Error> {
|
|||||||
.as_shutting_down_mut()
|
.as_shutting_down_mut()
|
||||||
.ser(&true)
|
.ser(&true)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
ctx.shutdown
|
ctx.shutdown
|
||||||
.send(Some(Shutdown {
|
.send(Some(Shutdown {
|
||||||
export_args: Some((ctx.disk_guid.clone(), Path::new(DATA_DIR).to_owned())),
|
export_args: Some((ctx.disk_guid.clone(), Path::new(DATA_DIR).to_owned())),
|
||||||
@@ -104,7 +105,8 @@ pub async fn restart(ctx: RpcContext) -> Result<(), Error> {
|
|||||||
.as_restarting_mut()
|
.as_restarting_mut()
|
||||||
.ser(&true)
|
.ser(&true)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
ctx.shutdown
|
ctx.shutdown
|
||||||
.send(Some(Shutdown {
|
.send(Some(Shutdown {
|
||||||
export_args: Some((ctx.disk_guid.clone(), Path::new(DATA_DIR).to_owned())),
|
export_args: Some((ctx.disk_guid.clone(), Path::new(DATA_DIR).to_owned())),
|
||||||
|
|||||||
@@ -145,7 +145,8 @@ pub async fn add(ctx: RpcContext, AddParams { key }: AddParams) -> Result<SshKey
|
|||||||
},
|
},
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
sync_pubkeys(&keys, SSH_DIR).await?;
|
sync_pubkeys(&keys, SSH_DIR).await?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
@@ -177,7 +178,8 @@ pub async fn remove(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
sync_pubkeys(&keys, SSH_DIR).await
|
sync_pubkeys(&keys, SSH_DIR).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,8 @@ pub async fn zram(ctx: RpcContext, ZramParams { enable }: ZramParams) -> Result<
|
|||||||
.ser(&enable)?;
|
.ser(&enable)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +171,8 @@ pub async fn governor(
|
|||||||
.as_governor_mut()
|
.as_governor_mut()
|
||||||
.ser(&Some(set))
|
.ser(&Some(set))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
}
|
}
|
||||||
let current = ctx
|
let current = ctx
|
||||||
.db
|
.db
|
||||||
@@ -911,7 +913,8 @@ pub async fn set_system_smtp(ctx: RpcContext, smtp: SmtpValue) -> Result<(), Err
|
|||||||
.as_smtp_mut()
|
.as_smtp_mut()
|
||||||
.ser(&smtp)
|
.ser(&smtp)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
if let Some(callbacks) = ctx.callbacks.get_system_smtp() {
|
if let Some(callbacks) = ctx.callbacks.get_system_smtp() {
|
||||||
callbacks.call(vector![to_value(&smtp)?]).await?;
|
callbacks.call(vector![to_value(&smtp)?]).await?;
|
||||||
}
|
}
|
||||||
@@ -925,7 +928,8 @@ pub async fn clear_system_smtp(ctx: RpcContext) -> Result<(), Error> {
|
|||||||
.as_smtp_mut()
|
.as_smtp_mut()
|
||||||
.ser(&None)
|
.ser(&None)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
if let Some(callbacks) = ctx.callbacks.get_system_smtp() {
|
if let Some(callbacks) = ctx.callbacks.get_system_smtp() {
|
||||||
callbacks.call(vector![Value::Null]).await?;
|
callbacks.call(vector![Value::Null]).await?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,7 +288,8 @@ async fn maybe_do_update(
|
|||||||
.ser(&status)?;
|
.ser(&status)?;
|
||||||
Ok(status)
|
Ok(status)
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
|
|
||||||
if status.updated {
|
if status.updated {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@@ -332,12 +333,10 @@ async fn maybe_do_update(
|
|||||||
status_info.as_update_progress_mut().ser(&None)?;
|
status_info.as_update_progress_mut().ser(&None)?;
|
||||||
status_info.as_updated_mut().ser(&true)
|
status_info.as_updated_mut().ser(&true)
|
||||||
})
|
})
|
||||||
.await?;
|
|
||||||
progress_task.await.with_kind(ErrorKind::Unknown)??;
|
|
||||||
CIRCLE_OF_5THS_SHORT
|
|
||||||
.play()
|
|
||||||
.await
|
.await
|
||||||
.expect("could not play sound");
|
.result?;
|
||||||
|
progress_task.await.with_kind(ErrorKind::Unknown)??;
|
||||||
|
CIRCLE_OF_5THS_SHORT.play().await.log_err();
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_string = format!("Update was not successful because of {}", e);
|
let err_string = format!("Update was not successful because of {}", e);
|
||||||
@@ -358,24 +357,13 @@ async fn maybe_do_update(
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.result
|
||||||
|
.log_err();
|
||||||
// TODO: refactor sound lib to make compound tempos easier to deal with
|
// TODO: refactor sound lib to make compound tempos easier to deal with
|
||||||
UPDATE_FAILED_1
|
UPDATE_FAILED_1.play().await.log_err();
|
||||||
.play()
|
UPDATE_FAILED_2.play().await.log_err();
|
||||||
.await
|
UPDATE_FAILED_3.play().await.log_err();
|
||||||
.expect("could not play song: update failed 1");
|
UPDATE_FAILED_4.play().await.log_err();
|
||||||
UPDATE_FAILED_2
|
|
||||||
.play()
|
|
||||||
.await
|
|
||||||
.expect("could not play song: update failed 2");
|
|
||||||
UPDATE_FAILED_3
|
|
||||||
.play()
|
|
||||||
.await
|
|
||||||
.expect("could not play song: update failed 3");
|
|
||||||
UPDATE_FAILED_4
|
|
||||||
.play()
|
|
||||||
.await
|
|
||||||
.expect("could not play song: update failed 4");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok::<(), Error>(())
|
Ok::<(), Error>(())
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ mod v0_3_6_alpha_13;
|
|||||||
mod v0_3_6_alpha_14;
|
mod v0_3_6_alpha_14;
|
||||||
mod v0_3_6_alpha_15;
|
mod v0_3_6_alpha_15;
|
||||||
mod v0_3_6_alpha_16;
|
mod v0_3_6_alpha_16;
|
||||||
|
mod v0_3_6_alpha_17;
|
||||||
|
mod v0_3_6_alpha_18;
|
||||||
|
|
||||||
mod v0_4_0_alpha_0;
|
mod v0_4_0_alpha_0;
|
||||||
|
|
||||||
@@ -56,7 +58,8 @@ impl Current {
|
|||||||
rollback_to_unchecked(&from, &self, &mut db)?;
|
rollback_to_unchecked(&from, &self, &mut db)?;
|
||||||
Ok::<_, Error>((db, ()))
|
Ok::<_, Error>((db, ()))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
}
|
}
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
let pre_ups = PreUps::load(&from, &self).await?;
|
let pre_ups = PreUps::load(&from, &self).await?;
|
||||||
@@ -64,7 +67,8 @@ impl Current {
|
|||||||
migrate_from_unchecked(&from, &self, pre_ups, &mut db)?;
|
migrate_from_unchecked(&from, &self, pre_ups, &mut db)?;
|
||||||
Ok::<_, Error>((to_value(&from_value::<Database>(db.clone())?)?, ()))
|
Ok::<_, Error>((to_value(&from_value::<Database>(db.clone())?)?, ()))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
}
|
}
|
||||||
Ordering::Equal => (),
|
Ordering::Equal => (),
|
||||||
}
|
}
|
||||||
@@ -105,7 +109,8 @@ pub async fn post_init(
|
|||||||
.as_post_init_migration_todos_mut()
|
.as_post_init_migration_todos_mut()
|
||||||
.mutate(|m| Ok(m.remove(&version.0.semver())))
|
.mutate(|m| Ok(m.remove(&version.0.semver())))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
progress += 1;
|
progress += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,6 +143,8 @@ enum Version {
|
|||||||
V0_3_6_alpha_14(Wrapper<v0_3_6_alpha_14::Version>),
|
V0_3_6_alpha_14(Wrapper<v0_3_6_alpha_14::Version>),
|
||||||
V0_3_6_alpha_15(Wrapper<v0_3_6_alpha_15::Version>),
|
V0_3_6_alpha_15(Wrapper<v0_3_6_alpha_15::Version>),
|
||||||
V0_3_6_alpha_16(Wrapper<v0_3_6_alpha_16::Version>),
|
V0_3_6_alpha_16(Wrapper<v0_3_6_alpha_16::Version>),
|
||||||
|
V0_3_6_alpha_17(Wrapper<v0_3_6_alpha_17::Version>),
|
||||||
|
V0_3_6_alpha_18(Wrapper<v0_3_6_alpha_18::Version>),
|
||||||
V0_4_0_alpha_0(Wrapper<v0_4_0_alpha_0::Version>), // VERSION_BUMP
|
V0_4_0_alpha_0(Wrapper<v0_4_0_alpha_0::Version>), // VERSION_BUMP
|
||||||
Other(exver::Version),
|
Other(exver::Version),
|
||||||
}
|
}
|
||||||
@@ -179,7 +186,9 @@ impl Version {
|
|||||||
Self::V0_3_6_alpha_14(v) => DynVersion(Box::new(v.0)),
|
Self::V0_3_6_alpha_14(v) => DynVersion(Box::new(v.0)),
|
||||||
Self::V0_3_6_alpha_15(v) => DynVersion(Box::new(v.0)),
|
Self::V0_3_6_alpha_15(v) => DynVersion(Box::new(v.0)),
|
||||||
Self::V0_3_6_alpha_16(v) => DynVersion(Box::new(v.0)),
|
Self::V0_3_6_alpha_16(v) => DynVersion(Box::new(v.0)),
|
||||||
Self::V0_4_0_alpha_0(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP
|
Self::V0_3_6_alpha_17(v) => DynVersion(Box::new(v.0)),
|
||||||
|
Self::V0_3_6_alpha_18(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP
|
||||||
|
Self::V0_4_0_alpha_0(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP
|
||||||
Self::Other(v) => {
|
Self::Other(v) => {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
eyre!("unknown version {v}"),
|
eyre!("unknown version {v}"),
|
||||||
@@ -212,6 +221,8 @@ impl Version {
|
|||||||
Version::V0_3_6_alpha_14(Wrapper(x)) => x.semver(),
|
Version::V0_3_6_alpha_14(Wrapper(x)) => x.semver(),
|
||||||
Version::V0_3_6_alpha_15(Wrapper(x)) => x.semver(),
|
Version::V0_3_6_alpha_15(Wrapper(x)) => x.semver(),
|
||||||
Version::V0_3_6_alpha_16(Wrapper(x)) => x.semver(),
|
Version::V0_3_6_alpha_16(Wrapper(x)) => x.semver(),
|
||||||
|
Version::V0_3_6_alpha_17(Wrapper(x)) => x.semver(),
|
||||||
|
Version::V0_3_6_alpha_18(Wrapper(x)) => x.semver(),
|
||||||
Version::V0_4_0_alpha_0(Wrapper(x)) => x.semver(), // VERSION_BUMP
|
Version::V0_4_0_alpha_0(Wrapper(x)) => x.semver(), // VERSION_BUMP
|
||||||
Version::Other(x) => x.clone(),
|
Version::Other(x) => x.clone(),
|
||||||
}
|
}
|
||||||
|
|||||||
36
core/startos/src/version/v0_3_6_alpha_17.rs
Normal file
36
core/startos/src/version/v0_3_6_alpha_17.rs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
use exver::{PreReleaseSegment, VersionRange};
|
||||||
|
|
||||||
|
use super::v0_3_5::V0_3_0_COMPAT;
|
||||||
|
use super::{v0_3_6_alpha_16, VersionT};
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref V0_3_6_alpha_17: exver::Version = exver::Version::new(
|
||||||
|
[0, 3, 6],
|
||||||
|
[PreReleaseSegment::String("alpha".into()), 17.into()]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
|
pub struct Version;
|
||||||
|
|
||||||
|
impl VersionT for Version {
|
||||||
|
type Previous = v0_3_6_alpha_16::Version;
|
||||||
|
type PreUpRes = ();
|
||||||
|
|
||||||
|
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn semver(self) -> exver::Version {
|
||||||
|
V0_3_6_alpha_17.clone()
|
||||||
|
}
|
||||||
|
fn compat(self) -> &'static VersionRange {
|
||||||
|
&V0_3_0_COMPAT
|
||||||
|
}
|
||||||
|
fn up(self, _db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn down(self, _db: &mut Value) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
36
core/startos/src/version/v0_3_6_alpha_18.rs
Normal file
36
core/startos/src/version/v0_3_6_alpha_18.rs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
use exver::{PreReleaseSegment, VersionRange};
|
||||||
|
|
||||||
|
use super::v0_3_5::V0_3_0_COMPAT;
|
||||||
|
use super::{v0_3_6_alpha_17, VersionT};
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref V0_3_6_alpha_18: exver::Version = exver::Version::new(
|
||||||
|
[0, 3, 6],
|
||||||
|
[PreReleaseSegment::String("alpha".into()), 18.into()]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
|
pub struct Version;
|
||||||
|
|
||||||
|
impl VersionT for Version {
|
||||||
|
type Previous = v0_3_6_alpha_17::Version;
|
||||||
|
type PreUpRes = ();
|
||||||
|
|
||||||
|
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn semver(self) -> exver::Version {
|
||||||
|
V0_3_6_alpha_18.clone()
|
||||||
|
}
|
||||||
|
fn compat(self) -> &'static VersionRange {
|
||||||
|
&V0_3_0_COMPAT
|
||||||
|
}
|
||||||
|
fn up(self, _db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn down(self, _db: &mut Value) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,7 +45,8 @@ impl VersionT for Version {
|
|||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn down(self, _db: &mut Value) -> Result<(), Error> {
|
fn down(self, _db: &mut Value) -> Result<(), Error> {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use exver::{PreReleaseSegment, VersionRange};
|
|||||||
use imbl_value::json;
|
use imbl_value::json;
|
||||||
|
|
||||||
use super::v0_3_5::V0_3_0_COMPAT;
|
use super::v0_3_5::V0_3_0_COMPAT;
|
||||||
use super::{v0_3_6_alpha_16, VersionT};
|
use super::{v0_3_6_alpha_18, VersionT};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
@@ -16,7 +16,7 @@ lazy_static::lazy_static! {
|
|||||||
pub struct Version;
|
pub struct Version;
|
||||||
|
|
||||||
impl VersionT for Version {
|
impl VersionT for Version {
|
||||||
type Previous = v0_3_6_alpha_16::Version;
|
type Previous = v0_3_6_alpha_18::Version;
|
||||||
type PreUpRes = ();
|
type PreUpRes = ();
|
||||||
|
|
||||||
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
|
||||||
|
|||||||
2
debian/postinst
vendored
2
debian/postinst
vendored
@@ -109,7 +109,7 @@ rm -rf /var/lib/tor/*
|
|||||||
ln -sf /usr/lib/startos/scripts/chroot-and-upgrade /usr/bin/chroot-and-upgrade
|
ln -sf /usr/lib/startos/scripts/chroot-and-upgrade /usr/bin/chroot-and-upgrade
|
||||||
ln -sf /usr/lib/startos/scripts/tor-check /usr/bin/tor-check
|
ln -sf /usr/lib/startos/scripts/tor-check /usr/bin/tor-check
|
||||||
ln -sf /usr/lib/startos/scripts/gather-debug-info /usr/bin/gather-debug-info
|
ln -sf /usr/lib/startos/scripts/gather-debug-info /usr/bin/gather-debug-info
|
||||||
ln -sf /usr/lib/startos/scripts/wg-vps-setup /usr/bin/wg-vps-setup
|
ln -sf /usr/lib/startos/scripts/wireguard-vps-proxy-setup /usr/bin/wireguard-vps-proxy-setup
|
||||||
|
|
||||||
echo "fs.inotify.max_user_watches=1048576" > /etc/sysctl.d/97-startos.conf
|
echo "fs.inotify.max_user_watches=1048576" > /etc/sysctl.d/97-startos.conf
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ PLATFORM_CONFIG_EXTRAS=()
|
|||||||
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
||||||
PLATFORM_CONFIG_EXTRAS+=( --firmware-binary false )
|
PLATFORM_CONFIG_EXTRAS+=( --firmware-binary false )
|
||||||
PLATFORM_CONFIG_EXTRAS+=( --firmware-chroot false )
|
PLATFORM_CONFIG_EXTRAS+=( --firmware-chroot false )
|
||||||
PLATFORM_CONFIG_EXTRAS+=( --linux-packages linux-image-6.6.51+rpt )
|
PLATFORM_CONFIG_EXTRAS+=( --linux-packages linux-image-6.12.20+rpt )
|
||||||
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours "rpi-v8 rpi-2712" )
|
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours "rpi-v8 rpi-2712" )
|
||||||
elif [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
|
elif [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
|
||||||
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours rockchip64 )
|
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours rockchip64 )
|
||||||
@@ -147,7 +147,7 @@ if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
cat > config/archives/backports.pref <<- EOF
|
cat > config/archives/backports.pref <<- EOF
|
||||||
Package: *
|
Package: linux-image-*
|
||||||
Pin: release n=${IB_SUITE}-backports
|
Pin: release n=${IB_SUITE}-backports
|
||||||
Pin-Priority: 500
|
Pin-Priority: 500
|
||||||
EOF
|
EOF
|
||||||
@@ -206,8 +206,8 @@ if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
|||||||
echo "Configuring raspi kernel '\$v'"
|
echo "Configuring raspi kernel '\$v'"
|
||||||
extract-ikconfig "/usr/lib/modules/\$v/kernel/kernel/configs.ko.xz" > /boot/config-\$v
|
extract-ikconfig "/usr/lib/modules/\$v/kernel/kernel/configs.ko.xz" > /boot/config-\$v
|
||||||
done
|
done
|
||||||
mkinitramfs -c gzip -o /boot/initramfs8 6.6.74-v8+
|
mkinitramfs -c gzip -o /boot/initramfs8 6.12.20-v8+
|
||||||
mkinitramfs -c gzip -o /boot/initramfs_2712 6.6.74-v8-16k+
|
mkinitramfs -c gzip -o /boot/initramfs_2712 6.12.20-v8-16k+
|
||||||
fi
|
fi
|
||||||
|
|
||||||
useradd --shell /bin/bash -G startos -m start9
|
useradd --shell /bin/bash -G startos -m start9
|
||||||
|
|||||||
2
patch-db
2
patch-db
Submodule patch-db updated: 0df18c651f...d1362bdcd9
@@ -130,7 +130,10 @@ export type Effects = {
|
|||||||
callback?: () => void
|
callback?: () => void
|
||||||
}): Promise<Host | null>
|
}): Promise<Host | null>
|
||||||
/** Returns the IP address of the container */
|
/** Returns the IP address of the container */
|
||||||
getContainerIp(): Promise<string>
|
getContainerIp(options: {
|
||||||
|
packageId?: PackageId
|
||||||
|
callback?: () => void
|
||||||
|
}): Promise<string>
|
||||||
/** Returns the IP address of StartOS */
|
/** Returns the IP address of StartOS */
|
||||||
getOsIp(): Promise<string>
|
getOsIp(): Promise<string>
|
||||||
// interface
|
// interface
|
||||||
|
|||||||
@@ -33,18 +33,6 @@ export const knownProtocols = {
|
|||||||
secure: { ssl: false },
|
secure: { ssl: false },
|
||||||
defaultPort: 22,
|
defaultPort: 22,
|
||||||
},
|
},
|
||||||
bitcoin: {
|
|
||||||
secure: { ssl: false },
|
|
||||||
defaultPort: 8333,
|
|
||||||
},
|
|
||||||
lightning: {
|
|
||||||
secure: { ssl: true },
|
|
||||||
defaultPort: 9735,
|
|
||||||
},
|
|
||||||
grpc: {
|
|
||||||
secure: { ssl: true },
|
|
||||||
defaultPort: 50051,
|
|
||||||
},
|
|
||||||
dns: {
|
dns: {
|
||||||
secure: { ssl: false },
|
secure: { ssl: false },
|
||||||
defaultPort: 53,
|
defaultPort: 53,
|
||||||
|
|||||||
8
sdk/base/lib/osBindings/GetContainerIpParams.ts
Normal file
8
sdk/base/lib/osBindings/GetContainerIpParams.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
import type { CallbackId } from "./CallbackId"
|
||||||
|
import type { PackageId } from "./PackageId"
|
||||||
|
|
||||||
|
export type GetContainerIpParams = {
|
||||||
|
packageId?: PackageId
|
||||||
|
callback?: CallbackId
|
||||||
|
}
|
||||||
@@ -81,6 +81,7 @@ export { ForgetInterfaceParams } from "./ForgetInterfaceParams"
|
|||||||
export { FullIndex } from "./FullIndex"
|
export { FullIndex } from "./FullIndex"
|
||||||
export { FullProgress } from "./FullProgress"
|
export { FullProgress } from "./FullProgress"
|
||||||
export { GetActionInputParams } from "./GetActionInputParams"
|
export { GetActionInputParams } from "./GetActionInputParams"
|
||||||
|
export { GetContainerIpParams } from "./GetContainerIpParams"
|
||||||
export { GetHostInfoParams } from "./GetHostInfoParams"
|
export { GetHostInfoParams } from "./GetHostInfoParams"
|
||||||
export { GetOsAssetParams } from "./GetOsAssetParams"
|
export { GetOsAssetParams } from "./GetOsAssetParams"
|
||||||
export { GetOsVersionParams } from "./GetOsVersionParams"
|
export { GetOsVersionParams } from "./GetOsVersionParams"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
ClearCallbacksParams,
|
ClearCallbacksParams,
|
||||||
ClearServiceInterfacesParams,
|
ClearServiceInterfacesParams,
|
||||||
GetActionInputParams,
|
GetActionInputParams,
|
||||||
|
GetContainerIpParams,
|
||||||
GetStatusParams,
|
GetStatusParams,
|
||||||
RequestActionParams,
|
RequestActionParams,
|
||||||
RunActionParams,
|
RunActionParams,
|
||||||
@@ -77,7 +78,7 @@ describe("startosTypeValidation ", () => {
|
|||||||
set: {} as any, // as SetStoreParams,
|
set: {} as any, // as SetStoreParams,
|
||||||
},
|
},
|
||||||
getSystemSmtp: {} as WithCallback<GetSystemSmtpParams>,
|
getSystemSmtp: {} as WithCallback<GetSystemSmtpParams>,
|
||||||
getContainerIp: undefined,
|
getContainerIp: {} as WithCallback<GetContainerIpParams>,
|
||||||
getOsIp: undefined,
|
getOsIp: undefined,
|
||||||
getServicePortForward: {} as GetServicePortForwardParams,
|
getServicePortForward: {} as GetServicePortForwardParams,
|
||||||
clearServiceInterfaces: {} as ClearServiceInterfacesParams,
|
clearServiceInterfaces: {} as ClearServiceInterfacesParams,
|
||||||
|
|||||||
@@ -47,7 +47,12 @@ import { GetSystemSmtp } from "./util"
|
|||||||
import { nullIfEmpty } from "./util"
|
import { nullIfEmpty } from "./util"
|
||||||
import { getServiceInterface, getServiceInterfaces } from "./util"
|
import { getServiceInterface, getServiceInterfaces } from "./util"
|
||||||
import { getStore } from "./store/getStore"
|
import { getStore } from "./store/getStore"
|
||||||
import { CommandOptions, MountOptions, SubContainer } from "./util/SubContainer"
|
import {
|
||||||
|
CommandOptions,
|
||||||
|
ExitError,
|
||||||
|
MountOptions,
|
||||||
|
SubContainer,
|
||||||
|
} from "./util/SubContainer"
|
||||||
import { splitCommand } from "./util"
|
import { splitCommand } from "./util"
|
||||||
import { Mounts } from "./mainFn/Mounts"
|
import { Mounts } from "./mainFn/Mounts"
|
||||||
import { setupDependencies } from "../../base/lib/dependencies/setupDependencies"
|
import { setupDependencies } from "../../base/lib/dependencies/setupDependencies"
|
||||||
@@ -104,7 +109,10 @@ export class StartSdk<Manifest extends T.SDKManifest, Store> {
|
|||||||
| "getHostInfo"
|
| "getHostInfo"
|
||||||
type MainUsedEffects = "setMainStatus" | "setHealth"
|
type MainUsedEffects = "setMainStatus" | "setHealth"
|
||||||
type CallbackEffects = "constRetry" | "clearCallbacks"
|
type CallbackEffects = "constRetry" | "clearCallbacks"
|
||||||
type AlreadyExposed = "getSslCertificate" | "getSystemSmtp"
|
type AlreadyExposed =
|
||||||
|
| "getSslCertificate"
|
||||||
|
| "getSystemSmtp"
|
||||||
|
| "getContainerIp"
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
type StartSdkEffectWrapper = {
|
type StartSdkEffectWrapper = {
|
||||||
@@ -123,7 +131,6 @@ export class StartSdk<Manifest extends T.SDKManifest, Store> {
|
|||||||
getServicePortForward: (effects, ...args) =>
|
getServicePortForward: (effects, ...args) =>
|
||||||
effects.getServicePortForward(...args),
|
effects.getServicePortForward(...args),
|
||||||
clearBindings: (effects, ...args) => effects.clearBindings(...args),
|
clearBindings: (effects, ...args) => effects.clearBindings(...args),
|
||||||
getContainerIp: (effects, ...args) => effects.getContainerIp(...args),
|
|
||||||
getOsIp: (effects, ...args) => effects.getOsIp(...args),
|
getOsIp: (effects, ...args) => effects.getOsIp(...args),
|
||||||
getSslKey: (effects, ...args) => effects.getSslKey(...args),
|
getSslKey: (effects, ...args) => effects.getSslKey(...args),
|
||||||
setDataVersion: (effects, ...args) => effects.setDataVersion(...args),
|
setDataVersion: (effects, ...args) => effects.setDataVersion(...args),
|
||||||
@@ -191,7 +198,61 @@ export class StartSdk<Manifest extends T.SDKManifest, Store> {
|
|||||||
opts: { packageId: PackageId },
|
opts: { packageId: PackageId },
|
||||||
) => getServiceInterfaces(effects, opts),
|
) => getServiceInterfaces(effects, opts),
|
||||||
},
|
},
|
||||||
|
getContainerIp: (
|
||||||
|
effects: T.Effects,
|
||||||
|
options: Omit<
|
||||||
|
Parameters<T.Effects["getContainerIp"]>[0],
|
||||||
|
"callback"
|
||||||
|
> = {},
|
||||||
|
) => {
|
||||||
|
async function* watch() {
|
||||||
|
while (true) {
|
||||||
|
let callback: () => void = () => {}
|
||||||
|
const waitForNext = new Promise<void>((resolve) => {
|
||||||
|
callback = resolve
|
||||||
|
})
|
||||||
|
yield await effects.getContainerIp({ ...options, callback })
|
||||||
|
await waitForNext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
const: () =>
|
||||||
|
effects.getContainerIp({
|
||||||
|
...options,
|
||||||
|
callback:
|
||||||
|
effects.constRetry &&
|
||||||
|
(() => effects.constRetry && effects.constRetry()),
|
||||||
|
}),
|
||||||
|
once: () => effects.getContainerIp(options),
|
||||||
|
watch,
|
||||||
|
onChange: (
|
||||||
|
callback: (
|
||||||
|
value: string | null,
|
||||||
|
error?: Error,
|
||||||
|
) => void | Promise<void>,
|
||||||
|
) => {
|
||||||
|
;(async () => {
|
||||||
|
for await (const value of watch()) {
|
||||||
|
try {
|
||||||
|
await callback(value)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
"callback function threw an error @ getContainerIp.onChange",
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
.catch((e) => callback(null, e))
|
||||||
|
.catch((e) =>
|
||||||
|
console.error(
|
||||||
|
"callback function threw an error @ getContainerIp.onChange",
|
||||||
|
e,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
store: {
|
store: {
|
||||||
get: <E extends Effects, StoreValue = unknown>(
|
get: <E extends Effects, StoreValue = unknown>(
|
||||||
effects: E,
|
effects: E,
|
||||||
@@ -230,7 +291,7 @@ export class StartSdk<Manifest extends T.SDKManifest, Store> {
|
|||||||
},
|
},
|
||||||
command: T.CommandType,
|
command: T.CommandType,
|
||||||
options: CommandOptions & {
|
options: CommandOptions & {
|
||||||
mounts?: { mountpoint: string; options: MountOptions }[]
|
mounts: Mounts<Manifest>
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* A name to use to refer to the ephemeral subcontainer for debugging purposes
|
* A name to use to refer to the ephemeral subcontainer for debugging purposes
|
||||||
@@ -527,7 +588,10 @@ export class StartSdk<Manifest extends T.SDKManifest, Store> {
|
|||||||
})
|
})
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
setupInstall: (fn: InstallFn<Manifest, Store>) => Install.of(fn),
|
setupInstall: (
|
||||||
|
fn: InstallFn<Manifest, Store>,
|
||||||
|
preFn?: InstallFn<Manifest, Store>,
|
||||||
|
) => Install.of(fn, preFn),
|
||||||
/**
|
/**
|
||||||
* @description Use this function to determine how this service will be hosted and served. The function executes on service install, service update, and inputSpec save.
|
* @description Use this function to determine how this service will be hosted and served. The function executes on service install, service update, and inputSpec save.
|
||||||
*
|
*
|
||||||
@@ -1076,7 +1140,7 @@ export async function runCommand<Manifest extends T.SDKManifest>(
|
|||||||
image: { imageId: keyof Manifest["images"] & T.ImageId; sharedRun?: boolean },
|
image: { imageId: keyof Manifest["images"] & T.ImageId; sharedRun?: boolean },
|
||||||
command: T.CommandType,
|
command: T.CommandType,
|
||||||
options: CommandOptions & {
|
options: CommandOptions & {
|
||||||
mounts?: { mountpoint: string; options: MountOptions }[]
|
mounts: Mounts<Manifest>
|
||||||
},
|
},
|
||||||
name?: string,
|
name?: string,
|
||||||
): Promise<{ stdout: string | Buffer; stderr: string | Buffer }> {
|
): Promise<{ stdout: string | Buffer; stderr: string | Buffer }> {
|
||||||
@@ -1094,7 +1158,7 @@ export async function runCommand<Manifest extends T.SDKManifest>(
|
|||||||
return SubContainer.with(
|
return SubContainer.with(
|
||||||
effects,
|
effects,
|
||||||
image,
|
image,
|
||||||
options.mounts || [],
|
options.mounts.build(),
|
||||||
name ||
|
name ||
|
||||||
commands
|
commands
|
||||||
.map((c) => {
|
.map((c) => {
|
||||||
@@ -1105,6 +1169,13 @@ export async function runCommand<Manifest extends T.SDKManifest>(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.join(" "),
|
.join(" "),
|
||||||
(subcontainer) => subcontainer.exec(commands),
|
async (subcontainer) => {
|
||||||
|
const res = await subcontainer.exec(commands)
|
||||||
|
if (res.exitCode || res.exitSignal) {
|
||||||
|
throw new ExitError(commands[0], res)
|
||||||
|
} else {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ExtendedVersion } from "../../../base/lib/exver"
|
|||||||
import { UpdateServiceInterfaces } from "../../../base/lib/interfaces/setupInterfaces"
|
import { UpdateServiceInterfaces } from "../../../base/lib/interfaces/setupInterfaces"
|
||||||
import { ExposedStorePaths } from "../../../base/lib/types"
|
import { ExposedStorePaths } from "../../../base/lib/types"
|
||||||
import * as T from "../../../base/lib/types"
|
import * as T from "../../../base/lib/types"
|
||||||
|
import { StorePath } from "../util"
|
||||||
import { VersionGraph } from "../version/VersionGraph"
|
import { VersionGraph } from "../version/VersionGraph"
|
||||||
import { Install } from "./setupInstall"
|
import { Install } from "./setupInstall"
|
||||||
import { Uninstall } from "./setupUninstall"
|
import { Uninstall } from "./setupUninstall"
|
||||||
@@ -16,6 +17,7 @@ export function setupInit<Manifest extends T.SDKManifest, Store>(
|
|||||||
effects: T.Effects
|
effects: T.Effects
|
||||||
}) => Promise<null | void | undefined>,
|
}) => Promise<null | void | undefined>,
|
||||||
actions: Actions<Store, any>,
|
actions: Actions<Store, any>,
|
||||||
|
initStore: Store,
|
||||||
exposedStore: ExposedStorePaths,
|
exposedStore: ExposedStorePaths,
|
||||||
): {
|
): {
|
||||||
packageInit: T.ExpectedExports.packageInit
|
packageInit: T.ExpectedExports.packageInit
|
||||||
@@ -53,6 +55,14 @@ export function setupInit<Manifest extends T.SDKManifest, Store>(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
containerInit: async (opts) => {
|
containerInit: async (opts) => {
|
||||||
|
const prev = await opts.effects.getDataVersion()
|
||||||
|
if (!prev) {
|
||||||
|
await opts.effects.store.set({
|
||||||
|
path: "" as StorePath,
|
||||||
|
value: initStore,
|
||||||
|
})
|
||||||
|
await install.preInstall(opts)
|
||||||
|
}
|
||||||
await setServiceInterfaces({
|
await setServiceInterfaces({
|
||||||
...opts,
|
...opts,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,11 +4,15 @@ export type InstallFn<Manifest extends T.SDKManifest, Store> = (opts: {
|
|||||||
effects: T.Effects
|
effects: T.Effects
|
||||||
}) => Promise<null | void | undefined>
|
}) => Promise<null | void | undefined>
|
||||||
export class Install<Manifest extends T.SDKManifest, Store> {
|
export class Install<Manifest extends T.SDKManifest, Store> {
|
||||||
private constructor(readonly fn: InstallFn<Manifest, Store>) {}
|
private constructor(
|
||||||
|
readonly fn: InstallFn<Manifest, Store>,
|
||||||
|
readonly preFn?: InstallFn<Manifest, Store>,
|
||||||
|
) {}
|
||||||
static of<Manifest extends T.SDKManifest, Store>(
|
static of<Manifest extends T.SDKManifest, Store>(
|
||||||
fn: InstallFn<Manifest, Store>,
|
fn: InstallFn<Manifest, Store>,
|
||||||
|
preFn?: InstallFn<Manifest, Store>,
|
||||||
) {
|
) {
|
||||||
return new Install(fn)
|
return new Install(fn, preFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
async install({ effects }: Parameters<T.ExpectedExports.packageInit>[0]) {
|
async install({ effects }: Parameters<T.ExpectedExports.packageInit>[0]) {
|
||||||
@@ -16,10 +20,18 @@ export class Install<Manifest extends T.SDKManifest, Store> {
|
|||||||
effects,
|
effects,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async preInstall({ effects }: Parameters<T.ExpectedExports.packageInit>[0]) {
|
||||||
|
this.preFn &&
|
||||||
|
(await this.preFn({
|
||||||
|
effects,
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupInstall<Manifest extends T.SDKManifest, Store>(
|
export function setupInstall<Manifest extends T.SDKManifest, Store>(
|
||||||
fn: InstallFn<Manifest, Store>,
|
fn: InstallFn<Manifest, Store>,
|
||||||
|
preFn?: InstallFn<Manifest, Store>,
|
||||||
) {
|
) {
|
||||||
return Install.of(fn)
|
return Install.of(fn, preFn)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ export class Daemons<Manifest extends T.SDKManifest, Ids extends string>
|
|||||||
daemon,
|
daemon,
|
||||||
daemonIndex,
|
daemonIndex,
|
||||||
options.requires
|
options.requires
|
||||||
.map((x) => this.ids.indexOf(id as any))
|
.map((x) => this.ids.indexOf(x))
|
||||||
.filter((x) => x >= 0)
|
.filter((x) => x >= 0)
|
||||||
.map((id) => this.healthDaemons[id]),
|
.map((id) => this.healthDaemons[id]),
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -467,3 +467,25 @@ export type MountOptionsBackup = {
|
|||||||
function wait(time: number) {
|
function wait(time: number) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, time))
|
return new Promise((resolve) => setTimeout(resolve, time))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ExitError extends Error {
|
||||||
|
constructor(
|
||||||
|
readonly command: string,
|
||||||
|
readonly result: {
|
||||||
|
exitCode: number | null
|
||||||
|
exitSignal: T.Signals | null
|
||||||
|
stdout: string | Buffer
|
||||||
|
stderr: string | Buffer
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
let message: string
|
||||||
|
if (result.exitCode) {
|
||||||
|
message = `${command} failed with exit code ${result.exitCode}: ${result.stderr}`
|
||||||
|
} else if (result.exitSignal) {
|
||||||
|
message = `${command} terminated with signal ${result.exitSignal}: ${result.stderr}`
|
||||||
|
} else {
|
||||||
|
message = `${command} succeeded: ${result.stdout}`
|
||||||
|
}
|
||||||
|
super(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
4
sdk/package/package-lock.json
generated
4
sdk/package/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@start9labs/start-sdk",
|
"name": "@start9labs/start-sdk",
|
||||||
"version": "0.3.6-beta.18",
|
"version": "0.3.6-beta.20",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@start9labs/start-sdk",
|
"name": "@start9labs/start-sdk",
|
||||||
"version": "0.3.6-beta.18",
|
"version": "0.3.6-beta.20",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@start9labs/start-sdk",
|
"name": "@start9labs/start-sdk",
|
||||||
"version": "0.3.6-beta.18",
|
"version": "0.3.6-beta.20",
|
||||||
"description": "Software development kit to facilitate packaging services for StartOS",
|
"description": "Software development kit to facilitate packaging services for StartOS",
|
||||||
"main": "./package/lib/index.js",
|
"main": "./package/lib/index.js",
|
||||||
"types": "./package/lib/index.d.ts",
|
"types": "./package/lib/index.d.ts",
|
||||||
|
|||||||
Reference in New Issue
Block a user