mirror of
https://github.com/DeBrosOfficial/network.git
synced 2025-12-11 08:18:49 +00:00
feat: enhance configuration handling for IPFS and cluster initialization
- Updated `select_data_dir_check` to handle both absolute and relative config paths, improving flexibility in configuration file management. - Enhanced `DefaultPath` to check for config files in both legacy and production directories, ensuring backward compatibility. - Modified `InitializeIPFSClusterConfig` to include cluster secret management and improve error handling during initialization. - Added functionality to update the cluster secret in the service.json configuration file, enhancing security and configurability.
This commit is contained in:
parent
6ba0a824e0
commit
a33d03c6b2
16
CHANGELOG.md
16
CHANGELOG.md
@ -13,6 +13,22 @@ The format is based on [Keep a Changelog][keepachangelog] and adheres to [Semant
|
||||
### Deprecated
|
||||
|
||||
### Fixed
|
||||
## [0.67.4] - 2025-11-11
|
||||
|
||||
### Added
|
||||
\n
|
||||
### Changed
|
||||
- Improved configuration file loading logic to support absolute paths for config files.
|
||||
- Updated IPFS Cluster initialization during setup to run `ipfs-cluster-service init` and automatically configure the cluster secret.
|
||||
- IPFS repositories initialized with a private swarm key will now automatically disable AutoConf.
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
- Fixed configuration path resolution to correctly check for config files in both the legacy (`~/.debros/`) and production (`~/.debros/configs/`) directories.
|
||||
|
||||
## [0.67.3] - 2025-11-11
|
||||
|
||||
### Added
|
||||
|
||||
2
Makefile
2
Makefile
@ -19,7 +19,7 @@ test-e2e:
|
||||
|
||||
.PHONY: build clean test run-node run-node2 run-node3 run-example deps tidy fmt vet lint clear-ports install-hooks kill
|
||||
|
||||
VERSION := 0.67.3
|
||||
VERSION := 0.67.4
|
||||
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
||||
DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.commit=$(COMMIT)' -X 'main.date=$(DATE)'
|
||||
|
||||
@ -66,23 +66,32 @@ func check_if_should_open_help(help *bool) {
|
||||
func select_data_dir_check(configName *string) {
|
||||
logger := setup_logger(logging.ComponentNode)
|
||||
|
||||
// Ensure config directory exists and is writable
|
||||
_, err := config.EnsureConfigDir()
|
||||
if err != nil {
|
||||
logger.Error("Failed to ensure config directory", zap.Error(err))
|
||||
fmt.Fprintf(os.Stderr, "\n❌ Configuration Error:\n")
|
||||
fmt.Fprintf(os.Stderr, "Failed to create/access config directory: %v\n", err)
|
||||
fmt.Fprintf(os.Stderr, "\nPlease ensure:\n")
|
||||
fmt.Fprintf(os.Stderr, " 1. Home directory is accessible: %s\n", os.ExpandEnv("~"))
|
||||
fmt.Fprintf(os.Stderr, " 2. You have write permissions to home directory\n")
|
||||
fmt.Fprintf(os.Stderr, " 3. Disk space is available\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
var configPath string
|
||||
var err error
|
||||
|
||||
configPath, err := config.DefaultPath(*configName)
|
||||
if err != nil {
|
||||
logger.Error("Failed to determine config path", zap.Error(err))
|
||||
os.Exit(1)
|
||||
// Check if configName is an absolute path
|
||||
if filepath.IsAbs(*configName) {
|
||||
// Use absolute path directly
|
||||
configPath = *configName
|
||||
} else {
|
||||
// Ensure config directory exists and is writable
|
||||
_, err = config.EnsureConfigDir()
|
||||
if err != nil {
|
||||
logger.Error("Failed to ensure config directory", zap.Error(err))
|
||||
fmt.Fprintf(os.Stderr, "\n❌ Configuration Error:\n")
|
||||
fmt.Fprintf(os.Stderr, "Failed to create/access config directory: %v\n", err)
|
||||
fmt.Fprintf(os.Stderr, "\nPlease ensure:\n")
|
||||
fmt.Fprintf(os.Stderr, " 1. Home directory is accessible: %s\n", os.ExpandEnv("~"))
|
||||
fmt.Fprintf(os.Stderr, " 2. You have write permissions to home directory\n")
|
||||
fmt.Fprintf(os.Stderr, " 3. Disk space is available\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
configPath, err = config.DefaultPath(*configName)
|
||||
if err != nil {
|
||||
logger.Error("Failed to determine config path", zap.Error(err))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := os.Stat(configPath); err != nil {
|
||||
@ -232,15 +241,21 @@ func main() {
|
||||
|
||||
check_if_should_open_help(help)
|
||||
|
||||
// Check if config file exists
|
||||
// Check if config file exists and determine path
|
||||
select_data_dir_check(configName)
|
||||
|
||||
// Load configuration from ~/.debros/node.yaml
|
||||
configPath, err := config.DefaultPath(*configName)
|
||||
if err != nil {
|
||||
logger.Error("Failed to determine config path", zap.Error(err))
|
||||
fmt.Fprintf(os.Stderr, "Configuration error: %v\n", err)
|
||||
os.Exit(1)
|
||||
// Determine config path (handle both absolute and relative paths)
|
||||
var configPath string
|
||||
var err error
|
||||
if filepath.IsAbs(*configName) {
|
||||
configPath = *configName
|
||||
} else {
|
||||
configPath, err = config.DefaultPath(*configName)
|
||||
if err != nil {
|
||||
logger.Error("Failed to determine config path", zap.Error(err))
|
||||
fmt.Fprintf(os.Stderr, "Configuration error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
var cfg *config.Config
|
||||
|
||||
@ -29,10 +29,26 @@ func EnsureConfigDir() (string, error) {
|
||||
|
||||
// DefaultPath returns the path to the config file for the given component name.
|
||||
// component should be e.g., "node.yaml", "bootstrap.yaml", "gateway.yaml"
|
||||
// It checks both ~/.debros/ and ~/.debros/configs/ for backward compatibility.
|
||||
func DefaultPath(component string) (string, error) {
|
||||
dir, err := ConfigDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(dir, component), nil
|
||||
|
||||
// First check in ~/.debros/configs/ (production installer location)
|
||||
configsPath := filepath.Join(dir, "configs", component)
|
||||
if _, err := os.Stat(configsPath); err == nil {
|
||||
return configsPath, nil
|
||||
}
|
||||
|
||||
// Fallback to ~/.debros/ (legacy/development location)
|
||||
legacyPath := filepath.Join(dir, component)
|
||||
if _, err := os.Stat(legacyPath); err == nil {
|
||||
return legacyPath, nil
|
||||
}
|
||||
|
||||
// Return configs path as default (even if it doesn't exist yet)
|
||||
// This allows the error message to show the expected production location
|
||||
return configsPath, nil
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package production
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
@ -363,10 +364,22 @@ func (bi *BinaryInstaller) InitializeIPFSRepo(nodeType, ipfsRepoPath string, swa
|
||||
}
|
||||
|
||||
// Copy swarm key if present
|
||||
swarmKeyExists := false
|
||||
if data, err := os.ReadFile(swarmKeyPath); err == nil {
|
||||
if err := os.WriteFile(filepath.Join(ipfsRepoPath, "swarm.key"), data, 0600); err != nil {
|
||||
return fmt.Errorf("failed to copy swarm key: %w", err)
|
||||
}
|
||||
swarmKeyExists = true
|
||||
}
|
||||
|
||||
// Disable AutoConf for private swarm (required when swarm.key is present)
|
||||
// This prevents IPFS from trying to use the public mainnet AutoConf service
|
||||
if swarmKeyExists {
|
||||
cmd = exec.Command(ipfsBinary, "config", "--json", "AutoConf.Enabled", "false")
|
||||
cmd.Env = append(os.Environ(), "IPFS_PATH="+ipfsRepoPath)
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to disable AutoConf: %v\n%s", err, string(output))
|
||||
}
|
||||
}
|
||||
|
||||
// Fix ownership
|
||||
@ -376,8 +389,7 @@ func (bi *BinaryInstaller) InitializeIPFSRepo(nodeType, ipfsRepoPath string, swa
|
||||
}
|
||||
|
||||
// InitializeIPFSClusterConfig initializes IPFS Cluster configuration
|
||||
// Note: This is a placeholder config. The full initialization will occur via `ipfs-cluster-service init`
|
||||
// which is run during Phase2cInitializeServices with the IPFS_CLUSTER_PATH env var set.
|
||||
// This runs `ipfs-cluster-service init` to create the service.json configuration file.
|
||||
func (bi *BinaryInstaller) InitializeIPFSClusterConfig(nodeType, clusterPath, clusterSecret string, ipfsAPIPort int) error {
|
||||
serviceJSONPath := filepath.Join(clusterPath, "service.json")
|
||||
if _, err := os.Stat(serviceJSONPath); err == nil {
|
||||
@ -391,7 +403,72 @@ func (bi *BinaryInstaller) InitializeIPFSClusterConfig(nodeType, clusterPath, cl
|
||||
return fmt.Errorf("failed to create IPFS Cluster directory: %w", err)
|
||||
}
|
||||
|
||||
// Fix ownership before running init
|
||||
exec.Command("chown", "-R", "debros:debros", clusterPath).Run()
|
||||
|
||||
// Resolve ipfs-cluster-service binary path
|
||||
clusterBinary, err := bi.ResolveBinaryPath("ipfs-cluster-service", "/usr/local/bin/ipfs-cluster-service", "/usr/bin/ipfs-cluster-service")
|
||||
if err != nil {
|
||||
return fmt.Errorf("ipfs-cluster-service binary not found: %w", err)
|
||||
}
|
||||
|
||||
// Initialize cluster config with ipfs-cluster-service init
|
||||
// This creates the service.json file with all required sections
|
||||
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Initializing IPFS Cluster config...\n")
|
||||
cmd := exec.Command(clusterBinary, "init", "--force")
|
||||
cmd.Env = append(os.Environ(), "IPFS_CLUSTER_PATH="+clusterPath)
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to initialize IPFS Cluster config: %v\n%s", err, string(output))
|
||||
}
|
||||
|
||||
// Update the cluster secret in service.json if provided
|
||||
if clusterSecret != "" {
|
||||
if err := bi.updateClusterSecret(clusterPath, clusterSecret); err != nil {
|
||||
return fmt.Errorf("failed to update cluster secret: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Fix ownership again after init
|
||||
exec.Command("chown", "-R", "debros:debros", clusterPath).Run()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateClusterSecret updates the secret field in IPFS Cluster service.json
|
||||
func (bi *BinaryInstaller) updateClusterSecret(clusterPath, secret string) error {
|
||||
serviceJSONPath := filepath.Join(clusterPath, "service.json")
|
||||
|
||||
// Read existing config
|
||||
data, err := os.ReadFile(serviceJSONPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read service.json: %w", err)
|
||||
}
|
||||
|
||||
// Parse JSON
|
||||
var config map[string]interface{}
|
||||
if err := json.Unmarshal(data, &config); err != nil {
|
||||
return fmt.Errorf("failed to parse service.json: %w", err)
|
||||
}
|
||||
|
||||
// Update cluster secret
|
||||
if cluster, ok := config["cluster"].(map[string]interface{}); ok {
|
||||
cluster["secret"] = secret
|
||||
} else {
|
||||
config["cluster"] = map[string]interface{}{
|
||||
"secret": secret,
|
||||
}
|
||||
}
|
||||
|
||||
// Write back
|
||||
updatedData, err := json.MarshalIndent(config, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal service.json: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(serviceJSONPath, updatedData, 0644); err != nil {
|
||||
return fmt.Errorf("failed to write service.json: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -231,10 +231,14 @@ func (ps *ProductionSetup) Phase2cInitializeServices(nodeType string) error {
|
||||
return fmt.Errorf("failed to initialize IPFS repo: %w", err)
|
||||
}
|
||||
|
||||
// Initialize IPFS Cluster path (just ensure directory exists, actual init happens in daemon startup)
|
||||
// Initialize IPFS Cluster config (runs ipfs-cluster-service init)
|
||||
clusterPath := filepath.Join(dataDir, "ipfs-cluster")
|
||||
if err := ps.binaryInstaller.InitializeIPFSClusterConfig(nodeType, clusterPath, "", 4501); err != nil {
|
||||
ps.logf(" ⚠️ IPFS Cluster initialization warning: %v", err)
|
||||
clusterSecret, err := ps.secretGenerator.EnsureClusterSecret()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get cluster secret: %w", err)
|
||||
}
|
||||
if err := ps.binaryInstaller.InitializeIPFSClusterConfig(nodeType, clusterPath, clusterSecret, 4501); err != nil {
|
||||
return fmt.Errorf("failed to initialize IPFS Cluster: %w", err)
|
||||
}
|
||||
|
||||
// Initialize RQLite data directory
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user