From 2fc9742957b2d938161ffa3668d1ef72756d24dd Mon Sep 17 00:00:00 2001 From: Peter Barnett Date: Sun, 17 Aug 2025 21:22:25 -0400 Subject: [PATCH 1/5] chore: add homebrew recipe --- influxdb3-core.rb | 294 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 influxdb3-core.rb diff --git a/influxdb3-core.rb b/influxdb3-core.rb new file mode 100644 index 00000000000..9426e08e54c --- /dev/null +++ b/influxdb3-core.rb @@ -0,0 +1,294 @@ +class Influxdb3Core < Formula + desc "InfluxDB 3 Core - Fast, columnar time series database" + homepage "https://www.influxdata.com/products/influxdb/" + version "3.3.0" + license any_of: ["Apache-2.0", "MIT"] + + depends_on "python@3.13" => :recommended + + on_macos do + if Hardware::CPU.arm? + url "https://dl.influxdata.com/influxdb/releases/influxdb3-core-#{version}_darwin_arm64.tar.gz" + sha256 "355fd93598619dba5fda91aed03b8d8282e0729a6765378740996f59bfb407df" + else + odie "Intel Mac support is not yet available for InfluxDB 3 Core." + end + end + + def install + bin.install "influxdb3" + + if File.directory?("python") + (bin/"python").install Dir["python/*"] + elsif File.directory?("plugins") + (bin/"plugins").install Dir["plugins/*"] + end + + # If no bundled Python, create symlinks to system Python + unless (bin/"python").exist? + python_prefix = Formula["python@3.13"].opt_prefix + (bin/"python").mkpath + (bin/"python/lib").mkpath + + python_lib = python_prefix/"lib/libpython3.13.dylib" + if python_lib.exist? + (bin/"python/lib/libpython3.13.dylib").make_symlink(python_lib) + end + end + + data_dir = var/"lib/influxdb3" + data_dir.mkpath + + config_dir = etc/"influxdb3" + config_dir.mkpath + + generate_default_config(config_dir) + + (var/"log/influxdb3").mkpath + + create_startup_script + + (data_dir/"README.txt").write <<~EOS + InfluxDB 3 Core Data Directory + + This directory contains your InfluxDB 3 Core data when using file-based storage. + + Configuration: #{config_dir}/influxdb3.conf + Logs: #{var}/log/influxdb3/ + + To start the server: brew services start influxdb3-core + To view logs: tail -f #{var}/log/influxdb3/influxdb3.log + EOS + end + + def generate_default_config(config_dir) + config_file = config_dir/"influxdb3.conf" + + return if config_file.exist? + + node_id = ENV.fetch("INFLUXDB3_NODE_ID", "node0") + + config_content = <<~EOS + # InfluxDB 3 Core Configuration File + # Generated by Homebrew on #{Time.now} + # Edit this file to customize your InfluxDB 3 setup + + # ============================================================================= + # Node Configuration + # ============================================================================= + NODE_ID=#{ENV.fetch("INFLUXDB3_NODE_ID", node_id)} + + # ============================================================================= + # Object Store Configuration + # ============================================================================= + # Options: memory, file, s3, google, azure + OBJECT_STORE_TYPE=#{ENV.fetch("INFLUXDB3_OBJECT_STORE", "file")} + + # File Object Store Settings (used when OBJECT_STORE_TYPE=file) + DATA_DIR=#{var}/lib/influxdb3 + + # S3 Object Store Settings (used when OBJECT_STORE_TYPE=s3) + # Uncomment and configure these if using S3: + # S3_BUCKET=your-bucket-name + # AWS_ACCESS_KEY_ID=your-access-key + # AWS_SECRET_ACCESS_KEY=your-secret-key + # AWS_REGION=your-region (default: us-east-1 if not uncommented) + # AWS_ENDPOINT= # Optional: for MinIO or other S3-compatible stores + # AWS_ALLOW_HTTP=false # Set to true for non-HTTPS endpoints + + # Google Cloud Storage Settings (used when OBJECT_STORE_TYPE=google) + # GOOGLE_SERVICE_ACCOUNT_PATH=/path/to/service-account.json + # GOOGLE_BUCKET=your-gcs-bucket + + # Azure Blob Storage Settings (used when OBJECT_STORE_TYPE=azure) + # AZURE_STORAGE_ACCOUNT=your-account + # AZURE_STORAGE_ACCESS_KEY=your-key + # AZURE_CONTAINER=your-container + + # ============================================================================= + # Server Configuration + # ============================================================================= + HTTP_BIND_ADDRESS=127.0.0.1:8181 + + EOS + + config_file.write(config_content) + end + + def create_startup_script + startup_script = bin/"influxdb3-core" + startup_script.write <<~EOS + #!/bin/bash + + # InfluxDB 3 Core Dynamic Startup Script + # This script reads configuration and starts influxdb3 with the right parameters + + CONFIG_FILE="#{etc}/influxdb3/influxdb3.conf" + + # Function to read config value + read_config() { + local key="$1" + local default="$2" + if [ -f "$CONFIG_FILE" ]; then + value=$(grep "^$key=" "$CONFIG_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d '"') + echo "${value:-$default}" + else + echo "$default" + fi + } + + # Read configuration + NODE_ID="${INFLUXDB3_NODE_ID:-$(read_config "NODE_ID" "node0")}" + OBJECT_STORE="${INFLUXDB3_OBJECT_STORE:-$(read_config "OBJECT_STORE_TYPE" "file")}" + HTTP_BIND="${INFLUXDB3_HTTP_BIND:-$(read_config "HTTP_BIND_ADDRESS" "127.0.0.1:8181")}" + + # Start building command + ARGS=("#{opt_bin}/influxdb3" "serve" "--node-id" "$NODE_ID" "--object-store" "$OBJECT_STORE") + + # Add object store specific arguments + case "$OBJECT_STORE" in + "file") + DATA_DIR="${INFLUXDB3_DATA_DIR:-$(read_config "DATA_DIR" "#{var}/lib/influxdb3")}" + ARGS+=("--data-dir" "$DATA_DIR") + ;; + "s3") + S3_BUCKET="$(read_config "S3_BUCKET" "")" + AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID:-$(read_config "AWS_ACCESS_KEY_ID" "")}" + AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY:-$(read_config "AWS_SECRET_ACCESS_KEY" "")}" + AWS_REGION="${AWS_REGION:-$(read_config "AWS_REGION" "")}" + AWS_ENDPOINT="${AWS_ENDPOINT:-$(read_config "AWS_ENDPOINT" "")}" + AWS_ALLOW_HTTP="$(read_config "AWS_ALLOW_HTTP" "")" + + [ -n "$S3_BUCKET" ] && ARGS+=("--bucket" "$S3_BUCKET") + [ -n "$AWS_ACCESS_KEY_ID" ] && ARGS+=("--aws-access-key-id" "$AWS_ACCESS_KEY_ID") + [ -n "$AWS_SECRET_ACCESS_KEY" ] && ARGS+=("--aws-secret-access-key" "$AWS_SECRET_ACCESS_KEY") + [ -n "$AWS_REGION" ] && ARGS+=("--aws-region" "$AWS_REGION") + [ -n "$AWS_ENDPOINT" ] && ARGS+=("--aws-endpoint" "$AWS_ENDPOINT") + [ "$AWS_ALLOW_HTTP" = "true" ] && ARGS+=("--aws-allow-http") + ;; + "google") + GOOGLE_SERVICE_ACCOUNT_PATH="${GOOGLE_SERVICE_ACCOUNT_PATH:-$(read_config "GOOGLE_SERVICE_ACCOUNT_PATH" "")}" + GOOGLE_BUCKET="${GOOGLE_BUCKET:-$(read_config "GOOGLE_BUCKET" "")}" + + [ -n "$GOOGLE_SERVICE_ACCOUNT_PATH" ] && ARGS+=("--google-service-account-path" "$GOOGLE_SERVICE_ACCOUNT_PATH") + [ -n "$GOOGLE_BUCKET" ] && ARGS+=("--google-bucket" "$GOOGLE_BUCKET") + ;; + "azure") + AZURE_STORAGE_ACCOUNT="${AZURE_STORAGE_ACCOUNT:-$(read_config "AZURE_STORAGE_ACCOUNT" "")}" + AZURE_STORAGE_ACCESS_KEY="${AZURE_STORAGE_ACCESS_KEY:-$(read_config "AZURE_STORAGE_ACCESS_KEY" "")}" + AZURE_CONTAINER="${AZURE_CONTAINER:-$(read_config "AZURE_CONTAINER" "")}" + + [ -n "$AZURE_STORAGE_ACCOUNT" ] && ARGS+=("--azure-storage-account" "$AZURE_STORAGE_ACCOUNT") + [ -n "$AZURE_STORAGE_ACCESS_KEY" ] && ARGS+=("--azure-storage-access-key" "$AZURE_STORAGE_ACCESS_KEY") + [ -n "$AZURE_CONTAINER" ] && ARGS+=("--azure-container" "$AZURE_CONTAINER") + ;; + esac + + # Add HTTP bind address + ARGS+=("--http-bind" "$HTTP_BIND") + + # Execute the command + echo "Starting InfluxDB 3 Core with configuration:" + echo " Node ID: $NODE_ID" + echo " Object Store: $OBJECT_STORE" + echo " HTTP Bind: $HTTP_BIND" + echo "" + echo "Full command: ${ARGS[*]}" + echo "" + + exec "${ARGS[@]}" + EOS + + startup_script.chmod(0755) + end + + def caveats + + bold = "\033[1m" + boldgreen = "\033[1;32m" + dim = "\033[2m" + nc = "\033[0m" # No Color + + <<~EOS + \n + ┌───────────────────────────────────────────────────────┐ + │ 🚀 #{boldgreen}InfluxDB 3 Core has been installed and configured!#{nc} │ + ├───────────────────────────────────────────────────────┘ + │ + │ 📁 Config file: #{etc}/influxdb3/influxdb3.conf + │ 📁 Data directory: #{var}/lib/influxdb3 + │ 📁 Logs directory: #{var}/log/influxdb3 + │ + │ #{bold}Current Configuration:#{nc} + │ Node ID: node0 + │ Storage: file + │ Address: 127.0.0.1:8181 + │ + │ #{dim}To customize storage (memory, s3, google, azure) or other,#{nc} + │ #{dim}settings, edit the config file and restart the service.#{nc} + │ #{dim}├─ vim #{etc}/influxdb3/influxdb3.conf#{nc} + │ #{dim}└─ brew services restart influxdb3-core#{nc} + │ + │ #{bold}Next Steps:#{nc} + │ 1. Start the service: #{bold}brew services start influxdb3-core#{nc} + │ 2. Create admin token: #{bold}influxdb3 create token --admin#{nc} + │ 3. Set the token: #{bold}export INFLUXDB3_AUTH_TOKEN="your-token"#{nc} + │ 4. Create a database: #{bold}influxdb3 create database mydata#{nc} + │ 5. Start writing data! + │ + │ #{bold}Documentation:#{nc} https://docs.influxdata.com/influxdb3/core/ + │ + └────────────────────────────────────────────────────────\n + EOS + end + + service do + run opt_bin/"influxdb3-core" + keep_alive true + working_dir HOMEBREW_PREFIX + log_path var/"log/influxdb3/influxdb3.log" + error_log_path var/"log/influxdb3/influxdb3.log" + environment_variables INFLUXDB3_CONFIG_FILE: etc/"influxdb3/influxdb3.conf" + end + + test do + assert_predicate bin/"influxdb3", :exist? + assert_predicate bin/"influxdb3", :executable? + + assert_predicate bin/"influxdb3-core", :exist? + assert_predicate bin/"influxdb3-core", :executable? + + output = shell_output("#{bin}/influxdb3 --help") + assert_match "InfluxDB 3", output + + assert_predicate etc/"influxdb3/influxdb3.conf", :exist? + config_content = (etc/"influxdb3/influxdb3.conf").read + assert_match "NODE_ID=", config_content + assert_match "OBJECT_STORE_TYPE=", config_content + + assert_predicate var/"lib/influxdb3", :exist? + assert_predicate var/"lib/influxdb3/README.txt", :exist? + + assert_predicate var/"log/influxdb3", :exist? + + # Test that we can start the server briefly (memory mode for testing) + influxdb_port = free_port + pid = fork do + exec bin/"influxdb3", "serve", + "--node-id", "test-node", + "--object-store", "memory", + "--http-bind", "127.0.0.1:#{influxdb_port}" + end + + sleep 5 + + # Test that the server responds (basic health check) + begin + output = shell_output("curl -s -f http://127.0.0.1:#{influxdb_port}/health || echo 'Server listening'") + assert_match(/Server listening|health|200|404/, output) + ensure + Process.kill("TERM", pid) if pid + Process.wait(pid) if pid + end + end +end \ No newline at end of file From 537fafbb15340111a557f26dd7fe8bf040c9ca9a Mon Sep 17 00:00:00 2001 From: Peter Barnett Date: Mon, 18 Aug 2025 13:58:09 -0400 Subject: [PATCH 2/5] fix: update to remove warnings and follow better practices --- influxdb3-core.rb | 182 ++++++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 87 deletions(-) diff --git a/influxdb3-core.rb b/influxdb3-core.rb index 9426e08e54c..20a02e7f759 100644 --- a/influxdb3-core.rb +++ b/influxdb3-core.rb @@ -1,5 +1,5 @@ class Influxdb3Core < Formula - desc "InfluxDB 3 Core - Fast, columnar time series database" + desc "Fast, columnar time series database" homepage "https://www.influxdata.com/products/influxdb/" version "3.3.0" license any_of: ["Apache-2.0", "MIT"] @@ -15,78 +15,84 @@ class Influxdb3Core < Formula end end + # Install the pre-compiled binary and configure the system def install bin.install "influxdb3" - + if File.directory?("python") (bin/"python").install Dir["python/*"] elsif File.directory?("plugins") (bin/"plugins").install Dir["plugins/*"] end - + # If no bundled Python, create symlinks to system Python unless (bin/"python").exist? python_prefix = Formula["python@3.13"].opt_prefix (bin/"python").mkpath (bin/"python/lib").mkpath - + python_lib = python_prefix/"lib/libpython3.13.dylib" - if python_lib.exist? - (bin/"python/lib/libpython3.13.dylib").make_symlink(python_lib) - end + (bin/"python/lib/libpython3.13.dylib").make_symlink(python_lib) if python_lib.exist? end - + data_dir = var/"lib/influxdb3" data_dir.mkpath - + + plugin_dir = var/"lib/influxdb3/plugins" + plugin_dir.mkpath + config_dir = etc/"influxdb3" config_dir.mkpath - + generate_default_config(config_dir) - + (var/"log/influxdb3").mkpath - + create_startup_script - + (data_dir/"README.txt").write <<~EOS InfluxDB 3 Core Data Directory - + This directory contains your InfluxDB 3 Core data when using file-based storage. - + Configuration: #{config_dir}/influxdb3.conf Logs: #{var}/log/influxdb3/ - + To start the server: brew services start influxdb3-core To view logs: tail -f #{var}/log/influxdb3/influxdb3.log EOS end + # Generate a default configuration file with common settings def generate_default_config(config_dir) config_file = config_dir/"influxdb3.conf" - + return if config_file.exist? - + node_id = ENV.fetch("INFLUXDB3_NODE_ID", "node0") - + config_content = <<~EOS # InfluxDB 3 Core Configuration File # Generated by Homebrew on #{Time.now} # Edit this file to customize your InfluxDB 3 setup - + # ============================================================================= # Node Configuration # ============================================================================= NODE_ID=#{ENV.fetch("INFLUXDB3_NODE_ID", node_id)} - + # ============================================================================= # Object Store Configuration # ============================================================================= # Options: memory, file, s3, google, azure OBJECT_STORE_TYPE=#{ENV.fetch("INFLUXDB3_OBJECT_STORE", "file")} - + # File Object Store Settings (used when OBJECT_STORE_TYPE=file) DATA_DIR=#{var}/lib/influxdb3 - + + # File Object Store Settings (used when OBJECT_STORE_TYPE=file) + PLUGIN_DIR=#{var}/lib/influxdb3/plugins + # S3 Object Store Settings (used when OBJECT_STORE_TYPE=s3) # Uncomment and configure these if using S3: # S3_BUCKET=your-bucket-name @@ -95,36 +101,36 @@ def generate_default_config(config_dir) # AWS_REGION=your-region (default: us-east-1 if not uncommented) # AWS_ENDPOINT= # Optional: for MinIO or other S3-compatible stores # AWS_ALLOW_HTTP=false # Set to true for non-HTTPS endpoints - + # Google Cloud Storage Settings (used when OBJECT_STORE_TYPE=google) # GOOGLE_SERVICE_ACCOUNT_PATH=/path/to/service-account.json # GOOGLE_BUCKET=your-gcs-bucket - + # Azure Blob Storage Settings (used when OBJECT_STORE_TYPE=azure) # AZURE_STORAGE_ACCOUNT=your-account # AZURE_STORAGE_ACCESS_KEY=your-key # AZURE_CONTAINER=your-container - + # ============================================================================= # Server Configuration # ============================================================================= HTTP_BIND_ADDRESS=127.0.0.1:8181 - EOS - + config_file.write(config_content) end + # Create a dynamic startup script that reads config and starts influxdb3 def create_startup_script startup_script = bin/"influxdb3-core" startup_script.write <<~EOS #!/bin/bash - + # InfluxDB 3 Core Dynamic Startup Script # This script reads configuration and starts influxdb3 with the right parameters - + CONFIG_FILE="#{etc}/influxdb3/influxdb3.conf" - + # Function to read config value read_config() { local key="$1" @@ -136,15 +142,16 @@ def create_startup_script echo "$default" fi } - + # Read configuration NODE_ID="${INFLUXDB3_NODE_ID:-$(read_config "NODE_ID" "node0")}" OBJECT_STORE="${INFLUXDB3_OBJECT_STORE:-$(read_config "OBJECT_STORE_TYPE" "file")}" HTTP_BIND="${INFLUXDB3_HTTP_BIND:-$(read_config "HTTP_BIND_ADDRESS" "127.0.0.1:8181")}" - + PLUGIN_DIR="${INFLUXDB3_PLUGIN_DIR:-$(read_config "PLUGIN_DIR" "/opt/homebrew/lib/influxdb3/plugins")}" + # Start building command ARGS=("#{opt_bin}/influxdb3" "serve" "--node-id" "$NODE_ID" "--object-store" "$OBJECT_STORE") - + # Add object store specific arguments case "$OBJECT_STORE" in "file") @@ -158,7 +165,7 @@ def create_startup_script AWS_REGION="${AWS_REGION:-$(read_config "AWS_REGION" "")}" AWS_ENDPOINT="${AWS_ENDPOINT:-$(read_config "AWS_ENDPOINT" "")}" AWS_ALLOW_HTTP="$(read_config "AWS_ALLOW_HTTP" "")" - + [ -n "$S3_BUCKET" ] && ARGS+=("--bucket" "$S3_BUCKET") [ -n "$AWS_ACCESS_KEY_ID" ] && ARGS+=("--aws-access-key-id" "$AWS_ACCESS_KEY_ID") [ -n "$AWS_SECRET_ACCESS_KEY" ] && ARGS+=("--aws-secret-access-key" "$AWS_SECRET_ACCESS_KEY") @@ -169,7 +176,7 @@ def create_startup_script "google") GOOGLE_SERVICE_ACCOUNT_PATH="${GOOGLE_SERVICE_ACCOUNT_PATH:-$(read_config "GOOGLE_SERVICE_ACCOUNT_PATH" "")}" GOOGLE_BUCKET="${GOOGLE_BUCKET:-$(read_config "GOOGLE_BUCKET" "")}" - + [ -n "$GOOGLE_SERVICE_ACCOUNT_PATH" ] && ARGS+=("--google-service-account-path" "$GOOGLE_SERVICE_ACCOUNT_PATH") [ -n "$GOOGLE_BUCKET" ] && ARGS+=("--google-bucket" "$GOOGLE_BUCKET") ;; @@ -177,16 +184,19 @@ def create_startup_script AZURE_STORAGE_ACCOUNT="${AZURE_STORAGE_ACCOUNT:-$(read_config "AZURE_STORAGE_ACCOUNT" "")}" AZURE_STORAGE_ACCESS_KEY="${AZURE_STORAGE_ACCESS_KEY:-$(read_config "AZURE_STORAGE_ACCESS_KEY" "")}" AZURE_CONTAINER="${AZURE_CONTAINER:-$(read_config "AZURE_CONTAINER" "")}" - + [ -n "$AZURE_STORAGE_ACCOUNT" ] && ARGS+=("--azure-storage-account" "$AZURE_STORAGE_ACCOUNT") [ -n "$AZURE_STORAGE_ACCESS_KEY" ] && ARGS+=("--azure-storage-access-key" "$AZURE_STORAGE_ACCESS_KEY") [ -n "$AZURE_CONTAINER" ] && ARGS+=("--azure-container" "$AZURE_CONTAINER") ;; esac - + # Add HTTP bind address ARGS+=("--http-bind" "$HTTP_BIND") - + + # Add Processing Engine + ARGS+=("--plugin-dir" "$PLUGIN_DIR") + # Execute the command echo "Starting InfluxDB 3 Core with configuration:" echo " Node ID: $NODE_ID" @@ -195,50 +205,46 @@ def create_startup_script echo "" echo "Full command: ${ARGS[*]}" echo "" - + exec "${ARGS[@]}" EOS - + startup_script.chmod(0755) end + # Provide user guidance after installation def caveats - - bold = "\033[1m" - boldgreen = "\033[1;32m" - dim = "\033[2m" - nc = "\033[0m" # No Color - <<~EOS - \n - ┌───────────────────────────────────────────────────────┐ - │ 🚀 #{boldgreen}InfluxDB 3 Core has been installed and configured!#{nc} │ - ├───────────────────────────────────────────────────────┘ + + ┌────────────────────────────────────────────────────┐ + │ InfluxDB 3 Core has been installed and configured! │ + ├────────────────────────────────────────────────────┘ │ - │ 📁 Config file: #{etc}/influxdb3/influxdb3.conf - │ 📁 Data directory: #{var}/lib/influxdb3 - │ 📁 Logs directory: #{var}/log/influxdb3 + │ 📁 Config file: #{etc}/influxdb3/influxdb3.conf + │ 📁 Data directory: #{var}/lib/influxdb3 + │ 📁 Logs directory: #{var}/log/influxdb3 + │ 📁 Plugins directory: #{var}/lib/influxdb3/plugins │ - │ #{bold}Current Configuration:#{nc} - │ Node ID: node0 - │ Storage: file - │ Address: 127.0.0.1:8181 + │ Current Configuration: + │ ├─ Node ID: node0 + │ ├─ Storage: file + │ └─ Address: 127.0.0.1:8181 │ - │ #{dim}To customize storage (memory, s3, google, azure) or other,#{nc} - │ #{dim}settings, edit the config file and restart the service.#{nc} - │ #{dim}├─ vim #{etc}/influxdb3/influxdb3.conf#{nc} - │ #{dim}└─ brew services restart influxdb3-core#{nc} + │ To customize storage (memory, s3, google, azure) or other + │ settings, edit the config file and restart the service: + │ ├─ vim #{etc}/influxdb3/influxdb3.conf + │ └─ brew services restart influxdb3-core │ - │ #{bold}Next Steps:#{nc} - │ 1. Start the service: #{bold}brew services start influxdb3-core#{nc} - │ 2. Create admin token: #{bold}influxdb3 create token --admin#{nc} - │ 3. Set the token: #{bold}export INFLUXDB3_AUTH_TOKEN="your-token"#{nc} - │ 4. Create a database: #{bold}influxdb3 create database mydata#{nc} + │ Next Steps: + │ 1. Start the service: brew services start influxdb3-core + │ 2. Create admin token: influxdb3 create token --admin + │ 3. Set the token: export INFLUXDB3_AUTH_TOKEN="your-token" + │ 4. Create a database: influxdb3 create database mydata │ 5. Start writing data! │ - │ #{bold}Documentation:#{nc} https://docs.influxdata.com/influxdb3/core/ - │ - └────────────────────────────────────────────────────────\n + │ Documentation: https://docs.influxdata.com/influxdb3/core/get-started/ + │ + └─────────────────────────────────────────────────────\n EOS end @@ -252,24 +258,24 @@ def caveats end test do - assert_predicate bin/"influxdb3", :exist? + assert_path_exists bin/"influxdb3" assert_predicate bin/"influxdb3", :executable? - - assert_predicate bin/"influxdb3-core", :exist? + + assert_path_exists bin/"influxdb3-core" assert_predicate bin/"influxdb3-core", :executable? - + output = shell_output("#{bin}/influxdb3 --help") assert_match "InfluxDB 3", output - - assert_predicate etc/"influxdb3/influxdb3.conf", :exist? + + assert_path_exists etc/"influxdb3/influxdb3.conf" config_content = (etc/"influxdb3/influxdb3.conf").read assert_match "NODE_ID=", config_content assert_match "OBJECT_STORE_TYPE=", config_content - - assert_predicate var/"lib/influxdb3", :exist? - assert_predicate var/"lib/influxdb3/README.txt", :exist? - - assert_predicate var/"log/influxdb3", :exist? + + assert_path_exists var/"lib/influxdb3" + assert_path_exists var/"lib/influxdb3/README.txt" + + assert_path_exists var/"log/influxdb3" # Test that we can start the server briefly (memory mode for testing) influxdb_port = free_port @@ -277,18 +283,20 @@ def caveats exec bin/"influxdb3", "serve", "--node-id", "test-node", "--object-store", "memory", - "--http-bind", "127.0.0.1:#{influxdb_port}" + "--http-bind", "127.0.0.1:#{influxdb_port}", + "--disable-authz", "health" end - + sleep 5 - + # Test that the server responds (basic health check) begin - output = shell_output("curl -s -f http://127.0.0.1:#{influxdb_port}/health || echo 'Server listening'") - assert_match(/Server listening|health|200|404/, output) + output = shell_output("curl -s http://127.0.0.1:#{influxdb_port}/health") + # With --disable-authz health, we should get "OK" + assert_match "OK", output ensure Process.kill("TERM", pid) if pid Process.wait(pid) if pid end end -end \ No newline at end of file +end From 085f2645a752e82d16cd7cb0154d809b5917fbc8 Mon Sep 17 00:00:00 2001 From: Peter Barnett Date: Mon, 18 Aug 2025 14:01:54 -0400 Subject: [PATCH 3/5] fix: clarify --- influxdb3-core.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/influxdb3-core.rb b/influxdb3-core.rb index 20a02e7f759..7aa770319a3 100644 --- a/influxdb3-core.rb +++ b/influxdb3-core.rb @@ -1,5 +1,5 @@ class Influxdb3Core < Formula - desc "Fast, columnar time series database" + desc "Fast, open source, edge data collector optimized for real-time analytics" homepage "https://www.influxdata.com/products/influxdb/" version "3.3.0" license any_of: ["Apache-2.0", "MIT"] @@ -35,6 +35,7 @@ def install (bin/"python/lib/libpython3.13.dylib").make_symlink(python_lib) if python_lib.exist? end + # Create necessary directories for storing data, plugins, and the config data_dir = var/"lib/influxdb3" data_dir.mkpath From 87f8d1c425496b98c45046b803745350199e3827 Mon Sep 17 00:00:00 2001 From: Peter Barnett Date: Wed, 20 Aug 2025 16:50:32 -0400 Subject: [PATCH 4/5] fix: update to require the bundled Python --- influxdb3-core.rb | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/influxdb3-core.rb b/influxdb3-core.rb index 7aa770319a3..e51fd0fa658 100644 --- a/influxdb3-core.rb +++ b/influxdb3-core.rb @@ -4,7 +4,6 @@ class Influxdb3Core < Formula version "3.3.0" license any_of: ["Apache-2.0", "MIT"] - depends_on "python@3.13" => :recommended on_macos do if Hardware::CPU.arm? @@ -20,19 +19,10 @@ def install bin.install "influxdb3" if File.directory?("python") - (bin/"python").install Dir["python/*"] - elsif File.directory?("plugins") - (bin/"plugins").install Dir["plugins/*"] - end - - # If no bundled Python, create symlinks to system Python - unless (bin/"python").exist? - python_prefix = Formula["python@3.13"].opt_prefix - (bin/"python").mkpath - (bin/"python/lib").mkpath - - python_lib = python_prefix/"lib/libpython3.13.dylib" - (bin/"python/lib/libpython3.13.dylib").make_symlink(python_lib) if python_lib.exist? + (lib/"python").install Dir["python/*"] + (bin/"python").make_symlink(lib/"python") + else + odie "Python runtime not found in bundle. InfluxDB 3 Core requires bundled Python." end # Create necessary directories for storing data, plugins, and the config From 97afe1a9fe48284b1f0273db307300ad088409bd Mon Sep 17 00:00:00 2001 From: Peter Barnett Date: Fri, 22 Aug 2025 17:57:28 -0400 Subject: [PATCH 5/5] fix: libexec --- influxdb3-core.rb | 92 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/influxdb3-core.rb b/influxdb3-core.rb index e51fd0fa658..48ddbc7b3a0 100644 --- a/influxdb3-core.rb +++ b/influxdb3-core.rb @@ -14,17 +14,84 @@ class Influxdb3Core < Formula end end - # Install the pre-compiled binary and configure the system def install - bin.install "influxdb3" - + # install influxdb3 binary and python/ in the libexec dir + libexec.install "influxdb3" if File.directory?("python") - (lib/"python").install Dir["python/*"] - (bin/"python").make_symlink(lib/"python") + (libexec/"python").install Dir["python/*"] else odie "Python runtime not found in bundle. InfluxDB 3 Core requires bundled Python." end + # Create a wrapper to call influxdb3 from the unversioned libexec dir. Use + # the unversioned #{HOMEBREW_PREFIX}/opt/influxdb3-core/libexec/influxdb3 to + # help with upgrades. #{HOMEBREW_PREFIX}/opt/influxdb3-core is a symlink + # into ../Cellar/influxdb3-core/ created automatically by brew. + (bin/"influxdb3").write <<~EOS + #!/bin/bash + + # '#{HOMEBREW_PREFIX}/opt/influxdb3-core/libexec/python/bin/python -m venv' + # unfortunately resolves symlinks for the 'executable' within pyvenv.cfg. + # Find the venv and then modify pyvenv.cfg before server startup. + if [ "$1" = "serve" ]; then + pyvenv_cfg= + + # Priority 1: VIRTUAL_ENV + if [ -n "$VIRTUAL_ENV" ]; then + pyvenv_cfg="$VIRTUAL_ENV/pyvenv.cfg" + else + # Priority 2: --virtual-env-location + for ((i=1; i<=$#; i++)); do + arg="${!i}" + next_idx=$((i+1)) + next_arg="${!next_idx}" + + if [[ "$arg" == "--virtual-env-location" ]] && [[ -n "$next_arg" ]]; then + # --virtual-env-location /path/to/foo + pyvenv_cfg="$next_arg/pyvenv.cfg" + break + elif [[ "$arg" == --virtual-env-location=* ]]; then + # --virtual-env-location=/path/to/foo + pyvenv_cfg="${arg#*=}/pyvenv.cfg" + break + fi + done + + # Priority 3: INFLUXDB3_PLUGIN_DIR + if [ -z "$pyvenv_cfg" ] && [ -n "$INFLUXDB3_PLUGIN_DIR" ]; then + pyvenv_cfg="$INFLUXDB3_PLUGIN_DIR/.venv/pyvenv.cfg" + fi + + # Priority 4: --plugin-dir + if [ -z "$pyvenv_cfg" ]; then + for ((i=1; i<=$#; i++)); do + arg="${!i}" + next_idx=$((i+1)) + next_arg="${!next_idx}" + + if [[ "$arg" == "--plugin-dir" ]] && [[ -n "$next_arg" ]]; then + # --plugin-dir /path/to/bar + pyvenv_cfg="$next_arg/.venv/pyvenv.cfg" + break + elif [[ "$arg" == --plugin-dir=* ]]; then + # --plugin-dir=/path/to/bar + pyvenv_cfg="${arg#*=}/.venv/pyvenv.cfg" + break + fi + done + fi + fi + + # Update the pyvenv.cfg file + if [ -e "$pyvenv_cfg" ]; then + sed -i '' 's|/Cellar/influxdb3-core/[^/]*/|/opt/influxdb3-core/|g' "$pyvenv_cfg" + fi + fi + + exec "#{HOMEBREW_PREFIX}/opt/influxdb3-core/libexec/influxdb3" "$@" + EOS + (bin/"influxdb3").chmod(0755) + # Create necessary directories for storing data, plugins, and the config data_dir = var/"lib/influxdb3" data_dir.mkpath @@ -141,7 +208,7 @@ def create_startup_script PLUGIN_DIR="${INFLUXDB3_PLUGIN_DIR:-$(read_config "PLUGIN_DIR" "/opt/homebrew/lib/influxdb3/plugins")}" # Start building command - ARGS=("#{opt_bin}/influxdb3" "serve" "--node-id" "$NODE_ID" "--object-store" "$OBJECT_STORE") + ARGS=("#{HOMEBREW_PREFIX}/bin/influxdb3" "serve" "--node-id" "$NODE_ID" "--object-store" "$OBJECT_STORE") # Add object store specific arguments case "$OBJECT_STORE" in @@ -249,23 +316,34 @@ def caveats end test do + # Test wrapper script exists and is executable assert_path_exists bin/"influxdb3" assert_predicate bin/"influxdb3", :executable? + # Test actual binary exists in libexec + assert_path_exists libexec/"influxdb3" + assert_predicate libexec/"influxdb3", :executable? + + # Test bundled Python exists in libexec + assert_path_exists libexec/"python" + + # Test startup script exists assert_path_exists bin/"influxdb3-core" assert_predicate bin/"influxdb3-core", :executable? + # Test wrapper script forwards help command output = shell_output("#{bin}/influxdb3 --help") assert_match "InfluxDB 3", output + # Test configuration file assert_path_exists etc/"influxdb3/influxdb3.conf" config_content = (etc/"influxdb3/influxdb3.conf").read assert_match "NODE_ID=", config_content assert_match "OBJECT_STORE_TYPE=", config_content + # Test directory structure assert_path_exists var/"lib/influxdb3" assert_path_exists var/"lib/influxdb3/README.txt" - assert_path_exists var/"log/influxdb3" # Test that we can start the server briefly (memory mode for testing)