Reputation: 1015
I'm using the python tufup library to manage updates for my application, it seems that I need to specify two different URLs, but I'm struggling to understand from the docs/examples where/how each one gets configured? or what am I misunderstanding here?
URL to Check for Updates: This URL is where the application checks for new releases or updates. ex: "https://github.com/USER/PROJECT/releases/latest" (doc)
URL to Get Metadata and Targets: This URL is where the tufup client fetches the metadata and target files required for verifying and applying updates. These files include root.json and other metadata files. This URL (I assume) should point to a secure server that I control. ex: "https://myCustomURL.com/verification_files"
Here is my current configuration:
__version__ = "0.1"
import customtkinter as ctk
import os, shutil, time
from pathlib import Path
from tufup.client import Client
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# Define settings (these should ideally be in a separate settings.py file)
APP_NAME = "myAppName"
APP_VERSION = __version__
INSTALL_DIR = Path(os.getenv("INSTALL_DIR", Path.home() / "myAppName"))
METADATA_DIR = INSTALL_DIR / "metadata"
METADATA_BASE_URL = os.getenv("METADATA_BASE_URL", "https://myCustomURL.com/verification_files/metadata")
TARGET_DIR = INSTALL_DIR / "targets"
TARGET_BASE_URL = os.getenv("TARGET_BASE_URL", "https://myCustomURL.com/verification_files/targets")
TRUSTED_ROOT_SRC = Path(os.getenv("TRUSTED_ROOT_SRC", "update_repo/metadata/root.json"))
TRUSTED_ROOT_DST = METADATA_DIR / "root.json"
class App(ctk.CTk):
def __init__(self):
super().__init__()
# Check for updates
self.check_for_updates()
def progress_hook(self, bytes_downloaded: int, bytes_expected: int):
progress_percent = bytes_downloaded / bytes_expected * 100
time.sleep(0.2) # Simulate slow or large download
if progress_percent >= 100:
print("Download complete.")
def check_for_updates(self):
print("Checking for updates...")
try:
# Ensure directories exist
for dir_path in [INSTALL_DIR, METADATA_DIR, TARGET_DIR]:
dir_path.mkdir(exist_ok=True, parents=True)
# Ensure trusted root metadata exists
if not TRUSTED_ROOT_DST.exists():
if not TRUSTED_ROOT_SRC.exists():
raise FileNotFoundError(f"Trusted root metadata file not found: {TRUSTED_ROOT_SRC}")
shutil.copy(src=TRUSTED_ROOT_SRC, dst=TRUSTED_ROOT_DST)
print('Trusted root metadata copied to cache.')
# Create update client
client = Client(
app_name=APP_NAME,
app_install_dir=INSTALL_DIR,
current_version=APP_VERSION,
metadata_dir=METADATA_DIR,
metadata_base_url=METADATA_BASE_URL,
target_dir=TARGET_DIR,
target_base_url=TARGET_BASE_URL,
refresh_required=False,
)
# Perform update
new_update = client.check_for_updates(pre=None)
if new_update:
# Apply the update
client.download_and_apply_update(
skip_confirmation=True,
progress_hook=self.progress_hook,
purge_dst_dir=False,
exclude_from_purge=None,
log_file_name='install.log',
)
print("Update installed. Please restart the application.")
else:
print("You are up to date!")
except Exception as e:
print(f"Update check failed: {e}")
Upvotes: 1
Views: 80
Reputation: 14315
The tufup package uses python-tuf to handle secure file downloads. python-tuf
is the reference implementation of TUF (The Update Framework). tufup
only adds some logic to handle versioned files, together with a slightly more specialized interface.
A tufup client's job is to check for new updates, download an update archive, if available, and extract the files from that archive into some directory.
To make this work, the tufup
client needs to know two things:
Where to find a list of available updates:
The list of available updates is found in a file called targets.json
, generated by tufup
(using python-tuf
). The client will try to download this file from the url specified in metadata_base_url
.
Where to find the actual update files:
The actual update files are contained in compressed "archives," also generated by tufup
, e.g. my-app-1.2.3.tar.gz
. TUF refers to these files as targets. The client will try to download the latest update archive from the url specified in targets_base_url
.
The important point is: You (the app developer) must make sure these files are available for download at the specified urls. Typically that means you need to set up one or more servers to serve both the metadata files and the target files.
The tufup-example readme shows how to serve these files on localhost
, for testing. In the tufup-example settings file, these urls are specified as:
METADATA_BASE_URL = 'http://localhost:8000/metadata/'
TARGET_BASE_URL = 'http://localhost:8000/targets/'
Note that, in addition to targets.json
, tufup
(or actually python-tuf
) also generates three other types of TUF metadata files: root.json
, snapshot.json
, and timestamp.json
. All four metadata files need to be available for download from the url specified in metadata_base_url
. The additional metadata files are used for security purposes. How this works is explained in detail in the TUF specification.
Upvotes: 1