From cdb01f81505ae1ea26d8beed2f90971ce84126bc Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Sat, 14 Nov 2026 13:50:18 -0800 Subject: [PATCH] install.sh: add --enterprise (#12660) * install.sh: offer the vector engine on linux only Releases build weed-vector for linux amd64/arm64 only, so --component vector on darwin or windows downloaded a missing asset. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_011UpvafvK8JpagF94MHWqwK * install.sh: add --enterprise Installs from seaweedfs/artifactory: weed-enterprise-_[_large_disk], weed-volume-enterprise[_large_disk], weed-worker-enterprise and weed-vector-enterprise. The latest tag skips vfs-* releases, and the Rust volume server is linux-only there, so --component all skips it elsewhere. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_011UpvafvK8JpagF94MHWqwK * Revert "install.sh: offer the vector engine on linux only" Releases after 4.53 publish weed-vector for darwin and windows too (rust-vector-platforms.yml). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_011UpvafvK8JpagF94MHWqwK * install.sh: Enterprise vector engine is linux-only Enterprise releases publish weed-vector-enterprise for linux amd64/arm64; open-source releases keep their darwin and windows engines. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_011UpvafvK8JpagF94MHWqwK * test: installer --enterprise asset names, platforms and latest tag Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_011UpvafvK8JpagF94MHWqwK * install.sh: Enterprise latest is the newest plain version tag artifactory also releases previews and a dev build, and a prerelease such as kvcache-filer-native-v0.1.0-preview.1 sits in the release list. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_011UpvafvK8JpagF94MHWqwK * README: show passing --enterprise through bash -s -- Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_011UpvafvK8JpagF94MHWqwK * install.sh: the open-source weed for windows is a .zip too Releases publish windows_amd64[_large_disk].zip, so asking for a .tar.gz 404s on every Windows host. Co-Authored-By: Claude Opus 5.5 * install.sh: install the windows weed as weed.exe weed-volume and weed-vector keep their .exe on Windows; weed lost it, so cmd and PowerShell could not run the installed binary. Co-Authored-By: Claude Opus 5.5 * install.sh: suggest weed-volume only when it was installed Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Claude Opus 5.5 --- README.md | 2 + install.sh | 91 +++++++++++++++++++++++++---------- test/installer/test_vector.py | 58 ++++++++++++++++++++++ 3 files changed, 125 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index aa8f58f83a..31620616ac 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,8 @@ Download the latest binary from the [releases](https://github.com/seaweedfs/seaw curl -fsSL https://raw.githubusercontent.com/seaweedfs/seaweedfs/master/install.sh | bash ``` +For SeaweedFS Enterprise binaries, pass `--enterprise` to the script: `... | bash -s -- --enterprise`. + Then start a ready-to-use S3 object store: ```bash diff --git a/install.sh b/install.sh index 73ce1e92f3..6bc2b0f702 100755 --- a/install.sh +++ b/install.sh @@ -7,12 +7,14 @@ # curl -fsSL https://raw.githubusercontent.com/seaweedfs/seaweedfs/master/install.sh | bash # curl -fsSL ... | bash -s -- --component volume-rust --large-disk # curl -fsSL ... | bash -s -- --version 4.34 --dir /usr/local/bin +# curl -fsSL ... | bash -s -- --enterprise --component all # # Options: # --component COMP Which binary to install: weed, volume-rust, worker-rust, vector, all (default: weed) # --version VER Release version tag (default: latest) # --large-disk Use large disk variant (5-byte offset, 8TB max volume) # --dir DIR Installation directory (default: /usr/local/bin) +# --enterprise Install SeaweedFS Enterprise binaries (from seaweedfs/artifactory) # --help Show this help message set -euo pipefail @@ -24,6 +26,10 @@ LARGE_DISK=false INSTALL_DIR="/usr/local/bin" WORKER_INSTALLED=false VECTOR_INSTALLED=false +VOLUME_INSTALLED=false +ENTERPRISE=false +# Enterprise assets carry this after the binary name, e.g. weed-vector-enterprise_linux_amd64.tar.gz. +EDITION="" # Colors (if terminal supports them) if [ -t 1 ]; then @@ -53,6 +59,7 @@ while [ $# -gt 0 ]; do --version) VERSION="$2"; shift 2 ;; --large-disk) LARGE_DISK=true; shift ;; --dir) INSTALL_DIR="$2"; shift 2 ;; + --enterprise) ENTERPRISE=true; REPO="seaweedfs/artifactory"; EDITION="-enterprise"; shift ;; --help|-h) usage ;; *) error "Unknown option: $1. Use --help for usage." ;; esac @@ -81,15 +88,22 @@ detect_platform() { } # Get latest release tag from GitHub API +# The Enterprise repo also releases other products (vfs-*, previews), which can +# be its latest release, so take the newest plain version tag like 4.53. get_latest_version() { local url="https://api.github.com/repos/${REPO}/releases/latest" + if [ "$ENTERPRISE" = true ]; then + url="https://api.github.com/repos/${REPO}/releases?per_page=30" + fi + local body if command -v curl &>/dev/null; then - curl -fsSL "$url" | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/' + body="$(curl -fsSL "$url")" elif command -v wget &>/dev/null; then - wget -qO- "$url" | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/' + body="$(wget -qO- "$url")" else error "Neither curl nor wget found. Please install one." fi + echo "$body" | grep '"tag_name"' | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/' | grep -E '^[0-9]+(\.[0-9]+)+$' | head -1 || true } # Download a file @@ -110,17 +124,22 @@ go_asset_name() { if [ "$LARGE_DISK" = true ]; then suffix="${suffix}_large_disk" fi - echo "${suffix}.tar.gz" + if [ "$ENTERPRISE" = true ]; then + suffix="weed-enterprise-${suffix}" + fi + if [ "$os" = "windows" ]; then + echo "${suffix}.zip" + else + echo "${suffix}.tar.gz" + fi } # Build Rust volume server asset name rust_asset_name() { local os="$1" arch="$2" - local prefix="weed-volume" + local prefix="weed-volume${EDITION}" if [ "$LARGE_DISK" = true ]; then - prefix="weed-volume_large_disk" - else - prefix="weed-volume" + prefix="${prefix}_large_disk" fi local suffix="${os}_${arch}" if [ "$os" = "windows" ]; then @@ -130,6 +149,19 @@ rust_asset_name() { fi } +# Enterprise publishes the Rust volume server for linux only. +rust_volume_platform_supported() { + case "$2" in + amd64|arm64) ;; + *) return 1 ;; + esac + case "$1" in + linux) return 0 ;; + darwin|windows) [ "$ENTERPRISE" != true ] ;; + *) return 1 ;; + esac +} + # Does a release carry this asset? Answers 0 for yes and 1 for a 404, and stops # the installer on anything else: a rate limit or a network blip must not read # as "this release predates the binary" and quietly skip it. @@ -154,22 +186,23 @@ asset_exists() { # maintains tables through the namespace and never opens a volume file. worker_asset_name() { local os="$1" arch="$2" - echo "weed-worker_${os}_${arch}.tar.gz" + echo "weed-worker${EDITION}_${os}_${arch}.tar.gz" } # The vector engine behind the S3 Vectors API, built like the worker. vector_asset_name() { local os="$1" arch="$2" if [ "$os" = "windows" ]; then - echo "weed-vector_${os}_${arch}.zip" + echo "weed-vector${EDITION}_${os}_${arch}.zip" else - echo "weed-vector_${os}_${arch}.tar.gz" + echo "weed-vector${EDITION}_${os}_${arch}.tar.gz" fi } vector_platform_supported() { case "$1/$2" in - linux/amd64|linux/arm64|darwin/amd64|darwin/arm64|windows/amd64) return 0 ;; + linux/amd64|linux/arm64) return 0 ;; + darwin/amd64|darwin/arm64|windows/amd64) [ "$ENTERPRISE" != true ] ;; *) return 1 ;; esac } @@ -189,7 +222,10 @@ install_component() { download "$download_url" "${tmpdir}/${asset_name}" info "Extracting ${asset_name}..." - tar xzf "${tmpdir}/${asset_name}" -C "$tmpdir" + case "$asset_name" in + *.zip) unzip -q "${tmpdir}/${asset_name}" -d "$tmpdir" ;; + *) tar xzf "${tmpdir}/${asset_name}" -C "$tmpdir" ;; + esac # The Go release action puts the binary inside a directory local weed_bin @@ -202,20 +238,16 @@ install_component() { fi chmod +x "$weed_bin" - install_binary "$weed_bin" "weed" - ok "Installed weed to ${INSTALL_DIR}/weed" + local dest_name="weed" + if [ "$os" = "windows" ]; then + dest_name="weed.exe" + fi + install_binary "$weed_bin" "$dest_name" + ok "Installed weed to ${INSTALL_DIR}/${dest_name}" ;; volume-rust) - # Check platform support for Rust volume server - case "$os" in - linux|darwin|windows) ;; - *) error "Rust volume server is not available for ${os}. Supported: linux, darwin, windows" ;; - esac - case "$arch" in - amd64|arm64) ;; - *) error "Rust volume server is not available for ${arch}. Supported: amd64, arm64" ;; - esac + rust_volume_platform_supported "$os" "$arch" || error "The Rust volume server is not available for ${os}/${arch}" asset_name="$(rust_asset_name "$os" "$arch")" download_url="https://github.com/${REPO}/releases/download/${VERSION}/${asset_name}" @@ -247,6 +279,7 @@ install_component() { dest_name="weed-volume.exe" fi install_binary "$rust_bin" "$dest_name" + VOLUME_INSTALLED=true ok "Installed weed-volume to ${INSTALL_DIR}/${dest_name}" ;; @@ -359,7 +392,11 @@ main() { case "$COMPONENT" in all) install_component "weed" "$os" "$arch" - install_component "volume-rust" "$os" "$arch" + if rust_volume_platform_supported "$os" "$arch"; then + install_component "volume-rust" "$os" "$arch" + else + warn "Skipping the Rust volume server: no build for ${os}/${arch}" + fi # The worker is published for linux amd64/arm64 only, and only by # releases new enough to carry it; skip either case rather than fail # an install that has already put two binaries in place. @@ -388,7 +425,7 @@ main() { if [ "$COMPONENT" = "weed" ] || [ "$COMPONENT" = "all" ]; then info " weed: ${INSTALL_DIR}/weed" fi - if [ "$COMPONENT" = "volume-rust" ] || [ "$COMPONENT" = "all" ]; then + if [ "$VOLUME_INSTALLED" = true ]; then info " weed-volume: ${INSTALL_DIR}/weed-volume" fi if [ "$WORKER_INSTALLED" = true ]; then @@ -401,7 +438,9 @@ main() { info "Quick start:" info " weed master # Start master server" info " weed volume -mserver=localhost:9333 # Start Go volume server" - info " weed-volume -mserver localhost:9333 # Start Rust volume server" + if [ "$VOLUME_INSTALLED" = true ]; then + info " weed-volume -mserver localhost:9333 # Start Rust volume server" + fi if [ "$WORKER_INSTALLED" = true ]; then info " weed-worker --admin localhost:12535 # Start the Rust maintenance worker" fi diff --git a/test/installer/test_vector.py b/test/installer/test_vector.py index 4a8ee993e1..e443e1067a 100644 --- a/test/installer/test_vector.py +++ b/test/installer/test_vector.py @@ -57,3 +57,61 @@ class VectorInstallerTest(unittest.TestCase): ARCHIVE=archive.as_posix(), DEST=dest.as_posix(), SYSTEM=system) self.assertEqual(result.returncode, 0, result.stdout + result.stderr) self.assertEqual((dest / name).read_bytes(), contents) + + +class EnterpriseInstallerTest(unittest.TestCase): + shell = VectorInstallerTest.shell + + def enterprise(self, code, **env): + return self.shell('ENTERPRISE=true; REPO=seaweedfs/artifactory; EDITION=-enterprise; ' + code, **env) + + def test_asset_names(self): + result = self.enterprise('go_asset_name linux amd64; go_asset_name windows amd64; ' + 'rust_asset_name linux arm64; worker_asset_name linux amd64; ' + 'vector_asset_name linux arm64; LARGE_DISK=true; ' + 'go_asset_name darwin arm64; rust_asset_name linux amd64') + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(result.stdout.split(), [ + 'weed-enterprise-linux_amd64.tar.gz', 'weed-enterprise-windows_amd64.zip', + 'weed-volume-enterprise_linux_arm64.tar.gz', 'weed-worker-enterprise_linux_amd64.tar.gz', + 'weed-vector-enterprise_linux_arm64.tar.gz', 'weed-enterprise-darwin_arm64_large_disk.tar.gz', + 'weed-volume-enterprise_large_disk_linux_amd64.tar.gz', + ]) + + def test_open_source_go_asset_names(self): + result = self.shell('go_asset_name linux amd64; go_asset_name windows amd64; ' + 'LARGE_DISK=true; go_asset_name windows amd64') + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(result.stdout.split(), [ + 'linux_amd64.tar.gz', 'windows_amd64.zip', 'windows_amd64_large_disk.zip', + ]) + + def test_windows_weed_keeps_exe(self): + with tempfile.TemporaryDirectory() as directory: + directory = Path(directory) + archive = directory / 'weed.zip' + with zipfile.ZipFile(archive, 'w') as output: + output.writestr('weed.exe', b'weed fixture') + dest = directory / 'bin' + result = self.shell('download() { cp "$ARCHIVE" "$2"; }; VERSION=test; ' + 'INSTALL_DIR="$DEST"; install_component weed windows amd64', + ARCHIVE=archive.as_posix(), DEST=dest.as_posix()) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertEqual((dest / 'weed.exe').read_bytes(), b'weed fixture') + + def test_rust_binaries_linux_only(self): + for system, arch, supported in [ + ('linux', 'amd64', True), ('linux', 'arm64', True), + ('darwin', 'arm64', False), ('windows', 'amd64', False), + ]: + with self.subTest(system=system, arch=arch): + for check in ['vector_platform_supported', 'rust_volume_platform_supported']: + result = self.enterprise(f'{check} "$SYSTEM" "$ARCH"', SYSTEM=system, ARCH=arch) + self.assertEqual(result.returncode == 0, supported, check) + + def test_latest_version_skips_other_releases(self): + tags = ['vfs-0.2.5', 'kvcache-filer-native-v0.1.0-preview.1', '4.54-rc1', '4.53', '4.52'] + listing = ''.join(f' "tag_name": "{tag}",\\n' for tag in tags) + result = self.enterprise(f"curl() {{ printf '{listing}'; }}; get_latest_version") + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(result.stdout.strip(), '4.53')