mirror of
https://github.com/DeBrosOfficial/network.git
synced 2025-12-11 10:18:50 +00:00
- Consolidated development commands into a new `dev` command group for better organization. - Introduced a `prod` command group to manage production environment operations. - Updated Makefile to simplify the development environment setup and improve logging. - Enhanced README to clarify the development process and health check requirements. - Removed deprecated configuration and service management commands to streamline the CLI interface.
308 lines
10 KiB
Go
308 lines
10 KiB
Go
package production
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// BinaryInstaller handles downloading and installing external binaries
|
|
type BinaryInstaller struct {
|
|
arch string
|
|
logWriter interface{} // io.Writer
|
|
}
|
|
|
|
// NewBinaryInstaller creates a new binary installer
|
|
func NewBinaryInstaller(arch string, logWriter interface{}) *BinaryInstaller {
|
|
return &BinaryInstaller{
|
|
arch: arch,
|
|
logWriter: logWriter,
|
|
}
|
|
}
|
|
|
|
// InstallRQLite downloads and installs RQLite
|
|
func (bi *BinaryInstaller) InstallRQLite() error {
|
|
if _, err := exec.LookPath("rqlited"); err == nil {
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ RQLite already installed\n")
|
|
return nil
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Installing RQLite...\n")
|
|
|
|
version := "8.43.0"
|
|
tarball := fmt.Sprintf("rqlite-v%s-linux-%s.tar.gz", version, bi.arch)
|
|
url := fmt.Sprintf("https://github.com/rqlite/rqlite/releases/download/v%s/%s", version, tarball)
|
|
|
|
// Download
|
|
cmd := exec.Command("wget", "-q", url, "-O", "/tmp/"+tarball)
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to download RQLite: %w", err)
|
|
}
|
|
|
|
// Extract
|
|
cmd = exec.Command("tar", "-C", "/tmp", "-xzf", "/tmp/"+tarball)
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to extract RQLite: %w", err)
|
|
}
|
|
|
|
// Copy binaries
|
|
dir := fmt.Sprintf("/tmp/rqlite-v%s-linux-%s", version, bi.arch)
|
|
exec.Command("cp", dir+"/rqlited", "/usr/local/bin/").Run()
|
|
exec.Command("chmod", "+x", "/usr/local/bin/rqlited").Run()
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ RQLite installed\n")
|
|
return nil
|
|
}
|
|
|
|
// InstallIPFS downloads and installs IPFS (Kubo)
|
|
func (bi *BinaryInstaller) InstallIPFS() error {
|
|
if _, err := exec.LookPath("ipfs"); err == nil {
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ IPFS already installed\n")
|
|
return nil
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Installing IPFS (Kubo)...\n")
|
|
|
|
// Use official install script
|
|
cmd := exec.Command("bash", "-c", "curl -fsSL https://dist.ipfs.tech/kubo/v0.27.0/install.sh | bash")
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to install IPFS: %w", err)
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ IPFS installed\n")
|
|
return nil
|
|
}
|
|
|
|
// InstallIPFSCluster downloads and installs IPFS Cluster Service
|
|
func (bi *BinaryInstaller) InstallIPFSCluster() error {
|
|
if _, err := exec.LookPath("ipfs-cluster-service"); err == nil {
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ IPFS Cluster already installed\n")
|
|
return nil
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Installing IPFS Cluster Service...\n")
|
|
|
|
// Check if Go is available
|
|
if _, err := exec.LookPath("go"); err != nil {
|
|
return fmt.Errorf("Go not found - required to install IPFS Cluster. Please install Go first")
|
|
}
|
|
|
|
cmd := exec.Command("go", "install", "github.com/ipfs-cluster/ipfs-cluster/cmd/ipfs-cluster-service@latest")
|
|
cmd.Env = append(os.Environ(), "GOBIN=/usr/local/bin")
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to install IPFS Cluster: %w", err)
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ IPFS Cluster installed\n")
|
|
return nil
|
|
}
|
|
|
|
// InstallOlric downloads and installs Olric server
|
|
func (bi *BinaryInstaller) InstallOlric() error {
|
|
if _, err := exec.LookPath("olric-server"); err == nil {
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ Olric already installed\n")
|
|
return nil
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Installing Olric...\n")
|
|
|
|
// Check if Go is available
|
|
if _, err := exec.LookPath("go"); err != nil {
|
|
return fmt.Errorf("Go not found - required to install Olric. Please install Go first")
|
|
}
|
|
|
|
cmd := exec.Command("go", "install", "github.com/olric-data/olric/cmd/olric-server@v0.7.0")
|
|
cmd.Env = append(os.Environ(), "GOBIN=/usr/local/bin")
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to install Olric: %w", err)
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ Olric installed\n")
|
|
return nil
|
|
}
|
|
|
|
// InstallGo downloads and installs Go toolchain
|
|
func (bi *BinaryInstaller) InstallGo() error {
|
|
if _, err := exec.LookPath("go"); err == nil {
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ Go already installed\n")
|
|
return nil
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Installing Go...\n")
|
|
|
|
goTarball := fmt.Sprintf("go1.21.6.linux-%s.tar.gz", bi.arch)
|
|
goURL := fmt.Sprintf("https://go.dev/dl/%s", goTarball)
|
|
|
|
// Download
|
|
cmd := exec.Command("wget", "-q", goURL, "-O", "/tmp/"+goTarball)
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to download Go: %w", err)
|
|
}
|
|
|
|
// Extract
|
|
cmd = exec.Command("tar", "-C", "/usr/local", "-xzf", "/tmp/"+goTarball)
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to extract Go: %w", err)
|
|
}
|
|
|
|
// Add to PATH
|
|
os.Setenv("PATH", os.Getenv("PATH")+":/usr/local/go/bin")
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ Go installed\n")
|
|
return nil
|
|
}
|
|
|
|
// InstallDeBrosBinaries clones and builds DeBros binaries
|
|
func (bi *BinaryInstaller) InstallDeBrosBinaries(branch string, debrosHome string) error {
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Building DeBros binaries...\n")
|
|
|
|
srcDir := filepath.Join(debrosHome, "src")
|
|
binDir := filepath.Join(debrosHome, "bin")
|
|
|
|
// Ensure directories exist
|
|
os.MkdirAll(srcDir, 0755)
|
|
os.MkdirAll(binDir, 0755)
|
|
|
|
// Clone repository if not present
|
|
if _, err := os.Stat(filepath.Join(srcDir, "Makefile")); os.IsNotExist(err) {
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Cloning repository...\n")
|
|
cmd := exec.Command("git", "clone", "--branch", branch, "--depth", "1", "https://github.com/DeBrosOfficial/network.git", srcDir)
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to clone repository: %w", err)
|
|
}
|
|
}
|
|
|
|
// Build binaries
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Building binaries...\n")
|
|
cmd := exec.Command("make", "build")
|
|
cmd.Dir = srcDir
|
|
cmd.Env = append(os.Environ(), "HOME="+debrosHome, "PATH="+os.Getenv("PATH")+":/usr/local/go/bin")
|
|
if output, err := cmd.CombinedOutput(); err != nil {
|
|
return fmt.Errorf("failed to build: %v\n%s", err, string(output))
|
|
}
|
|
|
|
// Copy binaries
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Copying binaries...\n")
|
|
cmd = exec.Command("sh", "-c", fmt.Sprintf("cp -r %s/bin/* %s/", srcDir, binDir))
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to copy binaries: %w", err)
|
|
}
|
|
|
|
exec.Command("chmod", "-R", "755", binDir).Run()
|
|
exec.Command("chown", "-R", "debros:debros", binDir).Run()
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ DeBros binaries installed\n")
|
|
return nil
|
|
}
|
|
|
|
// InstallSystemDependencies installs system-level dependencies via apt
|
|
func (bi *BinaryInstaller) InstallSystemDependencies() error {
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Installing system dependencies...\n")
|
|
|
|
// Update package list
|
|
cmd := exec.Command("apt-get", "update")
|
|
if err := cmd.Run(); err != nil {
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Warning: apt update failed\n")
|
|
}
|
|
|
|
// Install dependencies
|
|
cmd = exec.Command("apt-get", "install", "-y", "curl", "git", "make", "build-essential", "wget")
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to install dependencies: %w", err)
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " ✓ System dependencies installed\n")
|
|
return nil
|
|
}
|
|
|
|
// InitializeIPFSRepo initializes an IPFS repository for a node
|
|
func (bi *BinaryInstaller) InitializeIPFSRepo(nodeType, ipfsRepoPath string, swarmKeyPath string) error {
|
|
configPath := filepath.Join(ipfsRepoPath, "config")
|
|
if _, err := os.Stat(configPath); err == nil {
|
|
// Already initialized
|
|
return nil
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Initializing IPFS repo for %s...\n", nodeType)
|
|
|
|
os.MkdirAll(ipfsRepoPath, 0755)
|
|
|
|
// Initialize IPFS
|
|
cmd := exec.Command("ipfs", "init", "--profile=server", "--repo-dir="+ipfsRepoPath)
|
|
if output, err := cmd.CombinedOutput(); err != nil {
|
|
return fmt.Errorf("failed to initialize IPFS: %v\n%s", err, string(output))
|
|
}
|
|
|
|
// Copy swarm key if present
|
|
if data, err := os.ReadFile(swarmKeyPath); err == nil {
|
|
os.WriteFile(filepath.Join(ipfsRepoPath, "swarm.key"), data, 0600)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// InitializeIPFSClusterConfig initializes IPFS Cluster configuration
|
|
func (bi *BinaryInstaller) InitializeIPFSClusterConfig(nodeType, clusterPath, clusterSecret string, ipfsAPIPort int) error {
|
|
serviceJSONPath := filepath.Join(clusterPath, "service.json")
|
|
if _, err := os.Stat(serviceJSONPath); err == nil {
|
|
// Already initialized
|
|
return nil
|
|
}
|
|
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Initializing IPFS Cluster config for %s...\n", nodeType)
|
|
|
|
os.MkdirAll(clusterPath, 0755)
|
|
|
|
// For now, just create a minimal service.json
|
|
// This will be properly configured during service startup
|
|
cfgContent := fmt.Sprintf(`{
|
|
"cluster": {
|
|
"peername": "%s",
|
|
"secret": "%s",
|
|
"listen_multiaddress": ["/ip4/0.0.0.0/tcp/9096"],
|
|
"leave_on_shutdown": false
|
|
},
|
|
"api": {
|
|
"restapi": {
|
|
"http_listen_multiaddress": "/ip4/0.0.0.0/tcp/9094"
|
|
}
|
|
},
|
|
"ipfs_connector": {
|
|
"ipfshttp": {
|
|
"node_multiaddress": "/ip4/127.0.0.1/tcp/%d"
|
|
}
|
|
},
|
|
"consensus": {
|
|
"crdt": {
|
|
"cluster_name": "debros",
|
|
"trusted_peers": ["*"]
|
|
}
|
|
},
|
|
"datastore": {
|
|
"type": "badger",
|
|
"path": "%s/badger"
|
|
}
|
|
}`, nodeType, strings.TrimSpace(clusterSecret), ipfsAPIPort, clusterPath)
|
|
|
|
if err := os.WriteFile(serviceJSONPath, []byte(cfgContent), 0644); err != nil {
|
|
return fmt.Errorf("failed to write cluster config: %w", err)
|
|
}
|
|
|
|
exec.Command("chown", "-R", "debros:debros", clusterPath).Run()
|
|
return nil
|
|
}
|
|
|
|
// InitializeRQLiteDataDir initializes RQLite data directory
|
|
func (bi *BinaryInstaller) InitializeRQLiteDataDir(nodeType, dataDir string) error {
|
|
fmt.Fprintf(bi.logWriter.(interface{ Write([]byte) (int, error) }), " Initializing RQLite data dir for %s...\n", nodeType)
|
|
|
|
if err := os.MkdirAll(dataDir, 0755); err != nil {
|
|
return fmt.Errorf("failed to create RQLite data directory: %w", err)
|
|
}
|
|
|
|
exec.Command("chown", "-R", "debros:debros", dataDir).Run()
|
|
return nil
|
|
}
|